byebug 9.0.5 → 11.1.3

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 (133) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +399 -264
  3. data/CONTRIBUTING.md +12 -19
  4. data/GUIDE.md +40 -26
  5. data/LICENSE +18 -18
  6. data/README.md +103 -74
  7. data/exe/byebug +6 -0
  8. data/ext/byebug/breakpoint.c +2 -2
  9. data/ext/byebug/byebug.c +26 -31
  10. data/ext/byebug/byebug.h +44 -28
  11. data/ext/byebug/context.c +45 -32
  12. data/ext/byebug/extconf.rb +7 -5
  13. data/ext/byebug/locker.c +4 -4
  14. data/ext/byebug/threads.c +12 -12
  15. data/lib/byebug/attacher.rb +18 -4
  16. data/lib/byebug/breakpoint.rb +26 -6
  17. data/lib/byebug/command.rb +20 -14
  18. data/lib/byebug/command_list.rb +3 -1
  19. data/lib/byebug/commands/break.rb +36 -22
  20. data/lib/byebug/commands/catch.rb +16 -18
  21. data/lib/byebug/commands/condition.rb +11 -11
  22. data/lib/byebug/commands/continue.rb +32 -12
  23. data/lib/byebug/commands/debug.rb +7 -5
  24. data/lib/byebug/commands/delete.rb +13 -11
  25. data/lib/byebug/commands/disable/breakpoints.rb +7 -5
  26. data/lib/byebug/commands/disable/display.rb +7 -5
  27. data/lib/byebug/commands/disable.rb +8 -6
  28. data/lib/byebug/commands/display.rb +11 -9
  29. data/lib/byebug/commands/down.rb +10 -8
  30. data/lib/byebug/commands/edit.rb +11 -8
  31. data/lib/byebug/commands/enable/breakpoints.rb +7 -5
  32. data/lib/byebug/commands/enable/display.rb +7 -5
  33. data/lib/byebug/commands/enable.rb +8 -6
  34. data/lib/byebug/commands/finish.rb +9 -7
  35. data/lib/byebug/commands/frame.rb +11 -9
  36. data/lib/byebug/commands/help.rb +7 -5
  37. data/lib/byebug/commands/history.rb +7 -5
  38. data/lib/byebug/commands/info/breakpoints.rb +18 -14
  39. data/lib/byebug/commands/info/display.rb +16 -9
  40. data/lib/byebug/commands/info/file.rb +13 -14
  41. data/lib/byebug/commands/info/line.rb +5 -3
  42. data/lib/byebug/commands/info/program.rb +8 -6
  43. data/lib/byebug/commands/info.rb +11 -9
  44. data/lib/byebug/commands/interrupt.rb +8 -4
  45. data/lib/byebug/commands/irb.rb +13 -12
  46. data/lib/byebug/commands/kill.rb +11 -11
  47. data/lib/byebug/commands/list.rb +41 -46
  48. data/lib/byebug/commands/method.rb +10 -8
  49. data/lib/byebug/commands/next.rb +8 -6
  50. data/lib/byebug/commands/pry.rb +10 -10
  51. data/lib/byebug/commands/quit.rb +10 -8
  52. data/lib/byebug/commands/restart.rb +30 -11
  53. data/lib/byebug/commands/save.rb +10 -8
  54. data/lib/byebug/commands/set.rb +13 -11
  55. data/lib/byebug/commands/show.rb +7 -5
  56. data/lib/byebug/commands/skip.rb +85 -0
  57. data/lib/byebug/commands/source.rb +7 -7
  58. data/lib/byebug/commands/step.rb +8 -6
  59. data/lib/byebug/commands/thread/current.rb +6 -4
  60. data/lib/byebug/commands/thread/list.rb +7 -5
  61. data/lib/byebug/commands/thread/resume.rb +7 -7
  62. data/lib/byebug/commands/thread/stop.rb +6 -4
  63. data/lib/byebug/commands/thread/switch.rb +6 -4
  64. data/lib/byebug/commands/thread.rb +11 -9
  65. data/lib/byebug/commands/tracevar.rb +10 -11
  66. data/lib/byebug/commands/undisplay.rb +12 -11
  67. data/lib/byebug/commands/untracevar.rb +8 -6
  68. data/lib/byebug/commands/up.rb +10 -8
  69. data/lib/byebug/commands/var/all.rb +7 -5
  70. data/lib/byebug/commands/var/args.rb +6 -4
  71. data/lib/byebug/commands/var/const.rb +9 -9
  72. data/lib/byebug/commands/var/global.rb +5 -3
  73. data/lib/byebug/commands/var/instance.rb +6 -4
  74. data/lib/byebug/commands/var/local.rb +6 -4
  75. data/lib/byebug/commands/var.rb +12 -10
  76. data/lib/byebug/commands/where.rb +9 -7
  77. data/lib/byebug/commands.rb +40 -37
  78. data/lib/byebug/context.rb +7 -5
  79. data/lib/byebug/core.rb +26 -25
  80. data/lib/byebug/errors.rb +4 -2
  81. data/lib/byebug/frame.rb +19 -22
  82. data/lib/byebug/helpers/bin.rb +47 -0
  83. data/lib/byebug/helpers/eval.rb +15 -13
  84. data/lib/byebug/helpers/file.rb +6 -4
  85. data/lib/byebug/helpers/frame.rb +7 -5
  86. data/lib/byebug/helpers/parse.rb +5 -5
  87. data/lib/byebug/helpers/path.rb +9 -11
  88. data/lib/byebug/helpers/reflection.rb +2 -0
  89. data/lib/byebug/helpers/string.rb +11 -2
  90. data/lib/byebug/helpers/thread.rb +10 -8
  91. data/lib/byebug/helpers/toggle.rb +28 -27
  92. data/lib/byebug/helpers/var.rb +9 -7
  93. data/lib/byebug/history.rb +20 -11
  94. data/lib/byebug/interface.rb +13 -11
  95. data/lib/byebug/interfaces/local_interface.rb +25 -7
  96. data/lib/byebug/interfaces/remote_interface.rb +21 -9
  97. data/lib/byebug/interfaces/script_interface.rb +4 -1
  98. data/lib/byebug/interfaces/test_interface.rb +5 -3
  99. data/lib/byebug/option_setter.rb +14 -12
  100. data/lib/byebug/printers/base.rb +10 -10
  101. data/lib/byebug/printers/plain.rb +9 -8
  102. data/lib/byebug/printers/texts/base.yml +7 -3
  103. data/lib/byebug/printers/texts/plain.yml +1 -1
  104. data/lib/byebug/processors/command_processor.rb +11 -12
  105. data/lib/byebug/processors/control_processor.rb +4 -6
  106. data/lib/byebug/processors/post_mortem_processor.rb +4 -2
  107. data/lib/byebug/processors/script_processor.rb +7 -3
  108. data/lib/byebug/remote/client.rb +57 -0
  109. data/lib/byebug/remote/server.rb +47 -0
  110. data/lib/byebug/remote.rb +46 -66
  111. data/lib/byebug/runner.rb +43 -49
  112. data/lib/byebug/setting.rb +11 -5
  113. data/lib/byebug/settings/autoirb.rb +7 -5
  114. data/lib/byebug/settings/autolist.rb +7 -5
  115. data/lib/byebug/settings/autopry.rb +7 -5
  116. data/lib/byebug/settings/autosave.rb +4 -2
  117. data/lib/byebug/settings/basename.rb +4 -2
  118. data/lib/byebug/settings/callstyle.rb +4 -3
  119. data/lib/byebug/settings/fullpath.rb +4 -2
  120. data/lib/byebug/settings/histfile.rb +5 -3
  121. data/lib/byebug/settings/histsize.rb +4 -2
  122. data/lib/byebug/settings/linetrace.rb +6 -4
  123. data/lib/byebug/settings/listsize.rb +4 -2
  124. data/lib/byebug/settings/post_mortem.rb +6 -4
  125. data/lib/byebug/settings/savefile.rb +4 -2
  126. data/lib/byebug/settings/stack_on_error.rb +4 -2
  127. data/lib/byebug/settings/width.rb +3 -1
  128. data/lib/byebug/source_file_formatter.rb +71 -0
  129. data/lib/byebug/subcommands.rb +6 -4
  130. data/lib/byebug/version.rb +2 -1
  131. data/lib/byebug.rb +3 -1
  132. metadata +22 -20
  133. data/bin/byebug +0 -7
