oppen 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b656616fe07cf5b29b8dfa43f0b72ed6dbf80c56a9ca6790745a8db27f058ed7
4
- data.tar.gz: 3d46ddc3a703d029ac22460ac504cf2928f95d804d32e0266f0de7ffbbfd3359
3
+ metadata.gz: '008545ae6d86a7415e434ef51a19872fbf5b768db232d70bbac025667e002604'
4
+ data.tar.gz: a989a6e8d422c363e7ebca36fc10dac4ad030f145afc2b4bc152c9cff5bdfe49
5
5
  SHA512:
6
- metadata.gz: 7b69f0365a507dc9fca546cbfea064593a48d0d85140cd894ed2ff256e13c4c0e772bf9e0d2b29f9eefd9121c8b3adf03da93137c15b3c9570f6a7e49ed435b2
7
- data.tar.gz: aa608fa2238dc8eea6bf3ce5d03f10e6f8059eda98c02d1e53fa06f9ac9301b03b42e54b38ed4f945c28766c4959b441cc190b76f0f176a72c7f52967096258a
6
+ metadata.gz: 9a3e32d3a05c638bd26a9e170d737186c9635eeb3c54844869b108c8252fdafa942a05a76a1e3d3d25d5e93a47d076c280f7346c1c313b5c7159a8f3d1166ef6
7
+ data.tar.gz: 1f3c076ea8b298f5a772d9c209c4bc64087f6093576e41e2ffb6289b5d0aba08c1b3ed9d3022ebb14b7d7fe4c083804e60219735bce5c00f96785e9dede2bb69
data/README.md CHANGED
@@ -31,8 +31,7 @@ monkeypatching.
31
31
 
32
32
  ## Usage
33
33
 
34
- > [!WARNING]
35
- > Lands when the APIs are stable.
34
+ A few examples of the API usage can be found in [examples/](examples/README.md).
36
35
 
37
36
  ## Oppen vs Wadler
38
37
 
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
- # @param arr [Array]
10
- # @param offset [Integer] Rotation amount
8
+ # @!visibility private
9
+ # @note This method is not for public use.
11
10
  #
12
- # @return [Array<Array, Integer, Integer>] upsized array, lhs, rhs
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(offset)
16
- arr.fill(nil, size, 2 * size)
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
- nb_spaces = base_indent
29
- out = StringIO.new
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
- write = ->(txt) {
32
- out << (' ' * nb_spaces) << txt << "\n"
33
- }
34
- display_break_token = ->(token) {
31
+ handle_break_token = ->(token) {
35
32
  if token.offset.positive?
36
- write.("#{printer_name}.nest(#{token.offset}, \"\", \"\") {")
37
- nb_spaces += 2
33
+ printer.text "#{printer_name}.nest(#{token.offset}, '', '') {"
34
+ printer.nest_open indent
35
+ printer.break
38
36
  end
39
37
 
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
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
- nb_spaces -= 2
50
- write.('}')
49
+ printer.nest_close indent
50
+ printer.break
51
+ printer.text '}'
51
52
  end
52
53
  }
53
54
 
54
- tokens.each do |token|
55
+ tokens.each_with_index do |token, idx|
55
56
  case token
56
57
  in Token::String
57
- write.("#{printer_name}.text(#{token.value.inspect}, width: #{token.width})")
58
+ printer.text "#{printer_name}.text(#{token.value.inspect}, width: #{token.width})"
58
59
  in Token::Break
59
- display_break_token.(token)
60
+ handle_break_token.(token)
60
61
  in Token::Begin
61
- write.("#{printer_name}.group(#{token.offset}, \"\", \"\", #{token.break_type_name}) {")
62
- nb_spaces += 2
62
+ printer.text "#{printer_name}.group(#{token.offset}, '', '', #{token.break_type.inspect}) {"
63
+ printer.nest_open indent
63
64
  in Token::End
64
- nb_spaces -= 2
65
- write.('}')
65
+ printer.nest_close indent
66
+ printer.break
67
+ printer.text '}'
66
68
  in Token::EOF
67
- write.('') # new line
69
+ nil
68
70
  end
71
+ printer.break if !tokens[idx + 1].is_a?(Token::End)
69
72
  end
70
- out.string
73
+ printer.output
71
74
  end
72
75
  end
73
76
  end
@@ -2,15 +2,16 @@
2
2
 
3
3
  # Oppen.
4
4
  module Oppen
5
- # Class that represents a stack that builds an output string
6
- # using the values of the tokens that were pushed into it.
5
+ # A stack of {Token}s.
7
6
  class PrintStack
8
- # Class that represents an item in the print stack.
7
+ # An item in the print stack.
9
8
  class PrintStackEntry
10
- # @return [Integer] Indentation level.
11
- attr_reader :offset
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 element that builds the output.
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?(:call)
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
- # Returns the output of the print stack
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(buffer.pos)
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 string.
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 [Token]
76
- # @param token_width [Integer]
77
- # @param trim_on_break [Integer] Number of trailing whitespace characters to trim.
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 Token.
90
+ # Handle {Token::Begin}.
94
91
  #
95
- # @param token [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 == Token::BreakType::CONSISTENT
105
- Token::BreakType::CONSISTENT
99
+ if token.break_type == :consistent
100
+ :consistent
106
101
  else
107
- Token::BreakType::INCONSISTENT
102
+ :inconsistent
108
103
  end
109
- if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
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, Token::BreakType::FITS
114
+ push PrintStackEntry.new 0, :fits
120
115
  end
121
116
  end
122
117
 
123
- # Handle End Token.
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 Token.
125
+ # Handle {Token::Break}.
133
126
  #
134
- # @param token [Token]
135
- # @param token_width [Integer]
136
- # @param trim_on_break [Integer] Number of trailing whitespace characters to trim.
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 Token::BreakType::FITS
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 Token::BreakType::CONSISTENT
141
+ in :consistent
148
142
  @space = block.offset - token.offset
149
143
  indent =
150
- if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
144
+ if config&.indent_anchor == :current_offset
151
145
  token.offset
152
146
  else
153
147
  width - space
154
148
  end
155
- erase(trim_on_break)
149
+ erase trim_on_break
156
150
  write token.line_continuation
157
151
  print_new_line indent
158
- in Token::BreakType::INCONSISTENT
152
+ in :inconsistent
159
153
  if token_width > space
160
154
  @space = block.offset - token.offset
161
155
  indent =
162
- if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
156
+ if config&.indent_anchor == :current_offset
163
157
  token.offset
164
158
  else
165
159
  width - space
166
160
  end
167
- erase(trim_on_break)
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 Token.
171
+ # Handle {Token::String}.
178
172
  #
179
- # @param token [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(print_stack_entry)
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] indentation amount.
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 == Config::IndentAnchor::ON_BEGIN
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(obj.to_s)
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
  #