starscope 1.3.3 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/starscope.svg)](http://badge.fury.io/rb/starscope)
|
5
5
|
[![Build Status](https://travis-ci.org/eapache/starscope.svg?branch=master)](https://travis-ci.org/eapache/starscope)
|
6
|
+
[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](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
|