oppen 0.9.0 → 0.9.1

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: 7a496d964de133aa177270080b9444d8e9ef865ce1b355bef4a6c4a43462d48c
4
- data.tar.gz: d2955b0983ef133fd374c1c46fc3424d9cff05c4ec910a6ca5ad94ec3f2db78d
3
+ metadata.gz: 81c1832fc106f4f4622738ad55ea231c66bdb40a96523d9913b3426781aed296
4
+ data.tar.gz: 9c5797979a36d529317bf31cdc85a158309c26f5a0c298f8cd1e577a83f4386a
5
5
  SHA512:
6
- metadata.gz: d4319e6b5be2d8fa394cf8d6cd593c4e8ab0b5c1c0a313cc42e287a93b46e23a95d844b8bddd01e5547ac67faa4b04395d5edb5ae911380572a0df1b7acf0c95
7
- data.tar.gz: 680e57e6f38f4cda980b57d04e787b4b33becc7b45de4c73810b243e82169411d62cd0d34b56a67df3e96debcc6d8a2ad777046aedec342429792fc91f3b3346
6
+ metadata.gz: e6a37e27b916fc83323a4b4b387c3990265094ac0c326b5770328ce8d43977b421c8cc0b2092b3c8a877d619ee56578abee1c0f5b2af9390c12f696211eb6446
7
+ data.tar.gz: 2548a7c7cd71299b8779714537916cf603f72a57bf2d02cf0ebcad163bafe7d53299e833cae07ada8a8cc30ddf2ba4e7ef19df6556656c2c920a90478c734ce4
@@ -33,15 +33,15 @@ module Oppen
33
33
  # Delimiter between lines in output
34
34
  attr_reader :new_line
35
35
 
36
- # Page margin (Called length in the original paper).
37
- attr_reader :margin
36
+ # Maximum allowed width for printing (Called length in the original paper).
37
+ attr_reader :width
38
38
 
39
39
  # Current available space (Called index in the original paper).
40
40
  #
41
41
  # @return [Integer] Current available space (Called index in the original paper).
42
42
  attr_reader :space
43
43
 
44
- def initialize(margin, new_line, config, space, out)
44
+ def initialize(width, new_line, config, space, out)
45
45
  @buffer = out
46
46
  @config = config
47
47
  @genspace =
@@ -55,8 +55,8 @@ module Oppen
55
55
  end
56
56
  @items = []
57
57
  @new_line = new_line
58
- @margin = margin
59
- @space = margin
58
+ @width = width
59
+ @space = width
60
60
  end
61
61
 
62
62
  # Returns the output of the print stack
@@ -71,32 +71,32 @@ module Oppen
71
71
  # @note Called Print in the original paper.
72
72
  #
73
73
  # @param token [Token]
74
- # @param token_length [Integer]
74
+ # @param token_width [Integer]
75
75
  #
76
76
  # @return [Nil]
77
- def print(token, token_length)
77
+ def print(token, token_width)
78
78
  case token
79
79
  in Token::Begin
80
- handle_begin token, token_length
80
+ handle_begin token, token_width
81
81
  in Token::End
82
82
  handle_end
83
83
  in Token::Break
84
- handle_break token, token_length
84
+ handle_break token, token_width
85
85
  in Token::String
86
- handle_string token, token_length
86
+ handle_string token, token_width
87
87
  end
88
88
  end
89
89
 
90
90
  # Handle Begin Token.
91
91
  #
92
92
  # @param token [Token]
93
- # @param token_length [Integer]
93
+ # @param token_width [Integer]
94
94
  #
95
95
  # @return [Nil]
96
96
  #
97
97
  # @see Token::Begin
98
- def handle_begin(token, token_length)
99
- if token_length > space
98
+ def handle_begin(token, token_width)
99
+ if token_width > space
100
100
  type =
101
101
  if token.break_type == Token::BreakType::CONSISTENT
102
102
  Token::BreakType::CONSISTENT
@@ -129,16 +129,16 @@ module Oppen
129
129
  # Handle Break Token.
130
130
  #
131
131
  # @param token [Token]
132
- # @param token_length [Integer]
132
+ # @param token_width [Integer]
133
133
  #
134
134
  # @return [Nil]
135
135
  #
136
136
  # @see Token::Break
137
- def handle_break(token, token_length)
137
+ def handle_break(token, token_width)
138
138
  block = top
139
139
  case block.break_type
