Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract print methods to seperate classes #854

Merged
merged 1 commit into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 11 additions & 141 deletions lib/thor/shell/basic.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
require_relative "column_printer"
require_relative "table_printer"
require_relative "wrapped_printer"

class Thor
module Shell
class Basic
DEFAULT_TERMINAL_WIDTH = 80

attr_accessor :base
attr_reader :padding

Expand Down Expand Up @@ -161,16 +163,8 @@ def no?(statement, color = nil)
# Array[String, String, ...]
#
def print_in_columns(array)
return if array.empty?
colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
array.each_with_index do |value, index|
# Don't output trailing spaces when printing the last column
if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
stdout.puts value
else
stdout.printf("%-#{colwidth}s", value)
end
end
printer = ColumnPrinter.new(stdout)
printer.print(array)
end

# Prints a table.
Expand All @@ -183,56 +177,8 @@ def print_in_columns(array)
# colwidth<Integer>:: Force the first column to colwidth spaces wide.
#
def print_table(array, options = {}) # rubocop:disable Metrics/MethodLength
return if array.empty?

formats = []
indent = options[:indent].to_i
colwidth = options[:colwidth]
options[:truncate] = terminal_width if options[:truncate] == true

formats << "%-#{colwidth + 2}s".dup if colwidth
start = colwidth ? 1 : 0

colcount = array.max { |a, b| a.size <=> b.size }.size

maximas = []

start.upto(colcount - 1) do |index|
maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
maximas << maxima
formats << if index == colcount - 1
# Don't output 2 trailing spaces when printing the last column
"%-s".dup
else
"%-#{maxima + 2}s".dup
end
end

formats[0] = formats[0].insert(0, " " * indent)
formats << "%s"

array.each do |row|
sentence = "".dup

row.each_with_index do |column, index|
maxima = maximas[index]

f = if column.is_a?(Numeric)
if index == row.size - 1
# Don't output 2 trailing spaces when printing the last column
"%#{maxima}s"
else
"%#{maxima}s "
end
else
formats[index]
end
sentence << f % column.to_s
end

sentence = truncate(sentence, options[:truncate]) if options[:truncate]
stdout.puts sentence
end
printer = TablePrinter.new(stdout, options)
printer.print(array)
end

# Prints a long string, word-wrapping the text to the current width of the
Expand All @@ -245,33 +191,8 @@ def print_table(array, options = {}) # rubocop:disable Metrics/MethodLength
# indent<Integer>:: Indent each line of the printed paragraph by indent value.
#
def print_wrapped(message, options = {})
indent = options[:indent] || 0
width = terminal_width - indent
paras = message.split("\n\n")

paras.map! do |unwrapped|
words = unwrapped.split(" ")
counter = words.first.length
words.inject do |memo, word|
word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
counter = 0 if word.include? "\n"
if (counter + word.length + 1) < width
memo = "#{memo} #{word}"
counter += (word.length + 1)
else
memo = "#{memo}\n#{word}"
counter = word.length
end
memo
end
end.compact!

paras.each do |para|
para.split("\n").each do |line|
stdout.puts line.insert(0, " " * indent)
end
stdout.puts unless para == paras.last
end
printer = WrappedPrinter.new(stdout, options)
printer.print(message)
end

# Deals with file collision and returns true if the file should be
Expand Down Expand Up @@ -321,19 +242,6 @@ def file_collision(destination)
end
end

# This code was copied from Rake, available under MIT-LICENSE
# Copyright (c) 2003, 2004 Jim Weirich
def terminal_width
result = if ENV["THOR_COLUMNS"]
ENV["THOR_COLUMNS"].to_i
else
unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
end
result < 10 ? DEFAULT_TERMINAL_WIDTH : result
rescue
DEFAULT_TERMINAL_WIDTH
end

# Called if something goes wrong during the execution. This is used by Thor
# internally and should not be used inside your scripts. If something went
# wrong, you can always raise an exception. If you raise a Thor::Error, it
Expand Down Expand Up @@ -416,46 +324,8 @@ def quiet? #:nodoc:
mute? || (base && base.options[:quiet])
end

