byebug 3.2.0 → 3.3.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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +125 -99
  4. data/CONTRIBUTING.md +4 -6
  5. data/GUIDE.md +42 -20
  6. data/Gemfile +5 -3
  7. data/README.md +2 -3
  8. data/Rakefile +11 -7
  9. data/bin/byebug +2 -252
  10. data/byebug.gemspec +7 -4
  11. data/ext/byebug/byebug.c +17 -18
  12. data/ext/byebug/byebug.h +4 -5
  13. data/ext/byebug/context.c +37 -39
  14. data/ext/byebug/threads.c +39 -18
  15. data/lib/byebug.rb +2 -110
  16. data/lib/byebug/attacher.rb +23 -0
  17. data/lib/byebug/breakpoint.rb +60 -0
  18. data/lib/byebug/command.rb +62 -70
  19. data/lib/byebug/commands/break.rb +24 -24
  20. data/lib/byebug/commands/catchpoint.rb +18 -10
  21. data/lib/byebug/commands/condition.rb +18 -17
  22. data/lib/byebug/commands/continue.rb +17 -9
  23. data/lib/byebug/commands/delete.rb +19 -13
  24. data/lib/byebug/commands/display.rb +19 -53
  25. data/lib/byebug/commands/edit.rb +7 -4
  26. data/lib/byebug/commands/enable_disable.rb +130 -0
  27. data/lib/byebug/commands/eval.rb +40 -22
  28. data/lib/byebug/commands/finish.rb +13 -4
  29. data/lib/byebug/commands/frame.rb +65 -45
  30. data/lib/byebug/commands/help.rb +17 -18
  31. data/lib/byebug/commands/history.rb +14 -8
  32. data/lib/byebug/commands/info.rb +160 -182
  33. data/lib/byebug/commands/interrupt.rb +4 -1
  34. data/lib/byebug/commands/irb.rb +30 -0
  35. data/lib/byebug/commands/kill.rb +7 -8
  36. data/lib/byebug/commands/list.rb +71 -66
  37. data/lib/byebug/commands/method.rb +14 -6
  38. data/lib/byebug/commands/pry.rb +35 -0
  39. data/lib/byebug/commands/quit.rb +9 -6
  40. data/lib/byebug/commands/reload.rb +5 -2
  41. data/lib/byebug/commands/restart.rb +13 -9
  42. data/lib/byebug/commands/save.rb +17 -17
  43. data/lib/byebug/commands/set.rb +16 -15
  44. data/lib/byebug/commands/show.rb +10 -11
  45. data/lib/byebug/commands/source.rb +11 -5
  46. data/lib/byebug/commands/stepping.rb +38 -24
  47. data/lib/byebug/commands/threads.rb +45 -31
  48. data/lib/byebug/commands/trace.rb +22 -9
  49. data/lib/byebug/commands/undisplay.rb +45 -0
  50. data/lib/byebug/commands/variables.rb +83 -27
  51. data/lib/byebug/context.rb +25 -22
  52. data/lib/byebug/core.rb +82 -0
  53. data/lib/byebug/helper.rb +37 -28
  54. data/lib/byebug/history.rb +8 -4
  55. data/lib/byebug/interface.rb +12 -17
  56. data/lib/byebug/interfaces/local_interface.rb +11 -8
  57. data/lib/byebug/interfaces/remote_interface.rb +11 -8
  58. data/lib/byebug/interfaces/script_interface.rb +9 -6
  59. data/lib/byebug/options.rb +46 -0
  60. data/lib/byebug/processor.rb +7 -1
  61. data/lib/byebug/processors/command_processor.rb +135 -125
  62. data/lib/byebug/processors/control_command_processor.rb +23 -23
  63. data/lib/byebug/remote.rb +17 -26
  64. data/lib/byebug/runner.rb +100 -0
  65. data/lib/byebug/setting.rb +33 -8
  66. data/lib/byebug/settings/autoeval.rb +5 -15
  67. data/lib/byebug/settings/autoirb.rb +4 -1
  68. data/lib/byebug/settings/autolist.rb +5 -2
  69. data/lib/byebug/settings/autoreload.rb +5 -2
  70. data/lib/byebug/settings/autosave.rb +6 -2
  71. data/lib/byebug/settings/basename.rb +7 -2
  72. data/lib/byebug/settings/callstyle.rb +4 -1
  73. data/lib/byebug/settings/forcestep.rb +6 -3
  74. data/lib/byebug/settings/fullpath.rb +5 -2
  75. data/lib/byebug/settings/histfile.rb +5 -3
  76. data/lib/byebug/settings/histsize.rb +5 -3
  77. data/lib/byebug/settings/linetrace.rb +4 -1
  78. data/lib/byebug/settings/listsize.rb +5 -1
  79. data/lib/byebug/settings/post_mortem.rb +21 -13
  80. data/lib/byebug/settings/stack_on_error.rb +6 -2
  81. data/lib/byebug/settings/testing.rb +6 -1
  82. data/lib/byebug/settings/tracing_plus.rb +5 -1
  83. data/lib/byebug/settings/verbose.rb +13 -2
  84. data/lib/byebug/settings/width.rb +4 -1
  85. data/lib/byebug/version.rb +1 -1
  86. data/test/{break_test.rb → commands/break_test.rb} +41 -53
  87. data/test/{condition_test.rb → commands/condition_test.rb} +14 -14
  88. data/test/{continue_test.rb → commands/continue_test.rb} +0 -0
  89. data/test/{delete_test.rb → commands/delete_test.rb} +2 -2
  90. data/test/commands/display_test.rb +37 -0
  91. data/test/{edit_test.rb → commands/edit_test.rb} +0 -0
  92. data/test/{eval_test.rb → commands/eval_test.rb} +1 -0
  93. data/test/{finish_test.rb → commands/finish_test.rb} +11 -1
  94. data/test/{frame_test.rb → commands/frame_test.rb} +12 -16
  95. data/test/{help_test.rb → commands/help_test.rb} +21 -4
  96. data/test/{history_test.rb → commands/history_test.rb} +0 -0
  97. data/test/{info_test.rb → commands/info_test.rb} +5 -55
  98. data/test/{interrupt_test.rb → commands/interrupt_test.rb} +0 -0
  99. data/test/commands/irb_test.rb +28 -0
  100. data/test/{kill_test.rb → commands/kill_test.rb} +1 -1
  101. data/test/{list_test.rb → commands/list_test.rb} +1 -1
  102. data/test/{method_test.rb → commands/method_test.rb} +0 -0
  103. data/test/{post_mortem_test.rb → commands/post_mortem_test.rb} +6 -10
  104. data/test/{pry_test.rb → commands/pry_test.rb} +4 -13
  105. data/test/{quit_test.rb → commands/quit_test.rb} +4 -4
  106. data/test/{reload_test.rb → commands/reload_test.rb} +0 -0
  107. data/test/{restart_test.rb → commands/restart_test.rb} +6 -0
  108. data/test/{save_test.rb → commands/save_test.rb} +2 -2
  109. data/test/{set_test.rb → commands/set_test.rb} +9 -2
  110. data/test/{show_test.rb → commands/show_test.rb} +1 -1
  111. data/test/{source_test.rb → commands/source_test.rb} +3 -3
  112. data/test/{stepping_test.rb → commands/stepping_test.rb} +44 -35
  113. data/test/{thread_test.rb → commands/thread_test.rb} +0 -0
  114. data/test/{trace_test.rb → commands/trace_test.rb} +0 -0
  115. data/test/{display_test.rb → commands/undisplay_test.rb} +7 -45
  116. data/test/{variables_test.rb → commands/variables_test.rb} +10 -1
  117. data/test/debugger_alias_test.rb +2 -2
  118. data/test/runner_test.rb +127 -0
  119. data/test/support/matchers.rb +27 -25
  120. data/test/support/test_interface.rb +9 -5
  121. data/test/support/utils.rb +96 -101
  122. data/test/test_helper.rb +32 -20
  123. metadata +93 -68
  124. data/lib/byebug/commands/enable.rb +0 -154
  125. data/lib/byebug/commands/repl.rb +0 -126
  126. data/test/irb_test.rb +0 -47
  127. data/test/support/breakpoint.rb +0 -13