140
140
  in Token::BreakType::FITS
141
- @space -= token.length
141
+ @space -= token.width
142
142
  write token
143
143
  in Token::BreakType::CONSISTENT
144
144
  @space = block.offset - token.offset
@@ -146,23 +146,23 @@ module Oppen
146
146
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
147
147
  token.offset
148
148
  else
149
- margin - space
149
+ width - space
150
150
  end
151
151
  write token.line_continuation
152
152
  print_new_line indent
153
153
  in Token::BreakType::INCONSISTENT
154
- if token_length > space
154
+ if token_width > space
155
155
  @space = block.offset - token.offset
156
156
  indent =
157
157
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
158
158
  token.offset
159
159
  else
160
- margin - space
160
+ width - space
161
161
  end
162
162
  write token.line_continuation
163
163
  print_new_line indent
164
164
  else
165
- @space -= token.length
165
+ @space -= token.width
166
166
  write token
167
167
  end
168
168
  end
@@ -171,13 +171,13 @@ module Oppen
171
171
  # Handle String Token.
172
172
  #
173
173
  # @param token [Token]
174
- # @param token_length [Integer]
174
+ # @param token_width [Integer]
175
175
  #
176
176
  # @return [Nil]
177
177
  #
178
178
  # @see Token::String
179
- def handle_string(token, token_length)
180
- @space = [0, space - token_length].max
179
+ def handle_string(token, token_width)
180
+ @space = [0, space - token_width].max
181
181
  write token
182
182
  end
183
183
 
@@ -222,8 +222,8 @@ module Oppen
222
222
  def print_new_line(amount)
223
223
  write new_line
224
224
  if config&.indent_anchor == Config::IndentAnchor::ON_BEGIN
225
- @space = margin - top.offset - amount
226
- indent margin - space
225
+ @space = width - top.offset - amount
226
+ indent width - space
227
227
  else
228
228
  indent amount
229
229
  end
data/lib/oppen/printer.rb CHANGED
@@ -4,6 +4,7 @@ require 'stringio'
4
4
 
5
5
  require_relative 'scan_stack'
6
6
  require_relative 'print_stack'
7
+ require_relative 'utils'
7
8
 
8
9
  # Oppen.
9
10
  module Oppen
@@ -48,9 +49,18 @@ module Oppen
48
49
  # @note Called token in the original paper.
49
50
  attr_reader :tokens
50
51
 
51
- # @note Called PrettyPrintInit in the original paper.
52
+ # Some description
52
53
  #
53
- # @param margin [Integer] maximum line width desired.
54
+ # @example
55
+ # "This is a string" # => and this is a comment
56
+ # out = Oppen::Wadler.new (margin: 13) # Hawn
57
+ # # Baliz
58
+ #
59
+ # @example
60
+ # "This is a string" # => and this is a comment
61
+ # # var = 12
62
+ #
63
+ # @param width [Integer] maximum line width desired.
54
64
  # @param new_line [String] the delimiter between lines.
55
65
  # @param config [Config]
56
66
  # @param space [String, Proc] could be a String or a callable.
@@ -60,18 +70,18 @@ module Oppen
60
70
  # If it's a callable, it will receive `n` and it needs to return
61
71
  # a string.
62
72
  # @param out [Object] should have a write and string method
