byebug 2.7.0 → 3.0.0

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -6
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +23 -0
  5. data/Gemfile +9 -0
  6. data/README.md +35 -32
  7. data/Rakefile +1 -3
  8. data/byebug.gemspec +0 -6
  9. data/ext/byebug/byebug.c +64 -51
  10. data/ext/byebug/byebug.h +12 -13
  11. data/ext/byebug/context.c +28 -43
  12. data/ext/byebug/extconf.rb +6 -6
  13. data/lib/byebug.rb +34 -38
  14. data/lib/byebug/command.rb +4 -2
  15. data/lib/byebug/commands/continue.rb +0 -1
  16. data/lib/byebug/commands/control.rb +0 -1
  17. data/lib/byebug/commands/edit.rb +1 -1
  18. data/lib/byebug/commands/finish.rb +10 -16
  19. data/lib/byebug/commands/help.rb +1 -1
  20. data/lib/byebug/commands/kill.rb +1 -1
  21. data/lib/byebug/commands/quit.rb +1 -1
  22. data/lib/byebug/commands/repl.rb +3 -3
  23. data/lib/byebug/commands/set.rb +24 -39
  24. data/lib/byebug/commands/show.rb +39 -112
  25. data/lib/byebug/commands/stepping.rb +0 -2
  26. data/lib/byebug/commands/threads.rb +0 -5
  27. data/lib/byebug/commands/trace.rb +1 -1
  28. data/lib/byebug/commands/variables.rb +1 -1
  29. data/lib/byebug/context.rb +8 -12
  30. data/lib/byebug/helper.rb +1 -1
  31. data/lib/byebug/history.rb +46 -0
  32. data/lib/byebug/interface.rb +5 -5
  33. data/lib/byebug/interfaces/local_interface.rb +11 -62
  34. data/lib/byebug/interfaces/remote_interface.rb +6 -22
  35. data/lib/byebug/interfaces/script_interface.rb +2 -17
  36. data/lib/byebug/processor.rb +4 -4
  37. data/lib/byebug/{command_processor.rb → processors/command_processor.rb} +7 -14
  38. data/lib/byebug/{control_command_processor.rb → processors/control_command_processor.rb} +3 -7
  39. data/lib/byebug/version.rb +1 -1
  40. data/test/edit_test.rb +6 -6
  41. data/test/examples/breakpoint_deep.rb +1 -1
  42. data/test/finish_test.rb +6 -6
  43. data/test/help_test.rb +1 -1
  44. data/test/info_test.rb +0 -1
  45. data/test/kill_test.rb +2 -2
  46. data/test/post_mortem_test.rb +35 -219
  47. data/test/quit_test.rb +2 -2
  48. data/test/restart_test.rb +12 -33
  49. data/test/set_test.rb +80 -107
  50. data/test/show_test.rb +42 -77
  51. data/test/stepping_test.rb +1 -1
  52. data/test/support/test_dsl.rb +4 -25
  53. data/test/support/test_interface.rb +40 -48
  54. data/test/test_helper.rb +1 -3
  55. data/test/timeout_test.rb +9 -0
  56. metadata +8 -75
@@ -23,41 +23,29 @@ module Byebug
23
23
  end
24
24
  when /^verbose$/
25
25
  Byebug.verbose = setting_value
26
- when /^history$/
27
- try_subcmd = setting_args[0]
28
- subcmd = Command.find(SetCommand::SetHistorySubcommands, try_subcmd)
29
- return print "Invalid history parameter #{try_subcmd}. Should be" \
30
- ' "filename", "save" or "size"' unless subcmd
31
-
32
- sub_sub_cmd = setting_args[1]
33
- iface = @state.interface
34
- case subcmd.name
35
- when /^save$/
36
- iface.history_save = sub_sub_cmd ? get_onoff(sub_sub_cmd) : true
37
- when /^size$/
38
- return print 'You need to specify the history size' unless sub_sub_cmd
39
- iface.history_length = get_int(sub_sub_cmd, "Set history size")
40
- when /^filename$/
41
- return print 'You need to specify a filename' unless sub_sub_cmd
42
- iface.histfile = File.join(ENV["HOME"]||ENV["HOMEPATH"]||".", sub_sub_cmd)
43
- end
26
+ when /^histfile$/
27
+ return print 'You need to specify a filename' unless setting_args[0]
28
+ Byebug::History.file = File.expand_path(setting_args[0])
29
+ when /^histsize$/
30
+ return print 'You need to specify the history size' unless setting_args[0]
31
+ Byebug::History.max_size = get_int(setting_args[0], "Set histsize")
44
32
  when /^linetrace$/
