ruby_scope 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +45 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/bin/ruby_scope +5 -0
- data/lib/ruby_scope.rb +20 -0
- data/lib/ruby_scope/cli.rb +115 -0
- data/lib/ruby_scope/scanner.rb +92 -0
- data/lib/ruby_scope/sexp_cache.rb +45 -0
- data/test/integration/console_test.rb +51 -0
- data/test/test_helper.rb +5 -0
- data/test/unit/cli_test.rb +41 -0
- data/test/unit/scanner_test.rb +33 -0
- data/test/unit/sexp_cache_test.rb +42 -0
- metadata +109 -0
data/README.markdown
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
RubyScope
|
2
|
+
---------
|
3
|
+
Ruby colored binoculars for your code.
|
4
|
+
|
5
|
+
Usage: ruby_scope [options] path
|
6
|
+
|
7
|
+
Queries:
|
8
|
+
--def NAME Find the definition of instance method NAME
|
9
|
+
--class-def NAME Find the definition of class method NAME
|
10
|
+
--call NAME Find method calls of NAME
|
11
|
+
--class NAME Find definition of NAME
|
12
|
+
--variable NAME Find references to variable NAME
|
13
|
+
--assign NAME Find assignments to NAME
|
14
|
+
--any NAME Find any reference to NAME (class, variable, number)
|
15
|
+
--custom SEXP_PATH Searches for a custom SexpPath
|
16
|
+
|
17
|
+
Options:
|
18
|
+
-R Recursively search folders
|
19
|
+
--no-cache Do not use a cache
|
20
|
+
--cache PATH Use the cache at PATH (defaults to current dir)
|
21
|
+
-v, --verbose Verbose output
|
22
|
+
-h, --help Show this message
|
23
|
+
|
24
|
+
Find all the places `run` or `save` are called in your secret project:
|
25
|
+
|
26
|
+
ruby_scope -R --method 'run' --method 'save' ~/SecretProject
|
27
|
+
|
28
|
+
Where do I assign values to `a`:
|
29
|
+
|
30
|
+
ruby_scope -R --assign 'a' ~/SecretProject
|
31
|
+
|
32
|
+
Of course regular expressions are fair game:
|
33
|
+
|
34
|
+
ruby_scope -R --def '/^test/' ~/SecretProject
|
35
|
+
|
36
|
+
Wicked hacker? Go crazy and write your own SexpPath queries:
|
37
|
+
|
38
|
+
ruby_scope --custom 's(:call, s(:ivar, atom), :save, _)'
|
39
|
+
|
40
|
+
That finds all the saves on instance variables by the way.
|
41
|
+
|
42
|
+
Depends on RubyParser, SexpProcessor, and SexpPath, no gem yet.
|
43
|
+
|
44
|
+
Adam Sanderson
|
45
|
+
netghost@gmail.com
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
|
8
|
+
Jeweler::Tasks.new do |s|
|
9
|
+
s.name = "ruby_scope"
|
10
|
+
s.summary = "Ruby colored binoluars for your code."
|
11
|
+
s.description = <<-DESC
|
12
|
+
A ruby hacker's search tool. Quickly interrogate your code, seek out
|
13
|
+
classes, methods, variable assignments, and more.
|
14
|
+
DESC
|
15
|
+
s.email = "netghost@gmail.com"
|
16
|
+
s.homepage = "http://github.com/adamsanderson/ruby_scope"
|
17
|
+
s.authors = ["Adam Sanderson"]
|
18
|
+
s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
|
19
|
+
|
20
|
+
s.add_dependency 'sexp_processor', '~> 3.0'
|
21
|
+
s.add_dependency 'ruby_parser', '~> 2.0'
|
22
|
+
s.add_dependency 'sexp_path', '>= 0.4'
|
23
|
+
|
24
|
+
# Testing
|
25
|
+
s.test_files = FileList["test/**/*_test.rb"]
|
26
|
+
s.add_development_dependency 'mocha', '>= 0.9.8'
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue LoadError
|
30
|
+
puts "Jeweler not available. Install it for jeweler-related tasks with: sudo gem install jeweler"
|
31
|
+
end
|
32
|
+
|
33
|
+
Rake::RDocTask.new do |t|
|
34
|
+
#t.main = "README.rdoc"
|
35
|
+
t.rdoc_files.include("lib/**/*.rb")
|
36
|
+
end
|
37
|
+
|
38
|
+
Rake::TestTask.new do |t|
|
39
|
+
t.test_files = FileList['test/**/*_test.rb']
|
40
|
+
t.verbose = false
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :test do
|
44
|
+
['unit', 'integration'].each do |type|
|
45
|
+
Rake::TestTask.new(type) do |t|
|
46
|
+
t.test_files = FileList["test/#{type}/**/*_test.rb"]
|
47
|
+
t.verbose = false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/bin/ruby_scope
ADDED
data/lib/ruby_scope.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ruby_parser'
|
3
|
+
require 'sexp_path'
|
4
|
+
require 'unified_ruby'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
# RubyScope is a command line tool designed to help you scan ruby code lexically.
|
8
|
+
# See the README for more information.
|
9
|
+
module RubyScope
|
10
|
+
end
|
11
|
+
|
12
|
+
# Load RubyScope
|
13
|
+
root = File.dirname(__FILE__)+'/ruby_scope/'
|
14
|
+
%w[
|
15
|
+
scanner
|
16
|
+
sexp_cache
|
17
|
+
cli
|
18
|
+
].each do |file|
|
19
|
+
require root+file
|
20
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
class RubyScope::CLI
|
2
|
+
attr_reader :paths
|
3
|
+
attr_reader :cache_path
|
4
|
+
attr_reader :scanner
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
args = args.clone
|
8
|
+
@scanner = RubyScope::Scanner.new
|
9
|
+
@cache_path = FileUtils.pwd
|
10
|
+
|
11
|
+
opts = OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: ruby_scope [options] queries path"
|
13
|
+
|
14
|
+
opts.separator ""
|
15
|
+
opts.separator "Queries:"
|
16
|
+
|
17
|
+
opts.on("--def NAME", "Find the definition of instance method NAME") do |name|
|
18
|
+
@scanner.add_query("s(:defn, #{v name}, _, _)")
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("--class-def NAME", "Find the definition of class method NAME") do |name|
|
22
|
+
@scanner.add_query("s(:defs, _, #{v name}, _, _)")
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("--call NAME", "Find method calls of NAME") do |name|
|
26
|
+
@scanner.add_query("s(:call, _, #{v name}, _)")
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("--class NAME", "Find definition of NAME") do |name|
|
30
|
+
@scanner.add_query("s(:class, #{v name}, _, _)")
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("--variable NAME", "Find references to variable NAME") do |name|
|
34
|
+
tag = instance_variable?(name) ? 'ivar' : 'lvar'
|
35
|
+
@scanner.add_query("s(:#{tag}, #{v name})")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Finds block arguments, variable assignments, method arguments (in that order)
|
39
|
+
opts.on("--assign NAME", "Find assignments to NAME") do |name|
|
40
|
+
tag = instance_variable?(name) ? 'iasgn' : 'lasgn'
|
41
|
+
@scanner.add_query("s(:#{tag}, #{v name}) | s(:#{tag}, #{v name}, _) | (t(:args) & SexpPath::Matcher::Block.new{|s| s[1..-1].any?{|a| a == #{v name}}} )")
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("--any NAME", "Find any reference to NAME (class, variable, number)") do |name|
|
45
|
+
@scanner.add_query("include(#{v name})")
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("--custom SEXP_PATH", "Search for a custom SexpPath") do |sexp|
|
49
|
+
@scanner.add_query(sexp)
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.separator ""
|
53
|
+
opts.separator "Options:"
|
54
|
+
opts.on("-R", "Recursively search folders") do
|
55
|
+
@recurse = true
|
56
|
+
end
|
57
|
+
|
58
|
+
opts.on("--no-cache", "Do not use a cache") do
|
59
|
+
@cache_path = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("--cache PATH", "Use the cache at PATH (defaults to current dir)", "Beware, the cache can get rather large") do |path|
|
63
|
+
@cache_path = path if path
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on("-v", "--verbose", "Verbose output") do
|
67
|
+
@scanner.verbose = true
|
68
|
+
end
|
69
|
+
|
70
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
71
|
+
puts opts
|
72
|
+
exit
|
73
|
+
end
|
74
|
+
end
|
75
|
+
opts.parse!(args)
|
76
|
+
|
77
|
+
@paths = args
|
78
|
+
|
79
|
+
if @paths.empty?
|
80
|
+
puts opts
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
|
84
|
+
@paths = expand_paths(@paths) if @recurse
|
85
|
+
@scanner.cache = RubyScope::SexpCache.new(@cache_path) if @cache_path
|
86
|
+
end
|
87
|
+
|
88
|
+
def run
|
89
|
+
@paths.each do |path|
|
90
|
+
@scanner.scan path
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
def expand_paths(paths)
|
96
|
+
paths.inject([]){|p,v| File.directory?(v) ? p.concat(Dir[File.join(v,'**/*.rb')]) : p << v; p }
|
97
|
+
end
|
98
|
+
|
99
|
+
# Inserts the appropriate type of value given name.
|
100
|
+
# For instance:
|
101
|
+
# v('/cake/') #=> /cake/ # regular expression match
|
102
|
+
# v('apple') #=> :apple # atom match
|
103
|
+
def v(name)
|
104
|
+
if name =~ /^\/.+\/$/ # regular expression matching regular expression... WIN!
|
105
|
+
"m(#{name})"
|
106
|
+
else
|
107
|
+
":#{name}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def instance_variable?(name)
|
112
|
+
name[0..0] == '@'
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class RubyScope::Scanner
|
2
|
+
attr_accessor :verbose
|
3
|
+
attr_accessor :cache
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@query = nil
|
7
|
+
@verbose = false
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_query(pattern)
|
11
|
+
# Generate the pattern, we use a little instance_eval trickery here.
|
12
|
+
sexp = case pattern
|
13
|
+
when String then SexpPath::SexpQueryBuilder.instance_eval(pattern)
|
14
|
+
when Sexp then pattern
|
15
|
+
else raise ArgumentError, "Expected a String or Sexp"
|
16
|
+
end
|
17
|
+
|
18
|
+
if @query
|
19
|
+
@query = @query | sexp
|
20
|
+
else
|
21
|
+
@query = sexp
|
22
|
+
end
|
23
|
+
@query
|
24
|
+
|
25
|
+
rescue Exception=>ex
|
26
|
+
puts "Invalid Pattern: '#{pattern}'"
|
27
|
+
puts "Trace:"
|
28
|
+
puts ex
|
29
|
+
puts ex.backtrace
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def query
|
34
|
+
@query.clone if @query
|
35
|
+
end
|
36
|
+
|
37
|
+
def scan(path)
|
38
|
+
@path = path
|
39
|
+
begin
|
40
|
+
report_file path
|
41
|
+
|
42
|
+
# Reset our cached code and split lines
|
43
|
+
@code,@lines = nil,nil
|
44
|
+
|
45
|
+
# Load the code and parse it with RubyParser
|
46
|
+
# If we're caching pull from the cache, otherwise parse the code
|
47
|
+
sexp = @cache[path] if @cache
|
48
|
+
if !sexp
|
49
|
+
sexp = RubyParser.new.parse(code, @path)
|
50
|
+
@cache[path] = sexp if @cache
|
51
|
+
end
|
52
|
+
|
53
|
+
if sexp
|
54
|
+
# Search it with the given pattern, printing any results
|
55
|
+
sexp.search_each(@query) do |matching_sexp|
|
56
|
+
report_match matching_sexp
|
57
|
+
end
|
58
|
+
end
|
59
|
+
rescue StandardError => ex
|
60
|
+
report_exception ex
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
def report_file(path)
|
66
|
+
puts @path if @verbose
|
67
|
+
end
|
68
|
+
|
69
|
+
def report_match(match)
|
70
|
+
if !@lines
|
71
|
+
puts @path unless @verbose
|
72
|
+
@lines = code.split("\n")
|
73
|
+
end
|
74
|
+
line_number = match.sexp.line - 1
|
75
|
+
puts "%4i: %s" % [match.sexp.line, @lines[line_number].strip]
|
76
|
+
end
|
77
|
+
|
78
|
+
def report_exception(ex)
|
79
|
+
debug "Problem processing '#{@path}'"
|
80
|
+
debug ex.message.strip
|
81
|
+
debug ex.backtrace.map{|line| " #{line}"}.join("\n")
|
82
|
+
end
|
83
|
+
|
84
|
+
def code
|
85
|
+
@code ||= File.read(@path)
|
86
|
+
end
|
87
|
+
|
88
|
+
def debug(msg)
|
89
|
+
STDERR.print(msg.to_s.chomp + "\n")
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'dbm'
|
2
|
+
class RubyScope::SexpCache
|
3
|
+
DB = DBM
|
4
|
+
CacheEntry = Struct.new(:last_modified, :sexp)
|
5
|
+
|
6
|
+
def initialize(root)
|
7
|
+
@root = root
|
8
|
+
end
|
9
|
+
|
10
|
+
def [] path
|
11
|
+
with_cache do |cache|
|
12
|
+
entry = cache[path]
|
13
|
+
entry = Marshal.load(entry) if entry
|
14
|
+
|
15
|
+
if entry && entry.last_modified == last_modified(path)
|
16
|
+
entry.sexp
|
17
|
+
else
|
18
|
+
cache.delete path
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def []= path,value
|
25
|
+
with_cache do |cache|
|
26
|
+
entry = CacheEntry.new(last_modified(path), value)
|
27
|
+
cache[path] = Marshal.dump(entry)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def cache_path
|
32
|
+
@cache_path ||= File.join(@root,'.ruby_scope.cache')
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
def with_cache
|
37
|
+
DB.open(cache_path, 0666) do |cache|
|
38
|
+
yield cache
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def last_modified(path)
|
43
|
+
File.mtime(path)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
# Self referential testing!
|
4
|
+
# These are awesome, absurd, and abusive.
|
5
|
+
# Make sure that the app actually does what we say it does.
|
6
|
+
class ConsoleTest < Test::Unit::TestCase
|
7
|
+
ROOT = File.dirname(__FILE__) + '/../../'
|
8
|
+
|
9
|
+
def test_finding_this_test
|
10
|
+
res = rs "--def '/^test/'"
|
11
|
+
assert_success
|
12
|
+
assert res['test_finding_this_test'], "Should have found this test"
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_finding_assignment
|
16
|
+
self_referential_line_number = __LINE__
|
17
|
+
|
18
|
+
res = rs "--assign self_referential_line_number"
|
19
|
+
assert_success
|
20
|
+
assert res.split("\n").last =~ /(\d+)\:\s+self_referential_line_number = __LINE__/
|
21
|
+
assert_equal self_referential_line_number, $1.to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_reading_the_help_and_making_queries
|
25
|
+
help = rs "--help"
|
26
|
+
assert help =~ /Queries:(.+)\s+Options:/m, "Should have a queries section"
|
27
|
+
queries = $1
|
28
|
+
queries.split("\n").each do |query|
|
29
|
+
next if query =~ /^\s*$/
|
30
|
+
assert query =~ /(--\S+)\s+(\S+)?/, "Each query should be a long flag with an optional parameter\n#{query.inspect}"
|
31
|
+
flag, param_type = $1,$2
|
32
|
+
param = case param_type
|
33
|
+
when 'NAME' then "a"
|
34
|
+
when 'SEXP_PATH' then "'s()'"
|
35
|
+
else nil
|
36
|
+
end
|
37
|
+
|
38
|
+
res = rs "#{flag} #{param}"
|
39
|
+
assert_success res
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def rs(args)
|
45
|
+
`#{ROOT}bin/ruby_scope --no-cache #{args} #{__FILE__}`
|
46
|
+
end
|
47
|
+
|
48
|
+
def assert_success(msg=nil)
|
49
|
+
assert $?.success?, msg||"Exited with status #{$?.exitstatus}"
|
50
|
+
end
|
51
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class CLITest < Test::Unit::TestCase
|
4
|
+
def test_configuring_scanner
|
5
|
+
query = scanner_with('--def','cats','.').query
|
6
|
+
assert query, "Should have generated a query"
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_configuring_scanner_with_regex
|
10
|
+
query = scanner_with('--def','/cats/','.').query
|
11
|
+
assert query, "Should have generated a query"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_disabling_cache
|
15
|
+
c = cli_with('--no-cache', '.')
|
16
|
+
assert !c.cache_path
|
17
|
+
assert !c.scanner.cache
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_default_cache_behavior
|
21
|
+
c = cli_with('.')
|
22
|
+
assert c.cache_path
|
23
|
+
assert c.scanner.cache
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_custom_cache_path
|
27
|
+
path = File.dirname(__FILE__) + '../lib'
|
28
|
+
c = cli_with('--cache', path, '.')
|
29
|
+
assert_equal path, c.cache_path
|
30
|
+
assert c.scanner.cache
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def cli_with(*args)
|
35
|
+
RubyScope::CLI.new(args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def scanner_with(*args)
|
39
|
+
cli_with(*args).scanner
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class ScannerTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@scanner = RubyScope::Scanner.new
|
6
|
+
@scanner.cache = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_scanning_cache_hit_with_no_match
|
10
|
+
path = 'cached_sample.rb'
|
11
|
+
@scanner.cache[path] = s(:a)
|
12
|
+
@scanner.add_query( s(:b) )
|
13
|
+
|
14
|
+
# Should have no hit
|
15
|
+
@scanner.expects(:report_match).never
|
16
|
+
# Should not try to read the file since it is cached
|
17
|
+
@scanner.expects(:code).never
|
18
|
+
|
19
|
+
@scanner.scan(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_scanning_cache_hit_with_match
|
23
|
+
path = 'cached_sample.rb'
|
24
|
+
@scanner.cache[path] = s(:a)
|
25
|
+
@scanner.add_query( s(:a) )
|
26
|
+
|
27
|
+
# Should report a match
|
28
|
+
@scanner.expects(:report_match)
|
29
|
+
|
30
|
+
@scanner.scan(path)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class SexpCacheTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@path = File.dirname(__FILE__)
|
6
|
+
@cache = RubyScope::SexpCache.new(@path)
|
7
|
+
@cache.stubs(:last_modified).returns('ok')
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
File.delete(@cache.cache_path) if File.exists? @cache.cache_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_misses
|
15
|
+
assert_equal nil, @cache['missing']
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_writing_and_reading
|
19
|
+
key,value = 'a',s(:code)
|
20
|
+
|
21
|
+
@cache[key] = value
|
22
|
+
assert_equal value, @cache[key]
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_expired_reads
|
26
|
+
key,value = 'a',s(:code)
|
27
|
+
|
28
|
+
@cache[key] = value
|
29
|
+
# now invalidate the key
|
30
|
+
@cache.stubs(:last_modified).returns('old')
|
31
|
+
|
32
|
+
assert_equal nil, @cache[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_over_writing_and_reading
|
36
|
+
key,value1,value2 = 'a',s(:code),s(:new_code)
|
37
|
+
|
38
|
+
@cache[key] = value1
|
39
|
+
@cache[key] = value2
|
40
|
+
assert_equal value2, @cache[key]
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_scope
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Sanderson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-04-17 00:00:00 -07:00
|
13
|
+
default_executable: ruby_scope
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sexp_processor
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "3.0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: ruby_parser
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "2.0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: sexp_path
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0.4"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: mocha
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.8
|
54
|
+
version:
|
55
|
+
description: " A ruby hacker's search tool. Quickly interrogate your code, seek out \n classes, methods, variable assignments, and more.\n"
|
56
|
+
email: netghost@gmail.com
|
57
|
+
executables:
|
58
|
+
- ruby_scope
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- README.markdown
|
63
|
+
files:
|
64
|
+
- README.markdown
|
65
|
+
- Rakefile
|
66
|
+
- VERSION
|
67
|
+
- bin/ruby_scope
|
68
|
+
- lib/ruby_scope.rb
|
69
|
+
- lib/ruby_scope/cli.rb
|
70
|
+
- lib/ruby_scope/scanner.rb
|
71
|
+
- lib/ruby_scope/sexp_cache.rb
|
72
|
+
- test/integration/console_test.rb
|
73
|
+
- test/test_helper.rb
|
74
|
+
- test/unit/cli_test.rb
|
75
|
+
- test/unit/scanner_test.rb
|
76
|
+
- test/unit/sexp_cache_test.rb
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: http://github.com/adamsanderson/ruby_scope
|
79
|
+
licenses: []
|
80
|
+
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options:
|
83
|
+
- --charset=UTF-8
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: "0"
|
91
|
+
version:
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: "0"
|
97
|
+
version:
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 1.3.5
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Ruby colored binoluars for your code.
|
105
|
+
test_files:
|
106
|
+
- test/integration/console_test.rb
|
107
|
+
- test/unit/cli_test.rb
|
108
|
+
- test/unit/scanner_test.rb
|
109
|
+
- test/unit/sexp_cache_test.rb
|