starscope 0.1.10 → 1.0.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.
- data/.travis.yml +1 -2
- data/CHANGELOG.md +27 -2
- data/Gemfile.lock +8 -8
- data/README.md +5 -8
- data/bin/starscope +98 -62
- data/lib/starscope/db.rb +176 -143
- data/lib/starscope/langs/coffeescript.rb +12 -0
- data/lib/starscope/langs/go.rb +25 -21
- data/lib/starscope/langs/lua.rb +12 -0
- data/lib/starscope/langs/ruby.rb +16 -24
- data/lib/starscope/matcher.rb +44 -0
- data/lib/starscope/output.rb +41 -0
- data/lib/starscope/record.rb +88 -0
- data/lib/starscope/version.rb +1 -1
- data/starscope.gemspec +1 -1
- data/test/files/sample_golang.go +19 -0
- data/test/lib/test_db.rb +80 -16
- data/test/lib/test_golang.rb +16 -13
- data/test/lib/test_matcher.rb +34 -0
- data/test/lib/test_record.rb +20 -0
- data/test/lib/test_ruby.rb +12 -12
- data/test/lib/test_starscope.rb +33 -0
- metadata +16 -8
- data/lib/starscope/datum.rb +0 -91
- data/test/lib/test_version.rb +0 -9
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,33 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
v1.0.0 (trunk)
|
5
|
+
--------------------
|
6
|
+
|
7
|
+
New Features:
|
8
|
+
* Preliminary export of a few advanced ctags annotations
|
9
|
+
* New -x flag to exclude files from scan (such as compiled .o files)
|
10
|
+
* New --verbose flag for additional output
|
11
|
+
|
12
|
+
Bug Fixes:
|
13
|
+
* Correctly write out migrated databases
|
14
|
+
* Be compatible with ruby 1.8 everywhere
|
15
|
+
* Fix golang parsing untyped "var" declarations
|
16
|
+
* Fix golang parsing multi-line literals
|
17
|
+
* Record assignments to ruby constants as definitions
|
18
|
+
* Fix exporting to cscope when scanned files contain invalid unicode
|
19
|
+
|
20
|
+
Improvements:
|
21
|
+
* Faster file-type matching
|
22
|
+
* Reworked option flags:
|
23
|
+
* Merged -r and -w into -f
|
24
|
+
* Split -n into --no-read, --no-write, --no-update
|
25
|
+
* New, more flexible database format
|
26
|
+
* Substantially improved searching/matching logic
|
27
|
+
* Miscellanious others via updated dependencies
|
28
|
+
|
29
|
+
v0.1.10 (2014-02-24)
|
30
|
+
--------------------
|
6
31
|
|
7
32
|
Improvements:
|
8
33
|
* Import new ruby parser version and make necessary changes so that StarScope
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
starscope (0.
|
5
|
-
oj (~> 2.
|
4
|
+
starscope (1.0.0)
|
5
|
+
oj (~> 2.7)
|
6
6
|
parser (~> 2.1)
|
7
7
|
ruby-progressbar (~> 1.4)
|
8
8
|
|
@@ -12,18 +12,18 @@ GEM
|
|
12
12
|
ast (1.1.0)
|
13
13
|
coderay (1.1.0)
|
14
14
|
method_source (0.8.2)
|
15
|
-
minitest (5.
|
16
|
-
oj (2.
|
17
|
-
parser (2.1.
|
15
|
+
minitest (5.3.3)
|
16
|
+
oj (2.7.3)
|
17
|
+
parser (2.1.7)
|
18
18
|
ast (~> 1.1)
|
19
19
|
slop (~> 3.4, >= 3.4.5)
|
20
20
|
pry (0.9.12.6)
|
21
21
|
coderay (~> 1.0)
|
22
22
|
method_source (~> 0.8)
|
23
23
|
slop (~> 3.4)
|
24
|
-
rake (10.
|
25
|
-
ruby-progressbar (1.4.
|
26
|
-
slop (3.
|
24
|
+
rake (10.2.2)
|
25
|
+
ruby-progressbar (1.4.2)
|
26
|
+
slop (3.5.0)
|
27
27
|
|
28
28
|
PLATFORMS
|
29
29
|
ruby
|
data/README.md
CHANGED
@@ -10,31 +10,28 @@ only works for C (and sort of works for C++).
|
|
10
10
|
|
11
11
|
StarScope is a similar tool for [Ruby](https://www.ruby-lang.org/) and
|
12
12
|
[Golang](http://golang.org/), with a design intended to make it easy to add
|
13
|
-
support for other languages
|
14
|
-
|
13
|
+
support for other languages within the same framework (thus the name StarScope,
|
14
|
+
i.e. \*scope).
|
15
15
|
|
16
16
|
Install it as a gem:
|
17
17
|
```
|
18
18
|
$ gem install starscope
|
19
19
|
```
|
20
20
|
|
21
|
-
Build your database
|
21
|
+
Build your database by just running it in the project directory:
|
22
22
|
```
|
23
23
|
$ cd ~/my-project
|
24
24
|
$ starscope
|
25
25
|
```
|
26
26
|
|
27
|
-
Ask it things
|
27
|
+
Ask it things directly:
|
28
28
|
```
|
29
29
|
$ starscope -q calls,new # Lists all callers of new
|
30
30
|
```
|
31
31
|
|
32
|
-
Export it for use with your editor
|
32
|
+
Export it to various formats for use with your editor:
|
33
33
|
```
|
34
34
|
$ starscope -e ctags
|
35
|
-
```
|
36
|
-
or
|
37
|
-
```
|
38
35
|
$ starscope -e cscope
|
39
36
|
```
|
40
37
|
|
data/bin/starscope
CHANGED
@@ -7,18 +7,30 @@ require 'optparse'
|
|
7
7
|
require 'readline'
|
8
8
|
require 'starscope'
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
DEFAULT_DB='.starscope.db'
|
11
|
+
DEFAULT_CTAGS='tags'
|
12
|
+
DEFAULT_CSCOPE='cscope.out'
|
13
|
+
|
14
|
+
options = {:show_progress => true,
|
15
|
+
:read => true,
|
16
|
+
:write => true,
|
17
|
+
:update => true,
|
18
|
+
:verbose => false,
|
19
|
+
:db => DEFAULT_DB
|
20
|
+
}
|
12
21
|
|
13
22
|
# Options Parsing
|
14
23
|
OptionParser.new do |opts|
|
15
24
|
opts.banner = <<END
|
16
25
|
Usage: starscope [options] [PATHS]
|
17
26
|
|
18
|
-
|
19
|
-
|
27
|
+
The default database is `#{DEFAULT_DB}` if you don't specify one with -f.
|
28
|
+
The default behaviour is to read and update the database.
|
29
|
+
If no database exists and no PATHS are specified, StarScope builds a new
|
30
|
+
database by recursing in the current directory.
|
20
31
|
|
21
|
-
|
32
|
+
Scoped queries must use `::` as the scope separator, even for languages which
|
33
|
+
have their own scope syntax.
|
22
34
|
END
|
23
35
|
|
24
36
|
opts.separator "\nQueries"
|
@@ -39,14 +51,21 @@ END
|
|
39
51
|
opts.on("-e", "--export FORMAT[,PATH]", "Export in FORMAT to PATH, (see EXPORTING)") do |export|
|
40
52
|
options[:export] = export
|
41
53
|
end
|
42
|
-
opts.on("-
|
43
|
-
options[:
|
54
|
+
opts.on("-f", "--file FILE", "Use FILE instead of `#{DEFAULT_DB}`") do |path|
|
55
|
+
options[:db] = path
|
44
56
|
end
|
45
|
-
opts.on("-
|
46
|
-
options[:
|
57
|
+
opts.on("-x", "--exclude PATTERN", "Skip files matching PATTERN") do |pattern|
|
58
|
+
options[:exclude] ||= []
|
59
|
+
options[:exclude] << pattern
|
47
60
|
end
|
48
|
-
opts.on("-
|
49
|
-
options[:
|
61
|
+
opts.on("--no-read", "Don't read the DB from a file") do
|
62
|
+
options[:read] = false
|
63
|
+
end
|
64
|
+
opts.on("--no-write", "Don't write the DB to a file") do
|
65
|
+
options[:write] = false
|
66
|
+
end
|
67
|
+
opts.on("--no-update", "Don't update the DB") do
|
68
|
+
options[:update] = false
|
50
69
|
end
|
51
70
|
|
52
71
|
opts.separator "\nMisc"
|
@@ -54,22 +73,25 @@ END
|
|
54
73
|
puts StarScope::VERSION
|
55
74
|
exit
|
56
75
|
end
|
76
|
+
opts.on("--verbose", "Print extra details") do
|
77
|
+
options[:verbose] = true
|
78
|
+
end
|
57
79
|
opts.on("--no-progress", "Don't show progress-bar when updating DB") do
|
58
|
-
options[:
|
80
|
+
options[:show_progress] = false
|
59
81
|
end
|
60
82
|
|
61
83
|
opts.separator <<END
|
62
84
|
\nEXPORTING
|
63
85
|
At the moment two export formats are supported: 'ctags' and 'cscope'. If
|
64
|
-
you don't specify a path, the output is written to the files '
|
65
|
-
ctags) or '
|
86
|
+
you don't specify a path, the output is written to the files '#{DEFAULT_CTAGS}' (for
|
87
|
+
ctags) or '#{DEFAULT_CSCOPE}' (for cscope) in the current directory.
|
66
88
|
END
|
67
89
|
|
68
90
|
end.parse!
|
69
91
|
|
70
92
|
def print_summary(db)
|
71
93
|
db.summary.each do |name, count|
|
72
|
-
printf("%-8s %5d
|
94
|
+
printf("%-8s %5d records\n", name, count)
|
73
95
|
end
|
74
96
|
end
|
75
97
|
|
@@ -78,9 +100,11 @@ def run_query(db, table, value)
|
|
78
100
|
$stderr.puts "Invalid input - no query found."
|
79
101
|
return false
|
80
102
|
end
|
81
|
-
|
103
|
+
results = db.query(table.to_sym, value)
|
82
104
|
if results
|
83
|
-
|
105
|
+
results.sort_by {|x| x[:name].join(' ')}.each do |rec|
|
106
|
+
puts StarScope::Record.format(rec)
|
107
|
+
end
|
84
108
|
else
|
85
109
|
puts "No results found."
|
86
110
|
end
|
@@ -91,10 +115,12 @@ rescue StarScope::DB::NoTableError
|
|
91
115
|
end
|
92
116
|
|
93
117
|
def dump(db, table)
|
94
|
-
if table
|
95
|
-
db.dump_table(table.to_sym)
|
96
|
-
else
|
118
|
+
if table.nil?
|
97
119
|
db.dump_all
|
120
|
+
elsif table.start_with?('_')
|
121
|
+
db.dump_meta(table[1..-1].to_sym)
|
122
|
+
else
|
123
|
+
db.dump_table(table.to_sym)
|
98
124
|
end
|
99
125
|
return true
|
100
126
|
rescue StarScope::DB::NoTableError
|
@@ -102,42 +128,49 @@ rescue StarScope::DB::NoTableError
|
|
102
128
|
return false
|
103
129
|
end
|
104
130
|
|
105
|
-
|
106
|
-
options[:write] = DEFAULT_DB
|
107
|
-
options[:auto_write] = true
|
108
|
-
end
|
131
|
+
db = StarScope::DB.new(options[:show_progress], options[:verbose])
|
109
132
|
|
110
|
-
|
111
|
-
options[:read] = DEFAULT_DB
|
112
|
-
end
|
133
|
+
db_exists = File.exists?(options[:db])
|
113
134
|
|
114
|
-
|
135
|
+
if options[:read] and db_exists
|
136
|
+
new_data = db.load(options[:db])
|
137
|
+
else
|
138
|
+
# no need to run an update if we didn't read any old data
|
139
|
+
options[:update] = false
|
140
|
+
end
|
115
141
|
|
116
|
-
if options[:
|
117
|
-
db.
|
118
|
-
if !ARGV.empty?
|
119
|
-
db.add_paths(ARGV)
|
120
|
-
new_data = true
|
121
|
-
end
|
122
|
-
elsif ARGV.empty?
|
123
|
-
db.add_paths(['.'])
|
142
|
+
if options[:exclude]
|
143
|
+
db.add_excludes(options[:exclude])
|
124
144
|
new_data = true
|
125
|
-
|
145
|
+
end
|
146
|
+
|
147
|
+
if not ARGV.empty?
|
148
|
+
# paths specified, add them
|
126
149
|
db.add_paths(ARGV)
|
127
150
|
new_data = true
|
151
|
+
elsif not (options[:read] and db_exists)
|
152
|
+
# no paths were specified and the database was not read or did not exist;
|
153
|
+
# default to building a new DB in the current directory
|
154
|
+
db.add_paths(['.'])
|
155
|
+
new_data = true
|
128
156
|
end
|
129
157
|
|
130
|
-
|
158
|
+
updated = db.update() if options[:update]
|
159
|
+
new_data ||= updated
|
131
160
|
|
132
|
-
db.save(options[:
|
161
|
+
db.save(options[:db]) if options[:write] and (new_data or not db_exists)
|
133
162
|
|
134
163
|
if options[:export]
|
135
164
|
format, path = options[:export].split(',', 2)
|
136
165
|
case format
|
137
166
|
when 'ctags'
|
138
|
-
|
167
|
+
File.open(path || DEFAULT_CTAGS, 'w') do |file|
|
168
|
+
db.export_ctags(file)
|
169
|
+
end
|
139
170
|
when 'cscope'
|
140
|
-
|
171
|
+
File.open(path || DEFAULT_CSCOPE, 'w') do |file|
|
172
|
+
db.export_cscope(file)
|
173
|
+
end
|
141
174
|
else
|
142
175
|
puts "Unrecognized export format"
|
143
176
|
end
|
@@ -174,29 +207,32 @@ end
|
|
174
207
|
|
175
208
|
if options[:linemode]
|
176
209
|
puts "Run your query as 'TABLE QUERY' or run '!help' for more information."
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
dump
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
210
|
+
begin
|
211
|
+
while input = Readline.readline("> ", true)
|
212
|
+
cmd, param = input.split(' ', 2)
|
213
|
+
if cmd[0] == '!'
|
214
|
+
case cmd[1..-1]
|
215
|
+
when "dump"
|
216
|
+
dump(db, param)
|
217
|
+
when "summary"
|
218
|
+
print_summary(db)
|
219
|
+
when "update"
|
220
|
+
changed = db.update
|
221
|
+
db.save(options[:write]) if options[:write] and changed
|
222
|
+
when "help"
|
223
|
+
puts linemode_help
|
224
|
+
when "version"
|
225
|
+
puts StarScope::VERSION
|
226
|
+
when "quit"
|
227
|
+
exit
|
228
|
+
else
|
229
|
+
puts "Unknown command: '#{input}', try '!help'."
|
230
|
+
end
|
194
231
|
else
|
195
|
-
|
232
|
+
success = run_query(db, cmd, param)
|
233
|
+
puts "Try '!help'." unless success
|
196
234
|
end
|
197
|
-
else
|
198
|
-
success = run_query(db, cmd, param)
|
199
|
-
puts "Try '!help'." unless success
|
200
235
|
end
|
236
|
+
rescue Interrupt
|
201
237
|
end
|
202
238
|
end
|
data/lib/starscope/db.rb
CHANGED
@@ -1,47 +1,56 @@
|
|
1
|
-
require 'starscope/langs/go'
|
2
|
-
require 'starscope/langs/ruby'
|
3
|
-
require 'starscope/datum'
|
4
1
|
require 'date'
|
5
2
|
require 'oj'
|
6
3
|
require 'zlib'
|
7
|
-
|
4
|
+
|
5
|
+
require 'starscope/matcher'
|
6
|
+
require 'starscope/output'
|
7
|
+
require 'starscope/record'
|
8
|
+
|
9
|
+
require 'starscope/langs/coffeescript'
|
10
|
+
require 'starscope/langs/go'
|
11
|
+
require 'starscope/langs/lua'
|
12
|
+
require 'starscope/langs/ruby'
|
8
13
|
|
9
14
|
LANGS = [
|
15
|
+
StarScope::Lang::CoffeeScript,
|
10
16
|
StarScope::Lang::Go,
|
17
|
+
StarScope::Lang::Lua,
|
11
18
|
StarScope::Lang::Ruby
|
12
19
|
]
|
13
20
|
|
14
21
|
class StarScope::DB
|
15
22
|
|
16
|
-
DB_FORMAT =
|
17
|
-
PBAR_FORMAT = '%t: %c/%C %E ||%b>%i||'
|
23
|
+
DB_FORMAT = 5
|
18
24
|
|
19
25
|
class NoTableError < StandardError; end
|
20
26
|
class UnknownDBFormatError < StandardError; end
|
21
27
|
|
22
|
-
def initialize(progress)
|
23
|
-
@
|
24
|
-
@
|
25
|
-
@files = {}
|
28
|
+
def initialize(progress, verbose)
|
29
|
+
@output = StarScope::Output.new(progress, verbose)
|
30
|
+
@meta = {:paths => [], :files => {}, :excludes => []}
|
26
31
|
@tables = {}
|
27
32
|
end
|
28
33
|
|
34
|
+
# returns true if the database had to be up-converted from an old format
|
29
35
|
def load(file)
|
36
|
+
@output.log("Reading database from `#{file}`... ")
|
30
37
|
File.open(file, 'r') do |file|
|
31
38
|
Zlib::GzipReader.wrap(file) do |file|
|
32
39
|
format = file.gets.to_i
|
33
40
|
if format == DB_FORMAT
|
34
|
-
@
|
35
|
-
@
|
36
|
-
|
41
|
+
@meta = Oj.load(file.gets)
|
42
|
+
@tables = Oj.load(file.gets)
|
43
|
+
return false
|
37
44
|
elsif format <= 2
|
38
45
|
# Old format (pre-json), so read the directories segment then rebuild
|
39
46
|
len = file.gets.to_i
|
40
47
|
add_paths(Marshal::load(file.read(len)))
|
41
|
-
|
48
|
+
return true
|
49
|
+
elsif format <= 4
|
42
50
|
# Old format, so read the directories segment then rebuild
|
43
51
|
add_paths(Oj.load(file.gets))
|
44
|
-
|
52
|
+
return true
|
53
|
+
else
|
45
54
|
raise UnknownDBFormatError
|
46
55
|
end
|
47
56
|
end
|
@@ -49,57 +58,85 @@ class StarScope::DB
|
|
49
58
|
end
|
50
59
|
|
51
60
|
def save(file)
|
61
|
+
@output.log("Writing database to `#{file}`...")
|
52
62
|
File.open(file, 'w') do |file|
|
53
63
|
Zlib::GzipWriter.wrap(file) do |file|
|
54
64
|
file.puts DB_FORMAT
|
55
|
-
file.puts Oj.dump @
|
56
|
-
file.puts Oj.dump @files
|
65
|
+
file.puts Oj.dump @meta
|
57
66
|
file.puts Oj.dump @tables
|
58
67
|
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
|
71
|
+
def add_excludes(paths)
|
72
|
+
@meta[:paths] -= paths.map {|p| normalize_glob(p)}
|
73
|
+
paths = paths.map {|p| normalize_fnmatch(p)}
|
74
|
+
@meta[:excludes] += paths
|
75
|
+
@meta[:excludes].uniq!
|
76
|
+
@meta[:files].delete_if do |name, record|
|
77
|
+
if matches_exclude(paths, name)
|
78
|
+
remove_file(name)
|
79
|
+
true
|
80
|
+
else
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
62
86
|
def add_paths(paths)
|
63
|
-
|
64
|
-
|
65
|
-
@paths += paths
|
66
|
-
|
87
|
+
@meta[:excludes] -= paths.map {|p| normalize_fnmatch(p)}
|
88
|
+
paths = paths.map {|p| normalize_glob(p)}
|
89
|
+
@meta[:paths] += paths
|
90
|
+
@meta[:paths].uniq!
|
91
|
+
files = Dir.glob(paths).select {|f| File.file? f}
|
92
|
+
files.delete_if {|f| matches_exclude(@meta[:excludes], f)}
|
67
93
|
return if files.empty?
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
files.each do |f|
|
72
|
-
add_file(f)
|
73
|
-
pbar.increment if @progress
|
74
|
-
end
|
94
|
+
@output.new_pbar("Building", files.length)
|
95
|
+
add_new_files(files)
|
96
|
+
@output.finish_pbar
|
75
97
|
end
|
76
98
|
|
77
99
|
def update
|
78
|
-
new_files = (@paths.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
add_file(f)
|
89
|
-
pbar.increment if @progress
|
100
|
+
new_files = (Dir.glob(@meta[:paths]).select {|f| File.file? f}) - @meta[:files].keys
|
101
|
+
new_files.delete_if {|f| matches_exclude(@meta[:excludes], f)}
|
102
|
+
@output.new_pbar("Updating", new_files.length + @meta[:files].length)
|
103
|
+
changed = false
|
104
|
+
@meta[:files].delete_if do |name, record|
|
105
|
+
@output.log("Updating `#{name}`")
|
106
|
+
ret = update_file(name)
|
107
|
+
@output.inc_pbar
|
108
|
+
changed = true if ret == :update
|
109
|
+
ret == :delete
|
90
110
|
end
|
91
|
-
|
111
|
+
add_new_files(new_files)
|
112
|
+
@output.finish_pbar
|
113
|
+
changed || !new_files.empty?
|
92
114
|
end
|
93
115
|
|
94
116
|
def dump_table(table)
|
95
117
|
raise NoTableError if not @tables[table]
|
96
118
|
puts "== Table: #{table} =="
|
97
|
-
@tables[table].
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
119
|
+
@tables[table].sort {|a,b|
|
120
|
+
a[:name][-1].to_s.downcase <=> b[:name][-1].to_s.downcase
|
121
|
+
}.each do |record|
|
122
|
+
puts StarScope::Record.format(record)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def dump_meta(key)
|
127
|
+
if key == :meta
|
128
|
+
puts "== Metadata Summary =="
|
129
|
+
@meta.each do |k, v|
|
130
|
+
puts "#{k}: #{v.count}"
|
102
131
|
end
|
132
|
+
return
|
133
|
+
end
|
134
|
+
raise NoTableError if not @meta[key]
|
135
|
+
puts "== Metadata: #{key} =="
|
136
|
+
if @meta[key].is_a? Array
|
137
|
+
@meta[key].sort.each {|x| puts x}
|
138
|
+
else
|
139
|
+
@meta[key].sort.each {|k,v| puts "#{k}: #{v}"}
|
103
140
|
end
|
104
141
|
end
|
105
142
|
|
@@ -111,74 +148,56 @@ class StarScope::DB
|
|
111
148
|
ret = {}
|
112
149
|
|
113
150
|
@tables.each_key do |key|
|
114
|
-
ret[key] = @tables[key].
|
151
|
+
ret[key] = @tables[key].count
|
115
152
|
end
|
116
153
|
|
117
154
|
ret
|
118
155
|
end
|
119
156
|
|
120
157
|
def query(table, value)
|
121
|
-
fqn = value.split("::")
|
122
158
|
raise NoTableError if not @tables[table]
|
123
|
-
|
124
|
-
|
125
|
-
if results.empty?
|
126
|
-
matcher = Regexp.new(key, Regexp::IGNORECASE)
|
127
|
-
@tables[table].each do |k,v|
|
128
|
-
if matcher.match(k)
|
129
|
-
results << v
|
130
|
-
end
|
131
|
-
end
|
132
|
-
results.flatten!
|
133
|
-
end
|
134
|
-
return results if results.empty?
|
135
|
-
results.sort! do |a,b|
|
136
|
-
StarScope::Datum.score_match(b, fqn) <=> StarScope::Datum.score_match(a, fqn)
|
137
|
-
end
|
138
|
-
best_score = StarScope::Datum.score_match(results[0], fqn)
|
139
|
-
results = results.select do |result|
|
140
|
-
best_score - StarScope::Datum.score_match(result, fqn) < 4
|
141
|
-
end
|
142
|
-
return fqn.last.to_sym, results
|
159
|
+
input = @tables[table]
|
160
|
+
StarScope::Matcher.new(value, input).query()
|
143
161
|
end
|
144
162
|
|
145
|
-
def export_ctags(
|
146
|
-
|
147
|
-
|
148
|
-
!_TAG_FILE_FORMAT 2 //
|
163
|
+
def export_ctags(file)
|
164
|
+
file.puts <<END
|
165
|
+
!_TAG_FILE_FORMAT 2 /extended format/
|
149
166
|
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
150
|
-
!_TAG_PROGRAM_AUTHOR Evan Huus
|
151
|
-
!_TAG_PROGRAM_NAME
|
167
|
+
!_TAG_PROGRAM_AUTHOR Evan Huus /eapache@gmail.com/
|
168
|
+
!_TAG_PROGRAM_NAME StarScope //
|
152
169
|
!_TAG_PROGRAM_URL https://github.com/eapache/starscope //
|
153
170
|
!_TAG_PROGRAM_VERSION #{StarScope::VERSION} //
|
154
171
|
END
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
file.puts StarScope::Datum.ctag_line(entry)
|
159
|
-
end
|
160
|
-
end
|
172
|
+
defs = (@tables[:defs] || {}).sort_by {|x| x[:name][-1].to_s}
|
173
|
+
defs.each do |record|
|
174
|
+
file.puts StarScope::Record.ctag_line(record)
|
161
175
|
end
|
162
176
|
end
|
163
177
|
|
164
178
|
# ftp://ftp.eeng.dcu.ie/pub/ee454/cygwin/usr/share/doc/mlcscope-14.1.8/html/cscope.html
|
165
|
-
def export_cscope(
|
179
|
+
def export_cscope(file)
|
166
180
|
buf = ""
|
167
181
|
files = []
|
168
|
-
db_by_line().each do |
|
182
|
+
db_by_line().each do |filename, lines|
|
169
183
|
if not lines.empty?
|
170
|
-
buf << "\t@#{
|
171
|
-
files <<
|
184
|
+
buf << "\t@#{filename}\n\n"
|
185
|
+
files << filename
|
172
186
|
end
|
173
|
-
lines.sort.each do |line_no,
|
174
|
-
|
187
|
+
lines.sort.each do |line_no, records|
|
188
|
+
begin
|
189
|
+
line = records.first[:line].strip.gsub(/\s+/, ' ')
|
190
|
+
rescue ArgumentError
|
191
|
+
# invalid utf-8 byte sequence in the line, just do our best
|
192
|
+
line = records.first[:line]
|
193
|
+
end
|
175
194
|
toks = {}
|
176
195
|
|
177
|
-
|
178
|
-
index = line.index(
|
196
|
+
records.each do |record|
|
197
|
+
index = line.index(record[:name][-1].to_s)
|
179
198
|
while index
|
180
|
-
toks[index] =
|
181
|
-
index = line.index(
|
199
|
+
toks[index] = record
|
200
|
+
index = line.index(record[:name][-1].to_s, index + 1)
|
182
201
|
end
|
183
202
|
end
|
184
203
|
|
@@ -186,11 +205,11 @@ END
|
|
186
205
|
|
187
206
|
prev = 0
|
188
207
|
buf << line_no.to_s << " "
|
189
|
-
toks.sort().each do |offset,
|
208
|
+
toks.sort().each do |offset, record|
|
190
209
|
buf << line.slice(prev...offset) << "\n"
|
191
|
-
buf << StarScope::
|
192
|
-
buf <<
|
193
|
-
prev = offset +
|
210
|
+
buf << StarScope::Record.cscope_mark(record[:tbl], record)
|
211
|
+
buf << record[:name][-1].to_s << "\n"
|
212
|
+
prev = offset + record[:name][-1].to_s.length
|
194
213
|
end
|
195
214
|
buf << line.slice(prev..-1) << "\n\n"
|
196
215
|
end
|
@@ -199,86 +218,100 @@ END
|
|
199
218
|
buf << "\t@\n"
|
200
219
|
|
201
220
|
header = "cscope 15 #{Dir.pwd} -c "
|
202
|
-
offset = "%010d\n" % (header.length + 11 + buf.length)
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
file.print("#{buf.length}\n#{buf}")
|
216
|
-
end
|
221
|
+
offset = "%010d\n" % (header.length + 11 + buf.bytes.to_a.length)
|
222
|
+
|
223
|
+
file.print(header)
|
224
|
+
file.print(offset)
|
225
|
+
file.print(buf)
|
226
|
+
|
227
|
+
file.print("#{@meta[:paths].length}\n")
|
228
|
+
@meta[:paths].each {|p| file.print("#{p}\n")}
|
229
|
+
file.print("0\n")
|
230
|
+
file.print("#{files.length}\n")
|
231
|
+
buf = ""
|
232
|
+
files.each {|f| buf << f + "\n"}
|
233
|
+
file.print("#{buf.length}\n#{buf}")
|
217
234
|
end
|
218
235
|
|
219
236
|
private
|
220
237
|
|
221
|
-
def
|
222
|
-
|
223
|
-
|
238
|
+
def add_new_files(files)
|
239
|
+
files.each do |file|
|
240
|
+
@output.log("Adding `#{file}`")
|
241
|
+
@meta[:files][file] = {}
|
242
|
+
parse_file(file)
|
243
|
+
@output.inc_pbar
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# File.fnmatch treats a "**" to match files and directories recursively
|
248
|
+
def normalize_fnmatch(path)
|
249
|
+
if path == "."
|
250
|
+
"**"
|
251
|
+
elsif File.directory?(path)
|
252
|
+
File.join(path, "**")
|
253
|
+
else
|
254
|
+
path
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Dir.glob treats a "**" to only match directories recursively; you need
|
259
|
+
# "**/*" to match all files recursively
|
260
|
+
def normalize_glob(path)
|
261
|
+
if path == "."
|
262
|
+
File.join("**", "*")
|
224
263
|
elsif File.directory?(path)
|
225
|
-
|
264
|
+
File.join(path, "**", "*")
|
226
265
|
else
|
227
|
-
|
266
|
+
path
|
228
267
|
end
|
229
268
|
end
|
230
269
|
|
231
270
|
def db_by_line()
|
232
|
-
|
233
|
-
@tables.each do |tbl,
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
end
|
241
|
-
end
|
271
|
+
db = {}
|
272
|
+
@tables.each do |tbl, records|
|
273
|
+
records.each do |record|
|
274
|
+
next if not record[:line_no]
|
275
|
+
record[:tbl] = tbl
|
276
|
+
db[record[:file]] ||= {}
|
277
|
+
db[record[:file]][record[:line_no]] ||= []
|
278
|
+
db[record[:file]][record[:line_no]] << record
|
242
279
|
end
|
243
280
|
end
|
244
|
-
return
|
281
|
+
return db
|
245
282
|
end
|
246
283
|
|
247
|
-
def
|
248
|
-
|
284
|
+
def matches_exclude(patterns, file)
|
285
|
+
patterns.map {|p| File.fnmatch(p, file)}.any?
|
286
|
+
end
|
249
287
|
|
250
|
-
|
288
|
+
def parse_file(file)
|
289
|
+
@meta[:files][file][:last_updated] = File.mtime(file).to_i
|
251
290
|
|
252
291
|
LANGS.each do |lang|
|
253
292
|
next if not lang.match_file file
|
254
|
-
lang.extract file do |tbl,
|
255
|
-
|
256
|
-
@tables[tbl]
|
257
|
-
@tables[tbl][key] ||= []
|
258
|
-
@tables[tbl][key] << StarScope::Datum.build(file, key, args)
|
293
|
+
lang.extract file do |tbl, name, args|
|
294
|
+
@tables[tbl] ||= []
|
295
|
+
@tables[tbl] << StarScope::Record.build(file, name, args)
|
259
296
|
end
|
297
|
+
@meta[:files][file][:lang] = lang.name.split('::').last.to_sym
|
260
298
|
end
|
261
299
|
end
|
262
300
|
|
263
301
|
def remove_file(file)
|
264
|
-
@files.delete(file)
|
265
302
|
@tables.each do |name, tbl|
|
266
|
-
tbl.
|
267
|
-
val.delete_if {|dat| dat[:file] == file}
|
268
|
-
end
|
303
|
+
tbl.delete_if {|val| val[:file] == file}
|
269
304
|
end
|
270
305
|
end
|
271
306
|
|
272
307
|
def update_file(file)
|
273
308
|
if not File.exists?(file) or not File.file?(file)
|
274
309
|
remove_file(file)
|
275
|
-
|
276
|
-
elsif
|
310
|
+
:delete
|
311
|
+
elsif @meta[:files][file][:last_updated] < File.mtime(file).to_i
|
277
312
|
remove_file(file)
|
278
|
-
|
279
|
-
|
280
|
-
else
|
281
|
-
false
|
313
|
+
parse_file(file)
|
314
|
+
:update
|
282
315
|
end
|
283
316
|
end
|
284
317
|
|