byebug 4.0.4 → 4.0.5

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: 0d5196fdd3dc5f4325d6a7dc03edc403c3f54adc
4
- data.tar.gz: b99153ca69aa352475c74692bd4cf0092b7fafa6
3
+ metadata.gz: 86c24793f077ce32dceea91c8bde07dce922a274
4
+ data.tar.gz: f166af0f5a9b01024978ebf2ebb5d9b7103d8a7b
5
5
  SHA512:
6
- metadata.gz: aab4f3f7ed3f5da8c08b024b8b616fbbb67020cf652e7d9474b83fef9b0abeacee16a19016fd47fb3c4117071a4b1e9d6b0f491c3862626ea58351973bc06912
7
- data.tar.gz: 760d9cd65c9b2a7afad5c7f47d079dc84a1e3b0d0af754099998513a3d6a2ff835fcc661bdab3d0d8100cb0884d0e8d03a902d73763266e1761c7473fe733e09
6
+ metadata.gz: 19d9a87a1f69496bdb00574437c3913b167d2da92d1b1b35c64412a70adfc8309f2bc78bdac5233bea310bd46543af2966b762453318e450ff6d73092626b16d
7
+ data.tar.gz: cfe46396685e6cec68816f38b70183317cf7585e1bbec594de6e670962151a5cd1eb4e1eb2483c0aafe43e94d741589c595c8d8e5a4cecb5124200b617c04b05
@@ -1,3 +1,9 @@
1
+ ## 4.0.5 - 2015-04-02
2
+ ### Fixed
3
+ * #131
4
+ * Thread commands help format should be consistent with the rest of the help
5
+ system now.
6
+
1
7
  ## 4.0.4 - 2015-03-27
2
8
  ### Fixed
3
9
  * #127
@@ -17,6 +17,11 @@ API and a lot of bugs have been recently corrected. Without this fixes,
17
17
  `byebug` will fail to work properly, so make sure you have always the last
18
18
  patch level releases of Ruby installed.
19
19
 
20
+ Also, if you are developing on linux, make sure you have the GNU indent utility
21
+ installed for automatic check of code style in C files. If you're developing in
22
+ MacOSX, just make sure you keep a consistent style if you edit the C-extension
23
+ files. Travis CI will do the automatic check anyways.
24
+
20
25
 
21
26
  ## Getting started
22
27
 
data/GUIDE.md CHANGED
@@ -223,28 +223,28 @@ the output so that it nicely fits our screen.
223
223
  (byebug) set width 80
224
224
  Maximum width of byebug's output is 80
225
225
  (byebug) ps private_methods
226
- Array default_src_encoding open sleep
227
- Complex define_method p spawn
228
- Digest eval pp sprintf
229
- Float exec print srand
230
- Hash exit printf syscall
231
- Integer exit! private system
232
- Pathname fail proc test
233
- Rational fork public throw
234
- String format putc timeout
235
- URI gem_original_require puts trace_var
236
- __callee__ gets raise trap
226
+ Array default_src_encoding open sleep
227
+ Complex define_method p spawn
228
+ Digest eval pp sprintf
229
+ Float exec print srand
230
+ Hash exit printf syscall
231
+ Integer exit! private system
232
+ Pathname fail proc test
233
+ Rational fork public throw
234
+ String format putc timeout
235
+ URI gem_original_require puts trace_var
236
+ __callee__ gets raise trap
237
237
  __dir__ global_variables rand untrace_var
238
- __method__ include readline using
239
- ` initialize readlines warn
240
- abort initialize_clone require y
241
- at_exit initialize_copy require_relative
242
- autoload initialize_dup respond_to_missing?
243
- autoload? iterator? rubygems_require
244
- binding lambda select
245
- block_given? load set_trace_func
246
- caller local_variables singleton_method_added
247
- caller_locations loop singleton_method_removed
238
+ __method__ include readline using
239
+ ` initialize readlines warn
240
+ abort initialize_clone require y
241
+ at_exit initialize_copy require_relative
242
+ autoload initialize_dup respond_to_missing?
243
+ autoload? iterator? rubygems_require
244
+ binding lambda select
245
+ block_given? load set_trace_func
246
+ caller local_variables singleton_method_added
247
+ caller_locations loop singleton_method_removed
248
248
  catch method_missing singleton_method_undefined
