1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
open Printf
type node =
| Line of string
| Block of node list
| Inline of node list
type t = node list
let rec is_empty_node = function
| Line "" -> true
| Line _ -> false
| Block xs -> List.for_all is_empty_node xs
| Inline xs -> List.for_all is_empty_node xs
let split_multiline_text str =
String.split_on_char '\n' str
|> List.map (fun str -> Line str)
let to_buffer ?(offset = 0) ?(indent = 2) buf l =
let rec print n = function
| Block l -> List.iter (print (n + indent)) l
| Inline l -> List.iter (print n) l
| Line "" -> Buffer.add_char buf '\n'
| Line str ->
match split_multiline_text str with
| [] -> ()
| [_] ->
bprintf buf "%s%s\n" (String.make n ' ') str
| items ->
print n (Inline items)
in
List.iter (print offset) l
let to_string ?offset ?indent l =
let buf = Buffer.create 1000 in
to_buffer ?offset ?indent buf l;
Buffer.contents buf
let to_channel ?offset ?indent oc l =
let buf = Buffer.create 1000 in
to_buffer ?offset ?indent buf l;
Buffer.output_buffer oc buf
let to_stdout ?offset ?indent l =
to_channel ?offset ?indent stdout l
let to_file ?indent path l =
let oc = open_out path in
Fun.protect
~finally:(fun () -> close_out_noerr oc)
(fun () -> to_channel ?indent oc l)