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