cql_ruby 0.0.7 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/cql_ruby +139 -116
- data/lib/cql_ruby.rb +15 -15
- data/lib/cql_ruby/abstract_printer.rb +12 -12
- data/lib/cql_ruby/console_printer.rb +97 -97
- data/lib/cql_ruby/crumb_collector.rb +18 -18
- data/lib/cql_ruby/executor.rb +194 -148
- data/lib/cql_ruby/filter_evaluator.rb +178 -54
- data/lib/cql_ruby/filter_reader.rb +130 -81
- data/lib/cql_ruby/pattern_matcher.rb +57 -53
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbbc47dff29d232d492edfe95e28eab6a4bd9710ace6332ae7e14c9487830a4a
|
4
|
+
data.tar.gz: 39401f85b2ed054755aa5c8497a3822d3c1b2458119d151264029cdd97b4a3ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e94c7852a7fffe0d0d3d7221caf42c20be76392188c46faf58e44aff12dea386b6202368ae911ddf7abaf894835138e99103f6f78383c9c02462845e19b6fcb0
|
7
|
+
data.tar.gz: 93815de02dffcb1f1b61b1574ef03a610b2e758479048c25a58b22f50d0dd5d6d3dba69316eb10f1339160da91876a9b198a5e2337adbba1d9750035f59cd4d3
|
data/bin/cql_ruby
CHANGED
@@ -1,116 +1,139 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
\
|
10
|
-
|
11
|
-
\
|
12
|
-
|
13
|
-
|
14
|
-
\
|
15
|
-
|
16
|
-
\
|
17
|
-
|
18
|
-
\
|
19
|
-
\t\
|
20
|
-
\t\
|
21
|
-
|
22
|
-
\
|
23
|
-
\t\t
|
24
|
-
\t\t
|
25
|
-
|
26
|
-
\
|
27
|
-
\t\
|
28
|
-
\t\
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
options[:
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'parser'
|
4
|
+
require 'cql_ruby'
|
5
|
+
|
6
|
+
def show_help
|
7
|
+
puts <<~HELP
|
8
|
+
|
9
|
+
\tSYNOPSIS
|
10
|
+
\t\tcql_ruby [--token] pattern path options filters ...
|
11
|
+
\t\tcql_ruby --node type path options filters ...
|
12
|
+
|
13
|
+
\tDESCRIPTION
|
14
|
+
\t\tCQL (Code Query Language) is a semantic search tool for your Ruby source code.
|
15
|
+
|
16
|
+
\tFILTERS
|
17
|
+
\t\tParent node type: type:T(,T)* Example: type:def,send,arg
|
18
|
+
\t\tNesting under: nest:T(=NAME) Example: nest:def=save_user nest:class=UserManager
|
19
|
+
\t\tHas child: has:T(=NAME) Example: has:const has:def=valid?
|
20
|
+
\t\tPattern: pattern:(T-)*X(-T)* Example: pattern:class-def-X-block
|
21
|
+
|
22
|
+
\tOPTIONS
|
23
|
+
\t\t--include=PATTERN Parses only files whose name matches the pattern.
|
24
|
+
\t\t--exclude=PATTERN Parses only files whose name does not match the pattern.
|
25
|
+
\t\t-lN (N is integer) Add N surrounding line before and after.
|
26
|
+
\t\t-nc (--no-color) No color on output.
|
27
|
+
\t\t-nf (--no-file) No file names.
|
28
|
+
\t\t-ns (--no-source) No source code.
|
29
|
+
\t\t-nr (--no-recursion) Non-recursive search.
|
30
|
+
\t\t-v -vv -vvv Debug output levels.
|
31
|
+
|
32
|
+
\tALLOWED NODE TYPES
|
33
|
+
\t\tWhen defining filters only valid AST types can be defined. They are:
|
34
|
+
#{Parser::Meta::NODE_TYPES.to_a.join(' ')}
|
35
|
+
|
36
|
+
\tEXAMPLES
|
37
|
+
\t\tcql_ruby user ./
|
38
|
+
\t\tcql_ruby -ns -nr %user_info ./ type:send,arg nest:block nest:class=r/User/i has:str=WARNING
|
39
|
+
HELP
|
40
|
+
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Hash{Symbol->Boolean}]
|
45
|
+
def extract_options
|
46
|
+
options = {
|
47
|
+
show_color: true,
|
48
|
+
show_file: true,
|
49
|
+
show_source: true,
|
50
|
+
recursive_search: true,
|
51
|
+
surrounding_lines: 0,
|
52
|
+
include_pattern: nil,
|
53
|
+
exclude_pattern: nil,
|
54
|
+
search_type: :token,
|
55
|
+
}
|
56
|
+
|
57
|
+
ARGV.delete_if do |arg|
|
58
|
+
if arg[0] == '-'
|
59
|
+
if %w[-nc --no-color].include?(arg)
|
60
|
+
options[:show_color] = false
|
61
|
+
elsif %w[-nf --no-file].include?(arg)
|
62
|
+
options[:show_file] = false
|
63
|
+
elsif %w[-ns --no-source].include?(arg)
|
64
|
+
options[:show_source] = false
|
65
|
+
elsif %w[-h --help].include?(arg)
|
66
|
+
show_help
|
67
|
+
elsif %w[-v -vv -vvv].include?(arg)
|
68
|
+
lvl = arg.chars.find_all { |c| c == 'v' }.size
|
69
|
+
CqlRuby::Config.debug_level = lvl
|
70
|
+
elsif %w[-nr --no-recursive].include?(arg)
|
71
|
+
options[:recursive_search] = false
|
72
|
+
elsif arg[0..1] == '-l' && arg[2..].to_i > 0
|
73
|
+
options[:surrounding_lines] = arg[2..].to_i
|
74
|
+
elsif arg.start_with?('--include=')
|
75
|
+
options[:include_pattern] = arg.split('=')[1]
|
76
|
+
elsif arg.start_with?('--exclude=')
|
77
|
+
options[:exclude_pattern] = arg.split('=')[1]
|
78
|
+
elsif arg == '--node'
|
79
|
+
options[:search_type] = :node
|
80
|
+
elsif arg == '--token'
|
81
|
+
options[:search_type] = :token
|
82
|
+
else
|
83
|
+
raise "Unknown arg #{arg}"
|
84
|
+
end
|
85
|
+
|
86
|
+
true
|
87
|
+
else
|
88
|
+
false
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
options
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Array]
|
96
|
+
def extract_filters
|
97
|
+
ARGV.take(ARGV.size)
|
98
|
+
end
|
99
|
+
|
100
|
+
begin
|
101
|
+
options = extract_options
|
102
|
+
CqlRuby.log "Call options: #{options}" if CqlRuby::Config.debug_level_2?
|
103
|
+
|
104
|
+
raise unless ARGV.size >= 2
|
105
|
+
|
106
|
+
pattern = ARGV.shift
|
107
|
+
CqlRuby.log "Call pattern: <#{pattern}>" if CqlRuby::Config.debug_level_2?
|
108
|
+
|
109
|
+
path = ARGV.shift
|
110
|
+
CqlRuby.log "Call path: <#{path}>" if CqlRuby::Config.debug_level_2?
|
111
|
+
|
112
|
+
# Rest must be filters - can sink ARGV now.
|
113
|
+
filters = extract_filters
|
114
|
+
CqlRuby.log "Call filters: #{filters}" if CqlRuby::Config.debug_level_2?
|
115
|
+
|
116
|
+
filter_reader = CqlRuby::FilterReader.new(filters)
|
117
|
+
|
118
|
+
printer = CqlRuby::ConsolePrinter.new
|
119
|
+
printer.color_on = options[:show_color]
|
120
|
+
printer.file_on = options[:show_file]
|
121
|
+
printer.source_on = options[:show_source]
|
122
|
+
printer.surrounding_lines = options[:surrounding_lines]
|
123
|
+
|
124
|
+
collector = CqlRuby::CrumbCollector.new(printer)
|
125
|
+
CqlRuby::Executor.new(
|
126
|
+
collector: collector,
|
127
|
+
filter_reader: filter_reader,
|
128
|
+
pattern: pattern,
|
129
|
+
path: path,
|
130
|
+
filters: filters,
|
131
|
+
recursive: options[:recursive_search],
|
132
|
+
include: options[:include_pattern],
|
133
|
+
exclude: options[:exclude_pattern],
|
134
|
+
search_type: options[:search_type],
|
135
|
+
).search_all
|
136
|
+
rescue
|
137
|
+
puts "Error: #{$!}"
|
138
|
+
show_help
|
139
|
+
end
|
data/lib/cql_ruby.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CqlRuby;
|
4
|
-
def self.log(txt)
|
5
|
-
p txt
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
require 'cql_ruby/executor'
|
10
|
-
require 'cql_ruby/crumb_collector'
|
11
|
-
require 'cql_ruby/abstract_printer'
|
12
|
-
require 'cql_ruby/console_printer'
|
13
|
-
require 'cql_ruby/filter_reader'
|
14
|
-
require 'cql_ruby/filter_evaluator'
|
15
|
-
require 'cql_ruby/pattern_matcher'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CqlRuby;
|
4
|
+
def self.log(txt)
|
5
|
+
p txt
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'cql_ruby/executor'
|
10
|
+
require 'cql_ruby/crumb_collector'
|
11
|
+
require 'cql_ruby/abstract_printer'
|
12
|
+
require 'cql_ruby/console_printer'
|
13
|
+
require 'cql_ruby/filter_reader'
|
14
|
+
require 'cql_ruby/filter_evaluator'
|
15
|
+
require 'cql_ruby/pattern_matcher'
|
@@ -1,12 +1,12 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CqlRuby
|
4
|
-
#
|
5
|
-
# Printing
|
6
|
-
#
|
7
|
-
class AbstractPrinter
|
8
|
-
def print(_crumb)
|
9
|
-
raise NotImplementedError
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CqlRuby
|
4
|
+
#
|
5
|
+
# Printing CqlRuby::Crumb-s.
|
6
|
+
#
|
7
|
+
class AbstractPrinter
|
8
|
+
def print(_crumb)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,97 +1,97 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module CqlRuby
|
4
|
-
#
|
5
|
-
# Prints to console.
|
6
|
-
#
|
7
|
-
class ConsolePrinter < ::CqlRuby::AbstractPrinter
|
8
|
-
attr_writer :color_on
|
9
|
-
attr_writer :file_on
|
10
|
-
attr_writer :source_on
|
11
|
-
attr_writer :surrounding_lines
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
super
|
15
|
-
|
16
|
-
@color_on = true
|
17
|
-
@file_on = true
|
18
|
-
@source_on = true
|
19
|
-
@surrounding_lines = 0
|
20
|
-
@counter = 0
|
21
|
-
end
|
22
|
-
|
23
|
-
#
|
24
|
-
# @param crumb [
|
25
|
-
#
|
26
|
-
def print(crumb)
|
27
|
-
parts = "##{color(97)}#{@counter}#{decor_reset}"
|
28
|
-
parts += " #{color(94)}#{crumb.file_name}#{decor_reset}:#{color(33)}#{crumb.line_no}#{decor_reset} #{color(93)}#{crumb.type}#{decor_reset}" if @file_on
|
29
|
-
|
30
|
-
if @source_on && @surrounding_lines.positive?
|
31
|
-
parts_visible_len = parts.gsub(/\e\[\d+m/, '').size + 1
|
32
|
-
indent = ' ' * parts_visible_len
|
33
|
-
(-@surrounding_lines).upto(-1).each { |offs| puts "#{indent}#{crumb.surrounding_line(offs)}" }
|
34
|
-
end
|
35
|
-
|
36
|
-
parts += ' ' + decorate_source_line(crumb) if @source_on
|
37
|
-
|
38
|
-
puts parts
|
39
|
-
|
40
|
-
if @source_on && @surrounding_lines.positive?
|
41
|
-
1.upto(@surrounding_lines).each { |offs| puts "#{indent}#{crumb.surrounding_line(offs)}" }
|
42
|
-
puts '--'
|
43
|
-
end
|
44
|
-
|
45
|
-
@counter += 1
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def color(code)
|
51
|
-
if @color_on
|
52
|
-
"\e[#{code}m"
|
53
|
-
else
|
54
|
-
''
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def bold
|
59
|
-
if @color_on
|
60
|
-
"\e[1m"
|
61
|
-
else
|
62
|
-
''
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def decor_reset
|
67
|
-
if @color_on
|
68
|
-
"\e[0m"
|
69
|
-
else
|
70
|
-
''
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# @param [
|
75
|
-
# @return [String]
|
76
|
-
def decorate_source_line(crumb)
|
77
|
-
source = crumb.source
|
78
|
-
from = crumb.line_col_no
|
79
|
-
to = from + crumb.expression_size
|
80
|
-
|
81
|
-
prefix = source[0..from - 1] || ''
|
82
|
-
subject = source[from..to - 1] || ''
|
83
|
-
suffix = source[to..] || ''
|
84
|
-
|
85
|
-
color(97) +
|
86
|
-
prefix +
|
87
|
-
decor_reset +
|
88
|
-
color(31) +
|
89
|
-
bold +
|
90
|
-
subject +
|
91
|
-
decor_reset +
|
92
|
-
color(97) +
|
93
|
-
suffix +
|
94
|
-
decor_reset
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CqlRuby
|
4
|
+
#
|
5
|
+
# Prints to console.
|
6
|
+
#
|
7
|
+
class ConsolePrinter < ::CqlRuby::AbstractPrinter
|
8
|
+
attr_writer :color_on
|
9
|
+
attr_writer :file_on
|
10
|
+
attr_writer :source_on
|
11
|
+
attr_writer :surrounding_lines
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
|
16
|
+
@color_on = true
|
17
|
+
@file_on = true
|
18
|
+
@source_on = true
|
19
|
+
@surrounding_lines = 0
|
20
|
+
@counter = 0
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# @param crumb [CqlRuby::Crumb]
|
25
|
+
#
|
26
|
+
def print(crumb)
|
27
|
+
parts = "##{color(97)}#{@counter}#{decor_reset}"
|
28
|
+
parts += " #{color(94)}#{crumb.file_name}#{decor_reset}:#{color(33)}#{crumb.line_no}#{decor_reset} #{color(93)}#{crumb.type}#{decor_reset}" if @file_on
|
29
|
+
|
30
|
+
if @source_on && @surrounding_lines.positive?
|
31
|
+
parts_visible_len = parts.gsub(/\e\[\d+m/, '').size + 1
|
32
|
+
indent = ' ' * parts_visible_len
|
33
|
+
(-@surrounding_lines).upto(-1).each { |offs| puts "#{indent}#{crumb.surrounding_line(offs)}" }
|
34
|
+
end
|
35
|
+
|
36
|
+
parts += ' ' + decorate_source_line(crumb) if @source_on
|
37
|
+
|
38
|
+
puts parts
|
39
|
+
|
40
|
+
if @source_on && @surrounding_lines.positive?
|
41
|
+
1.upto(@surrounding_lines).each { |offs| puts "#{indent}#{crumb.surrounding_line(offs)}" }
|
42
|
+
puts '--'
|
43
|
+
end
|
44
|
+
|
45
|
+
@counter += 1
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def color(code)
|
51
|
+
if @color_on
|
52
|
+
"\e[#{code}m"
|
53
|
+
else
|
54
|
+
''
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def bold
|
59
|
+
if @color_on
|
60
|
+
"\e[1m"
|
61
|
+
else
|
62
|
+
''
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def decor_reset
|
67
|
+
if @color_on
|
68
|
+
"\e[0m"
|
69
|
+
else
|
70
|
+
''
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [CqlRuby::Crumb] crumb
|
75
|
+
# @return [String]
|
76
|
+
def decorate_source_line(crumb)
|
77
|
+
source = crumb.source
|
78
|
+
from = crumb.line_col_no
|
79
|
+
to = from + crumb.expression_size
|
80
|
+
|
81
|
+
prefix = source[0..from - 1] || ''
|
82
|
+
subject = source[from..to - 1] || ''
|
83
|
+
suffix = source[to..] || ''
|
84
|
+
|
85
|
+
color(97) +
|
86
|
+
prefix +
|
87
|
+
decor_reset +
|
88
|
+
color(31) +
|
89
|
+
bold +
|
90
|
+
subject +
|
91
|
+
decor_reset +
|
92
|
+
color(97) +
|
93
|
+
suffix +
|
94
|
+
decor_reset
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|