byebug 3.4.2 → 3.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 51062987a9c4c26728720d8416eb99354576fa00
4
- data.tar.gz: 2c85de15d46650690562bc84533ad254890efb18
3
+ metadata.gz: 1e311c958672db924c18ba6c50b079b8d0b02071
4
+ data.tar.gz: 9b5b874f7334cf8f2de778c6587d87717b79b780
5
5
  SHA512:
6
- metadata.gz: c6840103b5586afd62b89c16a28e512e73b4365734e4fc7e3c06f6e93f2563d7d9e255ef9bbe978b4557e9152c576e7800177a464f56ac93d5396a543ea18ba8
7
- data.tar.gz: bf2fee35bad9a06b866f6350435ad81b7807f6d7b8e42394de54b22e9f82bdbe2244d2a6b124b300b311b1072426e0587081e523ec4b9e11f16b75780b70110f
6
+ metadata.gz: 6804f3c19226009adecad6208753584bf3b9364e290c70b7be4e3ae92a8d7e300f4f6bb5a2aec029b7c3ac9df4ded55efa144ff7fff530364fec7d7058f42b10
7
+ data.tar.gz: 25f86abebed81ad2667b6fea393c8f4404d46d2556688fa900da8e5c5c45a223485eadab5ec0f599d9a62f978b597f379b625d182649ce7b95fa8cf0687980a9
@@ -1,3 +1,18 @@
1
+ # 3.5.0
2
+ - Bugfixes
3
+ * Fix #81, byebug's history does not mess with other programs that use
4
+ Readline too.
5
+ * Fix more issues with readline's history. Now it should always be properly
6
+ saved and inmediately available.
7
+ * Fix issue where user would not be notified when trying to debug a non
8
+ existent script.
9
+
10
+ - Improvements
11
+ * Complete rewrite of byebug's history.
12
+ * Complete rewrite of list command.
13
+ * Docs about stacktrace related commands (up, down, frame, backtrace).
14
+
15
+
1
16
  # 3.4.2
2
17
  * Fix #67, you can debug commands starting with `ruby` now, as in `byebug --
3
18
  ruby -Itest test/controllers/posts_controller_test.rb -n test_should_get_index`
data/GUIDE.md CHANGED
@@ -941,18 +941,18 @@ want to debug, add a call to `byebug` as was done without remote execution:
941
941
  ## Byebug Command Reference
942
942
 
943
943
  ### Command Syntax
944
- Usually a command is put on a single line. There is no limit on how long it can be.
945
- It starts with a command name, which is followed by arguments whose meaning depends
946
- on the command name. For example, the command `step` accepts an argument which is the
947
- number of times to step, as in `step 5`. You can also use the `step` command with no
948
- arguments. Some commands do not allow any arguments.
944
+ Usually a command is put on a single line. There is no limit on how long it can
945
+ be. It starts with a command name, which is followed by arguments whose meaning
946
+ depends on the command name. For example, the command `step` accepts an
947
+ argument which is the number of times to step, as in `step 5`. You can also use
948
+ the `step` command with no arguments. Some commands do not allow any arguments.
949
949
 
950
- Multiple commands can be put on a line by separating each with a semicolon `;`. You
951
- can disable the meaning of a semicolon to separate commands by escaping it with a
952
- backslash.
950
+ Multiple commands can be put on a line by separating each with a semicolon `;`.
951
+ You can disable the meaning of a semicolon to separate commands by escaping it
952
+ with a backslash.
953
953
 
954
- For example, if you have [autoeval]() set, which is the default, you might want to
955
- enter the following code to compute the 5th Fibonacci number.
954
+ For example, if you have [autoeval]() set, which is the default, you might want
955
+ to enter the following code to compute the 5th Fibonacci number.
956
956
 
957
957
  ```bash
958
958
  (byebug) fib1=0; fib2=1; 5.times {|temp| temp=fib1; fib1=fib2; fib2 += temp }
@@ -975,10 +975,11 @@ nil
975
975
  8
