starscope 0.0.8 → 0.1.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.
data/CHANGELOG.md CHANGED
@@ -1,7 +1,23 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- v0.0.8 (trunk)
4
+ v0.1.0 (trunk)
5
+ -------------------
6
+
7
+ New Features:
8
+ * Progress bar when building or updating database.
9
+
10
+ Bug Fixes:
11
+ * Handle the case when a ruby file produces a nil parse tree.
12
+ * Many misc fixes.
13
+
14
+ Internals:
15
+ * Another new version of the ruby parser.
16
+ * Replace the default JSON module with Oj, which is more than twice as fast for
17
+ large databases.
18
+ * Misc optimizations.
19
+
20
+ v0.0.8 (2013-07-20)
5
21
  -------------------
6
22
 
7
23
  Bug Fixes:
data/Gemfile.lock CHANGED
@@ -1,8 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- starscope (0.0.8)
5
- parser (= 2.0.0.pre2)
4
+ starscope (0.1.0)
5
+ oj (~> 2.1)
6
+ parser (= 2.0.0.pre6)
7
+ ruby-progressbar (~> 1.1)
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
@@ -17,7 +19,8 @@ GEM
17
19
  debugger-linecache (1.2.0)
18
20
  debugger-ruby_core_source (1.2.2)
19
21
  method_source (0.8.1)
20
- parser (2.0.0.pre2)
22
+ oj (2.1.4)
23
+ parser (2.0.0.pre6)
21
24
  ast (~> 1.1)
22
25
  slop (~> 3.4, >= 3.4.5)
23
26
  pry (0.9.12.2)
@@ -28,6 +31,7 @@ GEM
28
31
  debugger (~> 1.3)
29
32
  pry (~> 0.9.10)
30
33
  rake (10.0.4)
34
+ ruby-progressbar (1.1.1)
31
35
  slop (3.4.5)
32
36
 
33
37
  PLATFORMS
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  StarScope
2
2
  =========
3
3
 
4
+ https://rubygems.org/gems/starscope
5
+
4
6
  *Note to those users looking at the GitHub language statistics: there is no perl
5
7
  here, that is their bug to fix.*
6
8
 
data/TODO.md CHANGED
@@ -1,6 +1,7 @@
1
1
  TODO
2
2
  =========
3
3
 
4
+ * Add --quiet to hide progress bar and --verbose to print each file
4
5
  * Parallelization, perhaps via https://github.com/grosser/parallel
5
6
  * Export advanced ctags annotations
6
7
  * Export to cscope format
data/bin/starscope CHANGED
@@ -72,9 +72,10 @@ end
72
72
  def run_query(db, table, value)
73
73
  if not value
74
74
  $stderr.puts "Invalid input - no query found."
75
- return
75
+ return false
76
76
  end
77
- puts db.query(table.to_sym, value).map {|val| StarScope::Datum.to_s(val)}
77
+ key, results = db.query(table.to_sym, value)
78
+ puts results.map {|val| StarScope::Datum.to_s(key, val)} if results
78
79
  return true
79
80
  rescue StarScope::DB::NoTableError
80
81
  $stderr.puts "Table '#{table}' doesn't exist."
@@ -95,6 +96,7 @@ end
95
96
 
96
97
  if options[:auto] and not options[:write]
97
98
  options[:write] = DEFAULT_DB
99
+ options[:auto_write] = true
98
100
  end
99
101
 
100
102
  if File.exists?(DEFAULT_DB) and not options[:read]
@@ -105,16 +107,21 @@ db = StarScope::DB.new
105
107
 
106
108
  if options[:read]
107
109
  db.load(options[:read])
108
- db.add_dirs(ARGV)
110
+ if !ARGV.empty?
111
+ db.add_paths(ARGV)
112
+ new_data = true
113
+ end
109
114
  elsif ARGV.empty?
110
- db.add_dirs(['.'])
115
+ db.add_paths(['.'])
116
+ new_data = true
111
117
  else
112
- db.add_dirs(ARGV)
118
+ db.add_paths(ARGV)
119
+ new_data = true
113
120
  end
114
121
 
115
- db.update if options[:read] and options[:auto]
122
+ changed = db.update if options[:read] and options[:auto]
116
123
 
117
- db.save(options[:write]) if options[:write]
124
+ db.save(options[:write]) if options[:write] and (new_data or changed or not options[:auto_write])
118
125
 
