runger_byebug 11.2.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.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +954 -0
  3. data/CONTRIBUTING.md +58 -0
  4. data/GUIDE.md +1806 -0
  5. data/LICENSE +23 -0
  6. data/README.md +199 -0
  7. data/exe/byebug +6 -0
  8. data/ext/byebug/breakpoint.c +521 -0
  9. data/ext/byebug/byebug.c +900 -0
  10. data/ext/byebug/byebug.h +145 -0
  11. data/ext/byebug/context.c +687 -0
  12. data/ext/byebug/extconf.rb +12 -0
  13. data/ext/byebug/locker.c +96 -0
  14. data/ext/byebug/threads.c +241 -0
  15. data/lib/byebug/attacher.rb +48 -0
  16. data/lib/byebug/breakpoint.rb +94 -0
  17. data/lib/byebug/command.rb +111 -0
  18. data/lib/byebug/command_list.rb +34 -0
  19. data/lib/byebug/commands/break.rb +114 -0
  20. data/lib/byebug/commands/catch.rb +78 -0
  21. data/lib/byebug/commands/condition.rb +55 -0
  22. data/lib/byebug/commands/continue.rb +68 -0
  23. data/lib/byebug/commands/debug.rb +38 -0
  24. data/lib/byebug/commands/delete.rb +55 -0
  25. data/lib/byebug/commands/disable/breakpoints.rb +42 -0
  26. data/lib/byebug/commands/disable/display.rb +43 -0
  27. data/lib/byebug/commands/disable.rb +33 -0
  28. data/lib/byebug/commands/display.rb +66 -0
  29. data/lib/byebug/commands/down.rb +45 -0
  30. data/lib/byebug/commands/edit.rb +69 -0
  31. data/lib/byebug/commands/enable/breakpoints.rb +42 -0
  32. data/lib/byebug/commands/enable/display.rb +43 -0
  33. data/lib/byebug/commands/enable.rb +33 -0
  34. data/lib/byebug/commands/finish.rb +57 -0
  35. data/lib/byebug/commands/frame.rb +57 -0
  36. data/lib/byebug/commands/help.rb +64 -0
  37. data/lib/byebug/commands/history.rb +39 -0
  38. data/lib/byebug/commands/info/breakpoints.rb +65 -0
  39. data/lib/byebug/commands/info/display.rb +49 -0
  40. data/lib/byebug/commands/info/file.rb +80 -0
  41. data/lib/byebug/commands/info/line.rb +35 -0
  42. data/lib/byebug/commands/info/program.rb +49 -0
  43. data/lib/byebug/commands/info.rb +37 -0
  44. data/lib/byebug/commands/interrupt.rb +34 -0
  45. data/lib/byebug/commands/irb.rb +50 -0
  46. data/lib/byebug/commands/kill.rb +45 -0
  47. data/lib/byebug/commands/list.rb +159 -0
  48. data/lib/byebug/commands/method.rb +53 -0
  49. data/lib/byebug/commands/next.rb +40 -0
  50. data/lib/byebug/commands/pry.rb +41 -0
  51. data/lib/byebug/commands/quit.rb +42 -0
  52. data/lib/byebug/commands/restart.rb +64 -0
  53. data/lib/byebug/commands/save.rb +72 -0
  54. data/lib/byebug/commands/set.rb +79 -0
  55. data/lib/byebug/commands/show.rb +45 -0
  56. data/lib/byebug/commands/skip.rb +85 -0
  57. data/lib/byebug/commands/source.rb +40 -0
  58. data/lib/byebug/commands/step.rb +40 -0
  59. data/lib/byebug/commands/thread/current.rb +37 -0
  60. data/lib/byebug/commands/thread/list.rb +43 -0
  61. data/lib/byebug/commands/thread/resume.rb +45 -0
  62. data/lib/byebug/commands/thread/stop.rb +43 -0
  63. data/lib/byebug/commands/thread/switch.rb +46 -0
  64. data/lib/byebug/commands/thread.rb +34 -0
  65. data/lib/byebug/commands/tracevar.rb +54 -0
  66. data/lib/byebug/commands/undisplay.rb +51 -0
  67. data/lib/byebug/commands/untracevar.rb +36 -0
  68. data/lib/byebug/commands/up.rb +45 -0
  69. data/lib/byebug/commands/var/all.rb +41 -0
  70. data/lib/byebug/commands/var/args.rb +39 -0
  71. data/lib/byebug/commands/var/const.rb +49 -0
  72. data/lib/byebug/commands/var/global.rb +37 -0
  73. data/lib/byebug/commands/var/instance.rb +39 -0
  74. data/lib/byebug/commands/var/local.rb +39 -0
  75. data/lib/byebug/commands/var.rb +37 -0
  76. data/lib/byebug/commands/where.rb +64 -0
  77. data/lib/byebug/commands.rb +40 -0
  78. data/lib/byebug/context.rb +157 -0
  79. data/lib/byebug/core.rb +115 -0
  80. data/lib/byebug/errors.rb +29 -0
  81. data/lib/byebug/frame.rb +185 -0
  82. data/lib/byebug/helpers/bin.rb +47 -0
  83. data/lib/byebug/helpers/eval.rb +134 -0
  84. data/lib/byebug/helpers/file.rb +63 -0
  85. data/lib/byebug/helpers/frame.rb +75 -0
  86. data/lib/byebug/helpers/parse.rb +80 -0
  87. data/lib/byebug/helpers/path.rb +40 -0
  88. data/lib/byebug/helpers/reflection.rb +19 -0
  89. data/lib/byebug/helpers/string.rb +33 -0
  90. data/lib/byebug/helpers/thread.rb +67 -0
  91. data/lib/byebug/helpers/toggle.rb +62 -0
  92. data/lib/byebug/helpers/var.rb +70 -0
  93. data/lib/byebug/history.rb +130 -0
  94. data/lib/byebug/interface.rb +146 -0
  95. data/lib/byebug/interfaces/local_interface.rb +63 -0
  96. data/lib/byebug/interfaces/remote_interface.rb +50 -0
  97. data/lib/byebug/interfaces/script_interface.rb +33 -0
  98. data/lib/byebug/interfaces/test_interface.rb +67 -0
  99. data/lib/byebug/option_setter.rb +95 -0
  100. data/lib/byebug/printers/base.rb +68 -0
  101. data/lib/byebug/printers/plain.rb +44 -0
  102. data/lib/byebug/printers/texts/base.yml +115 -0
  103. data/lib/byebug/printers/texts/plain.yml +33 -0
  104. data/lib/byebug/processors/command_processor.rb +173 -0
  105. data/lib/byebug/processors/control_processor.rb +24 -0
  106. data/lib/byebug/processors/post_mortem_processor.rb +18 -0
  107. data/lib/byebug/processors/script_processor.rb +49 -0
  108. data/lib/byebug/remote/client.rb +57 -0
  109. data/lib/byebug/remote/server.rb +47 -0
  110. data/lib/byebug/remote.rb +85 -0
  111. data/lib/byebug/runner.rb +198 -0
  112. data/lib/byebug/setting.rb +79 -0
  113. data/lib/byebug/settings/autoirb.rb +29 -0
  114. data/lib/byebug/settings/autolist.rb +29 -0
  115. data/lib/byebug/settings/autopry.rb +29 -0
  116. data/lib/byebug/settings/autosave.rb +17 -0
  117. data/lib/byebug/settings/basename.rb +16 -0
  118. data/lib/byebug/settings/callstyle.rb +20 -0
  119. data/lib/byebug/settings/fullpath.rb +16 -0
  120. data/lib/byebug/settings/histfile.rb +20 -0
  121. data/lib/byebug/settings/histsize.rb +20 -0
  122. data/lib/byebug/settings/linetrace.rb +22 -0
  123. data/lib/byebug/settings/listsize.rb +21 -0
  124. data/lib/byebug/settings/post_mortem.rb +27 -0
  125. data/lib/byebug/settings/savefile.rb +20 -0
  126. data/lib/byebug/settings/stack_on_error.rb +15 -0
  127. data/lib/byebug/settings/width.rb +20 -0
  128. data/lib/byebug/source_file_formatter.rb +71 -0
  129. data/lib/byebug/subcommands.rb +54 -0
  130. data/lib/byebug/version.rb +8 -0
  131. data/lib/byebug.rb +3 -0
  132. metadata +194 -0
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ module Helpers
5
+ #
6
+ # Utilities for thread subcommands
7
+ #
8
+ module ThreadHelper
9
+ def display_context(ctx)
10
+ puts pr("thread.context", thread_arguments(ctx))
11
+ end
12
+
13
+ def thread_arguments(ctx)
14
+ {
15
+ status_flag: status_flag(ctx),
16
+ debug_flag: debug_flag(ctx),
17
+ id: ctx.thnum,
18
+ thread: ctx.thread.inspect,
19
+ file_line: location(ctx),
20
+ pid: Process.pid,
21
+ status: ctx.thread.status,
22
+ current: current_thread?(ctx)
23
+ }
24
+ end
25
+
26
+ def current_thread?(ctx)
27
+ ctx.thread == Thread.current
28
+ end
29
+
30
+ def context_from_thread(thnum)
31
+ ctx = Byebug.contexts.find { |c| c.thnum.to_s == thnum }
32
+
33
+ err = if ctx.nil?
34
+ pr("thread.errors.no_thread")
35
+ elsif ctx == context
36
+ pr("thread.errors.current_thread")
37
+ elsif ctx.ignored?
38
+ pr("thread.errors.ignored", arg: thnum)
39
+ end
40
+
41
+ [ctx, err]
42
+ end
43
+
44
+ private
45
+
46
+ # @todo Check whether it is Byebug.current_context or context
47
+ def location(ctx)
48
+ return context.location if ctx == Byebug.current_context
49
+
50
+ backtrace = ctx.thread.backtrace_locations
51
+ return "" unless backtrace && backtrace[0]
52
+
53
+ "#{backtrace[0].path}:#{backtrace[0].lineno}"
54
+ end
55
+
56
+ def status_flag(ctx)
57
+ return "$" if ctx.suspended?
58
+
59
+ current_thread?(ctx) ? "+" : " "
60
+ end
61
+
62
+ def debug_flag(ctx)
63
+ ctx.ignored? ? "!" : " "
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "parse"
4
+
5
+ module Byebug
6
+ module Helpers
7
+ #
8
+ # Utilities to assist breakpoint/display enabling/disabling.
9
+ #
10
+ module ToggleHelper
11
+ include ParseHelper
12
+
13
+ def enable_disable_breakpoints(is_enable, args)
14
+ raise pr("toggle.errors.no_breakpoints") if Breakpoint.none?
15
+
16
+ select_breakpoints(is_enable, args).each do |b|
17
+ enabled = (is_enable == "enable")
18
+ raise pr("toggle.errors.expression", expr: b.expr) if enabled && !syntax_valid?(b.expr)
19
+
20
+ puts pr("toggle.messages.toggled", bpnum: b.id,
21
+ endis: enabled ? "en" : "dis")
22
+ b.enabled = enabled
23
+ end
24
+ end
25
+
26
+ def enable_disable_display(is_enable, args)
27
+ raise pr("toggle.errors.no_display") if n_displays.zero?
28
+
29
+ selected_displays = args ? args.split(/ +/) : [1..n_displays + 1]
30
+
31
+ selected_displays.each do |pos|
32
+ pos, err = get_int(pos, "#{is_enable} display", 1, n_displays)
33
+ raise err unless err.nil?
34
+
35
+ Byebug.displays[pos - 1][0] = (is_enable == "enable")
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def select_breakpoints(is_enable, args)
42
+ all_breakpoints = Byebug.breakpoints.sort_by(&:id)
43
+ return all_breakpoints if args.nil?
44
+
45
+ selected_ids = []
46
+ args.split(/ +/).each do |pos|
47
+ last_id = all_breakpoints.last.id
48
+ pos, err = get_int(pos, "#{is_enable} breakpoints", 1, last_id)
49
+ raise(ArgumentError, err) unless pos
50
+
51
+ selected_ids << pos
52
+ end
53
+
54
+ all_breakpoints.select { |b| selected_ids.include?(b.id) }
55
+ end
56
+
57
+ def n_displays
58
+ Byebug.displays.size
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "eval"
4
+
5
+ module Byebug
6
+ module Helpers
7
+ #
8
+ # Utilities for variable subcommands
9
+ #
10
+ module VarHelper
11
+ include EvalHelper
12
+
13
+ def var_list(ary, binding = context.frame._binding)
14
+ vars = ary.sort.map do |name|
15
+ code = name.to_s
16
+
17
+ if code == "$SAFE" && Gem.ruby_version >= Gem::Version.new("2.7.0.preview3")
18
+ code = <<~RUBY
19
+ original_stderr = $stderr
20
+
21
+ begin
22
+ $stderr = StringIO.new
23
+
24
+ #{code}
25
+ ensure
26
+ $stderr = original_stderr
27
+ end
28
+ RUBY
29
+ end
30
+
31
+ [name, safe_inspect(silent_eval(code, binding))]
32
+ end
33
+
34
+ puts prv(vars, "instance")
35
+ end
36
+
37
+ def var_global
38
+ globals = global_variables.reject do |v|
39
+ %i[$IGNORECASE $= $KCODE $-K $binding].include?(v)
40
+ end
41
+
42
+ var_list(globals)
43
+ end
44
+
45
+ def var_instance(str)
46
+ obj = warning_eval(str || "self")
47
+
48
+ var_list(obj.instance_variables, obj.instance_eval { binding })
49
+ end
50
+
51
+ def var_local
52
+ locals = context.frame.locals
53
+ cur_self = context.frame._self
54
+ locals[:self] = cur_self unless cur_self.to_s == "main"
55
+ puts prv(locals.keys.sort.map { |k| [k, locals[k]] }, "instance")
56
+ end
57
+
58
+ def var_args
59
+ args = context.frame.args
60
+ return if args == [[:rest]]
61
+
62
+ all_locals = context.frame.locals
63
+ arg_values = args.map { |arg| arg[1] }
64
+
65
+ locals = all_locals.select { |k, _| arg_values.include?(k) }
66
+ puts prv(locals.keys.sort.map { |k| [k, locals[k]] }, "instance")
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "readline"
5
+ rescue LoadError
6
+ warn <<-MESSAGE
7
+ Sorry, you can't use byebug without Readline. To solve this, you need to
8
+ rebuild Ruby with Readline support. If using Ubuntu, try `sudo apt-get
9
+ install libreadline-dev` and then reinstall your Ruby.
10
+ MESSAGE
11
+
12
+ raise
13
+ end
14
+
15
+ module Byebug
16
+ #
17
+ # Handles byebug's history of commands.
18
+ #
19
+ class History
20
+ attr_reader :size
21
+
22
+ def initialize
23
+ @size = 0
24
+ end
25
+
26
+ #
27
+ # Array holding the list of commands in history
28
+ #
29
+ def buffer
30
+ Readline::HISTORY.to_a
31
+ end
32
+
33
+ #
34
+ # Restores history from disk.
35
+ #
36
+ def restore
37
+ return unless File.exist?(Setting[:histfile])
38
+
39
+ File.readlines(Setting[:histfile]).reverse_each { |l| push(l.chomp) }
40
+ end
41
+
42
+ #
43
+ # Saves history to disk.
44
+ #
45
+ def save
46
+ n_cmds = Setting[:histsize] > size ? size : Setting[:histsize]
47
+
48
+ File.open(Setting[:histfile], "w") do |file|
49
+ n_cmds.times { file.puts(pop) }
50
+ end
51
+
52
+ clear
53
+ end
54
+
55
+ #
56
+ # Discards history.
57
+ #
58
+ def clear
59
+ size.times { pop }
60
+ end
61
+
62
+ #
63
+ # Adds a new command to Readline's history.
64
+ #
65
+ def push(cmd)
66
+ return if ignore?(cmd)
67
+
68
+ @size += 1
69
+ Readline::HISTORY.push(cmd)
70
+ end
71
+
72
+ #
73
+ # Removes a command from Readline's history.
74
+ #
75
+ def pop
76
+ @size -= 1
77
+ Readline::HISTORY.pop
78
+ end
79
+
80
+ #
81
+ # Prints the requested numbers of history entries.
82
+ #
83
+ def to_s(n_cmds)
84
+ show_size = n_cmds ? specific_max_size(n_cmds) : default_max_size
85
+
86
+ commands = buffer.last(show_size)
87
+
88
+ last_ids(show_size).zip(commands).map do |l|
89
+ format("%<position>5d %<command>s", position: l[0], command: l[1])
90
+ end.join("\n") + "\n"
91
+ end
92
+
93
+ #
94
+ # Array of ids of the last +number+ commands.
95
+ #
96
+ def last_ids(number)
97
+ (1 + size - number..size).to_a
98
+ end
99
+
100
+ #
101
+ # Max number of commands to be displayed when no size has been specified.
102
+ #
103
+ # Never more than Setting[:histsize].
104
+ #
105
+ def default_max_size
106
+ [Setting[:histsize], size].min
107
+ end
108
+
109
+ #
110
+ # Max number of commands to be displayed when a size has been specified.
111
+ #
112
+ # The only bound here is not showing more items than available.
113
+ #
114
+ def specific_max_size(number)
115
+ [size, number].min
116
+ end
117
+
118
+ #
119
+ # Whether a specific command should not be stored in history.
120
+ #
121
+ # For now, empty lines and consecutive duplicates.
122
+ #
123
+ def ignore?(buf)
124
+ return true if /^\s*$/.match?(buf)
125
+ return false if Readline::HISTORY.empty?
126
+
127
+ buffer[Readline::HISTORY.length - 1] == buf
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setting"
4
+ require_relative "history"
5
+ require_relative "helpers/file"
6
+
7
+ #
8
+ # Namespace for all of byebug's code
9
+ #
10
+ module Byebug
11
+ #
12
+ # Main Interface class
13
+ #
14
+ # Contains common functionality to all implemented interfaces.
15
+ #
16
+ class Interface
17
+ include Helpers::FileHelper
18
+
19
+ attr_accessor :command_queue, :history
20
+ attr_reader :input, :output, :error
21
+
22
+ def initialize
23
+ @command_queue = []
24
+ @history = History.new
25
+ @last_line = ""
26
+ end
27
+
28
+ def last_if_empty(input)
29
+ @last_line = input.empty? ? @last_line : input
30
+ end
31
+
32
+ #
33
+ # Pops a command from the input stream.
34
+ #
35
+ def read_command(prompt)
36
+ return command_queue.shift unless command_queue.empty?
37
+
38
+ read_input(prompt)
39
+ end
40
+
41
+ #
42
+ # Pushes lines in +filename+ to the command queue.
43
+ #
44
+ def read_file(filename)
45
+ command_queue.concat(get_lines(filename))
46
+ end
47
+
48
+ #
49
+ # Reads a new line from the interface's input stream, parses it into
50
+ # commands and saves it to history.
51
+ #
52
+ # @return [String] Representing something to be run by the debugger.
53
+ #
54
+ def read_input(prompt, save_hist = true)
55
+ line = prepare_input(prompt)
56
+ return unless line
57
+
58
+ history.push(line) if save_hist
59
+
60
+ command_queue.concat(split_commands(line))
61
+ command_queue.shift
62
+ end
63
+
64
+ #
65
+ # Reads a new line from the interface's input stream.
66
+ #
67
+ # @return [String] New string read or the previous string if the string
68
+ # read now was empty.
69
+ #
70
+ def prepare_input(prompt)
71
+ line = readline(prompt)
72
+ return unless line
73
+
74
+ last_if_empty(line)
75
+ end
76
+
77
+ #
78
+ # Prints an error message to the error stream.
79
+ #
80
+ def errmsg(message)
81
+ error.print("*** #{message}\n")
82
+ end
83
+
84
+ #
85
+ # Prints an output message to the output stream.
86
+ #
87
+ def puts(message)
88
+ output.puts(message)
89
+ end
90
+
91
+ #
92
+ # Prints an output message to the output stream without a final "\n".
93
+ #
94
+ def print(message)
95
+ output.print(message)
96
+ end
97
+
98
+ #
99
+ # Confirms user introduced an affirmative response to the input stream.
100
+ #
101
+ def confirm(prompt)
102
+ readline(prompt) == "y"
103
+ end
104
+
105
+ def close
106
+ end
107
+
108
+ #
109
+ # Saves or clears history according to +autosave+ setting.
110
+ #
111
+ def autosave
112
+ Setting[:autosave] ? history.save : history.clear
113
+ end
114
+
115
+ #
116
+ # Restores history according to +autosave+ setting.
117
+ #
118
+ def autorestore
119
+ history.restore if Setting[:autosave]
120
+ end
121
+
122
+ private
123
+
124
+ #
125
+ # Splits a command line of the form "cmd1 ; cmd2 ; ... ; cmdN" into an
126
+ # array of commands: [cmd1, cmd2, ..., cmdN]
127
+ #
128
+ def split_commands(cmd_line)
129
+ return [""] if cmd_line.empty?
130
+
131
+ cmd_line.split(/;/).each_with_object([]) do |v, m|
132
+ if m.empty? || m.last[-1] != "\\"
133
+ m << v.strip
134
+ next
135
+ end
136
+
137
+ m.last[-1, 1] = ""
138
+ m.last << ";" << v
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ require_relative "interfaces/local_interface"
145
+ require_relative "interfaces/script_interface"
146
+ require_relative "interfaces/remote_interface"
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Interface class for standard byebug use.
6
+ #
7
+ class LocalInterface < Interface
8
+ EOF_ALIAS = "continue"
9
+
10
+ def initialize
11
+ super()
12
+ @input = $stdin
13
+ @output = $stdout
14
+ @error = $stderr
15
+ end
16
+
17
+ #
18
+ # Reads a single line of input using Readline. If Ctrl-D is pressed, it
19
+ # returns "continue", meaning that program's execution will go on.
20
+ #
21
+ # @param prompt Prompt to be displayed.
22
+ #
23
+ def readline(prompt)
24
+ with_repl_like_sigint { without_readline_completion { Readline.readline(prompt) || EOF_ALIAS } }
25
+ end
26
+
27
+ #
28
+ # Yields the block handling Ctrl-C the following way: if pressed while
29
+ # waiting for input, the line is reset to only the prompt and we ask for
30
+ # input again.
31
+ #
32
+ # @note Any external 'INT' traps are overriden during this method.
33
+ #
34
+ def with_repl_like_sigint
35
+ orig_handler = trap("INT") { raise Interrupt }
36
+ yield
37
+ rescue Interrupt
38
+ puts("^C")
39
+ retry
40
+ ensure
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
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../history"
4
+
5
+ module Byebug
6
+ #
7
+ # Interface class for remote use of byebug.
8
+ #
9
+ class RemoteInterface < Interface
10
+ def initialize(socket)
11
+ super()
12
+ @input = socket
13
+ @output = socket
14
+ @error = socket
15
+ end
16
+
17
+ def read_command(prompt)
18
+ super("PROMPT #{prompt}")
19
+ rescue Errno::EPIPE, Errno::ECONNABORTED
20
+ "continue"
21
+ end
22
+
23
+ def confirm(prompt)
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
39
+ end
40
+
41
+ def close
42
+ output.close
43
+ end
44
+
45
+ def readline(prompt)
46
+ puts(prompt)
47
+ (input.gets || "continue").chomp
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Interface class for command execution from script files.
6
+ #
7
+ class ScriptInterface < Interface
8
+ def initialize(file, verbose = false)
9
+ super()
10
+ @verbose = verbose
11
+ @input = File.open(file)
12
+ @output = verbose ? $stdout : StringIO.new
13
+ @error = $stderr
14
+ end
15
+
16
+ def read_command(prompt)
17
+ readline(prompt, false)
18
+ end
19
+
20
+ def close
21
+ input.close
22
+ end
23
+
24
+ def readline(*)
25
+ while (result = input.gets)
26
+ output.puts "+ #{result}" if @verbose
27
+ next if /^\s*#/.match?(result)
28
+
29
+ return result.chomp
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Custom interface for easier assertions
6
+ #
7
+ class TestInterface < Interface
8
+ attr_accessor :test_block
9
+
10
+ def initialize
11
+ super()
12
+
13
+ clear
14
+ end
15
+
16
+ def errmsg(message)
17
+ error.concat(prepare(message))
18
+ end
19
+
20
+ def print(message)
21
+ output.concat(prepare(message))
22
+ end
23
+
24
+ def puts(message)
25
+ output.concat(prepare(message))
26
+ end
27
+
28
+ def read_command(prompt)
29
+ cmd = super(prompt)
30
+
31
+ return cmd unless cmd.nil? && test_block
32
+
33
+ test_block.call
34
+ self.test_block = nil
35
+ end
36
+
37
+ def clear
38
+ @input = []
39
+ @output = []
40
+ @error = []
41
+ history.clear
42
+ end
43
+
44
+ def inspect
45
+ [
46
+ "Input:", input.join("\n"),
47
+ "Output:", output.join("\n"),
48
+ "Error:", error.join("\n")
49
+ ].join("\n")
50
+ end
51
+
52
+ def readline(prompt)
53
+ puts(prompt)
54
+
55
+ cmd = input.shift
56
+ cmd.is_a?(Proc) ? cmd.call : cmd
57
+ end
58
+
59
+ private
60
+
61
+ def prepare(message)
62
+ return message.map(&:to_s) if message.respond_to?(:map)
63
+
64
+ message.to_s.split("\n")
65
+ end
66
+ end
67
+ end