249
249
  (byebug)
250
250
  ```
@@ -500,7 +500,7 @@ Run options: --seed 31679
500
500
 
501
501
  [2, 11] in test_triangle.rb
502
502
  2: require_relative 'triangle.rb'
503
- 3:
503
+ 3:
504
504
  4: class TestTriangle < Minitest::Test
505
505
  5: def test_basic
506
506
  6: byebug
@@ -1035,7 +1035,7 @@ run a sleeping thread.
1035
1035
 
1036
1036
  Now we can investigate the problem in the employer's side:
1037
1037
 
1038
- ``bash
1038
+ ```bash
1039
1039
  (byebug) s
1040
1040
  [30, 39] in /path/to/company.rb
1041
1041
  30:
@@ -1088,7 +1088,7 @@ Now we can investigate the problem in the employer's side:
1088
1088
  39: show_off(@results.pop)
1089
1089
  40: end
1090
1090
  (byebug)
1091
- ``
1091
+ ```
1092
1092
 
1093
1093
  Now we can see the problem, the `@results` variable is always empty! The
1094
1094
  employee forgot to leave the results in his manager's deck. We fix it by
@@ -1193,14 +1193,14 @@ get a line trace, `tracer` is most likely faster than `byebug`.
1193
1193
  ```bash
1194
1194
  $ time byebug --trace --no-stop hanoi.rb > /dev/null
1195
1195
 
1196
- real 0m0.743s
1197
- user 0m0.668s
1198
- sys 0m0.068s
1196
+ real 0m0.743s
1197
+ user 0m0.668s
1198
+ sys 0m0.068s
1199
1199
  $ time ruby -rtracer hanoi.rb > /dev/null
1200
1200
 
1201
- real 0m0.077s
1202
- user 0m0.072s
1203
- sys 0m0.004s
1201
+ real 0m0.077s
1202
+ user 0m0.072s
1203
+ sys 0m0.004s
1204
1204
  ```
1205
1205
 
1206
1206
  ### Byebug default options
@@ -1620,19 +1620,40 @@ will just call pretty-print.
1620
1620
  :pretty_inspect,
1621
1621
  :byebug]
1622
1622
  (byebug) putl Kernel.instance_methods
1623
- nil? <=> tainted? frozen? private_methods remove_instance_variable public_send define_singleton_method byebug
1624
- === class untaint to_s public_methods instance_of? respond_to? object_id
1625
- =~ singleton_class untrust inspect instance_variables kind_of? extend to_enum
1626
- !~ clone untrusted? methods instance_variable_get is_a? display enum_for
1627
- eql? dup trust singleton_methods instance_variable_set tap method gem
1628
- hash taint freeze protected_methods instance_variable_defined? send public_method pretty_inspect
1623
+ nil? trust is_a?
1624
+ === freeze tap
1625
+ =~ frozen? send
1626
+ !~ to_s public_send
1627
+ eql? inspect respond_to?
1628
+ hash methods extend
1629
+ <=> singleton_methods display
1630
+ class protected_methods method
1631
+ singleton_class private_methods public_method
1632
+ clone public_methods singleton_method
1633
+ dup instance_variables define_singleton_method
1634
+ itself instance_variable_get object_id
1635
+ taint instance_variable_set to_enum
1636
+ tainted? instance_variable_defined? enum_for
1637
+ untaint remove_instance_variable gem
1638
+ untrust instance_of? pretty_inspect
1639
+ untrusted? kind_of?
1629
1640
  (byebug) ps Kernel.instance_methods
1630
- !~ clone extend instance_of? kind_of? private_methods respond_to? tap untrusted?
1631
- <=> define_singleton_method freeze instance_variable_defined? method protected_methods send to_enum
1632
- === display frozen? instance_variable_get methods public_method singleton_class to_s
1633
- =~ dup gem instance_variable_set nil? public_methods singleton_methods trust
1634
- byebug enum_for hash instance_variables object_id public_send taint untaint
1635
- class eql? inspect is_a? pretty_inspect remove_instance_variable tainted? untrust
1641
+ !~ instance_of? public_send
1642
+ <=> instance_variable_defined? remove_instance_variable
1643
+ === instance_variable_get respond_to?
1644
+ =~ instance_variable_set send
1645
+ class instance_variables singleton_class
1646
+ clone is_a? singleton_method
1647
+ define_singleton_method itself singleton_methods
1648
+ display kind_of? taint
1649
+ dup method tainted?
1650
+ enum_for methods tap
1651
+ eql? nil? to_enum
1652
+ extend object_id to_s
1653
+ freeze pretty_inspect trust
1654
+ frozen? private_methods untaint
1655
+ gem protected_methods untrust
1656
+ hash public_method untrusted?
1636
1657
  ```
