debug 1.4.0 → 1.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +210 -6
  3. data/Gemfile +2 -0
  4. data/LICENSE.txt +0 -0
  5. data/README.md +161 -85
  6. data/Rakefile +33 -10
  7. data/TODO.md +8 -8
  8. data/debug.gemspec +9 -7
  9. data/exe/rdbg +23 -4
  10. data/ext/debug/debug.c +111 -21
  11. data/ext/debug/extconf.rb +23 -0
  12. data/ext/debug/iseq_collector.c +2 -0
  13. data/lib/debug/abbrev_command.rb +77 -0
  14. data/lib/debug/breakpoint.rb +102 -74
  15. data/lib/debug/client.rb +46 -12
  16. data/lib/debug/color.rb +0 -0
  17. data/lib/debug/config.rb +129 -36
  18. data/lib/debug/console.rb +46 -40
  19. data/lib/debug/dap_custom/traceInspector.rb +336 -0
  20. data/lib/debug/frame_info.rb +40 -25
  21. data/lib/debug/irb_integration.rb +37 -0
  22. data/lib/debug/local.rb +17 -11
  23. data/lib/debug/open.rb +0 -0
  24. data/lib/debug/open_nonstop.rb +0 -0
  25. data/lib/debug/prelude.rb +3 -2
  26. data/lib/debug/server.rb +126 -56
  27. data/lib/debug/server_cdp.rb +673 -248
  28. data/lib/debug/server_dap.rb +497 -261
  29. data/lib/debug/session.rb +899 -441
  30. data/lib/debug/source_repository.rb +122 -49
  31. data/lib/debug/start.rb +1 -1
  32. data/lib/debug/thread_client.rb +460 -155
  33. data/lib/debug/tracer.rb +10 -16
  34. data/lib/debug/version.rb +1 -1
  35. data/lib/debug.rb +7 -2
  36. data/misc/README.md.erb +106 -56
  37. metadata +14 -24
  38. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -24
  39. data/.github/ISSUE_TEMPLATE/custom.md +0 -10
  40. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -14
  41. data/.github/pull_request_template.md +0 -9
  42. data/.github/workflows/ruby.yml +0 -34
  43. data/.gitignore +0 -12
  44. data/bin/console +0 -14
  45. data/bin/gentest +0 -30
  46. data/bin/setup +0 -8
  47. data/lib/debug/bp.vim +0 -68
data/lib/debug/config.rb CHANGED
@@ -7,46 +7,54 @@ module DEBUGGER__
7
7
  ERROR: 2,
8
8
  WARN: 3,
9
9
  INFO: 4,
10
+ DEBUG: 5
10
11
  }.freeze
11
12
 
12
13
  CONFIG_SET = {
13
14
  # UI setting
14
- log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger (default: WARN)", :loglevel],
15
- show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint (default: 10 lines)", :int],
16
- show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint (default: 2 frames)", :int],
17
- use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool],
18
- no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize (default: false)", :bool],
19
- no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT (default: false)", :bool],
20
- no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library (default: false)", :bool],
15
+ log_level: ['RUBY_DEBUG_LOG_LEVEL', "UI: Log level same as Logger", :loglevel, "WARN"],
16
+ show_src_lines: ['RUBY_DEBUG_SHOW_SRC_LINES', "UI: Show n lines source code on breakpoint", :int, "10"],
17
+ show_evaledsrc: ['RUBY_DEBUG_SHOW_EVALEDSRC', "UI: Show actually evaluated source", :bool, "false"],
18
+ show_frames: ['RUBY_DEBUG_SHOW_FRAMES', "UI: Show n frames on breakpoint", :int, "2"],
19
+ use_short_path: ['RUBY_DEBUG_USE_SHORT_PATH', "UI: Show shorten PATH (like $(Gem)/foo.rb)", :bool, "false"],
20
+ no_color: ['RUBY_DEBUG_NO_COLOR', "UI: Do not use colorize", :bool, "false"],
21
+ no_sigint_hook: ['RUBY_DEBUG_NO_SIGINT_HOOK', "UI: Do not suspend on SIGINT", :bool, "false"],
22
+ no_reline: ['RUBY_DEBUG_NO_RELINE', "UI: Do not use Reline library", :bool, "false"],
23
+ no_hint: ['RUBY_DEBUG_NO_HINT', "UI: Do not show the hint on the REPL", :bool, "false"],
24
+ no_lineno: ['RUBY_DEBUG_NO_LINENO', "UI: Do not show line numbers", :bool, "false"],
25
+ irb_console: ["RUBY_DEBUG_IRB_CONSOLE", "UI: Use IRB as the console", :bool, "false"],
21
26
 