976
976
  ```
977
977
 
978
- You might also consider using the [irb]() or [pry]() commands and then you won't have
979
- to escape semicolons.
978
+ You might also consider using the [irb]() or [pry]() commands and then you
979
+ won't have to escape semicolons.
980
980
 
981
- A blank line as input (typing just `<RET>`) means to repeat the previous command.
981
+ A blank line as input (typing just `<RET>`) means to repeat the previous
982
+ command.
982
983
 
983
984
  Byebug uses readline, which handles line editing and retrieval of previous commands.
984
985
  Up arrow, for example, moves to the previous byebug command; down arrow moves to the
@@ -1309,7 +1310,7 @@ same as running `ps <object>.instance_methods(false)`.
1309
1310
  `<class-or-module>`. Basically this is the same as running
1310
1311
  `ps <class-or-module>.methods`.
1311
1312
 
1312
- ### Examining Program Source Files (`list`)
1313
+ ### Examining Program Source Files: list
1313
1314
 
1314
1315
  `byebug` can print parts of your script's source. When your script stops,
1315
1316
  `byebug` spontaneously lists the source code around the line where it stopped
@@ -1342,7 +1343,7 @@ equivalent to typing just `list`. This is more useful than listing the same
1342
1343
  lines again. An exception is made for an argument of `-`: that argument is
1343
1344
  preserved in repetition so that each repetition moves up in the source file.
1344
1345
 
1345
- ### Editing Source files (`edit`)
1346
+ ### Editing Source files: edit
1346
1347
 
1347
1348
  To edit a source file, use the `edit` command. The editor of your choice is invoked
1348
1349
  with the current line set to the active line in the program. Alternatively, you can
@@ -1370,3 +1371,75 @@ or in the `csh` shell,
1370
1371
  setenv EDITOR /usr/bin/vi
1371
1372
  byebug ...
1372
1373
  ```
1374
+
1375
+ ### The stack trace
1376
+
1377
+ When your script has stopped, one thing you'll probably want to know is where
1378
+ it stopped and some idea of how it got there.
1379
+
1380
+ Each time your script calls a method or enters a block, information about this
1381
+ action is saved. This information is what we call a _stack frame_ or just a
1382
+ _frame_. The set of all frames at a certain point in the program's execution is
1383
+ called the _stack trace_ or just the _stack_. Each frame contains a line number
1384
+ and the source-file name that the line refers to. If the frame is the beginning
1385
+ of a method it also contains the method name.
1386
+
1387
+ When your script is started, the stack has only one frame, that of the `main`
1388
+ method. This is called the _initial frame_ or the _outermost frame_. Each time
1389
+ a method is called, a new frame is added to the stack trace. Each time a method
1390
+ returns, the frame for that method invocation is removed. If a method is
1391
+ recursive, there can be many frames for the same method. The frame for the
1392
+ method in which execution is actually occurring is called the _innermost
1393
+ frame_. This is the most recently created of all the stack frames that still
1394
+ exist.
1395
+
1396
+ Every time the debugger stops, one entry in the stack is selected as the
1397
+ current frame. Many byebug commands refer implicitly to the selected block. In
1398
+ particular, whenever you ask Byebug to list lines without giving a line number
1399
+ or location the value is found in the selected frame. There are special
1400
+ commands to select whichever frame you're interested in, such as `up`, `down`
1401
+ and `frame`.
1402
+
1403
+ After switching frames, when you issue a `list` command without any position
1404
+ information, the position used is the location in the frame that you just
1405
+ switched between, rather than a location that got updated via a prior `list`
1406
+ command.
1407
+
1408
+ Byebug assigns numbers to all existing stack frames, starting with zero for the
1409
+ _innermost frame_, one for the frame that called it, and so on upward. These
1410
+ numbers do not really exist in your script, they are assigned by Byebug to give
1411
+ you a way of designating stack frames in commands.
1412
+
1413
+ ### Printing the Stack: `where` command
1414
+
1415
+ The command `where`, aliased to `bt` or `backtrace` prints the call stack., It
1416
+ shows one line per frame, for many frames, starting with the place that you are
1417
+ stopped at (frame zero), followed by its caller (frame one), and on up the
1418
+ stack. Each frame is numbered and can be referred to in the `frame` command.
1419
+ The position of the current frame is marked with `-->`.
1420
+
1421
+ The are some special frames generated for methods that are implemented in C.
1422
+ One such method is `each`. They are marked differently in the call stack to
1423
+ indicate that we cannot switch to those frames. This is because they have no
1424
+ source code in Ruby, so we can not debug them using Byebug.
1425
+
1426
+ ```bash
1427
+ (byebug) where
1428
+ --> #0 Object.gcd(a#Fixnum, b#Fixnum) at line gcd.rb:6
1429
+ #1 at line gcd.rb:19
1430
+ ```
1431
+
1432
+ ### Selecting a frame: `up`, `down` and `frame` commands
1433
+
1434
+ * `up <n>`: Move `n` frames up the stack, towards the outermost frame (higher
1435
+ frame numbers, frames that have existed longer). `n` defaults to one.
1436
+
1437
+ * `down <n>`: Move `n` frames down the stack, towards the _innermost frame_
1438
+ (lower frame numbers, frames that were created more recently). `n` defaults to
1439
+ one.
1440
+
1441
+ * `frame <n>`: Allows you to move to an arbitrary frame. `n` is the stack frame
1442
+ number or 0 if no frame number is given. `frame 0` will show the current and
1443
+ most recent stack frame. If a negative number is given, counting is from the
1444
+ other end of the stack frame, so `frame -1` shows the least-recent, outermost
1445
+ stack frame. Without an argument, `frame` prints the current stack frame.
@@ -5,6 +5,7 @@ module Byebug
5
5
  #
