irb 1.16.0 → 1.17.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.
- checksums.yaml +4 -4
- data/Gemfile +8 -2
- data/lib/irb/color.rb +198 -167
- data/lib/irb/command/copy.rb +11 -1
- data/lib/irb/context.rb +1 -1
- data/lib/irb/debug.rb +2 -2
- data/lib/irb/nesting_parser.rb +361 -213
- data/lib/irb/ruby-lex.rb +42 -41
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +25 -12
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a457883af2f8f76b44bca4458e71fb4260244d033ab119f0cbc828b94bce01b5
|
|
4
|
+
data.tar.gz: 22dca36785746338f9b0928fd0a16d5a36c4766f9360be937869ab7e89e01966
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 284c0962361358e0aed3f0ded870a8f2bacafe1ab52d68df26f6e97e48d92396b75e78ab7a7019fc35d555a2c4016957fe4ac3017828f506d58828d9c83df16c
|
|
7
|
+
data.tar.gz: 8417bb9569aae0a3397db838c2ca51d45be16b473ee2f986fb0c03168c8f8f5c2800d30f13bb92436c0ca6cc4ff22f70abcf33db12f647e2c157772069735e96
|
data/Gemfile
CHANGED
|
@@ -24,8 +24,14 @@ gem "debug", github: "ruby/debug"
|
|
|
24
24
|
|
|
25
25
|
gem "rdoc", ">= 6.11.0"
|
|
26
26
|
|
|
27
|
+
if ENV['PRISM_VERSION'] == 'latest'
|
|
28
|
+
gem "prism", github: "ruby/prism"
|
|
29
|
+
elsif ENV['PRISM_VERSION']
|
|
30
|
+
gem "prism", ENV['PRISM_VERSION']
|
|
31
|
+
else
|
|
32
|
+
gem "prism", "!= 1.8.0"
|
|
33
|
+
end
|
|
34
|
+
|
|
27
35
|
if RUBY_VERSION >= "3.0.0" && !is_truffleruby
|
|
28
|
-
# TODO: Remove this after rbs is released with tsort in its dependencies
|
|
29
|
-
gem "rbs", github: "ruby/rbs" if RUBY_VERSION >= "3.2"
|
|
30
36
|
gem "repl_type_completor"
|
|
31
37
|
end
|
data/lib/irb/color.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'reline'
|
|
3
|
-
require '
|
|
3
|
+
require 'prism'
|
|
4
4
|
require_relative 'ruby-lex'
|
|
5
5
|
|
|
6
6
|
module IRB # :nodoc:
|
|
@@ -18,65 +18,100 @@ module IRB # :nodoc:
|
|
|
18
18
|
CYAN = 36
|
|
19
19
|
WHITE = 37
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
21
|
+
# Following pry's colors where possible
|
|
22
|
+
TOKEN_SEQS = {
|
|
23
|
+
KEYWORD_NIL: [CYAN, BOLD],
|
|
24
|
+
KEYWORD_SELF: [CYAN, BOLD],
|
|
25
|
+
KEYWORD_TRUE: [CYAN, BOLD],
|
|
26
|
+
KEYWORD_FALSE: [CYAN, BOLD],
|
|
27
|
+
KEYWORD___FILE__: [CYAN, BOLD],
|
|
28
|
+
KEYWORD___LINE__: [CYAN, BOLD],
|
|
29
|
+
KEYWORD___ENCODING__: [CYAN, BOLD],
|
|
30
|
+
CHARACTER_LITERAL: [BLUE, BOLD],
|
|
31
|
+
BACK_REFERENCE: [GREEN, BOLD],
|
|
32
|
+
BACKTICK: [RED, BOLD],
|
|
33
|
+
COMMENT: [BLUE, BOLD],
|
|
34
|
+
EMBDOC_BEGIN: [BLUE, BOLD],
|
|
35
|
+
EMBDOC_LINE: [BLUE, BOLD],
|
|
36
|
+
EMBDOC_END: [BLUE, BOLD],
|
|
37
|
+
CONSTANT: [BLUE, BOLD, UNDERLINE],
|
|
38
|
+
EMBEXPR_BEGIN: [RED],
|
|
39
|
+
EMBEXPR_END: [RED],
|
|
40
|
+
EMBVAR: [RED],
|
|
41
|
+
FLOAT: [MAGENTA, BOLD],
|
|
42
|
+
GLOBAL_VARIABLE: [GREEN, BOLD],
|
|
43
|
+
HEREDOC_START: [RED],
|
|
44
|
+
HEREDOC_END: [RED],
|
|
45
|
+
FLOAT_IMAGINARY: [BLUE, BOLD],
|
|
46
|
+
INTEGER_IMAGINARY: [BLUE, BOLD],
|
|
47
|
+
FLOAT_RATIONAL_IMAGINARY: [BLUE, BOLD],
|
|
48
|
+
INTEGER_RATIONAL_IMAGINARY: [BLUE, BOLD],
|
|
49
|
+
INTEGER: [BLUE, BOLD],
|
|
50
|
+
INTEGER_RATIONAL: [BLUE, BOLD],
|
|
51
|
+
FLOAT_RATIONAL: [BLUE, BOLD],
|
|
52
|
+
KEYWORD_END: [GREEN],
|
|
53
|
+
KEYWORD_CLASS: [GREEN],
|
|
54
|
+
KEYWORD_MODULE: [GREEN],
|
|
55
|
+
KEYWORD_IF: [GREEN],
|
|
56
|
+
KEYWORD_IF_MODIFIER: [GREEN],
|
|
57
|
+
KEYWORD_UNLESS_MODIFIER: [GREEN],
|
|
58
|
+
KEYWORD_WHILE_MODIFIER: [GREEN],
|
|
59
|
+
KEYWORD_UNTIL_MODIFIER: [GREEN],
|
|
60
|
+
KEYWORD_RESCUE_MODIFIER: [GREEN],
|
|
61
|
+
KEYWORD_THEN: [GREEN],
|
|
62
|
+
KEYWORD_UNLESS: [GREEN],
|
|
63
|
+
KEYWORD_ELSE: [GREEN],
|
|
64
|
+
KEYWORD_ELSIF: [GREEN],
|
|
65
|
+
KEYWORD_WHILE: [GREEN],
|
|
66
|
+
KEYWORD_UNTIL: [GREEN],
|
|
67
|
+
KEYWORD_CASE: [GREEN],
|
|
68
|
+
KEYWORD_WHEN: [GREEN],
|
|
69
|
+
KEYWORD_IN: [GREEN],
|
|
70
|
+
KEYWORD_DEF: [GREEN],
|
|
71
|
+
KEYWORD_DO: [GREEN],
|
|
72
|
+
KEYWORD_DO_LOOP: [GREEN],
|
|
73
|
+
KEYWORD_FOR: [GREEN],
|
|
74
|
+
KEYWORD_BEGIN: [GREEN],
|
|
75
|
+
KEYWORD_RESCUE: [GREEN],
|
|
76
|
+
KEYWORD_ENSURE: [GREEN],
|
|
77
|
+
KEYWORD_ALIAS: [GREEN],
|
|
78
|
+
KEYWORD_UNDEF: [GREEN],
|
|
79
|
+
KEYWORD_BEGIN_UPCASE: [GREEN],
|
|
80
|
+
KEYWORD_END_UPCASE: [GREEN],
|
|
81
|
+
KEYWORD_YIELD: [GREEN],
|
|
82
|
+
KEYWORD_REDO: [GREEN],
|
|
83
|
+
KEYWORD_RETRY: [GREEN],
|
|
84
|
+
KEYWORD_NEXT: [GREEN],
|
|
85
|
+
KEYWORD_BREAK: [GREEN],
|
|
86
|
+
KEYWORD_SUPER: [GREEN],
|
|
87
|
+
KEYWORD_RETURN: [GREEN],
|
|
88
|
+
KEYWORD_DEFINED: [GREEN],
|
|
89
|
+
KEYWORD_NOT: [GREEN],
|
|
90
|
+
KEYWORD_AND: [GREEN],
|
|
91
|
+
KEYWORD_OR: [GREEN],
|
|
92
|
+
LABEL: [MAGENTA],
|
|
93
|
+
LABEL_END: [RED, BOLD],
|
|
94
|
+
NUMBERED_REFERENCE: [GREEN, BOLD],
|
|
95
|
+
PERCENT_UPPER_W: [RED, BOLD],
|
|
96
|
+
PERCENT_LOWER_W: [RED, BOLD],
|
|
97
|
+
PERCENT_LOWER_X: [RED, BOLD],
|
|
98
|
+
REGEXP_BEGIN: [RED, BOLD],
|
|
99
|
+
REGEXP_END: [RED, BOLD],
|
|
100
|
+
STRING_BEGIN: [RED, BOLD],
|
|
101
|
+
STRING_CONTENT: [RED],
|
|
102
|
+
STRING_END: [RED, BOLD],
|
|
103
|
+
__END__: [GREEN],
|
|
104
|
+
# tokens from syntax tree traversal
|
|
105
|
+
method_name: [BLUE, BOLD],
|
|
106
|
+
symbol: [YELLOW],
|
|
107
|
+
# special colorization
|
|
108
|
+
error: [RED, REVERSE],
|
|
109
|
+
const_env: [CYAN, BOLD],
|
|
110
|
+
}.transform_values do |styles|
|
|
111
|
+
styles.map { |style| "\e[#{style}m" }.join
|
|
75
112
|
end
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
ERROR_TOKENS = TOKEN_SEQ_EXPRS.keys.select { |k| k.to_s.end_with?('error') }
|
|
79
|
-
private_constant :ERROR_TOKENS
|
|
113
|
+
CLEAR_SEQ = "\e[#{CLEAR}m"
|
|
114
|
+
private_constant :TOKEN_SEQS, :CLEAR_SEQ
|
|
80
115
|
|
|
81
116
|
class << self
|
|
82
117
|
def colorable?
|
|
@@ -113,14 +148,13 @@ module IRB # :nodoc:
|
|
|
113
148
|
end
|
|
114
149
|
|
|
115
150
|
def clear(colorable: colorable?)
|
|
116
|
-
|
|
117
|
-
"\e[#{CLEAR}m"
|
|
151
|
+
colorable ? CLEAR_SEQ : ''
|
|
118
152
|
end
|
|
119
153
|
|
|
120
154
|
def colorize(text, seq, colorable: colorable?)
|
|
121
155
|
return text unless colorable
|
|
122
156
|
seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('')
|
|
123
|
-
"#{seq}#{text}#{
|
|
157
|
+
"#{seq}#{text}#{CLEAR_SEQ}"
|
|
124
158
|
end
|
|
125
159
|
|
|
126
160
|
# If `complete` is false (code is incomplete), this does not warn compile_error.
|
|
@@ -129,135 +163,132 @@ module IRB # :nodoc:
|
|
|
129
163
|
def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, local_variables: [])
|
|
130
164
|
return code unless colorable
|
|
131
165
|
|
|
132
|
-
|
|
133
|
-
colored = +''
|
|
134
|
-
lvars_code = RubyLex.generate_local_variables_assign_code(local_variables)
|
|
135
|
-
code_with_lvars = lvars_code ? "#{lvars_code}\n#{code}" : code
|
|
166
|
+
result = Prism.parse_lex(code, scopes: [local_variables])
|
|
136
167
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
end
|
|
168
|
+
# IRB::ColorPrinter skips colorizing syntax invalid fragments
|
|
169
|
+
return Reline::Unicode.escape_for_print(code) if ignore_error && !result.success?
|
|
170
|
+
|
|
171
|
+
errors = result.errors
|
|
172
|
+
unless complete
|
|
173
|
+
errors = errors.reject { |error| error.message =~ /\Aexpected a|unexpected end-of-input|unterminated/ }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
prism_node, prism_tokens = result.value
|
|
177
|
+
visitor = ColorizeVisitor.new
|
|
178
|
+
prism_node.accept(visitor)
|
|
179
|
+
|
|
180
|
+
error_tokens = errors.map { |e| [e.location.start_line, e.location.start_column, 0, e.location.end_line, e.location.end_column, :error, e.location.slice] }
|
|
181
|
+
error_tokens.reject! { |t| t.last.match?(/\A\s*\z/) }
|
|
182
|
+
tokens = prism_tokens.map { |t,| [t.location.start_line, t.location.start_column, 2, t.location.end_line, t.location.end_column, t.type, t.value] }
|
|
183
|
+
tokens.pop if tokens.last&.[](5) == :EOF
|
|
143
184
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
185
|
+
colored = +''
|
|
186
|
+
line_index = 0
|
|
187
|
+
col = 0
|
|
188
|
+
lines = code.lines
|
|
189
|
+
flush = -> next_line_index, next_col {
|
|
190
|
+
return if next_line_index == line_index && next_col == col
|
|
191
|
+
(line_index...[next_line_index, lines.size].min).each do |ln|
|
|
192
|
+
colored << Reline::Unicode.escape_for_print(lines[line_index].byteslice(col..))
|
|
193
|
+
line_index = ln + 1
|
|
194
|
+
col = 0
|
|
195
|
+
end
|
|
196
|
+
unless col == next_col
|
|
197
|
+
colored << Reline::Unicode.escape_for_print(lines[next_line_index].byteslice(col..next_col - 1))
|
|
147
198
|
end
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
(visitor.tokens + tokens + error_tokens).sort.each do |start_line, start_column, _priority, end_line, end_column, type, value|
|
|
202
|
+
next if start_line - 1 < line_index || (start_line - 1 == line_index && start_column < col)
|
|
148
203
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
204
|
+
flush.call(start_line - 1, start_column)
|
|
205
|
+
if type == :CONSTANT && value == 'ENV'
|
|
206
|
+
color = TOKEN_SEQS[:const_env]
|
|
207
|
+
elsif type == :__END__
|
|
208
|
+
color = TOKEN_SEQS[type]
|
|
209
|
+
end_line = start_line
|
|
210
|
+
value = '__END__'
|
|
211
|
+
end_column = start_column + 7
|
|
212
|
+
else
|
|
213
|
+
color = TOKEN_SEQS[type]
|
|
214
|
+
end
|
|
215
|
+
if color
|
|
216
|
+
value.split(/(\n)/).each do |s|
|
|
217
|
+
colored << (s == "\n" ? s : "#{color}#{Reline::Unicode.escape_for_print(s)}#{CLEAR_SEQ}")
|
|
157
218
|
end
|
|
219
|
+
else
|
|
220
|
+
colored << value
|
|
158
221
|
end
|
|
222
|
+
line_index = end_line - 1
|
|
223
|
+
col = end_column
|
|
159
224
|
end
|
|
160
|
-
|
|
161
|
-
if lvars_code
|
|
162
|
-
raise "#{lvars_code.dump} should have no \\n" if lvars_code.include?("\n")
|
|
163
|
-
colored.sub!(/\A.+\n/, '') # delete_prefix lvars_code with colors
|
|
164
|
-
end
|
|
225
|
+
flush.call lines.size, 0
|
|
165
226
|
colored
|
|
166
227
|
end
|
|
167
228
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
block.call
|
|
174
|
-
ensure
|
|
175
|
-
seen.delete(obj)
|
|
176
|
-
end
|
|
229
|
+
class ColorizeVisitor < Prism::Visitor
|
|
230
|
+
attr_reader :tokens
|
|
231
|
+
def initialize
|
|
232
|
+
@tokens = []
|
|
233
|
+
end
|
|
177
234
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no)
|
|
182
|
-
byte_pos = 0
|
|
183
|
-
line_positions = [0]
|
|
184
|
-
inner_code.lines.each do |line|
|
|
185
|
-
line_positions << line_positions.last + line.bytesize
|
|
235
|
+
def dispatch(location, type)
|
|
236
|
+
if location
|
|
237
|
+
@tokens << [location.start_line, location.start_column, 1, location.end_line, location.end_column, type, location.slice]
|
|
186
238
|
end
|
|
239
|
+
end
|
|
187
240
|
|
|
188
|
-
|
|
189
|
-
|
|
241
|
+
def visit_array_node(node)
|
|
242
|
+
if node.opening&.match?(/\A%[iI]/)
|
|
243
|
+
dispatch node.opening_loc, :symbol
|
|
244
|
+
dispatch node.closing_loc, :symbol
|
|
245
|
+
end
|
|
246
|
+
super
|
|
247
|
+
end
|
|
190
248
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
249
|
+
def visit_def_node(node)
|
|
250
|
+
dispatch node.name_loc, :method_name
|
|
251
|
+
super
|
|
252
|
+
end
|
|
195
253
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
254
|
+
def visit_interpolated_symbol_node(node)
|
|
255
|
+
dispatch node.opening_loc, :symbol
|
|
256
|
+
node.parts.each do |part|
|
|
257
|
+
case part
|
|
258
|
+
when Prism::StringNode
|
|
259
|
+
dispatch part.content_loc, :symbol
|
|
260
|
+
when Prism::EmbeddedStatementsNode
|
|
261
|
+
dispatch part.opening_loc, :symbol
|
|
262
|
+
dispatch part.closing_loc, :symbol
|
|
263
|
+
when Prism::EmbeddedVariableNode
|
|
264
|
+
dispatch part.operator_loc, :symbol
|
|
200
265
|
end
|
|
201
266
|
end
|
|
267
|
+
dispatch node.closing_loc, :symbol
|
|
268
|
+
super
|
|
269
|
+
end
|
|
202
270
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
271
|
+
def visit_symbol_node(node)
|
|
272
|
+
if (node.opening_loc.nil? && node.closing == ':') || node.closing&.match?(/\A['"]:\z/)
|
|
273
|
+
# Colorize { symbol: 1 } and { 'symbol': 1 } as label
|
|
274
|
+
dispatch node.location, :LABEL
|
|
275
|
+
else
|
|
276
|
+
dispatch node.opening_loc, :symbol
|
|
277
|
+
dispatch node.value_loc, :symbol
|
|
278
|
+
dispatch node.closing_loc, :symbol
|
|
206
279
|
end
|
|
207
|
-
# yield uncolorable DATA section
|
|
208
|
-
yield(nil, inner_code.byteslice(byte_pos...inner_code.bytesize), nil) if byte_pos < inner_code.bytesize
|
|
209
280
|
end
|
|
210
|
-
ensure
|
|
211
|
-
$VERBOSE = verbose
|
|
212
281
|
end
|
|
213
282
|
|
|
214
|
-
|
|
215
|
-
if ERROR_TOKENS.include?(token)
|
|
216
|
-
TOKEN_SEQ_EXPRS[token][0]
|
|
217
|
-
elsif in_symbol
|
|
218
|
-
[YELLOW]
|
|
219
|
-
elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
|
|
220
|
-
[CYAN, BOLD]
|
|
221
|
-
elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; (expr & (exprs || 0)) != 0)
|
|
222
|
-
seq
|
|
223
|
-
else
|
|
224
|
-
nil
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
# A class to manage a state to know whether the current token is for Symbol or not.
|
|
230
|
-
class SymbolState
|
|
231
|
-
def initialize
|
|
232
|
-
# Push `true` to detect Symbol. `false` to increase the nest level for non-Symbol.
|
|
233
|
-
@stack = []
|
|
234
|
-
end
|
|
283
|
+
private
|
|
235
284
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
when :on_ident, :on_op, :on_const, :on_ivar, :on_cvar, :on_gvar, :on_kw, :on_backtick
|
|
243
|
-
if @stack.last # Pop only when it's Symbol
|
|
244
|
-
@stack.pop
|
|
245
|
-
return prev_state
|
|
246
|
-
end
|
|
247
|
-
when :on_tstring_beg
|
|
248
|
-
@stack << false
|
|
249
|
-
when :on_embexpr_beg
|
|
250
|
-
@stack << false
|
|
251
|
-
return prev_state
|
|
252
|
-
when :on_tstring_end # :on_tstring_end may close Symbol
|
|
253
|
-
@stack.pop
|
|
254
|
-
return prev_state
|
|
255
|
-
when :on_embexpr_end
|
|
256
|
-
@stack.pop
|
|
257
|
-
end
|
|
258
|
-
@stack.last
|
|
285
|
+
def without_circular_ref(obj, seen:, &block)
|
|
286
|
+
return false if seen.key?(obj)
|
|
287
|
+
seen[obj] = true
|
|
288
|
+
block.call
|
|
289
|
+
ensure
|
|
290
|
+
seen.delete(obj)
|
|
259
291
|
end
|
|
260
292
|
end
|
|
261
|
-
private_constant :SymbolState
|
|
262
293
|
end
|
|
263
294
|
end
|
data/lib/irb/command/copy.rb
CHANGED
|
@@ -54,6 +54,8 @@ module IRB
|
|
|
54
54
|
def clipboard_program
|
|
55
55
|
@clipboard_program ||= if IRB.conf[:COPY_COMMAND]
|
|
56
56
|
IRB.conf[:COPY_COMMAND]
|
|
57
|
+
elsif executable?("clip.exe")
|
|
58
|
+
"clip.exe"
|
|
57
59
|
elsif executable?("pbcopy")
|
|
58
60
|
"pbcopy"
|
|
59
61
|
elsif executable?("xclip")
|
|
@@ -62,12 +64,20 @@ module IRB
|
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
def executable?(command)
|
|
65
|
-
|
|
67
|
+
if windows?
|
|
68
|
+
system("where #{command} > NUL 2>&1")
|
|
69
|
+
else
|
|
70
|
+
system("which #{command} > /dev/null 2>&1")
|
|
71
|
+
end
|
|
66
72
|
end
|
|
67
73
|
|
|
68
74
|
def clipboard_available?
|
|
69
75
|
!!clipboard_program
|
|
70
76
|
end
|
|
77
|
+
|
|
78
|
+
def windows?
|
|
79
|
+
/mingw|mswin/.match?(RUBY_PLATFORM)
|
|
80
|
+
end
|
|
71
81
|
end
|
|
72
82
|
end
|
|
73
83
|
end
|
data/lib/irb/context.rb
CHANGED
|
@@ -649,7 +649,7 @@ module IRB
|
|
|
649
649
|
parsed_input = parse_input(input, false)
|
|
650
650
|
if parsed_input.is_a?(Statement::Command)
|
|
651
651
|
name, sep, arg = input.split(/(\s+)/, 2)
|
|
652
|
-
arg = IRB::Color.colorize_code(arg, complete: complete, local_variables: lvars)
|
|
652
|
+
arg = IRB::Color.colorize_code(arg, complete: complete, local_variables: lvars) if arg
|
|
653
653
|
"#{IRB::Color.colorize(name, [:BOLD])}\e[m#{sep}#{arg}"
|
|
654
654
|
else
|
|
655
655
|
IRB::Color.colorize_code(input, complete: complete, local_variables: lvars)
|
data/lib/irb/debug.rb
CHANGED
|
@@ -49,7 +49,7 @@ module IRB
|
|
|
49
49
|
def DEBUGGER__.capture_frames(*args)
|
|
50
50
|
frames = capture_frames_without_irb(*args)
|
|
51
51
|
frames.reject! do |frame|
|
|
52
|
-
frame.realpath&.start_with?(IRB_DIR) || frame.path
|
|
52
|
+
frame.realpath&.start_with?(IRB_DIR) || frame.path&.start_with?("<internal:")
|
|
53
53
|
end
|
|
54
54
|
frames
|
|
55
55
|
end
|
|
@@ -87,7 +87,7 @@ module IRB
|
|
|
87
87
|
module SkipPathHelperForIRB
|
|
88
88
|
def skip_internal_path?(path)
|
|
89
89
|
# The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved
|
|
90
|
-
super || path
|
|
90
|
+
super || path&.match?(IRB_DIR) || path&.match?('<internal:prelude>')
|
|
91
91
|
end
|
|
92
92
|
end
|
|
93
93
|
|