119
126
  if options[:export]
120
127
  format, path = options[:export].split(',', 2)
@@ -166,8 +173,8 @@ if options[:linemode]
166
173
  when "summary"
167
174
  print_summary(db)
168
175
  when "update"
169
- db.update
170
- db.save(options[:write]) if options[:write]
176
+ changed = db.update
177
+ db.save(options[:write]) if options[:write] and changed
171
178
  when "help"
172
179
  puts linemode_help
173
180
  when "version"
@@ -1,7 +1,6 @@
1
1
  class StarScope::Datum
2
2
 
3
- def self.build(key, file, args)
4
- args[:key] = key
3
+ def self.build(file, args)
5
4
  args[:file] = file
6
5
 
7
6
  if args[:line_no]
@@ -35,14 +34,14 @@ class StarScope::Datum
35
34
  "#{dat[:file]}:#{dat[:line_no]}"
36
35
  end
37
36
 
38
- def self.to_s(dat)
37
+ def self.to_s(key, dat)
39
38
  str = ""
40
39
  str << "#{dat[:scope].join " "} " unless dat[:scope].empty?
41
- str << "#{dat[:key]} -- #{location dat}"
40
+ str << "#{key} -- #{location dat}"
42
41
  str << " (#{dat[:line].strip})"
43
42
  end
44
43
 
45
- def self.ctag_line(dat)
46
- "#{dat[:key]}\t#{dat[:file]}\t/^#{dat[:line]}$/;"
44
+ def self.ctag_line(key, dat)
45
+ "#{key}\t#{dat[:file]}\t/^#{dat[:line]}$/;"
47
46
  end
48
47
  end
data/lib/starscope/db.rb CHANGED
@@ -1,20 +1,22 @@
1
1
  require 'starscope/langs/ruby'
2
2
  require 'starscope/datum'
3
3
  require 'date'
4
- require 'json'
4
+ require 'oj'
5
5
  require 'zlib'
6
+ require 'ruby-progressbar'
6
7
 
7
8
  LANGS = [StarScope::Lang::Ruby]
8
9
 
9
10
  class StarScope::DB
10
11
 
11
12
  DB_FORMAT = 3
13
+ PBAR_FORMAT = '%t: %c/%C %E ||%b>%i||'
12
14
 
13
15
  class NoTableError < StandardError; end
14
16
  class UnknownDBFormatError < StandardError; end
15
17
 
16
18
  def initialize
17
- @dirs = []
19
+ @paths = []
18
20
  @files = {}
19
21
  @tables = {}
20
22
  end
@@ -24,16 +26,16 @@ class StarScope::DB
24
26
  Zlib::GzipReader.wrap(file) do |file|
25
27
  format = file.gets.to_i
26
28
  if format == DB_FORMAT
27
- @dirs = JSON.parse(file.gets, symbolize_names: false)
28
- @files = JSON.parse(file.gets, symbolize_names: false)
29
- @tables = JSON.parse(file.gets, symbolize_names: true)
29
+ @paths = Oj.load(file.gets)
30
+ @files = Oj.load(file.gets)
31
+ @tables = Oj.load(file.gets, symbol_keys: true)
30
32
  elsif format <= 2
31
33
  # Old format (pre-json), so read the directories segment then rebuild
32
34
  len = file.gets.to_i
33
- add_dirs(Marshal::load(file.read(len)))
35
+ add_paths(Marshal::load(file.read(len)))
34
36
  elsif format < DB_FORMAT
35
37
  # Old format, so read the directories segment then rebuild
36
- add_dirs(JSON.parse(file.gets, symbolize_names: false))
38
+ add_paths(Oj.load(file.gets))
37
39
  elsif format > DB_FORMAT
38
40
  raise UnknownDBFormatError
39
41
  end
@@ -45,26 +47,39 @@ class StarScope::DB
45
47
  File.open(file, 'w') do |file|
46
48
  Zlib::GzipWriter.wrap(file) do |file|
47
49
  file.puts DB_FORMAT
48
- file.puts JSON.fast_generate @dirs
49
- file.puts JSON.fast_generate @files
50
- file.puts JSON.fast_generate @tables
50
+ file.puts Oj.dump @paths
51
+ file.puts Oj.dump @files
52
+ file.puts Oj.dump @tables
51
53
  end
52
54
  end
53
55
  end
54
56
 