63
- def initialize(margin, new_line, config = Config.oppen,
73
+ def initialize(width, new_line, config = Config.oppen,
64
74
  space = ' ', out = StringIO.new)
65
75
  # Maximum size if the stacks
66
- n = 3 * margin
76
+ n = 3 * width
67
77
 
68
78
  @config = config
69
79
  @left = 0
70
80
  @left_total = 1
71
- @print_stack = PrintStack.new margin, new_line, config, space, out
81
+ @print_stack = PrintStack.new width, new_line, config, space, out
72
82
  @right = 0
73
83
  @right_total = 1
74
- @scan_stack = ScanStack.new n
84
+ @scan_stack = ScanStack.new n, config
75
85
  @size = Array.new n
76
86
  @tokens = Array.new n
77
87
  end
@@ -148,7 +158,7 @@ module Oppen
148
158
  tokens[right] = token
149
159
  size[right] = -1
150
160
  scan_stack.push right
151
- if config&.eager_print &&
161
+ if config&.eager_print? &&
152
162
  (!scan_stack.empty? && right_total - left_total < print_stack.space)
153
163
  check_stack 0
154
164
  advance_left tokens[left], size[left]
@@ -174,7 +184,7 @@ module Oppen
174
184
  scan_stack.push right
175
185
  tokens[right] = token
176
186
  size[right] = -right_total
177
- @right_total += token.length
187
+ @right_total += token.width
178
188
  end
179
189
 
180
190
  # Handle String Token.
@@ -184,12 +194,12 @@ module Oppen
184
194
  # @see Token::String
185
195
  def handle_string(token)
186
196
  if scan_stack.empty?
187
- print_stack.print token, token.length
197
+ print_stack.print token, token.width
188
198
  else
189
199
  advance_right
190
200
  tokens[right] = token
191
- size[right] = token.length
192
- @right_total += token.length
201
+ size[right] = token.width
202
+ @right_total += token.width
193
203
  check_stream
194
204
  end
195
205
  end
@@ -220,7 +230,10 @@ module Oppen
220
230
  @right = (right + 1) % scan_stack.length
221
231
  return if right != left
222
232
 
223
- raise 'Token queue full'
233
+ raise 'Token queue full' if !config.upsize_stack?
234
+
235
+ @size, = Utils.upsize_circular_array(@size, @left)
236
+ @tokens, @left, @right = Utils.upsize_circular_array(@tokens, @left)
224
237
  end
225
238
 
226
239
  # Advances the `left` pointer and lets the print stack
@@ -229,16 +242,16 @@ module Oppen
229
242
  # @note Called AdvanceLeft as well in the original paper.
230
243
  #
231
244
  # @return [Nil]
232
- def advance_left(token, token_length)
233
- return if token_length.negative?
245
+ def advance_left(token, token_width)
246
+ return if token_width.negative?
234
247
 
235
- print_stack.print token, token_length
248
+ print_stack.print token, token_width
236
249
 
237
250
  case token
238
251
  when Token::Break
239
- @left_total += token.length
252
+ @left_total += token.width
240
253
  when Token::String
241
- @left_total += token_length
254
+ @left_total += token_width
242
255
  end
243
256
 
244
257
  return if left == right
@@ -1,11 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'utils'
4
+
3
5
  # Oppen.
4
6
  module Oppen
5
7
  # A fixed-size stack that can be popped from top and bottom.
6
8
  class ScanStack
7
- def initialize(size)
9
+ def initialize(size, config)
8
10
  @bottom = 0
11
+ @config = config
9
12
  @empty = true
10
13
  @stack = Array.new(size)
11
14
  @top = 0
@@ -68,7 +71,9 @@ module Oppen
68
71
  else
69
72
  @top = increment(@top)
70
73
  if @top == @bottom
71
- raise 'Stack full'
74
+ raise 'Stack full' if !@config.upsize_stack?
75
+
76
+ @stack, @bottom, @top = Utils.upsize_circular_array(@stack, @bottom)
72
77
  end
73
78
  end
74
79
  @stack[@top] = value
data/lib/oppen/token.rb CHANGED
@@ -18,60 +18,50 @@ module Oppen
18
18
  CONSISTENT = 2
19
19
  end
20
20
 
21
- # Default token length
21
+ # Default token width
22
22
  # @return [Integer]
23
- def length
24
- 0
25
- end
23
+ def width = 0
26
24
 
27
25
  # String Token.
28
26
  class String < Token
29
27
  # @return [String] String value.
30
28
  attr_reader :value
29
+ # @return [Integer]
30
+ attr_reader :width
31
31
 
32
- def initialize(value)
32
+ def initialize(value, width: value.length)
33
33
  @value = value
34
+ @width = width
34
35
  super()
35
36
  end
36
37
 
37
- # @return [Integer]
38
- def length
39
- value.length
40
- end
41
-
42
38
  # @return [String]
43
- def to_s
44
- value
45
- end
39
+ def to_s = value
46
40
  end
47
41
 
48
42
  # Break Token.
49
43
  class Break < Token
50
- # @return [String] Break strings.
51
- attr_reader :str
52
44
  # @return [String] If a new line is needed display this string before the new line
53
45
  attr_reader :line_continuation
54
46
  # @return [Integer] Indentation.
55
47
  attr_reader :offset
48
+ # @return [String] Break strings.
49
+ attr_reader :str
50
+ # @return [Integer]
51
+ attr_reader :width
56
52
 
57
- def initialize(str = ' ', line_continuation: '', offset: 0)
53
+ def initialize(str = ' ', width: str.length, line_continuation: '', offset: 0)
58
54
  raise ArgumentError, 'line_continuation cannot be nil' if line_continuation.nil?
59
55
 
60
56
  @line_continuation = line_continuation
61
57
  @offset = offset
62
58
  @str = str
59
+ @width = width
63
60
  super()
64
61
  end
65
62
 
66
- # @return [Integer]
67
- def length
68
- str.length
69
- end
70
-
71
63
  # @return [String]
72
- def to_s
73
- str
74
- end
64
+ def to_s = str
75
65
  end
76
66
 
77
67
  # Distinguished instance of Break which forces a line break.
@@ -79,9 +69,7 @@ module Oppen
79
69
  # Mock string that represents an infinite string to force new line.
80
70
  class LineBreakString
81
71
  # @return [Integer]
82
- def length
83
- 999_999
84
- end
72
+ def length = 999_999
85
73
  end
86
74
 
87
75
  def initialize(line_continuation: '', offset: 0)
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Oppen.
4
+ module Oppen
5
+ # Utils.
6
+ module Utils
7
+ # Rotates circular array and triples its size.
8
+ # @param arr [Array]
9
+ # @param offset [Integer] Rotation amount
10
+ #
11
+ # @return [Array(Array, Integer, Integer)] upsized array, lhs, rhs
12
+ def self.upsize_circular_array(arr, offset)
13
+ size = arr.size
14
+ arr = arr.rotate(offset)
15
+ arr.fill(nil, size, 2 * size)
16
+ [arr, 0, size]
17
+ end
18
+ end
19
+ end
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.0' # managed by release.sh
8
+ VERSION = '0.9.1' # managed by release.sh
9
9
  end
data/lib/oppen.rb CHANGED
@@ -18,15 +18,15 @@ module Oppen
18
18
  # to indent.
19
19
  # If it's a callable, it will receive `n` and it needs to return
20
20
  # a string.
21
- # @param margin [Integer] maximum line width desired
22
21
  # @param new_line [String] the delimiter between lines
23
22
  # @param out [Object] should have a write and string method
24
23
  # @param tokens [Array[Token]] the list of tokens to be printed
24
+ # @param width [Integer] maximum line width desired
25
25
  #
26
26
  # @return [String] output of the pretty printer
27
27
  def self.print(config: Config.oppen, space: ' ',
28
- margin: 80, new_line: "\n", out: StringIO.new, tokens: [])
29
- printer = Printer.new margin, new_line, config, space, out
28
+ new_line: "\n", out: StringIO.new, tokens: [], width: 80)
29
+ printer = Printer.new width, new_line, config, space, out
30
30
  tokens.each do |token|