1637
1658
 
1638
1659
  Finally, if you need more advanced functionality from REPL's, you can enter
@@ -7,12 +7,12 @@ module Byebug
7
7
  # events occur. Before entering byebug the init script is read.
8
8
  #
9
9
  def self.attach
10
- return errmsg('Byebug already started. Ignoring `byebug` call.') if started?
10
+ unless started?
11
+ self.mode = :attached
11
12
 
12
- setup_cmd_line_args
13
-
14
- start
15
- run_init_script
13
+ start
14
+ run_init_script
15
+ end
16
16
 
17
17
  current_context.step_out(2, true)
18
18
  end
@@ -15,15 +15,14 @@ module Byebug
15
15
  def execute
16
16
  return puts(self.class.help) unless @match[1]
17
17
 
18
- brkpt = line_breakpoint(@match[1]) || method_breakpoint(@match[1])
18
+ b = line_breakpoint(@match[1]) || method_breakpoint(@match[1])
19
+
19
20
  if syntax_valid?(@match[2])
20
- return puts(
21
- pr('break.created', id: brkpt.id, file: brkpt.source, line: brkpt.pos)
22
- )
21
+ return puts(pr('break.created', id: b.id, file: b.source, line: b.pos))
23
22
  end
24
23
 
25
24
  errmsg(pr('break.errors.expression', expr: @match[2]))
26
- brkpt.enabled = false
25
+ b.enabled = false
27
26
  rescue => e
28
27
  errmsg(e.message)
29
28
  end
@@ -7,8 +7,6 @@ module Byebug
7
7
  # Enables the user to catch unhandled assertion when they happen.
8
8
  #
9
9
  class CatchCommand < Command
10
- self.allow_in_control = false
11
-
12
10
  def regexp
13
11
  /^\s* cat(?:ch)? (?:\s+(\S+))? (?:\s+(off))? \s*$/x
14
12
  end
@@ -21,7 +21,7 @@ module Byebug
21
21
  return nil
22
22
  end
23
23
 
24
- @match[1].split(/[ \t]+/).each do |number|
24
+ @match[1].split(/ +/).each do |number|
25
25
  pos, err = get_int(number, 'Delete', 1)
26
26
 
27
27
  return errmsg(err) unless pos
@@ -76,7 +76,7 @@ module Byebug
76
76
 
77
77
  return errmsg(pr('toggle.errors.syntax', toggle: cmd)) unless @match[2]
78
78
 
79
- args = @match[2].split(/[ \t]+/)
79
+ args = @match[2].split(/ +/)
80
80
  param = args.shift
81
81
  subcmd = Command.find(Subcommands, param)
82
82
  if subcmd
@@ -176,7 +176,7 @@ module Byebug
176
176
  def execute
177
177
  return puts(self.class.help) unless @match[1]
178
178
 
179
- args = @match[1].split(/[ \t]+/)
179
+ args = @match[1].split(/ +/)
180
180
  param = args.shift
181
181
  subcmd = Command.find(Subcommands, param)
182
182
  return errmsg "Unknown info command #{param}\n" unless subcmd