22
27
  # control setting
23
- skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths (default: [])", :path],
24
- skip_nosrc: ['RUBY_DEBUG_SKIP_NOSRC', "CONTROL: Skip on no source code lines (default: false)", :bool],
25
- keep_alloc_site:['RUBY_DEBUG_KEEP_ALLOC_SITE',"CONTROL: Keep allocation site and p, pp shows it (default: false)", :bool],
26
- postmortem: ['RUBY_DEBUG_POSTMORTEM', "CONTROL: Enable postmortem debug (default: false)", :bool],
27
- fork_mode: ['RUBY_DEBUG_FORK_MODE', "CONTROL: Control which process activates a debugger after fork (both/parent/child) (default: both)", :forkmode],
28
- sigdump_sig: ['RUBY_DEBUG_SIGDUMP_SIG', "CONTROL: Sigdump signal (default: disabled)"],
28
+ skip_path: ['RUBY_DEBUG_SKIP_PATH', "CONTROL: Skip showing/entering frames for given paths", :path],
29
+ skip_nosrc: ['RUBY_DEBUG_SKIP_NOSRC', "CONTROL: Skip on no source code lines", :bool, "false"],
30
+ keep_alloc_site:['RUBY_DEBUG_KEEP_ALLOC_SITE',"CONTROL: Keep allocation site and p, pp shows it", :bool, "false"],
31
+ postmortem: ['RUBY_DEBUG_POSTMORTEM', "CONTROL: Enable postmortem debug", :bool, "false"],
32
+ fork_mode: ['RUBY_DEBUG_FORK_MODE', "CONTROL: Control which process activates a debugger after fork (both/parent/child)", :forkmode, "both"],
33
+ sigdump_sig: ['RUBY_DEBUG_SIGDUMP_SIG', "CONTROL: Sigdump signal", :bool, "false"],
29
34
 
30
35
  # boot setting
31
- nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool],
32
- stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool],
36
+ nonstop: ['RUBY_DEBUG_NONSTOP', "BOOT: Nonstop mode", :bool, "false"],
37
+ stop_at_load: ['RUBY_DEBUG_STOP_AT_LOAD',"BOOT: Stop at just loading location", :bool, "false"],
33
38
  init_script: ['RUBY_DEBUG_INIT_SCRIPT', "BOOT: debug command script path loaded at first stop"],
34
- commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop. commands should be separated by ';;'"],
35
- no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool],
36
- history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file (default: ~/.rdbg_history)"],
37
- save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines (default: 10,000)"],
39
+ commands: ['RUBY_DEBUG_COMMANDS', "BOOT: debug commands invoked at first stop. Commands should be separated by `;;`"],
40
+ no_rc: ['RUBY_DEBUG_NO_RC', "BOOT: ignore loading ~/.rdbgrc(.rb)", :bool, "false"],
41
+ history_file: ['RUBY_DEBUG_HISTORY_FILE',"BOOT: history file", :string, "~/.rdbg_history"],
42
+ save_history: ['RUBY_DEBUG_SAVE_HISTORY',"BOOT: maximum save history lines", :int, "10000"],
38
43
 
39
44
  # remote setting
45
+ open: ['RUBY_DEBUG_OPEN', "REMOTE: Open remote port (same as `rdbg --open` option)"],
40
46
  port: ['RUBY_DEBUG_PORT', "REMOTE: TCP/IP remote debugging: port"],
41
- host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host (localhost if not given)"],
47
+ host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"],
42
48
  sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"],
