unroller 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/unroller.rb +123 -44
- metadata +2 -12
data/lib/unroller.rb
CHANGED
@@ -22,6 +22,7 @@ require 'quality_extensions/module/malias_method_chain'
|
|
22
22
|
require 'quality_extensions/module/attribute_accessors'
|
23
23
|
require 'quality_extensions/enumerable/select_until'
|
24
24
|
require 'quality_extensions/module/bool_attr_accessor'
|
25
|
+
require 'quality_extensions/object/pp_s'
|
25
26
|
gem 'colored'
|
26
27
|
require 'colored'
|
27
28
|
#gem 'extensions'
|
@@ -30,10 +31,8 @@ require 'colored'
|
|
30
31
|
require 'English'
|
31
32
|
require 'pp'
|
32
33
|
require 'stringio'
|
33
|
-
gem 'termios'
|
34
|
-
require 'termios'
|
35
|
-
gem 'colored'
|
36
34
|
|
35
|
+
gem 'colored'
|
37
36
|
# To disable color, uncomment this:
|
38
37
|
#class String
|
39
38
|
# def colorize(string, options = {})
|
@@ -42,12 +41,55 @@ gem 'colored'
|
|
42
41
|
#end
|
43
42
|
|
44
43
|
begin
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
gem 'termios'
|
45
|
+
require 'termios'
|
46
|
+
begin
|
47
|
+
# Set up termios so that it returns immediately when you press a key.
|
48
|
+
# (http://blog.rezra.com/articles/2005/12/05/single-character-input)
|
49
|
+
t = Termios.tcgetattr(STDIN)
|
50
|
+
save_terminal_attributes = t.dup
|
51
|
+
t.lflag &= ~Termios::ICANON
|
52
|
+
Termios.tcsetattr(STDIN, 0, t)
|
53
|
+
|
54
|
+
# Set terminal_attributes back to how we found them...
|
55
|
+
at_exit { Termios.tcsetattr(STDIN, 0, save_terminal_attributes) }
|
56
|
+
rescue RuntimeError => exception # Necessary for automated testing.
|
57
|
+
if exception.message =~ /can't get terminal parameters/
|
58
|
+
puts 'Warning: Terminal not found.'
|
59
|
+
$interactive = false
|
60
|
+
elsif exception.message =~ /Inappropriate ioctl for device/
|
61
|
+
puts "Warning: #{exception.inspect}"
|
62
|
+
# This error happens when a Rails app is started with script/server -d
|
63
|
+
# By rescuing this error, we should be able to tail log/mongrel.log to see the output.
|
64
|
+
else
|
65
|
+
raise
|
66
|
+
end
|
67
|
+
end
|
68
|
+
$termios_loaded = true
|
69
|
+
rescue Gem::LoadError
|
70
|
+
$termios_loaded = false
|
71
|
+
end
|
72
|
+
|
73
|
+
class IO
|
74
|
+
# Gets a single character, as a string.
|
75
|
+
# Adjusts for the different behavior of getc if we are using termios to get it to return immediately when you press a single key
|
76
|
+
# or if they are not using that behavior and thus have to press Enter after their single key.
|
77
|
+
def getch
|
78
|
+
response = getc
|
79
|
+
if !$termios_loaded
|
80
|
+
next_char = getc
|
81
|
+
new_line_characters_expected = ["\n"]
|
82
|
+
#new_line_characters_expected = ["\n", "\r"] if windows?
|
83
|
+
if next_char.chr.in?(new_line_characters_expected)
|
84
|
+
# Eat the newline character
|
85
|
+
else
|
86
|
+
# Don't eat it
|
87
|
+
# (This case is necessary, for escape sequences, for example, where they press only one key, but it produces multiple characters.)
|
88
|
+
$stdin.ungetc(next_char)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
response.chr
|
92
|
+
end
|
51
93
|
end
|
52
94
|
|
53
95
|
class String
|
@@ -86,10 +128,11 @@ class Unroller
|
|
86
128
|
end
|
87
129
|
def to_s
|
88
130
|
#@variables.inspect
|
89
|
-
@variables.map do |variable|
|
131
|
+
ret = @variables.map do |variable|
|
90
132
|
name, value = *variable
|
91
133
|
"#{name} = #{value.inspect}"
|
92
134
|
end.join('; ').bracket(' (', ')')
|
135
|
+
ret[0..70] + '...' # Maybe truncating it could be optional in the future, but for now it's just too cluttered
|
93
136
|
end
|
94
137
|
def verbose_to_s
|
95
138
|
@variables.map do |variable|
|
@@ -103,6 +146,7 @@ class Unroller
|
|
103
146
|
end
|
104
147
|
end
|
105
148
|
@@instance = nil
|
149
|
+
@@quiting = false
|
106
150
|
|
107
151
|
Call = Struct.new(:file, :line_num, :klass, :name, :full_name)
|
108
152
|
# AKA stack frame?
|
@@ -186,6 +230,7 @@ class Unroller
|
|
186
230
|
|
187
231
|
# "Presets"
|
188
232
|
# Experimental -- subject to change a lot before it's finalized
|
233
|
+
options[:presets] = options.delete(:only) if options.has_key?(:only)
|
189
234
|
options[:presets] = options.delete(:debugging) if options.has_key?(:debugging)
|
190
235
|
options[:presets] = options.delete(:preset) if options.has_key?(:preset)
|
191
236
|
options[:presets] = [options[:presets]] unless options[:presets].is_a?(Array)
|
@@ -310,8 +355,11 @@ class Unroller
|
|
310
355
|
end
|
311
356
|
|
312
357
|
def trace(&block)
|
358
|
+
catch :quit do
|
359
|
+
throw :quit if @@quiting
|
313
360
|
if @tracing
|
314
361
|
yield if block_given?
|
362
|
+
# No need to call set_trace_func again; we're already tracing
|
315
363
|
return
|
316
364
|
end
|
317
365
|
|
@@ -321,7 +369,13 @@ class Unroller
|
|
321
369
|
|
322
370
|
if @condition.call
|
323
371
|
|
324
|
-
trap_chain("INT")
|
372
|
+
trap_chain("INT") do
|
373
|
+
puts
|
374
|
+
puts 'Exiting trace...'
|
375
|
+
set_trace_func(nil)
|
376
|
+
@@quiting = true
|
377
|
+
throw :quit
|
378
|
+
end
|
325
379
|
|
326
380
|
|
327
381
|
|
@@ -333,6 +387,7 @@ class Unroller
|
|
333
387
|
|
334
388
|
# (This is the meat of the library right here, so let's set it off with at least 5 blank lines.)
|
335
389
|
set_trace_func( proc do |event, file, line, id, binding, klass|
|
390
|
+
return if @@quiting
|
336
391
|
begin # begin/rescue block
|
337
392
|
@event, @file, @line, @id, @binding, @klass =
|
338
393
|
event, file, line, id, binding, klass
|
@@ -428,15 +483,31 @@ class Unroller
|
|
428
483
|
if @interactive && !(@last_call == current_call)
|
429
484
|
#(print '(o = Step out of | s = Skip = Step over | default = Step into > '; response = $stdin.gets) if @interactive
|
430
485
|
|
431
|
-
while response.nil? do
|
486
|
+
while response.nil? or !response.in? ['i',' ',"\e[C","\e[19~", 'v',"\e[B","\e[20~", 'u',"\e[D", 'r', "\n", 'q'] do
|
432
487
|
print "Debugger (" +
|
433
|
-
"Step
|
434
|
-
"Step over (
|
435
|
-
"Step
|
488
|
+
"Step into (F8/Right/Space)".menu_item(:green, 'i') + ' | ' +
|
489
|
+
"Step over (F9/Down/Enter)".menu_item(:cyan, 'v') + ' | ' +
|
490
|
+
"Step out (Left)".menu_item(:red, 'u') + ' | ' +
|
436
491
|
"show Locals".menu_item(:yellow, 'l') + ' | ' +
|
437
|
-
"Run".menu_item(:blue) +
|
492
|
+
"Run".menu_item(:blue) + ' | ' +
|
493
|
+
"Quit".menu_item(:magenta) +
|
438
494
|
') > '
|
439
|
-
|
495
|
+
$stdout.flush
|
496
|
+
|
497
|
+
response = $stdin.getch.downcase
|
498
|
+
|
499
|
+
# Escape sequence such as the up arrow key ("\e[A")
|
500
|
+
if response == "\e"
|
501
|
+
response << (next_char = $stdin.getch)
|
502
|
+
if next_char == '['
|
503
|
+
response << (next_char = $stdin.getch)
|
504
|
+
if next_char.in? ['1', '2']
|
505
|
+
response << (next_char = $stdin.getch)
|
506
|
+
response << (next_char = $stdin.getch)
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
440
511
|
puts unless response == "\n"
|
441
512
|
|
442
513
|
case response
|
@@ -446,18 +517,24 @@ class Unroller
|
|
446
517
|
end
|
447
518
|
end
|
448
519
|
end
|
520
|
+
|
449
521
|
if response
|
450
522
|
case response
|
451
|
-
when '
|
452
|
-
|
453
|
-
when '
|
454
|
-
@silent_until_return_to_this_depth = @internal_depth - 1
|
455
|
-
#puts "Setting @silent_until_return_to_this_depth = #{@silent_until_return_to_this_depth}"
|
456
|
-
when 'v', "\n" # Step over = Ignore anything with a greater depth.
|
523
|
+
when 'i', ' ', "\e[C", "\e[19~" # (Right, F8)
|
524
|
+
# keep right on tracing...
|
525
|
+
when 'v', "\n", "\e[B", "\e[20~" # (Down, F9) Step over = Ignore anything with a greater depth.
|
457
526
|
@only_makes_sense_if_next_event_is_call = true
|
458
527
|
@silent_until_return_to_this_depth = @internal_depth
|
528
|
+
when 'u', "\e[D" # (Left) Step out
|
529
|
+
@silent_until_return_to_this_depth = @internal_depth - 1
|
530
|
+
#puts "Setting @silent_until_return_to_this_depth = #{@silent_until_return_to_this_depth}"
|
531
|
+
when 'r' # Run
|
532
|
+
@interactive = false
|
533
|
+
when 'q'
|
534
|
+
@@quiting = true
|
535
|
+
throw :quit
|
459
536
|
else
|
460
|
-
#
|
537
|
+
# we shouldn't get here
|
461
538
|
end
|
462
539
|
end
|
463
540
|
|
@@ -635,7 +712,9 @@ class Unroller
|
|
635
712
|
ensure
|
636
713
|
trace_off if block_given?
|
637
714
|
end # rescue/ensure block
|
715
|
+
end
|
638
716
|
end # def trace(&block)
|
717
|
+
|
639
718
|
class << self
|
640
719
|
alias_method :trace_on, :trace
|
641
720
|
end
|
@@ -1068,13 +1147,13 @@ if $0 == __FILE__
|
|
1068
1147
|
('a'..last='y').each do |method_name|
|
1069
1148
|
next_method_name = method_name.next unless method_name == last
|
1070
1149
|
eval <<-End, binding, __FILE__, __LINE__ + 1
|
1071
|
-
def #{method_name}
|
1072
|
-
#{next_method_name}
|
1150
|
+
def _#{method_name}
|
1151
|
+
#{next_method_name && "_#{next_method_name}"}
|
1073
1152
|
end
|
1074
1153
|
End
|
1075
1154
|
end
|
1076
1155
|
Unroller::trace(:depth => 5) do
|
1077
|
-
|
1156
|
+
_a
|
1078
1157
|
end
|
1079
1158
|
|
1080
1159
|
herald '-----------------------------------------------------------'
|
@@ -1082,13 +1161,13 @@ if $0 == __FILE__
|
|
1082
1161
|
('a'..last='y').each do |method_name|
|
1083
1162
|
next_method_name = method_name.next unless method_name == last
|
1084
1163
|
eval <<-End, binding, __FILE__, __LINE__ + 1
|
1085
|
-
def #{method_name}
|
1086
|
-
#{next_method_name}
|
1164
|
+
def _#{method_name}
|
1165
|
+
#{next_method_name && "_#{next_method_name}"}
|
1087
1166
|
#{'Unroller::trace(:depth => caller(0).size)' if method_name == last }
|
1088
1167
|
end
|
1089
1168
|
End
|
1090
1169
|
end
|
1091
|
-
|
1170
|
+
_a
|
1092
1171
|
Unroller::trace_off
|
1093
1172
|
|
1094
1173
|
|
@@ -1117,14 +1196,14 @@ if $0 == __FILE__
|
|
1117
1196
|
('a'..last='c').each do |method_name|
|
1118
1197
|
next_method_name = method_name.next unless method_name == last
|
1119
1198
|
eval <<-End, binding, __FILE__, __LINE__ + 1
|
1120
|
-
def #{method_name}
|
1121
|
-
#{next_method_name}
|
1199
|
+
def _#{method_name}
|
1200
|
+
#{next_method_name && "_#{next_method_name}"}
|
1122
1201
|
end
|
1123
1202
|
End
|
1124
1203
|
end
|
1125
1204
|
go_to_depth_and_call_1(14) do
|
1126
1205
|
Unroller::trace(:depth => :use_call_stack_depth) do
|
1127
|
-
|
1206
|
+
_a
|
1128
1207
|
end
|
1129
1208
|
end
|
1130
1209
|
|
@@ -1132,7 +1211,7 @@ if $0 == __FILE__
|
|
1132
1211
|
herald 'Testing without :depth => :use_call_stack_depth (for comparison)'
|
1133
1212
|
go_to_depth_and_call_1(14) do
|
1134
1213
|
Unroller::trace() do
|
1135
|
-
|
1214
|
+
_a
|
1136
1215
|
end
|
1137
1216
|
end
|
1138
1217
|
|
@@ -1141,13 +1220,13 @@ if $0 == __FILE__
|
|
1141
1220
|
('a'..last='y').each do |method_name|
|
1142
1221
|
next_method_name = method_name.next unless method_name == last
|
1143
1222
|
eval <<-End, binding, __FILE__, __LINE__ + 1
|
1144
|
-
def #{method_name}
|
1145
|
-
#{next_method_name}
|
1223
|
+
def _#{method_name}
|
1224
|
+
#{next_method_name && "_#{next_method_name}"}
|
1146
1225
|
end
|
1147
1226
|
End
|
1148
1227
|
end
|
1149
1228
|
Unroller::trace(:max_depth => 5) do
|
1150
|
-
|
1229
|
+
_a
|
1151
1230
|
end
|
1152
1231
|
|
1153
1232
|
herald '-----------------------------------------------------------'
|
@@ -1171,13 +1250,13 @@ if $0 == __FILE__
|
|
1171
1250
|
('a'..last='h').each do |method_name|
|
1172
1251
|
next_method_name = method_name.next unless method_name == last
|
1173
1252
|
eval <<-End, binding, __FILE__, __LINE__ + 1
|
1174
|
-
def #{method_name}
|
1175
|
-
#{next_method_name}
|
1253
|
+
def _#{method_name}
|
1254
|
+
#{next_method_name && "_#{next_method_name}"}
|
1176
1255
|
end
|
1177
1256
|
End
|
1178
1257
|
end
|
1179
1258
|
Unroller::trace(:max_lines => 20) do
|
1180
|
-
|
1259
|
+
_a
|
1181
1260
|
end
|
1182
1261
|
|
1183
1262
|
herald '-----------------------------------------------------------'
|
@@ -1275,8 +1354,8 @@ if $0 == __FILE__
|
|
1275
1354
|
('a'..last='h').each do |method_name|
|
1276
1355
|
next_method_name = method_name.next unless method_name == last
|
1277
1356
|
eval <<-End, binding, __FILE__, __LINE__ + 1
|
1278
|
-
def #{method_name}
|
1279
|
-
#{next_method_name}
|
1357
|
+
def _#{method_name}
|
1358
|
+
#{next_method_name && "_#{next_method_name}"}
|
1280
1359
|
#{'Interesting::method' if method_name == last }
|
1281
1360
|
#{'Interesting.new.method' if method_name == last }
|
1282
1361
|
end
|
@@ -1285,7 +1364,7 @@ if $0 == __FILE__
|
|
1285
1364
|
end
|
1286
1365
|
end
|
1287
1366
|
def create_an_instance_of_UninterestingClassThatCluttersUpOnesTraces
|
1288
|
-
Uninteresting::ClassThatCluttersUpOnesTraces.new.
|
1367
|
+
Uninteresting::ClassThatCluttersUpOnesTraces.new._a
|
1289
1368
|
end
|
1290
1369
|
Unroller::trace(:exclude_classes => Uninteresting::ClassThatCluttersUpOnesTraces) do
|
1291
1370
|
create_an_instance_of_UninterestingClassThatCluttersUpOnesTraces
|
@@ -1496,7 +1575,7 @@ if $0 == __FILE__
|
|
1496
1575
|
def block_taker(&block)
|
1497
1576
|
puts "I'm the block taker. I take blocks."
|
1498
1577
|
puts "Please Step Over the next line."
|
1499
|
-
yield # buggy!
|
1578
|
+
yield # buggy! it keeps stopping at every line in the yielded block, but shouldn't.
|
1500
1579
|
# false:: (unroller.rb:1433) (line): ??
|
1501
1580
|
puts "Done yielding to the block"
|
1502
1581
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unroller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler Rick
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-12-30 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,16 +42,6 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: "0"
|
44
44
|
version:
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: termios
|
47
|
-
type: :runtime
|
48
|
-
version_requirement:
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: "0"
|
54
|
-
version:
|
55
45
|
description: A debugging/tracing tool for Ruby. While it is enabled, it will watch every Ruby statement and method call that gets executed and will display the source code that is being executed in real time on your screen.
|
56
46
|
email:
|
57
47
|
executables: []
|