@@ -0,0 +1,145 @@
1
+ require 'byebug/command'
2
+
3
+ module Byebug
4
+ #
5
+ # Manipulation of Ruby threads
6
+ #
7
+ class ThreadCommand < Command
8
+ Subcommands = [
9
+ ['current', 1, 'Shows current thread'],
10
+ ['list', 1, 'Lists all threads'],
11
+ ['resume', 1, 'Resumes execution of specified thread number'],
12
+ ['stop', 2, 'Stops execution of specified thread number'],
13
+ ['switch', 2, 'Switches execution to specified thread']
14
+ ].map do |name, min, help|
15
+ Subcmd.new(name, min, help)
16
+ end
17
+
18
+ def regexp
19
+ /^\s* th(?:read)? (?:\s+ (.+))? \s*$/x
20
+ end
21
+
22
+ def execute
23
+ return puts(self.class.help) unless @match[1]
24
+
25
+ name, thnum = @match[1].split(/ +/)[0..1]
26
+ subcmd = Command.find(Subcommands, name)
27
+ return errmsg("Unknown thread command '#{name}'\n") unless subcmd
28
+
29
+ send("thread_#{subcmd.name}", thnum)
30
+ end
31
+
32
+ class << self
33
+ def names
34
+ %w(thread)
35
+ end
36
+
37
+ def description
38
+ prettify <<-EOD
39
+ Commands to manipulate threads.
40
+ EOD
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def thread_list(thnum)
47
+ return errmsg("thread list doesn't need params") unless thnum.nil?
48
+
49
+ contexts = Byebug.contexts.sort_by(&:thnum)
50
+
51
+ thread_list = prc('thread.context', contexts) do |context, _|
52
+ thread_arguments(context)
53
+ end
54
+
55
+ print(thread_list)
56
+ end
57
+
58
+ def thread_current(thnum)
59
+ return errmsg("thread current doesn't need params") unless thnum.nil?
60
+
61
+ display_context(@state.context)
62
+ end
63
+
64
+ def thread_stop(thnum)
65
+ ctx, err = parse_thread_num_for_cmd('thread stop', thnum)
66
+ return errmsg(err) if err
67
+
68
+ ctx.suspend
69
+ display_context(ctx)
70
+ end
71
+
72
+ def thread_resume(thnum)
73
+ ctx, err = parse_thread_num_for_cmd('thread resume', thnum)
74
+ return errmsg(err) if err
75
+ return errmsg(pr('thread.errors.already_running')) unless ctx.suspended?
76
+
77
+ ctx.resume
78
+ display_context(ctx)
79
+ end
80
+
81
+ def thread_switch(thnum)
82
+ ctx, err = parse_thread_num_for_cmd('thread switch', thnum)
83
+ return errmsg(err) if err
84
+
85
+ display_context(ctx)
86
+
87
+ ctx.switch
88
+ @state.proceed
89
+ end
90
+
91
+ def display_context(context)
92
+ puts pr('thread.context', thread_arguments(context))
93
+ end
94
+
95
+ def thread_arguments(context)
96
+ status_flag = if context.suspended?
97
+ '$'
98
+ else
99
+ context.thread == Thread.current ? '+' : ' '
100
+ end
101
+ debug_flag = context.ignored? ? '!' : ' '
102
+
103
+ if context == Byebug.current_context
104
+ file_line = "#{@state.file}:#{@state.line}"
105
+ else
106
+ backtrace = context.thread.backtrace_locations
107
+ if backtrace && backtrace[0]
108
+ file_line = "#{backtrace[0].path}:#{backtrace[0].lineno}"
109
+ end
110
+ end
111
+
112
+ {
113
+ status_flag: status_flag,
114
+ debug_flag: debug_flag,
115
+ id: context.thnum,
116
+ thread: context.thread.inspect,
117
+ file_line: file_line || ''
118
+ }
119
+ end
120
+
121
+ def parse_thread_num(subcmd, arg)
122
+ thnum, err = get_int(arg, subcmd, 1)
123
+ return [nil, err] unless thnum
124
+
125
+ Byebug.contexts.find { |c| c.thnum == thnum }
126
+ end
127
+
128
+ def parse_thread_num_for_cmd(subcmd, arg)
129
+ c, err = parse_thread_num(subcmd, arg)
130
+
131
+ case
132
+ when err
133
+ [c, err]
134
+ when c.nil?
135
+ [nil, pr('thread.errors.no_thread')]
136
+ when @state.context == c
137
+ [c, pr('thread.errors.current_thread')]
138
+ when c.ignored?
139
+ [c, pr('thread.errors.wrong_action', subcmd: subcmd, arg: arg)]
140
+ else
141
+ [c, nil]
142
+ end
143
+ end
144
+ end
145
+ end
@@ -14,7 +14,7 @@ module Byebug
14
14
  def execute
