starscope 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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