2
2
3
3
class SyntaxTree
4
4
module CLI
5
+ # A utility wrapper around colored strings in the output.
6
+ class ColoredString
7
+ COLORS = { default : "0" , gray : "38;5;102" , yellow : "33" }
8
+
9
+ attr_reader :code , :string
10
+
11
+ def initialize ( color , string )
12
+ @code = COLORS [ color ]
13
+ @string = string
14
+ end
15
+
16
+ def to_s
17
+ "\033 [#{ code } m#{ string } \033 [0m"
18
+ end
19
+ end
20
+
21
+ # The parent action class for the CLI that implements the basics.
22
+ class Action
23
+ def run ( filepath , source )
24
+ end
25
+
26
+ def success
27
+ end
28
+
29
+ def failure
30
+ end
31
+ end
32
+
5
33
# An action of the CLI that prints out the AST for the given source.
6
- class AST
34
+ class AST < Action
7
35
def run ( filepath , source )
8
36
pp SyntaxTree . parse ( source )
9
37
end
10
38
end
11
39
12
40
# An action of the CLI that formats the source twice to check if the first
13
41
# format is not idempotent.
14
- class Check
42
+ class Check < Action
15
43
def run ( filepath , source )
16
44
formatted = SyntaxTree . format ( source )
17
- raise if formatted != SyntaxTree . format ( formatted )
45
+ return true if formatted == SyntaxTree . format ( formatted )
46
+
47
+ puts "[#{ ColoredString . new ( :yellow , "warn" ) } ] #{ filepath } "
48
+ false
49
+ end
50
+
51
+ def success
52
+ puts "All files matched expected format."
53
+ end
54
+
55
+ def failure
56
+ warn ( "The listed files did not match the expected format." )
18
57
end
19
58
end
20
59
21
60
# An action of the CLI that prints out the doc tree IR for the given source.
22
- class Doc
61
+ class Doc < Action
23
62
def run ( filepath , source )
24
63
formatter = Formatter . new ( [ ] )
25
64
SyntaxTree . parse ( source ) . format ( formatter )
@@ -28,17 +67,26 @@ def run(filepath, source)
28
67
end
29
68
30
69
# An action of the CLI that formats the input source and prints it out.
31
- class Format
70
+ class Format < Action
32
71
def run ( filepath , source )
33
72
puts SyntaxTree . format ( source )
34
73
end
35
74
end
36
75
37
76
# An action of the CLI that formats the input source and writes the
38
77
# formatted output back to the file.
39
- class Write
78
+ class Write < Action
40
79
def run ( filepath , source )
41
- File . write ( filepath , SyntaxTree . format ( source ) )
80
+ print filepath
81
+ start = Time . now
82
+
83
+ formatted = SyntaxTree . format ( source )
84
+ File . write ( filepath , formatted )
85
+
86
+ delta = ( ( Time . now - start ) * 1000 ) . round
87
+ color = source == formatted ? :gray : :default
88
+
89
+ puts "\r #{ ColoredString . new ( color , filepath ) } #{ delta } ms"
42
90
end
43
91
end
44
92
@@ -81,15 +129,32 @@ def run(argv)
81
129
errored = false
82
130
patterns . each do |pattern |
83
131
Dir . glob ( pattern ) . each do |filepath |
84
- errored |= run_for ( action , filepath ) if File . file? ( filepath )
132
+ next unless File . file? ( filepath )
133
+
134
+ begin
135
+ action . run ( filepath , source_for ( filepath ) )
136
+ rescue => error
137
+ warn ( "!!! Failed on #{ filepath } " )
138
+ warn ( error . message )
139
+ warn ( error . backtrace )
140
+ errored = true
141
+ end
85
142
end
86
143
end
87
-
88
- errored ? 1 : 0
144
+
145
+ if errored
146
+ action . failure
147
+ 1
148
+ else
149
+ action . success
150
+ 0
151
+ end
89
152
end
90
153
91
154
private
92
155
156
+ # Returns the source from the given filepath taking into account any
157
+ # potential magic encoding comments.
93
158
def source_for ( filepath )
94
159
encoding =
95
160
File . open ( filepath , "r" ) do |file |
@@ -100,16 +165,6 @@ def source_for(filepath)
100
165
101
166
File . read ( filepath , encoding : encoding )
102
167
end
103
-
104
- def run_for ( action , filepath )
105
- action . run ( filepath , source_for ( filepath ) )
106
- false
107
- rescue => error
108
- warn ( "!!! Failed on #{ filepath } " )
109
- warn ( error . message )
110
- warn ( error . backtrace )
111
- true
112
- end
113
168
end
114
169
end
115
170
end
0 commit comments