55
- def add_dirs(dirs)
56
- @dirs += dirs
57
- dirs.each do |dir|
58
- Dir["#{dir}/**/*"].each do |file|
59
- add_file(file)
60
- end
57
+ def add_paths(paths)
58
+ paths -= @paths
59
+ return if paths.empty?
60
+ @paths += paths
61
+ files = paths.map {|p| self.class.files_from_path(p)}.flatten
62
+ return if files.empty?
63
+ pbar = ProgressBar.create(title: "Building", total: files.length, format: PBAR_FORMAT, length: 80)
64
+ files.each do |f|
65
+ add_file(f)
66
+ pbar.increment
61
67
  end
62
68
  end
63
69
 
64
70
  def update
65
- @files.keys.each {|f| update_file(f)}
66
- cur_files = @dirs.each {|d| Dir["#{d}/**/*"]}.flatten
67
- (cur_files - @files.keys).each {|f| add_file(f)}
71
+ new_files = (@paths.map {|p| self.class.files_from_path(p)}.flatten) - @files.keys
72
+ pbar = ProgressBar.create(title: "Updating", total: new_files.length + @files.length, format: PBAR_FORMAT, length: 80)
73
+ changed = @files.keys.map do |f|
74
+ changed = update_file(f)
75
+ pbar.increment
76
+ changed
77
+ end
78
+ new_files.each do |f|
79
+ add_file(f)
80
+ pbar.increment
81
+ end
82
+ changed.any? || !new_files.empty?
68
83
  end
69
84
 
70
85
  def dump_table(table)
@@ -74,7 +89,7 @@ class StarScope::DB
74
89
  puts "#{val}"
75
90
  data.each do |datum|
76
91
  print "\t"
77
- puts StarScope::Datum.to_s(datum)
92
+ puts StarScope::Datum.to_s(val, datum)
78
93
  end
79
94
  end
80
95
  end
@@ -96,15 +111,17 @@ class StarScope::DB
96
111
  def query(table, value)
97
112
  fqn = value.split("::")
98
113
  raise NoTableError if not @tables[table]
99
- results = @tables[table][fqn.last.to_sym]
114
+ key = fqn.last.to_sym
115
+ results = @tables[table][key]
100
116
  return [] if results.nil? || results.empty?
101
117
  results.sort! do |a,b|
102
118
  StarScope::Datum.score_match(b, fqn) <=> StarScope::Datum.score_match(a, fqn)
103
119
  end
104
120
  best_score = StarScope::Datum.score_match(results[0], fqn)
105
- results.select do |result|
121
+ results = results.select do |result|
106
122
  best_score - StarScope::Datum.score_match(result, fqn) < 4
107
123
  end
124
+ return key, results
108
125
  end
109
126
 
110
127
  def export_ctags(filename)
@@ -120,7 +137,7 @@ END
120
137
  defs = (@tables[:defs] || []).sort {|a,b| a <=> b}
121
138
  defs.each do |key, val|
122
139
  val.each do |entry|
123
- file.puts StarScope::Datum.ctag_line(entry)
140
+ file.puts StarScope::Datum.ctag_line(key, entry)
124
141
  end
125
142
  end
126
143
  end
@@ -128,6 +145,16 @@ END
128
145
 
129
146
  private
130
147
 
148
+ def self.files_from_path(path)
149
+ if File.file?(path)
150
+ [path]
151
+ elsif File.directory?(path)
152
+ Dir[File.join(path, "**", "*")].select {|p| File.file?(p)}
153
+ else
154
+ []
155
+ end
156
+ end
157
+
131
158
  def add_file(file)
132
159
  return if not File.file? file
133
160
 
@@ -138,7 +165,7 @@ END
138
165
  lang.extract file do |tbl, key, args|
139
166
  @tables[tbl] ||= {}
140
167
  @tables[tbl][key] ||= []
141
- @tables[tbl][key] << StarScope::Datum.build(key, file, args)
168
+ @tables[tbl][key] << StarScope::Datum.build(file, args)
142
169
  end
143
170
  end
144
171
  end
@@ -153,11 +180,15 @@ END
153
180
  end
154
181
 
155
182
  def update_file(file)
156
- if not File.exists?(file)
183
+ if not File.exists?(file) or not File.file?(file)
157
184
  remove_file(file)
185
+ true
158
186
  elsif DateTime.parse(@files[file]).to_time < File.mtime(file)
159
187
  remove_file(file)
