byebug 3.4.2 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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