@@ -1,6 +1,8 @@
1
- require 'byebug/setting'
2
- require 'byebug/history'
3
- require 'byebug/helpers/file'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setting"
4
+ require_relative "history"
5
+ require_relative "helpers/file"
4
6
 
5
7
  #
6
8
  # Namespace for all of byebug's code
@@ -20,7 +22,7 @@ module Byebug
20
22
  def initialize
21
23
  @command_queue = []
22
24
  @history = History.new
23
- @last_line = ''
25
+ @last_line = ""
24
26
  end
25
27
 
26
28
  def last_if_empty(input)
@@ -97,7 +99,7 @@ module Byebug
97
99
  # Confirms user introduced an affirmative response to the input stream.
98
100
  #
99
101
  def confirm(prompt)
100
- readline(prompt) == 'y'
102
+ readline(prompt) == "y"
101
103
  end
102
104
 
103
105
  def close
@@ -124,7 +126,7 @@ module Byebug
124
126
  # array of commands: [cmd1, cmd2, ..., cmdN]
125
127
  #
126
128
  def split_commands(cmd_line)
127
- return [''] if cmd_line.empty?
129
+ return [""] if cmd_line.empty?
128
130
 
129
131
  cmd_line.split(/;/).each_with_object([]) do |v, m|
130
132
  if m.empty? || m.last[-1] != '\\'
