utils 0.2.4 → 0.6.4
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.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/classify +15 -3
- data/bin/discover +25 -10
- data/bin/edit +16 -9
- data/bin/probe +36 -11
- data/bin/search +87 -8
- data/lib/utils.rb +4 -1
- data/lib/utils/finder.rb +0 -3
- data/lib/utils/grepper.rb +6 -13
- data/lib/utils/irb.rb +78 -182
- data/lib/utils/irb/service.rb +39 -0
- data/lib/utils/line_formatter.rb +162 -103
- data/lib/utils/patterns.rb +2 -0
- data/lib/utils/probe_server.rb +62 -82
- data/lib/utils/version.rb +1 -1
- data/utils.gemspec +12 -12
- data/utils.gemspec +0 -0
- metadata +10 -7
data/lib/utils/line_formatter.rb
CHANGED
@@ -2,112 +2,171 @@ require 'tins/terminal'
|
|
2
2
|
require 'term/ansicolor'
|
3
3
|
|
4
4
|
begin
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
rescue LoadError
|
11
|
-
end
|
12
|
-
|
13
|
-
if defined?(RSpec) && defined?(RSpec::Core::Formatters::BaseTextFormatter)
|
5
|
+
require 'rspec/core'
|
6
|
+
require 'rspec/core/formatters'
|
7
|
+
rescue LoadError => e
|
8
|
+
$DEBUG and warn "Caught #{e.class}: #{e}"
|
9
|
+
else
|
14
10
|
module Utils
|
15
|
-
class LineFormatter
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
output
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
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
|
-
|
11
|
+
class LineFormatter
|
12
|
+
::RSpec::Core::Formatters.register self, :start, :close,
|
13
|
+
:example_passed, :example_pending, :example_failed, :dump_summary
|
14
|
+
|
15
|
+
def initialize(output)
|
16
|
+
@output = output
|
17
|
+
@output.sync = true
|
18
|
+
filename = 'errors.lst'
|
19
|
+
@errors_lst = File.new(filename, 'w')
|
20
|
+
@errors_lst.sync = true
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :output
|
24
|
+
|
25
|
+
def start(_ignore)
|
26
|
+
output.puts "Storing error list in #{@errors_lst.path.inspect}: "
|
27
|
+
output.puts ?- * Tins::Terminal.columns
|
28
|
+
end
|
29
|
+
|
30
|
+
def close(_ignore)
|
31
|
+
@errors_lst.close
|
32
|
+
end
|
33
|
+
|
34
|
+
def dump_summary(summary)
|
35
|
+
line = summary_line(summary)
|
36
|
+
@errors_lst.puts ?= * 80, line
|
37
|
+
output.puts ?= * Tins::Terminal.columns, line
|
38
|
+
end
|
39
|
+
|
40
|
+
def example_passed(example)
|
41
|
+
output.puts format_line(example)
|
42
|
+
end
|
43
|
+
|
44
|
+
def example_pending(example)
|
45
|
+
output.puts format_line(example)
|
46
|
+
end
|
47
|
+
|
48
|
+
def example_failed(example)
|
49
|
+
dump_failure_to_error_file(example)
|
50
|
+
output.puts format_line(example)
|
51
|
+
dump_failure(example)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def summary_line(summary)
|
57
|
+
failure_percentage = 100 * summary.failure_count.to_f / summary.example_count
|
58
|
+
failure_percentage.nan? and failure_percentage = 0.0
|
59
|
+
pending_percentage = 100 * summary.pending_count.to_f / summary.example_count
|
60
|
+
pending_percentage.nan? and pending_percentage = 0.0
|
61
|
+
"%u of %u (%.2f %%) failed, %u pending (%.2f %%) in %.3f seconds" % [
|
62
|
+
summary.failure_count,
|
63
|
+
summary.example_count,
|
64
|
+
failure_percentage,
|
65
|
+
summary.pending_count,
|
66
|
+
pending_percentage,
|
67
|
+
summary.duration,
|
68
|
+
]
|
69
|
+
end
|
70
|
+
|
71
|
+
def dump_failure(example)
|
72
|
+
output.puts(
|
73
|
+
description(example, full: true),
|
74
|
+
dump_failure_for_example(example)
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def read_failed_line(example)
|
79
|
+
''.strip
|
80
|
+
end
|
81
|
+
|
82
|
+
def dump_failure_for_example(example)
|
83
|
+
result = ''
|
84
|
+
exception = execution_result(example).exception
|
85
|
+
exception_class_name = exception.class.name
|
86
|
+
result << "Failure/Error: #{read_failed_line(example)}\n"
|
87
|
+
result << "#{exception_class_name}:\n" unless exception_class_name =~ /RSpec/
|
88
|
+
if m = exception.message
|
89
|
+
m.to_s.split("\n").each { |line| result << " #{line}\n" }
|
90
|
+
end
|
91
|
+
result
|
92
|
+
end
|
93
|
+
|
94
|
+
def format_backtrace(example, folding: false, limit: nil)
|
95
|
+
backtrace = execution_result(example).exception.backtrace
|
96
|
+
backtrace.nil? and return ''
|
97
|
+
if limit
|
98
|
+
backtrace = backtrace[0, limit]
|
99
|
+
end
|
100
|
+
result = []
|
101
|
+
folding and result << '{{{'
|
102
|
+
for line in backtrace
|
103
|
+
result << RSpec::Core::Metadata::relative_path(line)
|
104
|
+
end
|
105
|
+
folding and result << '}}}'
|
106
|
+
result * ?\n
|
107
|
+
end
|
108
|
+
|
109
|
+
def dump_failure_to_error_file(example)
|
110
|
+
@errors_lst.flock File::LOCK_EX
|
111
|
+
@errors_lst.puts "%s\n%3.3fs %s\n%s\n%s" % [
|
112
|
+
location(example), run_time(example), description(example, full: true),
|
113
|
+
dump_failure_for_example(example), format_backtrace(example, folding: true)
|
114
|
+
]
|
115
|
+
ensure
|
116
|
+
@errors_lst.flock File::LOCK_UN
|
117
|
+
end
|
118
|
+
|
119
|
+
def execution_result(example)
|
120
|
+
example.example.metadata[:execution_result]
|
121
|
+
end
|
122
|
+
|
123
|
+
def description(example, full: ENV['VERBOSE'].to_i == 1)
|
124
|
+
if full
|
125
|
+
example.example.full_description
|
126
|
+
else
|
127
|
+
example.example.description
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def run_time(example)
|
132
|
+
execution_result(example).run_time
|
133
|
+
end
|
134
|
+
|
135
|
+
def format_line(example)
|
136
|
+
args = [ location(example), run_time(example), description(example) ]
|
137
|
+
uncolored = "%s # S %3.3fs %s" % args
|
138
|
+
uncolored = uncolored[0, Tins::Terminal.columns]
|
139
|
+
case execution_result(example).status
|
140
|
+
when :passed
|
141
|
+
success_color(uncolored)
|
142
|
+
when :failed
|
143
|
+
failure_color(uncolored)
|
144
|
+
when :pending
|
145
|
+
pending_color(uncolored)
|
90
146
|
else
|
91
|
-
|
147
|
+
uncolored % args
|
92
148
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
149
|
+
end
|
150
|
+
|
151
|
+
def success_color(text)
|
152
|
+
Term::ANSIColor.green(text)
|
153
|
+
end
|
154
|
+
|
155
|
+
def failure_color(text)
|
156
|
+
Term::ANSIColor.red(text)
|
157
|
+
end
|
158
|
+
|
159
|
+
def pending_color(text)
|
160
|
+
Term::ANSIColor.yellow(text)
|
161
|
+
end
|
162
|
+
|
163
|
+
def location(example)
|
164
|
+
location = example.example.metadata[:location]
|
165
|
+
unless location.include?(?/)
|
166
|
+
location = example.example.metadata[:example_group][:location]
|
167
|
+
end
|
168
|
+
RSpec::Core::Metadata::relative_path(location)
|
169
|
+
end
|
111
170
|
end
|
112
171
|
end
|
113
172
|
end
|
data/lib/utils/patterns.rb
CHANGED
data/lib/utils/probe_server.rb
CHANGED
@@ -7,19 +7,9 @@ end
|
|
7
7
|
module Utils
|
8
8
|
class ProbeServer
|
9
9
|
class Job
|
10
|
-
|
11
|
-
class << self
|
12
|
-
attr_writer :colorize
|
13
|
-
|
14
|
-
def colorize?
|
15
|
-
!!@colorize
|
16
|
-
end
|
17
|
-
end
|
18
|
-
self.colorize = false
|
19
|
-
|
20
10
|
def initialize(probe_server, args)
|
21
11
|
@id = probe_server.next_job_id
|
22
|
-
@args = args
|
12
|
+
@args = Array(args)
|
23
13
|
end
|
24
14
|
|
25
15
|
attr_reader :id
|
@@ -37,18 +27,15 @@ module Utils
|
|
37
27
|
end
|
38
28
|
|
39
29
|
def ok_colorize(string)
|
40
|
-
return string unless self.class.colorize?
|
41
30
|
case @ok
|
42
31
|
when false then string.white.on_red
|
43
32
|
when true then string.black.on_green
|
44
|
-
else string
|
33
|
+
else string
|
45
34
|
end
|
46
35
|
end
|
47
36
|
|
48
37
|
def inspect
|
49
|
-
ok_colorize(
|
50
|
-
"#<Job id=#{id} args=#{args.inspect} ok=#{ok}>"
|
51
|
-
)
|
38
|
+
ok_colorize("Job##{id} #{args.map { |a| a.include?(' ') ? a.inspect : a } * ' '}")
|
52
39
|
end
|
53
40
|
|
54
41
|
alias to_s inspect
|
@@ -62,6 +49,12 @@ module Utils
|
|
62
49
|
Thread.new { work_loop }
|
63
50
|
end
|
64
51
|
|
52
|
+
def print(*msg)
|
53
|
+
if msg.first !~ /^irb: warn: can't alias / # shut your god d*mn wh*re mouth
|
54
|
+
super
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
65
58
|
def start
|
66
59
|
output_message "Starting probe server listening to #{@uri.inspect}.", type: :info
|
67
60
|
DRb.start_service(@uri, self)
|
@@ -69,7 +62,8 @@ module Utils
|
|
69
62
|
DRb.thread.join
|
70
63
|
rescue Interrupt
|
71
64
|
ARGV.clear << '-f'
|
72
|
-
output_message %{\nEntering interactive mode
|
65
|
+
output_message %{\nEntering interactive mode.}, type: :info
|
66
|
+
help
|
73
67
|
begin
|
74
68
|
old, $VERBOSE = $VERBOSE, nil
|
75
69
|
examine(self)
|
@@ -88,40 +82,24 @@ module Utils
|
|
88
82
|
|
89
83
|
annotate :doc
|
90
84
|
|
91
|
-
|
92
|
-
annotations = self.class.doc_annotations.sort_by(&:first)
|
93
|
-
max_size = annotations.map { |a| a.first.size }.max
|
94
|
-
output_message annotations.map { |n, v| "#{n.to_s.ljust(max_size + 1)}#{v}" }
|
95
|
-
end
|
85
|
+
annotate :shortcut
|
96
86
|
|
97
|
-
doc '
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
rescue ThreadError
|
110
|
-
false
|
111
|
-
end
|
112
|
-
|
113
|
-
doc 'Return the currently running job.'
|
114
|
-
def job
|
115
|
-
queue_synchronize do
|
116
|
-
@job
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def next_job_id
|
121
|
-
@current_job_id += 1
|
87
|
+
doc 'Display this help.'
|
88
|
+
shortcut :h
|
89
|
+
def help
|
90
|
+
docs = doc_annotations.sort_by(&:first)
|
91
|
+
docs_size = docs.map { |a| a.first.size }.max
|
92
|
+
format = '%-20s %-3s %s'
|
93
|
+
output_message [
|
94
|
+
(format % %w[ command sho description ]).on_color(20).white
|
95
|
+
] << docs.map { |cmd, doc|
|
96
|
+
shortcut = shortcut_of(cmd) and shortcut = "(#{shortcut})"
|
97
|
+
format % [ cmd, shortcut, doc ]
|
98
|
+
}
|
122
99
|
end
|
123
100
|
|
124
101
|
doc 'Enqueue a new job with the argument array <job_args>.'
|
102
|
+
shortcut :e
|
125
103
|
def job_enqueue(job_args)
|
126
104
|
job = Job.new(self, job_args)
|
127
105
|
output_message " → #{job.inspect} enqueued.", type: :info
|
@@ -130,35 +108,15 @@ module Utils
|
|
130
108
|
alias enqueue job_enqueue
|
131
109
|
|
132
110
|
doc 'Send the <signal> to the process that is working on the current job, if any.'
|
133
|
-
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
doc 'Shutdown the server.'
|
111
|
+
doc 'Quit the server.'
|
112
|
+
shortcut :q
|
138
113
|
def shutdown
|
139
114
|
output_message "Server was shutdown down – HARD!", type: :warn
|
140
|
-
exit
|
141
|
-
end
|
142
|
-
|
143
|
-
doc 'List the currently pending jobs waiting to be run.'
|
144
|
-
def jobs_list
|
145
|
-
output_message @jobs_queue.instance_variable_get(:@que)
|
146
|
-
end
|
147
|
-
|
148
|
-
doc 'Clear all pending jobs.'
|
149
|
-
def jobs_clear
|
150
|
-
queue_synchronize do
|
151
|
-
unless @jobs_queue.empty?
|
152
|
-
@jobs_queue.clear
|
153
|
-
output_message "Cleared all queued jobs.", type: :warn
|
154
|
-
true
|
155
|
-
else
|
156
|
-
false
|
157
|
-
end
|
158
|
-
end
|
115
|
+
exit 23
|
159
116
|
end
|
160
117
|
|
161
118
|
doc 'Repeat the job with <job_id> or the last, it will be assigned a new id, though.'
|
119
|
+
shortcut :r
|
162
120
|
def job_repeat(job_id = @history.last)
|
163
121
|
Job === job_id and job_id = job_id.id
|
164
122
|
if old_job = @history.find { |job| job.id == job_id }
|
@@ -170,6 +128,7 @@ module Utils
|
|
170
128
|
end
|
171
129
|
|
172
130
|
doc 'List the history of run jobs.'
|
131
|
+
shortcut :l
|
173
132
|
def history_list
|
174
133
|
output_message @history
|
175
134
|
end
|
@@ -180,19 +139,39 @@ module Utils
|
|
180
139
|
true
|
181
140
|
end
|
182
141
|
|
142
|
+
class LogWrapper < BasicObject
|
143
|
+
def initialize(server, object)
|
144
|
+
@server, @object = server, object
|
145
|
+
end
|
146
|
+
|
147
|
+
def []=(name, value)
|
148
|
+
name, value = name.to_s, value.to_s
|
149
|
+
@server.output_message("Setting #{name}=#{value.inspect}.", type: :info)
|
150
|
+
@object[name] = value
|
151
|
+
end
|
152
|
+
|
153
|
+
def method_missing(*a, &b)
|
154
|
+
@object.__send__(*a, &b)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
183
158
|
doc "The environment of the server process, use env['a'] = 'b' and env['a']."
|
184
|
-
def env
|
185
|
-
ENV
|
159
|
+
memoize_method def env
|
160
|
+
LogWrapper.new(self, ENV)
|
186
161
|
end
|
187
162
|
|
188
|
-
|
163
|
+
doc "Clear the terminal screen"
|
164
|
+
shortcut :c
|
165
|
+
def clear
|
166
|
+
system "clear"
|
167
|
+
end
|
189
168
|
|
190
|
-
|
191
|
-
|
169
|
+
for (method_name, shortcut) in shortcut_annotations
|
170
|
+
alias_method shortcut, method_name
|
192
171
|
end
|
193
172
|
|
194
|
-
def
|
195
|
-
|
173
|
+
def next_job_id
|
174
|
+
@current_job_id += 1
|
196
175
|
end
|
197
176
|
|
198
177
|
def output_message(msg, type: nil)
|
@@ -204,7 +183,7 @@ module Utils
|
|
204
183
|
when :info
|
205
184
|
msg.on_color(20).white
|
206
185
|
when :warn
|
207
|
-
msg.on_color(
|
186
|
+
msg.on_color(94).white
|
208
187
|
when :failure
|
209
188
|
msg.on_color(124).blink.white
|
210
189
|
else
|
@@ -215,10 +194,11 @@ module Utils
|
|
215
194
|
self
|
216
195
|
end
|
217
196
|
|
197
|
+
private
|
198
|
+
|
218
199
|
def run_job(job)
|
219
|
-
|
220
|
-
|
221
|
-
Process.wait @pid
|
200
|
+
output_message " → #{job.inspect} now running.", type: :info
|
201
|
+
system *cmd(job.args)
|
222
202
|
message = " → #{job.inspect} was just run"
|
223
203
|
if $?.success?
|
224
204
|
job.ok = true
|