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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 16cc0b7d5c3226ca3680b475dfcd923348352d9f
4
- data.tar.gz: f3c98060b7b84c54fc13fab3469387f691dfb76f
2
+ SHA256:
3
+ metadata.gz: d71f7d9d5748e9df63987f08669e56866a5669a7877a5b78bec7274ae6b11e3b
4
+ data.tar.gz: a037cc0b16644f69a37c1d9a00f076a036353cb84cbcaef39e17f864af2c70eb
5
5
  SHA512:
6
- metadata.gz: 6b56db7031396663009a1d062b7444ada17e3d103f2bb972e6bd94b6211eb22a4a44d3891ae1e9a01dc8317800d64438c3f45d4fa25fc8dd17e8e8e1f9ce36bc
7
- data.tar.gz: 7080292f2aaa289b20733edf0a40594ad213864cdda3b7c014143aae6405c51aa142993b52058313f8ddfa0703401db21c47eec0b7d30cfcc36de94648c344b4
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
- - 'test/fixtures/sample_ruby.rb'
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
- [![Build Status](https://travis-ci.org/eapache/starscope.svg?branch=master)](https://travis-ci.org/eapache/starscope)
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: [:test, :rubocop]
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('../../lib', __FILE__)
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 = <<END
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
- END
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
- $stderr.puts "Can't be both verbose and quiet"
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
- $stderr.puts "Can't be both verbose and quiet"
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 <<END
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
- END
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("%-9s %6d records\n", table, db.records(table).length)
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
- $stderr.puts 'Invalid input - no query found.'
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
- return true
149
+ true
150
150
  rescue Starscope::DB::NoTableError
151
- $stderr.puts "Table '#{table}' doesn't exist."
152
- return false
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..-1].to_sym)
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
- return true
182
+ true
183
183
  rescue Starscope::DB::NoTableError
184
- $stderr.puts "Table '#{table}' doesn't exist."
185
- return false
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
- $stderr.puts "Unrecognized export format \"#{format}\""
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
- <<END
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
- END
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..-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'."
@@ -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
- For commonly excluded files you can create a `~/.starscope.json` file with
113
- contents like:
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
- Patterns listed there will be excluded from all starscope databases by default.
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
- begin
153
- Zlib::GzipReader.wrap(file) do |stream|
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
- return true
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
- return false
172
+ false
174
173
  when 0..2
175
- # Old format (pre-json), so read the directories segment then rebuild
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
- return true
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
- def extractors # so we can stub it in tests
332
+ # so we can stub it in tests
333
+ def extractors
338
334
  EXTRACTORS
339
335
  end
340
336
  end
@@ -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 <<END
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
- END
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 + "\n" }
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 [:defs, :end].include?(record[:tbl])
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
- when :func
265
- ret = '$'
266
- when :class, :module
267
- ret = 'c'
268
- when :type
269
- ret = 't'
270
- else
271
- ret = 'g'
272
- end
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" + ret
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, text)
9
- text = @frags.map { |f| f.delete(:frag).strip }.join("\n")
8
+ def extract(path, _text)
9
+ compiled_text = @frags.map { |f| f.delete(:frag).strip }.join("\n")
10
10
 
11
- extractor_metadata = @child.extract(path, text) do |tbl, name, args|
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