starscope 1.3.3 → 1.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/.rubocop.yml +29 -0
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +6 -6
- data/README.md +4 -1
- data/bin/starscope +43 -45
- data/doc/LANGUAGE_SUPPORT.md +27 -10
- data/lib/starscope.rb +2 -2
- data/lib/starscope/db.rb +71 -50
- data/lib/starscope/exportable.rb +38 -41
- data/lib/starscope/fragment_extractor.rb +22 -0
- data/lib/starscope/langs/erb.rb +45 -0
- data/lib/starscope/langs/go.rb +33 -38
- data/lib/starscope/langs/ruby.rb +10 -10
- data/lib/starscope/output.rb +3 -5
- data/lib/starscope/queryable.rb +5 -6
- data/lib/starscope/version.rb +1 -1
- data/starscope.gemspec +6 -6
- data/test/fixtures/db_missing_language.json +15 -0
- data/test/fixtures/db_old_subextractor.json +17 -0
- data/test/fixtures/sample_erb.erb +14 -0
- data/test/fixtures/sample_ruby.rb +14 -16
- data/test/functional/starscope_test.rb +13 -15
- data/test/test_helper.rb +2 -1
- data/test/unit/db_test.rb +55 -28
- data/test/unit/exportable_test.rb +3 -5
- data/test/unit/fragment_extractor_test.rb +38 -0
- data/test/unit/langs/erb_test.rb +36 -0
- data/test/unit/langs/golang_test.rb +13 -13
- data/test/unit/langs/ruby_test.rb +14 -14
- data/test/unit/output_test.rb +9 -11
- data/test/unit/queryable_test.rb +19 -20
- metadata +18 -6
- data/lib/starscope/langs/coffeescript.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0034f945269abf5a562e9ac393621ef5ab6dfed0
|
4
|
+
data.tar.gz: 772a237027e861ea5a76c3e87a891fe9cc45b825
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68a111fe637ba4a2e0307f04d5fec574bf3fca41ad9eee91cba1f1fe07cdaa36cc18ed953a29702a0dff4c4435cdb45b8b4a0ff06a1a39702aa8136bb9b04c27
|
7
|
+
data.tar.gz: fb56e7e538076c94866cd6d10b427919ed91ec50fba6f4d3692b30bbcd1e56eee004f4caba8eb64c832d8e490f67faaae3b9d3498fb951fbdb2613d662ff1327
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Lint/UnusedBlockArgument:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Lint/UnusedMethodArgument:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Style/HashSyntax:
|
8
|
+
EnforcedStyle: hash_rockets
|
9
|
+
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics/ClassLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Metrics/CyclomaticComplexity:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Metrics/LineLength:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Metrics/PerceivedComplexity:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/Documentation:
|
29
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,21 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
v1.
|
4
|
+
v1.4.0 (trunk)
|
5
|
+
--------------------
|
6
|
+
|
7
|
+
New Features:
|
8
|
+
* Implement support for files with multiple nested languages (#61).
|
9
|
+
* Implement support for extracting ruby inside ERB files (#120).
|
10
|
+
|
11
|
+
Bug Fixes:
|
12
|
+
* Correctly handle the removal of language extractors (#122).
|
13
|
+
|
14
|
+
Misc:
|
15
|
+
* Preliminary use of Rubocop for more consistent code style.
|
16
|
+
* Document the fact that `!` can't be used at the beginning of table names.
|
17
|
+
|
18
|
+
v1.3.3 (2015-03-07)
|
5
19
|
--------------------
|
6
20
|
|
7
21
|
Bug Fixes:
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
starscope (1.
|
4
|
+
starscope (1.4.0)
|
5
5
|
backports (~> 3.6)
|
6
6
|
oj (~> 2.9)
|
7
|
-
parser (~> 2.2.
|
7
|
+
parser (~> 2.2.2)
|
8
8
|
ruby-progressbar (~> 1.5)
|
9
9
|
|
10
10
|
GEM
|
@@ -15,18 +15,18 @@ GEM
|
|
15
15
|
coderay (1.1.0)
|
16
16
|
metaclass (0.0.4)
|
17
17
|
method_source (0.8.2)
|
18
|
-
minitest (5.
|
18
|
+
minitest (5.7.0)
|
19
19
|
mocha (1.1.0)
|
20
20
|
metaclass (~> 0.0.1)
|
21
|
-
oj (2.
|
22
|
-
parser (2.2.
|
21
|
+
oj (2.12.9)
|
22
|
+
parser (2.2.2.5)
|
23
23
|
ast (>= 1.1, < 3.0)
|
24
24
|
pry (0.10.1)
|
25
25
|
coderay (~> 1.1.0)
|
26
26
|
method_source (~> 0.8.1)
|
27
27
|
slop (~> 3.4)
|
28
28
|
rake (10.4.2)
|
29
|
-
ruby-progressbar (1.7.
|
29
|
+
ruby-progressbar (1.7.5)
|
30
30
|
slop (3.6.0)
|
31
31
|
|
32
32
|
PLATFORMS
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@ Starscope
|
|
3
3
|
|
4
4
|
[](http://badge.fury.io/rb/starscope)
|
5
5
|
[](https://travis-ci.org/eapache/starscope)
|
6
|
+
[](https://eapache.github.io/conduct.html)
|
6
7
|
|
7
8
|
Anyone who has done much programming in C (or C++) on a Unix-based OS has come
|
8
9
|
across the fantastic [Cscope](http://cscope.sourceforge.net/) tool. Sadly, it
|
@@ -46,5 +47,7 @@ More Documentation
|
|
46
47
|
Other Uses
|
47
48
|
----------
|
48
49
|
|
49
|
-
Starscope is a supported backend for
|
50
|
+
- Starscope is a supported backend for
|
50
51
|
[CodeQuery](https://github.com/ruben2020/codequery).
|
52
|
+
- Starscope has been [packaged for Arch
|
53
|
+
Linux](https://aur.archlinux.org/packages/ruby-starscope/).
|
data/bin/starscope
CHANGED
@@ -7,14 +7,14 @@ require 'optparse'
|
|
7
7
|
require 'readline'
|
8
8
|
require 'starscope'
|
9
9
|
|
10
|
-
DEFAULT_DB='.starscope.db'
|
11
|
-
|
12
|
-
options = {:read => true,
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
DEFAULT_DB = '.starscope.db'
|
11
|
+
|
12
|
+
options = { :read => true,
|
13
|
+
:write => true,
|
14
|
+
:update => true,
|
15
|
+
:output => :normal,
|
16
|
+
:export => [],
|
17
|
+
:db => DEFAULT_DB
|
18
18
|
}
|
19
19
|
|
20
20
|
# Options Parsing
|
@@ -35,53 +35,53 @@ User Manual: https://github.com/eapache/starscope/blob/master/doc/USER_GUIDE.md
|
|
35
35
|
END
|
36
36
|
|
37
37
|
opts.separator "\nQueries"
|
38
|
-
opts.on(
|
38
|
+
opts.on('-d', '--dump [TABLE]', 'Dumps the DB or specified table to stdout') do |tbl|
|
39
39
|
options[:dump] = tbl || true
|
40
40
|
end
|
41
|
-
opts.on(
|
41
|
+
opts.on('-l', '--line-mode', 'Starts line-oriented interface') do
|
42
42
|
options[:linemode] = true
|
43
43
|
end
|
44
|
-
opts.on(
|
44
|
+
opts.on('-q', '--query TABLE,QUERY', 'Looks up QUERY in TABLE') do |query|
|
45
45
|
options[:query] = query
|
46
46
|
end
|
47
|
-
opts.on(
|
47
|
+
opts.on('-s', '--summary', 'Print a database summary to stdout') do
|
48
48
|
options[:summary] = true
|
49
49
|
end
|
50
50
|
|
51
51
|
opts.separator "\nDatabase Management"
|
52
|
-
opts.on(
|
52
|
+
opts.on('-e', '--export FORMAT[,PATH]', 'Export in FORMAT to PATH, (see EXPORTING)') do |export|
|
53
53
|
options[:export] << export
|
54
54
|
end
|
55
|
-
opts.on(
|
55
|
+
opts.on('-f', '--file FILE', "Use FILE instead of `#{DEFAULT_DB}`") do |path|
|
56
56
|
options[:db] = path
|
57
57
|
end
|
58
|
-
opts.on(
|
58
|
+
opts.on('-x', '--exclude PATTERN', 'Skip files matching PATTERN') do |pattern|
|
59
59
|
options[:exclude] ||= []
|
60
60
|
options[:exclude] << pattern
|
61
61
|
end
|
62
|
-
opts.on(
|
62
|
+
opts.on('--no-read', "Don't read the DB from a file") do
|
63
63
|
options[:read] = false
|
64
64
|
end
|
65
|
-
opts.on(
|
65
|
+
opts.on('--no-write', "Don't write the DB to a file") do
|
66
66
|
options[:write] = false
|
67
67
|
end
|
68
|
-
opts.on(
|
68
|
+
opts.on('--no-update', "Don't update the DB") do
|
69
69
|
options[:update] = false
|
70
70
|
end
|
71
71
|
|
72
72
|
opts.separator "\nMisc"
|
73
|
-
opts.on(
|
73
|
+
opts.on('-v', '--version', 'Print the version number') do
|
74
74
|
puts Starscope::VERSION
|
75
75
|
exit
|
76
76
|
end
|
77
|
-
opts.on(
|
77
|
+
opts.on('--verbose', 'Print extra status messages') do
|
78
78
|
if options[:output] == :quiet
|
79
79
|
$stderr.puts "Can't be both verbose and quiet"
|
80
80
|
exit(1)
|
81
81
|
end
|
82
82
|
options[:output] = :verbose
|
83
83
|
end
|
84
|
-
opts.on(
|
84
|
+
opts.on('--quiet', 'Print fewer messages') do
|
85
85
|
if options[:output] == :verbose
|
86
86
|
$stderr.puts "Can't be both verbose and quiet"
|
87
87
|
exit(1)
|
@@ -95,19 +95,18 @@ END
|
|
95
95
|
you don't specify a path, the output is written to the file '#{Starscope::Exportable::CTAGS_DEFAULT_PATH}' (for
|
96
96
|
ctags) or '#{Starscope::Exportable::CSCOPE_DEFAULT_PATH}' (for cscope) in the current directory.
|
97
97
|
END
|
98
|
-
|
99
98
|
end.parse!
|
100
99
|
|
101
100
|
def print_summary(db)
|
102
101
|
tables = db.tables
|
103
|
-
puts
|
104
|
-
tables.sort {|a,b| a.to_s <=> b.to_s}.each do |table|
|
102
|
+
puts 'No tables' if tables.empty?
|
103
|
+
tables.sort { |a, b| a.to_s <=> b.to_s }.each do |table|
|
105
104
|
printf("%-9s %6d records\n", table, db.records(table).length)
|
106
105
|
end
|
107
106
|
end
|
108
107
|
|
109
108
|
def format_record(db, rec)
|
110
|
-
"#{rec[:name].join
|
109
|
+
"#{rec[:name].join ' '} -- #{rec[:file]}:#{rec[:line_no]} (#{db.line_for_record(rec).strip})"
|
111
110
|
end
|
112
111
|
|
113
112
|
def run_query(db, query, separator)
|
@@ -130,15 +129,15 @@ def run_query(db, query, separator)
|
|
130
129
|
match = match.join(separator)
|
131
130
|
|
132
131
|
if match.empty?
|
133
|
-
$stderr.puts
|
132
|
+
$stderr.puts 'Invalid input - no query found.'
|
134
133
|
return false
|
135
134
|
end
|
136
135
|
tables = (table == '*' ? db.tables : table.to_sym)
|
137
136
|
results = db.query(tables, match, filters)
|
138
137
|
if !results || results.empty?
|
139
|
-
puts
|
138
|
+
puts 'No results found.'
|
140
139
|
else
|
141
|
-
results.sort_by {|x| x[:name].join(' ')}.each do |rec|
|
140
|
+
results.sort_by { |x| x[:name].join(' ') }.each do |rec|
|
142
141
|
puts format_record(db, rec)
|
143
142
|
end
|
144
143
|
end
|
@@ -149,12 +148,12 @@ rescue Starscope::DB::NoTableError
|
|
149
148
|
end
|
150
149
|
|
151
150
|
def dump_table(db, table)
|
152
|
-
records = db.records(table).sort
|
151
|
+
records = db.records(table).sort do |a, b|
|
153
152
|
a[:name][-1].to_s.downcase <=> b[:name][-1].to_s.downcase
|
154
|
-
|
153
|
+
end
|
155
154
|
|
156
155
|
puts "== Table: #{table} =="
|
157
|
-
puts
|
156
|
+
puts 'No records' if records.empty?
|
158
157
|
|
159
158
|
records.each do |record|
|
160
159
|
puts format_record(db, record)
|
@@ -162,11 +161,10 @@ def dump_table(db, table)
|
|
162
161
|
end
|
163
162
|
|
164
163
|
def dump(db, table)
|
165
|
-
|
166
164
|
case table
|
167
165
|
when nil
|
168
|
-
db.tables.each {|t| dump_table(db, t)}
|
169
|
-
when
|
166
|
+
db.tables.each { |t| dump_table(db, t) }
|
167
|
+
when '_meta'
|
170
168
|
puts db.metadata
|
171
169
|
when /^_/
|
172
170
|
puts db.metadata(table[1..-1].to_sym)
|
@@ -190,7 +188,7 @@ end
|
|
190
188
|
output = Starscope::Output.new(options[:output])
|
191
189
|
db = Starscope::DB.new(output)
|
192
190
|
|
193
|
-
db_exists = File.
|
191
|
+
db_exists = File.exist?(options[:db])
|
194
192
|
|
195
193
|
if options[:read] && db_exists
|
196
194
|
# we consider it 'new data' if the db was upconverted from an old format
|
@@ -216,7 +214,7 @@ elsif !(options[:read] && db_exists)
|
|
216
214
|
new_data = true
|
217
215
|
end
|
218
216
|
|
219
|
-
updated = db.update
|
217
|
+
updated = db.update if options[:update]
|
220
218
|
new_data ||= updated
|
221
219
|
|
222
220
|
db.save(options[:db]) if options[:write] && (new_data || !db_exists)
|
@@ -253,29 +251,29 @@ end
|
|
253
251
|
if options[:linemode]
|
254
252
|
puts "Run your query as 'TABLE QUERY' or run '!help' for more information."
|
255
253
|
begin
|
256
|
-
while input = Readline.readline(
|
254
|
+
while input = Readline.readline('> ', true)
|
257
255
|
next if input.empty?
|
258
256
|
cmd, param = input.split(' ', 2)
|
259
257
|
if cmd[0] == '!'
|
260
258
|
case cmd[1..-1]
|
261
|
-
when
|
259
|
+
when 'dump'
|
262
260
|
dump(db, param)
|
263
|
-
when
|
261
|
+
when 'export'
|
264
262
|
if param
|
265
263
|
export(db, param)
|
266
264
|
else
|
267
|
-
puts
|
265
|
+
puts '!export requires an argument'
|
268
266
|
end
|
269
|
-
when
|
267
|
+
when 'summary'
|
270
268
|
print_summary(db)
|
271
|
-
when
|
269
|
+
when 'update'
|
272
270
|
changed = db.update
|
273
271
|
db.save(options[:db]) if options[:write] && changed
|
274
|
-
when
|
272
|
+
when 'help'
|
275
273
|
puts linemode_help
|
276
|
-
when
|
274
|
+
when 'version'
|
277
275
|
puts Starscope::VERSION
|
278
|
-
when
|
276
|
+
when 'quit'
|
279
277
|
exit
|
280
278
|
else
|
281
279
|
puts "Unknown command: '#{input}', try '!help'."
|
data/doc/LANGUAGE_SUPPORT.md
CHANGED
@@ -16,19 +16,19 @@ on anything language-specific, they just read the internal database record
|
|
16
16
|
format.
|
17
17
|
|
18
18
|
For this doc, we're going to pretend to add support for a language called
|
19
|
-
"MyLanguage". Create a file called `
|
20
|
-
drop the following template in:
|
19
|
+
"MyLanguage". Create a file called `my_language.rb` in `lib/starscope/langs/`
|
20
|
+
and drop the following template in:
|
21
21
|
|
22
22
|
```ruby
|
23
23
|
module Starscope::Lang
|
24
|
-
module
|
24
|
+
module MyLanguage
|
25
25
|
VERSION = 1
|
26
26
|
|
27
27
|
def self.match_file(name)
|
28
28
|
name.end_with?(".mylang")
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.extract(
|
31
|
+
def self.extract(path, contents)
|
32
32
|
# TODO
|
33
33
|
end
|
34
34
|
end
|
@@ -36,18 +36,19 @@ end
|
|
36
36
|
```
|
37
37
|
|
38
38
|
This code is pretty simple: we define a module called
|
39
|
-
`Starscope::Lang::
|
39
|
+
`Starscope::Lang::MyLanguage` and give it one constant and two public module
|
40
40
|
methods:
|
41
41
|
* `VERSION` is a constant integer defining the current version of the
|
42
42
|
extractor. It should be incremented when the extractor has changed enough
|
43
43
|
that any existing files should be re-parsed with the new version.
|
44
44
|
* `match_file` takes the name of the file and returns a boolean if that file is
|
45
45
|
written in MyLanguage or not. This can be as simple as checking the file
|
46
|
-
extension (which the sample code does) or looking for a shell
|
46
|
+
extension (which the sample code does) or looking for a shell `#!` line, or
|
47
47
|
anything you want.
|
48
|
-
* `extract` takes
|
49
|
-
the file, `yield`ing records as it finds function
|
50
|
-
It may also return a final hash of file-wide
|
48
|
+
* `extract` takes the path to the file and a string containing the contents of
|
49
|
+
the file, and must parse the text, `yield`ing records as it finds function
|
50
|
+
definitions and the like. It may also return a final hash of file-wide
|
51
|
+
metadata to store.
|
51
52
|
|
52
53
|
The record requirements are pretty straight-forward:
|
53
54
|
```ruby
|
@@ -67,7 +68,7 @@ belongs (basically its type). Current tables already include:
|
|
67
68
|
Try to use pre-existing tables where possible, but feel free to add more if the
|
68
69
|
language has some weird feature that doesn't map to any of the above. You don't
|
69
70
|
have to do anything special to create a new table, just yield the appropriate
|
70
|
-
symbol.
|
71
|
+
symbol. Table names cannot begin with exclamation points (`!`).
|
71
72
|
|
72
73
|
The second yielded argument is the name (string or symbol) of the token that
|
73
74
|
you want to add: the name of the function being called, or the name of the class
|
@@ -85,3 +86,19 @@ And that's it! Parse your files, yield your records, and the Starscope engine
|
|
85
86
|
takes care of everything else for you. If you've added support for a language
|
86
87
|
that you think others might find useful, please contribute it (with tests!) via
|
87
88
|
pull request.
|
89
|
+
|
90
|
+
Sublanguages and Fragments
|
91
|
+
--------------------------
|
92
|
+
|
93
|
+
Some languages (such as ERB and Markdown) include support for nesting chunks of
|
94
|
+
other languages inside. If your extractor comes across a fragment of another
|
95
|
+
language while it is parsing, it can pass that off to the correct sub-extractor
|
96
|
+
by yielding to the special `FRAGMENT` table, with the name of the language as
|
97
|
+
the name, and a `frag` argument containing the actual raw text. For example:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
yield FRAGMENT, :Ruby, :frag => my_extracted_ruby_code, :line_no => line_no
|
101
|
+
```
|
102
|
+
|
103
|
+
Fragments will be accumulated by the database and passed to the appropriate
|
104
|
+
extractor when the current file has been completely parsed.
|
data/lib/starscope.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'starscope/version'
|
2
|
+
require 'starscope/db'
|
data/lib/starscope/db.rb
CHANGED
@@ -5,6 +5,7 @@ require 'set'
|
|
5
5
|
require 'zlib'
|
6
6
|
|
7
7
|
require 'starscope/exportable'
|
8
|
+
require 'starscope/fragment_extractor'
|
8
9
|
require 'starscope/queryable'
|
9
10
|
require 'starscope/output'
|
10
11
|
|
@@ -19,8 +20,9 @@ Starscope::Lang.constants.each do |lang|
|
|
19
20
|
LANGS[lang.to_sym] = extractor.const_get(:VERSION)
|
20
21
|
end
|
21
22
|
|
22
|
-
|
23
|
+
FRAGMENT = :'!fragment'
|
23
24
|
|
25
|
+
class Starscope::DB
|
24
26
|
include Starscope::Exportable
|
25
27
|
include Starscope::Queryable
|
26
28
|
|
@@ -31,8 +33,8 @@ class Starscope::DB
|
|
31
33
|
|
32
34
|
def initialize(output)
|
33
35
|
@output = output
|
34
|
-
@meta = {:paths => [], :files => {}, :excludes => [],
|
35
|
-
|
36
|
+
@meta = { :paths => [], :files => {}, :excludes => [],
|
37
|
+
:langs => LANGS, :version => Starscope::VERSION }
|
36
38
|
@tables = {}
|
37
39
|
end
|
38
40
|
|
@@ -63,43 +65,43 @@ class Starscope::DB
|
|
63
65
|
|
64
66
|
def add_excludes(paths)
|
65
67
|
@output.extra("Excluding files in paths #{paths}...")
|
66
|
-
@meta[:paths] -= paths.map {|p| self.class.normalize_glob(p)}
|
67
|
-
paths = paths.map {|p| self.class.normalize_fnmatch(p)}
|
68
|
+
@meta[:paths] -= paths.map { |p| self.class.normalize_glob(p) }
|
69
|
+
paths = paths.map { |p| self.class.normalize_fnmatch(p) }
|
68
70
|
@meta[:excludes] += paths
|
69
71
|
@meta[:excludes].uniq!
|
70
72
|
|
71
|
-
excluded = @meta[:files].keys.select {|name| matches_exclude?(name, paths)}
|
73
|
+
excluded = @meta[:files].keys.select { |name| matches_exclude?(name, paths) }
|
72
74
|
remove_files(excluded)
|
73
75
|
end
|
74
76
|
|
75
77
|
def add_paths(paths)
|
76
78
|
@output.extra("Adding files in paths #{paths}...")
|
77
|
-
@meta[:excludes] -= paths.map {|p| self.class.normalize_fnmatch(p)}
|
78
|
-
paths = paths.map {|p| self.class.normalize_glob(p)}
|
79
|
+
@meta[:excludes] -= paths.map { |p| self.class.normalize_fnmatch(p) }
|
80
|
+
paths = paths.map { |p| self.class.normalize_glob(p) }
|
79
81
|
@meta[:paths] += paths
|
80
82
|
@meta[:paths].uniq!
|
81
|
-
files = Dir.glob(paths).select {|f| File.file? f}
|
82
|
-
files.delete_if {|f| matches_exclude?(f)}
|
83
|
+
files = Dir.glob(paths).select { |f| File.file? f }
|
84
|
+
files.delete_if { |f| matches_exclude?(f) }
|
83
85
|
return if files.empty?
|
84
|
-
@output.new_pbar(
|
86
|
+
@output.new_pbar('Building', files.length)
|
85
87
|
add_files(files)
|
86
88
|
@output.finish_pbar
|
87
89
|
end
|
88
90
|
|
89
91
|
def update
|
90
|
-
changes = @meta[:files].keys.group_by {|name| file_changed(name)}
|
92
|
+
changes = @meta[:files].keys.group_by { |name| file_changed(name) }
|
91
93
|
changes[:modified] ||= []
|
92
94
|
changes[:deleted] ||= []
|
93
95
|
|
94
|
-
new_files = (Dir.glob(@meta[:paths]).select {|f| File.file? f}) - @meta[:files].keys
|
95
|
-
new_files.delete_if {|f| matches_exclude?(f)}
|
96
|
+
new_files = (Dir.glob(@meta[:paths]).select { |f| File.file? f }) - @meta[:files].keys
|
97
|
+
new_files.delete_if { |f| matches_exclude?(f) }
|
96
98
|
|
97
99
|
if changes[:deleted].empty? && changes[:modified].empty? && new_files.empty?
|
98
|
-
@output.normal(
|
100
|
+
@output.normal('No changes detected.')
|
99
101
|
return false
|
100
102
|
end
|
101
103
|
|
102
|
-
@output.new_pbar(
|
104
|
+
@output.new_pbar('Updating', changes[:modified].length + new_files.length)
|
103
105
|
remove_files(changes[:deleted])
|
104
106
|
update_files(changes[:modified])
|
105
107
|
add_files(new_files)
|
@@ -113,7 +115,7 @@ class Starscope::DB
|
|
113
115
|
|
114
116
|
file = @meta[:files][rec[:file]]
|
115
117
|
|
116
|
-
return file[:lines][rec[:line_no]-1] if file[:lines]
|
118
|
+
return file[:lines][rec[:line_no] - 1] if file[:lines]
|
117
119
|
end
|
118
120
|
|
119
121
|
def tables
|
@@ -121,15 +123,15 @@ class Starscope::DB
|
|
121
123
|
end
|
122
124
|
|
123
125
|
def records(table)
|
124
|
-
|
126
|
+
fail NoTableError unless @tables[table]
|
125
127
|
|
126
128
|
@tables[table]
|
127
129
|
end
|
128
130
|
|
129
|
-
def metadata(key=nil)
|
131
|
+
def metadata(key = nil)
|
130
132
|
return @meta.keys if key.nil?
|
131
133
|
|
132
|
-
|
134
|
+
fail NoTableError unless @meta[key]
|
133
135
|
|
134
136
|
@meta[key]
|
135
137
|
end
|
@@ -163,10 +165,10 @@ class Starscope::DB
|
|
163
165
|
when 0..2
|
164
166
|
# Old format (pre-json), so read the directories segment then rebuild
|
165
167
|
len = stream.gets.to_i
|
166
|
-
add_paths(Marshal
|
168
|
+
add_paths(Marshal.load(stream.read(len)))
|
167
169
|
return false
|
168
170
|
else
|
169
|
-
|
171
|
+
fail UnknownDBFormatError
|
170
172
|
end
|
171
173
|
rescue Oj::ParseError
|
172
174
|
stream.rewind
|
@@ -174,7 +176,7 @@ class Starscope::DB
|
|
174
176
|
# try reading as formated json, which is much slower, but it is sometimes
|
175
177
|
# useful to be able to directly read your db
|
176
178
|
objects = []
|
177
|
-
Oj.load(stream) {|obj| objects << obj}
|
179
|
+
Oj.load(stream) { |obj| objects << obj }
|
178
180
|
@meta, @tables = objects
|
179
181
|
return true
|
180
182
|
end
|
@@ -186,10 +188,10 @@ class Starscope::DB
|
|
186
188
|
|
187
189
|
# File.fnmatch treats a "**" to match files and directories recursively
|
188
190
|
def self.normalize_fnmatch(path)
|
189
|
-
if path ==
|
190
|
-
|
191
|
+
if path == '.'
|
192
|
+
'**'
|
191
193
|
elsif File.directory?(path)
|
192
|
-
File.join(path,
|
194
|
+
File.join(path, '**')
|
193
195
|
else
|
194
196
|
path
|
195
197
|
end
|
@@ -198,17 +200,17 @@ class Starscope::DB
|
|
198
200
|
# Dir.glob treats a "**" to only match directories recursively; you need
|
199
201
|
# "**/*" to match all files recursively
|
200
202
|
def self.normalize_glob(path)
|
201
|
-
if path ==
|
202
|
-
File.join(
|
203
|
+
if path == '.'
|
204
|
+
File.join('**', '*')
|
203
205
|
elsif File.directory?(path)
|
204
|
-
File.join(path,
|
206
|
+
File.join(path, '**', '*')
|
205
207
|
else
|
206
208
|
path
|
207
209
|
end
|
208
210
|
end
|
209
211
|
|
210
212
|
def matches_exclude?(file, patterns = @meta[:excludes])
|
211
|
-
patterns.map {|p| File.fnmatch(p, file)}.any?
|
213
|
+
patterns.map { |p| File.fnmatch(p, file) }.any?
|
212
214
|
end
|
213
215
|
|
214
216
|
def add_files(files)
|
@@ -226,7 +228,7 @@ class Starscope::DB
|
|
226
228
|
end
|
227
229
|
files = files.to_set
|
228
230
|
@tables.each do |name, tbl|
|
229
|
-
tbl.delete_if {|val| files.include?(val[:file])}
|
231
|
+
tbl.delete_if { |val| files.include?(val[:file]) }
|
230
232
|
end
|
231
233
|
end
|
232
234
|
|
@@ -236,7 +238,7 @@ class Starscope::DB
|
|
236
238
|
end
|
237
239
|
|
238
240
|
def parse_file(file)
|
239
|
-
@meta[:files][file] = {:last_updated => File.mtime(file).to_i}
|
241
|
+
@meta[:files][file] = { :last_updated => File.mtime(file).to_i }
|
240
242
|
|
241
243
|
EXTRACTORS.each do |extractor|
|
242
244
|
begin
|
@@ -246,27 +248,40 @@ class Starscope::DB
|
|
246
248
|
next
|
247
249
|
end
|
248
250
|
|
249
|
-
|
251
|
+
line_cache = File.readlines(file)
|
252
|
+
lines = Array.new(line_cache.length)
|
253
|
+
@meta[:files][file][:sublangs] = []
|
254
|
+
extract_file(extractor, file, line_cache, lines)
|
250
255
|
|
251
|
-
|
256
|
+
break
|
252
257
|
end
|
253
258
|
end
|
254
259
|
|
255
|
-
def extract_file(extractor, file)
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
260
|
+
def extract_file(extractor, file, line_cache, lines)
|
261
|
+
fragment_cache = {}
|
262
|
+
|
263
|
+
extractor_metadata = extractor.extract(file, File.read(file)) do |tbl, name, args|
|
264
|
+
case tbl
|
265
|
+
when FRAGMENT
|
266
|
+
fragment_cache[name] ||= []
|
267
|
+
fragment_cache[name] << args
|
268
|
+
else
|
269
|
+
@tables[tbl] ||= []
|
270
|
+
@tables[tbl] << self.class.normalize_record(file, name, args)
|
271
|
+
|
272
|
+
if args[:line_no]
|
273
|
+
line_cache ||= File.readlines(file)
|
274
|
+
lines ||= Array.new(line_cache.length)
|
275
|
+
lines[args[:line_no] - 1] = line_cache[args[:line_no] - 1].chomp
|
276
|
+
end
|
267
277
|
end
|
268
278
|
end
|
269
279
|
|
280
|
+
fragment_cache.each do |lang, frags|
|
281
|
+
extract_file(Starscope::FragmentExtractor.new(lang, frags), file, line_cache, lines)
|
282
|
+
@meta[:files][file][:sublangs] << lang
|
283
|
+
end
|
284
|
+
|
270
285
|
@meta[:files][file][:lang] = extractor.name.split('::').last.to_sym
|
271
286
|
@meta[:files][file][:lines] = lines
|
272
287
|
|
@@ -280,26 +295,32 @@ class Starscope::DB
|
|
280
295
|
|
281
296
|
def file_changed(name)
|
282
297
|
file_meta = @meta[:files][name]
|
283
|
-
if !File.
|
298
|
+
if !File.exist?(name) || !File.file?(name)
|
284
299
|
:deleted
|
285
300
|
elsif (file_meta[:last_updated] < File.mtime(name).to_i) ||
|
286
|
-
(file_meta[:lang]
|
301
|
+
language_out_of_date(file_meta[:lang]) ||
|
302
|
+
(file_meta[:sublangs] || []).any? { |lang| language_out_of_date(lang) }
|
287
303
|
:modified
|
288
304
|
else
|
289
305
|
:unchanged
|
290
306
|
end
|
291
307
|
end
|
292
308
|
|
309
|
+
def language_out_of_date(lang)
|
310
|
+
return false unless lang
|
311
|
+
return true unless LANGS[lang]
|
312
|
+
(@meta[:langs][lang] || 0) < LANGS[lang]
|
313
|
+
end
|
314
|
+
|
293
315
|
def self.normalize_record(file, name, args)
|
294
316
|
args[:file] = file
|
295
317
|
|
296
318
|
if name.is_a? Array
|
297
|
-
args[:name] = name.map
|
319
|
+
args[:name] = name.map(&:to_sym)
|
298
320
|
else
|
299
321
|
args[:name] = [name.to_sym]
|
300
322
|
end
|
301
323
|
|
302
324
|
args
|
303
325
|
end
|
304
|
-
|
305
326
|
end
|