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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 209072194fbb082bd25f2583b7f930e38c79ca042c21e711e18dd7295ee00e86
4
- data.tar.gz: 6eeb620d7d3bd6599477a46a2a5b9df86db2bc8c6a0f07a619d065245393127f
3
+ metadata.gz: b656616fe07cf5b29b8dfa43f0b72ed6dbf80c56a9ca6790745a8db27f058ed7
4
+ data.tar.gz: 3d46ddc3a703d029ac22460ac504cf2928f95d804d32e0266f0de7ffbbfd3359
5
5
  SHA512:
6
- metadata.gz: a2f8d7bd7b199b7ef0d5a97feebbe456fea9e557f6535760ad84b21a304d73c52ea954f392e7c07e0b682844fe86c0c8ccc4ef6786057785cba9f02f58c31c14
7
- data.tar.gz: 31a73892d3afff56d85c60a6756d6fedbd2bce259d7ca259b662a7f7002549fcb53146f2fb1a32136ae2c8cca03b20ded90d95a814363d18d0d80192db79c39b
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 = 4)
27
+ def tokens_to_wadler(tokens, base_indent: 0, printer_name: 'out')
28
+ nb_spaces = base_indent
27
29
  out = StringIO.new
28
- write = ->(txt, nb_spaces) {
29
- out.write("#{' ' * nb_spaces}#{txt}\n")
30
+
31
+ write = ->(txt) {
32
+ out << (' ' * nb_spaces) << txt << "\n"
30
33
  }
31
- nb_spaces = base_indent
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.call("out.text '#{token}'", nb_spaces)
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
- write.call('out.breakable', nb_spaces)
59
+ display_break_token.(token)
40
60
  in Token::Begin
41
- write.call('out.group {', nb_spaces)
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.call('}', nb_spaces)
65
+ write.('}')
46
66
  in Token::EOF
47
- write.call('', nb_spaces) # new line
67
+ write.('') # new line
48
68
  end
49
69
  end
50
70
  out.string
@@ -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.call(amount) if amount.positive?
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
- print_stack.print token, token_width
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) % scan_stack.length
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
@@ -5,5 +5,5 @@ module Oppen
5
5
  # Oppen version
6
6
  #
7
7
  # @return [String] current version
8
- VERSION = '0.9.6' # managed by release.sh
8
+ VERSION = '0.9.7' # managed by release.sh
9
9
  end
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, upsize_stack: 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, width: 80)
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
- # @return [String]
37
- def output
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? Oppen::Token::EOF
43
- tokens << Oppen.eof
44
- end
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
- tokens << Oppen.string(value, width:)
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.6
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 <firasalkhalil@gmail.com>
8
+ - Firas al-Khalil <firas.alkhalil@faveod.com>
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-11-25 00:00:00.000000000 Z
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: