Skip to content

Commit

Permalink
Line wrapping output buffer.. half implemented.
Browse files Browse the repository at this point in the history
  • Loading branch information
ioquatix committed Apr 22, 2016
1 parent 854ee36 commit 55d4822
Showing 1 changed file with 87 additions and 0 deletions.
87 changes: 87 additions & 0 deletions lib/flopp/output/line_wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

module Flopp
module Output
# This is an incomplete implementation of an automatic line wrapping output buffer which handles any kind of output, provided it has special wrapping markers.
class LineWrapping
MARKER = "\e[0;0m".freeze

def initialize(output, wrapping_width = 80, minimum_width = 20)
@output = output
@wrapping_width = wrapping_width
@minimum_width = minimum_width
end

ESCAPE_SEQUENCE = /(.*?)(\e\[.*?m|$)/

def printable_width(text)
text.size
end

def wrap(line)
wrapping_offset = nil
offset = 0
buffer = String.new
lines = []
prefix = nil

line.scan(ESCAPE_SEQUENCE) do |text, escape_sequence|
width = printable_width(text)
next_offset = offset + printable_width

if next_offset > @wrapping_width
if wrapping_offset
text_wrap_offset = @wrapping_width - offset

# This text flows past the end of the line and we have a valid wrapping offset. We need to wrap this text.
if best_split_index = text.rindex(/\s/, text_wrap_offset) and best_split_index >= @minimum_width
# We have enough space to wrap.
buffer << text[0...best_split_index]
lines << buffer
buffer = String.new()
else
# In this case we can't really wrap on the current line. We fall back to letting the terminal wrap.
return line
end
else
# We don't have a specific wrapping offset, and the text flows longer than the wrapping width. We can't do anything - let the terminal wrap.
return line
end
else
buffer << text << escape_sequence
end

offset = next_offset

if wrapping_offset.nil? and offset < @wrapping_width and escape_sequence == MARKER
wrapping_offset = offset
end
end
end

def puts(*lines)
lines = lines.flat_map{|line| wrap(line)}

@output.puts(*lines)
end
end
end
end

0 comments on commit 55d4822

Please sign in to comment.