45
33
  Byebug.tracing = setting_value
46
34
  when /^listsize$/
47
- listsize = get_int(setting_args[0], "Set listsize", 1, nil, 10)
35
+ listsize = get_int(setting_args[0], 'Set listsize', 1, nil, 10)
48
36
  return unless listsize
49
37
  Command.settings[:listsize] = listsize
50
38
  when /^width$/
51
- return unless width = get_int(setting_args[0], "Set width", 10, nil, 80)
39
+ return unless width = get_int(setting_args[0], 'Set width', 10, nil, 80)
52
40
  Command.settings[:width] = width
53
41
  when /^post_mortem$/
54
42
  if setting_value == true
55
43
  Byebug.post_mortem
56
44
  else
57
- return print 'Sorry... not implemented yet. Restart byebug'
45
+ Byebug.post_mortem = false
58
46
  end
59
- when /^autoeval|autoreload|basename|forcestep|fullpath|linetrace_plus|
60
- testing|stack_on_error$/x
47
+ when /^autoeval|autoreload|autosave|basename|forcestep|fullpath|
48
+ linetrace_plus|testing|stack_on_error$/x
61
49
  Command.settings[setting_name.to_sym] = setting_value
62
50
  else
63
51
  return print "Unknown setting #{@match[1]}.\n"
