prettier_print 0.1.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -2
- data/Gemfile.lock +3 -2
- data/README.md +1 -5
- data/lib/prettier_print/version.rb +1 -1
- data/lib/prettier_print.rb +208 -229
- 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: 5392f4dae350d56612ec1850aa3ca28bb51e5776690e213d31cf1671db789fac
|
4
|
+
data.tar.gz: 72494c92f76eafe77b4afd04e2c8da7d45a209dd4d1c9b2d5aaf5820b3153050
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9db5ca110447b075995e72c89cdaa0d881d9e7cef6786820ff1bec18b1cc1fc05c035717b7a8641a67a0586c8612a5a3a11933d9f95f5248f5fb95bb378b547d
|
7
|
+
data.tar.gz: de1c9038d6c84db2d9e2f8bf047b446abe3b4561cbf6700c8c925244adb46dffdcb2c2b19dfa23e800ba44cc09f77aa64d00f6848449e22a31b6617a375d8e8e
|
data/CHANGELOG.md
CHANGED
@@ -6,11 +6,38 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.0.1] - 2022-10-18
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
* `breakable_return` - should also break parent
|
14
|
+
|
15
|
+
## [1.0.0] - 2022-10-17
|
16
|
+
|
17
|
+
### Added
|
18
|
+
|
19
|
+
* `breakable_space` - a shortcut for `breakable`
|
20
|
+
* `breakable_empty` - a shortcut for `breakable("")`
|
21
|
+
* `breakable_force` - a shortcut for `breakable("", force: true)`
|
22
|
+
* `breakable_return` - a shortcut for `breakable(" ", indent: false, force: true)`
|
23
|
+
* Strings can now be added directly to the output buffer, which means they don't have to be placed into the `Text` node. This cuts down on quite a bit of allocations.
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
|
27
|
+
* `trim` now strips its whitespace using `rstrip!` instead of a custom `gsub!`. This means that other forms of whitespace beyond tabs and spaces are included. This shouldn't really impact anyone unless they're using vertical tab or something in combination with `trim` and wanted them to stay in.
|
28
|
+
|
29
|
+
### Removed
|
30
|
+
|
31
|
+
* There is no longer a `PrettierPrint::DefaultBuffer` class. Since there were only ever two implementations, those implementations now no longer share a parent.
|
32
|
+
* `PrettierPrint::IndentLevel` is now entirely gone. This was mostly an implementation detail, and no one should have been relying on it anyway. However, it means that the ability to use nest with a string literal is now gone as well. It can be created again by using seplist though, so the functionality just isn't there in the shortcut version. This means we're able to keep track of indentation as a single integer again, which drastically simplifies the code.
|
33
|
+
|
9
34
|
## [0.1.0] - 2022-05-13
|
10
35
|
|
11
36
|
### Added
|
12
37
|
|
13
38
|
- 🎉 Initial release! 🎉
|
14
39
|
|
15
|
-
[unreleased]: https://github.com/ruby-syntax-tree/prettier_print/compare/
|
16
|
-
[0.1
|
40
|
+
[unreleased]: https://github.com/ruby-syntax-tree/prettier_print/compare/v1.0.1...HEAD
|
41
|
+
[1.0.1]: https://github.com/ruby-syntax-tree/prettier_print/compare/v1.0.0...v1.0.1
|
42
|
+
[1.0.0]: https://github.com/ruby-syntax-tree/prettier_print/compare/v0.1.0...v1.0.0
|
43
|
+
[0.1.0]: https://github.com/ruby-syntax-tree/prettier_print/compare/df51ce...v0.1.0
|
data/Gemfile.lock
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
prettier_print (0.1
|
4
|
+
prettier_print (1.0.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
power_assert (2.0.1)
|
10
10
|
rake (13.0.6)
|
11
|
-
test-unit (3.5.
|
11
|
+
test-unit (3.5.5)
|
12
12
|
power_assert
|
13
13
|
|
14
14
|
PLATFORMS
|
15
|
+
arm64-darwin-21
|
15
16
|
x86_64-darwin-21
|
16
17
|
x86_64-linux
|
17
18
|
|
data/README.md
CHANGED
@@ -137,11 +137,7 @@ This node increases the indentation by a fixed number of spaces or a string. It
|
|
137
137
|
q.nest(2) {}
|
138
138
|
```
|
139
139
|
|
140
|
-
It accepts a block that specifies the contents of the alignment node. The value that you're indenting by can be positive or negative.
|
141
|
-
|
142
|
-
```ruby
|
143
|
-
q.nest("-->") {}
|
144
|
-
```
|
140
|
+
It accepts a block that specifies the contents of the alignment node. The value that you're indenting by can be positive or negative.
|
145
141
|
|
146
142
|
#### `BreakParent`
|
147
143
|
|
data/lib/prettier_print.rb
CHANGED
@@ -120,6 +120,13 @@ class PrettierPrint
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
+
# Below here are the most common combination of options that are created when
|
124
|
+
# creating new breakables. They are here to cut down on some allocations.
|
125
|
+
BREAKABLE_SPACE = Breakable.new(" ", 1, indent: true, force: false)
|
126
|
+
BREAKABLE_EMPTY = Breakable.new("", 0, indent: true, force: false)
|
127
|
+
BREAKABLE_FORCE = Breakable.new(" ", 1, indent: true, force: true)
|
128
|
+
BREAKABLE_RETURN = Breakable.new(" ", 1, indent: false, force: true)
|
129
|
+
|
123
130
|
# A node in the print tree that forces the surrounding group to print out in
|
124
131
|
# the "break" mode as opposed to the "flat" mode. Useful for when you need to
|
125
132
|
# force a newline into a group.
|
@@ -129,6 +136,10 @@ class PrettierPrint
|
|
129
136
|
end
|
130
137
|
end
|
131
138
|
|
139
|
+
# Since there's really no difference in these instances, just using the same
|
140
|
+
# one saves on some allocations.
|
141
|
+
BREAK_PARENT = BreakParent.new
|
142
|
+
|
132
143
|
# A node in the print tree that represents a group of items which the printer
|
133
144
|
# should try to fit onto one line. This is the basic command to tell the
|
134
145
|
# printer when to break. Groups are usually nested, and the printer will try
|
@@ -254,19 +265,23 @@ class PrettierPrint
|
|
254
265
|
end
|
255
266
|
end
|
256
267
|
|
268
|
+
# Since all of the instances here are the same, we can reuse the same one to
|
269
|
+
# cut down on allocations.
|
270
|
+
TRIM = Trim.new
|
271
|
+
|
257
272
|
# When building up the contents in the output buffer, it's convenient to be
|
258
273
|
# able to trim trailing whitespace before newlines. If the output object is a
|
259
274
|
# string or array or strings, then we can do this with some gsub calls. If
|
260
275
|
# not, then this effectively just wraps the output object and forwards on
|
261
276
|
# calls to <<.
|
262
277
|
module Buffer
|
263
|
-
# This is
|
264
|
-
# trim! that
|
265
|
-
#
|
266
|
-
class
|
278
|
+
# This is an output buffer that wraps a string output object. It provides a
|
279
|
+
# trim! method that trims off trailing whitespace from the string using
|
280
|
+
# gsub!.
|
281
|
+
class StringBuffer
|
267
282
|
attr_reader :output
|
268
283
|
|
269
|
-
def initialize(output =
|
284
|
+
def initialize(output = "".dup)
|
270
285
|
@output = output
|
271
286
|
end
|
272
287
|
|
@@ -274,22 +289,9 @@ class PrettierPrint
|
|
274
289
|
@output << object
|
275
290
|
end
|
276
291
|
|
277
|
-
def trim!
|
278
|
-
0
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
# This is an output buffer that wraps a string output object. It provides a
|
283
|
-
# trim! method that trims off trailing whitespace from the string using
|
284
|
-
# gsub!.
|
285
|
-
class StringBuffer < DefaultBuffer
|
286
|
-
def initialize(output = "".dup)
|
287
|
-
super(output)
|
288
|
-
end
|
289
|
-
|
290
292
|
def trim!
|
291
293
|
length = output.length
|
292
|
-
output.
|
294
|
+
output.rstrip!
|
293
295
|
length - output.length
|
294
296
|
end
|
295
297
|
end
|
@@ -298,9 +300,15 @@ class PrettierPrint
|
|
298
300
|
# trim! method that trims off trailing whitespace from the last element in
|
299
301
|
# the array if it's an unfrozen string using the same method as the
|
300
302
|
# StringBuffer.
|
301
|
-
class ArrayBuffer
|
303
|
+
class ArrayBuffer
|
304
|
+
attr_reader :output
|
305
|
+
|
302
306
|
def initialize(output = [])
|
303
|
-
|
307
|
+
@output = output
|
308
|
+
end
|
309
|
+
|
310
|
+
def <<(object)
|
311
|
+
@output << object
|
304
312
|
end
|
305
313
|
|
306
314
|
def trim!
|
@@ -315,7 +323,7 @@ class PrettierPrint
|
|
315
323
|
|
316
324
|
if output.any? && output.last.is_a?(String) && !output.last.frozen?
|
317
325
|
length = output.last.length
|
318
|
-
output.last.
|
326
|
+
output.last.rstrip!
|
319
327
|
trimmed += length - output.last.length
|
320
328
|
end
|
321
329
|
|
@@ -326,14 +334,7 @@ class PrettierPrint
|
|
326
334
|
# This is a switch for building the correct output buffer wrapper class for
|
327
335
|
# the given output object.
|
328
336
|
def self.for(output)
|
329
|
-
|
330
|
-
when String
|
331
|
-
StringBuffer.new(output)
|
332
|
-
when Array
|
333
|
-
ArrayBuffer.new(output)
|
334
|
-
else
|
335
|
-
DefaultBuffer.new(output)
|
336
|
-
end
|
337
|
+
output.is_a?(String) ? StringBuffer.new(output) : ArrayBuffer.new(output)
|
337
338
|
end
|
338
339
|
end
|
339
340
|
|
@@ -482,88 +483,6 @@ class PrettierPrint
|
|
482
483
|
end
|
483
484
|
end
|
484
485
|
|
485
|
-
# This object represents the current level of indentation within the printer.
|
486
|
-
# It has the ability to generate new levels of indentation through the #align
|
487
|
-
# and #indent methods.
|
488
|
-
class IndentLevel
|
489
|
-
IndentPart = Object.new
|
490
|
-
DedentPart = Object.new
|
491
|
-
|
492
|
-
StringAlignPart = Struct.new(:n)
|
493
|
-
NumberAlignPart = Struct.new(:n)
|
494
|
-
|
495
|
-
attr_reader :genspace, :value, :length, :queue, :root
|
496
|
-
|
497
|
-
def initialize(
|
498
|
-
genspace:,
|
499
|
-
value: genspace.call(0),
|
500
|
-
length: 0,
|
501
|
-
queue: [],
|
502
|
-
root: nil
|
503
|
-
)
|
504
|
-
@genspace = genspace
|
505
|
-
@value = value
|
506
|
-
@length = length
|
507
|
-
@queue = queue
|
508
|
-
@root = root
|
509
|
-
end
|
510
|
-
|
511
|
-
# This can accept a whole lot of different kinds of objects, due to the
|
512
|
-
# nature of the flexibility of the Align node.
|
513
|
-
def align(n)
|
514
|
-
case n
|
515
|
-
when NilClass
|
516
|
-
self
|
517
|
-
when String
|
518
|
-
indent(StringAlignPart.new(n))
|
519
|
-
else
|
520
|
-
indent(n < 0 ? DedentPart : NumberAlignPart.new(n))
|
521
|
-
end
|
522
|
-
end
|
523
|
-
|
524
|
-
def indent(part = IndentPart)
|
525
|
-
next_value = genspace.call(0)
|
526
|
-
next_length = 0
|
527
|
-
next_queue = (part == DedentPart ? queue[0...-1] : [*queue, part])
|
528
|
-
|
529
|
-
last_spaces = 0
|
530
|
-
|
531
|
-
add_spaces = ->(count) do
|
532
|
-
next_value << genspace.call(count)
|
533
|
-
next_length += count
|
534
|
-
end
|
535
|
-
|
536
|
-
flush_spaces = -> do
|
537
|
-
add_spaces[last_spaces] if last_spaces > 0
|
538
|
-
last_spaces = 0
|
539
|
-
end
|
540
|
-
|
541
|
-
next_queue.each do |next_part|
|
542
|
-
case next_part
|
543
|
-
when IndentPart
|
544
|
-
flush_spaces.call
|
545
|
-
add_spaces.call(2)
|
546
|
-
when StringAlignPart
|
547
|
-
flush_spaces.call
|
548
|
-
next_value += next_part.n
|
549
|
-
next_length += next_part.n.length
|
550
|
-
when NumberAlignPart
|
551
|
-
last_spaces += next_part.n
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
flush_spaces.call
|
556
|
-
|
557
|
-
IndentLevel.new(
|
558
|
-
genspace: genspace,
|
559
|
-
value: next_value,
|
560
|
-
length: next_length,
|
561
|
-
queue: next_queue,
|
562
|
-
root: root
|
563
|
-
)
|
564
|
-
end
|
565
|
-
end
|
566
|
-
|
567
486
|
# When printing, you can optionally specify the value that should be used
|
568
487
|
# whenever a group needs to be broken onto multiple lines. In this case the
|
569
488
|
# default is \n.
|
@@ -734,7 +653,7 @@ class PrettierPrint
|
|
734
653
|
|
735
654
|
# This is our command stack. A command consists of a triplet of an
|
736
655
|
# indentation level, the mode (break or flat), and a doc node.
|
737
|
-
commands = [[
|
656
|
+
commands = [[0, MODE_BREAK, doc]]
|
738
657
|
|
739
658
|
# This is a small optimization boolean. It keeps track of whether or not
|
740
659
|
# when we hit a group node we should check if it fits on the same line.
|
@@ -750,49 +669,35 @@ class PrettierPrint
|
|
750
669
|
# priority set on the line suffix and the index it was in the original
|
751
670
|
# array.
|
752
671
|
line_suffix_sort = ->(line_suffix) do
|
753
|
-
[-line_suffix.last, -line_suffixes.index(line_suffix)]
|
672
|
+
[-line_suffix.last.priority, -line_suffixes.index(line_suffix)]
|
754
673
|
end
|
755
674
|
|
756
675
|
# This is a linear stack instead of a mutually recursive call defined on
|
757
676
|
# the individual doc nodes for efficiency.
|
758
677
|
while (indent, mode, doc = commands.pop)
|
759
678
|
case doc
|
760
|
-
when
|
761
|
-
|
762
|
-
position += doc.
|
763
|
-
when Array
|
764
|
-
doc.reverse_each { |part| commands << [indent, mode, part] }
|
765
|
-
when Indent
|
766
|
-
commands << [indent.indent, mode, doc.contents]
|
767
|
-
when Align
|
768
|
-
commands << [indent.align(doc.indent), mode, doc.contents]
|
769
|
-
when Trim
|
770
|
-
position -= buffer.trim!
|
679
|
+
when String
|
680
|
+
buffer << doc
|
681
|
+
position += doc.length
|
771
682
|
when Group
|
772
683
|
if mode == MODE_FLAT && !should_remeasure
|
773
|
-
|
774
|
-
|
775
|
-
doc.break? ? MODE_BREAK : MODE_FLAT,
|
776
|
-
doc.contents
|
777
|
-
]
|
684
|
+
next_mode = doc.break? ? MODE_BREAK : MODE_FLAT
|
685
|
+
commands += doc.contents.reverse.map { |part| [indent, next_mode, part] }
|
778
686
|
else
|
779
687
|
should_remeasure = false
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
next_cmd
|
688
|
+
|
689
|
+
if doc.break?
|
690
|
+
commands += doc.contents.reverse.map { |part| [indent, MODE_BREAK, part] }
|
784
691
|
else
|
785
|
-
[indent,
|
692
|
+
next_commands = doc.contents.reverse.map { |part| [indent, MODE_FLAT, part] }
|
693
|
+
|
694
|
+
if fits?(next_commands, commands, maxwidth - position)
|
695
|
+
commands += next_commands
|
696
|
+
else
|
697
|
+
commands += next_commands.map { |command| command[1] = MODE_BREAK; command }
|
698
|
+
end
|
786
699
|
end
|
787
700
|
end
|
788
|
-
when IfBreak
|
789
|
-
if mode == MODE_BREAK && doc.break_contents.any?
|
790
|
-
commands << [indent, mode, doc.break_contents]
|
791
|
-
elsif mode == MODE_FLAT && doc.flat_contents.any?
|
792
|
-
commands << [indent, mode, doc.flat_contents]
|
793
|
-
end
|
794
|
-
when LineSuffix
|
795
|
-
line_suffixes << [indent, mode, doc.contents, doc.priority]
|
796
701
|
when Breakable
|
797
702
|
if mode == MODE_FLAT
|
798
703
|
if doc.force?
|
@@ -813,28 +718,45 @@ class PrettierPrint
|
|
813
718
|
# to flush them now, as we are about to add a newline.
|
814
719
|
if line_suffixes.any?
|
815
720
|
commands << [indent, mode, doc]
|
816
|
-
|
817
|
-
line_suffixes
|
721
|
+
|
722
|
+
line_suffixes.sort_by(&line_suffix_sort).each do |(indent, mode, doc)|
|
723
|
+
commands += doc.contents.reverse.map { |part| [indent, mode, part] }
|
724
|
+
end
|
725
|
+
|
726
|
+
line_suffixes.clear
|
818
727
|
next
|
819
728
|
end
|
820
729
|
|
821
730
|
if !doc.indent?
|
822
731
|
buffer << newline
|
823
|
-
|
824
|
-
if indent.root
|
825
|
-
buffer << indent.root.value
|
826
|
-
position = indent.root.length
|
827
|
-
else
|
828
|
-
position = 0
|
829
|
-
end
|
732
|
+
position = 0
|
830
733
|
else
|
831
734
|
position -= buffer.trim!
|
832
735
|
buffer << newline
|
833
|
-
buffer << indent
|
834
|
-
position = indent
|
736
|
+
buffer << genspace.call(indent)
|
737
|
+
position = indent
|
738
|
+
end
|
739
|
+
when Indent
|
740
|
+
next_indent = indent + 2
|
741
|
+
commands += doc.contents.reverse.map { |part| [next_indent, mode, part] }
|
742
|
+
when Align
|
743
|
+
next_indent = indent + doc.indent
|
744
|
+
commands += doc.contents.reverse.map { |part| [next_indent, mode, part] }
|
745
|
+
when Trim
|
746
|
+
position -= buffer.trim!
|
747
|
+
when IfBreak
|
748
|
+
if mode == MODE_BREAK && doc.break_contents.any?
|
749
|
+
commands += doc.break_contents.reverse.map { |part| [indent, mode, part] }
|
750
|
+
elsif mode == MODE_FLAT && doc.flat_contents.any?
|
751
|
+
commands += doc.flat_contents.reverse.map { |part| [indent, mode, part] }
|
835
752
|
end
|
753
|
+
when LineSuffix
|
754
|
+
line_suffixes << [indent, mode, doc]
|
836
755
|
when BreakParent
|
837
756
|
# do nothing
|
757
|
+
when Text
|
758
|
+
doc.objects.each { |object| buffer << object }
|
759
|
+
position += doc.width
|
838
760
|
else
|
839
761
|
# Special case where the user has defined some way to get an extra doc
|
840
762
|
# node that we don't explicitly support into the list. In this case
|
@@ -861,13 +783,42 @@ class PrettierPrint
|
|
861
783
|
# Helper node builders
|
862
784
|
# ----------------------------------------------------------------------------
|
863
785
|
|
786
|
+
# The vast majority of breakable calls you receive while formatting are a
|
787
|
+
# space in flat mode and a newline in break mode. Since this is so common,
|
788
|
+
# we have a method here to skip past unnecessary calculation.
|
789
|
+
def breakable_space
|
790
|
+
target << BREAKABLE_SPACE
|
791
|
+
end
|
792
|
+
|
793
|
+
# Another very common breakable call you receive while formatting is an
|
794
|
+
# empty string in flat mode and a newline in break mode. Similar to
|
795
|
+
# breakable_space, this is here for avoid unnecessary calculation.
|
796
|
+
def breakable_empty
|
797
|
+
target << BREAKABLE_EMPTY
|
798
|
+
end
|
799
|
+
|
800
|
+
# The final of the very common breakable calls you receive while formatting
|
801
|
+
# is the normal breakable space but with the addition of the break_parent.
|
802
|
+
def breakable_force
|
803
|
+
target << BREAKABLE_FORCE
|
804
|
+
break_parent
|
805
|
+
end
|
806
|
+
|
807
|
+
# This is the same shortcut as breakable_force, except that it doesn't indent
|
808
|
+
# the next line. This is necessary if you're trying to preserve some custom
|
809
|
+
# formatting like a multi-line string.
|
810
|
+
def breakable_return
|
811
|
+
target << BREAKABLE_RETURN
|
812
|
+
break_parent
|
813
|
+
end
|
814
|
+
|
864
815
|
# A convenience method which is same as follows:
|
865
816
|
#
|
866
817
|
# text(",")
|
867
818
|
# breakable
|
868
819
|
def comma_breakable
|
869
820
|
text(",")
|
870
|
-
|
821
|
+
breakable_space
|
871
822
|
end
|
872
823
|
|
873
824
|
# This is similar to #breakable except the decision to break or not is
|
@@ -896,18 +847,18 @@ class PrettierPrint
|
|
896
847
|
queue = [node]
|
897
848
|
width = 0
|
898
849
|
|
899
|
-
|
900
|
-
doc = queue.shift
|
901
|
-
|
850
|
+
while (doc = queue.shift)
|
902
851
|
case doc
|
903
|
-
when
|
904
|
-
width += doc.
|
905
|
-
when Indent, Align
|
852
|
+
when String
|
853
|
+
width += doc.length
|
854
|
+
when Group, Indent, Align
|
906
855
|
queue = doc.contents + queue
|
907
|
-
when IfBreak
|
908
|
-
queue = doc.break_contents + queue
|
909
856
|
when Breakable
|
910
857
|
width = 0
|
858
|
+
when IfBreak
|
859
|
+
queue = doc.break_contents + queue
|
860
|
+
when Text
|
861
|
+
width += doc.width
|
911
862
|
end
|
912
863
|
end
|
913
864
|
|
@@ -918,26 +869,16 @@ class PrettierPrint
|
|
918
869
|
# no newlines are present in the output. If a newline is being forced into
|
919
870
|
# the output, the replace value will be used.
|
920
871
|
def remove_breaks(node, replace = "; ")
|
921
|
-
|
922
|
-
stack = [node]
|
923
|
-
|
924
|
-
while stack.any?
|
925
|
-
doc = stack.pop
|
926
|
-
|
927
|
-
if doc == marker
|
928
|
-
stack.pop
|
929
|
-
next
|
930
|
-
end
|
931
|
-
|
932
|
-
stack += [doc, marker]
|
872
|
+
queue = [node]
|
933
873
|
|
874
|
+
while (doc = queue.shift)
|
934
875
|
case doc
|
935
876
|
when Align, Indent, Group
|
936
877
|
doc.contents.map! { |child| remove_breaks_with(child, replace) }
|
937
|
-
|
878
|
+
queue += doc.contents
|
938
879
|
when IfBreak
|
939
880
|
doc.flat_contents.map! { |child| remove_breaks_with(child, replace) }
|
940
|
-
|
881
|
+
queue += doc.flat_contents
|
941
882
|
end
|
942
883
|
end
|
943
884
|
end
|
@@ -967,13 +908,14 @@ class PrettierPrint
|
|
967
908
|
# q.comma_breakable
|
968
909
|
# xxx 3
|
969
910
|
def seplist(list, sep=nil, iter_method=:each) # :yield: element
|
970
|
-
sep ||= lambda { comma_breakable }
|
971
911
|
first = true
|
972
912
|
list.__send__(iter_method) {|*v|
|
973
913
|
if first
|
974
914
|
first = false
|
975
|
-
|
915
|
+
elsif sep
|
976
916
|
sep.call
|
917
|
+
else
|
918
|
+
comma_breakable
|
977
919
|
end
|
978
920
|
RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v)
|
979
921
|
}
|
@@ -1013,26 +955,20 @@ class PrettierPrint
|
|
1013
955
|
indent: true,
|
1014
956
|
force: false
|
1015
957
|
)
|
1016
|
-
|
1017
|
-
|
1018
|
-
target << doc
|
958
|
+
target << Breakable.new(separator, width, indent: indent, force: !!force)
|
1019
959
|
break_parent if force == true
|
1020
|
-
|
1021
|
-
doc
|
1022
960
|
end
|
1023
961
|
|
1024
962
|
# This inserts a BreakParent node into the print tree which forces the
|
1025
963
|
# surrounding and all parent group nodes to break.
|
1026
964
|
def break_parent
|
1027
|
-
doc =
|
965
|
+
doc = BREAK_PARENT
|
1028
966
|
target << doc
|
1029
967
|
|
1030
968
|
groups.reverse_each do |group|
|
1031
969
|
break if group.break?
|
1032
970
|
group.break
|
1033
971
|
end
|
1034
|
-
|
1035
|
-
doc
|
1036
972
|
end
|
1037
973
|
|
1038
974
|
# This inserts a Trim node into the print tree which, when printed, will clear
|
@@ -1040,10 +976,7 @@ class PrettierPrint
|
|
1040
976
|
# case where you need to delete printed indentation and force the next node
|
1041
977
|
# to start at the beginning of the line.
|
1042
978
|
def trim
|
1043
|
-
|
1044
|
-
target << doc
|
1045
|
-
|
1046
|
-
doc
|
979
|
+
target << TRIM
|
1047
980
|
end
|
1048
981
|
|
1049
982
|
# ----------------------------------------------------------------------------
|
@@ -1089,15 +1022,36 @@ class PrettierPrint
|
|
1089
1022
|
# A small DSL-like object used for specifying the alternative contents to be
|
1090
1023
|
# printed if the surrounding group doesn't break for an IfBreak node.
|
1091
1024
|
class IfBreakBuilder
|
1092
|
-
attr_reader :
|
1025
|
+
attr_reader :q, :flat_contents
|
1093
1026
|
|
1094
|
-
def initialize(
|
1095
|
-
@
|
1096
|
-
@
|
1027
|
+
def initialize(q, flat_contents)
|
1028
|
+
@q = q
|
1029
|
+
@flat_contents = flat_contents
|
1097
1030
|
end
|
1098
1031
|
|
1099
|
-
def if_flat
|
1100
|
-
|
1032
|
+
def if_flat
|
1033
|
+
q.with_target(flat_contents) { yield }
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
# When we already know that groups are broken, we don't actually need to track
|
1038
|
+
# the flat versions of the contents. So this builder version is effectively a
|
1039
|
+
# no-op, but we need it to maintain the same API. The only thing this can
|
1040
|
+
# impact is that if there's a forced break in the flat contents, then we need
|
1041
|
+
# to propagate that break up the whole tree.
|
1042
|
+
class IfFlatIgnore
|
1043
|
+
attr_reader :q
|
1044
|
+
|
1045
|
+
def initialize(q)
|
1046
|
+
@q = q
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
def if_flat
|
1050
|
+
contents = []
|
1051
|
+
group = Group.new(0, contents: contents)
|
1052
|
+
|
1053
|
+
q.with_target(contents) { yield }
|
1054
|
+
q.break_parent if group.break?
|
1101
1055
|
end
|
1102
1056
|
end
|
1103
1057
|
|
@@ -1111,31 +1065,50 @@ class PrettierPrint
|
|
1111
1065
|
# In the example above, if the surrounding group is broken it will print 'do'
|
1112
1066
|
# and if it is not it will print '{'.
|
1113
1067
|
def if_break
|
1114
|
-
|
1068
|
+
break_contents = []
|
1069
|
+
flat_contents = []
|
1070
|
+
|
1071
|
+
doc = IfBreak.new(break_contents: break_contents, flat_contents: flat_contents)
|
1115
1072
|
target << doc
|
1116
1073
|
|
1117
|
-
with_target(
|
1118
|
-
|
1074
|
+
with_target(break_contents) { yield }
|
1075
|
+
|
1076
|
+
if groups.last.break?
|
1077
|
+
IfFlatIgnore.new(self)
|
1078
|
+
else
|
1079
|
+
IfBreakBuilder.new(self, flat_contents)
|
1080
|
+
end
|
1119
1081
|
end
|
1120
1082
|
|
1121
1083
|
# This is similar to if_break in that it also inserts an IfBreak node into the
|
1122
1084
|
# print tree, however it's starting from the flat contents, and cannot be used
|
1123
1085
|
# to build the break contents.
|
1124
1086
|
def if_flat
|
1125
|
-
|
1126
|
-
|
1087
|
+
if groups.last.break?
|
1088
|
+
contents = []
|
1089
|
+
group = Group.new(0, contents: contents)
|
1127
1090
|
|
1128
|
-
|
1091
|
+
with_target(contents) { yield }
|
1092
|
+
break_parent if group.break?
|
1093
|
+
else
|
1094
|
+
flat_contents = []
|
1095
|
+
doc = IfBreak.new(break_contents: [], flat_contents: flat_contents)
|
1096
|
+
target << doc
|
1097
|
+
|
1098
|
+
with_target(flat_contents) { yield }
|
1099
|
+
doc
|
1100
|
+
end
|
1129
1101
|
end
|
1130
1102
|
|
1131
1103
|
# Very similar to the #nest method, this indents the nested content by one
|
1132
1104
|
# level by inserting an Indent node into the print tree. The contents of the
|
1133
1105
|
# node are determined by the block.
|
1134
1106
|
def indent
|
1135
|
-
|
1107
|
+
contents = []
|
1108
|
+
doc = Indent.new(contents: contents)
|
1136
1109
|
target << doc
|
1137
1110
|
|
1138
|
-
with_target(
|
1111
|
+
with_target(contents) { yield }
|
1139
1112
|
doc
|
1140
1113
|
end
|
1141
1114
|
|
@@ -1152,10 +1125,11 @@ class PrettierPrint
|
|
1152
1125
|
# Increases left margin after newline with +indent+ for line breaks added in
|
1153
1126
|
# the block.
|
1154
1127
|
def nest(indent)
|
1155
|
-
|
1128
|
+
contents = []
|
1129
|
+
doc = Align.new(indent: indent, contents: contents)
|
1156
1130
|
target << doc
|
1157
1131
|
|
1158
|
-
with_target(
|
1132
|
+
with_target(contents) { yield }
|
1159
1133
|
doc
|
1160
1134
|
end
|
1161
1135
|
|
@@ -1192,7 +1166,7 @@ class PrettierPrint
|
|
1192
1166
|
# fit onto the remaining space on the current line. If we finish printing
|
1193
1167
|
# all of the commands or if we hit a newline, then we return true. Otherwise
|
1194
1168
|
# if we continue printing past the remaining space, we return false.
|
1195
|
-
def fits?(
|
1169
|
+
def fits?(next_commands, rest_commands, remaining)
|
1196
1170
|
# This is the index in the remaining commands that we've handled so far.
|
1197
1171
|
# We reverse through the commands and add them to the stack if we've run
|
1198
1172
|
# out of nodes to handle.
|
@@ -1200,7 +1174,7 @@ class PrettierPrint
|
|
1200
1174
|
|
1201
1175
|
# This is our stack of commands, very similar to the commands list in the
|
1202
1176
|
# print method.
|
1203
|
-
commands = [
|
1177
|
+
commands = [*next_commands]
|
1204
1178
|
|
1205
1179
|
# This is our output buffer, really only necessary to keep track of
|
1206
1180
|
# because we could encounter a Trim doc node that would actually add
|
@@ -1219,25 +1193,12 @@ class PrettierPrint
|
|
1219
1193
|
indent, mode, doc = commands.pop
|
1220
1194
|
|
1221
1195
|
case doc
|
1222
|
-
when
|
1223
|
-
|
1224
|
-
remaining -= doc.
|
1225
|
-
when Array
|
1226
|
-
doc.reverse_each { |part| commands << [indent, mode, part] }
|
1227
|
-
when Indent
|
1228
|
-
commands << [indent.indent, mode, doc.contents]
|
1229
|
-
when Align
|
1230
|
-
commands << [indent.align(doc.indent), mode, doc.contents]
|
1231
|
-
when Trim
|
1232
|
-
remaining += fit_buffer.trim!
|
1196
|
+
when String
|
1197
|
+
fit_buffer << doc
|
1198
|
+
remaining -= doc.length
|
1233
1199
|
when Group
|
1234
|
-
|
1235
|
-
|
1236
|
-
if mode == MODE_BREAK && doc.break_contents.any?
|
1237
|
-
commands << [indent, mode, doc.break_contents]
|
1238
|
-
elsif mode == MODE_FLAT && doc.flat_contents.any?
|
1239
|
-
commands << [indent, mode, doc.flat_contents]
|
1240
|
-
end
|
1200
|
+
next_mode = doc.break? ? MODE_BREAK : mode
|
1201
|
+
commands += doc.contents.reverse.map { |part| [indent, next_mode, part] }
|
1241
1202
|
when Breakable
|
1242
1203
|
if mode == MODE_FLAT && !doc.force?
|
1243
1204
|
fit_buffer << doc.separator
|
@@ -1246,6 +1207,23 @@ class PrettierPrint
|
|
1246
1207
|
end
|
1247
1208
|
|
1248
1209
|
return true
|
1210
|
+
when Indent
|
1211
|
+
next_indent = indent + 2
|
1212
|
+
commands += doc.contents.reverse.map { |part| [next_indent, mode, part] }
|
1213
|
+
when Align
|
1214
|
+
next_indent = indent + doc.indent
|
1215
|
+
commands += doc.contents.reverse.map { |part| [next_indent, mode, part] }
|
1216
|
+
when Trim
|
1217
|
+
remaining += fit_buffer.trim!
|
1218
|
+
when IfBreak
|
1219
|
+
if mode == MODE_BREAK && doc.break_contents.any?
|
1220
|
+
commands += doc.break_contents.reverse.map { |part| [indent, mode, part] }
|
1221
|
+
elsif mode == MODE_FLAT && doc.flat_contents.any?
|
1222
|
+
commands += doc.flat_contents.reverse.map { |part| [indent, mode, part] }
|
1223
|
+
end
|
1224
|
+
when Text
|
1225
|
+
doc.objects.each { |object| fit_buffer << object }
|
1226
|
+
remaining -= doc.width
|
1249
1227
|
end
|
1250
1228
|
end
|
1251
1229
|
|
@@ -1255,8 +1233,9 @@ class PrettierPrint
|
|
1255
1233
|
# Resets the group stack and target array so that this pretty printer object
|
1256
1234
|
# can continue to be used before calling flush again if desired.
|
1257
1235
|
def reset
|
1258
|
-
|
1259
|
-
@
|
1236
|
+
contents = []
|
1237
|
+
@groups = [Group.new(0, contents: contents)]
|
1238
|
+
@target = contents
|
1260
1239
|
end
|
1261
1240
|
|
1262
1241
|
def remove_breaks_with(doc, replace)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prettier_print
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Newton
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -50,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
50
|
- !ruby/object:Gem::Version
|
51
51
|
version: '0'
|
52
52
|
requirements: []
|
53
|
-
rubygems_version: 3.
|
53
|
+
rubygems_version: 3.3.21
|
54
54
|
signing_key:
|
55
55
|
specification_version: 4
|
56
56
|
summary: A drop-in replacement for the prettyprint gem with more functionality.
|