module Scrollable
Objects which include this module are supposed to be multi-line text as they have to respond to :to_s. The new functionality will allow this text to become scrollable in a terminal-window. See the scroll-functions up(), down(), left() and right().
You can have a box around the scrollable “window” by setting the attribute 'box' to true and, -as I do not care to be asked for my opinion-, you should.
Attributes
Public Instance Methods
scrolls
# File lib/scrollable.rb, line 111 def down defaults() if !@have_defaults # increase number of visible lines by step_y scroll_y(@step_y) end
# File lib/scrollable.rb, line 146 def first_column() defaults() if !@have_defaults @xoff = 0 end
# File lib/scrollable.rb, line 136 def first_line() defaults() if !@have_defaults @yoff = 0 end
# File lib/scrollable.rb, line 177 def height=(h) @height = h if h >= 1 end
read the code
# File lib/scrollable.rb, line 125 def home() first_line first_column end
# File lib/scrollable.rb, line 151 def last_column() defaults() if !@have_defaults @xoff = num_columns - 1 end
# File lib/scrollable.rb, line 141 def last_line() defaults() if !@have_defaults @yoff = @lines.length end
scrolls
# File lib/scrollable.rb, line 93 def left() defaults() if !@have_defaults scroll_x(@step_x * -1) end
dto. To the right. You guessed that.
# File lib/scrollable.rb, line 99 def right() defaults() if !@have_defaults scroll_x(@step_x) end
scrolls
# File lib/scrollable.rb, line 118 def scroll(xoffset, yoffset) defaults() if !@have_defaults scroll_y(yoffset) scroll_x(xoffset) end
guess
# File lib/scrollable.rb, line 66 def scroll_x(offset) defaults(self) if !@have_defaults if(offset != 0) xt = @xoff + offset width_x = num_columns - xt if(width_x > 0) @xoff = xt end end show() end
scroll up or down by offset lines.
# File lib/scrollable.rb, line 79 def scroll_y(offset) defaults() if !@have_defaults # any offset is okay if(offset != 0 ) yt = @yoff + offset height_y = @lines.length + yt if(height_y > 0) @yoff = yt end end show() end
does it
# File lib/scrollable.rb, line 54 def show defaults() if !@have_defaults system('clear') new_view = limit_lines if @box box(new_view) else puts new_view end end
set the size of a horizontal scroll step
# File lib/scrollable.rb, line 165 def step_x=(step) if step > 0 @step_x = step else raise ScrollException.new('ERROR: scroll-steps must be positive numbers') end end
set the size of a vertical scroll step
# File lib/scrollable.rb, line 156 def step_y=(step) if step > 0 @step_y = step else raise ScrollException.new('ERROR: scroll-steps must be positive numbers') end end
dto.
# File lib/scrollable.rb, line 131 def to_end() last_column last_line end
scrolls
# File lib/scrollable.rb, line 105 def up() defaults() if !@have_defaults scroll_y(@step_y * -1 ) end
# File lib/scrollable.rb, line 173 def width=(w) @width = w if w >= 1 end
Private Instance Methods
draw lines of color, wherever the content is clipped.
# File lib/scrollable.rb, line 265 def box(view) nl = "\n" lines = view.split(nl) ctl = @@box[0] bl = @@box[5] cbl = @@box[2] bt = @@box[4] ctr = @@box[1] br = @@box[5] cbr = @@box[3] bb = @@box[4] if clipped_left ctl = bold(blue(ctl)) bl = bold(blue(bl)) cbl = bold(blue(cbl)) end if clipped_right ctr = bold(blue(ctr)) br = bold(blue(br)) cbr = bold(blue(cbr)) end if clipped_top ctr = bold(blue(ctr)) bt = bold(blue(bt)) ctl = bold(blue(ctl)) end if clipped_bottom cbl = bold(blue(cbl)) cbr = bold(blue(cbr)) bb = bold(blue(bb)) end size = `stty size`.split.map { |x| x.to_i }.reverse @width -= 1 until (@width + 5) <= size[0] #@height -= 1 until (@height + 2) <= size[1] puts "%s%s%s" %[ctl, bt * (@width + 3), ctr ] height.times {|n| puts "%s %-#{@width+1}s %s" %[bl, lines[n], br] } puts "%s%s%s" %[cbl, bb * (@width + 3), cbr ] end
sets a few values, needed for the rest of the module to function.
# File lib/scrollable.rb, line 229 def defaults() @log = @@log if(self.respond_to?(:to_s) ) # @view = self @view = self.gsub(/\e\[\d+m/, '') @lines = @view.split("\n") @xoff = 0 @yoff = 0 @step_x ||= @@def_step_x @step_y ||= @@def_step_y @width ||= 60 @height ||= 30 @fixed_rows ||= 0 @fixed_cols ||= 0 @box ||= false @have_defaults = true elsif !view msg = 'Need to know, what to scroll! (argument "view" missing)' @log.error(yellow(msg)) raise ScrollException.new(msg) else msg = 'The "view" to scroll must have a method "to_s()"' @log.error(yellow(msg)) raise ScrollException.new(msg) end end
Clip off all that cannot fit into the defined width and height. Removes probably more than needed, but in its current state, I tend to understand this method. In addition, it somehow appears to work for me…
# File lib/scrollable.rb, line 190 def limit_lines() # limit lines laterally if(@xoff < 0) @xoff = 0 end new_view = @lines.collect do |l| short = l[0...@fixed_cols].to_s + l[(@xoff + @fixed_cols)..(@width + @xoff)].to_s end # limit number of lines if(@yoff >= 0) if(@yoff > (@lines.length - @height + @fixed_rows)) @yoff = @lines.length - @height + @fixed_rows end end @yoff = 0 if @yoff < 0 new_view = new_view[0...@fixed_rows] + new_view[(@yoff + @fixed_rows)...(@height + @yoff - @fixed_rows) ] # describe the situation in case that someone must know.., if @box @clipped_left = @xoff > 0 @clipped_top = @yoff > 0 @clipped_right = num_columns - @xoff > @width @clipped_bottom = @lines.length - @yoff > @height end #... not, if not return new_view.join("\n") end
calculates the number of columns (characters), needed.
# File lib/scrollable.rb, line 223 def num_columns defaults if !@have_defaults @lines.max {|a, b| a.length <=> b.length}.length end