6
6
  def self.attach(steps_out, before)
7
7
  start
8
+ self.debugged_program = $PROGRAM_NAME
8
9
  run_init_script(StringIO.new)
9
10
  current_context.step_out(steps_out, before)
10
11
  end
@@ -41,7 +41,7 @@ module Byebug
41
41
 
42
42
  args.each do |pos|
43
43
  pos, err = get_int(pos, "#{is_enable} display", 1, @state.display.size)
44
- return errmsg(err) unless pos
44
+ return errmsg(err) unless err.nil?
45
45
 
46
46
  @state.display[pos - 1][0] = ('enable' == is_enable)
47
47
  end
@@ -45,7 +45,7 @@ module Byebug
45
45
  @state.frame_pos = abs_frame_pos
46
46
  @state.file = @state.context.frame_file @state.frame_pos
47
47
  @state.line = @state.context.frame_line @state.frame_pos
48
- @state.previous_line = nil
48
+ @state.prev_line = nil
49
49
  ListCommand.new(@state).execute
50
50
  end
51
51
 
@@ -8,17 +8,14 @@ module Byebug
8
8
  end
9
9
 
10
10
  def execute
11
- unless Setting[:autosave]
12
- return errmsg('Not currently saving history. ' \
13
- "Enable it with \"set autosave\"")
14
- end
11
+ history = @state.interface.history
15
12
 
16
13
  if @match[:num_cmds]
17
- size, err = get_int(@match[:num_cmds], 'history', 1, Setting[:histsize])
14
+ size, _ = get_int(@match[:num_cmds], 'history', 1, history.size)
18
15
  return errmsg(err) unless size
19
16
  end
20
17
 
21
- puts History.to_s(size || Setting[:histsize])
18
+ puts history.to_s(size)
22
19
  end
23
20
 
24
21
  class << self
@@ -11,17 +11,14 @@ module Byebug
11
11
  Byebug.source_reload if Setting[:autoreload]
12
12
 
13
13
  lines = get_lines(@state.file)
14
- unless lines
15
- errmsg "No sourcefile available for #{@state.file}\n"
16
- return @state.previous_line
17
- end
18
-
19
- b, e = set_line_range(Setting[:listsize], lines.size)
20
- return @state.previous_line if b < 0
14
+ return errmsg "No sourcefile available for #{@state.file}\n" unless lines
21
15
 
16
+ @match ||= match('list')
17
+ b, e = range(@match[2], lines.size)
18
+ return errmsg('Invalid line range') unless valid_range?(b, e, lines.size)
22
19
  display_lines(b, e, lines)
23
20
 
24
- @state.previous_line = b > lines.size ? @previous_line : b
21
+ @state.prev_line = b
25
22
  end
26
23
 
27
24
  class << self
@@ -42,57 +39,70 @@ module Byebug
42
39
 
43
40
  private
44
41
 
45
- ##
42
+ #
43
+ # Line range to be printed by `list`.
44
+ #
45
+ # If <input> is set, range is parsed from it.
46
+ #
47
+ # Otherwise it's automatically chosen.
48
+ #
49
+ def range(input, max_line)
50
+ size = [Setting[:listsize], max_line].min
51
+
52
+ return set_range(size, max_line) unless input
53
+
54
+ parse_range(input, size, max_line)
55
+ end
56
+
57
+ def valid_range?(first, last, max)
58
+ first <= last && (1..max).include?(first) && (1..max).include?(last)
59
+ end
60
+
61
+ #
46
62
  # Set line range to be printed by list
