byebug 10.0.1 → 11.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +352 -285
  3. data/CONTRIBUTING.md +6 -34
  4. data/GUIDE.md +9 -8
  5. data/LICENSE +18 -18
  6. data/README.md +83 -72
  7. data/exe/byebug +1 -1
  8. data/ext/byebug/breakpoint.c +1 -1
  9. data/ext/byebug/byebug.c +9 -14
  10. data/ext/byebug/byebug.h +9 -7
  11. data/ext/byebug/context.c +19 -6
  12. data/ext/byebug/locker.c +4 -4
  13. data/ext/byebug/threads.c +3 -3
  14. data/lib/byebug.rb +1 -1
  15. data/lib/byebug/attacher.rb +4 -4
  16. data/lib/byebug/command.rb +2 -2
  17. data/lib/byebug/command_list.rb +1 -1
  18. data/lib/byebug/commands.rb +38 -37
  19. data/lib/byebug/commands/break.rb +10 -14
  20. data/lib/byebug/commands/catch.rb +4 -8
  21. data/lib/byebug/commands/condition.rb +3 -5
  22. data/lib/byebug/commands/continue.rb +27 -9
  23. data/lib/byebug/commands/debug.rb +2 -2
  24. data/lib/byebug/commands/delete.rb +3 -5
  25. data/lib/byebug/commands/disable.rb +4 -4
  26. data/lib/byebug/commands/disable/breakpoints.rb +1 -1
  27. data/lib/byebug/commands/disable/display.rb +1 -1
  28. data/lib/byebug/commands/display.rb +2 -2
  29. data/lib/byebug/commands/down.rb +3 -3
  30. data/lib/byebug/commands/edit.rb +2 -1
  31. data/lib/byebug/commands/enable.rb +3 -3
  32. data/lib/byebug/commands/enable/breakpoints.rb +1 -1
  33. data/lib/byebug/commands/enable/display.rb +1 -1
  34. data/lib/byebug/commands/finish.rb +2 -2
  35. data/lib/byebug/commands/frame.rb +3 -3
  36. data/lib/byebug/commands/help.rb +2 -2
  37. data/lib/byebug/commands/history.rb +2 -2
  38. data/lib/byebug/commands/info.rb +6 -6
  39. data/lib/byebug/commands/info/breakpoints.rb +2 -4
  40. data/lib/byebug/commands/info/display.rb +1 -3
  41. data/lib/byebug/commands/info/file.rb +2 -4
  42. data/lib/byebug/commands/interrupt.rb +1 -1
  43. data/lib/byebug/commands/irb.rb +2 -4
  44. data/lib/byebug/commands/kill.rb +3 -5
  45. data/lib/byebug/commands/list.rb +4 -4
  46. data/lib/byebug/commands/method.rb +2 -2
  47. data/lib/byebug/commands/next.rb +2 -2
  48. data/lib/byebug/commands/pry.rb +3 -5
  49. data/lib/byebug/commands/quit.rb +4 -4
  50. data/lib/byebug/commands/restart.rb +3 -3
  51. data/lib/byebug/commands/save.rb +1 -1
  52. data/lib/byebug/commands/set.rb +3 -3
  53. data/lib/byebug/commands/show.rb +1 -1
  54. data/lib/byebug/commands/skip.rb +85 -0
  55. data/lib/byebug/commands/source.rb +2 -4
  56. data/lib/byebug/commands/step.rb +2 -2
  57. data/lib/byebug/commands/thread.rb +6 -6
  58. data/lib/byebug/commands/thread/current.rb +1 -1
  59. data/lib/byebug/commands/thread/list.rb +1 -1
  60. data/lib/byebug/commands/thread/resume.rb +2 -4
  61. data/lib/byebug/commands/thread/stop.rb +1 -1
  62. data/lib/byebug/commands/thread/switch.rb +1 -1
  63. data/lib/byebug/commands/tracevar.rb +2 -5
  64. data/lib/byebug/commands/undisplay.rb +5 -6
  65. data/lib/byebug/commands/untracevar.rb +1 -1
  66. data/lib/byebug/commands/up.rb +3 -3
  67. data/lib/byebug/commands/var.rb +8 -8
  68. data/lib/byebug/commands/var/all.rb +1 -1
  69. data/lib/byebug/commands/var/args.rb +1 -1
  70. data/lib/byebug/commands/var/const.rb +2 -4
  71. data/lib/byebug/commands/var/instance.rb +1 -1
  72. data/lib/byebug/commands/var/local.rb +1 -1
  73. data/lib/byebug/commands/where.rb +2 -2
  74. data/lib/byebug/context.rb +4 -4
  75. data/lib/byebug/core.rb +10 -9
  76. data/lib/byebug/frame.rb +2 -2
  77. data/lib/byebug/helpers/frame.rb +1 -1
  78. data/lib/byebug/helpers/parse.rb +1 -3
  79. data/lib/byebug/helpers/string.rb +0 -3
  80. data/lib/byebug/helpers/toggle.rb +2 -4
  81. data/lib/byebug/helpers/var.rb +1 -1
  82. data/lib/byebug/history.rb +1 -1
  83. data/lib/byebug/interface.rb +6 -6
  84. data/lib/byebug/interfaces/local_interface.rb +1 -1
  85. data/lib/byebug/interfaces/remote_interface.rb +1 -1
  86. data/lib/byebug/interfaces/script_interface.rb +2 -1
  87. data/lib/byebug/printers/base.rb +4 -5
  88. data/lib/byebug/printers/plain.rb +1 -1
  89. data/lib/byebug/processors/command_processor.rb +2 -2
  90. data/lib/byebug/processors/control_processor.rb +1 -1
  91. data/lib/byebug/processors/post_mortem_processor.rb +1 -1
  92. data/lib/byebug/processors/script_processor.rb +1 -1
  93. data/lib/byebug/remote.rb +3 -3
  94. data/lib/byebug/remote/client.rb +2 -0
  95. data/lib/byebug/runner.rb +7 -7
  96. data/lib/byebug/setting.rb +2 -2
  97. data/lib/byebug/settings/autoirb.rb +2 -2
  98. data/lib/byebug/settings/autolist.rb +2 -2
  99. data/lib/byebug/settings/autopry.rb +2 -2
  100. data/lib/byebug/settings/autosave.rb +1 -1
  101. data/lib/byebug/settings/basename.rb +1 -1
  102. data/lib/byebug/settings/callstyle.rb +2 -2
  103. data/lib/byebug/settings/fullpath.rb +1 -1
  104. data/lib/byebug/settings/histfile.rb +1 -1
  105. data/lib/byebug/settings/histsize.rb +1 -1
  106. data/lib/byebug/settings/linetrace.rb +1 -1
  107. data/lib/byebug/settings/listsize.rb +1 -1
  108. data/lib/byebug/settings/post_mortem.rb +1 -1
  109. data/lib/byebug/settings/savefile.rb +1 -1
  110. data/lib/byebug/settings/stack_on_error.rb +1 -1
  111. data/lib/byebug/settings/width.rb +1 -1
  112. data/lib/byebug/source_file_formatter.rb +2 -2
  113. data/lib/byebug/subcommands.rb +2 -2
  114. data/lib/byebug/version.rb +1 -1
  115. metadata +9 -9