@@ -66,16 +66,15 @@ extern void add_to_locked(VALUE thread);
66
66
  extern VALUE remove_from_locked();
67
67
 
68
68
  /* functions from threads.c */
69
- extern VALUE threads_create(void);
70
- extern void threads_clear(VALUE table);
71
- extern void check_thread_contexts(void);
69
+ extern void Init_threads_table(VALUE mByebug);
70
+ extern VALUE create_threads_table(void);
71
+ extern void check_threads_table(void);
72
72
  extern void thread_context_lookup(VALUE thread, VALUE *context);
73
73
  extern void halt_while_other_thread_is_active(debug_context_t *dc);
74
74
 
75
75
  /* global variables */
76
76
  extern VALUE locker;
77
77
  extern VALUE threads;
78
- extern VALUE cThreadsTable;
79
78
 
80
79
  /* functions */
81
80
  extern void Init_context(VALUE mByebug);
@@ -117,11 +116,11 @@ typedef struct {
117
116
  enum hit_condition hit_condition;
118
117
  } breakpoint_t;
119
118
 
119
+ extern void Init_breakpoint(VALUE mByebug);
120
120
  extern VALUE catchpoint_hit_count(VALUE catchpoints, VALUE exception, VALUE *exception_name);
121
121
  extern VALUE find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