47
63
  #
48
- # @param listsize - number of lines to be printed
49
- # @param maxline - max line number that can be printed
64
+ # @param size - number of lines to be printed
65
+ # @param max_line - max line number that can be printed
50
66
  #
51
- def set_line_range(listsize, maxline)
52
- if !@match || !(@match[1] || @match[2])
53
- b = if @state.previous_line
54
- @state.previous_line + listsize
55
- else
56
- @state.line - (listsize / 2)
57
- end
58
- elsif @match[1] == '-'
59
- b = if @state.previous_line
60
- if @state.previous_line > 0
61
- @state.previous_line - listsize
62
- else
63
- @state.previous_line
64
- end
65
- else
66
- @state.line - (listsize / 2)
67
- end
68
- elsif @match[1] == '='
69
- @state.previous_line = nil
70
- b = @state.line - (listsize / 2)
67
+ # @return first line number to list
68
+ # @return last line number to list
69
+ #
70
+ def set_range(size, max_line)
71
+ first = amend(lower(size, @match[1] || '+'), size, max_line - size + 1)
72
+
73
+ [first, move(first, size - 1)]
74
+ end
75
+
76
+ def parse_range(input, size, max_line)
77
+ first, err = get_int(input.split(/[-,]/)[0], 'List', 1, max_line)
78
+ return [-1, -1] if err
79
+
80
+ if input.split(/[-,]/)[1]
81
+ last, err = get_int(input.split(/[-,]/)[1], 'List', 1, max_line)
82
+ return [-1, -1] unless last
83
+
84
+ last = amend(last, size, max_line)
71
85
  else
72
- b, e = @match[2].split(/[-,]/)
73
- if e
74
- b = b.to_i
75
- e = e.to_i
76
- else
77
- b = b.to_i - (listsize / 2)
78
- end
86
+ first -= (size / 2)
79
87
  end
80
88
 
81
- if b > maxline
82
- errmsg 'Invalid line range'
83
- return [-1, -1]
84
- end
89
+ [first, last || move(first, size - 1)]
90
+ end
85
91
 
86
- b = [1, b].max
87
- e ||= b + listsize - 1
92
+ def amend(line, size, max_line)
93
+ return 1 if line < 1
88
94
 
89
- if e > maxline
90
- e = maxline
91
- b = e - listsize + 1
92
- b = [1, b].max
93
- end
95
+ [max_line, line].min
96
+ end
97
+
98
+ def lower(size, direction = '+')
99
+ return @state.line - size / 2 if direction == '=' || !@state.prev_line
100
+
101
+ move(@state.prev_line, size, direction)
102
+ end
94
103
 
95
- [b, e]
104
+ def move(line, size, direction = '+')
105
+ line.send(direction, size)
96
106
  end
97
107
 
98
108
  #
@@ -1,10 +1,3 @@
1
- begin
2
- require 'pry'
3
- has_pry = true
4
- rescue LoadError
5
- has_pry = false
6
- end
7
-
8
1
  module Byebug
9
2
  #
10
3
  # Enter Pry from byebug's prompt
@@ -32,4 +25,4 @@ module Byebug
32
25
  end
33
26
  end
34
27
  end
35
- end if has_pry
28
+ end if defined?(Pry)
@@ -12,10 +12,6 @@ module Byebug
12
12
  def execute
13
13
  prog = Byebug.debugged_program
14
14
 
15
- unless File.exist?(File.expand_path(prog))
16
- return errmsg("Ruby program #{prog} doesn't exist")
17
- end
18
-
19
15
  if defined?(BYEBUG_SCRIPT)
20
16
  cmd = "#{BYEBUG_SCRIPT} #{prog}"
21
17
  else
@@ -23,8 +19,7 @@ module Byebug
23
19
  if File.executable?(prog)
24
20
  cmd = prog
25
21
  else
26
- puts "Ruby program #{prog} not executable... " \
27
- "We'll wrap it in a ruby call"
22
+ puts "Program #{prog} not executable... Wrapping it in a ruby call"
28
23
  cmd = "ruby -rbyebug -I#{$LOAD_PATH.join(' -I')} #{prog}"
29
24
  end
30
25
  end
