bloopletech-rtags 0.99.1

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.
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