@@ -72,21 +60,25 @@ module Byebug
72
60
  Subcommands = [
73
61
  ['args' , 2 , false, 'Set argument list to the program ' \
74
62
  'being debugged when it is started' ],
75
- ['autoeval' , 4 , true , 'Evaluate every unrecognized command' ],
76
- ['autolist' , 4 , true , 'Execute "list" command on every ' \
63
+ ['autoeval' , 5 , true , 'Evaluate every unrecognized command' ],
64
+ ['autolist' , 5 , true , 'Execute "list" command on every ' \
77
65
  'breakpoint' ],
78
- ['autoirb' , 4 , true , 'Invoke IRB on every stop' ],
79
- ['autoreload' , 4 , true , 'Reload source code when changed' ],
66
+ ['autoirb' , 5 , true , 'Invoke IRB on every stop' ],
67
+ ['autoreload' , 5 , true , 'Reload source code when changed' ],
68
+ ['autosave' , 5 , true , 'Automatically save command history ' \
69
+ 'record on exit' ],
80
70
  ['basename' , 1 , true , 'Set filename display style' ],
81
71
  ['callstyle' , 2 , false, 'Set how you want call parameters ' \
82
72
  'displayed' ],
83
- ['testing' , 2 , false, 'Used when testing byebug' ],
84
73
  ['forcestep' , 2 , true , 'Make sure "next/step" commands always' \
85
74
  'move to a new line' ],
86
75
  ['fullpath' , 2 , true , 'Display full file names in frames' ],
87
- ['history' , 2 , false, 'Command for setting command history ' \
88
- 'parameters, namely, "filename", ' \
89
- '"save" and "size"' ],
76
+ ['histfile' , 5 , false, 'Customize file where history is ' \
77
+ 'loaded from and saved to. By ' \
78
+ 'default, .byebug_hist' ],
79
+ ['histsize' , 5 , false, 'Customize maximum number of commands ' \
80
+ 'that are stored in byebug history ' \
81
+ 'record. By default, 256' ],
90
82
  ['linetrace' , 3 , true , 'Enable line execution tracing' ],
91
83
  ['linetrace_plus', 10, true , 'Set line execution tracing to show' \
92
84
  'different lines' ],
@@ -95,6 +87,7 @@ module Byebug
95
87
  ['post_mortem' , 2 , true , 'Enable post-mortem mode' ],
96
88
  ['stack_on_error', 1 , true , 'Display stack trace when "eval" ' \
97
89
  'raises exception' ],
90
+ ['testing' , 2 , false, 'Used when testing byebug' ],
98
91
  ['verbose' , 1 , true , 'Enable verbose output of TracePoint ' \
99
92
  'API events is enabled' ],
100
93
  ['width' , 1 , false, 'Number of characters per line for ' \
@@ -103,14 +96,6 @@ module Byebug
103
96
  Subcmd2.new(name, min, is_bool, help)
104
97
  end unless defined?(Subcommands)
105
98
 
106
- SetHistorySubcommands = [
107
- ['filename', 1, 'Set the filename in which to record command history'],
108
- ['save' , 1, 'Set saving of the history record on exit' ],
109
- ['size' , 1, 'Set the size of the command history' ]
110
- ].map do |name, min, help|
111
- Subcmd.new(name, min, help)
112
- end unless defined?(SetHistorySubcommands)
113
-
114
99
  self.allow_in_control = true
115
100
 
116
101
  def regexp
@@ -17,129 +17,60 @@ module Byebug
17
17
  else
18
18
  args = ''
19
19
  end
20
- return "Argument list to give program being debugged when it is started is \"#{args}\"."
20
+ "Argument list to give program being debugged when it is started is \"#{args}\"."
21
21
  when /^autolist$/
22
- on_off = Command.settings[:autolist] > 0
23
- return "autolist is #{show_onoff(on_off)}."
24
- when /^autoeval$/
25
- on_off = Command.settings[:autoeval]
26
- return "autoeval is #{show_onoff(on_off)}."
27
- when /^autoreload$/
28
- on_off = Command.settings[:autoreload]
29
- return "autoreload is #{show_onoff(on_off)}."
22
+ "autolist is #{show_onoff(Command.settings[:autolist] > 0)}."
30
23
  when /^autoirb$/
31
- on_off = Command.settings[:autoirb] > 0
32
- return "autoirb is #{show_onoff(on_off)}."
33
- when /^basename$/
34
- on_off = Command.settings[:basename]
35
- return "basename is #{show_onoff(on_off)}."
24
+ "autoirb is #{show_onoff(Command.settings[:autoirb] > 0)}."
25
+ when /^autosave$/
26
+ "Saving history is #{show_onoff(Command.settings[:autosave])}."
36
27
  when /^callstyle$/
37
- style = Command.settings[:callstyle]
38
- return "Frame call-display style is #{style}."
28
+ "Frame call-display style is #{Command.settings[:callstyle]}."
39
29
  when /^commands(:?\s+(\d+))?$/
40
- if @state.interface.readline_support?
41
- s = '';
30
+ if Command.settings[:autosave]
31
+ history = Byebug::History
42
32
  args = @match[1].split
43
33
  if args[1]
44
- first_line = args[1].to_i - 4
45
- last_line = first_line + 10 - 1
46
- if first_line > Readline::HISTORY.length
47
- first_line = last_line = Readline::HISTORY.length
48
- elsif first_line <= 0
49
- first_line = 1
50
- end
51
- if last_line > Readline::HISTORY.length
52
- last_line = Readline::HISTORY.length
53
- end
54
- i = first_line
55
- commands = Readline::HISTORY.to_a[first_line..last_line]
56
- else
57
- if Readline::HISTORY.length > 10
58
- commands = Readline::HISTORY.to_a[-10..-1]
59
- i = Readline::HISTORY.length - 10
60
- else
61
- commands = Readline::HISTORY.to_a
62
- i = 1
63
- end
64
- end
65
- commands.each do |cmd|
66
- s += ("%5d %s\n" % [i, cmd])
67
- i += 1
34
+ size = get_int(args[1], 'show commands', 1, history.max_size)
68
35
  end
36
+ size ? history.to_s(size) : history.to_s
69
37
  else
70
- s='No readline support'
38
+ 'Not currently saving history. Enable it with "set autosave"'
71
39
  end
72
- return s
73
40
  when /^testing$/
74
- on_off = Command.settings[:testing]
75
- return "Currently testing byebug is #{show_onoff(on_off)}."
41
+ "Currently testing byebug is #{show_onoff(Command.settings[:testing])}."
76
42
  when /^forcestep$/
77
- on_off = Command.settings[:forcestep]
78
- return "force-stepping is #{show_onoff(on_off)}."
43
+ "force-stepping is #{show_onoff(Command.settings[:forcestep])}."
79
44
  when /^fullpath$/
80
- on_off = Command.settings[:fullpath]
81
- return "Displaying frame's full file names is #{show_onoff(on_off)}."
82
- when /^history(:?\s+(filename|save|size))?$/
83
- args = @match[1].split
84
- interface = @state.interface
85
- if args[1]
86
- show_save = show_size = show_filename = false
87
- prefix = false
88
- if args[1] == "save"
89
- show_save = true
90
- elsif args[1] == "size"
91
- show_size = true
92
- elsif args[1] == "filename"
93
- show_filename = true
94
- end
95
- else
96
- show_save = show_size = show_filename = true
97
- prefix = true
98
- end
99
- s = []
100
- if show_filename
101
- msg = "#{prefix ? 'filename:' : ''} The command history file is " \
102
- "#{interface.histfile.inspect}"
103
- s << msg
104
- end
105
- if show_save
106
- msg = (prefix ? "save: " : "") +
107
- "Saving of history save is #{show_onoff(interface.history_save)}."
108
- s << msg
109
- end
110
- if show_size
111
- msg = (prefix ? "size: " : "") +
112
- "Byebug history size is #{interface.history_length}"
113
- s << msg
114
- end
115
- return s.join("\n")
45
+ "Displaying frame's full file names is #{show_onoff(Command.settings[:fullpath])}."
46
+ when /^histfile$/
47
+ "The command history file is \"#{Byebug::History.file}\""
48
+ when /^histsize$/
49
+ "Byebug history's maximum size is #{Byebug::History.max_size}"
116
50
  when /^linetrace$/
117
- on_off = Byebug.tracing?
118
- return "line tracing is #{show_onoff(on_off)}."
51
+ "line tracing is #{show_onoff(Byebug.tracing?)}."
119
52
  when /^linetrace_plus$/
120
53
  if Command.settings[:linetrace_plus]
121
- return "line tracing style is every line."
54
+ 'line tracing style is every line.'
122
55
  else
123
- return "line tracing style is different consecutive lines."
56
+ 'line tracing style is different consecutive lines.'
124
57
  end
125
58
  when /^listsize$/
126
- listlines = Command.settings[:listsize]
127
- return "Number of source lines to list is #{listlines}."
59
+ "Number of source lines to list is #{Command.settings[:listsize]}."
128
60
  when /^post_mortem$/
129
- on_off = Byebug.post_mortem?
130
- return "post-mortem mode is #{show_onoff(on_off)}"
61
+ "Post-mortem mode is #{show_onoff(Byebug.post_mortem?)}"
131
62
  when /^stack_on_error$/
132
- on_off = Command.settings[:stack_on_error]
133
- return "Displaying stack trace is #{show_onoff(on_off)}."
63
+ "Displaying stack trace is #{show_onoff(Command.settings[:stack_on_error])}."
134
64
  when /^verbose$/
135
- on_off = Byebug.verbose
136
- return "Verbose output of TracePoint API events is #{show_onoff(on_off)}."
65
+ "Verbose output of TracePoint API events is #{show_onoff(Byebug.verbose)}."
137
66
  when /^version$/
138
- return "Byebug #{Byebug::VERSION}"
67
+ "Byebug #{Byebug::VERSION}"
139
68
  when /^width$/
140
- return "width is #{Command.settings[:width]}."
69
+ "Width is #{Command.settings[:width]}."
70
+ when /^autoeval|autoreload|basename$/x
71
+ "#{setting_name} is #{show_onoff(Command.settings[setting_name.to_sym])}."
141
72
  else
142
- return "Unknown show subcommand #{setting_name}."
73
+ "Unknown show subcommand #{setting_name}."
143
74
  end
144
75
  end
145
76
  end
@@ -150,12 +81,14 @@ module Byebug
150
81
  Subcommands = [
151
82
  ['args' , 2 , 'Show argument list to the program being ' \
152
83
  'debugged when it is started' ],
153
- ['autoeval' , 4 , 'Show whether unrecognized commands are ' \
84
+ ['autoeval' , 5 , 'Show whether unrecognized commands are ' \
154
85
  'evaluated' ],
155
- ['autolist' , 4 , 'Show whether "list" command is run on stopping' ],
156
- ['autoirb' , 4 , 'Show whether IRB is invoked on stopping' ],
157
- ['autoreload' , 4 , 'Show whether source code is reloaded when ' \
86
+ ['autolist' , 5 , 'Show whether "list" command is run on stopping' ],
87
+ ['autoirb' , 5 , 'Show whether IRB is invoked on stopping' ],
88
+ ['autoreload' , 5 , 'Show whether source code is reloaded when ' \
158
89
  'changed' ],
90
+ ['autosave' , 5 , 'Show whether command history is ' \
91
+ 'automatically saved on exit' ],
159
92
  ['basename' , 1 , 'Show whether basename is used when reporting' \
160
93
  ' files' ],
161
94
  ['callstyle' , 2 , 'Show parameter style used when showing call' \
@@ -165,7 +98,9 @@ module Byebug
165
98
  ['forcestep' , 1 , 'Show whether "next/step" commands are set to' \
166
99
  ' always move to a line' ],
167
100
  ['fullpath' , 2 , 'Show whether full paths are displayed in frames'],
168
- ['history' , 2 , 'Show command history configurations. ' ],
101
+ ['histfile' , 5 , 'File where byebug save history of commands' ],
102
+ ['histsize' , 5 , 'Maximum number of commands stored in ' \
103
+ 'byebug\'s history' ],
169
104
  ['linetrace' , 3 , 'Show line execution tracing status' ],
170
105
  ['linetrace_plus', 10, 'Show whether different consecutive lines are' \
171
106
  ' shown in tracing' ],
@@ -183,14 +118,6 @@ module Byebug
183
118
  Subcmd.new(name, min, help)
184
119
  end unless defined?(Subcommands)
185
120
 
186
- ShowHistorySubcommands = [
187
- ['filename', 1, 'Show the filename in which to record command history' ],
188
- ['save' , 1, 'Show whether history record should be saved on exit' ],
189
- ['size' , 1, 'Show the size of the command history' ]
190
- ].map do |name, min, help|
191
- Subcmd.new(name, min, help)
192
- end unless defined?(SetHistorySubcommands)
193
-
194
121
  self.allow_in_control = true
195
122
 
196
123
  def regexp
@@ -18,7 +18,6 @@ module Byebug
18
18
  # Implements byebug "next" command.
19
19
  class NextCommand < Command
20
20
  self.allow_in_post_mortem = false
21
- self.need_context = true
22
21
 
23
22
  def regexp
24
23
  /^\s* n(?:ext)?([+-])? (?:\s+(\S+))? \s*$/x
@@ -48,7 +47,6 @@ module Byebug
48
47
  # Implements byebug "step" command.
49
48
  class StepCommand < Command
50
49
  self.allow_in_post_mortem = false
51
- self.need_context = true
52
50
 
53
51
  def regexp
54
52
  /^\s* s(?:tep)?([+-]) ?(?:\s+(\S+))? \s*$/x
@@ -90,8 +90,6 @@ module Byebug
90
90
  end
91
91
 
92
92
  class ThreadCurrentCommand < Command
93
- self.need_context = true
94
-
95
93
  def regexp
96
94
  /^\s* th(?:read)? \s+ (?:cur(?:rent)?)? \s*$/x
97
95
  end
@@ -114,7 +112,6 @@ module Byebug
114
112
  class ThreadStopCommand < Command
115
113
  self.allow_in_control = true
116
114
  self.allow_in_post_mortem = false
117
- self.need_context = true
118
115
 
119
116
  def regexp
120
117
  /^\s* th(?:read)? \s+ stop \s* (\S*) \s*$/x
@@ -141,7 +138,6 @@ module Byebug
141
138
  class ThreadResumeCommand < Command
142
139
  self.allow_in_control = true
143
140
  self.allow_in_post_mortem = false
144
- self.need_context = true
145
141
 
146
142
  def regexp
147
143
  /^\s* th(?:read)? \s+ resume \s* (\S*) \s*$/x
@@ -172,7 +168,6 @@ module Byebug
172
168
  class ThreadSwitchCommand < Command
173
169
  self.allow_in_control = true
174
170
  self.allow_in_post_mortem = false
175
- self.need_context = true
176
171
 
177
172
  def regexp
178
173
  /^\s* th(?:read)? \s+ (?:sw(?:itch)?\s+)? (\S+) \s*$/x
@@ -19,7 +19,7 @@ module Byebug
19
19
  if @match[3] && @match[3] !~ /(:?no)?stop/
20
20
  errmsg "expecting \"stop\" or \"nostop\"; got \"#{@match[3]}\"\n"
21
21
  else
22
- dbg_cmd = (@match[3] && @match[3] !~ /nostop/) ? 'byebug(1,0)' : ''
22
+ dbg_cmd = (@match[3] && @match[3] !~ /nostop/) ? 'byebug(1, false)' : ''
23
23
  end
24
24
  eval("trace_var(:\"\$#{varname}\") do |val|
25
25
  print \"traced global variable '#{varname}' has value '\#{val}'\"\n
@@ -27,7 +27,7 @@ module Byebug
27
27
  end
28
28
 
29
29
  # Implements byebug's 'var class' command
30
- class VarClassVarCommand < Command
30
+ class VarClassCommand < Command
31
31
  def regexp
32
32
  /^\s* v(?:ar)? \s+ cl(?:ass)? \s*/x
33
33
  end
@@ -3,24 +3,20 @@ module Byebug
3
3
  class Context
4
4
 
5
5
  class << self
6
- def stack_size
6
+ def stack_size(byebug_frames = false)
7
7
  if backtrace = Thread.current.backtrace_locations(0)
8
- backtrace.drop_while { |l| !ignored(l.path) }
9
- .drop_while { |l| ignored(l.path) }
10
- .take_while { |l| !ignored(l.path) }
11
- .size
8
+ unless byebug_frames
9
+ backtrace = backtrace.drop_while { |l| !ignored(l.path) }
10
+ .drop_while { |l| ignored(l.path) }
11
+ .take_while { |l| !ignored(l.path) }
12
+ end
13
+ backtrace.size
12
14
  else
13
- print 'No backtrace available!!'
15
+ print 'WARNING: No backtrace available!!'
14
16
  0
15
17
  end
16
18
  end
17
19
 
18
- def real_stack_size
19
- if backtrace = Thread.current.backtrace_locations(0)
20
- backtrace.size
21
- end
22
- end
23
-
24
20
  def ignored(path)
25
21
  IGNORED_FILES.include?(path)
26
22
  end
@@ -61,7 +61,7 @@ module Byebug
61
61
  # Return true if code is syntactically correct for Ruby.
62
62
  def syntax_valid?(code)
63
63
  eval("BEGIN {return true}\n#{code}", nil, "", 0)
64
- rescue Exception
64
+ rescue SyntaxError
65
65
  false
66
66
  end
67
67
 
@@ -0,0 +1,46 @@
1
+ require 'readline'
2
+
3
+ module Byebug
4
+ class History
5
+ DEFAULT_FILE = File.expand_path("#{ENV['HOME']||'.'}/.byebug_hist")
6
+ DEFAULT_MAX_SIZE = 256
7
+
8
+ @file = DEFAULT_FILE
9
+ @max_size = DEFAULT_MAX_SIZE
10
+
11
+ class << self
12
+ attr_accessor :file, :max_size
13
+
14
+ def load
15
+ open(@file, 'r') do |file|
16
+ file.each do |line|
17
+ line.chomp!
18
+ Readline::HISTORY << line
19
+ end
20
+ end if File.exist?(@file)
21
+ end
22
+
23
+ def save
24
+ open(@file, 'w') do |file|
25
+ Readline::HISTORY.to_a.last(@max_size).each do |line|
26
+ file.puts line unless line.strip.empty?
27
+ end
28
+ end
29
+ end
30
+
31
+ def to_s(size = @max_size)
32
+ n_entries = Readline::HISTORY.length < size ? Readline::HISTORY.length : size
33
+
34
+ first = Readline::HISTORY.length - n_entries
35
+ commands = Readline::HISTORY.to_a.last(n_entries)
36
+
37
+ s = ''
38
+ commands.each_with_index do |command, index|
39
+ s += ("%5d %s\n" % [first + index + 1, command])
40
+ end
41
+
42
+ return s
43
+ end
44
+ end
45
+ end
46
+ end