]> git.cworth.org Git - sup/blob - lib/sup/modes/scroll-mode.rb
3477575998413249ff94c007fd18dbebc1c123f1
[sup] / lib / sup / modes / scroll-mode.rb
1 module Redwood
2
3 class ScrollMode < Mode
4   attr_reader :status, :topline, :botline
5
6   COL_JUMP = 2
7
8   register_keymap do |k|
9     k.add :line_down, "Down one line", :down, 'j', 'J'
10     k.add :line_up, "Up one line", :up, 'k', 'K'
11     k.add :col_left, "Left one column", :left, 'h'
12     k.add :col_right, "Right one column", :right, 'l'
13     k.add :page_down, "Down one page", :page_down, 'n', ' '
14     k.add :page_up, "Up one page", :page_up, 'p', :backspace
15     k.add :jump_to_home, "Jump to top", :home, '^', '1'
16     k.add :jump_to_end, "Jump to bottom", :end, '$', '0'
17     k.add :jump_to_left, "Jump to the left", '['
18   end
19
20   def initialize opts={}
21     @topline, @botline, @leftcol = 0, 0, 0
22     @slip_rows = opts[:slip_rows] || 0 # when we pgup/pgdown,
23                                        # how many lines do we keep?
24     @twiddles = opts.member?(:twiddles) ? opts[:twiddles] : true
25     super()
26   end
27
28   def draw
29     ensure_mode_validity
30     (@topline ... @botline).each { |ln| draw_line ln }
31     ((@botline - @topline) ... buffer.content_height).each do |ln|
32       if @twiddles
33         buffer.write ln, 0, "~", :color => :twiddle_color
34       else
35         buffer.write ln, 0, ""
36       end
37     end
38     @status = "lines #{@topline + 1}:#{@botline}/#{lines}"
39   end
40
41   def col_left
42     return unless @leftcol > 0
43     @leftcol -= COL_JUMP
44     buffer.mark_dirty
45   end
46
47   def col_right
48     @leftcol += COL_JUMP
49     buffer.mark_dirty
50   end
51
52   def jump_to_left
53     buffer.mark_dirty unless @leftcol == 0
54     @leftcol = 0
55   end
56
57   ## set top line to l
58   def jump_to_line l
59     l = l.clamp 0, lines - 1
60     return if @topline == l
61     @topline = l
62     @botline = [l + buffer.content_height, lines].min
63     buffer.mark_dirty
64   end
65
66   def line_down; jump_to_line @topline + 1; end
67   def line_up;  jump_to_line @topline - 1; end
68   def page_down; jump_to_line @topline + buffer.content_height - @slip_rows; end
69   def page_up; jump_to_line @topline - buffer.content_height + @slip_rows; end
70   def jump_to_home; jump_to_line 0; end
71   def jump_to_end; jump_to_line lines - buffer.content_height; end
72
73
74   def ensure_mode_validity
75     @topline = @topline.clamp 0, lines - 1
76     @topline = 0 if @topline < 0 # empty 
77     @botline = [@topline + buffer.content_height, lines].min
78   end
79
80 protected
81
82   def draw_line ln, opts={}
83     case(s = self[ln])
84     when String
85       buffer.write ln - @topline, 0, s[@leftcol .. -1],
86                    :highlight => opts[:highlight]
87     when Array
88       xpos = 0
89       s.each do |color, text|
90         raise "nil text for color '#{color}'" if text.nil? # good for debugging
91         if xpos + text.length < @leftcol
92           buffer.write ln - @topline, 0, "", :color => color,
93                        :highlight => opts[:highlight]
94           xpos += text.length
95         elsif xpos < @leftcol
96           ## partial
97           buffer.write ln - @topline, 0, text[(@leftcol - xpos) .. -1],
98                        :color => color,
99                        :highlight => opts[:highlight]
100           xpos += text.length
101         else
102           buffer.write ln - @topline, xpos - @leftcol, text,
103                        :color => color, :highlight => opts[:highlight]
104           xpos += text.length
105         end
106
107       end
108     end
109   end
110 end
111
112 end