15
15
  var = @match[1]
16
16
  if global_variables.include?(:"#{var}")
17
- eval("untrace_var(:\"#{var}\")")
17
+ untrace_var(:"#{var}")
18
18
  puts pr('trace.messages.undo', var: var)
19
19
  else
20
20
  errmsg pr('trace.errors.not_global', var: var)
@@ -29,6 +29,9 @@ module Byebug
29
29
  self.class.ignored_files.include?(path)
30
30
  end
31
31
 
32
+ #
33
+ # Context's stack size
34
+ #
32
35
  def stack_size
33
36
  return 0 unless backtrace
34
37
 
@@ -10,12 +10,6 @@ require 'byebug/printers/plain'
10
10
  module Byebug
11
11
  extend self
12
12
 
13
- class NoScript < StandardError
14
- end
15
-
16
- class NonExistentScript < StandardError
17
- end
18
-
19
13
  #
20
14
  # Configuration file used for startup commands. Default value is .byebugrc
21
15
  #
@@ -27,15 +21,15 @@ module Byebug
27
21
  attr_accessor :handler
28
22
  self.handler = CommandProcessor.new
29
23
 
24
+ extend Forwardable
25
+ def_delegators :handler, :errmsg, :puts
26
+
30
27
  #
31
28
  # Main debugger's printer
32
29
  #
33
30
  attr_accessor :printer
34
31
  self.printer = Printers::Plain.new
35
32
 
36
- extend Forwardable
37
- def_delegators :handler, :errmsg, :puts
38
-
39
33
  #
40
34
  # Running mode of the debugger. Can be either:
41
35
  #
@@ -61,26 +55,6 @@ module Byebug
61
55
  run_script(cwd_rc) if File.exist?(cwd_rc) && cwd_rc != home_rc
62
56
  end
63
57
 
64
- #
65
- # Extracts debugged program from command line args
66
- #
67
- def setup_cmd_line_args
68
- unless $PROGRAM_NAME.include?('bin/byebug')
69
- self.mode = :attached
70
- return
71
- end
72
-
73
- self.mode = :standalone
74
-
75
- fail(NoScript, 'You must specify a program to debug...') if $ARGV.empty?
76
-
77
- program = which($ARGV.shift)
78
- program = which($ARGV.shift) if program == which('ruby')
79
- fail(NonExistentScript, "The script doesn't exist") unless program
80
-
81
- $PROGRAM_NAME = program
82
- end
83
-
84
58
  private
85
59
 
86
60
  #
@@ -91,24 +65,6 @@ module Byebug
91
65
  processor = ControlCommandProcessor.new(interface)
92
66
  processor.process_commands
93
67
  end
94
-
95
- #
96
- # Cross-platform way of finding an executable in the $PATH.
97
- # Borrowed from: http://stackoverflow.com/questions/2108727
98
- #
99
- def which(cmd)
100
- return File.expand_path(cmd) if File.exist?(cmd)
101
-
102
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
103
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
104
- exts.each do |ext|
105
- exe = File.join(path, "#{cmd}#{ext}")
106
- return exe if File.executable?(exe) && !File.directory?(exe)
107
- end
108
- end
109
-
110
- nil
111
- end
112
68
  end
113
69
 
114
70
  #
@@ -88,12 +88,31 @@ module Byebug
88
88
  end
89
89
 
90
90
  #
91
- # Returns true if code is syntactically correct for Ruby.
91
+ # Returns true if code is syntactically correct for Ruby
92
92
  #
93
93
  def syntax_valid?(code)
