Source file indentPrinter.ml
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
open Nstream
open Approx_lexer
type output_elt =
| Newline
| Indent of int
| Whitespace of string
| Text of string
type 'a output_kind =
| Numeric of (int -> 'a -> 'a)
| Print of (string -> 'a -> 'a)
| Extended of (IndentBlock.t -> output_elt -> 'a -> 'a)
type 'a output = {
debug: bool;
config: IndentConfig.t;
in_lines: int -> bool;
adaptive: bool;
indent_empty: bool;
kind: 'a output_kind;
}
let std_output = {
debug = false;
config = IndentConfig.default;
in_lines = (fun _ -> true);
adaptive = true;
indent_empty = false;
kind = Print (fun s () -> print_endline s);
}
let pr_string output block text usr =
match output.kind with
| Numeric _ -> usr
| Print f -> f text usr
| Extended f -> f block (Text text) usr
let pr_whitespace output block text usr =
match output.kind with
| Numeric _ -> usr
| Print f -> f text usr
| Extended f -> f block (Whitespace text) usr
let warn_tabs = ref true
let print_indent ?(empty_line = false) output line blank block usr =
if output.in_lines line then
let indent =
if empty_line then
if output.indent_empty then
IndentBlock.guess_indent block
else
0
else
IndentBlock.indent block in
match output.kind with
| Numeric pr -> pr indent usr
| Print pr -> pr (String.make indent ' ') usr
| Extended pr -> pr block (Indent indent) usr
else begin
if !warn_tabs && String.contains blank '\t' then begin
warn_tabs := false;
prerr_endline
"Warning: ocp-indent input contains indentation by tabs, \
partial indent will be unreliable."
end;
match output.kind with
| Numeric _ -> usr
| Print pr -> pr blank usr
| Extended pr -> pr block (Whitespace blank) usr
end
let print_spacing output block tok usr =
let line = Region.start_line tok.region in
if IndentBlock.starts_line block then
let empty_line =
match tok.token with
| EOL -> true
| _ -> false in
print_indent ~empty_line output line tok.between block usr
else
pr_whitespace output block tok.between usr
let rec proceed output stream block usr =
match Nstream.next stream with
| Some ({token = EOF }, _)
| None -> usr
| Some (tok, stream) ->
let block = IndentBlock.update output.config block stream tok in
let line = Region.start_line tok.region in
let block =
if output.adaptive && not (output.in_lines line)
then IndentBlock.reverse block
else block
in
if output.debug &&
true then
IndentBlock.dump block;
usr
|> print_spacing output block tok
|> pr_string output block tok.substr
|> proceed output stream block