Skip to content

Commit c5ea79d

Browse files
committed
Add OMIT_ON_ASSIGNMENT
Omit the results evaluated at assignment if they are too long. The behavior of ECHO_ON_ASSIGNMENT being on by default is hard to understand, so I change it to off by default. Instead, we turn OMIT_ON_ASSIGNMENT on by default. The result is displayed on assignment, but it will always be short and within one line of the screen.
1 parent 9bb6562 commit c5ea79d

File tree

5 files changed

+143
-10
lines changed

5 files changed

+143
-10
lines changed

lib/irb.rb

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#
1111
#
1212
require "ripper"
13+
require "reline"
1314

1415
require_relative "irb/init"
1516
require_relative "irb/context"
@@ -538,7 +539,15 @@ def eval_input
538539
begin
539540
line.untaint if RUBY_VERSION < '2.7'
540541
@context.evaluate(line, line_no, exception: exc)
541-
output_value if @context.echo? && (@context.echo_on_assignment? || !assignment_expression?(line))
542+
if @context.echo?
543+
if assignment_expression?(line)
544+
if @context.echo_on_assignment?
545+
output_value(@context.omit_on_assignment?)
546+
end
547+
else
548+
output_value
549+
end
550+
end
542551
rescue Interrupt => exc
543552
rescue SystemExit, SignalException
544553
raise
@@ -737,9 +746,22 @@ def prompt(prompt, ltype, indent, line_no) # :nodoc:
737746
p
738747
end
739748

740-
def output_value # :nodoc:
749+
def output_value(omit = false) # :nodoc:
741750
str = @context.inspect_last_value
742751
multiline_p = str.include?("\n")
752+
if omit
753+
if multiline_p
754+
str.gsub!(/(\A.*?\n).*/m, "\\1...")
755+
else
756+
winwidth = @context.io.winsize.last
757+
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
758+
diff_size = output_width - Reline::Unicode.calculate_width(str, true)
759+
if diff_size.positive? and output_width > winwidth
760+
lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
761+
str = "%s...\e[0m" % lines.first
762+
end
763+
end
764+
end
743765
if multiline_p && @context.newline_before_multiline_output?
744766
printf @context.return_format, "\n#{str}"
745767
else

lib/irb/context.rb

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ def initialize(irb, workspace = nil, input_method = nil)
131131

132132
@echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
133133
if @echo_on_assignment.nil?
134-
@echo_on_assignment = false
134+
@echo_on_assignment = true
135+
end
136+
137+
@omit_on_assignment = IRB.conf[:OMIT_ON_ASSIGNMENT]
138+
if @omit_on_assignment.nil?
139+
@omit_on_assignment = true
135140
end
136141

137142
@newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
@@ -251,13 +256,27 @@ def main
251256
attr_accessor :echo
252257
# Whether to echo for assignment expressions
253258
#
254-
# Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +false+.
259+
# Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
255260
#
256261
# a = "omg"
257-
# IRB.CurrentContext.echo_on_assignment = true
258-
# a = "omg"
259262
# #=> omg
263+
# IRB.CurrentContext.echo_on_assignment = false
264+
# a = "omg"
260265
attr_accessor :echo_on_assignment
266+
# Whether to omit echo for assignment expressions
267+
#
268+
# Uses <code>IRB.conf[:OMIT_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
269+
#
270+
# a = [1] * 10
271+
# #=> [1, 1, 1, 1, 1, 1, 1, 1, ...
272+
# [1] * 10
273+
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
274+
# IRB.CurrentContext.omit_on_assignment = false
275+
# a = [1] * 10
276+
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
277+
# [1] * 10
278+
# #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
279+
attr_accessor :omit_on_assignment
261280
# Whether a newline is put before multiline output.
262281
#
263282
# Uses <code>IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]</code> if available,
@@ -306,6 +325,7 @@ def main
306325
alias ignore_eof? ignore_eof
307326
alias echo? echo
308327
alias echo_on_assignment? echo_on_assignment
328+
alias omit_on_assignment? omit_on_assignment
309329
alias newline_before_multiline_output? newline_before_multiline_output
310330

311331
# Returns whether messages are displayed or not.

lib/irb/init.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def IRB.init_config(ap_path)
5252
@CONF[:IGNORE_EOF] = false
5353
@CONF[:ECHO] = nil
5454
@CONF[:ECHO_ON_ASSIGNMENT] = nil
55+
@CONF[:OMIT_ON_ASSIGNMENT] = nil
5556
@CONF[:VERBOSE] = nil
5657

5758
@CONF[:EVAL_HISTORY] = nil
@@ -177,6 +178,10 @@ def IRB.parse_opts(argv: ::ARGV)
177178
@CONF[:ECHO_ON_ASSIGNMENT] = true
178179
when "--noecho-on-assignment"
179180
@CONF[:ECHO_ON_ASSIGNMENT] = false
181+
when "--omit-on-assignment"
182+
@CONF[:OMIT_ON_ASSIGNMENT] = true
183+
when "--noomit-on-assignment"
184+
@CONF[:OMIT_ON_ASSIGNMENT] = false
180185
when "--verbose"
181186
@CONF[:VERBOSE] = true
182187
when "--noverbose"