43
49
  sock_dir: ['RUBY_DEBUG_SOCK_DIR', "REMOTE: UNIX Domain Socket remote debugging: socket directory"],
50
+ local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map],
51
+ skip_bp: ['RUBY_DEBUG_SKIP_BP', "REMOTE: Skip breakpoints if no clients are attached", :bool, 'false'],
44
52
  cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"],
45
- open_frontend: ['RUBY_DEBUG_OPEN_FRONTEND',"REMOTE: frontend used by open command (vscode, chrome, default: rdbg)."],
53
+ session_name: ['RUBY_DEBUG_SESSION_NAME', "REMOTE: Session name for differentiating multiple sessions"],
46
54
  chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"],
47
55
 
48
56
  # obsolete
49
- parent_on_fork: ['RUBY_DEBUG_PARENT_ON_FORK', "OBSOLETE: Keep debugging parent process on fork (default: false)", :bool],
57
+ parent_on_fork: ['RUBY_DEBUG_PARENT_ON_FORK', "OBSOLETE: Keep debugging parent process on fork", :bool, "false"],
50
58
  }.freeze
51
59
 
52
60
  CONFIG_MAP = CONFIG_SET.map{|k, (ev, _)| [k, ev]}.to_h.freeze
@@ -63,7 +71,17 @@ module DEBUGGER__
63
71
  raise 'Can not make multiple configurations in one process'
64
72
  end
65
73
 
66
- update self.class.parse_argv(argv)
74
+ config = self.class.parse_argv(argv)
75
+
76
+ # apply defaults
77
+ CONFIG_SET.each do |k, config_detail|
78
+ unless config.key?(k)
79
+ default_value = config_detail[3]
80
+ config[k] = parse_config_value(k, default_value)
81
+ end
82
+ end
83
+
84
+ update config
67
85
  end
68
86
 
69
87
  def inspect
@@ -114,11 +132,13 @@ module DEBUGGER__
114
132
  self.class.instance_variable_set(:@config, conf.freeze)
115
133
 
116
134
  # Post process
117
- if_updated old_conf, conf, :keep_alloc_site do |_, new|
135
+ if_updated old_conf, conf, :keep_alloc_site do |old, new|
118
136
  if new
119
137
  require 'objspace'
120
138
  ObjectSpace.trace_object_allocations_start
121
- else
139
+ end
140
+
141
+ if old && !new
122
142
  ObjectSpace.trace_object_allocations_stop
123
143
  end
124
144
  end
@@ -132,6 +152,28 @@ module DEBUGGER__
132
152
  if_updated old_conf, conf, :sigdump_sig do |old_sig, new_sig|
133
153
  setup_sigdump old_sig, new_sig
134
154
  end
155
+
156
+ if_updated old_conf, conf, :no_sigint_hook do |old, new|
157
+ if defined?(SESSION)
158
+ SESSION.set_no_sigint_hook old, new
159
+ end
160
+ end
161
+
162
+ if_updated old_conf, conf, :irb_console do |old, new|
163
+ if defined?(SESSION) && SESSION.active?
164
+ # irb_console is switched from true to false
165
+ if old
166
+ SESSION.deactivate_irb_integration
167
+ # irb_console is switched from false to true
168
+ else
169
+ if CONFIG[:open]
170
+ SESSION.instance_variable_get(:@ui).puts "\nIRB is not supported on the remote console."
171
+ else
172
+ SESSION.activate_irb_integration
173
+ end
174
+ end
175
+ end
176
+ end
135
177
  end
136
178
 
137
179
  private def if_updated old_conf, new_conf, key
@@ -215,6 +257,8 @@ module DEBUGGER__
215
257
  e
216
258
  end
217
259
  }
260
+ when :path_map
261
+ valstr.split(',').map{|e| e.split(':')}
218
262
  else
219
263
  valstr
220
264
  end
@@ -223,6 +267,7 @@ module DEBUGGER__
223
267
  def self.parse_argv argv
224
268
  config = {
225
269
  mode: :start,
270
+ no_color: (nc = ENV['NO_COLOR']) && !nc.empty?,
226
271
  }