@@ -132,13 +134,13 @@ module Byebug
132
134
  next
133
135
  end
134
136
 
135
- m.last[-1, 1] = ''
136
- m.last << ';' << v
137
+ m.last[-1, 1] = ""
138
+ m.last << ";" << v
137
139
  end
138
140
  end
139
141
  end
140
142
  end
141
143
 
142
- require 'byebug/interfaces/local_interface'
143
- require 'byebug/interfaces/script_interface'
144
- require 'byebug/interfaces/remote_interface'
144
+ require_relative "interfaces/local_interface"
145
+ require_relative "interfaces/script_interface"
146
+ require_relative "interfaces/remote_interface"
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Byebug
3
4
  #
4
5
  # Interface class for standard byebug use.
5
6
  #
6
7
  class LocalInterface < Interface
7
- EOF_ALIAS = 'continue'.freeze
8
+ EOF_ALIAS = "continue"
8
9
 
9
10
  def initialize
10
11
  super()
@@ -20,9 +21,7 @@ module Byebug
20
21
  # @param prompt Prompt to be displayed.
21
22
  #
22
23
  def readline(prompt)
23
- with_repl_like_sigint do
24
- Readline.readline(prompt, false) || EOF_ALIAS
25
- end
24
+ with_repl_like_sigint { without_readline_completion { Readline.readline(prompt) || EOF_ALIAS } }
26
25
  end
27
26
 
28
27
  #
@@ -33,13 +32,32 @@ module Byebug
33
32
  # @note Any external 'INT' traps are overriden during this method.
34
33
  #
35
34
  def with_repl_like_sigint
36
- orig_handler = trap('INT') { raise Interrupt }
35
+ orig_handler = trap("INT") { raise Interrupt }
37
36
  yield
38
37
  rescue Interrupt
39
- puts('^C')
38
+ puts("^C")
40
39
  retry
41
40
  ensure
42
- trap('INT', orig_handler)
41
+ trap("INT", orig_handler)
42
+ end
43
+
44
+ #
45
+ # Disable any Readline completion procs.
46
+ #
47
+ # Other gems, for example, IRB could've installed completion procs that are
48
+ # dependent on them being loaded. Disable those while byebug is the REPL
49
+ # making use of Readline.
50
+ #
51
+ def without_readline_completion
52
+ orig_completion = Readline.completion_proc
53
+ return yield unless orig_completion
54
+
55
+ begin
56
+ Readline.completion_proc = ->(_) { nil }
57
+ yield
58
+ ensure
59
+ Readline.completion_proc = orig_completion
60
+ end
43
61
  end
44
62
  end
45
63
  end
@@ -1,4 +1,6 @@
1
- require 'byebug/history'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../history"
2
4
 
3
5
  module Byebug
4
6
  #
@@ -14,25 +16,35 @@ module Byebug
14
16
 
15
17
  def read_command(prompt)
16
18
  super("PROMPT #{prompt}")
19
+ rescue Errno::EPIPE, Errno::ECONNABORTED
20
+ "continue"
17
21
  end
18
22
 
19
23
  def confirm(prompt)
20
24
  super("CONFIRM #{prompt}")
