@@ -154,6 +154,88 @@ def failure
154154 end
155155 end
156156
157+ # An action of the CLI that generates ctags for the given source.
158+ class CTags < Action
159+ attr_reader :entries
160+
161+ def initialize ( options )
162+ super ( options )
163+ @entries = [ ]
164+ end
165+
166+ def run ( item )
167+ lines = item . source . lines ( chomp : true )
168+
169+ SyntaxTree . index ( item . source ) . each do |entry |
170+ line = lines [ entry . location . line - 1 ]
171+ pattern = "/^#{ line . gsub ( "\\ " , "\\ \\ \\ \\ " ) . gsub ( "/" , "\\ /" ) } $/;\" "
172+
173+ entries <<
174+ case entry
175+ when SyntaxTree ::Index ::ModuleDefinition
176+ parts = [ entry . name , item . filepath , pattern , "m" ]
177+
178+ if entry . nesting != [ [ entry . name ] ]
179+ parts << "class:#{ entry . nesting . flatten . tap ( &:pop ) . join ( "." ) } "
180+ end
181+
182+ parts . join ( "\t " )
183+ when SyntaxTree ::Index ::ClassDefinition
184+ parts = [ entry . name , item . filepath , pattern , "c" ]
185+
186+ if entry . nesting != [ [ entry . name ] ]
187+ parts << "class:#{ entry . nesting . flatten . tap ( &:pop ) . join ( "." ) } "
188+ end
189+
190+ unless entry . superclass . empty?
191+ inherits = entry . superclass . join ( "." ) . delete_prefix ( "." )
192+ parts << "inherits:#{ inherits } "
193+ end
194+
195+ parts . join ( "\t " )
196+ when SyntaxTree ::Index ::MethodDefinition
197+ parts = [ entry . name , item . filepath , pattern , "f" ]
198+
199+ unless entry . nesting . empty?
200+ parts << "class:#{ entry . nesting . flatten . join ( "." ) } "
201+ end
202+
203+ parts . join ( "\t " )
204+ when SyntaxTree ::Index ::SingletonMethodDefinition
205+ parts = [ entry . name , item . filepath , pattern , "F" ]
206+
207+ unless entry . nesting . empty?
208+ parts << "class:#{ entry . nesting . flatten . join ( "." ) } "
209+ end
210+
211+ parts . join ( "\t " )
212+ when SyntaxTree ::Index ::AliasMethodDefinition
213+ parts = [ entry . name , item . filepath , pattern , "a" ]
214+
215+ unless entry . nesting . empty?
216+ parts << "class:#{ entry . nesting . flatten . join ( "." ) } "
217+ end
218+
219+ parts . join ( "\t " )
220+ when SyntaxTree ::Index ::ConstantDefinition
221+ parts = [ entry . name , item . filepath , pattern , "C" ]
222+
223+ unless entry . nesting . empty?
224+ parts << "class:#{ entry . nesting . flatten . join ( "." ) } "
225+ end
226+
227+ parts . join ( "\t " )
228+ end
229+ end
230+ end
231+
232+ def success
233+ puts ( "!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;\" to lines/" )
234+ puts ( "!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/" )
235+ entries . sort . each { |entry | puts ( entry ) }
236+ end
237+ end
238+
157239 # An action of the CLI that formats the source twice to check if the first
158240 # format is not idempotent.
159241 class Debug < Action
@@ -488,6 +570,8 @@ def run(argv)
488570 AST . new ( options )
489571 when "c" , "check"
490572 Check . new ( options )
573+ when "ctags"
574+ CTags . new ( options )
491575 when "debug"
492576 Debug . new ( options )
493577 when "doc"
0 commit comments