lib/troo/presentation/formatter.rb in troo-0.0.9 vs lib/troo/presentation/formatter.rb in troo-0.0.10
- old
+ new
@@ -9,10 +9,11 @@
values do
attribute :pos, Symbol, default: :none
attribute :pad, Integer, default: 0
attribute :char, String, default: ' '
attribute :width, Integer, default: 80
+ attribute :prune, Boolean, default: false
end
end
class Format
include Virtus.value_object
@@ -68,14 +69,11 @@
options.reset
].join
end
def wordwrap
- formatted_value
- .gsub(/\n/, ' ')
- .gsub(/(.{1,#{options.align.width}})(\s+|$)/, "\\1\n")
- .strip
+ Wordwrap.this(formatted_value, width: width)
end
private
def formatted_value
@@ -88,10 +86,14 @@
left: value.ljust(padding, spacer),
right: value.rjust(padding, spacer)
}
end
+ def width
+ options.align.width
+ end
+
def position
options.align.pos
end
def padding
@@ -101,19 +103,112 @@
def spacer
options.align.char
end
end
+ class Wordwrap
+ class << self
+ def this(value, options = {})
+ new(value, options).reformat
+ end
+ end
+
+ def initialize(value, options = {})
+ @value, @options = value, options
+ end
+
+ def reformat
+ return pruned if prune?
+ wordwrapped
+ end
+
+ def wordwrapped
+ processed = []
+ value.split(/\n/).map do |unprocessed|
+ line_length = 0
+ reformatted = []
+
+ unprocessed.split(/\s/).map do |word|
+ word_length = word.length + 1
+
+ if (line_length += word_length) >= maximum_width
+ line_length = word_length
+ processed << reformatted
+ reformatted = []
+ end
+
+ reformatted << word
+ end
+
+ processed << reformatted
+ end
+
+ output(processed)
+ end
+
+ private
+
+ attr_reader :value, :options
+
+ def output(paragraph)
+ paragraph.reduce([]) do |output, line|
+ output << line.join(' ')
+ end.join("\n")
+ end
+
+ def pruned
+ return value if value.size <= pruned_width
+ [
+ value.chomp.slice(0..pruned_width),
+ '...',
+ Esc.reset
+ ].join
+ end
+
+ def pruned_width
+ maximum_width - 3
+ end
+
+ def prune?
+ options.fetch(:prune)
+ end
+
+ def maximum_width
+ options.fetch(:width)
+ end
+
+ def options
+ defaults.merge!(@options)
+ end
+
+ def defaults
+ {
+ width: 70,
+ prune: false
+ }
+ end
+ end
+
class Output
attr_accessor :count
def initialize
@count = 0
end
def render(lines)
Array(lines).each { |line| print indentation + line }
nil
+ end
+
+ def spacer(&block)
+ if block_given?
+ print "\n"
+ yield
+ print "\n"
+ else
+ print "\n"
+ end
end
def indent(&block)
@count += 1