oppen 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -2
- data/lib/oppen/mixins.rb +42 -39
- data/lib/oppen/print_stack.rb +62 -69
- data/lib/oppen/printer.rb +91 -78
- data/lib/oppen/scan_stack.rb +36 -16
- data/lib/oppen/token.rb +51 -36
- data/lib/oppen/version.rb +3 -2
- data/lib/oppen.rb +177 -77
- data/lib/wadler/print.rb +221 -46
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '008545ae6d86a7415e434ef51a19872fbf5b768db232d70bbac025667e002604'
|
4
|
+
data.tar.gz: a989a6e8d422c363e7ebca36fc10dac4ad030f145afc2b4bc152c9cff5bdfe49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a3e32d3a05c638bd26a9e170d737186c9635eeb3c54844869b108c8252fdafa942a05a76a1e3d3d25d5e93a47d076c280f7346c1c313b5c7159a8f3d1166ef6
|
7
|
+
data.tar.gz: 1f3c076ea8b298f5a772d9c209c4bc64087f6093576e41e2ffb6289b5d0aba08c1b3ed9d3022ebb14b7d7fe4c083804e60219735bce5c00f96785e9dede2bb69
|
data/README.md
CHANGED
data/lib/oppen/mixins.rb
CHANGED
@@ -4,70 +4,73 @@ module Oppen
|
|
4
4
|
# Mixins.
|
5
5
|
module Mixins
|
6
6
|
# Rotates circular array and triples its size.
|
7
|
-
# This method is not for public use.
|
8
7
|
#
|
9
|
-
#
|
10
|
-
# @
|
8
|
+
# @!visibility private
|
9
|
+
# @note This method is not for public use.
|
11
10
|
#
|
12
|
-
# @
|
11
|
+
# @param arr [Array]
|
12
|
+
# the circular array.
|
13
|
+
# @param offset [Integer]
|
14
|
+
# rotation amount.
|
15
|
+
#
|
16
|
+
# @return [Array<Array, Integer, Integer>]
|
17
|
+
# upsized array, lhs, rhs.
|
13
18
|
def upsize_circular_array(arr, offset)
|
14
19
|
size = arr.size
|
15
|
-
arr = arr.rotate
|
16
|
-
arr.fill
|
20
|
+
arr = arr.rotate offset
|
21
|
+
arr.fill nil, size, 2 * size
|
17
22
|
[arr, 0, size]
|
18
23
|
end
|
19
24
|
|
20
|
-
# Convert a list of tokens to its wadler representation.
|
21
|
-
#
|
22
|
-
# @param tokens [Array[Token]]
|
23
|
-
# @param base_indent [Integer]
|
24
|
-
# @param printer_name [String]
|
25
|
-
#
|
26
25
|
# @return [String]
|
27
|
-
def tokens_to_wadler(tokens, base_indent: 0, printer_name: 'out')
|
28
|
-
|
29
|
-
|
26
|
+
def tokens_to_wadler(tokens, base_indent: 0, printer_name: 'out', width: tokens.length * 3)
|
27
|
+
printer = Oppen::Wadler.new(width: width)
|
28
|
+
printer.base_indent(base_indent)
|
29
|
+
indent = 2
|
30
30
|
|
31
|
-
|
32
|
-
out << (' ' * nb_spaces) << txt << "\n"
|
33
|
-
}
|
34
|
-
display_break_token = ->(token) {
|
31
|
+
handle_break_token = ->(token) {
|
35
32
|
if token.offset.positive?
|
36
|
-
|
37
|
-
|
33
|
+
printer.text "#{printer_name}.nest(#{token.offset}, '', '') {"
|
34
|
+
printer.nest_open indent
|
35
|
+
printer.break
|
38
36
|
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
printer.text(
|
39
|
+
case token
|
40
|
+
in Token::LineBreak
|
41
|
+
"#{printer_name}.break(line_continuation: #{token.line_continuation.inspect})"
|
42
|
+
in Token::Break
|
43
|
+
"#{printer_name}.breakable(#{token.str.inspect}, width: #{token.width}, " \
|
44
|
+
"line_continuation: #{token.line_continuation.inspect})"
|
45
|
+
end,
|
46
|
+
)
|
47
47
|
|
48
48
|
if token.offset.positive?
|
49
|
-
|
50
|
-
|
49
|
+
printer.nest_close indent
|
50
|
+
printer.break
|
51
|
+
printer.text '}'
|
51
52
|
end
|
52
53
|
}
|
53
54
|
|
54
|
-
tokens.
|
55
|
+
tokens.each_with_index do |token, idx|
|
55
56
|
case token
|
56
57
|
in Token::String
|
57
|
-
|
58
|
+
printer.text "#{printer_name}.text(#{token.value.inspect}, width: #{token.width})"
|
58
59
|
in Token::Break
|
59
|
-
|
60
|
+
handle_break_token.(token)
|
60
61
|
in Token::Begin
|
61
|
-
|
62
|
-
|
62
|
+
printer.text "#{printer_name}.group(#{token.offset}, '', '', #{token.break_type.inspect}) {"
|
63
|
+
printer.nest_open indent
|
63
64
|
in Token::End
|
64
|
-
|
65
|
-
|
65
|
+
printer.nest_close indent
|
66
|
+
printer.break
|
67
|
+
printer.text '}'
|
66
68
|
in Token::EOF
|
67
|
-
|
69
|
+
nil
|
68
70
|
end
|
71
|
+
printer.break if !tokens[idx + 1].is_a?(Token::End)
|
69
72
|
end
|
70
|
-
|
73
|
+
printer.output
|
71
74
|
end
|
72
75
|
end
|
73
76
|
end
|
data/lib/oppen/print_stack.rb
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
# Oppen.
|
4
4
|
module Oppen
|
5
|
-
#
|
6
|
-
# using the values of the tokens that were pushed into it.
|
5
|
+
# A stack of {Token}s.
|
7
6
|
class PrintStack
|
8
|
-
#
|
7
|
+
# An item in the print stack.
|
9
8
|
class PrintStackEntry
|
10
|
-
# @return [
|
11
|
-
|
12
|
-
# @return [Token::BreakType] (Called break in the original paper).
|
9
|
+
# @return [Token::BreakType]
|
10
|
+
# Called `break` in the original paper.
|
13
11
|
attr_reader :break_type
|
12
|
+
# @return [Integer]
|
13
|
+
# Indentation level.
|
14
|
+
attr_reader :offset
|
14
15
|
|
15
16
|
def initialize(offset, break_type)
|
16
17
|
@offset = offset
|
@@ -18,34 +19,26 @@ module Oppen
|
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
|
-
# IO
|
22
|
+
# IO sink for the output.
|
22
23
|
attr_reader :buffer
|
23
|
-
|
24
|
-
# Config containing customization flags
|
24
|
+
# The printer's configuration, altering its behavior.
|
25
25
|
attr_reader :config
|
26
|
-
|
27
|
-
# Callable that generate spaces
|
26
|
+
# Space generator, a callable.
|
28
27
|
attr_reader :genspace
|
29
|
-
|
30
|
-
# Array representing the stack of PrintStackEntries.
|
28
|
+
# The stack of PrintStackEntries.
|
31
29
|
attr_reader :items
|
32
|
-
|
33
|
-
# Delimiter between lines in output
|
30
|
+
# Delimiter between lines.
|
34
31
|
attr_reader :new_line
|
35
|
-
|
36
|
-
# Maximum allowed width for printing (Called length in the original paper).
|
37
|
-
attr_reader :width
|
38
|
-
|
39
|
-
# Current available space (Called index in the original paper).
|
40
|
-
#
|
41
|
-
# @return [Integer] Current available space (Called index in the original paper).
|
32
|
+
# Current available space (`index` in the original paper).
|
42
33
|
attr_reader :space
|
34
|
+
# Maximum allowed width for printing (`length` in the original paper).
|
35
|
+
attr_reader :width
|
43
36
|
|
44
37
|
def initialize(width, new_line, config, space, out)
|
45
38
|
@buffer = out
|
46
39
|
@config = config
|
47
40
|
@genspace =
|
48
|
-
if space.respond_to?
|
41
|
+
if space.respond_to? :call
|
49
42
|
raise ArgumentError, 'space argument must be a Proc of arity 1' \
|
50
43
|
if space.to_proc.arity != 1
|
51
44
|
|
@@ -53,28 +46,32 @@ module Oppen
|
|
53
46
|
else
|
54
47
|
->(n) { space * n }
|
55
48
|
end
|
56
|
-
@indent = 0
|
49
|
+
@indent = 0 # the amount of indentation to display on the next non empty new line.
|
57
50
|
@items = []
|
58
51
|
@new_line = new_line
|
59
52
|
@width = width
|
60
53
|
@space = width
|
61
54
|
end
|
62
55
|
|
63
|
-
#
|
56
|
+
# The final pretty-printed output.
|
64
57
|
#
|
65
58
|
# @return [String]
|
59
|
+
# The output of the print stack.
|
66
60
|
def output
|
67
|
-
buffer.truncate
|
61
|
+
buffer.truncate buffer.pos
|
68
62
|
buffer.string
|
69
63
|
end
|
70
64
|
|
71
|
-
# Core method responsible for building the print stack and the output
|
65
|
+
# Core method responsible for building the print stack and the output
|
66
|
+
# string.
|
72
67
|
#
|
73
|
-
# @note Called Print in the original paper.
|
68
|
+
# @note Called `Print` in the original paper.
|
74
69
|
#
|
75
|
-
# @param token
|
76
|
-
# @param token_width
|
77
|
-
# @param trim_on_break [Integer]
|
70
|
+
# @param token [Token]
|
71
|
+
# @param token_width [Integer]
|
72
|
+
# @param trim_on_break [Integer]
|
73
|
+
# number of trailing whitespace characters to trim. If zero, no
|
74
|
+
# character will be trimmed.
|
78
75
|
#
|
79
76
|
# @return [Nil]
|
80
77
|
def print(token, token_width, trim_on_break: 0)
|
@@ -84,29 +81,27 @@ module Oppen
|
|
84
81
|
in Token::End
|
85
82
|
handle_end
|
86
83
|
in Token::Break
|
87
|
-
handle_break token, token_width, trim_on_break:
|
84
|
+
handle_break token, token_width, trim_on_break: trim_on_break
|
88
85
|
in Token::String
|
89
86
|
handle_string token, token_width
|
90
87
|
end
|
91
88
|
end
|
92
89
|
|
93
|
-
# Handle Begin
|
90
|
+
# Handle {Token::Begin}.
|
94
91
|
#
|
95
|
-
# @param token
|
92
|
+
# @param token [Token]
|
96
93
|
# @param token_width [Integer]
|
97
94
|
#
|
98
95
|
# @return [Nil]
|
99
|
-
#
|
100
|
-
# @see Token::Begin
|
101
96
|
def handle_begin(token, token_width)
|
102
97
|
if token_width > space
|
103
98
|
type =
|
104
|
-
if token.break_type ==
|
105
|
-
|
99
|
+
if token.break_type == :consistent
|
100
|
+
:consistent
|
106
101
|
else
|
107
|
-
|
102
|
+
:inconsistent
|
108
103
|
end
|
109
|
-
if config&.indent_anchor ==
|
104
|
+
if config&.indent_anchor == :current_offset
|
110
105
|
indent = token.offset
|
111
106
|
if !items.empty?
|
112
107
|
indent += top.offset
|
@@ -116,55 +111,54 @@ module Oppen
|
|
116
111
|
end
|
117
112
|
push PrintStackEntry.new indent, type
|
118
113
|
else
|
119
|
-
push PrintStackEntry.new 0,
|
114
|
+
push PrintStackEntry.new 0, :fits
|
120
115
|
end
|
121
116
|
end
|
122
117
|
|
123
|
-
# Handle End
|
118
|
+
# Handle {Token::End}.
|
124
119
|
#
|
125
120
|
# @return [Nil]
|
126
|
-
#
|
127
|
-
# @see Token::End
|
128
121
|
def handle_end
|
129
122
|
pop
|
130
123
|
end
|
131
124
|
|
132
|
-
# Handle Break
|
125
|
+
# Handle {Token::Break}.
|
133
126
|
#
|
134
|
-
# @param token
|
135
|
-
# @param token_width
|
136
|
-
# @param trim_on_break [Integer]
|
127
|
+
# @param token [Token::Break]
|
128
|
+
# @param token_width [Integer]
|
129
|
+
# @param trim_on_break [Integer]
|
130
|
+
# number of trailing whitespace characters to trim.
|
131
|
+
# 0 = none.
|
137
132
|
#
|
138
133
|
# @return [Nil]
|
139
|
-
#
|
140
|
-
# @see Token::Break
|
141
134
|
def handle_break(token, token_width, trim_on_break: 0)
|
142
135
|
block = top
|
143
136
|
case block.break_type
|
144
|
-
in
|
137
|
+
in :fits
|
138
|
+
# No new line is needed (the block fits on the line).
|
145
139
|
@space -= token.width
|
146
140
|
write token
|
147
|
-
in
|
141
|
+
in :consistent
|
148
142
|
@space = block.offset - token.offset
|
149
143
|
indent =
|
150
|
-
if config&.indent_anchor ==
|
144
|
+
if config&.indent_anchor == :current_offset
|
151
145
|
token.offset
|
152
146
|
else
|
153
147
|
width - space
|
154
148
|
end
|
155
|
-
erase
|
149
|
+
erase trim_on_break
|
156
150
|
write token.line_continuation
|
157
151
|
print_new_line indent
|
158
|
-
in
|
152
|
+
in :inconsistent
|
159
153
|
if token_width > space
|
160
154
|
@space = block.offset - token.offset
|
161
155
|
indent =
|
162
|
-
if config&.indent_anchor ==
|
156
|
+
if config&.indent_anchor == :current_offset
|
163
157
|
token.offset
|
164
158
|
else
|
165
159
|
width - space
|
166
160
|
end
|
167
|
-
erase
|
161
|
+
erase trim_on_break
|
168
162
|
write token.line_continuation
|
169
163
|
print_new_line indent
|
170
164
|
else
|
@@ -174,14 +168,12 @@ module Oppen
|
|
174
168
|
end
|
175
169
|
end
|
176
170
|
|
177
|
-
# Handle String
|
171
|
+
# Handle {Token::String}.
|
178
172
|
#
|
179
|
-
# @param token
|
173
|
+
# @param token [Token::String]
|
180
174
|
# @param token_width [Integer]
|
181
175
|
#
|
182
176
|
# @return [Nil]
|
183
|
-
#
|
184
|
-
# @see Token::String
|
185
177
|
def handle_string(token, token_width)
|
186
178
|
return if token.value.empty?
|
187
179
|
|
@@ -193,16 +185,16 @@ module Oppen
|
|
193
185
|
write token
|
194
186
|
end
|
195
187
|
|
196
|
-
# Push a PrintStackEntry into the stack.
|
188
|
+
# Push a {PrintStackEntry} into the stack.
|
197
189
|
#
|
198
190
|
# @param print_stack_entry [PrintStackEntry]
|
199
191
|
#
|
200
192
|
# @return [Nil]
|
201
193
|
def push(print_stack_entry)
|
202
|
-
items.append
|
194
|
+
items.append print_stack_entry
|
203
195
|
end
|
204
196
|
|
205
|
-
# Pop a PrintStackEntry from the stack.
|
197
|
+
# Pop a {PrintStackEntry} from the stack.
|
206
198
|
#
|
207
199
|
# @return [PrintStackEntry]
|
208
200
|
def pop
|
@@ -226,14 +218,15 @@ module Oppen
|
|
226
218
|
|
227
219
|
# Add a new line to the output.
|
228
220
|
#
|
229
|
-
# @note Called PrintNewLine as well in the original paper.
|
221
|
+
# @note Called `PrintNewLine` as well in the original paper.
|
230
222
|
#
|
231
|
-
# @param amount [Integer]
|
223
|
+
# @param amount [Integer]
|
224
|
+
# indentation amount.
|
232
225
|
#
|
233
226
|
# @return [Nil]
|
234
227
|
def print_new_line(amount)
|
235
228
|
write new_line
|
236
|
-
if config&.indent_anchor ==
|
229
|
+
if config&.indent_anchor == :current_offset
|
237
230
|
@space = width - top.offset - amount
|
238
231
|
@indent = width - space
|
239
232
|
else
|
@@ -247,7 +240,7 @@ module Oppen
|
|
247
240
|
#
|
248
241
|
# @return [Nil]
|
249
242
|
def write(obj)
|
250
|
-
buffer.write
|
243
|
+
buffer.write obj.to_s
|
251
244
|
end
|
252
245
|
|
253
246
|
# Erase the last `count` characters.
|
@@ -264,7 +257,7 @@ module Oppen
|
|
264
257
|
|
265
258
|
# Add indentation by `amount`.
|
266
259
|
#
|
267
|
-
# @note Called Indent as well in the original paper.
|
260
|
+
# @note Called `Indent` as well in the original paper.
|
268
261
|
#
|
269
262
|
# @param amount [Integer]
|
270
263
|
#
|