@@ -1,19 +1,8 @@
1
1
  module Byebug
2
2
  #
3
- # Utilities for the save command.
3
+ # Default file where commands are saved
4
4
  #
5
- module SaveFunctions
6
- # Create a temporary file to write in if file is nil
7
- def open_save
8
- require 'tempfile'
9
- file = Tempfile.new('byebug-save')
10
- # We want close to not unlink, so redefine.
11
- def file.close
12
- @tmpfile.close if @tmpfile
13
- end
14
- file
15
- end
16
- end
5
+ RESTART_FILE = '.byebug-save' unless defined?(RESTART_FILE)
17
6
 
18
7
  #
19
8
  # Save current settings to use them in another debug session.
@@ -48,17 +37,14 @@ module Byebug
48
37
  end
49
38
 
50
39
  def execute
51
- if !@match[1]
52
- file = open_save
53
- else
54
- file = open(@match[1], 'w')
55
- end
40
+ file = open(@match[1] || RESTART_FILE, 'w')
41
+
56
42
  save_breakpoints(file)
57
43
  save_catchpoints(file)
58
44
  save_displays(file)
59
45
  save_settings(file)
46
+
60
47
  puts "Saved to '#{file.path}'"
61
- @state.interface.restart_file = file.path if @state && @state.interface
62
48
  file.close
63
49
  end
64
50
 
@@ -11,8 +11,8 @@ module Byebug
11
11
 
12
12
  def execute
13
13
  if @match[1]
14
- pos, err = get_int(@match[1], 'Undisplay')
15
- return errmsg(err) unless pos
14
+ pos, err = get_int(@match[1], 'Undisplay', 1, @state.display.size)
15
+ return errmsg(err) unless err.nil?
16
16
 
17
17
  unless @state.display[pos - 1]
18
18
  return errmsg("Display expression #{pos} is not defined.")
@@ -12,26 +12,25 @@ require 'tracer'
12
12
  require 'linecache19'
13
13
 
14
14
  module Byebug
15
+ #
15
16
  # List of files byebug will ignore while debugging
17
+ #
16
18
  IGNORED_FILES = Dir.glob(File.expand_path('../**/*.rb', __FILE__))
17
19
 
20
+ #
18
21
  # Configuration file used for startup commands. Default value is .byebugrc
19
- INITFILE = '.byebugrc' unless defined?(INITFILE)
22
+ #
23
+ INIT_FILE = '.byebugrc' unless defined?(INIT_FILE)
20
24
 
21
25
  class << self
22
- attr_accessor :handler
23
- attr_writer :debugged_program
26
+ attr_accessor :handler, :debugged_program
27
+
28
+ extend Forwardable
29
+ def_delegators :handler, :errmsg, :puts
24
30
  end
25
31
 
26
32
  Byebug.handler = CommandProcessor.new
27
33
 
28
- #
29
- # Program being debugged (or a default one if not set yet)
30
- #
31
- def self.debugged_program
32
- @debugged_program ||= $PROGRAM_NAME
33
- end
34
-
35
34
  def self.source_reload
36
35
  hsh = 'SCRIPT_LINES__'
37
36
  Object.send(:remove_const, hsh) if Object.const_defined?(hsh)
@@ -45,13 +44,6 @@ module Byebug
45
44
  handler.interface = value
46
45
  end
47
46
 
48
- #
49
- # Byebug's prints according to its handler's interface
50
- #
51
- def self.puts(message)
52
- handler.interface.puts(message)
53
- end
54
-
55
47
  #
56
48
  # Runs normal byebug initialization scripts.
57
49
  #
@@ -62,10 +54,10 @@ module Byebug
62
54
  # program you are debugging, in the directory where you invoke byebug.
63
55
  #
64
56
  def self.run_init_script(out = handler.interface)
65
- cwd_script = File.expand_path(File.join('.', INITFILE))
57
+ cwd_script = File.expand_path(File.join('.', INIT_FILE))
66
58
  run_script(cwd_script, out, true) if File.exist?(cwd_script)
67
59
 
68
- home_script = File.expand_path(File.join(ENV['HOME'].to_s, INITFILE))
60
+ home_script = File.expand_path(File.join(ENV['HOME'].to_s, INIT_FILE))
69
61
  if File.exist?(home_script) && cwd_script != home_script
70
62
  run_script(home_script, out, true)
71
63
  end