122
122
  VALUE binding);
123
123
  extern VALUE find_breakpoint_by_method(VALUE breakpoints, VALUE klass,
124
124
  VALUE mid, VALUE binding, VALUE self);
125
- extern void Init_breakpoint(VALUE mByebug);
126
125
 
127
126
  #endif
@@ -40,7 +40,7 @@ context_mark(void *data)
40
40
  static int
41
41
  real_stack_size()
42
42
  {
43
- return FIX2INT(rb_funcall(cContext, rb_intern("stack_size"), 1, Qtrue));
43
+ return FIX2INT(rb_funcall(cContext, rb_intern("stack_size"), 0));
44
44
  }
45
45
 
46
46
  extern VALUE
@@ -182,25 +182,19 @@ call_with_debug_inspector(struct call_with_inspection_data *data)
182
182
  close_debug_inspector, (VALUE)data);
183
183
  }
184
184
 
185
- #define FRAME_SETUP \
186
- debug_context_t *context; \
187
- VALUE frame_no; \
188
- int frame_n, stack_size; \
189
- Data_Get_Struct(self, debug_context_t, context); \
190
- if (!rb_scan_args(argc, argv, "01", &frame_no)) \
191
- frame_n = 0; \
192
- else \
193
- frame_n = FIX2INT(frame_no); \
194
- stack_size = real_stack_size(); \
195
- if (frame_n < 0 || frame_n >= stack_size) \
196
- { \
197
- rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)", \
198
- frame_n, stack_size - 1); \
199
- } \
185
+ #define FRAME_SETUP \
186
+ debug_context_t *context; \
187
+ VALUE frame_no; \
188
+ int frame_n; \
189
+ Data_Get_Struct(self, debug_context_t, context); \
190
+ if (!rb_scan_args(argc, argv, "01", &frame_no)) \
191
+ frame_n = 0; \
192
+ else \
193
+ frame_n = FIX2INT(frame_no);
200
194
 
201
195
  /*
202
196
  * call-seq:
203
- * context.frame_binding(frame_position=0) -> binding
197
+ * context.frame_binding(frame_position = 0) -> binding
204
198
  *
205
199
  * Returns frame's binding.
206
200
  */
