prettyrb 0.4.0 → 0.5.0
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/.ruby-version +1 -1
- data/Gemfile.lock +1 -1
- data/lib/prettyrb.rb +12 -0
- data/lib/prettyrb/builder.rb +6 -1
- data/lib/prettyrb/cli.rb +15 -6
- data/lib/prettyrb/document.rb +164 -0
- data/lib/prettyrb/formatter.rb +1 -10
- data/lib/prettyrb/nodes/and_node.rb +11 -0
- data/lib/prettyrb/nodes/base_node.rb +5 -1
- data/lib/prettyrb/nodes/def_node.rb +17 -0
- data/lib/prettyrb/nodes/if_node.rb +17 -1
- data/lib/prettyrb/nodes/logical_operator_helper.rb +13 -0
- data/lib/prettyrb/nodes/or_node.rb +11 -0
- data/lib/prettyrb/nodes/regexp_node.rb +41 -0
- data/lib/prettyrb/nodes/send_node.rb +63 -0
- data/lib/prettyrb/nodes/string_helper.rb +17 -1
- data/lib/prettyrb/version.rb +1 -1
- data/lib/prettyrb/visitor.rb +820 -636
- data/lib/prettyrb/writer.rb +157 -0
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3ca66d3c436cf92ecaeef327cd56e32380eb956c844cafcc605e471f80e5a9d
|
4
|
+
data.tar.gz: 6a88f83ea9a52c7cebcb0c70d72a8f599c8480e0a628c2eba016ce506ef99996
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fb301879d8c8905aa82268ac2d04944fc02eb4a3e9d28466b80a70dd3e3b2e1ad93dba3a4916736e5c5533c067eb69b869a610f12ee6746d61ec5165e43d128
|
7
|
+
data.tar.gz: 3a2894fd21b9493aec14b1d85a08e3be929e356ad7dd2dee013409f2ec3dcd47f914ab15d6028146e769533812abb786bbce415d449edcaefd679093c06d5af5
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.0
|
data/Gemfile.lock
CHANGED
data/lib/prettyrb.rb
CHANGED
@@ -1,17 +1,29 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
1
3
|
require "parser/current"
|
2
4
|
require "prettyrb/version"
|
3
5
|
|
4
6
|
require "prettyrb/nodes/base_node"
|
5
7
|
require "prettyrb/nodes/if_node"
|
6
8
|
require "prettyrb/nodes/string_helper"
|
9
|
+
require "prettyrb/nodes/logical_operator_helper"
|
7
10
|
require "prettyrb/nodes/str_node"
|
8
11
|
require "prettyrb/nodes/dstr_node"
|
12
|
+
require "prettyrb/nodes/def_node"
|
13
|
+
require "prettyrb/nodes/and_node"
|
14
|
+
require "prettyrb/nodes/or_node"
|
15
|
+
require "prettyrb/nodes/regexp_node"
|
16
|
+
require "prettyrb/nodes/send_node"
|
17
|
+
|
18
|
+
require "prettyrb/document"
|
9
19
|
require "prettyrb/builder"
|
10
20
|
require "prettyrb/formatter"
|
11
21
|
require "prettyrb/visitor"
|
22
|
+
require "prettyrb/writer"
|
12
23
|
|
13
24
|
require "prettyrb/cli"
|
14
25
|
|
15
26
|
module Prettyrb
|
27
|
+
MAX_LINE_LENGTH = 100
|
16
28
|
class Error < StandardError; end
|
17
29
|
end
|
data/lib/prettyrb/builder.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
module Prettyrb
|
2
2
|
class Builder < Parser::Builders::Default
|
3
3
|
NODE_TYPES = {
|
4
|
+
and: Prettyrb::Nodes::AndNode,
|
5
|
+
dstr: Prettyrb::Nodes::DstrNode,
|
4
6
|
if: Prettyrb::Nodes::IfNode,
|
7
|
+
or: Prettyrb::Nodes::OrNode,
|
8
|
+
regexp: Prettyrb::Nodes::RegexpNode,
|
9
|
+
send: Prettyrb::Nodes::SendNode,
|
5
10
|
str: Prettyrb::Nodes::StrNode,
|
6
|
-
|
11
|
+
def: Prettyrb::Nodes::DefNode,
|
7
12
|
}.freeze
|
8
13
|
|
9
14
|
def n(type, children, source_map)
|
data/lib/prettyrb/cli.rb
CHANGED
@@ -3,18 +3,27 @@ require "thor"
|
|
3
3
|
module Prettyrb
|
4
4
|
class CLI < Thor
|
5
5
|
desc "format [FILE]", "Ruby file to prettify"
|
6
|
-
|
7
|
-
method_option :files, type: :array
|
8
|
-
def format(*files)
|
6
|
+
def format(file)
|
9
7
|
content = File.read(file)
|
10
8
|
formatted_content = Prettyrb::Formatter.new(content).format
|
11
9
|
|
12
|
-
|
10
|
+
puts formatted_content
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "write [FILES]", "Write prettified Ruby files"
|
14
|
+
def write(*files)
|
15
|
+
files.each do |file|
|
16
|
+
content = File.read(file)
|
17
|
+
begin
|
18
|
+
formatted_content = Prettyrb::Formatter.new(content).format
|
19
|
+
rescue Exception => e
|
20
|
+
puts "Failed to write #{file}"
|
21
|
+
throw e
|
22
|
+
end
|
23
|
+
|
13
24
|
File.open(file, 'w') do |f|
|
14
25
|
f.write(formatted_content)
|
15
26
|
end
|
16
|
-
else
|
17
|
-
puts formatted_content
|
18
27
|
end
|
19
28
|
end
|
20
29
|
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Prettyrb
|
2
|
+
module Document
|
3
|
+
module DSL
|
4
|
+
def concat(*args)
|
5
|
+
Document::Concat.new(*args)
|
6
|
+
end
|
7
|
+
|
8
|
+
def join(*args)
|
9
|
+
Document::Join.new(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def group(*args)
|
13
|
+
Document::Group.new(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def if_break(*args)
|
17
|
+
Document::IfBreak.new(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def indent(*args)
|
21
|
+
Document::Indent.new(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def dedent(*args)
|
25
|
+
Document::Dedent.new(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def hardline(*args)
|
29
|
+
Document::Hardline.new(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def softline(*args)
|
33
|
+
Document::Softline.new(*args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Builder
|
38
|
+
attr_reader :parts
|
39
|
+
|
40
|
+
include Enumerable
|
41
|
+
|
42
|
+
def initialize(*args)
|
43
|
+
@parts = args
|
44
|
+
end
|
45
|
+
|
46
|
+
def each
|
47
|
+
@parts.each
|
48
|
+
end
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
inspect_children(self, indent_level: 0)
|
52
|
+
end
|
53
|
+
|
54
|
+
def has_group_part?
|
55
|
+
parts.any? { |p| p.is_a?(Group) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def groups
|
59
|
+
parts.select { |p| p.is_a?(Group) } + parts.flat_map do |p|
|
60
|
+
p.groups if p.respond_to?(:groups)
|
61
|
+
end.compact
|
62
|
+
end
|
63
|
+
|
64
|
+
def max_group_depth
|
65
|
+
return 0 if !parts
|
66
|
+
return @max_group_depth if defined?(@max_group_depth)
|
67
|
+
|
68
|
+
has_groups = parts.any? { |p| p.is_a?(Group) }
|
69
|
+
|
70
|
+
total = if has_groups
|
71
|
+
1
|
72
|
+
else
|
73
|
+
0
|
74
|
+
end
|
75
|
+
|
76
|
+
# TODO swap filter/flat_map for single iteration
|
77
|
+
nested_total = parts.
|
78
|
+
filter { |p| p.respond_to?(:max_group_depth) }.
|
79
|
+
flat_map { |p| p.max_group_depth }.
|
80
|
+
max
|
81
|
+
|
82
|
+
@max_group_depth = total + (nested_total || 0)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def inspect_children(builder, indent_level:)
|
88
|
+
if builder.respond_to?(:parts)
|
89
|
+
children = if builder.parts
|
90
|
+
builder.parts.map do |p|
|
91
|
+
inspect_children(p, indent_level: indent_level + 1)
|
92
|
+
end.join("\n")
|
93
|
+
end
|
94
|
+
|
95
|
+
" " * indent_level + "(#{builder.class}\n#{" "*indent_level}#{children}\n #{" " * indent_level})"
|
96
|
+
else
|
97
|
+
" " * indent_level + builder.inspect
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class Concat < Builder
|
103
|
+
end
|
104
|
+
|
105
|
+
class Group < Builder
|
106
|
+
attr_reader :joiner
|
107
|
+
|
108
|
+
def initialize(*args, joiner: "")
|
109
|
+
super(*args)
|
110
|
+
@joiner = joiner
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class Join < Builder
|
115
|
+
attr_reader :separator
|
116
|
+
|
117
|
+
def initialize(separator: ",", parts:)
|
118
|
+
if parts.is_a?(Array)
|
119
|
+
super(*parts)
|
120
|
+
else
|
121
|
+
super(parts)
|
122
|
+
end
|
123
|
+
@separator = separator
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class IfBreak
|
128
|
+
attr_reader :without_break, :with_break
|
129
|
+
def initialize(without_break:, with_break: )
|
130
|
+
@without_break = without_break
|
131
|
+
@with_break = with_break
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Indent < Builder
|
136
|
+
attr_reader :only_when_break
|
137
|
+
|
138
|
+
def initialize(*args, only_when_break: false)
|
139
|
+
@only_when_break = only_when_break
|
140
|
+
super(*args)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Dedent < Builder
|
145
|
+
end
|
146
|
+
|
147
|
+
class Hardline < Builder
|
148
|
+
attr_reader :count, :skip_indent
|
149
|
+
def initialize(count: 1, skip_indent: false)
|
150
|
+
@count = count
|
151
|
+
@skip_indent = skip_indent
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class Softline < Builder
|
156
|
+
attr_reader :fallback
|
157
|
+
|
158
|
+
def initialize(*args, fallback: nil)
|
159
|
+
super(args)
|
160
|
+
@fallback = fallback
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
data/lib/prettyrb/formatter.rb
CHANGED
@@ -20,7 +20,7 @@ module Prettyrb
|
|
20
20
|
Parser::CurrentRuby.send(:setup_source_buffer, "file='(string)'", 1, @code, parser.default_encoding)
|
21
21
|
)
|
22
22
|
|
23
|
-
visitor = Visitor.new
|
23
|
+
visitor = Visitor.new(root_node)
|
24
24
|
visitor.visit(root_node)
|
25
25
|
|
26
26
|
visitor.output
|
@@ -28,15 +28,6 @@ module Prettyrb
|
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
-
def format_type(node, indentation)
|
32
|
-
case node.node_type
|
33
|
-
when :if
|
34
|
-
IfFormatter.new(node, indentation).format
|
35
|
-
else
|
36
|
-
raise "can't handle #{node}"
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
31
|
attr_reader :code
|
41
32
|
end
|
42
33
|
end
|
@@ -8,7 +8,7 @@ module Prettyrb
|
|
8
8
|
|
9
9
|
super
|
10
10
|
|
11
|
-
children
|
11
|
+
children&.each do |child|
|
12
12
|
next unless child.is_a?(BaseNode)
|
13
13
|
child.parent = self
|
14
14
|
end
|
@@ -20,6 +20,10 @@ module Prettyrb
|
|
20
20
|
@mutable[:parent]
|
21
21
|
end
|
22
22
|
|
23
|
+
def string?
|
24
|
+
type == :str || type == :dstr
|
25
|
+
end
|
26
|
+
|
23
27
|
protected
|
24
28
|
|
25
29
|
def parent=(parent)
|
@@ -11,7 +11,7 @@ module Prettyrb
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def conditions
|
15
15
|
children[0]
|
16
16
|
end
|
17
17
|
|
@@ -42,6 +42,22 @@ module Prettyrb
|
|
42
42
|
def unless_node?
|
43
43
|
children[1].nil? && children[2] != :if
|
44
44
|
end
|
45
|
+
|
46
|
+
def elsif_branches
|
47
|
+
if has_elsif?
|
48
|
+
[else_body_node] + else_body_node.elsif_branches
|
49
|
+
else
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def else_branch
|
55
|
+
if has_elsif?
|
56
|
+
elsif_branches.last.children[2]
|
57
|
+
else
|
58
|
+
else_body_node
|
59
|
+
end
|
60
|
+
end
|
45
61
|
end
|
46
62
|
end
|
47
63
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Prettyrb
|
2
|
+
module Nodes
|
3
|
+
class RegexpNode < BaseNode
|
4
|
+
include StringHelper
|
5
|
+
|
6
|
+
PERCENT_PAIRS = {
|
7
|
+
"{" => "}",
|
8
|
+
"[" => "]",
|
9
|
+
"(" => ")",
|
10
|
+
"<" => ">",
|
11
|
+
}
|
12
|
+
|
13
|
+
def percent?
|
14
|
+
loc.expression.source.start_with?("%")
|
15
|
+
end
|
16
|
+
|
17
|
+
def percent_type
|
18
|
+
loc.expression.source[1]
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_delimiter
|
22
|
+
loc.expression.source[2]
|
23
|
+
end
|
24
|
+
|
25
|
+
def end_delimiter
|
26
|
+
PERCENT_PAIRS.fetch(start_delimiter, start_delimiter)
|
27
|
+
end
|
28
|
+
|
29
|
+
def format
|
30
|
+
raw_content = loc.expression.source
|
31
|
+
content = raw_content[1...-1]
|
32
|
+
|
33
|
+
if raw_content[0] == "'"
|
34
|
+
content.gsub('"', '\\"').gsub('#{', '\\#{')
|
35
|
+
else
|
36
|
+
content.gsub("\\", "\\\\")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|