31
31
  printer.print token
32
32
  end
@@ -47,10 +47,17 @@ module Oppen
47
47
  end
48
48
 
49
49
  attr_accessor :indent_anchor
50
+
51
+ def initialize(indent_anchor: IndentAnchor::ON_BREAK, eager_print: false, upsize_stack: false)
52
+ @indent_anchor = indent_anchor
53
+ @eager_print = eager_print
54
+ @upsize_stack = upsize_stack
55
+ end
56
+
50
57
  # Print groups eagerly
51
58
  #
52
59
  # @example
53
- # out = Oppen::Wadler.new (margin: 13)
60
+ # out = Oppen::Wadler.new (width: 13)
54
61
  # out.group {
55
62
  # out.group {
56
63
  # out.text 'abc'
@@ -76,12 +83,9 @@ module Oppen
76
83
  # # jkl
77
84
  #
78
85
  # @return [Boolean]
79
- attr_accessor :eager_print
86
+ def eager_print? = @eager_print
80
87
 
81
- def initialize(indent_anchor: IndentAnchor::ON_BREAK, eager_print: false)
82
- @indent_anchor = indent_anchor
83
- @eager_print = eager_print
84
- end
88
+ def upsize_stack? = @upsize_stack
85
89
 
86
90
  # Default config for Oppen usage
87
91
  # @return [Config]
@@ -91,25 +95,27 @@ module Oppen
91
95
 
92
96
  # Default config for Wadler usage
93
97
  # @return [Config]
94
- def self.wadler(eager_print: true)
95
- new(indent_anchor: IndentAnchor::ON_BEGIN, eager_print:)
98
+ def self.wadler(eager_print: true, upsize_stack: true)
99
+ new(indent_anchor: IndentAnchor::ON_BEGIN, eager_print:, upsize_stack:)
96
100
  end