@@ -214,7 +208,7 @@ Context_frame_binding(int argc, VALUE *argv, VALUE self)
214
208
 
215
209
  /*
216
210
  * call-seq:
217
- * context.frame_class(frame_position=0) -> binding
211
+ * context.frame_class(frame_position = 0) -> binding
218
212
  *
219
213
  * Returns frame's defined class.
220
214
  */
@@ -228,7 +222,7 @@ Context_frame_class(int argc, VALUE *argv, VALUE self)
228
222
 
229
223
  /*
230
224
  * call-seq:
231
- * context.frame_file(frame_position=0) -> string
225
+ * context.frame_file(frame_position = 0) -> string
232
226
  *
233
227
  * Returns the name of the file in the frame.
234
228
  */
@@ -418,32 +412,32 @@ Context_step_into(int argc, VALUE *argv, VALUE self)
418
412
 
419
413
  /*
420
414
  * call-seq:
421
- * context.step_out(frame)
415
+ * context.step_out(n_frames = 1, force = false)
422
416
  *
423
- * Stops after +n_frames+ frames are finished. Implements +finish+ and
424
- * +next+ commands. +force+ parameter (if true) ensures that the cursor will
425
- * stop in the specified frame even when there's no more instructions to run.
426
- * In that case, it will stop when the return event for that frame is
427
- * triggered.
417
+ * Stops after +n_frames+ frames are finished. +force+ parameter (if true)
418
+ * ensures that the execution will stop in the specified frame even when there
419
+ * are no more instructions to run. In that case, it will stop when the return
420
+ * event for that frame is triggered.
428
421
  */
429
422
  static VALUE
430
423
  Context_step_out(int argc, VALUE *argv, VALUE self)