25
+ rescue Errno::EPIPE, Errno::ECONNABORTED
26
+ false
27
+ end
28
+
29
+ def print(message)
30
+ super(message)
31
+ rescue Errno::EPIPE, Errno::ECONNABORTED
32
+ nil
33
+ end
34
+
35
+ def puts(message)
36
+ super(message)
37
+ rescue Errno::EPIPE, Errno::ECONNABORTED
38
+ nil
21
39
  end
22
40
 
23
41
  def close
24
42
  output.close
25
- rescue IOError
26
- errmsg('Error closing the interface...')
27
43
  end
28
44
 
29
45
  def readline(prompt)
30
- output.puts(prompt)
31
-
32
- result = input.gets
33
- raise IOError unless result
34
-
35
- result.chomp
46
+ puts(prompt)
47
+ (input.gets || "continue").chomp
36
48
  end
37
49
  end
38
50
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Byebug
2
4
  #
3
5
  # Interface class for command execution from script files.
@@ -22,7 +24,8 @@ module Byebug
22
24
  def readline(*)
23
25
  while (result = input.gets)
24
26
  output.puts "+ #{result}" if @verbose
25
- next if result =~ /^\s*#/
27
+ next if /^\s*#/.match?(result)
28
+
26
29
  return result.chomp
27
30
  end
28
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Byebug
2
4
  #
3
5
  # Custom interface for easier assertions
@@ -41,9 +43,9 @@ module Byebug
41
43
 
42
44
  def inspect
43
45
  [
44
- 'Input:', input.join("\n"),
45
- 'Output:', output.join("\n"),
46
- 'Error:', error.join("\n")
46
+ "Input:", input.join("\n"),
47
+ "Output:", output.join("\n"),
48
+ "Error:", error.join("\n")
47
49
  ].join("\n")
48
50
  end
49
51
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Byebug
2
4
  #
3
5
  # Handles byebug's command line options
@@ -25,67 +27,67 @@ module Byebug
25
27
  private
26
28
 
27
29
  def debug
28
- @opts.on '-d', '--debug', 'Set $DEBUG=true' do
30
+ @opts.on "-d", "--debug", "Set $DEBUG=true" do
29
31
  $DEBUG = true
30
32
  end
31
33
  end
32
34
 
33
35
  def include_flag
34
- @opts.on '-I', '--include list', 'Add to paths to $LOAD_PATH' do |list|
35
- $LOAD_PATH.push(list.split(':')).flatten!
36
+ @opts.on "-I", "--include list", "Add to paths to $LOAD_PATH" do |list|
37
+ $LOAD_PATH.push(list.split(":")).flatten!
36
38
  end
37
39
  end
38
40
 
39
41
  def post_mortem
40
- @opts.on '-m', '--[no-]post-mortem', 'Use post-mortem mode' do |v|
42
+ @opts.on "-m", "--[no-]post-mortem", "Use post-mortem mode" do |v|
41
43
  Setting[:post_mortem] = v
42
44
  end
43
45
  end
44
46
 
45
47
  def quit
46
- @opts.on '-q', '--[no-]quit', 'Quit when script finishes' do |v|
48
+ @opts.on "-q", "--[no-]quit", "Quit when script finishes" do |v|
47
49
  @runner.quit = v
48
50
  end
49
51
  end
50
52
 
51
53
  def rc
52
- @opts.on '-x', '--[no-]rc', 'Run byebug initialization file' do |v|
54
+ @opts.on "-x", "--[no-]rc", "Run byebug initialization file" do |v|
53
55
  @runner.init_script = v
54
56
  end
55
57
  end
56
58
 
57
59
  def stop
58
- @opts.on '-s', '--[no-]stop', 'Stop when script is loaded' do |v|
60
+ @opts.on "-s", "--[no-]stop", "Stop when script is loaded" do |v|
59
61
  @runner.stop = v
60
62
  end
61
63
  end
62
64
 
63
65
  def require_flag
64
- @opts.on '-r', '--require file', 'Require library before script' do |lib|
66
+ @opts.on "-r", "--require file", "Require library before script" do |lib|
65
67
  require lib
66
68
  end
67
69
  end
68
70
 
69
71
  def remote
70
- @opts.on '-R', '--remote [host:]port', 'Remote debug [host:]port' do |p|
72
+ @opts.on "-R", "--remote [host:]port", "Remote debug [host:]port" do |p|
71
73
  @runner.remote = p