227
272
  CONFIG_MAP.each{|key, evname|
228
273
  if val = ENV[evname]
@@ -239,6 +284,8 @@ module DEBUGGER__
239
284
  require 'optparse'
240
285
  require_relative 'version'
241
286
 
287
+ have_shown_version = false
288
+
242
289
  opt = OptionParser.new do |o|
243
290
  o.banner = "#{$0} [options] -- [debuggee options]"
244
291
  o.separator ''
@@ -279,8 +326,25 @@ module DEBUGGER__
279
326
  'If TCP/IP options are not given, a UNIX domain socket will be used.',
280
327
  'If FRONTEND is given, prepare for the FRONTEND.',
281
328
  'Now rdbg, vscode and chrome is supported.') do |f|
282
- config[:remote] = true
283
- config[:open_frontend] = f.downcase if f
329
+
330
+ case f # some format patterns are not documented yet
331
+ when nil
332
+ config[:open] = true
333
+ when /\A\d\z/
334
+ config[:open] = true
335
+ config[:port] = f.to_i
336
+ when /\A(\S+):(\d+)\z/
337
+ config[:open] = true
338
+ config[:host] = $1
339
+ config[:port] = $2.to_i
340
+ when 'tcp'
341
+ config[:open] = true
342
+ config[:port] ||= 0
343
+ when 'vscode', 'chrome', 'cdp'
344
+ config[:open] = f&.downcase
345
+ else
346
+ raise "Unknown option for --open: #{f}"
347
+ end
284
348
  end
285
349
  o.on('--sock-path=SOCK_PATH', 'UNIX Domain socket path') do |path|
286
350
  config[:sock_path] = path
@@ -294,6 +358,9 @@ module DEBUGGER__
294
358
  o.on('--cookie=COOKIE', 'Set a cookie for connection') do |c|
295
359
  config[:cookie] = c
296
360
  end
361
+ o.on('--session-name=NAME', 'Session name') do |name|
362
+ config[:session_name] = name
363
+ end
297
364
 
298
365
  rdbg = 'rdbg'
299
366
 
@@ -329,6 +396,16 @@ module DEBUGGER__
329
396
  o.separator ''
330
397
  o.separator 'Other options:'
331
398
 
399
+ o.on('-v', 'Show version number') do
400
+ puts o.ver
401
+ have_shown_version = true
402
+ end
403
+
404
+ o.on('--version', 'Show version number and exit') do
405
+ puts o.ver
406
+ exit
407
+ end
408
+
332
409
  o.on("-h", "--help", "Print help") do
333
410
  puts o
334
411
  exit
@@ -352,6 +429,13 @@ module DEBUGGER__
352
429
 
353
430
  opt.parse!(argv)
354
431
 
432
+ if argv.empty?
433
+ case
434
+ when have_shown_version && config[:mode] == :start
435
+ exit
436
+ end
437
+ end
438
+
355
439
  config
356
440
  end
357
441
 
@@ -361,6 +445,8 @@ module DEBUGGER__
361
445
  case CONFIG_SET[key][2]
362
446
  when :path
363
447
  valstr = config[key].map{|e| e.kind_of?(Regexp) ? e.inspect : e}.join(':')
448
+ when :path_map
449
+ valstr = config[key].map{|e| e.join(':')}.join(',')
364
450
  else
365
451
  valstr = config[key].to_s
366
452
  end
@@ -380,8 +466,9 @@ module DEBUGGER__
380
466
  unless (dir_uid = fs.uid) == (uid = Process.uid)
381
467
  raise "#{path} uid is #{dir_uid}, but Process.uid is #{uid}"
382
468
  end
383
- unless (dir_mode = fs.mode) == 040700 # 4: dir, 7:rwx
384
- raise "#{path}'s mode is #{dir_mode.to_s(8)} (should be 040700)"
469
+
470
+ if fs.world_writable? && !fs.sticky?
471
+ raise "#{path} is world writable but not sticky"
385
472
  end
386
473
 
387
474
  path
@@ -391,7 +478,7 @@ module DEBUGGER__
391
478
  require 'tmpdir'
392
479
 
393
480
  if tmpdir = Dir.tmpdir