94
- eval("BEGIN {return true}\n#{code}", nil, '', 0)
95
- rescue SyntaxError
96
- false
94
+ return true unless code
95
+
96
+ without_stderr do
97
+ begin
98
+ RubyVM::InstructionSequence.compile(code)
99
+ true
100
+ rescue SyntaxError
101
+ false
102
+ end
103
+ end
104
+ end
105
+
106
+ #
107
+ # Temporarily disable output to $stderr
108
+ #
109
+ def without_stderr
110
+ stderr = $stderr
111
+ $stderr.reopen(IO::NULL)
112
+
113
+ yield
114
+ ensure
115
+ $stderr.reopen(stderr)
97
116
  end
98
117
 
99
118
  #
@@ -1,12 +1,28 @@
1
1
  require 'optparse'
2
2
  require 'English'
3
3
  require 'byebug/core'
4
+ require 'byebug/helper'
4
5
 
5
6
  module Byebug
6
7
  #
7
8
  # Responsible for starting the debugger when started from the command line.
8
9
  #
9
10
  class Runner
11
+ #
12
+ # Error class signaling absence of a script to debug
13
+ #
14
+ class NoScript < StandardError; end
15
+
16
+ #
17
+ # Error class signaling a non existent script to debug
18
+ #
19
+ class NonExistentScript < StandardError; end
20
+
21
+ #
22
+ # Error class signaling a script with invalid Ruby syntax
23
+ #
24
+ class InvalidScript < StandardError; end
25
+
10
26
  #
11
27
  # Special working modes that don't actually start the debugger.
12
28
  #
@@ -36,27 +52,6 @@ module Byebug
36
52
  EOB
37
53
  end
38
54
 
39
- #
40
- # Debugs a script only if syntax checks okay.
41
- #
42
- def debug_program
43
- check_syntax($PROGRAM_NAME)
44
-
45
- status = Byebug.debug_load($PROGRAM_NAME, @stop)
46
- Byebug.puts "#{status}\n#{status.backtrace}" if status
47
- end
48
-
49
- #
50
- # Exits and outputs error message if syntax of the given program is invalid.
51
- #
52
- def check_syntax(program_name)
53
- output = `ruby -c "#{program_name}" 2>&1`
54
- return unless $CHILD_STATUS.exitstatus != 0
55
-
56
- Byebug.errmsg(output)
57
- exit($CHILD_STATUS.exitstatus)
58
- end
59
-
60
55
  #
61
56
  # Starts byebug to debug a program
62
57
  #
@@ -78,7 +73,7 @@ module Byebug
78
73
  return
79
74
  end
80
75
 
81
- Byebug.setup_cmd_line_args
76
+ setup_cmd_line_args
82
77
 
83
78
  loop do
84
79
  debug_program
@@ -90,6 +85,11 @@ module Byebug
90
85
  end
91
86
  end
92
87
 
88
+ private
89
+
90
+ #
91
+ # Processes options passed from the command line
92
+ #
93
93
  def prepare_options
94
94
  OptionParser.new(banner, 25) do |opts|
95
95
  opts.banner = banner
@@ -139,5 +139,50 @@ module Byebug
139
139
  end
140
140
  end
141
141
  end
142
+
143
+ #
144
+ # Extracts debugged program from command line args
145
+ #
146
+ def setup_cmd_line_args
147
+ Byebug.mode = :standalone
148
+
149
+ fail(NoScript, 'You must specify a program to debug...') if $ARGV.empty?
150
+
151
+ program = which($ARGV.shift)
152
+ program = which($ARGV.shift) if program == which('ruby')
153
+ fail(NonExistentScript, "The script doesn't exist") unless program
154
+
155
+ $PROGRAM_NAME = program
156
+ end
157
+
158
+ include ParseFunctions
159
+ #
160
+ # Debugs a script only if syntax checks okay.
161
+ #
162
+ def debug_program
163
+ ok = syntax_valid?(File.read($PROGRAM_NAME))
164
+ fail(InvalidScript, 'The script has incorrect syntax') unless ok
165
+
166
+ error = Byebug.debug_load($PROGRAM_NAME, @stop)
167
+ Byebug.puts "#{status}\n#{status.backtrace}" if error
168
+ end
169
+
170
+ #
171
+ # Cross-platform way of finding an executable in the $PATH.
172
+ # Borrowed from: http://stackoverflow.com/questions/2108727
173
+ #
174
+ def which(cmd)
175
+ return File.expand_path(cmd) if File.exist?(cmd)
176
+
177
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
178
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
179
+ exts.each do |ext|
180
+ exe = File.join(path, "#{cmd}#{ext}")
181
+ return exe if File.executable?(exe) && !File.directory?(exe)
182
+ end
183
+ end
184
+
185
+ nil
186
+ end
142
187
  end