72
74
  end
73
75
  end
74
76
 
75
77
  def trace
76
- @opts.on '-t', '--[no-]trace', 'Turn on line tracing' do |v|
78
+ @opts.on "-t", "--[no-]trace", "Turn on line tracing" do |v|
77
79
  Setting[:linetrace] = v
78
80
  end
79
81
  end
80
82
 
81
83
  def version
82
- @opts.on '-v', '--version', 'Print program version' do
84
+ @opts.on "-v", "--version", "Print program version" do
83
85
  @runner.version = Byebug::VERSION
84
86
  end
85
87
  end
86
88
 
87
89
  def help
88
- @opts.on '-h', '--help', 'Display this message' do
90
+ @opts.on "-h", "--help", "Display this message" do
89
91
  @runner.help = @opts.help
90
92
  end
91
93
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'yaml'
2
+
3
+ require "yaml"
3
4
 
4
5
  module Byebug
5
6
  module Printers
@@ -10,33 +11,32 @@ module Byebug
10
11
  class MissedPath < StandardError; end
11
12
  class MissedArgument < StandardError; end
12
13
 
13
- SEPARATOR = '.'.freeze
14
+ SEPARATOR = "."
14
15
 
15
16
  def type
16
- self.class.name.split('::').last.downcase
17
+ self.class.name.split("::").last.downcase
17
18
  end
18
19
 
19
20
  private
20
21
 
21
22
  def locate(path)
22
23
  result = nil
23
- contents.each do |_, contents|
24
+ contents.each_value do |contents|
24
25
  result = parts(path).reduce(contents) do |r, part|
25
- r && r.key?(part) ? r[part] : nil
26
+ r&.key?(part) ? r[part] : nil
26
27
  end
27
28
  break if result
28
29
  end
29
30
  raise MissedPath, "Can't find part path '#{path}'" unless result
31
+
30
32
  result
31
33
  end
32
34
 
33
35
  def translate(string, args = {})
34
36
  # they may contain #{} string interpolation
