2
2
3
3
module SyntaxTree
4
4
module CLI
5
+ # This holds references to objects that respond to both #parse and #format
6
+ # so that we can use them in the CLI.
7
+ HANDLERS = { }
8
+ HANDLERS . default = SyntaxTree
9
+
10
+ # This is a hook provided so that plugins can register themselves as the
11
+ # handler for a particular file type.
12
+ def self . register_handler ( extension , handler )
13
+ HANDLERS [ extension ] = handler
14
+ end
15
+
5
16
# A utility wrapper around colored strings in the output.
6
17
class Color
7
18
attr_reader :value , :code
@@ -34,7 +45,7 @@ def self.yellow(value)
34
45
35
46
# The parent action class for the CLI that implements the basics.
36
47
class Action
37
- def run ( filepath , source )
48
+ def run ( handler , filepath , source )
38
49
end
39
50
40
51
def success
@@ -46,8 +57,8 @@ def failure
46
57
47
58
# An action of the CLI that prints out the AST for the given source.
48
59
class AST < Action
49
- def run ( filepath , source )
50
- pp SyntaxTree . parse ( source )
60
+ def run ( handler , filepath , source )
61
+ pp handler . parse ( source )
51
62
end
52
63
end
53
64
@@ -57,8 +68,8 @@ class Check < Action
57
68
class UnformattedError < StandardError
58
69
end
59
70
60
- def run ( filepath , source )
61
- raise UnformattedError if source != SyntaxTree . format ( source )
71
+ def run ( handler , filepath , source )
72
+ raise UnformattedError if source != handler . format ( source )
62
73
rescue StandardError
63
74
warn ( "[#{ Color . yellow ( "warn" ) } ] #{ filepath } " )
64
75
raise
@@ -79,11 +90,11 @@ class Debug < Action
79
90
class NonIdempotentFormatError < StandardError
80
91
end
81
92
82
- def run ( filepath , source )
93
+ def run ( handler , filepath , source )
83
94
warning = "[#{ Color . yellow ( "warn" ) } ] #{ filepath } "
84
- formatted = SyntaxTree . format ( source )
95
+ formatted = handler . format ( source )
85
96
86
- if formatted != SyntaxTree . format ( formatted )
97
+ if formatted != handler . format ( formatted )
87
98
raise NonIdempotentFormatError
88
99
end
89
100
rescue StandardError
@@ -102,28 +113,28 @@ def failure
102
113
103
114
# An action of the CLI that prints out the doc tree IR for the given source.
104
115
class Doc < Action
105
- def run ( filepath , source )
116
+ def run ( handler , filepath , source )
106
117
formatter = Formatter . new ( [ ] )
107
- SyntaxTree . parse ( source ) . format ( formatter )
118
+ handler . parse ( source ) . format ( formatter )
108
119
pp formatter . groups . first
109
120
end
110
121
end
111
122
112
123
# An action of the CLI that formats the input source and prints it out.
113
124
class Format < Action
114
- def run ( filepath , source )
115
- puts SyntaxTree . format ( source )
125
+ def run ( handler , filepath , source )
126
+ puts handler . format ( source )
116
127
end
117
128
end
118
129
119
130
# An action of the CLI that formats the input source and writes the
120
131
# formatted output back to the file.
121
132
class Write < Action
122
- def run ( filepath , source )
133
+ def run ( handler , filepath , source )
123
134
print filepath
124
135
start = Time . now
125
136
126
- formatted = SyntaxTree . format ( source )
137
+ formatted = handler . format ( source )
127
138
File . write ( filepath , formatted )
128
139
129
140
color = source == formatted ? Color . gray ( filepath ) : filepath
@@ -214,10 +225,12 @@ def run(argv)
214
225
patterns . each do |pattern |
215
226
Dir . glob ( pattern ) . each do |filepath |
216
227
next unless File . file? ( filepath )
228
+
229
+ handler = HANDLERS [ File . extname ( filepath ) ]
217
230
source = SyntaxTree . read ( filepath )
218
231
219
232
begin
220
- action . run ( filepath , source )
233
+ action . run ( handler , filepath , source )
221
234
rescue ParseError => error
222
235
warn ( "Error: #{ error . message } " )
223
236
0 commit comments