394
- path = File.join(tmpdir, "ruby-debug-sock-#{Process.uid}")
481
+ path = File.join(tmpdir, "rdbg-#{Process.uid}")
395
482
 
396
483
  unless File.exist?(path)
397
484
  d = Dir.mktmpdir
@@ -404,7 +491,7 @@ module DEBUGGER__
404
491
 
405
492
  def self.unix_domain_socket_homedir
406
493
  if home = ENV['HOME']
407
- path = File.join(home, '.ruby-debug-sock')
494
+ path = File.join(home, '.rdbg-sock')
408
495
 
409
496
  unless File.exist?(path)
410
497
  Dir.mkdir(path, 0700)
@@ -428,12 +515,14 @@ module DEBUGGER__
428
515
  end
429
516
 
430
517
  def self.create_unix_domain_socket_name_prefix(base_dir = unix_domain_socket_dir)
431
- user = ENV['USER'] || 'ruby-debug'
432
- File.join(base_dir, "ruby-debug-#{user}")
518
+ File.join(base_dir, "rdbg")
433
519
  end
434
520
 
435
521
  def self.create_unix_domain_socket_name(base_dir = unix_domain_socket_dir)
436
- create_unix_domain_socket_name_prefix(base_dir) + "-#{Process.pid}"
522
+ suffix = "-#{Process.pid}"
523
+ name = CONFIG[:session_name]
524
+ suffix << "-#{name}" if name
525
+ create_unix_domain_socket_name_prefix(base_dir) + suffix
437
526
  end
438
527
 
439
528
  ## Help
@@ -448,10 +537,14 @@ module DEBUGGER__
448
537
  when /\A\s*### (.+)/
449
538
  cat = $1
450
539
  break if $1 == 'END'
451
- when /\A when (.+)/
540
+ when /\A register_command (.+)/
452
541
  next unless cat
453
542
  next unless desc
454
- ws = $1.split(/,\s*/).map{|e| e.gsub('\'', '')}
543
+
544
+ ws = []
545
+ $1.gsub(/'([a-z]+)'/){|w|
546
+ ws << $1
547
+ }
455
548
  helps[cat] << [ws, desc]
456
549
  desc = nil
457
550
  max_w = ws.max_by{|w| w.length}
data/lib/debug/console.rb CHANGED
@@ -5,30 +5,21 @@ module DEBUGGER__
5
5
  raise LoadError if CONFIG[:no_reline]
6
6
  require 'reline'
7
7
 
8
- # reline 0.2.7 or later is required.
9
- raise LoadError if Reline::VERSION < '0.2.7'
10
-
11
8
  require_relative 'color'
12
- include Color
13
9
 
14
- begin
15
- prev = trap(:SIGWINCH, nil)
16
- trap(:SIGWINCH, prev)
17
- SIGWINCH_SUPPORTED = true
18
- rescue ArgumentError
19
- SIGWINCH_SUPPORTED = false
20
- end
10
+ include Color
21
11
 
22
- # 0.2.7 has SIGWINCH issue on non-main thread
23
- class ::Reline::LineEditor
24
- m = Module.new do
25
- def reset(prompt = '', encoding:)
26
- super
27
- Signal.trap(:SIGWINCH, nil)
28
- end
12
+ def parse_input buff, commands
13
+ c, rest = get_command buff
14
+ case
15
+ when commands.keys.include?(c)
16
+ :command
17
+ when !rest && /\A\s*[a-z]*\z/ =~ c
18
+ nil
19
+ else
20
+ :ruby
29
21
  end
30
- prepend m
31
- end if SIGWINCH_SUPPORTED
22
+ end
32
23
 
33
24
  def readline_setup prompt
34
25
  load_history_if_not_loaded
@@ -38,7 +29,17 @@ module DEBUGGER__
38
29
  prev_output_modifier_proc = Reline.output_modifier_proc
39
30
  prev_prompt_proc = Reline.prompt_proc
40
31
 