# Calculate the dynamic width of the terminal
def dynamic_width
@dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
end

def dynamic_width_stty
`stty size 2>/dev/null`.split[1].to_i
end

def dynamic_width_tput
`tput cols 2>/dev/null`.to_i
end

def unix?
RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris)/i
end

def truncate(string, width)
as_unicode do
chars = string.chars.to_a
if chars.length <= width
chars.join
else
chars[0, width - 3].join + "..."
end
end
end

if "".respond_to?(:encode)
def as_unicode
yield
end
else
def as_unicode
old = $KCODE
$KCODE = "U"
yield
ensure
$KCODE = old
end
Terminal.unix?
end

def ask_simply(statement, color, options)
Expand Down
29 changes: 29 additions & 0 deletions lib/thor/shell/column_printer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require_relative "terminal"

class Thor
module Shell
class ColumnPrinter
attr_reader :stdout, :options

def initialize(stdout, options = {})
@stdout = stdout
@options = options
@indent = options[:indent].to_i
end

def print(array)
return if array.empty?
colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
array.each_with_index do |value, index|
# Don't output trailing spaces when printing the last column
if ((((index + 1) % (Terminal.terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
stdout.puts value
else
stdout.printf("%-#{colwidth}s", value)
end
end
end
end
end
end

95 changes: 95 additions & 0 deletions lib/thor/shell/table_printer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require_relative "column_printer"
require_relative "terminal"

class Thor
module Shell
class TablePrinter < ColumnPrinter
def initialize(stdout, options = {})
super
@formats = []
@maximas = []
@colwidth = options[:colwidth]
@truncate = options[:truncate] == true ? Terminal.terminal_width : options[:truncate]
end

def print(array)
return if array.empty?

prepare(array)

array.each do |row|
sentence = "".dup

row.each_with_index do |column, index|
maxima = @maximas[index]

f = if column.is_a?(Numeric)
if index == row.size - 1
# Don't output 2 trailing spaces when printing the last column
"%#{maxima}s"
else
"%#{maxima}s "
end
else
@formats[index]
end
sentence << f % column.to_s
end

sentence = truncate(sentence)
stdout.puts sentence
end
end

private

def prepare(array)
@formats << "%-#{@colwidth + 2}s".dup if @colwidth
start = @colwidth ? 1 : 0

colcount = array.max { |a, b| a.size <=> b.size }.size

start.upto(colcount - 1) do |index|
maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
@maximas << maxima
@formats << if index == colcount - 1
# Don't output 2 trailing spaces when printing the last column
"%-s".dup
else
"%-#{maxima + 2}s".dup
end
end

@formats[0] = @formats[0].insert(0, " " * @indent)
@formats << "%s"
end

def truncate(string)
return string unless @truncate
as_unicode do
chars = string.chars.to_a
if chars.length <= @truncate
chars.join
else
chars[0, @truncate - 3].join + "..."
end
end
end

if "".respond_to?(:encode)
def as_unicode
yield
end
else
def as_unicode
old = $KCODE # rubocop:disable Style/GlobalVars
$KCODE = "U" # rubocop:disable Style/GlobalVars
yield
ensure
$KCODE = old # rubocop:disable Style/GlobalVars
end
end
end
end
end

42 changes: 42 additions & 0 deletions lib/thor/shell/terminal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class Thor
module Shell
module Terminal
DEFAULT_TERMINAL_WIDTH = 80

class << self
# This code was copied from Rake, available under MIT-LICENSE
# Copyright (c) 2003, 2004 Jim Weirich
def terminal_width
result = if ENV["THOR_COLUMNS"]
ENV["THOR_COLUMNS"].to_i
else
unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
end
result < 10 ? DEFAULT_TERMINAL_WIDTH : result
rescue
DEFAULT_TERMINAL_WIDTH
end

def unix?
RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris)/i
end

private

# Calculate the dynamic width of the terminal
def dynamic_width
@dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
end

def dynamic_width_stty
`stty size 2>/dev/null`.split[1].to_i
end

def dynamic_width_tput
`tput cols 2>/dev/null`.to_i
end

end
end
end
end
Loading