@@ -30,7 +30,8 @@
30
30
  } while (0)
31
31
 
32
32
  /* types */
33
- typedef enum {
33
+ typedef enum
34
+ {
34
35
  CTX_STOP_NONE,
35
36
  CTX_STOP_STEP,
36
37
  CTX_STOP_BREAKPOINT,
@@ -54,7 +55,8 @@ typedef struct
54
55
  VALUE backtrace; /* [[loc, self, klass, binding], ...] */
55
56
  } debug_context_t;
56
57
 
57
- typedef enum {
58
+ typedef enum
59
+ {
58
60
  LOCATION,
59
61
  SELF,
60
62
  CLASS,
@@ -107,9 +109,9 @@ typedef struct
107
109
  } breakpoint_t;
108
110
 
109
111
  /* functions from locker.c */
110
- extern void add_to_locked(VALUE thread);
111
- extern VALUE pop_from_locked();
112
- extern void remove_from_locked(VALUE thread);
112
+ extern void byebug_add_to_locked(VALUE thread);
113
+ extern VALUE byebug_pop_from_locked();
114
+ extern void byebug_remove_from_locked(VALUE thread);
113
115
 
114
116
  /* functions from threads.c */
115
117
  extern void Init_threads_table(VALUE mByebug);
@@ -127,13 +129,13 @@ extern VALUE next_thread;
127
129
  extern void Init_byebug_context(VALUE mByebug);
128
130
  extern VALUE byebug_context_create(VALUE thread);
129
131
  extern VALUE context_dup(debug_context_t *context);
130
- extern void reset_stepping_stop_points(debug_context_t *context);
132
+ extern void byebug_reset_stepping_stop_points(debug_context_t *context);
131
133
  extern VALUE call_with_debug_inspector(struct call_with_inspection_data *data);
132
134
  extern VALUE context_backtrace_set(const rb_debug_inspector_t *inspector,
133
135
  void *data);
134
136
 
135
137
  /* functions from breakpoint.c */
136
- extern void Init_breakpoint(VALUE mByebug);
138
+ extern void Init_byebug_breakpoint(VALUE mByebug);
137
139
  extern VALUE find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
138
140
  VALUE bind);
139
141
 
@@ -5,9 +5,9 @@ static VALUE cDebugThread;
5
5
  static int thnum_max = 0;
6
6
 
7
7
  /* "Step", "Next" and "Finish" do their work by saving information about where
8
- * to stop next. reset_stepping_stop_points removes/resets this information. */
8
+ * to stop next. byebug_reset_stepping_stop_points removes/resets this information. */
9
9
  extern void
10
- reset_stepping_stop_points(debug_context_t *context)
10
+ byebug_reset_stepping_stop_points(debug_context_t *context)
11
11
  {
12
12
  context->dest_frame = -1;
13
13
  context->lines = -1;
@@ -63,7 +63,7 @@ byebug_context_create(VALUE thread)
63
63
  context->flags = 0;
64
64
  context->thnum = ++thnum_max;
65
65
  context->thread = thread;
66
- reset_stepping_stop_points(context);
66
+ byebug_reset_stepping_stop_points(context);
67
67
  context->stop_reason = CTX_STOP_NONE;
68
68
 
69
69
  rb_debug_inspector_open(context_backtrace_set, (void *)context);
@@ -81,7 +81,7 @@ context_dup(debug_context_t *context)
81
81
  debug_context_t *new_context = ALLOC(debug_context_t);
82
82
 
83
83
  memcpy(new_context, context, sizeof(debug_context_t));
84
- reset_stepping_stop_points(new_context);
84
+ byebug_reset_stepping_stop_points(new_context);
85
85
  new_context->backtrace = context->backtrace;
86
86
  CTX_FL_SET(new_context, CTX_FL_DEAD);
87
87
 
@@ -177,6 +177,13 @@ open_debug_inspector(struct call_with_inspection_data *cwi)
177
177
  return rb_debug_inspector_open(open_debug_inspector_i, cwi);
178
178
  }
179
179
 
180
+ static VALUE
181
+ open_debug_inspector_ensure(VALUE v)
182
+ {
183
+ return open_debug_inspector((struct call_with_inspection_data *)v);
184
+ }
185
+
186
+
180
187
  static VALUE
181
188
  close_debug_inspector(struct call_with_inspection_data *cwi)
182
189
  {
@@ -184,10 +191,16 @@ close_debug_inspector(struct call_with_inspection_data *cwi)
184
191
  return Qnil;
185
192
  }
186
193
 
194
+ static VALUE
195
+ close_debug_inspector_ensure(VALUE v)
196
+ {
197
+ return close_debug_inspector((struct call_with_inspection_data *)v);
198
+ }
199
+
187
200
  extern VALUE
188
201
  call_with_debug_inspector(struct call_with_inspection_data *data)
189
202
  {
190
- return rb_ensure(open_debug_inspector, (VALUE)data, close_debug_inspector,
203
+ return rb_ensure(open_debug_inspector_ensure, (VALUE)data, close_debug_inspector_ensure,
191
204
  (VALUE)data);
192
205
  }
193
206
 
@@ -669,5 +682,5 @@ Init_byebug_context(VALUE mByebug)
669
682
  rb_define_method(cContext, "tracing=", Context_set_tracing, 1);
670
683
 
671
684
  cDebugThread = rb_define_class_under(mByebug, "DebugThread", rb_cThread);
672
- rb_define_singleton_method(cDebugThread, "inherited", dt_inherited, 1);
685
+ rb_define_singleton_method(cDebugThread, "inherited", dt_inherited, 0);
673
686
  }
@@ -29,7 +29,7 @@ is_in_locked(VALUE thread)
29
29
  }
