starscope 1.5.7 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://img.shields.io/gem/v/starscope.svg)](https://rubygems.org/gems/starscope)
|
5
|
-
[![
|
5
|
+
[![Ruby CI](https://github.com/eapache/starscope/actions/workflows/ruby-ci.yml/badge.svg)](https://github.com/eapache/starscope/actions/workflows/ruby-ci.yml)
|
6
6
|
[![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-active-blue.svg)](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
|