oppen 0.9.6 → 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 +21 -4
- 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
@@ -64,6 +64,7 @@ module Oppen
|
|
64
64
|
#
|
65
65
|
# @return [String]
|
66
66
|
def output
|
67
|
+
buffer.truncate(buffer.pos)
|
67
68
|
buffer.string
|
68
69
|
end
|
69
70
|
|
@@ -73,16 +74,17 @@ module Oppen
|
|
73
74
|
#
|
74
75
|
# @param token [Token]
|
75
76
|
# @param token_width [Integer]
|
77
|
+
# @param trim_on_break [Integer] Number of trailing whitespace characters to trim.
|
76
78
|
#
|
77
79
|
# @return [Nil]
|
78
|
-
def print(token, token_width)
|
80
|
+
def print(token, token_width, trim_on_break: 0)
|
79
81
|
case token
|
80
82
|
in Token::Begin
|
81
83
|
handle_begin token, token_width
|
82
84
|
in Token::End
|
83
85
|
handle_end
|
84
86
|
in Token::Break
|
85
|
-
handle_break token, token_width
|
87
|
+
handle_break token, token_width, trim_on_break:
|
86
88
|
in Token::String
|
87
89
|
handle_string token, token_width
|
88
90
|
end
|
@@ -131,11 +133,12 @@ module Oppen
|
|
131
133
|
#
|
132
134
|
# @param token [Token]
|
133
135
|
# @param token_width [Integer]
|
136
|
+
# @param trim_on_break [Integer] Number of trailing whitespace characters to trim.
|
134
137
|
#
|
135
138
|
# @return [Nil]
|
136
139
|
#
|
137
140
|
# @see Token::Break
|
138
|
-
def handle_break(token, token_width)
|
141
|
+
def handle_break(token, token_width, trim_on_break: 0)
|
139
142
|
block = top
|
140
143
|
case block.break_type
|
141
144
|
in Token::BreakType::FITS
|
@@ -149,6 +152,7 @@ module Oppen
|
|
149
152
|
else
|
150
153
|
width - space
|
151
154
|
end
|
155
|
+
erase(trim_on_break)
|
152
156
|
write token.line_continuation
|
153
157
|
print_new_line indent
|
154
158
|
in Token::BreakType::INCONSISTENT
|
@@ -160,6 +164,7 @@ module Oppen
|
|
160
164
|
else
|
161
165
|
width - space
|
162
166
|
end
|
167
|
+
erase(trim_on_break)
|
163
168
|
write token.line_continuation
|
164
169
|
print_new_line indent
|
165
170
|
else
|
@@ -245,6 +250,18 @@ module Oppen
|
|
245
250
|
buffer.write(obj.to_s)
|
246
251
|
end
|
247
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
|
+
|
248
265
|
# Add indentation by `amount`.
|
249
266
|
#
|
250
267
|
# @note Called Indent as well in the original paper.
|
@@ -255,7 +272,7 @@ module Oppen
|
|
255
272
|
def indent(amount)
|
256
273
|
raise ArgumentError 'Indenting using negative amount' if amount.negative?
|
257
274
|
|
258
|
-
write genspace.
|
275
|
+
write genspace.(amount) if amount.positive?
|
259
276
|
end
|
260
277
|
end
|
261
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:
|