starscope 1.5.7 → 1.6.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 +5 -5
- data/.github/workflows/ruby-ci.yml +26 -0
- data/.rubocop.yml +10 -4
- data/CHANGELOG.md +18 -0
- data/README.md +1 -1
- data/Rakefile +5 -2
- data/bin/starscope +53 -51
- data/doc/LANGUAGE_SUPPORT.md +8 -0
- data/doc/USER_GUIDE.md +14 -4
- data/lib/starscope/db.rb +20 -24
- data/lib/starscope/exportable.rb +34 -32
- data/lib/starscope/fragment_extractor.rb +3 -4
- data/lib/starscope/langs/erb.rb +3 -3
- data/lib/starscope/langs/golang.rb +24 -25
- data/lib/starscope/langs/javascript.rb +4 -2
- data/lib/starscope/langs/ruby.rb +4 -2
- data/lib/starscope/matcher.rb +2 -2
- data/lib/starscope/output.rb +6 -3
- data/lib/starscope/queryable.rb +1 -0
- data/lib/starscope/version.rb +1 -1
- data/starscope.gemspec +14 -11
- data/test/fixtures/sample_golang.go +1 -1
- data/test/functional/starscope_test.rb +15 -15
- data/test/unit/db_test.rb +50 -50
- data/test/unit/exportable_test.rb +12 -10
- data/test/unit/fragment_extractor_test.rb +10 -10
- data/test/unit/langs/erb_test.rb +17 -17
- data/test/unit/langs/golang_test.rb +55 -55
- data/test/unit/langs/javascript_test.rb +44 -44
- data/test/unit/langs/ruby_test.rb +27 -27
- data/test/unit/output_test.rb +3 -3
- data/test/unit/queryable_test.rb +29 -29
- metadata +59 -31
- data/.travis.yml +0 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d71f7d9d5748e9df63987f08669e56866a5669a7877a5b78bec7274ae6b11e3b
|
|
4
|
+
data.tar.gz: a037cc0b16644f69a37c1d9a00f076a036353cb84cbcaef39e17f864af2c70eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85d4390356102ec0dfc658fa99bb8816a197f48f990abe56fd5b1df7ac85d3d1ffdd93666ca463ca9c42a362ae81a369cc81fa700c83729a9e73a9ba1e431730
|
|
7
|
+
data.tar.gz: 6cb4cc84d760ba1e5114f2401878e9312eff5e1b7d30ae7b3c4feec10a76c0f87f1f3d00de59417aee8e5e57aa2eb9744ae6a851303b964d9b8edaf8fcec3dad
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Ruby CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ master ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
ruby-version: ['2.6', '2.7', '3.0', '3.1']
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v2
|
|
18
|
+
- name: Set up Ruby
|
|
19
|
+
uses: ruby/setup-ruby@v1
|
|
20
|
+
with:
|
|
21
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
22
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
23
|
+
- name: Run tests
|
|
24
|
+
run: bundle exec rake test
|
|
25
|
+
- name: Lint
|
|
26
|
+
run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
require:
|
|
2
|
+
- rubocop-minitest
|
|
3
|
+
- rubocop-rake
|
|
4
|
+
|
|
1
5
|
AllCops:
|
|
6
|
+
NewCops: enable
|
|
2
7
|
Exclude:
|
|
3
|
-
-
|
|
8
|
+
- test/fixtures/sample_ruby.rb
|
|
9
|
+
- vendor/bundle/**/*
|
|
10
|
+
|
|
11
|
+
Layout/LineLength:
|
|
12
|
+
Max: 120
|
|
4
13
|
|
|
5
14
|
Metrics/AbcSize:
|
|
6
15
|
Enabled: false
|
|
@@ -17,9 +26,6 @@ Metrics/ClassLength:
|
|
|
17
26
|
Metrics/CyclomaticComplexity:
|
|
18
27
|
Enabled: false
|
|
19
28
|
|
|
20
|
-
Metrics/LineLength:
|
|
21
|
-
Max: 120
|
|
22
|
-
|
|
23
29
|
Metrics/MethodLength:
|
|
24
30
|
Enabled: false
|
|
25
31
|
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
v1.6.0 (2022-02-10)
|
|
5
|
+
-------------------
|
|
6
|
+
|
|
7
|
+
Improvements:
|
|
8
|
+
* Support per-directory `.starscope.json` config (#181).
|
|
9
|
+
* Support abbreviated special commands in line mode (e.g. `!u`, `!s`, `!q`).
|
|
10
|
+
* Properly support non-ASCII identifiers in Golang.
|
|
11
|
+
* Tiny performance improvements.
|
|
12
|
+
|
|
13
|
+
Bug Fixes:
|
|
14
|
+
* Strip non-ASCII characters from cscope export to avoid cscope crashes (#182).
|
|
15
|
+
|
|
16
|
+
Misc:
|
|
17
|
+
* Drop support for ancient Marshall-format databases.
|
|
18
|
+
* Drop support for several old Ruby versions. 2.6 is now the oldest supported.
|
|
19
|
+
* Dependency upgrades.
|
|
20
|
+
* Documentation improvements.
|
|
21
|
+
|
|
4
22
|
v1.5.7 (2019-04-04)
|
|
5
23
|
--------------------
|
|
6
24
|
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@ Starscope
|
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
4
|
[](https://rubygems.org/gems/starscope)
|
|
5
|
-
[](https://github.com/eapache/starscope/actions/workflows/ruby-ci.yml)
|
|
6
6
|
[](https://eapache.github.io/conduct.html)
|
|
7
7
|
|
|
8
8
|
Starscope is a code indexer, search and navigation tool for
|
data/Rakefile
CHANGED
|
@@ -6,7 +6,10 @@ Rake::TestTask.new do |t|
|
|
|
6
6
|
t.test_files = FileList['test/**/*_test.rb']
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
RuboCop::RakeTask.new
|
|
9
|
+
RuboCop::RakeTask.new do |t|
|
|
10
|
+
t.requires << 'rubocop-minitest'
|
|
11
|
+
t.requires << 'rubocop-rake'
|
|
12
|
+
end
|
|
10
13
|
|
|
11
14
|
desc 'Run tests and style checks'
|
|
12
|
-
task default: [
|
|
15
|
+
task default: %i[test rubocop]
|
data/bin/starscope
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path('
|
|
3
|
+
lib = File.expand_path('../lib', __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
|
6
6
|
require 'oj'
|
|
@@ -9,7 +9,7 @@ require 'readline'
|
|
|
9
9
|
require 'starscope'
|
|
10
10
|
|
|
11
11
|
DEFAULT_DB = '.starscope.db'.freeze
|
|
12
|
-
CONFIG_FILE = File.join(Dir.home, '.starscope.json')
|
|
12
|
+
CONFIG_FILE = File.exist?('.starscope.json') ? '.starscope.json' : File.join(Dir.home, '.starscope.json')
|
|
13
13
|
GLOBAL_CONFIG = File.exist?(CONFIG_FILE) ? Oj.load_file(CONFIG_FILE, symbol_keys: true) : {}
|
|
14
14
|
|
|
15
15
|
options = { read: true,
|
|
@@ -21,20 +21,20 @@ options = { read: true,
|
|
|
21
21
|
|
|
22
22
|
# Options Parsing
|
|
23
23
|
OptionParser.new do |opts|
|
|
24
|
-
opts.banner =
|
|
25
|
-
Usage: starscope [options] [PATHS]
|
|
24
|
+
opts.banner = <<~BANNER
|
|
25
|
+
Usage: starscope [options] [PATHS]
|
|
26
26
|
|
|
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.
|
|
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.
|
|
31
31
|
|
|
32
|
-
Scoped queries must use `::` as the scope separator, even for languages which
|
|
33
|
-
have their own scope syntax.
|
|
32
|
+
Scoped queries must use `::` as the scope separator, even for languages which
|
|
33
|
+
have their own scope syntax.
|
|
34
34
|
|
|
35
|
-
Website: https://github.com/eapache/starscope
|
|
36
|
-
User Manual: https://github.com/eapache/starscope/blob/master/doc/USER_GUIDE.md
|
|
37
|
-
|
|
35
|
+
Website: https://github.com/eapache/starscope
|
|
36
|
+
User Manual: https://github.com/eapache/starscope/blob/master/doc/USER_GUIDE.md
|
|
37
|
+
BANNER
|
|
38
38
|
|
|
39
39
|
opts.separator "\nQueries"
|
|
40
40
|
opts.on('-d', '--dump [TABLE]', 'Dumps the DB or specified table to stdout') do |tbl|
|
|
@@ -81,32 +81,32 @@ END
|
|
|
81
81
|
end
|
|
82
82
|
opts.on('--verbose', 'Print extra status messages') do
|
|
83
83
|
if options[:output] == :quiet
|
|
84
|
-
|
|
84
|
+
warn "Can't be both verbose and quiet"
|
|
85
85
|
exit(1)
|
|
86
86
|
end
|
|
87
87
|
options[:output] = :verbose
|
|
88
88
|
end
|
|
89
89
|
opts.on('--quiet', 'Print fewer messages') do
|
|
90
90
|
if options[:output] == :verbose
|
|
91
|
-
|
|
91
|
+
warn "Can't be both verbose and quiet"
|
|
92
92
|
exit(1)
|
|
93
93
|
end
|
|
94
94
|
options[:output] = :quiet
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
opts.separator
|
|
98
|
-
\nEXPORTING
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
opts.separator <<~TAIL
|
|
98
|
+
\nEXPORTING
|
|
99
|
+
At the moment two export formats are supported: 'ctags' and 'cscope'. If
|
|
100
|
+
you don't specify a path, the output is written to the file '#{Starscope::Exportable::CTAGS_DEFAULT_PATH}' (for
|
|
101
|
+
ctags) or '#{Starscope::Exportable::CSCOPE_DEFAULT_PATH}' (for cscope) in the current directory.
|
|
102
|
+
TAIL
|
|
103
103
|
end.parse!
|
|
104
104
|
|
|
105
105
|
def print_summary(db)
|
|
106
106
|
tables = db.tables
|
|
107
107
|
puts 'No tables' if tables.empty?
|
|
108
108
|
tables.sort.each do |table|
|
|
109
|
-
printf("
|
|
109
|
+
printf("%<table>-9s %<length>6d records\n", table: table, length: db.records(table).length)
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
|
|
@@ -134,7 +134,7 @@ def run_query(db, query, separator)
|
|
|
134
134
|
match = match.join(separator)
|
|
135
135
|
|
|
136
136
|
if match.empty?
|
|
137
|
-
|
|
137
|
+
warn 'Invalid input - no query found.'
|
|
138
138
|
return false
|
|
139
139
|
end
|
|
140
140
|
tables = (table == '*' ? db.tables : table.to_sym)
|
|
@@ -146,10 +146,10 @@ def run_query(db, query, separator)
|
|
|
146
146
|
puts format_record(db, rec)
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
|
-
|
|
149
|
+
true
|
|
150
150
|
rescue Starscope::DB::NoTableError
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
warn "Table '#{table}' doesn't exist."
|
|
152
|
+
false
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
def dump_table(db, table)
|
|
@@ -174,22 +174,22 @@ def dump(db, table)
|
|
|
174
174
|
when '_files'
|
|
175
175
|
puts db.metadata(:files).keys
|
|
176
176
|
when /^_/
|
|
177
|
-
puts db.metadata(table[1
|
|
177
|
+
puts db.metadata(table[1..].to_sym)
|
|
178
178
|
else
|
|
179
179
|
dump_table(db, table.to_sym)
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
true
|
|
183
183
|
rescue Starscope::DB::NoTableError
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
warn "Table '#{table}' doesn't exist."
|
|
185
|
+
false
|
|
186
186
|
end
|
|
187
187
|
|
|
188
188
|
def export(db, param)
|
|
189
189
|
format, path = param.split(',', 2)
|
|
190
190
|
db.export(format.to_sym, path)
|
|
191
191
|
rescue Starscope::Exportable::UnknownExportFormatError
|
|
192
|
-
|
|
192
|
+
warn "Unrecognized export format \"#{format}\""
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
output = Starscope::Output.new(options[:output])
|
|
@@ -246,18 +246,19 @@ if options[:dump]
|
|
|
246
246
|
end
|
|
247
247
|
|
|
248
248
|
def linemode_help
|
|
249
|
-
|
|
250
|
-
Input can be a query of the form 'TABLE QUERY' or a special command starting
|
|
251
|
-
with a '!'. Recognized special commands are:
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
249
|
+
<<~HELP
|
|
250
|
+
Input can be a query of the form 'TABLE QUERY' or a special command starting
|
|
251
|
+
with a '!'. Recognized special commands are:
|
|
252
|
+
!dump [TABLE]
|
|
253
|
+
!export FORMAT[,PATH]
|
|
254
|
+
!summary
|
|
255
|
+
!update
|
|
256
|
+
|
|
257
|
+
!help
|
|
258
|
+
!version
|
|
259
|
+
!quit
|
|
260
|
+
Abbreviations of special commands (e.g `!u` or `!q`) are also recognized.
|
|
261
|
+
HELP
|
|
261
262
|
end
|
|
262
263
|
|
|
263
264
|
if options[:linemode]
|
|
@@ -265,27 +266,28 @@ if options[:linemode]
|
|
|
265
266
|
begin
|
|
266
267
|
while (input = Readline.readline('> ', true))
|
|
267
268
|
next if input.empty?
|
|
269
|
+
|
|
268
270
|
cmd, param = input.split(' ', 2)
|
|
269
271
|
if cmd[0] == '!'
|
|
270
|
-
case cmd[1
|
|
271
|
-
when 'dump'
|
|
272
|
+
case cmd[1..]
|
|
273
|
+
when 'dump', 'd'
|
|
272
274
|
dump(db, param)
|
|
273
|
-
when 'export'
|
|
275
|
+
when 'export', 'e', 'ex'
|
|
274
276
|
if param
|
|
275
277
|
export(db, param)
|
|
276
278
|
else
|
|
277
279
|
puts '!export requires an argument'
|
|
278
280
|
end
|
|
279
|
-
when 'summary'
|
|
281
|
+
when 'summary', 's', 'sum'
|
|
280
282
|
print_summary(db)
|
|
281
|
-
when 'update'
|
|
283
|
+
when 'update', 'u', 'up'
|
|
282
284
|
changed = db.update
|
|
283
285
|
db.save(options[:db]) if options[:write] && changed
|
|
284
|
-
when 'help'
|
|
286
|
+
when 'help', 'h'
|
|
285
287
|
puts linemode_help
|
|
286
|
-
when 'version'
|
|
288
|
+
when 'version', 'v'
|
|
287
289
|
puts Starscope::VERSION
|
|
288
|
-
when 'quit'
|
|
290
|
+
when 'quit', 'q'
|
|
289
291
|
exit
|
|
290
292
|
else
|
|
291
293
|
puts "Unknown command: '#{input}', try '!help'."
|
data/doc/LANGUAGE_SUPPORT.md
CHANGED
|
@@ -9,6 +9,14 @@ Already Supported
|
|
|
9
9
|
* [JavaScript](https://en.wikipedia.org/wiki/JavaScript)
|
|
10
10
|
(including ES6/ES7 and JSX via [Babel](https://babeljs.io/))
|
|
11
11
|
|
|
12
|
+
External Support
|
|
13
|
+
-----------------
|
|
14
|
+
|
|
15
|
+
Other languages are sometimes supported in third-party plugin files, or forks
|
|
16
|
+
which don't upstream their changes, but I try and list them here. I make no
|
|
17
|
+
warranty that these are still maintained or even work.
|
|
18
|
+
* [Puppet](https://github.com/fihuer/starscope/tree/language/puppet)
|
|
19
|
+
|
|
12
20
|
How to Add Another Language
|
|
13
21
|
---------------------------
|
|
14
22
|
|
data/doc/USER_GUIDE.md
CHANGED
|
@@ -109,14 +109,22 @@ Excluded patterns are also remembered, and can be added at any time. If an
|
|
|
109
109
|
existing file in the database matches a newly added exclusion rule, it will be
|
|
110
110
|
removed.
|
|
111
111
|
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
Paths to add and exclude are recursive by default. If you need more control, you
|
|
113
|
+
may use any special characters accepted by Ruby's
|
|
114
|
+
[`File::fnmatch`](https://ruby-doc.org/core-2.6.9/File.html#method-c-fnmatch).
|
|
115
|
+
|
|
116
|
+
You can automatically exclude files on a per-directory basis by creating a
|
|
117
|
+
`.starscope.json` file in a given directory with contents like:
|
|
114
118
|
```json
|
|
115
119
|
{
|
|
116
|
-
"excludes": ["foo", "bar"]
|
|
120
|
+
"excludes": ["foo", "bar/", "**/*.ext"]
|
|
117
121
|
}
|
|
118
122
|
```
|
|
119
|
-
|
|
123
|
+
|
|
124
|
+
For commonly excluded files you can create a home directory config file at
|
|
125
|
+
`~/.starscope.json`. Patterns listed there will be excluded from all starscope
|
|
126
|
+
databases by default. Currently `excludes` is the only valid key for
|
|
127
|
+
`.starscope.json` files.
|
|
120
128
|
|
|
121
129
|
Queries
|
|
122
130
|
-------
|
|
@@ -177,6 +185,8 @@ non-line-mode options:
|
|
|
177
185
|
* `!version` - same as the `--version` flag
|
|
178
186
|
* `!quit` - exit line-mode
|
|
179
187
|
|
|
188
|
+
Abbreviations of special commands are also recognized (e.g. `!q` for `!quit`,
|
|
189
|
+
`!s` for `!summary`, etc).
|
|
180
190
|
|
|
181
191
|
Miscellaneous
|
|
182
192
|
-------------
|
data/lib/starscope/db.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Starscope
|
|
|
17
17
|
FRAGMENT = :'!fragment'
|
|
18
18
|
|
|
19
19
|
# dynamically load all our language extractors
|
|
20
|
-
Dir.glob("#{File.dirname(__FILE__)}/langs/*.rb").each { |path| require path }
|
|
20
|
+
Dir.glob("#{File.dirname(__FILE__)}/langs/*.rb").sort.each { |path| require path }
|
|
21
21
|
|
|
22
22
|
langs = {}
|
|
23
23
|
extractors = []
|
|
@@ -31,6 +31,7 @@ module Starscope
|
|
|
31
31
|
|
|
32
32
|
class NoTableError < StandardError; end
|
|
33
33
|
class UnknownDBFormatError < StandardError; end
|
|
34
|
+
class TooOldDBFormatError < StandardError; end
|
|
34
35
|
|
|
35
36
|
def initialize(output, config = {})
|
|
36
37
|
@output = output
|
|
@@ -84,9 +85,9 @@ module Starscope
|
|
|
84
85
|
paths = paths.map { |p| self.class.normalize_glob(p) }
|
|
85
86
|
@meta[:paths] += paths
|
|
86
87
|
@meta[:paths].uniq!
|
|
87
|
-
files = Dir.glob(paths).select { |f| File.file? f }
|
|
88
|
-
files.delete_if { |f| matches_exclude?(f) }
|
|
88
|
+
files = Dir.glob(paths).select { |f| File.file?(f) && !matches_exclude?(f) }
|
|
89
89
|
return if files.empty?
|
|
90
|
+
|
|
90
91
|
@output.new_pbar('Building', files.length)
|
|
91
92
|
add_files(files)
|
|
92
93
|
@output.finish_pbar
|
|
@@ -149,14 +150,12 @@ module Starscope
|
|
|
149
150
|
|
|
150
151
|
def open_db(filename)
|
|
151
152
|
File.open(filename, 'rb') do |file|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
parse_db(stream)
|
|
155
|
-
end
|
|
156
|
-
rescue Zlib::GzipFile::Error
|
|
157
|
-
file.rewind
|
|
158
|
-
parse_db(file)
|
|
153
|
+
Zlib::GzipReader.wrap(file) do |stream|
|
|
154
|
+
parse_db(stream)
|
|
159
155
|
end
|
|
156
|
+
rescue Zlib::GzipFile::Error
|
|
157
|
+
file.rewind
|
|
158
|
+
parse_db(file)
|
|
160
159
|
end
|
|
161
160
|
end
|
|
162
161
|
|
|
@@ -166,28 +165,26 @@ module Starscope
|
|
|
166
165
|
when DB_FORMAT
|
|
167
166
|
@meta = Oj.load(stream.gets)
|
|
168
167
|
@tables = Oj.load(stream.gets)
|
|
169
|
-
|
|
168
|
+
true
|
|
170
169
|
when 3..4
|
|
171
170
|
# Old format, so read the directories segment then rebuild
|
|
172
171
|
add_paths(Oj.load(stream.gets))
|
|
173
|
-
|
|
172
|
+
false
|
|
174
173
|
when 0..2
|
|
175
|
-
|
|
176
|
-
len = stream.gets.to_i
|
|
177
|
-
add_paths(Marshal.load(stream.read(len)))
|
|
178
|
-
return false
|
|
174
|
+
raise TooOldDBFormatError
|
|
179
175
|
else
|
|
180
176
|
raise UnknownDBFormatError
|
|
181
177
|
end
|
|
182
178
|
rescue Oj::ParseError
|
|
183
179
|
stream.rewind
|
|
184
180
|
raise unless stream.gets.to_i == DB_FORMAT
|
|
181
|
+
|
|
185
182
|
# try reading as formated json, which is much slower, but it is sometimes
|
|
186
183
|
# useful to be able to directly read your db
|
|
187
184
|
objects = []
|
|
188
185
|
Oj.load(stream) { |obj| objects << obj }
|
|
189
186
|
@meta, @tables = objects
|
|
190
|
-
|
|
187
|
+
true
|
|
191
188
|
end
|
|
192
189
|
|
|
193
190
|
def fixup
|
|
@@ -233,7 +230,7 @@ module Starscope
|
|
|
233
230
|
self.class.extractors.each do |extractor|
|
|
234
231
|
begin
|
|
235
232
|
next unless extractor.match_file file
|
|
236
|
-
rescue => e
|
|
233
|
+
rescue StandardError => e
|
|
237
234
|
@output.normal("#{extractor} raised \"#{e}\" while matching #{file}")
|
|
238
235
|
next
|
|
239
236
|
end
|
|
@@ -271,8 +268,7 @@ module Starscope
|
|
|
271
268
|
extract_file(Starscope::FragmentExtractor.new(lang, frags), file, line_cache, lines)
|
|
272
269
|
@meta[:files][file][:sublangs] << lang
|
|
273
270
|
end
|
|
274
|
-
|
|
275
|
-
rescue => e
|
|
271
|
+
rescue StandardError => e
|
|
276
272
|
@output.normal("#{extractor} raised \"#{e}\" while extracting #{file}")
|
|
277
273
|
ensure
|
|
278
274
|
# metadata must be created for any record that was inserted into a tbl
|
|
@@ -280,9 +276,7 @@ module Starscope
|
|
|
280
276
|
@meta[:files][file][:lang] = extractor.name.split('::').last.to_sym
|
|
281
277
|
@meta[:files][file][:lines] = lines
|
|
282
278
|
|
|
283
|
-
if extractor_metadata.is_a? Hash
|
|
284
|
-
@meta[:files][file] = extractor_metadata.merge!(@meta[:files][file])
|
|
285
|
-
end
|
|
279
|
+
@meta[:files][file] = extractor_metadata.merge!(@meta[:files][file]) if extractor_metadata.is_a? Hash
|
|
286
280
|
end
|
|
287
281
|
|
|
288
282
|
def file_changed(name)
|
|
@@ -301,6 +295,7 @@ module Starscope
|
|
|
301
295
|
def language_out_of_date(lang)
|
|
302
296
|
return false unless lang
|
|
303
297
|
return true unless LANGS[lang]
|
|
298
|
+
|
|
304
299
|
(@meta[:langs][lang] || 0) < LANGS[lang]
|
|
305
300
|
end
|
|
306
301
|
|
|
@@ -334,7 +329,8 @@ module Starscope
|
|
|
334
329
|
args
|
|
335
330
|
end
|
|
336
331
|
|
|
337
|
-
|
|
332
|
+
# so we can stub it in tests
|
|
333
|
+
def extractors
|
|
338
334
|
EXTRACTORS
|
|
339
335
|
end
|
|
340
336
|
end
|
data/lib/starscope/exportable.rb
CHANGED
|
@@ -4,6 +4,7 @@ module Starscope
|
|
|
4
4
|
module Exportable
|
|
5
5
|
CTAGS_DEFAULT_PATH = 'tags'.freeze
|
|
6
6
|
CSCOPE_DEFAULT_PATH = 'cscope.out'.freeze
|
|
7
|
+
ASCII = Encoding.find('ASCII')
|
|
7
8
|
|
|
8
9
|
class UnknownExportFormatError < StandardError; end
|
|
9
10
|
|
|
@@ -39,14 +40,14 @@ module Starscope
|
|
|
39
40
|
private
|
|
40
41
|
|
|
41
42
|
def export_ctags(file, path_prefix)
|
|
42
|
-
file.puts
|
|
43
|
-
!_TAG_FILE_FORMAT 2 /extended format/
|
|
44
|
-
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
|
45
|
-
!_TAG_PROGRAM_AUTHOR Evan Huus /eapache@gmail.com/
|
|
46
|
-
!_TAG_PROGRAM_NAME Starscope //
|
|
47
|
-
!_TAG_PROGRAM_URL https://github.com/eapache/starscope //
|
|
48
|
-
!_TAG_PROGRAM_VERSION #{Starscope::VERSION} //
|
|
49
|
-
|
|
43
|
+
file.puts <<~HEADER
|
|
44
|
+
!_TAG_FILE_FORMAT 2 /extended format/
|
|
45
|
+
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
|
46
|
+
!_TAG_PROGRAM_AUTHOR Evan Huus /eapache@gmail.com/
|
|
47
|
+
!_TAG_PROGRAM_NAME Starscope //
|
|
48
|
+
!_TAG_PROGRAM_URL https://github.com/eapache/starscope //
|
|
49
|
+
!_TAG_PROGRAM_VERSION #{Starscope::VERSION} //
|
|
50
|
+
HEADER
|
|
50
51
|
defs = (@tables[:defs] || {}).sort_by { |x| x[:name][-1].to_s }
|
|
51
52
|
defs.each do |record|
|
|
52
53
|
file.puts ctag_line(record, @meta[:files][record[:file]], path_prefix)
|
|
@@ -150,7 +151,7 @@ END
|
|
|
150
151
|
file.print("0\n")
|
|
151
152
|
file.print("#{files.length}\n")
|
|
152
153
|
buf = ''
|
|
153
|
-
files.each { |f| buf << f
|
|
154
|
+
files.each { |f| buf << "#{f}\n" }
|
|
154
155
|
file.print("#{buf.length}\n#{buf}")
|
|
155
156
|
end
|
|
156
157
|
|
|
@@ -159,6 +160,7 @@ END
|
|
|
159
160
|
@tables.each do |tbl, records|
|
|
160
161
|
records.each do |record|
|
|
161
162
|
next unless record[:line_no]
|
|
163
|
+
|
|
162
164
|
record[:tbl] = tbl
|
|
163
165
|
db[record[:file]] ||= {}
|
|
164
166
|
db[record[:file]][record[:line_no]] ||= []
|
|
@@ -177,16 +179,14 @@ END
|
|
|
177
179
|
# use the column if we have it, otherwise fall back to scanning
|
|
178
180
|
index = record[:col] || line.index(key)
|
|
179
181
|
|
|
180
|
-
while index && !valid_index?(line, index, key)
|
|
181
|
-
index = line.index(key, index + 1)
|
|
182
|
-
end
|
|
182
|
+
index = line.index(key, index + 1) while index && !valid_index?(line, index, key)
|
|
183
183
|
|
|
184
184
|
next if index.nil?
|
|
185
185
|
|
|
186
186
|
# Strip trailing non-word characters, otherwise cscope barfs on
|
|
187
187
|
# function names like `include?`
|
|
188
188
|
if key =~ /^\W*$/
|
|
189
|
-
next unless [
|
|
189
|
+
next unless %i[defs end].include?(record[:tbl])
|
|
190
190
|
else
|
|
191
191
|
key.sub!(/\W+$/, '')
|
|
192
192
|
end
|
|
@@ -209,25 +209,23 @@ END
|
|
|
209
209
|
|
|
210
210
|
index = line.index(key, prev)
|
|
211
211
|
|
|
212
|
-
while index && index + key.length < offset && !valid_index?(line, index, key)
|
|
213
|
-
index = line.index(key, index + 1)
|
|
214
|
-
end
|
|
212
|
+
index = line.index(key, index + 1) while index && index + key.length < offset && !valid_index?(line, index, key)
|
|
215
213
|
|
|
216
214
|
next unless index && index + key.length < offset
|
|
217
215
|
|
|
218
216
|
buf << cscope_plaintext(line, prev, index) << "\n"
|
|
219
|
-
buf << "#{key}\n"
|
|
217
|
+
buf << "#{strip_unicode(key)}\n"
|
|
220
218
|
prev = index + key.length
|
|
221
219
|
end
|
|
222
220
|
|
|
223
221
|
buf << cscope_plaintext(line, prev, offset) << "\n"
|
|
224
|
-
buf << cscope_mark(record) << record[:key] << "\n"
|
|
222
|
+
buf << cscope_mark(record) << strip_unicode(record[:key]) << "\n"
|
|
225
223
|
|
|
226
224
|
buf << CSCOPE_GLOBAL_HACK_START if record[:type] == :func && record[:tbl] == :end
|
|
227
225
|
buf
|
|
228
226
|
rescue ArgumentError
|
|
229
227
|
# invalid utf-8 byte sequence in the line, oh well
|
|
230
|
-
line
|
|
228
|
+
strip_unicode(line)
|
|
231
229
|
end
|
|
232
230
|
|
|
233
231
|
def valid_index?(line, index, key)
|
|
@@ -242,10 +240,10 @@ END
|
|
|
242
240
|
ret.lstrip! if start == 0
|
|
243
241
|
ret.rstrip! if stop == line.length
|
|
244
242
|
ret.gsub!(/\s+/, ' ')
|
|
245
|
-
ret.empty? ? ' ' : ret
|
|
243
|
+
ret.empty? ? ' ' : strip_unicode(ret)
|
|
246
244
|
rescue ArgumentError
|
|
247
245
|
# invalid utf-8 byte sequence in the line, oh well
|
|
248
|
-
line
|
|
246
|
+
strip_unicode(line)
|
|
249
247
|
end
|
|
250
248
|
|
|
251
249
|
def cscope_mark(rec)
|
|
@@ -260,16 +258,16 @@ END
|
|
|
260
258
|
when :file
|
|
261
259
|
ret = '@'
|
|
262
260
|
when :defs
|
|
263
|
-
case rec[:type]
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
261
|
+
ret = case rec[:type]
|
|
262
|
+
when :func
|
|
263
|
+
'$'
|
|
264
|
+
when :class, :module
|
|
265
|
+
'c'
|
|
266
|
+
when :type
|
|
267
|
+
't'
|
|
268
|
+
else
|
|
269
|
+
'g'
|
|
270
|
+
end
|
|
273
271
|
when :calls
|
|
274
272
|
ret = '`'
|
|
275
273
|
when :requires
|
|
@@ -282,7 +280,11 @@ END
|
|
|
282
280
|
return ''
|
|
283
281
|
end
|
|
284
282
|
|
|
285
|
-
"\t"
|
|
283
|
+
"\t#{ret}"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def strip_unicode(str)
|
|
287
|
+
str.encode(ASCII, invalid: :replace, undef: :replace, replace: '')
|
|
286
288
|
end
|
|
287
289
|
end
|
|
288
290
|
end
|
|
@@ -5,16 +5,15 @@ module Starscope
|
|
|
5
5
|
@frags = frags
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
def extract(path,
|
|
9
|
-
|
|
8
|
+
def extract(path, _text)
|
|
9
|
+
compiled_text = @frags.map { |f| f.delete(:frag).strip }.join("\n")
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
@child.extract(path, compiled_text) do |tbl, name, args|
|
|
12
12
|
args.merge!(@frags[args[:line_no] - 1]) if args[:line_no]
|
|
13
13
|
yield tbl, name, args
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# TODO: translate metadata?
|
|
17
|
-
extractor_metadata
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
def name
|