97
101
  end
98
102
 
99
103
  # @param value [String]
104
+ # @param width [Integer] token width that defaults to value.length
100
105
  #
101
106
  # @return [Oppen::Token::String] a new String token
102
- def self.string(value)
103
- Token::String.new(value)
107
+ def self.string(value, width: value.length)
108
+ Token::String.new(value, width:)
104
109
  end
105
110
 
106
111
  # @param str [String]
107
112
  # @param line_continuation [String] If a new line is needed display this string before the new line
108
113
  # @param offset [Integer]
114
+ # @param width [Integer] token width that defaults to str.length
109
115
  #
110
116
  # @return [Oppen::Token::Break] a new Break token
111
- def self.break(str = ' ', line_continuation: '', offset: 0)
112
- Token::Break.new(str, line_continuation:, offset:)
117
+ def self.break(str = ' ', line_continuation: '', offset: 0, width: str.length)
118
+ Token::Break.new(str, width:, line_continuation:, offset:)
113
119
  end
114
120
 
115
121
  # @param line_continuation [String] If a new line is needed display this string before the new line
data/lib/wadler/print.rb CHANGED
@@ -7,10 +7,10 @@ module Oppen
7
7
  attr_reader :config
8
8
  attr_reader :current_indent
9
9
  attr_reader :space
10
- attr_reader :margin
11
10
  attr_reader :new_line
12
11
  attr_reader :out
13
12
  attr_reader :tokens
13
+ attr_reader :width
14
14
 
15
15
  # @param config [Oppen::Config]
16
16
  # @param space [String, Proc] could be a String or a callable.
@@ -19,15 +19,15 @@ module Oppen
19
19
  # to indent.
20
20
  # If it's a callable, it will receive `n` and it needs to return
21
21
  # a string.
22
- # @param margin [Integer]
23
22
  # @param new_line [String]
24
23
  # @param out [Object] should have a write and string method
24
+ # @param width [Integer]
25
25
  def initialize(config: Config.wadler, space: ' ',
26
- margin: 80, new_line: "\n", out: StringIO.new)
26
+ new_line: "\n", out: StringIO.new, width: 80)
27
27
  @config = config
28
28
  @current_indent = 0
29
29
  @space = space
30
- @margin = margin
30
+ @width = width
31
31
  @new_line = new_line
32
32
  @out = out
33
33
  @tokens = []
@@ -38,7 +38,7 @@ module Oppen
38
38
  if !tokens.last.is_a? Oppen::Token::EOF
39
39
  tokens << Oppen.eof
40
40
  end
41
- Oppen.print(tokens:, margin:, new_line:, config:, space:, out:)
41
+ Oppen.print(tokens:, new_line:, config:, space:, out:, width:)
42
42
  end
43
43
 
44
44
  # @param indent [Integer] group indentation
@@ -110,16 +110,16 @@ module Oppen
110
110
  # @param value [String]
111
111
  #
112
112
  # @return [Nil]
113
- def text(value)
114
- tokens << Oppen.string(value)
113
+ def text(value, width: value.length)
114
+ tokens << Oppen.string(value, width:)
115
115
  end
116
116
 
117
117
  # @param str [String]
118
118
  # @param line_continuation [String] If a new line is needed display this string before the new line
119
119
  #
120
120
  # @return [Nil]
121
- def breakable(str = ' ', line_continuation: '')
122
- tokens << Oppen.break(str, line_continuation:, offset: current_indent)
121
+ def breakable(str = ' ', width: str.length, line_continuation: '')
122
+ tokens << Oppen.break(str, width:, line_continuation:, offset: current_indent)
123
123
  end
124
124
 
125
125
  # @param line_continuation [String] If a new line is needed display this string before the new line
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oppen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amine Mike El Maalouf <amine.el-maalouf@epita.fr>
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-09-27 00:00:00.000000000 Z
12
+ date: 2024-10-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Implementation of the Oppen's pretty printing algorithm
15
15
  email:
@@ -24,6 +24,7 @@ files:
24
24
  - lib/oppen/printer.rb
25
25
  - lib/oppen/scan_stack.rb
26
26
  - lib/oppen/token.rb
27
+ - lib/oppen/utils.rb
27
28
  - lib/oppen/version.rb
28
29
  - lib/wadler/print.rb
29
30
  homepage: http://github.com/Faveod/oppen-ruby