lib/irb/input-method.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require_relative 'src_encoding'
1313
require_relative 'magic-file'
1414
require_relative 'completion'
15+
require 'io/console'
1516
require 'reline'
1617

1718
module IRB
@@ -36,6 +37,14 @@ def gets
3637
end
3738
public :gets
3839

40+
def winsize
41+
if instance_variable_defined?(:@stdout)
42+
@stdout.winsize
43+
else
44+
[24, 80]
45+
end
46+
end
47+
3948
# Whether this input method is still readable when there is no more data to
4049
# read.
4150
#

test/irb/test_context.rb

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ def encoding
3030
def reset
3131
@line_no = 0
3232
end
33+
34+
def winsize
35+
[10, 20]
36+
end
3337
end
3438

3539
def setup
@@ -213,6 +217,75 @@ def test_echo_on_assignment
213217
assert_equal("", out)
214218
end
215219

220+
def test_omit_on_assignment
221+
input = TestInputMethod.new([
222+
"a = [1] * 100\n",
223+
"a\n",
224+
])
225+
value = [1] * 100
226+
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
227+
irb.context.return_format = "=> %s\n"
228+
229+
irb.context.echo = true
230+
irb.context.echo_on_assignment = false
231+
irb.context.omit_on_assignment = true
232+
out, err = capture_io do
233+
irb.eval_input
234+
end
235+
assert_empty err
236+
assert_equal("=> #{value.inspect}\n", out)
237+
238+
input.reset
239+
irb.context.echo = true
240+
irb.context.echo_on_assignment = true
241+
irb.context.omit_on_assignment = true
242+
out, err = capture_io do
243+
irb.eval_input
244+
end
245+
assert_empty err
246+
assert_equal("=> #{value.inspect[0..(input.winsize.last - 9)]}...\e[0m\n=> #{value.inspect}\n", out)
247+
248+
input.reset
249+
irb.context.echo = true
250+
irb.context.echo_on_assignment = true
251+
irb.context.omit_on_assignment = false
252+
out, err = capture_io do
253+
irb.eval_input
254+
end
255+
assert_empty err
256+
assert_equal("=> #{value.inspect}\n=> #{value.inspect}\n", out)
257+
258+
input.reset
259+
irb.context.echo = false
260+
irb.context.echo_on_assignment = false
261+
irb.context.omit_on_assignment = true
262+
out, err = capture_io do
263+
irb.eval_input
264+
end
265+
assert_empty err
266+
assert_equal("", out)
267+
268+
input.reset
269+
irb.context.echo = false
270+
irb.context.echo_on_assignment = true
271+
irb.context.omit_on_assignment = true
272+
out, err = capture_io do
273+
irb.eval_input
274+
end
275+
assert_empty err
276+
assert_equal("", out)
277+
278+
input.reset
279+
irb.context.echo = false
280+
irb.context.echo_on_assignment = true
281+
irb.context.omit_on_assignment = false
282+
out, err = capture_io do
283+
irb.eval_input
284+
end
285+
assert_empty err
286+
assert_equal("", out)
287+
end
288+
216289
def test_echo_on_assignment_conf
217290
# Default
218291
IRB.conf[:ECHO] = nil
@@ -221,22 +294,26 @@ def test_echo_on_assignment_conf
221294
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
222295

223296
assert(irb.context.echo?, "echo? should be true by default")
224-
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false by default")
297+
assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true by default")
298+
assert(irb.context.omit_on_assignment?, "omit_on_assignment? should be true by default")
225299

226300
# Explicitly set :ECHO to false
227301
IRB.conf[:ECHO] = false
228302
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
229303

230304
refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
231-
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false by default")
305+
assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true by default")
306+
assert(irb.context.omit_on_assignment?, "omit_on_assignment? should be true by default")
232307

233308
# Explicitly set :ECHO_ON_ASSIGNMENT to true
234309
IRB.conf[:ECHO] = nil
235-
IRB.conf[:ECHO_ON_ASSIGNMENT] = true
310+
IRB.conf[:ECHO_ON_ASSIGNMENT] = false
311+
IRB.conf[:OMIT_ON_ASSIGNMENT] = false
236312
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
237313

238314
assert(irb.context.echo?, "echo? should be true by default")
239-
assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to true")
315+
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false")
316+
refute(irb.context.omit_on_assignment?, "omit_on_assignment? should be false when IRB.conf[:OMIT_ON_ASSIGNMENT] is set to false")
240317
end
241318

242319
def test_multiline_output_on_default_inspector

0 commit comments

Comments
 (0)