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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
open Printf
type color = Default | Red | Green | Yellow | Cyan | Bold | Faint
let ansi_code_of_style = function
| Default -> "0"
| Red -> "31"
| Green -> "32"
| Yellow -> "33"
| Cyan -> "36"
| Bold -> "1"
| Faint -> "2"
let color color str =
Printf.sprintf "\027[%sm%s\027[%sm" (ansi_code_of_style color) str
(ansi_code_of_style Default)
let opt_color cond color_ str = if cond then color color_ str else str
let strip =
let re = Re.Pcre.regexp "\027\\[[0-9]+m" in
fun str -> Re.replace re ~f:(fun _ -> "") str
let utf8_length str =
let count = ref 0 in
String.iter
(fun c ->
if Char.code c <= 0b01111111 || Char.code c >= 0b11000000 then incr count)
str;
!count
let graph_length str = strip str |> utf8_length
let pad str min_len =
let len = graph_length str in
if len >= min_len then str ^ " " else str ^ String.make (min_len - len) ' '
let left_col text = pad text 8
let string_make len unit =
let buf = Buffer.create (len * String.length unit) in
for _ = 1 to len do
Buffer.add_string buf unit
done;
Buffer.contents buf
let term_width = 80
let horizontal_line =
let res = (string_make term_width "─" |> color Faint) ^ "\n" in
fun () -> res
let frame str =
let padded_str = pad str (term_width - 4) in
let horizontal_line =
string_make (String.length (strip padded_str) + 2) "─"
in
let top_line = sprintf "┌%s┐\n" horizontal_line |> color Faint in
let bottom_line = sprintf "└%s┘\n" horizontal_line |> color Faint in
let contents_line =
sprintf "%s %s %s\n" (color Faint "│") padded_str (color Faint "│")
in
top_line ^ contents_line ^ bottom_line
let truncate_text ~ ~decorate_data_fragment ~max_bytes str =
match max_bytes with
| None -> str
| Some max_len ->
let orig_len = String.length str in
let max_len = max 0 max_len in
if orig_len <= max_len then str
else
let head_len = max_len / 2 in
let tail_len = max_len - head_len in
if head_len <= 0 || tail_len <= 0 then str
else
let mid_len = orig_len - head_len - tail_len in
let head = String.sub str 0 head_len in
let tail = String.sub str (head_len + mid_len) tail_len in
let mid = sprintf "\n###### [hidden: %d bytes] ######\n" mid_len in
let warning =
sprintf "###### Warning: bytes %d-%d below were elided ######\n"
head_len
(head_len + mid_len - 1)
in
String.concat ""
[
decorate_comment warning;
decorate_data_fragment head;
decorate_comment mid;
decorate_data_fragment tail;
]
let quote_multiline_text =
let margin = " " in
fun ?( = color Yellow)
?(decorate_data_fragment = fun str -> str) ?max_bytes str ->
str
|> truncate_text ~decorate_comment ~decorate_data_fragment ~max_bytes
|> String.split_on_char '\n'
|> Helpers.list_map (fun line -> margin ^ line ^ "\n")
|> String.concat ""