431
424
  {
432
425
  int n_args, n_frames;
433
- VALUE v_frames, v_force;
426
+ VALUE v_frames, force;
434
427
  debug_context_t *context;
435
428
 
436
- n_args = rb_scan_args(argc, argv, "02", &v_frames, &v_force);
429
+ n_args = rb_scan_args(argc, argv, "02", &v_frames, &force);
437
430
  n_frames = n_args == 0 ? 1 : FIX2INT(v_frames);
438
- v_force = (n_args < 2) ? Qfalse : v_force;
439
431
 
440
432
  Data_Get_Struct(self, debug_context_t, context);
441
433
 
442
434
  if (n_frames < 0 || n_frames >= context->calced_stack_size)
443
- rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
435
+ rb_raise(rb_eRuntimeError,
436
+ "You wan't to finish %d frames, but stack size is only %d",
437
+ n_frames, context->calced_stack_size);
444
438
 
445
439
  context->steps_out = n_frames;
446
- if (RTEST(v_force))
440
+ if (n_args == 2 && RTEST(force))
447
441
  CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
448
442
  else
449
443
  CTX_FL_UNSET(context, CTX_FL_STOP_ON_RET);
@@ -453,17 +447,18 @@ Context_step_out(int argc, VALUE *argv, VALUE self)
453
447
 
454
448
  /*
455
449
  * call-seq:
456
- * context.step_over(lines, frame = nil, force = false)
450
+ * context.step_over(lines, frame = 0, force = false)
457
451
  *
458
452
  * Steps over +lines+ lines.
459
- * Make step over operation on +frame+, by default the current frame.
453
+ * Make step over operation on +frame+, by default the newest frame.
460
454
  * +force+ parameter (if true) ensures that the cursor moves away from the
461
455
  * current line.
462
456
  */
463
457
  static VALUE
464
458
  Context_step_over(int argc, VALUE *argv, VALUE self)
465
459
  {
466
- VALUE lines, frame, force;
460
+ int n_args, frame;
461
+ VALUE lines, v_frame, force;
467
462
  debug_context_t *context;
468
463
 
469
464
  Data_Get_Struct(self, debug_context_t, context);
@@ -471,14 +466,18 @@ Context_step_over(int argc, VALUE *argv, VALUE self)
471
466
  if (context->calced_stack_size == 0)
472
467
  rb_raise(rb_eRuntimeError, "No frames collected.");
473
468
 
474
- rb_scan_args(argc, argv, "12", &lines, &frame, &force);
475
- if (FIX2INT(frame) < 0 || FIX2INT(frame) >= context->calced_stack_size)
476
- rb_raise(rb_eRuntimeError, "Destination frame is out of range.");
469
+ n_args = rb_scan_args(argc, argv, "12", &lines, &v_frame, &force);
470
+ frame = n_args == 1 ? 0 : FIX2INT(v_frame);
471
+
472
+ if (frame < 0 || frame >= context->calced_stack_size)
473
+ rb_raise(rb_eRuntimeError,
474
+ "Destination frame (%d) is out of range (%d)",
475
+ frame, context->calced_stack_size);
477
476
 
478
477
  context->lines = FIX2INT(lines);
479
- context->dest_frame = context->calced_stack_size - FIX2INT(frame);
478
+ context->dest_frame = context->calced_stack_size - frame;
480
479
 
481
- if (RTEST(force))
480
+ if (n_args == 3 && RTEST(force))
482
481
  CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
483
482
  else
484
483
  CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
@@ -597,7 +596,6 @@ Context_set_tracing(VALUE self, VALUE value)
597
596
  return value;
598
597
  }
599
598
 
600
-
601
599
  /* :nodoc: */
602
600
  static VALUE
603
601
  DebugThread_inherited(VALUE klass)
@@ -1,5 +1,8 @@
1
1
  #include <byebug.h>
2
2
 
3
+ /* Threads table class */
4
+ static VALUE cThreadsTable;
5
+
3
6
  static int
4
7
  t_tbl_mark_keyvalue(st_data_t key, st_data_t value, st_data_t tbl)
5
8
  {
@@ -29,8 +32,12 @@ t_tbl_free(void* data)
29
32
  xfree(t_tbl);
30
33
  }
31
34
 
35
+ /*
36
+ * Creates a numeric hash whose keys are the currently active threads and
37
+ * whose values are their associated contexts.
38
+ */
32
39
  VALUE
33
- threads_create(void)
40
+ create_threads_table(void)
34
41
  {
35
42
  threads_table_t *t_tbl;
36
43
 
@@ -39,42 +46,42 @@ threads_create(void)
39
46
  return Data_Wrap_Struct(cThreadsTable, t_tbl_mark, t_tbl_free, t_tbl);
40
47
  }
41
48
 
42
- void
43
- threads_clear(VALUE table)
44
- {
45
- threads_table_t *t_tbl;
46
-
47
- Data_Get_Struct(table, threads_table_t, t_tbl);
48
- st_clear(t_tbl->tbl);
49
- }
50
-
49
+ /*
50
+ * The condition to be in the thread's table is to be either running or
51
+ * sleeping, namely, to be Thread#alive?
52
+ */
51
53
  static int
52
54
  is_living_thread(VALUE thread)
53
55
  {
54
56
  return rb_funcall(thread, rb_intern("alive?"), 0) == Qtrue;
55
57
  }
56
58
 
59
+ /*
60
+ * Checks a single entry in the threads table.
61
+ *
62
+ * If it has no associated context or the key doesn't correspond to a living
63
+ * thread, the entry is removed from the thread's list.
64
+ */
57
65
  static int
58
- t_tbl_check_i(st_data_t key, st_data_t value, st_data_t dummy)
66
+ check_thread_i(st_data_t key, st_data_t value, st_data_t dummy)
59
67
  {
60
- VALUE thread;
61
-
62
68
  if (!value) return ST_DELETE;
63
69
 
64
- thread = (VALUE)key;
65
-
66
- if (!is_living_thread(thread)) return ST_DELETE;
70
+ if (!is_living_thread((VALUE)key)) return ST_DELETE;
67
71
 
68
72
  return ST_CONTINUE;
69
73
  }
70
74
 
75
+ /*
76
+ * Checks threads table for dead/finished threads.
77
+ */
71
78
  void
72
- check_thread_contexts(void)
79
+ check_threads_table(void)
73
80
  {
74
81
  threads_table_t *t_tbl;
75
82
 
76
83
  Data_Get_Struct(threads, threads_table_t, t_tbl);
77
- st_foreach(t_tbl->tbl, t_tbl_check_i, 0);
84
+ st_foreach(t_tbl->tbl, check_thread_i, 0);
78
85
  }
79
86
 
80
87
  void
@@ -111,3 +118,17 @@ halt_while_other_thread_is_active(debug_context_t *dc)
111
118
  else break;
112
119
  }
