summaryrefslogtreecommitdiff
path: root/lib/irb
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2021-03-20 23:15:51 -0700
committergit <svn-admin@ruby-lang.org>2021-03-21 15:19:04 +0900
commitd0b044a842ec03525ab839eb79864899ad81bed3 (patch)
tree0478ee62d54dacd4815fdcc3006fd1d3c55d00e1 /lib/irb
parent21863470d965b8cc299b1f82417c70d5d26f8ab2 (diff)
[ruby/irb] Fix column overflow on ls output
https://github.com/ruby/irb/commit/6115754623
Diffstat (limited to 'lib/irb')
-rw-r--r--lib/irb/cmd/ls.rb45
1 files changed, 40 insertions, 5 deletions
diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb
index c39937d4db..07e6fbc487 100644
--- a/lib/irb/cmd/ls.rb
+++ b/lib/irb/cmd/ls.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+require "reline"
require_relative "nop"
require_relative "../color"
@@ -23,8 +24,11 @@ module IRB
end
class Output
+ MARGIN = " "
+
def initialize(grep: nil)
@grep = grep
+ @line_width = screen_width
end
def dump(name, strs)
@@ -32,14 +36,45 @@ module IRB
strs = strs.sort
return if strs.empty?
+ # Attempt a single line
print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
- if strs.size > 7
- len = [strs.map(&:length).max, 16].min
- puts; strs.each_slice(7) { |ss| puts " #{ss.map { |s| "%-#{len}s" % s }.join(" ")}" }
- else
- puts strs.join(" ")
+ if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
+ puts strs.join(MARGIN)
+ return
+ end
+ puts
+
+ # Dump with the largest # of columns that fits on a line
+ cols = strs.size
+ until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
+ cols -= 1
+ end
+ widths = col_widths(strs, cols: cols)
+ strs.each_slice(cols) do |ss|
+ puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
+ end
+ end
+
+ private
+
+ def fits_on_line?(strs, cols:, offset: 0)
+ width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
+ width <= @line_width - offset
+ end
+
+ def col_widths(strs, cols:)
+ cols.times.map do |col|
+ (col...strs.size).step(cols.size - 1).map do |i|
+ strs[i].length
+ end.max
end
end
+
+ def screen_width
+ Reline.get_screen_size.last
+ rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
+ 79
+ end
end
private_constant :Output
end