160
188
  add_file(file)
189
+ true
190
+ else
191
+ false
161
192
  end
162
193
  end
163
194
 
@@ -3,7 +3,7 @@ require "parser/current"
3
3
  module StarScope::Lang
4
4
  module Ruby
5
5
  def self.match_file(name)
6
- name =~ /.*\.rb/
6
+ name =~ /.*\.rb$/
7
7
  end
8
8
 
9
9
  def self.extract(file, &block)
@@ -24,7 +24,7 @@ module StarScope::Lang
24
24
  end
25
25
 
26
26
  def extract(&block)
27
- extract_tree(@ast, &block)
27
+ extract_tree(@ast, &block) if not @ast.nil?
28
28
  end
29
29
 
30
30
  private
@@ -44,37 +44,36 @@ module StarScope::Lang
44
44
  end
45
45
 
46
46
  def extract_node(node)
47
- if node.type == :send
47
+ case node.type
48
+ when :send
48
49
  fqn = scoped_name(node)
49
- yield :calls, fqn.last, line_no: node.location.expression.line,
50
+ yield :calls, fqn.last,
51
+ line_no: node.location.expression.line,
50
52
  scope: fqn[0...-1]
51
-
52
53
  if node.children[0].nil? and node.children[1] == :require and node.children[2].type == :str
53
54
  fqn = node.children[2].children[0].split("/")
54
- yield :requires, fqn.last, line_no: node.location.expression.line,
55
+ yield :requires, fqn.last,
56
+ line_no: node.location.expression.line,
55
57
  scope: fqn[0...-1]
56
58
  end
57
- end
58
-
59
- if node.type == :def
59
+ when :def
60
60
  yield :defs, node.children[0],
61
61
  line_no: node.location.expression.line,
62
62
  scope: @scope
63
- elsif node.type == :defs
63
+ when :defs
64
64
  yield :defs, node.children[1],
65
65
  line_no: node.location.expression.line,
66
66
  scope: @scope
67
- elsif [:module, :class].include? node.type
67
+ when :module, :class
68
68
  fqn = @scope + scoped_name(node.children[0])
69
69
  yield :defs, fqn.last, line_no: node.location.expression.line,
70
70
  scope: fqn[0...-1]
71
- end
72
-
73
- if node.type == :casgn
71
+ when :casgn
74
72
  fqn = scoped_name(node)
75
- yield :assigns, fqn.last, line_no: node.location.expression.line,
73
+ yield :assigns, fqn.last,
74
+ line_no: node.location.expression.line,
76
75
  scope: fqn[0...-1]
77
- elsif [:lvasgn, :ivasgn, :cvasgn, :gvasgn].include? node.type
76
+ when :lvasgn, :ivasgn, :cvasgn, :gvasgn
78
77
  yield :assigns, node.children[0],
79
78
  line_no: node.location.expression.line,
80
79
  scope: @scope
@@ -1,3 +1,3 @@
1
1
  module StarScope
2
- VERSION = "0.0.8"
2
+ VERSION = "0.1.0"
3
3
  end
data/starscope.gemspec CHANGED
@@ -13,7 +13,9 @@ Gem::Specification.new do |gem|
13
13
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
14
  gem.require_paths = ["lib"]
15
15
 
16
- gem.add_dependency 'parser', '= 2.0.0.pre2'
16
+ gem.add_dependency 'oj', '~> 2.1'
17
+ gem.add_dependency 'parser', '= 2.0.0.pre6'
18
+ gem.add_dependency 'ruby-progressbar', '~> 1.1'
17
19
  gem.add_development_dependency 'bundler', '~> 1.3'
18
20
  gem.add_development_dependency 'rake'
19
21
  gem.add_development_dependency 'pry'
metadata CHANGED
@@ -1,96 +1,128 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: starscope
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
5
4
  prerelease:
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Evan Huus
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-20 00:00:00.000000000 Z
12
+ date: 2013-08-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: parser
16
- requirement: !ruby/object:Gem::Requirement
15
+ prerelease: false
16
+ name: oj
17
+ type: :runtime
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '2.1'
17
23
  none: false
24
+ requirement: !ruby/object:Gem::Requirement
18
25
  requirements:
19
- - - '='
26
+ - - ~>
20
27
  - !ruby/object:Gem::Version
21
- version: 2.0.0.pre2
22
- type: :runtime
28
+ version: '2.1'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
23
31
  prerelease: false
