Skip to content

Commit 9c9ab52

Browse files
authored
Merge pull request #854 from p8/refactor/extract-printers
Extract print methods to seperate classes
2 parents f98f4a9 + 580234a commit 9c9ab52

File tree

7 files changed

+217
-144
lines changed

7 files changed

+217
-144
lines changed

lib/thor/shell/basic.rb

Lines changed: 11 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
require_relative "column_printer"
2+
require_relative "table_printer"
3+
require_relative "wrapped_printer"
4+
15
class Thor
26
module Shell
37
class Basic
4-
DEFAULT_TERMINAL_WIDTH = 80
5-
68
attr_accessor :base
79
attr_reader :padding
810

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

176170
# Prints a table.
@@ -183,56 +177,8 @@ def print_in_columns(array)
183177
# colwidth<Integer>:: Force the first column to colwidth spaces wide.
184178
#
185179
def print_table(array, options = {}) # rubocop:disable Metrics/MethodLength
186-
return if array.empty?
187-
188-
formats = []
189-
indent = options[:indent].to_i
190-
colwidth = options[:colwidth]
191-
options[:truncate] = terminal_width if options[:truncate] == true
192-
193-
formats << "%-#{colwidth + 2}s".dup if colwidth
194-
start = colwidth ? 1 : 0
195-
196-
colcount = array.max { |a, b| a.size <=> b.size }.size
197-
198-
maximas = []
199-
200-
start.upto(colcount - 1) do |index|
201-
maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
202-
maximas << maxima
203-
formats << if index == colcount - 1
204-
# Don't output 2 trailing spaces when printing the last column
205-
"%-s".dup
206-
else
207-
"%-#{maxima + 2}s".dup
208-
end
209-
end
210-
211-
formats[0] = formats[0].insert(0, " " * indent)
212-
formats << "%s"
213-
214-
array.each do |row|
215-
sentence = "".dup
216-
217-
row.each_with_index do |column, index|
218-
maxima = maximas[index]
219-
220-
f = if column.is_a?(Numeric)
221-
if index == row.size - 1
222-
# Don't output 2 trailing spaces when printing the last column
223-
"%#{maxima}s"
224-
else
225-
"%#{maxima}s "
226-
end
227-
else
228-
formats[index]
229-
end
230-
sentence << f % column.to_s
231-
end
232-
233-
sentence = truncate(sentence, options[:truncate]) if options[:truncate]
234-
stdout.puts sentence
235-
end
180+
printer = TablePrinter.new(stdout, options)
181+
printer.print(array)
236182
end
237183

238184
# Prints a long string, word-wrapping the text to the current width of the
@@ -245,33 +191,8 @@ def print_table(array, options = {}) # rubocop:disable Metrics/MethodLength
245191
# indent<Integer>:: Indent each line of the printed paragraph by indent value.
246192
#
247193
def print_wrapped(message, options = {})
248-
indent = options[:indent] || 0
249-
width = terminal_width - indent
250-
paras = message.split("\n\n")
251-
252-
paras.map! do |unwrapped|
253-
words = unwrapped.split(" ")
254-
counter = words.first.length
255-
words.inject do |memo, word|
256-
word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
257-
counter = 0 if word.include? "\n"
258-
if (counter + word.length + 1) < width
259-
memo = "#{memo} #{word}"
260-
counter += (word.length + 1)
261-
else
262-
memo = "#{memo}\n#{word}"
263-
counter = word.length
264-
end
265-
memo
266-
end
267-
end.compact!
268-
269-
paras.each do |para|
270-
para.split("\n").each do |line|
271-
stdout.puts line.insert(0, " " * indent)
272-
end
273-
stdout.puts unless para == paras.last
274-
end
194+
printer = WrappedPrinter.new(stdout, options)
195+
printer.print(message)
275196
end
276197

277198
# Deals with file collision and returns true if the file should be
@@ -321,19 +242,6 @@ def file_collision(destination)
321242
end
322243
end
323244

324-
# This code was copied from Rake, available under MIT-LICENSE
325-
# Copyright (c) 2003, 2004 Jim Weirich
326-
def terminal_width
327-
result = if ENV["THOR_COLUMNS"]
328-
ENV["THOR_COLUMNS"].to_i
329-
else
330-
unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
331-
end
332-
result < 10 ? DEFAULT_TERMINAL_WIDTH : result
333-
rescue
334-
DEFAULT_TERMINAL_WIDTH
335-
end
336-
337245
# Called if something goes wrong during the execution. This is used by Thor
338246
# internally and should not be used inside your scripts. If something went
339247
# wrong, you can always raise an exception. If you raise a Thor::Error, it
@@ -416,46 +324,8 @@ def quiet? #:nodoc:
416324
mute? || (base && base.options[:quiet])
417325
end
418326