41
- Reline.prompt_proc = nil
32
+ # prompt state
33
+ state = nil # :command, :ruby, nil (unknown)
34
+
35
+ Reline.prompt_proc = -> args, *kw do
36
+ case state = parse_input(args.first, commands)
37
+ when nil, :command
38
+ [prompt]
39
+ when :ruby
40
+ [prompt.sub('rdbg'){colorize('ruby', [:RED])}]
41
+ end * args.size
42
+ end
42
43
 
43
44
  Reline.completion_proc = -> given do
44
45
  buff = Reline.line_buffer
@@ -52,17 +53,16 @@ module DEBUGGER__
52
53
  end
53
54
  files
54
55
  else
55
- commands.keys.grep(/\A#{given}/)
56
+ commands.keys.grep(/\A#{Regexp.escape(given)}/)
56
57
  end
57
58
  end
58
59
 
59
60
  Reline.output_modifier_proc = -> buff, **kw do
60
61
  c, rest = get_command buff
61
62
 
62
- case
63
- when commands.keys.include?(c = c.strip)
64
- # [:DIM, :CYAN, :BLUE, :CLEAR, :UNDERLINE, :REVERSE, :RED, :GREEN, :MAGENTA, :BOLD, :YELLOW]
65
- cmd = colorize(c.strip, [:CYAN, :UNDERLINE])
63
+ case state
64
+ when :command
65
+ cmd = colorize(c, [:CYAN, :UNDERLINE])
66
66
 
67
67
  if commands[c] == c
68
68
  rprompt = colorize(" # command", [:DIM])
@@ -70,14 +70,14 @@ module DEBUGGER__
70
70
  rprompt = colorize(" # #{commands[c]} command", [:DIM])
71
71
  end
72
72
 
73
- rest = (rest ? colorize_code(rest) : '') + rprompt
74
- cmd + rest
75
- when !rest && /\A\s*[a-z]*\z/ =~ c
73
+ rest = rest ? colorize_code(rest) : ''
74
+ cmd + rest + rprompt
75
+ when nil
76
76
  buff
77
- else
78
- colorize_code(buff.chomp) + colorize(" # ruby", [:DIM])
77
+ when :ruby
78
+ colorize_code(buff)
79
79
  end
80
- end
80
+ end unless CONFIG[:no_hint]
81
81
 
82
82
  yield
83
83
 
@@ -90,9 +90,9 @@ module DEBUGGER__
90
90
  private def get_command line
91
91
  case line.chomp
92
92
  when /\A(\s*[a-z]+)(\s.*)?\z$/
93
- return $1, $2
93
+ return $1.strip, $2
94
94
  else
95
- line.chomp
95
+ line.strip
96
96
  end
97
97
  end
98
98
 
@@ -143,7 +143,7 @@ module DEBUGGER__
143
143
  rescue LoadError
144
144
  def readline prompt
145
145
  print prompt
146
- gets
146
+ $stdin.gets
147
147
  end
148
148
 
149
149
  def history
@@ -153,7 +153,13 @@ module DEBUGGER__
153
153
  end
154
154
 
155
155
  def history_file
156
- CONFIG[:history_file] || File.expand_path("~/.rdbg_history")
156
+ history_file = CONFIG[:history_file]
157
+
158
+ if !history_file.empty?
159
+ File.expand_path(history_file)
160
+ else
161
+ history_file
162
+ end
157
163
  end
158
164
 
159
165
  FH = "# Today's OMIKUJI: "
@@ -181,7 +187,7 @@ module DEBUGGER__
181
187
  if history && @init_history_lines
182
188
  added_records = history.to_a[@init_history_lines .. -1]
183
189
  path = history_file
184
- max = CONFIG[:save_history] || 10_000
190
+ max = CONFIG[:save_history]
185
191
 
186
192
  if !added_records.empty? && !path.empty?
187
193
  orig_records = read_history_file
@@ -197,11 +203,11 @@ module DEBUGGER__
197
203
  end
198
204
 
199
205
  def load_history
200
- read_history_file.count{|line|
206
+ read_history_file.each{|line|
201
207
  line.strip!
202
208
  history << line unless line.empty?
203
- }
209
+ } if history.empty?
210
+ history.count
204
211
  end
205
212
  end # class Console
206
213
  end
207
-