@@ -22,7 +22,6 @@ module CodePrinter = struct
22
22
The idea is that we capture events in a context type.
23
23
Doing this allows us to reason about the current state of the writer
24
24
and whether the next expression fits on the current line or not.
25
-
26
25
*)
27
26
28
27
type writerEvents =
@@ -31,27 +30,39 @@ module CodePrinter = struct
31
30
| IndentBy of int
32
31
| UnindentBy of int
33
32
33
+ type writerMode = Standard | TrySingleLine | ConfirmedMultiline
34
+
35
+ (* Type representing the writer context during code printing
36
+
37
+ - [indent_size] is the configured indentation size, typically 2
38
+ - [max_line_length] is the maximum line length before we break the line
39
+ - [current_indent] is the current indentation size
40
+ - [current_line_column] is the characters written on the current line
41
+ - [line_count] is the number of lines written
42
+ - [events] is the write events in reverse order, head event is last written
43
+ - [mode] is the current writer mode (Standard or SingleLine)
44
+ *)
34
45
type context = {
35
46
indent_size : int ;
36
47
max_line_length : int ;
37
48
current_indent : int ;
38
49
current_line_column : int ;
39
- events : writerEvents list ;
40
50
line_count : int ;
41
- nesting_level : int ;
51
+ events : writerEvents list ;
52
+ mode : writerMode ;
42
53
}
43
54
44
55
type appendEvents = context -> context
45
56
46
57
let emptyContext =
47
58
{
48
59
indent_size = 2 ;
49
- max_line_length = 80 ;
60
+ max_line_length = 120 ;
50
61
current_indent = 0 ;
51
62
current_line_column = 0 ;
52
- events = [] ;
53
63
line_count = 0 ;
54
- nesting_level = 0 ;
64
+ events = [] ;
65
+ mode = Standard ;
55
66
}
56
67
57
68
(* * Fold all the events in context into text *)
@@ -76,22 +87,30 @@ module CodePrinter = struct
76
87
Buffer. contents buf
77
88
78
89
let debug_context (ctx : context ) =
79
- Format. printf " Current indent: %d, Current line: %d, Events: %d\n "
80
- ctx.current_indent ctx.line_count (List. length ctx.events);
90
+ let mode =
91
+ match ctx.mode with
92
+ | Standard -> " Standard"
93
+ | TrySingleLine _ -> " TrySingleLine"
94
+ | ConfirmedMultiline -> " ConfirmedMultiline"
95
+ in
96
+ Format. printf
97
+ " Current indent: %d, Current column: %d, # Lines: %d Events: %d, Mode: %s\n "
98
+ ctx.current_indent ctx.current_line_column ctx.line_count
99
+ (List. length ctx.events) mode;
81
100
ctx
82
101
83
- let increase_nesting ctx = { ctx with nesting_level = ctx.nesting_level + 1 }
84
-
85
- let decrease_nesting ctx =
86
- {ctx with nesting_level = max 0 (ctx.nesting_level - 1 )}
87
-
88
- (* Type representing the writer context during code printing
89
-
90
- - [indent_size] is the configured indentation size, typically 2
91
- - [current_indent] is the current indentation size
92
- - [current_line_column] is the characters written on the current line
93
- - [events] is the write events in reverse order, head event is last written
94
- *)
102
+ let updateMode ( newlineWasAdded : bool ) ( ctx : context ) =
103
+ match ctx.mode with
104
+ | Standard -> ctx
105
+ | ConfirmedMultiline -> ctx
106
+ | TrySingleLine ->
107
+ {
108
+ ctx with
109
+ mode =
110
+ ( if newlineWasAdded || ctx.current_line_column > ctx.max_line_length
111
+ then ConfirmedMultiline
112
+ else TrySingleLine );
113
+ }
95
114
96
115
let id x = x
97
116
@@ -102,9 +121,14 @@ module CodePrinter = struct
102
121
events = Write str :: ctx .events;
103
122
current_line_column = ctx.current_line_column + String. length str;
104
123
}
124
+ |> updateMode false
105
125
106
126
(* * compose two context transforming functions *)
107
- let ( +> ) f g ctx = g (f ctx)
127
+ let ( +> ) f g ctx =
128
+ let fCtx = f ctx in
129
+ match fCtx.mode with
130
+ | ConfirmedMultiline -> fCtx
131
+ | _ -> g fCtx
108
132
109
133
let sepNln ctx =
110
134
{
@@ -113,6 +137,8 @@ module CodePrinter = struct
113
137
current_line_column = ctx.current_indent;
114
138
line_count = ctx.line_count + 1 ;
115
139
}
140
+ |> updateMode true
141
+
116
142
let sepSpace ctx = ! - " " ctx
117
143
let sepComma ctx = ! - " , " ctx
118
144
let sepSemi ctx = ! - " ; " ctx
@@ -156,13 +182,20 @@ module CodePrinter = struct
156
182
157
183
let expressionFitsOnRestOfLine (f : appendEvents ) (fallback : appendEvents )
158
184
(ctx : context ) =
159
- (* create a short context and check if the expression fits on the current line *)
160
- let shortCtx = f ctx in
161
- if
162
- ctx.line_count == shortCtx.line_count
163
- && shortCtx.current_line_column < = ctx.max_line_length
164
- then shortCtx
165
- else fallback ctx
185
+ match ctx.mode with
186
+ | ConfirmedMultiline -> ctx
187
+ | _ -> (
188
+ let shortCtx =
189
+ match ctx.mode with
190
+ | Standard -> {ctx with mode = TrySingleLine }
191
+ | _ -> ctx
192
+ in
193
+ let resultCtx = f shortCtx in
194
+ match resultCtx.mode with
195
+ | ConfirmedMultiline -> fallback ctx
196
+ | TrySingleLine -> {resultCtx with mode = ctx.mode}
197
+ | Standard ->
198
+ failwith " Unexpected Standard mode after trying SingleLine mode" )
166
199
167
200
let rec genOak (oak : oak ) : appendEvents =
168
201
match oak with
@@ -240,6 +273,11 @@ module CodePrinter = struct
240
273
expressionFitsOnRestOfLine short long
241
274
end
242
275
276
+ (*
277
+ Interpret using ocaml /home/nojaf/projects/rescript-vscode/tools/src/prettier_printer.ml
278
+ *)
279
+
280
+ (*
243
281
open DSL
244
282
245
283
let oak =
@@ -271,10 +309,6 @@ let oak =
271
309
{name = "foo"; value = Ident "baaaaaaaaaaaaaaaaar"};
272
310
]
273
311
274
- (* let _ =
312
+ let _ =
275
313
CodePrinter.genOak oak {CodePrinter.emptyContext with max_line_length = 20}
276
314
|> CodePrinter.dump |> Format.printf "%s\n" *)
277
-
278
- (*
279
- Interpret using ocaml /home/nojaf/projects/rescript-vscode/tools/src/prettier_printer.ml
280
- *)
0 commit comments