419-
# Calculate the dynamic width of the terminal
420-
def dynamic_width
421-
@dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
422-
end
423-
424-
def dynamic_width_stty
425-
`stty size 2>/dev/null`.split[1].to_i
426-
end
427-
428-
def dynamic_width_tput
429-
`tput cols 2>/dev/null`.to_i
430-
end
431-
432327
def unix?
433-
RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris)/i
434-
end
435-
436-
def truncate(string, width)
437-
as_unicode do
438-
chars = string.chars.to_a
439-
if chars.length <= width
440-
chars.join
441-
else
442-
chars[0, width - 3].join + "..."
443-
end
444-
end
445-
end
446-
447-
if "".respond_to?(:encode)
448-
def as_unicode
449-
yield
450-
end
451-
else
452-
def as_unicode
453-
old = $KCODE
454-
$KCODE = "U"
455-
yield
456-
ensure
457-
$KCODE = old
458-
end
328+
Terminal.unix?
459329
end
460330

461331
def ask_simply(statement, color, options)

lib/thor/shell/column_printer.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require_relative "terminal"
2+
3+
class Thor
4+
module Shell
5+
class ColumnPrinter
6+
attr_reader :stdout, :options
7+
8+
def initialize(stdout, options = {})
9+
@stdout = stdout
10+
@options = options
11+
@indent = options[:indent].to_i
12+
end
13+
14+
def print(array)
15+
return if array.empty?
16+
colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
17+
array.each_with_index do |value, index|
18+
# Don't output trailing spaces when printing the last column
19+
if ((((index + 1) % (Terminal.terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
20+
stdout.puts value
21+
else
22+
stdout.printf("%-#{colwidth}s", value)
23+
end
24+
end
25+
end
26+
end
27+
end
28+
end
29+

lib/thor/shell/table_printer.rb

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
require_relative "column_printer"
2+
require_relative "terminal"
3+
4+
class Thor
5+
module Shell
6+
class TablePrinter < ColumnPrinter
7+
def initialize(stdout, options = {})
8+
super
9+
@formats = []
10+
@maximas = []
11+
@colwidth = options[:colwidth]
12+
@truncate = options[:truncate] == true ? Terminal.terminal_width : options[:truncate]
13+
end
14+
15+
def print(array)
16+
return if array.empty?
17+
18+
prepare(array)
19+
20+
array.each do |row|
21+
sentence = "".dup
22+
23+
row.each_with_index do |column, index|
24+
maxima = @maximas[index]
25+
26+
f = if column.is_a?(Numeric)
27+
if index == row.size - 1
28+
# Don't output 2 trailing spaces when printing the last column
29+
"%#{maxima}s"
30+
else
31+
"%#{maxima}s "
32+
end
33+
else
34+
@formats[index]
35+
end
36+
sentence << f % column.to_s
37+
end
38+
39+
sentence = truncate(sentence)
40+
stdout.puts sentence
41+
end
42+
end
43+
44+
private
45+
46+
def prepare(array)
47+
@formats << "%-#{@colwidth + 2}s".dup if @colwidth
48+
start = @colwidth ? 1 : 0
49+
50+
colcount = array.max { |a, b| a.size <=> b.size }.size
51+
52+
start.upto(colcount - 1) do |index|
53+
maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
54+
@maximas << maxima
55+
@formats << if index == colcount - 1
56+
# Don't output 2 trailing spaces when printing the last column
57+
"%-s".dup
58+
else
59+
"%-#{maxima + 2}s".dup
60+
end
61+
end
62+
63+
@formats[0] = @formats[0].insert(0, " " * @indent)
64+
@formats << "%s"
65+
end
66+
67+
def truncate(string)
68+
return string unless @truncate
69+
as_unicode do
70+
chars = string.chars.to_a
71+
if chars.length <= @truncate
72+
chars.join
73+
else
74+
chars[0, @truncate - 3].join + "..."
75+
end
76+
end
77+
end
78+
79+
if "".respond_to?(:encode)
80+
def as_unicode
81+
yield
82+
end
83+
else
84+
def as_unicode
85+
old = $KCODE # rubocop:disable Style/GlobalVars
86+
$KCODE = "U" # rubocop:disable Style/GlobalVars
87+
yield
88+
ensure
89+
$KCODE = old # rubocop:disable Style/GlobalVars
90+
end
91+
end
92+
end
93+
end
94+
end
95+

lib/thor/shell/terminal.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
class Thor
2+
module Shell
3+
module Terminal
4+
DEFAULT_TERMINAL_WIDTH = 80
5+
6+
class << self
7+
# This code was copied from Rake, available under MIT-LICENSE
8+
# Copyright (c) 2003, 2004 Jim Weirich
9+
def terminal_width
10+
result = if ENV["THOR_COLUMNS"]
11+
ENV["THOR_COLUMNS"].to_i
12+
else
13+
unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
14+
end
15+
result < 10 ? DEFAULT_TERMINAL_WIDTH : result
16+
rescue
17+
DEFAULT_TERMINAL_WIDTH
18+
end
19+
20+
def unix?
21+
RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris)/i
22+
end
23+
24+
private
25+
26+
# Calculate the dynamic width of the terminal
27+
def dynamic_width
28+
@dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
29+
end
30+
31+
def dynamic_width_stty
32+
`stty size 2>/dev/null`.split[1].to_i
33+
end
34+
35+
def dynamic_width_tput
36+
`tput cols 2>/dev/null`.to_i
37+
end
38+
39+
end
40+
end
41+
end
42+
end

0 commit comments

Comments
 (0)