bloopletech-rtags 0.99.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/LICENSE.txt +55 -0
  2. data/README +8 -0
  3. data/RELEASENOTES +43 -0
  4. data/TODO +40 -0
  5. data/bin/rtags +861 -0
  6. metadata +54 -0
data/LICENSE.txt ADDED
@@ -0,0 +1,55 @@
1
+ rtags is copyrighted free software.
2
+
3
+ You can redistribute it and/or modify it under either the terms of the GPL
4
+ (see COPYING.txt file), or the conditions below:
5
+
6
+ 1. You may make and give away verbatim copies of the source form of the
7
+ software without restriction, provided that you duplicate all of the
8
+ original copyright notices and associated disclaimers.
9
+
10
+ 2. You may modify your copy of the software in any way, provided that
11
+ you do at least ONE of the following:
12
+
13
+ a) place your modifications in the Public Domain or otherwise
14
+ make them Freely Available, such as by posting said
15
+ modifications to Usenet or an equivalent medium, or by allowing
16
+ the author to include your modifications in the software.
17
+
18
+ b) use the modified software only within your corporation or
19
+ organization.
20
+
21
+ c) rename any non-standard executables so the names do not conflict
22
+ with standard executables, which must also be provided.
23
+
24
+ d) make other distribution arrangements with the author.
25
+
26
+ 3. You may distribute the software in object code or executable
27
+ form, provided that you do at least ONE of the following:
28
+
29
+ a) distribute the executables and library files of the software,
30
+ together with instructions (in the manual page or equivalent)
31
+ on where to get the original distribution.
32
+
33
+ b) accompany the distribution with the machine-readable source of
34
+ the software.
35
+
36
+ c) give non-standard executables non-standard names, with
37
+ instructions on where to get the original software distribution.
38
+
39
+ d) make other distribution arrangements with the author.
40
+
41
+ 4. You may modify and include the part of the software into any other
42
+ software (possibly commercial). But some files in the distribution
43
+ are not written by the author, so that they are not under this terms.
44
+
45
+ 5. The scripts and library files supplied as input to or produced as
46
+ output from the software do not automatically fall under the
47
+ copyright of the software, but belong to whomever generated them,
48
+ and may be sold commercially, and may be aggregated with this
49
+ software.
50
+
51
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
52
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
53
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54
+ PURPOSE.
55
+
data/README ADDED
@@ -0,0 +1,8 @@
1
+ rtags: like ctags, but for ruby.
2
+
3
+ For more information, see ./bin/rtags
4
+
5
+ Originally by Keiju ISHITSUKA
6
+ Was maintained by Pjotr Prins
7
+ Currently maintained by no-one
8
+
data/RELEASENOTES ADDED
@@ -0,0 +1,43 @@
1
+ rtags.rb -
2
+
3
+ Release Version: 0.96 (April 2006) by Pjotr Prins
4
+ Improved filtering on repository files (skip _darcs, CVS, .SVN)
5
+ Test for hash bang Ruby - if no .rb extension
6
+
7
+ Release Version: 0.95 (December 2006) by Pjotr Prins
8
+ Added -R/--recurse switch by Chetan Patil
9
+ Added regression tests for recursion
10
+
11
+ Release Version: 0.94 (December 2006) by Pjotr Prins
12
+ Added support for ClassName.new tags - which point to the
13
+ Class def initialize methods
14
+
15
+ Release Version: 0.93 (August 2006) by Pjotr Prins
16
+ Fixed bug where multiple lines were written to tags file - which
17
+ broke them for vi
18
+ Fixed infinite loop for specific cases
19
+ Added -a switch (append mode)
20
+ Turned warnings off by default (-w switch)
21
+ Included RELEASENOTES in gem
22
+ More regression testing (-a, tags, TAGS)
23
+ Run regression test before making a release
24
+
25
+ Release Version: 0.92 (August 2006) by Pjotr Prins
26
+ Added catching of parse errors
27
+ Fixed exit on 'alias' token error (`parse_alias': undefined method `name')
28
+ Added support for command line arguments with optparse
29
+ Added debug switches (--debug, --debug_tokens)
30
+ Print to stderr on debug
31
+ Added support for alternate tags filename (-f switch)
32
+ Added --quiet switch
33
+ Added regression files to ./test
34
+
35
+ Release Version: 0.91 (July 2006) by Pjotr Prins
36
+ First independent public release on RubyForge
37
+ Depends on irb 0.9
38
+ Wrote install.sh and gem packaging
39
+
40
+ Release Version: 0.9 (2002/07/09) by Keiju ISHITSUKA
41
+ Released as part of irb source tree
42
+
43
+
data/TODO ADDED
@@ -0,0 +1,40 @@
1
+ TODO
2
+
3
+ For version 1.0:
4
+
5
+ - Recognise 'alias :name' tokens
6
+ - include the argument list and an end of line $ pattern (at least the
7
+ first opening parenthesis should be included in the pattern)
8
+ - indicate whether the entry is a c(lass), a m(odule), or a f (method)
9
+ like ctags
10
+
11
+ Later:
12
+
13
+ - Add switch for not following symlinks
14
+ - Fix class Foo::Bar to show as such in the TAGS file
15
+ - Find modules with double colon notation like "BIO::MODULE::IO"
16
+ - Cache class names so classes can be found that lack an initialize
17
+ method
18
+ - Provide - command line switch, allowing for
19
+ find . -name '*.rb' -print | rtags -
20
+
21
+ MUSINGS
22
+
23
+ Apart from adding the - switch at some point in the future it would
24
+ be neat to have smarter tags. For one, if a class has not initialize
25
+ method we would like to jump to the class definition on
26
+ Classname.new. If we were to store the tags we find in memory
27
+ (instead of just writing them out, as is the current behaviour) it
28
+ would be trivial to implement.
29
+
30
+ Also some tokens (alias) and multilines are not handled correctly.
31
+
32
+ Try:
33
+
34
+ cd ./test ruby ../bin/rtags -R
35
+
36
+ and you get
37
+
38
+ Warn: parse error in <./data/report.rb> in line 170, pos 4
39
+
40
+ which is an unrecognised alias.
data/bin/rtags ADDED
@@ -0,0 +1,861 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # rtags is a Ruby replacement for ctags - allowing for name navigation in
4
+ # source code using vim, emacs and others.
5
+ #
6
+ # by Keiju ISHITSUKA and Pjotr Prins
7
+ #
8
+ # LICENSE: RUBY LICENSE - see file LICENSE.TXT
9
+ # INSTALL: see file README
10
+ # RELEASE NOTES: see file RELEASENOTES
11
+
12
+ RTAGS_VERSION='0.99.1 (January 2013)'
13
+
14
+ require 'optparse'
15
+ require 'ostruct'
16
+
17
+ usage = <<USAGE
18
+
19
+ rtags #{RTAGS_VERSION} (Ruby tags) by Keiju ISHITSUKA
20
+ improvements by Pjotr Prins, Chetan Patil, Gaizka Villane, Brenton Fletcher
21
+
22
+ A Ruby tool for using Ruby tags rendering more tags than
23
+ other tools for use with vim or emacs
24
+
25
+ For info see http://rtags.rubyforge.org/
26
+
27
+ usage:
28
+
29
+ rtags [--vi] [-R] filenames
30
+ rtags --help
31
+
32
+ by default creates an emacs tags file. With the --vi switch
33
+ a vim tags file is created instead.
34
+
35
+ USAGE
36
+
37
+
38
+ $options = OpenStruct.new()
39
+ $options.warning_level = 0
40
+ $options.recurse = false
41
+
42
+ OptionParser.new do |opts|
43
+ opts.on_tail("-h", "--help", "Print this message") do
44
+ print(usage)
45
+ print(opts)
46
+ print <<EXAMPLE
47
+
48
+ Examples:
49
+
50
+ rtags *.rb
51
+ rtags -x *.rb
52
+ rtags -R <path>
53
+ rtags --vi -f vim_tags *.rb
54
+ rtags `find ~/src/ -name *.rb|grep -v _darcs`
55
+
56
+ EXAMPLE
57
+ exit()
58
+ end
59
+
60
+ opts.on("-f tagfile", String, "Output to tagfile") do |s|
61
+ $options.tagfile = s
62
+ end
63
+ opts.on("-a", "append mode") do
64
+ $options.tagfile_mode = 'a'
65
+ end
66
+ opts.on("-w level", Integer, "Warning level (default 0)") do |w|
67
+ $options.warning_level = w
68
+ end
69
+ opts.on("--vi", "Use vi type tags (default is emacs)") do
70
+ $options.vi = true
71
+ end
72
+ opts.on("-x", "Print cross reference file to stdout") do
73
+ $options.xref = true
74
+ end
75
+ opts.on("-b", "When using -x, only print base name. E.g., print only 'method' and not '::Module::Class#method'") do
76
+ $options.xref_only_base = true
77
+ end
78
+ opts.on("-B", "When using -x, only print absolute name. E.g., print only '::Module::Class#method' and not 'method'. Inverse of -b") do
79
+ $options.xref_only_abs = true
80
+ end
81
+ opts.on("--quiet", "Quiet mode") do
82
+ $options.quiet = true
83
+ end
84
+ opts.on("--debug", "Debug output to stderr") do
85
+ $options.debug = true
86
+ end
87
+ opts.on("--debug_tokens", "Debug token information to stdout") do
88
+ $options.debug_tokens = true
89
+ end
90
+ opts.on("-R", "--recurse", "Recurse path for .rb files (default '.')") do
91
+ $options.recurse = true
92
+ end
93
+ opts.on("-L file", String, "Read from file a list of file names for which tags should be generated.") do |f|
94
+ $options.files_in_list = f
95
+ end
96
+ end.parse!(ARGV)
97
+
98
+ if $options.tagfile == nil
99
+ if $options.vi
100
+ $options.tagfile = 'tags'
101
+ else
102
+ $options.tagfile = 'TAGS'
103
+ end
104
+ end
105
+ $options.tagfile_mode = 'w' if $options.tagfile_mode == nil
106
+ $options.warning_level = -1 if $options.quiet
107
+ if $options.recurse and ARGV.size == 0
108
+ ARGV.push '.'
109
+ end
110
+
111
+ print "\nrtags.rb #{RTAGS_VERSION} writing to file '#{$options.tagfile}'\n" if (!$options.quiet && !$options.xref)
112
+
113
+ require "e2mmap"
114
+ require "tracer"
115
+
116
+ require "irb/ruby-lex"
117
+ require "irb/ruby-token"
118
+
119
+ class RubyLex
120
+ def identify_string_dvar
121
+ end
122
+ end
123
+
124
+ require "stringio"
125
+
126
+ module RTAGS
127
+ @RCS_ID='-rtags.rb 0.95 -'
128
+
129
+ class RTToken
130
+ def initialize(readed, context, name, token)
131
+ @readed = readed
132
+ @context = context
133
+ @name = name
134
+ @token = token
135
+ end
136
+ attr :readed
137
+ attr :context
138
+ attr :name
139
+ attr :token
140
+
141
+ def line_no
142
+ @token.line_no
143
+ end
144
+
145
+ def seek
146
+ @token.seek
147
+ end
148
+
149
+ def to_s
150
+ "#{def_name} #{abs_name} in #{token.inspect}"
151
+ end
152
+ end
153
+
154
+ class RTModule < RTToken
155
+ def abs_name
156
+ (context || "") + "::" + name
157
+ end
158
+
159
+ def def_name
160
+ "module"
161
+ end
162
+ end
163
+
164
+ class RTClass < RTModule
165
+ def abs_name
166
+ (context || "") + "::" + name
167
+ end
168
+
169
+ def def_name
170
+ "class"
171
+ end
172
+ end
173
+
174
+ class RTSingleClass < RTClass
175
+ def abs_name
176
+ (context || "") + "<<" + name
177
+ end
178
+
179
+ def def_name
180
+ "class"
181
+ end
182
+ end
183
+
184
+ class RTMethod < RTToken
185
+ def abs_name
186
+ (context || "") + "#" + name
187
+ end
188
+
189
+ def def_name
190
+ "method"
191
+ end
192
+ end
193
+
194
+ class RTAlias < RTMethod
195
+ def def_name
196
+ "alias"
197
+ end
198
+ end
199
+
200
+ class RTAttr < RTMethod
201
+ def def_name
202
+ "attr"
203
+ end
204
+ end
205
+
206
+ class RTClassCall < RTMethod
207
+ def abs_name
208
+ (context || "") + "!" + (token.name == name ? name : "#{token.name}(#{name})")
209
+ end
210
+
211
+ def def_name
212
+ "class call"
213
+ end
214
+ end
215
+
216
+ class RTSingleMethod < RTToken
217
+ def abs_name
218
+ (context || "") + "." + name
219
+ end
220
+
221
+ def def_name
222
+ "class method"
223
+ end
224
+ end
225
+
226
+ class RTSingleAlias < RTSingleMethod
227
+ def def_name
228
+ "alias"
229
+ end
230
+ end
231
+
232
+ class RTSingleAttr < RTSingleMethod
233
+ def def_name
234
+ "attr"
235
+ end
236
+ end
237
+
238
+ class RTSingleClassCall < RTSingleMethod
239
+ def abs_name
240
+ (context || "") + ":" + (token.name == name ? name : "#{token.name}(#{name})")
241
+ end
242
+
243
+ def def_name
244
+ "class call"
245
+ end
246
+ end
247
+
248
+ class Parser
249
+ include RubyToken
250
+
251
+ def initialize(file_name)
252
+ @size = 0
253
+ @input_file_name = file_name
254
+ @scanner = RubyLex.new
255
+ @scanner.exception_on_syntax_error = false
256
+ # @scanner.skip_space = true
257
+ # @scanner.readed_auto_clean_up = true
258
+ #parse_statements
259
+ end
260
+
261
+ # display warnings on stderr, depending on the set warning_level
262
+
263
+ def warn s,level=0,token=nil,extra=nil
264
+ if level <= $options.warning_level
265
+ $stderr.print "\nWarn: #{s} in <#{@input_file_name}> "
266
+ if token
267
+ $stderr.print "in line #{token.line_no}, pos #{token.char_no}"
268
+ # $stderr.print "by name <#{token.name}>" if token and token.name
269
+ $stderr.print "\n"
270
+ end
271
+ if $options.debug
272
+ $stderr.print "Token=",token.inspect,"\n" if token
273
+ $stderr.print extra if extra
274
+ end
275
+ end
276
+ end
277
+
278
+ # Scan +@input_file_name+ for tags and yields each tag
279
+
280
+ def scan(&block)
281
+ print "\nParsing #{@input_file_name}..." if (!$options.quiet && !$options.xref)
282
+
283
+ input = StringIO.new(File.read(@input_file_name) + "\n")
284
+ @tokens = []
285
+ @unget_readed = []
286
+ @readed = []
287
+ @scanner.set_input(input)
288
+ parse_statements(&block)
289
+ end
290
+
291
+ # get the next token - fetching it from the temporary +@tokens+
292
+ # stack if it is not empty
293
+
294
+ def get_tk
295
+ if @tokens.empty?
296
+ tk = @scanner.token
297
+ @readed.push @scanner.get_readed
298
+ $stderr.print tk.inspect if $options.debug_tokens
299
+ tk
300
+ else
301
+ @readed.push @unget_readed.shift
302
+ tk = @tokens.shift
303
+ $stderr.print tk.inspect if $options.debug_tokens
304
+ tk
305
+ end
306
+ end
307
+
308
+ # lookahead returning the next token without popping it
309
+ def peek_tk
310
+ unget_tk(tk = get_tk)
311
+ tk
312
+ end
313
+
314
+ # push the token +tk+ back onto the stack
315
+ def unget_tk(tk)
316
+ @tokens.unshift tk
317
+ @unget_readed.unshift @readed.pop
318
+ end
319
+
320
+ def skip_tkspace(skip_nl = true)
321
+ tokens = []
322
+ while ((tk = get_tk).kind_of?(TkSPACE) ||
323
+ (skip_nl && tk.kind_of?(TkNL)))
324
+ tokens.push tk
325
+ end
326
+ unget_tk(tk)
327
+ tokens
328
+ end
329
+
330
+ # returns the actual token string as it was read and
331
+ # sets the read buffer to zero length
332
+ def get_tkreaded
333
+ readed = @readed.join("")
334
+ @readed = []
335
+ readed
336
+ end
337
+
338
+ NORMAL = "::"
339
+ SINGLE = "<<"
340
+
341
+ # The 'grunt' method splits a line into tokens and invokes the
342
+ # basic parsers for class, module, method etc.
343
+
344
+ def parse_statements(context = nil, single = NORMAL, &block)
345
+ begin
346
+ last_seekpos = -1
347
+ nest = 1
348
+ symbeg = false
349
+
350
+ while (tk = get_tk)
351
+ case tk
352
+ when TkCLASS
353
+ parse_class(context, single, tk, &block)
354
+ when TkMODULE
355
+ parse_module(context, single, tk, &block)
356
+ when TkDEF
357
+ nest += 1
358
+ parse_method(context, single, tk, &block)
359
+ when TkALIAS
360
+ parse_alias(context, single, tk, &block)
361
+ when TkCASE,
362
+ TkDO,
363
+ TkFOR,
364
+ TkIF,
365
+ TkUNLESS,
366
+ TkUNTIL,
367
+ TkWHILE,
368
+ TkBEGIN
369
+ nest += 1
370
+ when TkSYMBEG
371
+ symbeg = true
372
+ when TkIDENTIFIER
373
+ parse_identifier(context, single, nest, symbeg, tk, &block)
374
+ symbeg = false
375
+ when TkEND
376
+ return if (nest -= 1) == 0
377
+ end
378
+ begin
379
+ get_tkreaded
380
+ skip_tkspace(false) # don't skip newlines
381
+ # prevent endless loop (tokenizer does not always behave
382
+ # at eof)
383
+ tmp_tk = tk
384
+ seekpos = tmp_tk.seek if tmp_tk and tmp_tk.seek
385
+ if last_seekpos == seekpos
386
+ warn('bailing out early',0,tk)
387
+ return
388
+ end
389
+ last_seekpos = seekpos
390
+ end while peek_tk == TkNL
391
+ # p [@input_file_name, peek_tk]
392
+ end
393
+ rescue
394
+ warn('parse error',0,tk,"#{$!.message}:\n#{$!.backtrace.join("\n")}")
395
+ end
396
+ end
397
+
398
+ # Get the full name of the constant including namespaces
399
+ def parse_full_constant_name(name_token)
400
+ name = name_token.name
401
+ if peek_tk.kind_of? TkCOLON2
402
+ get_tk # skip the ::
403
+ namespaced_name_token = get_tk
404
+ rest = parse_full_constant_name(namespaced_name_token)
405
+ name += '::' + rest unless rest.nil?
406
+ end
407
+
408
+ name
409
+ end
410
+
411
+ def parse_class(context, single, tk, &block)
412
+ skip_tkspace
413
+ case name_t = get_tk
414
+ when TkCONSTANT
415
+ name = parse_full_constant_name(name_t)
416
+ if single == SINGLE
417
+ yield RTSingleClass.new(get_tkreaded, context, name, tk)
418
+ else
419
+ yield RTClass.new(get_tkreaded, context, name, tk)
420
+ end
421
+ parse_statements((context || "") + single + name, &block)
422
+
423
+ when TkLSHFT
424
+ skip_tkspace
425
+ case (name_t2 = get_tk)
426
+ when TkSELF
427
+ parse_statements(context, SINGLE, &block)
428
+ when TkCONSTANT, TkIVAR
429
+ # yield RTSingleClass.new(get_tkreaded, context, name_t2.name, tk)
430
+ parse_statements((context || "") + "::" + name_t2.name,
431
+ SINGLE,
432
+ &block)
433
+ else
434
+ warn('unrecognised token',1,name_t2)
435
+ end
436
+ else
437
+ warn('unrecognised token',1,name_t2)
438
+ end
439
+ end
440
+
441
+ def parse_module(context, single, tk, &block)
442
+ skip_tkspace
443
+ name = get_tk.name
444
+ yield RTModule.new(get_tkreaded, context, name, tk)
445
+ parse_statements((context||"") + single + name, &block)
446
+ end
447
+
448
+ def parse_method(context, single, tk, &block)
449
+ skip_tkspace
450
+ name_t = get_tk
451
+ back_tk = skip_tkspace
452
+
453
+ if (dot = get_tk).kind_of?(TkDOT)
454
+ # tricky tech. Not sure when this gets reached - probably
455
+ # 'static' definitions as part of modules
456
+ @scanner.instance_eval{@lex_state = EXPR_FNAME}
457
+ skip_tkspace
458
+ name_t2 = get_tk
459
+ case name_t
460
+ when TkSELF
461
+ name = name_t2.name
462
+ when TkId
463
+ if context and
464
+ context =~ /^#{name_t.name}$/ || context =~ /::#{name_t.name}$/
465
+ name = name_t2.name
466
+ else
467
+ context = (context || "") + "::" + name_t.name
468
+ name = name_t2.name
469
+ end
470
+ else
471
+ warn('unrecognised token',1,name_t2)
472
+ #break
473
+ end
474
+ yield RTSingleMethod.new(get_tkreaded, context, name, tk)
475
+
476
+ else
477
+ unget_tk dot
478
+ back_tk.reverse_each do |tk|
479
+ unget_tk tk
480
+ end
481
+ name = name_t.name
482
+ # ---- if the method is an initialize make sure the class
483
+ # initiation (with Class.new) points to the tag
484
+ if name=='initialize'
485
+ name = 'new'
486
+ if context and context =~ /::(\S+)$/
487
+ name = $1+'.new'
488
+ end
489
+ end
490
+ if single == SINGLE
491
+ yield RTSingleMethod.new(get_tkreaded, context, name, tk)
492
+ else
493
+ yield RTMethod.new(get_tkreaded, context, name, tk)
494
+ end
495
+ end
496
+ end
497
+
498
+ def parse_alias(context, single, tk, &block)
499
+ skip_tkspace
500
+ if (token = get_tk).is_a? TkSYMBEG
501
+ # Name is in next token
502
+ token = get_tk
503
+ end
504
+
505
+ name = token.name
506
+ if context
507
+ if single == SINGLE
508
+ yield RTSingleAlias.new(get_tkreaded, context, name, tk)
509
+ else
510
+ yield RTAlias.new(get_tkreaded, context, name, tk)
511
+ end
512
+ else
513
+ if single == SINGLE
514
+ yield RTSingleAlias.new(get_tkreaded, "main", name, tk)
515
+ else
516
+ yield RTAlias.new(get_tkreaded, nil, name, tk)
517
+ end
518
+ end
519
+ end
520
+
521
+ def parse_attr(context, single, tk, &block)
522
+ args = parse_symbol_arg(1)
523
+ if args.size > 0
524
+ name = args[0]
525
+ if context
526
+ if single == SINGLE
527
+ yield RTSingleAttr.new(get_tkreaded, context, name, tk)
528
+ else
529
+ yield RTAttr.new(get_tkreaded, context, name, tk)
530
+ end
531
+ else
532
+ if single == SINGLE
533
+ yield RTSingleAttr.new(get_tkreaded, "main", name, tk)
534
+ else
535
+ yield RTAttr.new(get_tkreaded, nil, name, tk)
536
+ end
537
+ end
538
+ else
539
+ warn('token not recognized - next attr arg size == zero',1)
540
+ end
541
+ end
542
+
543
+ def parse_attr_accessor(context, single, tk, &block)
544
+ args = parse_symbol_arg
545
+ readed = get_tkreaded
546
+ for name in args
547
+ if context
548
+ if single == SINGLE
549
+ yield RTSingleAttr.new(readed, context, name, tk)
550
+ else
551
+ yield RTAttr.new(readed, context, name, tk)
552
+ end
553
+ else
554
+ if single == SINGLE
555
+ yield RTSingleAttr.new(readed, "main", name, tk)
556
+ else
557
+ yield RTAttr.new(readed, nil, name, tk)
558
+ end
559
+ end
560
+ end
561
+ end
562
+
563
+ KNOWN_CLASS_METHOD_CALLS = %w(belongs_to has_one has_many has_and_belongs_to_many after_create after_destroy after_find after_initialize after_save after_update after_validation around_create around_destroy around_save around_update before_create before_destroy before_save before_update before_validation)
564
+
565
+ def parse_known_class_method_calls(context, single, tk, &block)
566
+ args = parse_symbol_arg
567
+ readed = get_tkreaded
568
+ (args.empty? ? [tk.name] : args).each do |name|
569
+ if context
570
+ if single == SINGLE
571
+ yield RTSingleClassCall.new(readed, context, name, tk)
572
+ else
573
+ yield RTClassCall.new(readed, context, name, tk)
574
+ end
575
+ else
576
+ if single == SINGLE
577
+ yield RTSingleClassCall.new(readed, "main", name, tk)
578
+ else
579
+ yield RTClassCall.new(readed, nil, name, tk)
580
+ end
581
+ end
582
+ end
583
+ end
584
+
585
+ def parse_identifier(context, single, nest, symbeg, tk, &block)
586
+ case tk.name
587
+ when "attr"
588
+ parse_attr(context, single, tk, &block)
589
+ when /^attr_(reader|writer|accessor)$/
590
+ parse_attr_accessor(context, single, tk, &block)
591
+ else
592
+ if !context.nil? && nest == 1 && !symbeg
593
+ parse_known_class_method_calls(context, single, tk, &block)
594
+ end
595
+ end
596
+ end
597
+
598
+
599
+
600
+ def parse_symbol_arg(no = nil)
601
+ args = []
602
+ skip_tkspace
603
+ case (tk = get_tk)
604
+ when TkLPAREN
605
+ loop do
606
+ skip_tkspace
607
+ if tk1 = parse_symbol_in_arg
608
+ args.push tk1
609
+ break if no and args.size >= no
610
+ end
611
+
612
+ skip_tkspace
613
+ case tk2 = get_tk
614
+ when TkRPAREN
615
+ break
616
+ when TkCOMMA
617
+ else
618
+ warn('token not recognized in funargs',1,tk)
619
+ break
620
+ end
621
+ end
622
+ else
623
+ unget_tk tk
624
+
625
+ loop do
626
+ skip_tkspace(false)
627
+ case (tk1 = get_tk)
628
+ when TkCOMMA
629
+ when TkDO, TkNL
630
+ unget_tk tk1
631
+ break
632
+ else
633
+ skip_tkspace
634
+ unget_tk tk1
635
+ if tk = parse_symbol_in_arg
636
+ args.push tk
637
+ break if no and args.size >= no
638
+ else
639
+ warn('token not recognized in funargs',1,tk1)
640
+
641
+ unless args.empty?
642
+ while (tk2 = get_tk) && !tk2.is_a?(TkNL) && !tk2.is_a?(TkDO)
643
+ end
644
+ unget_tk tk2
645
+ return args
646
+ end
647
+ return args
648
+ end
649
+ end
650
+ end
651
+ end
652
+ args
653
+ end
654
+
655
+ def parse_symbol_in_arg
656
+ case (tk = get_tk)
657
+ when TkSYMBEG
658
+ case (tk1 = get_tk)
659
+ when TkIDENTIFIER
660
+ tokens = skip_tkspace(false)
661
+ if (tk2 = get_tk).is_a?(TkASSIGN)
662
+ unget_tk tk2
663
+ tokens.each { |tk3| unget_tk tk3 }
664
+ unget_tk tk1
665
+ unget_tk tk
666
+ warn('token not recognized; next ',1,tk)
667
+ nil
668
+ else
669
+ tokens.each { |tk3| unget_tk tk3 }
670
+ tk1.name
671
+ end
672
+ when TkCONSTANT, TkFID
673
+ tk1.name
674
+ else
675
+ unget_tk tk1
676
+ warn('token not recognized; next SYMBEG ',1,tk1)
677
+ nil
678
+ end
679
+ when TkSTRING
680
+ eval @readed[-1]
681
+ else
682
+ unget_tk tk
683
+ warn('token not recognized; next SYMBEG and STRING ',1,tk) if $options.debug
684
+ nil
685
+ end
686
+ end
687
+ end
688
+
689
+ module Filter
690
+
691
+ # Test for boring repository directories that should be skipped
692
+ def Filter::skipdir name
693
+ if name =~ /\/(\.svn|\.hg|_darcs|CVS|\.git)/
694
+ print "\nSkipping boring directory #{name}"
695
+ return true
696
+ end
697
+ false
698
+ end
699
+
700
+ # Test whether this is a Ruby file
701
+ def Filter::skipfile name
702
+ if name =~ /.rb$/i
703
+ return false
704
+ end
705
+ # OK - test for magic hash bang
706
+ firstline = File.new(name, :encoding => "BINARY").gets
707
+ return false if firstline =~ /^#\!/ and firstline =~ /ruby/i
708
+ true
709
+ end
710
+
711
+ end
712
+
713
+ class TAGS
714
+ def initialize(files)
715
+ if $options.recurse
716
+ @files = []
717
+ recurse = lambda do |fname|
718
+ if File.directory? fname and not Filter::skipdir(fname)
719
+ Dir.entries(fname).select {|f| f !~ /^\.(?:\.|\w+)?$/ }.map {|f| fname+'/'+f }.each(&recurse)
720
+ else
721
+ # is a file
722
+ if File.file?(fname) and not Filter::skipfile(fname)
723
+ # @files.push(fname) if fname =~ /.rb$/i
724
+ @files.push(fname)
725
+ end
726
+ end
727
+ end
728
+ files.each(&recurse)
729
+ else
730
+ @files = files
731
+ end
732
+ end
733
+ end
734
+
735
+ class EMACS_TAGS < TAGS
736
+ # Create the tags file in emacs mode
737
+ def shipout
738
+ open($options.tagfile, $options.tagfile_mode) do |out|
739
+ @output = out
740
+ @files.each do |fn|
741
+ if File.directory? fn
742
+ puts "\nWarning: #{fn} is a directory - SKIPPING. Specify --recurse option to recurse into directories.\n"
743
+ next
744
+ end
745
+ output = []
746
+ size = 0
747
+
748
+ $stderr.printf "--\n-- parse file: %s\n", fn if $options.debug
749
+ parser = Parser.new(fn)
750
+ parser.scan do |tk|
751
+ $stderr.print tk, "\n" if $options.debug
752
+ line = tk.readed.split(/\n/)[0]
753
+ item = sprintf("%s\C-?%s\C-A%d,%s\n",
754
+ line,
755
+ tk.abs_name,
756
+ tk.line_no,
757
+ tk.seek)
758
+ output.push item
759
+ size += item.size
760
+ end
761
+ @output.print "\C-L\n#{fn},#{size}\n"
762
+ @output.print output.join
763
+ end
764
+ end
765
+ end
766
+ end
767
+
768
+ class VI_TAGS < TAGS
769
+ # Create the tags file in vi(m) mode
770
+ def shipout
771
+ output = []
772
+ @files.each do |fn|
773
+ if File.directory? fn
774
+ puts "\nWarning: #{fn} is a directory - SKIPPING. Specify --recurse option to recurse into directories.\n"
775
+ next
776
+ end
777
+
778
+ $stderr.printf "--\n-- parse file: %s\n", fn if $options.debug
779
+ parser = Parser.new(fn)
780
+ parser.scan do |tk|
781
+ $stderr.print tk, "\n" if $options.debug
782
+ line = tk.readed.split(/\n/)[0]
783
+ output.push sprintf("%s\t%s\t/^%s/\n",
784
+ tk.name,
785
+ fn,
786
+ line)
787
+ output.push sprintf("%s\t%s\t/^%s/\n",
788
+ tk.abs_name,
789
+ fn,
790
+ line)
791
+ end
792
+ end
793
+ # sort entries
794
+ open($options.tagfile, $options.tagfile_mode) do |out|
795
+ out << output.sort!.join
796
+ end
797
+ end
798
+ end
799
+
800
+ class XREF_TAGS < TAGS
801
+ # Print cross ref file (like ctags -x)
802
+ def shipout
803
+ output = []
804
+ @files.each do |fn|
805
+ if File.directory? fn
806
+ puts "\nWarning: #{fn} is a directory - SKIPPING. Specify --recurse option to recurse into directories.\n"
807
+ next
808
+ end
809
+
810
+ size = 0
811
+
812
+ $stderr.printf "--\n-- parse file: %s\n", fn if $options.debug
813
+ parser = Parser.new(fn)
814
+ parser.scan do |tk|
815
+ $stderr.print tk, "\n" if $options.debug
816
+ line = tk.readed.split(/\n/)[0]
817
+ unless $options.xref_only_abs
818
+ output.push sprintf("%-16s %-10s %4d %-16s %s\n",
819
+ tk.name.gsub(/^::/, "").gsub(" ", "_"),
820
+ tk.def_name,
821
+ tk.line_no,
822
+ fn,
823
+ line)
824
+ end
825
+
826
+ unless $options.xref_only_base
827
+ output.push sprintf("%-16s %-10s %4d %-16s %s\n",
828
+ tk.abs_name.gsub(/^::/, "").gsub(" ", "_"),
829
+ tk.def_name,
830
+ tk.line_no,
831
+ fn,
832
+ line)
833
+ end
834
+ end
835
+ end
836
+ puts output.join
837
+ end
838
+ end
839
+
840
+
841
+ end
842
+
843
+ if (!$options.files_in_list && ARGV.size == 0) or ARGV[0] == '--help'
844
+ ARGV.shift
845
+ print usage
846
+ exit 1
847
+ end
848
+
849
+ files = ARGV
850
+ files += File.readlines($options.files_in_list).map { |f| f.chomp } if $options.files_in_list
851
+
852
+ if $options.vi
853
+ tags = RTAGS::VI_TAGS.new(files)
854
+ elsif $options.xref
855
+ tags = RTAGS::XREF_TAGS.new(files)
856
+ else
857
+ tags = RTAGS::EMACS_TAGS.new(files)
858
+ end
859
+ tags.shipout
860
+ print "\n" if !$options.xref
861
+ $stderr.print "\nEnd - tagfile generated\n" if (!$options.quiet && !$options.xref)
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bloopletech-rtags
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.99.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pjotr Prins, Keiju Ishitsuka
9
+ autorequire: irb
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: This is the original commit of the rtags source code as written by Keiju
15
+ ISHITSUKA as part of the irb project. Now irb has moved into the main Ruby source
16
+ tree rtags has become an independent project
17
+ email: pjotr.public02@thebird.nl
18
+ executables:
19
+ - rtags
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - RELEASENOTES
24
+ - TODO
25
+ - README
26
+ - LICENSE.txt
27
+ - bin/rtags
28
+ homepage: http://rtags.rubyforge.org
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: 1.8.1
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project: rtags
48
+ rubygems_version: 1.8.24
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: rtags is a Ruby replacement for ctags - allowing for name navigation in source
52
+ code using vim, emacs and others
53
+ test_files: []
54
+ has_rdoc: false