Class: Samovar::Output::LineWrapping

Inherits:
Object
  • Object
show all
Defined in:
lib/samovar/output/line_wrapper.rb

Overview

This is an incomplete implementation of an automatic line wrapping output buffer which handles any kind of output, provided it has special wrapping markers.

Constant Summary collapse

MARKER =
"\e[0;0m".freeze
ESCAPE_SEQUENCE =
/(.*?)(\e\[.*?m|$)/

Instance Method Summary collapse

Constructor Details

#initialize(output, wrapping_width = 80, minimum_width = 20) ⇒ LineWrapping

Returns a new instance of LineWrapping.



27
28
29
30
31
# File 'lib/samovar/output/line_wrapper.rb', line 27

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

Instance Method Details

#printable_width(text) ⇒ Object



35
36
37
# File 'lib/samovar/output/line_wrapper.rb', line 35

def printable_width(text)
	text.size
end

#puts(*lines) ⇒ Object



80
81
82
83
84
# File 'lib/samovar/output/line_wrapper.rb', line 80

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

#wrap(line) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/samovar/output/line_wrapper.rb', line 39

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