ripper-tags 0.3.5 → 0.4.0
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.
- checksums.yaml +4 -4
- data/lib/ripper-tags.rb +65 -14
- data/lib/ripper-tags/data_reader.rb +21 -8
- data/lib/ripper-tags/default_formatter.rb +16 -6
- data/lib/ripper-tags/parser.rb +108 -5
- data/lib/ripper-tags/vim_formatter.rb +18 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52c268f393b07f8fa528f4886a5c5c3d39fa712f
|
4
|
+
data.tar.gz: 7ea8519875252ee44f554ad3021d02a29e482970
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed66eb27100243fe6766f609f2ac3aa6f9f556a01f7c3f995fb663e973ef36fc7ab35e46eadf64e448ee75d133c96aa6177fa8a508548ab27fdce7268ade9ca0
|
7
|
+
data.tar.gz: 504ecdbdbb6315116d0d12d70827597c1f565fe08034d0201498ac5d878888c9e96bb7e7c750db79fd3f95798508493f1bdf9f0c00da9c07129eb3c84863aba7
|
data/lib/ripper-tags.rb
CHANGED
@@ -9,7 +9,7 @@ require 'ripper-tags/vim_formatter'
|
|
9
9
|
require 'ripper-tags/json_formatter'
|
10
10
|
|
11
11
|
module RipperTags
|
12
|
-
def self.version() "0.
|
12
|
+
def self.version() "0.4.0" end
|
13
13
|
|
14
14
|
FatalError = Class.new(RuntimeError)
|
15
15
|
|
@@ -26,11 +26,51 @@ module RipperTags
|
|
26
26
|
:files => %w[.],
|
27
27
|
:recursive => false,
|
28
28
|
:exclude => %w[.git],
|
29
|
-
:all_files => false
|
29
|
+
:all_files => false,
|
30
|
+
:fields => Set.new,
|
31
|
+
:excmd => nil,
|
32
|
+
:input_file => nil
|
33
|
+
end
|
34
|
+
|
35
|
+
class ForgivingOptionParser < OptionParser
|
36
|
+
attr_accessor :ignore_unsupported_options
|
37
|
+
|
38
|
+
def parse(argv)
|
39
|
+
argv = argv.dup
|
40
|
+
exceptions = []
|
41
|
+
remaining = []
|
42
|
+
|
43
|
+
while argv.size > 0
|
44
|
+
begin
|
45
|
+
remaining = super(argv)
|
46
|
+
break
|
47
|
+
rescue OptionParser::InvalidOption => err
|
48
|
+
argv -= err.args
|
49
|
+
exceptions << err
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if exceptions.any? && !ignore_unsupported_options
|
54
|
+
raise exceptions.first
|
55
|
+
end
|
56
|
+
|
57
|
+
remaining
|
58
|
+
end
|
30
59
|
end
|
31
60
|
|
32
61
|
def self.option_parser(options)
|
33
|
-
|
62
|
+
flags_string_to_set = lambda do |string, set|
|
63
|
+
flags = string.split("")
|
64
|
+
operation = :add
|
65
|
+
if flags[0] == "+" || flags[0] == "-"
|
66
|
+
operation = :delete if flags.shift == "-"
|
67
|
+
else
|
68
|
+
set.clear
|
69
|
+
end
|
70
|
+
flags.each { |f| set.send(operation, f) }
|
71
|
+
end
|
72
|
+
|
73
|
+
ForgivingOptionParser.new do |opts|
|
34
74
|
opts.banner = "Usage: #{opts.program_name} [options] FILES..."
|
35
75
|
opts.version = version
|
36
76
|
|
@@ -43,6 +83,9 @@ module RipperTags
|
|
43
83
|
opts.on("--tag-relative[=OPTIONAL]", "Make file paths relative to the directory of the tag file") do |value|
|
44
84
|
options.tag_relative = value != "no"
|
45
85
|
end
|
86
|
+
opts.on("-L", "--input-file=FILE", "File to read paths to process trom (use `-` for stdin)") do |file|
|
87
|
+
options.input_file = file
|
88
|
+
end
|
46
89
|
opts.on("-R", "--recursive", "Descend recursively into subdirectories") do
|
47
90
|
options.recursive = true
|
48
91
|
end
|
@@ -53,7 +96,16 @@ module RipperTags
|
|
53
96
|
options.exclude << pattern
|
54
97
|
end
|
55
98
|
end
|
56
|
-
opts.on("--
|
99
|
+
opts.on("--excmd=number", "Use EX number command to locate tags.") do |excmd|
|
100
|
+
options.excmd = excmd
|
101
|
+
end
|
102
|
+
opts.on("-n", "Equivalent to --excmd=number.") do
|
103
|
+
options.excmd = "number"
|
104
|
+
end
|
105
|
+
opts.on("--fields=+n", "Include line number information in the tag") do |flags|
|
106
|
+
flags_string_to_set.call(flags, options.fields)
|
107
|
+
end
|
108
|
+
opts.on("--all-files", "Parse all files in recursive mode (default: parse `*.rb' files)") do
|
57
109
|
options.all_files = true
|
58
110
|
end
|
59
111
|
|
@@ -66,14 +118,7 @@ module RipperTags
|
|
66
118
|
options.format = "emacs"
|
67
119
|
end
|
68
120
|
opts.on("--extra=FLAGS", "Specify extra flags for the formatter") do |flags|
|
69
|
-
flags
|
70
|
-
operation = :add
|
71
|
-
if flags[0] == "+" || flags[0] == "-"
|
72
|
-
operation = :delete if flags.shift == "-"
|
73
|
-
else
|
74
|
-
options.extra_flags.clear
|
75
|
-
end
|
76
|
-
flags.each { |f| options.extra_flags.send(operation, f) }
|
121
|
+
flags_string_to_set.call(flags, options.extra_flags)
|
77
122
|
end
|
78
123
|
|
79
124
|
opts.separator ""
|
@@ -106,6 +151,9 @@ module RipperTags
|
|
106
151
|
exit 1
|
107
152
|
end
|
108
153
|
end
|
154
|
+
opts.on_tail("--ignore-unsupported-options", "Don't fail when unsupported options given, just skip them") do
|
155
|
+
opts.ignore_unsupported_options = true
|
156
|
+
end
|
109
157
|
opts.on_tail("-v", "--version", "Print version information") do
|
110
158
|
puts opts.ver
|
111
159
|
exit
|
@@ -118,14 +166,17 @@ module RipperTags
|
|
118
166
|
def self.process_args(argv, run = method(:run))
|
119
167
|
option_parser(default_options) do |optparse, options|
|
120
168
|
file_list = optparse.parse(argv)
|
169
|
+
|
121
170
|
if !file_list.empty?
|
122
171
|
options.files = file_list
|
123
|
-
elsif !options.recursive
|
124
|
-
raise OptionParser::InvalidOption, "needs either a list of files or `-R' flag"
|
172
|
+
elsif !(options.recursive || options.input_file)
|
173
|
+
raise OptionParser::InvalidOption, "needs either a list of files, `-L`, or `-R' flag"
|
125
174
|
end
|
175
|
+
|
126
176
|
options.tag_file_name ||= options.format == 'emacs' ? './TAGS' : './tags'
|
127
177
|
options.format ||= File.basename(options.tag_file_name) == 'TAGS' ? 'emacs' : 'vim'
|
128
178
|
options.tag_relative = options.format == "emacs" if options.tag_relative.nil?
|
179
|
+
|
129
180
|
return run.call(options)
|
130
181
|
end
|
131
182
|
end
|
@@ -49,8 +49,8 @@ module RipperTags
|
|
49
49
|
file.end_with?(RUBY_EXT)
|
50
50
|
end
|
51
51
|
|
52
|
-
def include_file?(file)
|
53
|
-
(options.all_files || ruby_file?(file)) && !exclude_file?(file)
|
52
|
+
def include_file?(file, depth)
|
53
|
+
(depth == 0 || options.all_files || ruby_file?(file)) && !exclude_file?(file)
|
54
54
|
end
|
55
55
|
|
56
56
|
def resolve_file(file, depth = 0, &block)
|
@@ -66,8 +66,8 @@ module RipperTags
|
|
66
66
|
end
|
67
67
|
elsif depth > 0 || File.exist?(file)
|
68
68
|
file = clean_path(file) if depth == 0
|
69
|
-
yield file if include_file?(file)
|
70
|
-
|
69
|
+
yield file if include_file?(file, depth)
|
70
|
+
else
|
71
71
|
$stderr.puts "%s: %p: no such file or directory" % [
|
72
72
|
File.basename($0),
|
73
73
|
file
|
@@ -81,19 +81,32 @@ module RipperTags
|
|
81
81
|
|
82
82
|
def each_file(&block)
|
83
83
|
return to_enum(__method__) unless block_given?
|
84
|
-
|
84
|
+
each_input_file do |file|
|
85
85
|
resolve_file(file, &block)
|
86
86
|
end
|
87
87
|
end
|
88
|
+
|
89
|
+
def each_input_file(&block)
|
90
|
+
if options.input_file
|
91
|
+
io = options.input_file == "-" ? $stdin : File.new(options.input_file, DataReader::READ_MODE)
|
92
|
+
begin
|
93
|
+
io.each_line { |line| yield line.chomp }
|
94
|
+
ensure
|
95
|
+
io.close
|
96
|
+
end
|
97
|
+
else
|
98
|
+
options.files.each(&block)
|
99
|
+
end
|
100
|
+
end
|
88
101
|
end
|
89
102
|
|
90
103
|
class DataReader
|
91
104
|
attr_reader :options
|
92
|
-
|
105
|
+
|
106
|
+
READ_MODE = 'r:utf-8'
|
93
107
|
|
94
108
|
def initialize(options)
|
95
109
|
@options = options
|
96
|
-
@read_mode = defined?(::Encoding) ? 'r:utf-8' : 'r'
|
97
110
|
end
|
98
111
|
|
99
112
|
def file_finder
|
@@ -101,7 +114,7 @@ module RipperTags
|
|
101
114
|
end
|
102
115
|
|
103
116
|
def read_file(filename)
|
104
|
-
str = File.open(filename,
|
117
|
+
str = File.open(filename, READ_MODE) {|f| f.read }
|
105
118
|
normalize_encoding(str)
|
106
119
|
end
|
107
120
|
|
@@ -9,11 +9,15 @@ module RipperTags
|
|
9
9
|
|
10
10
|
def initialize(options)
|
11
11
|
@options = options
|
12
|
+
check_supported_flags(@options.extra_flags, supported_flags)
|
13
|
+
check_supported_flags(@options.fields, supported_fields)
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
def check_supported_flags(set, supported)
|
17
|
+
if set
|
18
|
+
unsupported = set - supported.to_set
|
15
19
|
if unsupported.any?
|
16
|
-
raise FatalError, "these
|
20
|
+
raise FatalError, "these fields are not supported in the '%s' format: %s" % [
|
17
21
|
options.format,
|
18
22
|
unsupported.to_a.join(", ")
|
19
23
|
]
|
@@ -27,6 +31,12 @@ module RipperTags
|
|
27
31
|
options.extra_flags && options.extra_flags.include?(flag)
|
28
32
|
end
|
29
33
|
|
34
|
+
def supported_fields() [] end
|
35
|
+
|
36
|
+
def field?(field)
|
37
|
+
options.fields && options.fields.include?(field)
|
38
|
+
end
|
39
|
+
|
30
40
|
def stdout?
|
31
41
|
'-' == options.tag_file_name
|
32
42
|
end
|
@@ -35,9 +45,9 @@ module RipperTags
|
|
35
45
|
if stdout?
|
36
46
|
begin
|
37
47
|
yield $stdout
|
38
|
-
|
39
|
-
|
40
|
-
|
48
|
+
rescue Errno::EINVAL
|
49
|
+
raise BrokenPipe
|
50
|
+
end
|
41
51
|
else
|
42
52
|
File.open(options.tag_file_name, 'w+') do |outfile|
|
43
53
|
yield outfile
|
data/lib/ripper-tags/parser.rb
CHANGED
@@ -71,8 +71,16 @@ class Parser < Ripper
|
|
71
71
|
"has_one", "has_many",
|
72
72
|
"belongs_to", "has_and_belongs_to_many",
|
73
73
|
"scope", "named_scope",
|
74
|
+
"public_class_method", "private_class_method",
|
75
|
+
"public", "protected", "private",
|
74
76
|
/^attr_(accessor|reader|writer)$/
|
75
77
|
on_method_add_arg([:fcall, name], args[0])
|
78
|
+
when "delegate"
|
79
|
+
on_delegate(*args[0][1..-1])
|
80
|
+
when "def_delegator", "def_instance_delegator"
|
81
|
+
on_def_delegator(*args[0][1..-1])
|
82
|
+
when "def_delegators", "def_instance_delegators"
|
83
|
+
on_def_delegators(*args[0][1..-1])
|
76
84
|
end
|
77
85
|
end
|
78
86
|
def on_bodystmt(*args)
|
@@ -95,11 +103,38 @@ class Parser < Ripper
|
|
95
103
|
end
|
96
104
|
end
|
97
105
|
|
106
|
+
def on_array(args)
|
107
|
+
if args.is_a?(Array) && args[0] == :args
|
108
|
+
args[1..-1]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def on_hash(args)
|
113
|
+
return unless args
|
114
|
+
|
115
|
+
args.select { |arg| arg.is_a?(Array) && arg[0] == :assoc }.map { |_assoc, k, _v| k }
|
116
|
+
end
|
117
|
+
|
98
118
|
undef on_tstring_content
|
99
119
|
def on_tstring_content(str)
|
100
120
|
str
|
101
121
|
end
|
102
122
|
|
123
|
+
def on_string_add(*args)
|
124
|
+
[args[1], lineno]
|
125
|
+
end
|
126
|
+
|
127
|
+
def on_string_embexpr(*)
|
128
|
+
:string_embexpr
|
129
|
+
end
|
130
|
+
def on_string_dvar(*)
|
131
|
+
:string_embexpr
|
132
|
+
end
|
133
|
+
def on_string_literal(*args)
|
134
|
+
args = args.flatten
|
135
|
+
args unless args.include?(:string_embexpr)
|
136
|
+
end
|
137
|
+
|
103
138
|
def on_xstring_add(first, arg)
|
104
139
|
arg if first.nil?
|
105
140
|
end
|
@@ -109,7 +144,7 @@ class Parser < Ripper
|
|
109
144
|
end
|
110
145
|
|
111
146
|
def on_vcall(name)
|
112
|
-
[name[0].to_sym] if name[0].to_s =~ /^(private|protected|public)$/
|
147
|
+
[name[0].to_sym] if name[0].to_s =~ /^(private|protected|public|private_class_method|public_class_method)$/
|
113
148
|
end
|
114
149
|
|
115
150
|
def on_call(lhs, op, rhs)
|
@@ -136,6 +171,18 @@ class Parser < Ripper
|
|
136
171
|
[:alias, args[1][0], args[2][0], line] if args[1] && args[2]
|
137
172
|
when "define_method"
|
138
173
|
[:def, args[1][0], line]
|
174
|
+
when "public_class_method", "private_class_method", "private", "public", "protected"
|
175
|
+
access = name.sub("_class_method", "")
|
176
|
+
|
177
|
+
if args[1][1] == 'self'
|
178
|
+
klass = 'self'
|
179
|
+
method_name = args[1][2]
|
180
|
+
else
|
181
|
+
klass = nil
|
182
|
+
method_name = args[1][1]
|
183
|
+
end
|
184
|
+
|
185
|
+
[:def_with_access, klass, method_name, access, line]
|
139
186
|
when "scope", "named_scope"
|
140
187
|
[:rails_def, :scope, args[1][0], line]
|
141
188
|
when /^attr_(accessor|reader|writer)$/
|
@@ -218,6 +265,43 @@ class Parser < Ripper
|
|
218
265
|
super
|
219
266
|
end
|
220
267
|
end
|
268
|
+
|
269
|
+
# Otherwise hashes and keyword arguments turn into a list of their keys only
|
270
|
+
def on_assoc_new(key, value)
|
271
|
+
[:assoc, key, value]
|
272
|
+
end
|
273
|
+
|
274
|
+
def on_delegate(*args)
|
275
|
+
method_names = args.select { |arg| arg.first.is_a? String }
|
276
|
+
options = args.select { |arg| arg.first.is_a?(Array) && arg.first.first == :assoc }.flatten(1)
|
277
|
+
options = Hash[options.map { |_assoc, key, val| [key.first, val.first] }]
|
278
|
+
|
279
|
+
target = options["to:"] || options["to"] # When using hashrocket syntax there is no ':'
|
280
|
+
prefix = options["prefix:"] || options["prefix"]
|
281
|
+
method_prefix = if prefix.is_a?(Array) && prefix.first == "true"
|
282
|
+
"#{target}_"
|
283
|
+
elsif prefix.is_a? String
|
284
|
+
"#{prefix}_"
|
285
|
+
else
|
286
|
+
""
|
287
|
+
end
|
288
|
+
|
289
|
+
method_names.map do |name, lineno|
|
290
|
+
[:def, "#{method_prefix}#{name}", lineno]
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def on_def_delegator(*args)
|
295
|
+
name, lineno = args.last
|
296
|
+
[:def, name, lineno]
|
297
|
+
end
|
298
|
+
|
299
|
+
def on_def_delegators(*args)
|
300
|
+
_target, *names = args
|
301
|
+
names.map do |name, lineno|
|
302
|
+
[:def, name, lineno]
|
303
|
+
end
|
304
|
+
end
|
221
305
|
end
|
222
306
|
|
223
307
|
class Visitor
|
@@ -254,7 +338,10 @@ end
|
|
254
338
|
sexp.each{ |child| process(child) }
|
255
339
|
when Symbol
|
256
340
|
name, *args = sexp
|
257
|
-
|
341
|
+
name = name.to_s
|
342
|
+
if name.index("@") != 0 && name.index("-@") != 0
|
343
|
+
__send__("on_#{name}", *args)
|
344
|
+
end
|
258
345
|
when String, nil
|
259
346
|
# nothing
|
260
347
|
end
|
@@ -297,9 +384,11 @@ end
|
|
297
384
|
on_module_or_class(:class, name, superclass, *body)
|
298
385
|
end
|
299
386
|
|
300
|
-
def on_private()
|
301
|
-
def on_protected()
|
302
|
-
def on_public()
|
387
|
+
def on_private() @current_access = 'private' end
|
388
|
+
def on_protected() @current_access = 'protected' end
|
389
|
+
def on_public() @current_access = 'public' end
|
390
|
+
def on_private_class_method() @current_access = 'private' end
|
391
|
+
def on_public_class_method() @current_access = 'public' end
|
303
392
|
|
304
393
|
# Ripper trips up on keyword arguments in pre-2.1 Ruby and supplies extra
|
305
394
|
# arguments that we just ignore here
|
@@ -320,6 +409,8 @@ end
|
|
320
409
|
namespace = namespace + parts
|
321
410
|
end
|
322
411
|
|
412
|
+
process(rhs)
|
413
|
+
|
323
414
|
emit_tag :constant, line,
|
324
415
|
:name => name,
|
325
416
|
:full_name => (namespace + [name]).join('::'),
|
@@ -354,6 +445,18 @@ end
|
|
354
445
|
:class => ns.join('::')
|
355
446
|
end
|
356
447
|
|
448
|
+
def on_def_with_access(klass, name, access, line)
|
449
|
+
ns = (@namespace.empty? ? 'Object' : @namespace.join('::'))
|
450
|
+
singleton = @is_singleton || klass == 'self'
|
451
|
+
kind = singleton ? 'singleton method' : 'method'
|
452
|
+
|
453
|
+
emit_tag kind, line,
|
454
|
+
:name => name,
|
455
|
+
:full_name => "#{ns}#{singleton ? '.' : '#'}#{name}",
|
456
|
+
:class => ns,
|
457
|
+
:access => access
|
458
|
+
end
|
459
|
+
|
357
460
|
def on_rails_def(kind, name, line)
|
358
461
|
ns = (@namespace.empty?? 'Object' : @namespace.join('::'))
|
359
462
|
|
@@ -3,6 +3,7 @@ require 'ripper-tags/default_formatter'
|
|
3
3
|
module RipperTags
|
4
4
|
class VimFormatter < DefaultFormatter
|
5
5
|
def supported_flags() ['q'] end
|
6
|
+
def supported_fields() ['n'] end
|
6
7
|
|
7
8
|
def include_qualified_names?
|
8
9
|
return @include_qualified_names if defined? @include_qualified_names
|
@@ -39,8 +40,12 @@ module RipperTags
|
|
39
40
|
const.to_s.gsub('::', '.')
|
40
41
|
end
|
41
42
|
|
42
|
-
def
|
43
|
-
|
43
|
+
def display_excmd_info(tag)
|
44
|
+
if options.excmd == "number"
|
45
|
+
"%d;\"" % tag.fetch(:line)
|
46
|
+
else
|
47
|
+
"/^%s$/;\"" % tag.fetch(:pattern).to_s.gsub('\\','\\\\\\\\').gsub('/','\\/')
|
48
|
+
end
|
44
49
|
end
|
45
50
|
|
46
51
|
def display_class(tag)
|
@@ -59,6 +64,14 @@ module RipperTags
|
|
59
64
|
end
|
60
65
|
end
|
61
66
|
|
67
|
+
def display_line_number(tag)
|
68
|
+
if field?('n') && tag[:line]
|
69
|
+
"\tline:%s" % tag[:line]
|
70
|
+
else
|
71
|
+
""
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
62
75
|
def display_kind(tag)
|
63
76
|
case tag.fetch(:kind)
|
64
77
|
when 'method' then 'f'
|
@@ -71,11 +84,12 @@ module RipperTags
|
|
71
84
|
end
|
72
85
|
|
73
86
|
def format(tag, name_field = :name)
|
74
|
-
"%s\t%s\t
|
87
|
+
"%s\t%s\t%s\t%s%s%s%s" % [
|
75
88
|
tag.fetch(name_field),
|
76
89
|
relative_path(tag),
|
77
|
-
|
90
|
+
display_excmd_info(tag),
|
78
91
|
display_kind(tag),
|
92
|
+
display_line_number(tag),
|
79
93
|
name_field == :full_name ? nil : display_class(tag),
|
80
94
|
display_inheritance(tag),
|
81
95
|
]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ripper-tags
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aman Gupta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: fast, accurate ctags generator for ruby source code using Ripper
|
14
14
|
email:
|
@@ -40,7 +40,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
43
|
+
version: '1.9'
|
44
44
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - ">="
|