刷新 OCaml 格式化程序而不重置漂亮的打印机状态

问题描述 投票:0回答:1

Format
模块中,
pp_print_flush
将输出写入格式化程序,并重置漂亮的打印状态。是否可以刷新但不重置状态?

例如,使用

Format.make_formatter out flush
创建格式化程序,当例如使用
out
。我想触发此调用,但不重置漂亮的打印机状态,例如打开盒子。
(我认为我的问题是漂亮打印机的行为,而不是我不明白的一些 Lwt 同步)

问题

我的系统是一个单元测试框架,我想支持测试的并发执行。但输出应该是这样的:测试的输出与启动的顺序相同,并且最肯定的是不同测试的输出不会交错。

但是我也想尽快输出,所以一旦“Test 1”完成,它的输出就会立即写入,但是如果“Test 3”在“Test 1”和“Test 2”之前完成,则不会写入,直到前两个已完成。

为了验证此行为,我编写了一个测试来控制测试完成的顺序,并在每个任务完成后验证打印输出。

为了帮助测试,我制作了一个附加到

fprintf fmt ...

的格式化程序。但在调用

string ref
之前,不会调用 out 函数。

pp_print_flush

make_string_ref_formatter

测试:

let make_string_ref_formatter s = let out b p l = let current = !s in let appended = String.sub b p l in s := current ^ appended in Format.make_formatter out (fun _ -> ())

因此,如果测试未刷新,则无法验证输出。但当冲洗关闭漂亮的打印机盒子时,压痕就消失了。

现在,我已经更改了期望以匹配这种不良行为,但我真的希望测试能够描述

实际

预期输出。

ocaml
1个回答
0
投票

对于第二个 hackish 选项,需要记住的重要一点是,如果打印队列中没有未知大小的令牌,则

let s = ref "" in let fmt = make_string_ref_formatter s in let p1, r1 = Lwt.wait () in let p2, r2 = Lwt.wait () in let p3, r3 = Lwt.wait () in (* Setup test functions for these delayed promises, and run the test runner ... *) Lwt.wakeup r3 (); !s |> should (equal_string ""); Lwt.wakeup r1 (); (* The assertion fails if I don't flush the formatter here *) Format.pp_print_flush fmt (); !s |> should (equal_string "• ctx\n ✔ 1\n "); Lwt.wakeup r2 (); (* Flush is not necessary in tests, the test runner has completed and flushed *) (* But the assertion fails because the boxes were reset, so the last item is not indented *) !s |> should (equal_string "• ctx\n ✔ 1\n ✔ 2\n ✔ 3");

格式化引擎始终直接打印到低级设备。换句话说,如果需要刷新才能看到内容,格式化引擎仍在尝试确定下一个标记的大小。这也意味着强制输出的一种方法是将打印队列的当前大小设置为+无穷大

Format

let large_size = 1_000_000 (*ideally Format.pp_infinity when available*) in Format.fprintf ppf "@<%n>%s" large_size ""

格式化程序上“打印”

""
,就好像其大小为
ppf
小备注:您的 

large_size

make_string_ref_formatter
的性能较差的实现。
    

© www.soinside.com 2019 - 2024. All rights reserved.