lib/strings/wrap.rb in strings-0.1.8 vs lib/strings/wrap.rb in strings-0.2.0
- old
+ new
@@ -1,66 +1,63 @@
# frozen_string_literal: true
-require 'strings-ansi'
-require 'unicode/display_width'
-require 'unicode_utils/each_grapheme'
+require "strings-ansi"
+require "unicode/display_width"
+require "unicode_utils/each_grapheme"
-require_relative 'fold'
-
module Strings
module Wrap
DEFAULT_WIDTH = 80
- NEWLINE = "\n".freeze
- SPACE = " ".freeze
+ NEWLINE = "\n"
+ SPACE = " "
LINE_BREAK = %r{\r\n|\r|\n}.freeze
- LINE_BREAKS = "\r\n+|\r+|\n+".freeze
+ LINE_BREAKS = "\r\n+|\r+|\n+"
# Wrap a text into lines no longer than wrap_at length.
# Preserves existing lines and existing word boundaries.
#
# @example
# Strings::Wrap.wrap("Some longish text", 8)
# # => "Some \nlongish \ntext"
#
# @api public
- def wrap(text, wrap_at = DEFAULT_WIDTH, separator: nil)
+ def wrap(text, wrap_at = DEFAULT_WIDTH, separator: NEWLINE)
if text.scan(/[[:print:]]/).length < wrap_at.to_i || wrap_at.to_i.zero?
return text
end
+
ansi_stack = []
- sep = separator || text[LINE_BREAK] || NEWLINE
- text.split(%r{#{LINE_BREAKS}}, -1).map do |paragraph|
- format_paragraph(paragraph, wrap_at, ansi_stack)
- end * sep
+ text.lines.map do |line|
+ format_line(line, wrap_at, ansi_stack).join(separator)
+ end.join
end
module_function :wrap
- # Format paragraph to be maximum of wrap_at length
+ # Format line to be maximum of wrap_at length
#
- # @param [String] paragraph
- # the paragraph to format
+ # @param [String] text_line
+ # the line to format
# @param [Integer] wrap_at
- # the maximum length to wrap the paragraph
+ # the maximum length to wrap the line
#
# @return [Array[String]]
# the wrapped lines
#
# @api private
- def format_paragraph(paragraph, wrap_at, ansi_stack)
- cleared_para = Fold.fold(paragraph)
+ def format_line(text_line, wrap_at, ansi_stack)
lines = []
line = []
word = []
ansi = []
ansi_matched = false
word_length = 0
line_length = 0
char_length = 0 # visible char length
- text_length = display_width(cleared_para)
+ text_length = display_width(text_line)
total_length = 0
- UnicodeUtils.each_grapheme(cleared_para) do |char|
+ UnicodeUtils.each_grapheme(text_line) do |char|
# we found ansi let's consume
if char == Strings::ANSI::CSI || ansi.length > 0
ansi << char
if Strings::ANSI.only_ansi?(ansi.join)
ansi_matched = true
@@ -113,11 +110,11 @@
end
lines << insert_ansi(line.join, ansi_stack) unless line.empty?
lines << insert_ansi(word.join, ansi_stack) unless word.empty?
lines
end
- module_function :format_paragraph
+ module_function :format_line
# Insert ANSI code into string
#
# Check if there are any ANSI states, if present
# insert ANSI codes at given positions unwinding the stack.
@@ -149,10 +146,14 @@
next
elsif !matched_reset # ansi without reset
matched_reset = false
new_stack << ansi # keep the ansi
next if ansi[1] == length
- output.insert(-1, ansi_reset) # add reset at the end
+ if output.end_with?(NEWLINE)
+ output.insert(-2, ansi_reset)
+ else
+ output.insert(-1, ansi_reset) # add reset at the end
+ end
end
output.insert(ansi[1], ansi[0])
end