35
- string.gsub(/\|\w+$/, '').gsub(/([^#]?){([^}]*)}/) do
37
+ string.gsub(/\|\w+$/, "").gsub(/([^#]?){([^}]*)}/) do
36
38
  key = Regexp.last_match[2].to_s
37
- unless args.key?(key.to_sym)
38
- raise MissedArgument, "Missed argument #{key} for '#{string}'"
39
- end
39
+ raise MissedArgument, "Missed argument #{key} for '#{string}'" unless args.key?(key.to_sym)
40
40
 
41
41
  "#{Regexp.last_match[1]}#{args[key.to_sym]}"
42
42
  end
@@ -61,7 +61,7 @@ module Byebug
61
61
  end
62
62
 
63
63
  def contents_files
64
- [File.expand_path(File.join('..', 'texts', 'base.yml'), __FILE__)]
64
+ [File.join(__dir__, "texts", "base.yml")]
65
65
  end
66
66
  end
67
67
  end
@@ -1,4 +1,6 @@
1
- require 'byebug/printers/base'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
2
4
 
3
5
  module Byebug
4
6
  module Printers
@@ -8,7 +10,7 @@ module Byebug
8
10
  class Plain < Base
9
11
  def print(path, args = {})
10
12
  message = translate(locate(path), args)
11
- tail = parts(path).include?('confirmations') ? ' (y/n) ' : "\n"
13
+ tail = parts(path).include?("confirmations") ? " (y/n) " : "\n"
12
14
  message << tail
13
15
  end
14
16
 
@@ -20,12 +22,12 @@ module Byebug
20
22
  lines.join
21
23
  end
22
24
 
23
- def print_variables(variables, *_)
24
- print_collection('variable.variable', variables) do |(key, value), _|
25
- value = value.nil? ? 'nil' : value.to_s
25
+ def print_variables(variables, *_unused)
26
+ print_collection("variable.variable", variables) do |(key, value), _|
27
+ value = value.nil? ? "nil" : value.to_s
26
28
  if "#{key} = #{value}".size > Setting[:width]
27
29
  key_size = "#{key} = ".size
28
- value = value[0..Setting[:width] - key_size - 4] + '...'
30
+ value = value[0..Setting[:width] - key_size - 4] + "..."
29
31
  end
30
32
 
31
33
  { key: key, value: value }
@@ -35,8 +37,7 @@ module Byebug
35
37
  private
36
38
 
37
39
  def contents_files
38
- [File.expand_path(File.join('..', 'texts', 'plain.yml'), __FILE__)] +
39
- super
40
+ [File.join(__dir__, "texts", "plain.yml")] + super
40
41
  end
41
42
  end
42
43
  end
@@ -1,10 +1,10 @@
1
1
  base:
2
2
  errors:
3
- only_local: 'Command is available only in local mode.'
3
+ only_local: "Command is available only in local mode."
4
4
 
5
5
  break:
6
6
  errors:
7
- line: "Line {line} is not a valid breakpoint in file {file}"
7
+ line: "Line {line} is not a valid breakpoint in file {file}.\n\nValid break points are:\n{valid_breakpoints}"
8
8
  location: "Invalid breakpoint location"
9
9
  state: "We are not in a state that has an associated file"
10
10
  class: "Unknown class {klass}"
@@ -16,6 +16,8 @@ break:
16
16
  not_changed: "Incorrect expression \"{expr}\", breakpoint not changed"
17
17
  confirmations:
18
18
  delete_all: "Delete all breakpoints?"
19
+ messages:
20
+ breakpoint_deleted: "Deleted breakpoint {pos}"
19
21
 
20
22
  catch:
21
23
  added: "Catching exception {exception}."
@@ -60,7 +62,7 @@ info:
60
62
 
61
63
  pry:
62
64
  errors:
63
- not_installed: 'You need to install pry in order to run this command'
65
+ not_installed: "You need to install pry in order to run this command"
64
66
 
65
67
  quit:
66
68
  confirmations:
@@ -97,6 +99,8 @@ toggle:
97
99
  no_display: "No display expressions have been set"
98
100
  syntax: "\"{toggle}\" must be followed by \"display\", \"breakpoints\" or breakpoint ids"
99
101
  expression: "Expression \"{expr}\" syntactically incorrect; breakpoint remains disabled."
102
+ messages:
103
+ toggled: "Breakpoint {bpnum} {endis}abled"
100
104
 
101
105
  parse:
102
106
  errors:
@@ -1,5 +1,5 @@
1
1
  break:
2
- created: "Successfully created breakpoint with id {id}"
2
+ created: "Created breakpoint {id} at {file}:{line}"
3
3
 
4
4
  display:
5
5
  result: "{n}: {exp} = {result}"
@@ -1,7 +1,9 @@
1
- require 'forwardable'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'byebug/helpers/eval'
4
- require 'byebug/errors'
3
+ require "forwardable"
4
+
5
+ require_relative "../helpers/eval"
6
+ require_relative "../errors"
5
7
 
6
8
  module Byebug
7
9
  #
@@ -16,19 +18,16 @@ module Byebug
16
18
  include Helpers::EvalHelper
17
19
 
18
20
  attr_accessor :prev_line
19
- attr_reader :context
21
+ attr_reader :context, :interface
20
22
 
21
- def initialize(context)
23
+ def initialize(context, interface = LocalInterface.new)
22
24
  @context = context
25
+ @interface = interface
23
26
 
24
27
  @proceed = false
25
28
  @prev_line = nil
26
29
  end
27
30
 
28
- def interface
29
- @interface ||= Context.interface
30
- end
31
-
32
31
  def printer
33
32
  @printer ||= Printers::Plain.new
34
33
  end
@@ -106,7 +105,7 @@ module Byebug
106
105
  # Prompt shown before reading a command.
107
106
  #
108
107
  def prompt
109
- '(byebug) '
108
+ "(byebug) "
110
109
  end
111
110
 
112
111
  def before_repl
@@ -129,7 +128,7 @@ module Byebug
129
128
  cmd = interface.read_command(prompt)
130
129
  return if cmd.nil?
131
130
 
132
- next if cmd == ''
131
+ next if cmd == ""
133
132
 
134
133
  run_cmd(cmd)
135
134
  end
@@ -167,7 +166,7 @@ module Byebug
167
166
 
168
167
  def safely
169
168
  yield
170
- rescue => e
169
+ rescue StandardError => e
171
170
  errmsg(e.message)
172
171
  end
173
172
  end
@@ -1,14 +1,12 @@
1
- require 'byebug/processors/command_processor'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command_processor"
2
4
 
3
5
  module Byebug
4
6
  #
5
7
  # Processes commands when there's not program running
6
8
  #
7
9
  class ControlProcessor < CommandProcessor
8
- def initialize(context = nil)
9
- @context = context
10
- end
11
-
12
10
  #
13
11
  # Available commands
14
12
  #
@@ -20,7 +18,7 @@ module Byebug
20
18
  # Prompt shown before reading a command.
21
19
  #
22
20
  def prompt
23
- '(byebug:ctrl) '
21
+ "(byebug:ctrl) "
24
22
  end
25
23
  end
26
24
  end
@@ -1,4 +1,6 @@
1
- require 'byebug/processors/command_processor'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command_processor"
2
4
 
3
5
  module Byebug
4
6
  #
@@ -10,7 +12,7 @@ module Byebug
10
12
  end
11
13
 
12
14
  def prompt
13
- '(byebug:post_mortem) '
15
+ "(byebug:post_mortem) "
14
16
  end
15
17
  end
16
18
  end
@@ -1,4 +1,6 @@
1
- require 'byebug/processors/command_processor'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command_processor"
2
4
 
3
5
  module Byebug
4
6
  #
@@ -24,6 +26,8 @@ module Byebug
24
26
  end
25
27
 
26
28
  def after_repl
29
+ super
30
+
27
31
  interface.close
28
32
  end
29
33
 
@@ -31,14 +35,14 @@ module Byebug
31
35
  # Prompt shown before reading a command.
32
36
  #
33
37
  def prompt
34
- '(byebug:ctrl) '
38
+ "(byebug:ctrl) "
35
39
  end
36
40
 
37
41
  private
38
42
 
39
43
  def without_exceptions
40
44
  yield
41
- rescue
45
+ rescue StandardError
42
46
  nil
43
47
  end
44
48
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+
5
+ module Byebug
6
+ module Remote
7
+ #
8
+ # Client for remote debugging
9
+ #
10
+ class Client
11
+ attr_reader :interface, :socket
12
+
13
+ def initialize(interface)
14
+ @interface = interface
15
+ @socket = nil
16
+ end
17
+
18
+ #
19
+ # Connects to the remote byebug
20
+ #
21
+ def start(host = "localhost", port = PORT)
22
+ connect_at(host, port)
23
+
24
+ while (line = socket.gets)
25
+ case line
26
+ when /^PROMPT (.*)$/
27
+ input = interface.read_command(Regexp.last_match[1])
28
+ break unless input
29
+
30
+ socket.puts input
31
+ when /^CONFIRM (.*)$/
32
+ input = interface.readline(Regexp.last_match[1])
33
+ break unless input
34
+
35
+ socket.puts input
36
+ else
37
+ interface.puts line
38
+ end
39
+ end
40
+
41
+ socket.close
42
+ end
43
+
44
+ def started?
45
+ !socket.nil?
46
+ end
47
+
48
+ private
49
+
50
+ def connect_at(host, port)
51
+ interface.puts "Connecting to byebug server at #{host}:#{port}..."
52
+ @socket = TCPSocket.new(host, port)
53
+ interface.puts "Connected."
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+
5
+ module Byebug
6
+ module Remote
7
+ #
8
+ # Server for remote debugging
9
+ #
10
+ class Server
11
+ attr_reader :actual_port, :wait_connection
12
+
13
+ def initialize(wait_connection:, &block)
14
+ @thread = nil
15
+ @wait_connection = wait_connection
16
+ @main_loop = block
17
+ end
18
+
19
+ #
20
+ # Start the remote debugging server
21
+ #
22
+ def start(host, port)
23
+ return if @thread
24
+
25
+ if wait_connection
26
+ mutex = Mutex.new
27
+ proceed = ConditionVariable.new
28
+ end
29
+
30
+ server = TCPServer.new(host, port)
31
+ @actual_port = server.addr[1]
32
+
33
+ yield if block_given?
34
+
35
+ @thread = DebugThread.new do
36
+ while (session = server.accept)
37
+ @main_loop.call(session)
38
+
39
+ mutex.synchronize { proceed.signal } if wait_connection
40
+ end
41
+ end
42
+
43
+ mutex.synchronize { proceed.wait(mutex) } if wait_connection
44
+ end
45
+ end
46
+ end
47
+ end