30
30
 
31
31
  extern void
32
- add_to_locked(VALUE thread)
32
+ byebug_add_to_locked(VALUE thread)
33
33
  {
34
34
  locked_thread_t *node;
35
35
 
@@ -50,7 +50,7 @@ add_to_locked(VALUE thread)
50
50
  }
51
51
 
52
52
  extern VALUE
53
- pop_from_locked()
53
+ byebug_pop_from_locked()
54
54
  {
55
55
  VALUE thread;
56
56
  locked_thread_t *node;
@@ -71,7 +71,7 @@ pop_from_locked()
71
71
  }
72
72
 
73
73
  extern void
74
- remove_from_locked(VALUE thread)
74
+ byebug_remove_from_locked(VALUE thread)
75
75
  {
76
76
  locked_thread_t *node;
77
77
  locked_thread_t *next_node;
@@ -81,7 +81,7 @@ remove_from_locked(VALUE thread)
81
81
 
82
82
  if (locked_head->thread == thread)
83
83
  {
84
- pop_from_locked();
84
+ byebug_pop_from_locked();
85
85
  return;
86
86
  }
87
87
 
@@ -134,7 +134,7 @@ acquire_lock(debug_context_t *dc)
134
134
  while ((!NIL_P(locker) && locker != rb_thread_current())
135
135
  || CTX_FL_TEST(dc, CTX_FL_SUSPEND))
136
136
  {
137
- add_to_locked(rb_thread_current());
137
+ byebug_add_to_locked(rb_thread_current());
138
138
  rb_thread_stop();
139
139
 
140
140
  if (CTX_FL_TEST(dc, CTX_FL_SUSPEND))
@@ -159,10 +159,10 @@ release_lock(void)
159
159
  locker = Qnil;
160
160
 
161
161
  if (NIL_P(next_thread))
162
- thread = pop_from_locked();
162
+ thread = byebug_pop_from_locked();
163
163
  else
164
164
  {
165
- remove_from_locked(next_thread);
165
+ byebug_remove_from_locked(next_thread);
166
166
  thread = next_thread;
167
167
  next_thread = Qnil;
168
168
  }
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/attacher"
3
+ require_relative "byebug/attacher"
@@ -8,8 +8,6 @@ module Byebug
8
8
  # Starts byebug, and stops at the first line of user's code.
9
9
  #
10
10
  def self.attach
11
- require "byebug/core"
12
-
13
11
  unless started?
14
12
  self.mode = :attached
15
13
 
@@ -21,7 +19,7 @@ module Byebug
21
19
  end
22
20
 
23
21
  def self.spawn(host = "localhost", port = nil)
24
- require "byebug/core"
22
+ require_relative "core"
25
23
 
26
24
  self.wait_connection = true
27
25
  start_server(host, port || PORT)
@@ -35,7 +33,9 @@ end
35
33
  #
36
34
  module Kernel
37
35
  def byebug
38
- Byebug.attach
36
+ require_relative "core"
37
+
38
+ Byebug.attach unless Byebug.mode == :off
39
39
  end
40
40
 
41
41
  def remote_byebug(host = "localhost", port = nil)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "forwardable"
4
- require "byebug/helpers/string"
4
+ require_relative "helpers/string"
5
5
 
6
6
  module Byebug
7
7
  #
@@ -80,7 +80,7 @@ module Byebug
80
80
  def to_s
81
81
  name
82
82
  .split("::")
83
- .map { |n| n.gsub(/Command$/, "").downcase if n =~ /Command$/ }
83
+ .map { |n| n.gsub(/Command$/, "").downcase if /Command$/.match?(n) }
84
84
  .compact
85
85
  .join(" ")
86
86
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/errors"
3
+ require_relative "errors"
4
4
 
5
5
  module Byebug
6
6
  #
@@ -1,39 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/commands/break"
4
- require "byebug/commands/catch"
5
- require "byebug/commands/condition"
6
- require "byebug/commands/continue"
7
- require "byebug/commands/debug"
8
- require "byebug/commands/delete"
9
- require "byebug/commands/disable"
10
- require "byebug/commands/display"
11
- require "byebug/commands/down"
12
- require "byebug/commands/edit"
13
- require "byebug/commands/enable"
14
- require "byebug/commands/finish"
15
- require "byebug/commands/frame"
16
- require "byebug/commands/help"
17
- require "byebug/commands/history"
18
- require "byebug/commands/info"
19
- require "byebug/commands/interrupt"
20
- require "byebug/commands/irb"
21
- require "byebug/commands/kill"
22
- require "byebug/commands/list"
23
- require "byebug/commands/method"
24
- require "byebug/commands/next"
25
- require "byebug/commands/pry"
26
- require "byebug/commands/quit"
27
- require "byebug/commands/restart"
28
- require "byebug/commands/save"
29
- require "byebug/commands/set"
30
- require "byebug/commands/show"
31
- require "byebug/commands/source"
32
- require "byebug/commands/step"
33
- require "byebug/commands/thread"
34
- require "byebug/commands/tracevar"
35
- require "byebug/commands/undisplay"
36
- require "byebug/commands/untracevar"
37
- require "byebug/commands/up"
38
- require "byebug/commands/var"
39
- require "byebug/commands/where"
3
+ require_relative "commands/break"
4
+ require_relative "commands/catch"
5
+ require_relative "commands/condition"
6
+ require_relative "commands/continue"
7
+ require_relative "commands/debug"
8
+ require_relative "commands/delete"
9
+ require_relative "commands/disable"
10
+ require_relative "commands/display"
11
+ require_relative "commands/down"
12
+ require_relative "commands/edit"
13
+ require_relative "commands/enable"
14
+ require_relative "commands/finish"
15
+ require_relative "commands/frame"
16
+ require_relative "commands/help"
17
+ require_relative "commands/history"
18
+ require_relative "commands/info"
19
+ require_relative "commands/interrupt"
20
+ require_relative "commands/irb"
21
+ require_relative "commands/kill"
22
+ require_relative "commands/list"
23
+ require_relative "commands/method"
24
+ require_relative "commands/next"
25
+ require_relative "commands/pry"
26
+ require_relative "commands/quit"
27
+ require_relative "commands/restart"
28
+ require_relative "commands/save"
29
+ require_relative "commands/set"
30
+ require_relative "commands/show"
31
+ require_relative "commands/skip"
32
+ require_relative "commands/source"
33
+ require_relative "commands/step"
34
+ require_relative "commands/thread"
35
+ require_relative "commands/tracevar"
36
+ require_relative "commands/undisplay"
37
+ require_relative "commands/untracevar"
38
+ require_relative "commands/up"
39
+ require_relative "commands/var"
40
+ require_relative "commands/where"
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/command"
4
- require "byebug/helpers/eval"
5
- require "byebug/helpers/file"
6
- require "byebug/helpers/parse"
7
- require "byebug/source_file_formatter"
3
+ require_relative "../command"
4
+ require_relative "../helpers/eval"
5
+ require_relative "../helpers/file"
6
+ require_relative "../helpers/parse"
7
+ require_relative "../source_file_formatter"
8
8
 
9
9
  module Byebug
10
10
  #
@@ -23,8 +23,8 @@ module Byebug
23
23
 
24
24
  def self.description
25
25
  <<-DESCRIPTION
26
- b[reak] [file:]line [if expr]
27
- b[reak] [module::...]class(.|#)method [if expr]
26
+ b[reak] [<file>:]<line> [if <expr>]
27
+ b[reak] [<module>::...]<class>(.|#)<method> [if <expr>]
28
28
 
29
29
  They can be specified by line or method and an expression can be added
30
30
  for conditionally enabled breakpoints.
@@ -43,9 +43,7 @@ module Byebug
43
43
  b = line_breakpoint(@match[1]) || method_breakpoint(@match[1])
44
44
  return errmsg(pr("break.errors.location")) unless b
45
45
 
46
- if syntax_valid?(@match[2])
47
- return puts(pr("break.created", id: b.id, file: b.source, line: b.pos))
48
- end
46
+ return puts(pr("break.created", id: b.id, file: b.source, line: b.pos)) if syntax_valid?(@match[2])
49
47
 
50
48
  errmsg(pr("break.errors.expression", expr: @match[2]))
51
49
  b.enabled = false
@@ -76,7 +74,7 @@ module Byebug
76
74
  def target_object(str)
77
75
  k = error_eval(str)
78
76
 
79
- k && k.is_a?(Module) ? k.name : str
77
+ k&.is_a?(Module) ? k.name : str
80
78
  rescue StandardError
81
79
  errmsg("Warning: breakpoint source is not yet defined")
82
80
  str
@@ -87,9 +85,7 @@ module Byebug
87
85
 
88
86
  fullpath = File.realpath(file)
89
87
 
90
- if line > n_lines(file)
91
- raise(pr("break.errors.far_line", lines: n_lines(file), file: fullpath))
92
- end
88
+ raise(pr("break.errors.far_line", lines: n_lines(file), file: fullpath)) if line > n_lines(file)
93
89
 
94
90
  unless Breakpoint.potential_line?(fullpath, line)
95
91
  msg = pr(
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/command"
4
- require "byebug/helpers/eval"
3
+ require_relative "../command"
4
+ require_relative "../helpers/eval"
5
5
 
6
6
  module Byebug
7
7
  #
@@ -48,18 +48,14 @@ module Byebug
48
48
  private
49
49
 
50
50
  def remove(exception)
51
- unless Byebug.catchpoints.member?(exception)
52
- return errmsg pr("catch.errors.not_found", exception: exception)
53
- end
51
+ return errmsg pr("catch.errors.not_found", exception: exception) unless Byebug.catchpoints.member?(exception)
54
52
 
55
53
  puts pr("catch.removed", exception: exception)
56
54
  Byebug.catchpoints.delete(exception)
57
55
  end
58
56
 
59
57
  def add(exception)
60
- if warning_eval(exception.is_a?(Class).to_s)
61
- errmsg pr("catch.errors.not_class", class: exception)
62
- end
58
+ errmsg pr("catch.errors.not_class", class: exception) if warning_eval(exception.is_a?(Class).to_s)
63
59
 
64
60
  puts pr("catch.added", exception: exception)
65
61
  Byebug.add_catchpoint(exception)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/command"
4
- require "byebug/helpers/parse"
3
+ require_relative "../command"
4
+ require_relative "../helpers/parse"
5
5
 
6
6
  module Byebug
7
7
  #
@@ -47,9 +47,7 @@ module Byebug
47
47
  breakpoint = breakpoints.find { |b| b.id == pos }
48
48
  return errmsg(pr("break.errors.no_breakpoint")) unless breakpoint
49
49
 
50
- unless syntax_valid?(@match[2])
51
- return errmsg(pr("break.errors.not_changed", expr: @match[2]))
52
- end
50
+ return errmsg(pr("break.errors.not_changed", expr: @match[2])) unless syntax_valid?(@match[2])
53
51
 
54
52
  breakpoint.expr = @match[2]
55
53
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "byebug/command"
4
- require "byebug/helpers/parse"
3
+ require_relative "../command"
4
+ require_relative "../helpers/parse"
5
5
 
6
6
  module Byebug
7
7
  #
@@ -14,7 +14,7 @@ module Byebug
14
14
  include Helpers::ParseHelper
15
15
 
16
16
  def self.regexp
17
- /^\s* c(?:ont(?:inue)?)? (?:\s+(\S+))? \s*$/x
17
+ /^\s* c(?:ont(?:inue)?)? (?:(!|\s+unconditionally|\s+\S+))? \s*$/x
18
18
  end
19
19
 
20
20
  def self.description
@@ -22,6 +22,11 @@ module Byebug
22
22
  c[ont[inue]][ <line_number>]
23
23
 
24
24
  #{short_description}
25
+
26
+ Normally the program stops at the next breakpoint. However, if the
27
+ parameter "unconditionally" is given or the command is suffixed with
28
+ "!", the program will run until the end regardless of any enabled
29
+ breakpoints.
25
30
  DESCRIPTION
26
31
  end
27
32
 
@@ -30,21 +35,34 @@ module Byebug
30
35
  end
31
36
 
32
37
  def execute
33
- if @match[1]
34
- num, err = get_int(@match[1], "Continue", 0, nil)
38
+ if until_line?
39
+ num, err = get_int(modifier, "Continue", 0, nil)
35
40
  return errmsg(err) unless num
36
41
 
37
42
  filename = File.expand_path(frame.file)
38
- unless Breakpoint.potential_line?(filename, num)
39
- return errmsg(pr("continue.errors.unstopped_line", line: num))
40
- end
43
+ return errmsg(pr("continue.errors.unstopped_line", line: num)) unless Breakpoint.potential_line?(filename, num)
41
44
 
42
45
  Breakpoint.add(filename, num)
43
46
  end
44
47
 
45
48
  processor.proceed!
46
49
 
47
- Byebug.stop if Byebug.stoppable?
50
+ Byebug.mode = :off if unconditionally?
51
+ Byebug.stop if unconditionally? || Byebug.stoppable?
52
+ end
53
+
54
+ private
55
+
56
+ def until_line?
57
+ @match[1] && !["!", "unconditionally"].include?(modifier)
58
+ end
59
+
60
+ def unconditionally?
61
+ @match[1] && ["!", "unconditionally"].include?(modifier)
62
+ end
63
+
64
+ def modifier
65
+ @match[1].lstrip
48
66
  end
49
67
  end
50
68
  end