113
120
  }
121
+
122
+ /*
123
+ *
124
+ * Document-class: ThreadsTable
125
+ *
126
+ * == Sumary
127
+ *
128
+ * Hash table holding currently active threads and their associated contexts
129
+ */
130
+ void
131
+ Init_threads_table(VALUE mByebug)
132
+ {
133
+ cThreadsTable = rb_define_class_under(mByebug, "ThreadsTable", rb_cObject);
134
+ }
@@ -1,110 +1,2 @@
1
- require 'byebug/byebug'
2
- require 'byebug/version'
3
- require 'byebug/context'
4
- require 'byebug/interface'
5
- require 'byebug/processor'
6
- require 'byebug/setting'
7
- require 'byebug/remote'
8
- require 'stringio'
9
- require 'tracer'
10
- require 'linecache19'
11
-
12
- module Byebug
13
-
14
- # List of files byebug will ignore while debugging
15
- IGNORED_FILES = Dir.glob(File.expand_path('../**/*.rb', __FILE__))
16
-
17
- # Configuration file used for startup commands. Default value is .byebugrc
18
- INITFILE = '.byebugrc' unless defined?(INITFILE)
19
-
20
- # Stores program being debugged to make restarts possible
21
- PROG_SCRIPT = $0 unless defined?(PROG_SCRIPT)
22
-
23
- class << self
24
-
25
- # processor modules provide +handler+ object
26
- attr_accessor :handler
27
- Byebug.handler = CommandProcessor.new
28
-
29
- def source_reload
30
- hsh = 'SCRIPT_LINES__'
31
- Object.send(:remove_const, hsh) if Object.const_defined?(hsh)
32
- Object.const_set(hsh, {})
33
- end
34
-
35
- #
36
- # Add a new breakpoint
37
- #
38
- # @param [String] file
39
- # @param [Fixnum] line
40
- # @param [String] expr
41
- #
42
- def add_breakpoint(file, line, expr=nil)
43
- breakpoint = Breakpoint.new(file, line, expr)
44
- breakpoints << breakpoint
45
- breakpoint
46
- end
47
-
48
- #
49
- # Remove a breakpoint
50
- #
51
- # @param [integer] breakpoint number
52
- #
53
- def remove_breakpoint(id)
54
- breakpoints.reject! { |b| b.id == id }
55
- end
56
-
57
- def interface=(value)
58
- handler.interface = value
59
- end
60
-
61
- extend Forwardable
62
- def_delegators :"handler.interface", :print
63
-
64
- #
65
- # Runs normal byebug initialization scripts.
66
- #
67
- # Reads and executes the commands from init file (if any) in the current
68
- # working directory. This is only done if the current directory is
69
- # different from your home directory. Thus, you can have more than one init
70
- # file, one generic in your home directory, and another, specific to the
71
- # program you are debugging, in the directory where you invoke byebug.
72
- #
73
- def run_init_script(out = handler.interface)
74
- cwd_script = File.expand_path(File.join(".", INITFILE))
75
- run_script(cwd_script, out) if File.exist?(cwd_script)
76
-
77
- home_script = File.expand_path(File.join(ENV['HOME'].to_s, INITFILE))
78
- if File.exist?(home_script) and cwd_script != home_script
79
- run_script(home_script, out)
80
- end
81
- end
82
-
83
- #
84
- # Runs a script file
85
- #
86
- def run_script(file, out = handler.interface, verbose=false)
87
- interface = ScriptInterface.new(File.expand_path(file), out)
88
- processor = ControlCommandProcessor.new(interface)
89
- processor.process_commands(verbose)
90
- end
91
- end
92
- end
93
-
94
- class Exception
95
- attr_reader :__bb_file, :__bb_line, :__bb_binding, :__bb_context
96
- end
97
-
98
- module Kernel
99
- #
100
- # Enters byebug right before (or right after if _before_ is false) return
101
- # events occur. Before entering byebug the init script is read.
102
- #
103
- def byebug(steps_out = 1, before = true)
104
- Byebug.run_init_script(StringIO.new)
105
- Byebug.start
106
- Byebug.current_context.step_out(steps_out, before)
107
- end
108
-
109
- alias_method :debugger, :byebug
110
- end
1
+ require 'byebug/core'
2
+ require 'byebug/attacher'
@@ -0,0 +1,23 @@
1
+ module Byebug
2
+ # Stores program being debugged to make restarts possible
3
+ PROG_SCRIPT = $PROGRAM_NAME unless defined?(PROG_SCRIPT)
4
+ end
5
+
6
+ #
7
+ # Adds a `byebug` method to the Kernel module.
8
+ #
9
+ # Dropping a `byebug` call anywhere in your code, you get a debug prompt.
10
+ #
11
+ module Kernel
12
+ #
13
+ # Enters byebug right before (or right after if _before_ is false) return
14
+ # events occur. Before entering byebug the init script is read.
15
+ #
16
+ def byebug(steps_out = 1, before = true)
17
+ Byebug.start
18
+ Byebug.run_init_script(StringIO.new)
19
+ Byebug.current_context.step_out(steps_out, before)
20
+ end
21
+
22
+ alias_method :debugger, :byebug
23
+ end
@@ -0,0 +1,60 @@
1
+ module Byebug
2
+ #
3
+ # Implements breakpoints
4
+ #
5
+ class Breakpoint
6
+ #
7
+ # First breakpoint, in order of creation
8
+ #
9
+ def self.first
10
+ Byebug.breakpoints.first
11
+ end
12
+
13
+ #
14
+ # Last breakpoint, in order of creation
15
+ #
16
+ def self.last
17
+ Byebug.breakpoints.last
18
+ end
19
+
20
+ #
21
+ # Adds a new breakpoint
22
+ #
23
+ # @param [String] file
24
+ # @param [Fixnum] line
25
+ # @param [String] expr
26
+ #
27
+ def self.add(file, line, expr = nil)
28
+ breakpoint = Breakpoint.new(file, line, expr)
29
+ Byebug.breakpoints << breakpoint
30
+ breakpoint
31
+ end
32
+
33
+ #
34
+ # Removes a breakpoint
35
+ #
36
+ # @param [integer] breakpoint number
37
+ #
38
+ def self.remove(id)
39
+ Byebug.breakpoints.reject! { |b| b.id == id }
40
+ end
41
+
42
+ #
43
+ # True if there's no breakpoints
44
+ #
45
+ def self.none?
46
+ Byebug.breakpoints.empty?
47
+ end
48
+
49
+ #
50
+ # Prints all information associated to the breakpoint
51
+ #
52
+ def inspect
53
+ meths = %w(id pos source expr hit_condition hit_count hit_value enabled?)
54
+ values = meths.map do |field|
55
+ "#{field}: #{send(field)}"
56
+ end.join(', ')
57
+ "#<Byebug::Breakpoint #{values}>"
58
+ end
59
+ end
60
+ end