oppen 0.9.5 → 0.9.7
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/lib/oppen/mixins.rb +31 -11
- data/lib/oppen/print_stack.rb +30 -6
- data/lib/oppen/printer.rb +35 -3
- data/lib/oppen/token.rb +17 -0
- data/lib/oppen/version.rb +1 -1
- data/lib/oppen.rb +14 -3
- data/lib/wadler/print.rb +38 -10
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b656616fe07cf5b29b8dfa43f0b72ed6dbf80c56a9ca6790745a8db27f058ed7
|
4
|
+
data.tar.gz: 3d46ddc3a703d029ac22460ac504cf2928f95d804d32e0266f0de7ffbbfd3359
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b69f0365a507dc9fca546cbfea064593a48d0d85140cd894ed2ff256e13c4c0e772bf9e0d2b29f9eefd9121c8b3adf03da93137c15b3c9570f6a7e49ed435b2
|
7
|
+
data.tar.gz: aa608fa2238dc8eea6bf3ce5d03f10e6f8059eda98c02d1e53fa06f9ac9301b03b42e54b38ed4f945c28766c4959b441cc190b76f0f176a72c7f52967096258a
|
data/lib/oppen/mixins.rb
CHANGED
@@ -21,30 +21,50 @@ module Oppen
|
|
21
21
|
#
|
22
22
|
# @param tokens [Array[Token]]
|
23
23
|
# @param base_indent [Integer]
|
24
|
+
# @param printer_name [String]
|
24
25
|
#
|
25
26
|
# @return [String]
|
26
|
-
def tokens_to_wadler(tokens, base_indent
|
27
|
+
def tokens_to_wadler(tokens, base_indent: 0, printer_name: 'out')
|
28
|
+
nb_spaces = base_indent
|
27
29
|
out = StringIO.new
|
28
|
-
|
29
|
-
|
30
|
+
|
31
|
+
write = ->(txt) {
|
32
|
+
out << (' ' * nb_spaces) << txt << "\n"
|
30
33
|
}
|
31
|
-
|
34
|
+
display_break_token = ->(token) {
|
35
|
+
if token.offset.positive?
|
36
|
+
write.("#{printer_name}.nest(#{token.offset}, \"\", \"\") {")
|
37
|
+
nb_spaces += 2
|
38
|
+
end
|
39
|
+
|
40
|
+
case token
|
41
|
+
in Token::LineBreak
|
42
|
+
write.("#{printer_name}.break(line_continuation: #{token.line_continuation.inspect})")
|
43
|
+
in Token::Break
|
44
|
+
write.("#{printer_name}.breakable(#{token.str.inspect}, width: #{token.width}, " \
|
45
|
+
"line_continuation: #{token.line_continuation.inspect})")
|
46
|
+
end
|
47
|
+
|
48
|
+
if token.offset.positive?
|
49
|
+
nb_spaces -= 2
|
50
|
+
write.('}')
|
51
|
+
end
|
52
|
+
}
|
53
|
+
|
32
54
|
tokens.each do |token|
|
33
55
|
case token
|
34
56
|
in Token::String
|
35
|
-
write.
|
36
|
-
in Token::LineBreak
|
37
|
-
write.call('out.break', nb_spaces)
|
57
|
+
write.("#{printer_name}.text(#{token.value.inspect}, width: #{token.width})")
|
38
58
|
in Token::Break
|
39
|
-
|
59
|
+
display_break_token.(token)
|
40
60
|
in Token::Begin
|
41
|
-
write.
|
61
|
+
write.("#{printer_name}.group(#{token.offset}, \"\", \"\", #{token.break_type_name}) {")
|
42
62
|
nb_spaces += 2
|
43
63
|
in Token::End
|
44
64
|
nb_spaces -= 2
|
45
|
-
write.
|
65
|
+
write.('}')
|
46
66
|
in Token::EOF
|
47
|
-
write.
|
67
|
+
write.('') # new line
|
48
68
|
end
|
49
69
|
end
|
50
70
|
out.string
|
data/lib/oppen/print_stack.rb
CHANGED
@@ -53,6 +53,7 @@ module Oppen
|
|
53
53
|
else
|
54
54
|
->(n) { space * n }
|
55
55
|
end
|
56
|
+
@indent = 0
|
56
57
|
@items = []
|
57
58
|
@new_line = new_line
|
58
59
|
@width = width
|
@@ -63,6 +64,7 @@ module Oppen
|
|
63
64
|
#
|
64
65
|
# @return [String]
|
65
66
|
def output
|
67
|
+
buffer.truncate(buffer.pos)
|
66
68
|
buffer.string
|
67
69
|
end
|
68
70
|
|
@@ -72,16 +74,17 @@ module Oppen
|
|
72
74
|
#
|
73
75
|
# @param token [Token]
|
74
76
|
# @param token_width [Integer]
|
77
|
+
# @param trim_on_break [Integer] Number of trailing whitespace characters to trim.
|
75
78
|
#
|
76
79
|
# @return [Nil]
|
77
|
-
def print(token, token_width)
|
80
|
+
def print(token, token_width, trim_on_break: 0)
|
78
81
|
case token
|
79
82
|
in Token::Begin
|
80
83
|
handle_begin token, token_width
|
81
84
|
in Token::End
|
82
85
|
handle_end
|
83
86
|
in Token::Break
|
84
|
-
handle_break token, token_width
|
87
|
+
handle_break token, token_width, trim_on_break:
|
85
88
|
in Token::String
|
86
89
|
handle_string token, token_width
|
87
90
|
end
|
@@ -130,11 +133,12 @@ module Oppen
|
|
130
133
|
#
|
131
134
|
# @param token [Token]
|
132
135
|
# @param token_width [Integer]
|
136
|
+
# @param trim_on_break [Integer] Number of trailing whitespace characters to trim.
|
133
137
|
#
|
134
138
|
# @return [Nil]
|
135
139
|
#
|
136
140
|
# @see Token::Break
|
137
|
-
def handle_break(token, token_width)
|
141
|
+
def handle_break(token, token_width, trim_on_break: 0)
|
138
142
|
block = top
|
139
143
|
case block.break_type
|
140
144
|
in Token::BreakType::FITS
|
@@ -148,6 +152,7 @@ module Oppen
|
|
148
152
|
else
|
149
153
|
width - space
|
150
154
|
end
|
155
|
+
erase(trim_on_break)
|
151
156
|
write token.line_continuation
|
152
157
|
print_new_line indent
|
153
158
|
in Token::BreakType::INCONSISTENT
|
@@ -159,6 +164,7 @@ module Oppen
|
|
159
164
|
else
|
160
165
|
width - space
|
161
166
|
end
|
167
|
+
erase(trim_on_break)
|
162
168
|
write token.line_continuation
|
163
169
|
print_new_line indent
|
164
170
|
else
|
@@ -177,7 +183,13 @@ module Oppen
|
|
177
183
|
#
|
178
184
|
# @see Token::String
|
179
185
|
def handle_string(token, token_width)
|
186
|
+
return if token.value.empty?
|
187
|
+
|
180
188
|
@space = [0, space - token_width].max
|
189
|
+
if @indent.positive?
|
190
|
+
indent @indent
|
191
|
+
@indent = 0
|
192
|
+
end
|
181
193
|
write token
|
182
194
|
end
|
183
195
|
|
@@ -223,9 +235,9 @@ module Oppen
|
|
223
235
|
write new_line
|
224
236
|
if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
|
225
237
|
@space = width - top.offset - amount
|
226
|
-
indent width - space
|
238
|
+
@indent = width - space
|
227
239
|
else
|
228
|
-
indent amount
|
240
|
+
@indent = amount
|
229
241
|
end
|
230
242
|
end
|
231
243
|
|
@@ -238,6 +250,18 @@ module Oppen
|
|
238
250
|
buffer.write(obj.to_s)
|
239
251
|
end
|
240
252
|
|
253
|
+
# Erase the last `count` characters.
|
254
|
+
#
|
255
|
+
# @param count [Integer]
|
256
|
+
#
|
257
|
+
# @return [Nil]
|
258
|
+
def erase(count = 0)
|
259
|
+
raise ArgumentError, "count = #{count} must be non-negative" if count.negative?
|
260
|
+
|
261
|
+
buffer.seek(-count, IO::SEEK_CUR)
|
262
|
+
@space += count
|
263
|
+
end
|
264
|
+
|
241
265
|
# Add indentation by `amount`.
|
242
266
|
#
|
243
267
|
# @note Called Indent as well in the original paper.
|
@@ -248,7 +272,7 @@ module Oppen
|
|
248
272
|
def indent(amount)
|
249
273
|
raise ArgumentError 'Indenting using negative amount' if amount.negative?
|
250
274
|
|
251
|
-
write genspace.
|
275
|
+
write genspace.(amount) if amount.positive?
|
252
276
|
end
|
253
277
|
end
|
254
278
|
end
|
data/lib/oppen/printer.rb
CHANGED
@@ -78,6 +78,7 @@ module Oppen
|
|
78
78
|
n = 3 * width
|
79
79
|
|
80
80
|
@config = config
|
81
|
+
@last_whitespaces_width = 0
|
81
82
|
@left = 0
|
82
83
|
@left_total = 1
|
83
84
|
@print_stack = PrintStack.new width, new_line, config, space, out
|
@@ -110,7 +111,11 @@ module Oppen
|
|
110
111
|
handle_end token
|
111
112
|
in Token::Break
|
112
113
|
handle_break token
|
114
|
+
in Token::Whitespace
|
115
|
+
@last_whitespaces_width += token.width
|
116
|
+
handle_string token
|
113
117
|
in Token::String
|
118
|
+
@last_whitespaces_width = 0
|
114
119
|
handle_string token
|
115
120
|
end
|
116
121
|
end
|
@@ -139,6 +144,9 @@ module Oppen
|
|
139
144
|
@left_total = 1
|
140
145
|
@right = 0
|
141
146
|
@right_total = 1
|
147
|
+
|
148
|
+
# config.trim_trailing_whitespaces
|
149
|
+
@tokens[-1] = nil
|
142
150
|
else
|
143
151
|
advance_right
|
144
152
|
end
|
@@ -179,6 +187,11 @@ module Oppen
|
|
179
187
|
@left_total = 1
|
180
188
|
@right = 0
|
181
189
|
@right_total = 1
|
190
|
+
|
191
|
+
# config.trim_trailing_whitespaces
|
192
|
+
tokens[-1] = nil
|
193
|
+
print_stack.erase @last_whitespaces_width
|
194
|
+
@last_whitespaces_width = 0
|
182
195
|
else
|
183
196
|
advance_right
|
184
197
|
end
|
@@ -202,7 +215,7 @@ module Oppen
|
|
202
215
|
tokens[right] = token
|
203
216
|
size[right] = token.width
|
204
217
|
@right_total += token.width
|
205
|
-
check_stream
|
218
|
+
check_stream if @last_whitespaces_width.zero?
|
206
219
|
end
|
207
220
|
end
|
208
221
|
|
@@ -249,7 +262,26 @@ module Oppen
|
|
249
262
|
def advance_left(token, token_width)
|
250
263
|
return if token_width.negative?
|
251
264
|
|
252
|
-
|
265
|
+
trim_on_break =
|
266
|
+
if token.is_a?(Token::Break)
|
267
|
+
# Find the first previous String token.
|
268
|
+
idx = (left - 1) % tokens.length
|
269
|
+
while idx != right && tokens[idx] && !tokens[idx].is_a?(Token::String) \
|
270
|
+
&& !tokens[idx].is_a?(Token::Break)
|
271
|
+
idx = (idx - 1) % tokens.length
|
272
|
+
end
|
273
|
+
# Sum the widths of the last whitespace tokens.
|
274
|
+
total = 0
|
275
|
+
while tokens[idx].is_a?(Token::Whitespace)
|
276
|
+
total += tokens[idx].width
|
277
|
+
idx = (idx - 1) % tokens.length
|
278
|
+
end
|
279
|
+
@last_whitespaces_width = 0
|
280
|
+
total
|
281
|
+
end
|
282
|
+
trim_on_break ||= 0
|
283
|
+
|
284
|
+
print_stack.print(token, token_width, trim_on_break:)
|
253
285
|
|
254
286
|
case token
|
255
287
|
when Token::Break
|
@@ -260,7 +292,7 @@ module Oppen
|
|
260
292
|
|
261
293
|
return if left == right
|
262
294
|
|
263
|
-
@left = (left + 1) %
|
295
|
+
@left = (left + 1) % tokens.length
|
264
296
|
advance_left tokens[left], size[left]
|
265
297
|
end
|
266
298
|
|
data/lib/oppen/token.rb
CHANGED
@@ -39,6 +39,12 @@ module Oppen
|
|
39
39
|
def to_s = value
|
40
40
|
end
|
41
41
|
|
42
|
+
# If a [Token::Break] follows [Token::Whitespace], and an actual break
|
43
|
+
# is issued, and `trim_trailing_whitespaces == true`, then all whitespace
|
44
|
+
# text will be omitted from the output.
|
45
|
+
class Whitespace < ::Oppen::Token::String
|
46
|
+
end
|
47
|
+
|
42
48
|
# Break Token.
|
43
49
|
class Break < Token
|
44
50
|
# @return [String] If a new line is needed display this string before the new line
|
@@ -89,6 +95,17 @@ module Oppen
|
|
89
95
|
@break_type = break_type
|
90
96
|
super()
|
91
97
|
end
|
98
|
+
|
99
|
+
# The break_type name as a String.
|
100
|
+
#
|
101
|
+
# @return [String]
|
102
|
+
def break_type_name
|
103
|
+
case @break_type
|
104
|
+
in BreakType::FITS then 'Oppen::Token::BreakType::FITS'
|
105
|
+
in BreakType::INCONSISTENT then 'Oppen::Token::BreakType::INCONSISTENT'
|
106
|
+
in BreakType::CONSISTENT then 'Oppen::Token::BreakType::CONSISTENT'
|
107
|
+
end
|
108
|
+
end
|
92
109
|
end
|
93
110
|
|
94
111
|
# End Token
|
data/lib/oppen/version.rb
CHANGED
data/lib/oppen.rb
CHANGED
@@ -51,9 +51,11 @@ module Oppen
|
|
51
51
|
|
52
52
|
attr_accessor :indent_anchor
|
53
53
|
|
54
|
-
def initialize(indent_anchor: IndentAnchor::ON_BREAK, eager_print: false,
|
54
|
+
def initialize(indent_anchor: IndentAnchor::ON_BREAK, eager_print: false,
|
55
|
+
trim_trailing_whitespaces: false, upsize_stack: false)
|
55
56
|
@indent_anchor = indent_anchor
|
56
57
|
@eager_print = eager_print
|
58
|
+
@trim_trailing_whitespaces = trim_trailing_whitespaces
|
57
59
|
@upsize_stack = upsize_stack
|
58
60
|
end
|
59
61
|
|
@@ -88,6 +90,8 @@ module Oppen
|
|
88
90
|
# @return [Boolean]
|
89
91
|
def eager_print? = @eager_print
|
90
92
|
|
93
|
+
def trim_trailing_whitespaces? = @trim_trailing_whitespaces
|
94
|
+
|
91
95
|
def upsize_stack? = @upsize_stack
|
92
96
|
|
93
97
|
# Default config for Oppen usage
|
@@ -98,8 +102,8 @@ module Oppen
|
|
98
102
|
|
99
103
|
# Default config for Wadler usage
|
100
104
|
# @return [Config]
|
101
|
-
def self.wadler(eager_print: true, upsize_stack: true)
|
102
|
-
new(indent_anchor: IndentAnchor::ON_BEGIN, eager_print:, upsize_stack:)
|
105
|
+
def self.wadler(eager_print: true, trim_trailing_whitespaces: true, upsize_stack: true)
|
106
|
+
new(indent_anchor: IndentAnchor::ON_BEGIN, eager_print:, trim_trailing_whitespaces:, upsize_stack:)
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
@@ -111,6 +115,13 @@ module Oppen
|
|
111
115
|
Token::String.new(value, width:)
|
112
116
|
end
|
113
117
|
|
118
|
+
# @see Token::Whitespace
|
119
|
+
#
|
120
|
+
# @return [Oppen::Token::Whitespace] a new Whitespace token.
|
121
|
+
def self.whitespace(value)
|
122
|
+
Token::Whitespace.new(value, width: value.bytesize)
|
123
|
+
end
|
124
|
+
|
114
125
|
# @param str [String]
|
115
126
|
# @param line_continuation [String] If a new line is needed display this string before the new line
|
116
127
|
# @param offset [Integer]
|
data/lib/wadler/print.rb
CHANGED
@@ -10,6 +10,7 @@ module Oppen
|
|
10
10
|
attr_reader :new_line
|
11
11
|
attr_reader :out
|
12
12
|
attr_reader :tokens
|
13
|
+
attr_reader :whitespace
|
13
14
|
attr_reader :width
|
14
15
|
|
15
16
|
# @param config [Oppen::Config]
|
@@ -22,8 +23,11 @@ module Oppen
|
|
22
23
|
# @param new_line [String]
|
23
24
|
# @param out [Object] should have a write and string method
|
24
25
|
# @param width [Integer]
|
26
|
+
# @param whitespace [String] the whitespace character. Used to trim trailing whitespaces.
|
27
|
+
# @see Token::Whitespace
|
25
28
|
def initialize(config: Config.wadler, space: ' ',
|
26
|
-
new_line: "\n", out: StringIO.new,
|
29
|
+
new_line: "\n", out: StringIO.new,
|
30
|
+
width: 80, whitespace: ' ')
|
27
31
|
@config = config
|
28
32
|
@current_indent = 0
|
29
33
|
@space = space
|
@@ -31,20 +35,37 @@ module Oppen
|
|
31
35
|
@new_line = new_line
|
32
36
|
@out = out
|
33
37
|
@tokens = []
|
38
|
+
@whitespace = whitespace
|
34
39
|
end
|
35
40
|
|
36
|
-
#
|
37
|
-
|
41
|
+
# Add missing Begin, End or EOF tokens.
|
42
|
+
# @return [Nil]
|
43
|
+
def add_missing_begin_and_end
|
38
44
|
if !tokens.first.is_a? Token::Begin
|
39
45
|
tokens.unshift Oppen.begin_consistent(offset: 0)
|
40
46
|
tokens << Oppen.end
|
41
47
|
end
|
42
|
-
if !tokens.last.is_a?
|
43
|
-
|
44
|
-
|
48
|
+
tokens << Oppen.eof if !tokens.last.is_a?(Oppen::Token::EOF)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Generate the output string of the built list of tokens
|
52
|
+
# using Oppen's pretty printing algorithm.
|
53
|
+
#
|
54
|
+
# @return [String]
|
55
|
+
def output
|
56
|
+
add_missing_begin_and_end
|
45
57
|
Oppen.print(tokens:, new_line:, config:, space:, out:, width:)
|
46
58
|
end
|
47
59
|
|
60
|
+
# Generate the the list of Wadler commands needed to build the built
|
61
|
+
# list of tokens.
|
62
|
+
#
|
63
|
+
# @return [String]
|
64
|
+
def show_print_commands(**)
|
65
|
+
add_missing_begin_and_end
|
66
|
+
Oppen.tokens_to_wadler(tokens, **)
|
67
|
+
end
|
68
|
+
|
48
69
|
# @param indent [Integer] group indentation
|
49
70
|
# @param open_obj [String] group opening delimiter
|
50
71
|
# @param close_obj [String] group closing delimiter
|
@@ -84,11 +105,9 @@ module Oppen
|
|
84
105
|
# @param indent [Integer] nest indentation
|
85
106
|
# @param open_obj [String] nest opening delimiter
|
86
107
|
# @param close_obj [String] nest closing delimiter
|
87
|
-
# @param break_type [Oppen::Token::BreakType] nest breaking type
|
88
108
|
#
|
89
109
|
# @return [Nil]
|
90
|
-
def nest(indent, open_obj = '', close_obj = ''
|
91
|
-
break_type = Oppen::Token::BreakType::CONSISTENT)
|
110
|
+
def nest(indent, open_obj = '', close_obj = '')
|
92
111
|
raise ArgumentError, "#{open_obj.nil? ? 'open_obj' : 'close_obj'} cannot be nil" \
|
93
112
|
if open_obj.nil? || close_obj.nil?
|
94
113
|
|
@@ -115,7 +134,16 @@ module Oppen
|
|
115
134
|
#
|
116
135
|
# @return [Nil]
|
117
136
|
def text(value, width: value.length)
|
118
|
-
|
137
|
+
if config.trim_trailing_whitespaces? && value.match(/((?:#{Regexp.escape(whitespace)})+)\z/)
|
138
|
+
match = Regexp.last_match(1)
|
139
|
+
matched_length = match.length
|
140
|
+
if value.length != matched_length
|
141
|
+
tokens << Oppen.string(value[0...-matched_length], width: width - matched_length)
|
142
|
+
end
|
143
|
+
tokens << Oppen.whitespace(match)
|
144
|
+
else
|
145
|
+
tokens << Oppen.string(value, width:)
|
146
|
+
end
|
119
147
|
end
|
120
148
|
|
121
149
|
# @param str [String]
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oppen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amine Mike El Maalouf <amine.el-maalouf@epita.fr>
|
8
|
-
- Firas al-Khalil <
|
8
|
+
- Firas al-Khalil <firas.alkhalil@faveod.com>
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-12-05 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Implementation of the Oppen's pretty printing algorithm
|
15
15
|
email:
|