32
+ name: parser
33
+ type: :runtime
24
34
  version_requirements: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '='
37
+ - !ruby/object:Gem::Version
38
+ version: 2.0.0.pre6
25
39
  none: false
40
+ requirement: !ruby/object:Gem::Requirement
26
41
  requirements:
27
42
  - - '='
28
43
  - !ruby/object:Gem::Version
29
- version: 2.0.0.pre2
44
+ version: 2.0.0.pre6
45
+ none: false
30
46
  - !ruby/object:Gem::Dependency
31
- name: bundler
32
- requirement: !ruby/object:Gem::Requirement
47
+ prerelease: false
48
+ name: ruby-progressbar
49
+ type: :runtime
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
33
55
  none: false
56
+ requirement: !ruby/object:Gem::Requirement
34
57
  requirements:
35
58
  - - ~>
36
59
  - !ruby/object:Gem::Version
37
- version: '1.3'
38
- type: :development
60
+ version: '1.1'
61
+ none: false
62
+ - !ruby/object:Gem::Dependency
39
63
  prerelease: false
64
+ name: bundler
65
+ type: :development
40
66
  version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: '1.3'
41
71
  none: false
72
+ requirement: !ruby/object:Gem::Requirement
42
73
  requirements:
43
74
  - - ~>
44
75
  - !ruby/object:Gem::Version
45
76
  version: '1.3'
77
+ none: false
46
78
  - !ruby/object:Gem::Dependency
79
+ prerelease: false
47
80
  name: rake
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
81
+ type: :development
82
+ version_requirements: !ruby/object:Gem::Requirement
50
83
  requirements:
51
84
  - - ! '>='
52
85
  - !ruby/object:Gem::Version
53
86
  version: '0'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
87
  none: false
88
+ requirement: !ruby/object:Gem::Requirement
58
89
  requirements:
59
90
  - - ! '>='
60
91
  - !ruby/object:Gem::Version
61
92
  version: '0'
93
+ none: false
62
94
  - !ruby/object:Gem::Dependency
95
+ prerelease: false
63
96
  name: pry
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
97
+ type: :development
98
+ version_requirements: !ruby/object:Gem::Requirement
66
99
  requirements:
67
100
  - - ! '>='
68
101
  - !ruby/object:Gem::Version
69
102
  version: '0'
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
103
  none: false
104
+ requirement: !ruby/object:Gem::Requirement
74
105
  requirements:
75
106
  - - ! '>='
76
107
  - !ruby/object:Gem::Version
77
108
  version: '0'
109
+ none: false
78
110
  - !ruby/object:Gem::Dependency
111
+ prerelease: false
79
112
  name: pry-debugger
80
- requirement: !ruby/object:Gem::Requirement
81
- none: false
113
+ type: :development
114
+ version_requirements: !ruby/object:Gem::Requirement
82
115
  requirements:
83
116
  - - ! '>='
84
117
  - !ruby/object:Gem::Version
85
118
  version: '0'
86
- type: :development
87
- prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
119
  none: false
120
+ requirement: !ruby/object:Gem::Requirement
90
121
  requirements:
91
122
  - - ! '>='
92
123
  - !ruby/object:Gem::Version
93
124
  version: '0'
125
+ none: false
94
126
  description: A tool like the venerable cscope, but for ruby and other languages
95
127
  email: eapache@gmail.com
96
128
  executables:
@@ -122,23 +154,23 @@ rdoc_options: []
122
154
  require_paths:
123
155
  - lib
124
156
  required_ruby_version: !ruby/object:Gem::Requirement
125
- none: false
126
157
  requirements:
127
158
  - - ! '>='
128
159
  - !ruby/object:Gem::Version
129
- version: '0'
130
160
  segments:
131
161
  - 0
132
- hash: -2279719336139896086
133
- required_rubygems_version: !ruby/object:Gem::Requirement
162
+ hash: -4533453239802094474
163
+ version: '0'
134
164
  none: false
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
166
  requirements:
136
167
  - - ! '>='
137
168
  - !ruby/object:Gem::Version
138
- version: '0'
139
169
  segments:
140
170
  - 0
141
- hash: -2279719336139896086
171
+ hash: -4533453239802094474
172
+ version: '0'
173
+ none: false
142
174
  requirements: []
143
175
  rubyforge_project:
144
176
  rubygems_version: 1.8.23