143
188
  end
@@ -1,3 +1,3 @@
1
1
  module Byebug
2
- VERSION = '4.0.4'
2
+ VERSION = '4.0.5'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: byebug
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.4
4
+ version: 4.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Rodriguez
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-03-27 00:00:00.000000000 Z
13
+ date: 2015-04-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: columnize
@@ -102,7 +102,7 @@ files:
102
102
  - lib/byebug/commands/show.rb
103
103
  - lib/byebug/commands/source.rb
104
104
  - lib/byebug/commands/stepping.rb
105
- - lib/byebug/commands/threads.rb
105
+ - lib/byebug/commands/thread.rb
106
106
  - lib/byebug/commands/tracevar.rb
107
107
  - lib/byebug/commands/undisplay.rb
108
108
  - lib/byebug/commands/untracevar.rb
@@ -165,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
165
  version: '0'
166
166
  requirements: []
167
167
  rubyforge_project:
168
- rubygems_version: 2.4.6
168
+ rubygems_version: 2.4.5
169
169
  signing_key:
170
170
  specification_version: 4
171
171
  summary: Ruby 2.0 fast debugger - base + CLI
@@ -1,237 +0,0 @@
1
- require 'byebug/command'
2
-
3
- #
4
- # TODO: Implement thread commands as a single command with subcommands, just
5
- # like `info`, `var`, `enable` and `disable`. This allows consistent help
6
- # format and we can go back to showing help for a single command in the `help`
7
- # command.
8
- #
9
- module Byebug
10
- #
11
- # Utilities to assist commands related to threads.
12
- #
13
- module ThreadFunctions
14
- def display_context(context, should_show_top_frame = true)
15
- puts pr('thread.context',
16
- thread_arguments(context, should_show_top_frame))
17
- end
18
-
19
- def thread_arguments(context, should_show_top_frame = true)
20
- status_flag = if context.suspended?
21
- '$'
22
- else
23
- context.thread == Thread.current ? '+' : ' '
24
- end
25
- debug_flag = context.ignored? ? '!' : ' '
26
-
27
- if should_show_top_frame
28
- if context == Byebug.current_context
29
- file_line = "#{@state.file}:#{@state.line}"
30
- else
31
- backtrace = context.thread.backtrace_locations
32
- if backtrace && backtrace[0]
33
- file_line = "#{backtrace[0].path}:#{backtrace[0].lineno}"
34
- end
35
- end
36
- end
37
- {
38
- status_flag: status_flag,
39
- debug_flag: debug_flag,
40
- id: context.thnum,
41
- thread: context.thread.inspect,
42
- file_line: file_line || ''
43
- }
44
- end
45
-
46
- def parse_thread_num(subcmd, arg)
47
- thnum, err = get_int(arg, subcmd, 1)
48
- return [nil, err] unless thnum
49
-
50
- Byebug.contexts.find { |c| c.thnum == thnum }
51
- end
52
-
53
- def parse_thread_num_for_cmd(subcmd, arg)
54
- c, err = parse_thread_num(subcmd, arg)
55
-
56
- case
57
- when err
58
- [c, err]
59
- when c.nil?
60
- [nil, pr('thread.errors.no_thread')]
61
- when @state.context == c
62
- [c, pr('thread.errors.current_thread')]
63
- when c.ignored?
64
- [c, pr('thread.errors.wrong_action', subcmd: subcmd, arg: arg)]
65
- else
66
- [c, nil]
67
- end
68
- end
69
- end
70
-
71
- #
72
- # List current threads.
73
- #
74
- class ThreadListCommand < Command
75
- include ThreadFunctions
76
-
77
- self.allow_in_control = true
78
-
79
- def regexp
80
- /^\s* th(?:read)? \s+ l(?:ist)? \s*$/x
81
- end
82
-
83
- def execute
84
- contexts = Byebug.contexts.sort_by(&:thnum)
85
-
86
- thread_list = prc('thread.context', contexts) do |context, _|
87
- thread_arguments(context)
88
- end
89
-
90
- print(thread_list)
91
- end
92
-
93
- class << self
94
- def names
95
- %w(thread)
96
- end
97
-
98
- def description
99
- prettify <<-EOD
100
- th[read] l[ist] Lists all threads.
101
- EOD
102
- end
103
- end
104
- end
105
-
106
- #
107
- # Show current thread.
108
- #
109
- class ThreadCurrentCommand < Command
110
- include ThreadFunctions
111
-
112
- def regexp
113
- /^\s* th(?:read)? \s+ (?:cur(?:rent)?)? \s*$/x
114
- end
115
-
116
- def execute
117
- display_context(@state.context)
118
- end
119
-
120
- class << self
121
- def names
122
- %w(thread)
123
- end
124
-
125
- def description
126
- prettify <<-EOD
127
- th[read] cur[rent] Shows current thread.
128
- EOD
129
- end
130
- end
131
- end
132
-
133
- #
134
- # Stop execution of a thread.
135
- #
136
- class ThreadStopCommand < Command
137
- include ThreadFunctions
138
-
139
- self.allow_in_control = true
140
- self.allow_in_post_mortem = false
141
-
142
- def regexp
143
- /^\s* th(?:read)? \s+ stop \s* (\S*) \s*$/x
144
- end
145
-
146
- def execute
147
- c, err = parse_thread_num_for_cmd('thread stop', @match[1])
148
- return errmsg(err) if err
149
-
150
- c.suspend
151
- display_context(c)
152
- end
153
-
154
- class << self
155
- def names
156
- %w(thread)
157
- end
158
-
159
- def description
160
- prettify <<-EOD
161
- th[read] stop <n> Stops thread <n>.
162
- EOD
163
- end
164
- end
165
- end
166
-
167
- #
168
- # Resume execution of a thread.
169
- #
170
- class ThreadResumeCommand < Command
171
- include ThreadFunctions
172
-
173
- self.allow_in_control = true
174
- self.allow_in_post_mortem = false
175
-
176
- def regexp
177
- /^\s* th(?:read)? \s+ resume \s* (\S*) \s*$/x
178
- end
179
-
180
- def execute
181
- c, err = parse_thread_num_for_cmd('thread resume', @match[1])
182
- return errmsg(err) if err
183
- return errmsg pr('thread.errors.already_running') unless c.suspended?
184
-
185
- c.resume
186
- display_context(c)
187
- end
188
-
189
- class << self
190
- def names
191
- %w(thread)
192
- end
193
-
194
- def description
195
- prettify <<-EOD
196
- th[read] resume <n> Resumes thread <n>.
197
- EOD
198
- end
199
- end
200
- end
201
-
202
- #
203
- # Switch execution to a different thread.
204
- #
205
- class ThreadSwitchCommand < Command
206
- include ThreadFunctions
207
-
208
- self.allow_in_control = true
209
- self.allow_in_post_mortem = false
210
-
211
- def regexp
212
- /^\s* th(?:read)? \s+ sw(?:itch)? (?:\s+(\S+))? \s*$/x
213
- end
214
-
215
- def execute
216
- c, err = parse_thread_num_for_cmd('thread switch', @match[1])
217
- return errmsg(err) if err
218
-
219
- display_context(c)
220
-
221
- c.switch
222
- @state.proceed
223
- end
224
-
225
- class << self
226
- def names
227
- %w(thread)
228
- end
229
-
230
- def description
231
- prettify <<-EOD
232
- th[read] sw[itch] <n> Switches thread context to <n>.
233
- EOD
234
- end
235
- end
236
- end
237
- end