]> git.cworth.org Git - sup/blob - lib/sup/modes/scroll-mode.rb
bugfix: label search for killed, deleted, spam
[sup] / lib / sup / modes / scroll-mode.rb
1 module Redwood
2
3 class ScrollMode < Mode
4   ## we define topline and botline as the top and bottom lines of any
5   ## content in the currentview.
6   
7   ## we left leftcol and rightcol as the left and right columns of any
8   ## content in the current view. but since we're operating in a
9   ## line-centric fashion, rightcol is always leftcol + the buffer
10   ## width. (whereas botline is topline + at most the buffer height,
11   ## and can be == to topline in the case that there's no content.)
12
13   attr_reader :status, :topline, :botline, :leftcol
14
15   COL_JUMP = 2
16
17   register_keymap do |k|
18     k.add :line_down, "Down one line", :down, 'j', 'J'
19     k.add :line_up, "Up one line", :up, 'k', 'K'
20     k.add :col_left, "Left one column", :left, 'h'
21     k.add :col_right, "Right one column", :right, 'l'
22     k.add :page_down, "Down one page", :page_down, 'n', ' '
23     k.add :page_up, "Up one page", :page_up, 'p', :backspace
24     k.add :jump_to_start, "Jump to top", :home, '^', '1'
25     k.add :jump_to_end, "Jump to bottom", :end, '$', '0'
26     k.add :jump_to_left, "Jump to the left", '['
27   end
28
29   def initialize opts={}
30     @topline, @botline, @leftcol = 0, 0, 0
31     @slip_rows = opts[:slip_rows] || 0 # when we pgup/pgdown,
32                                        # how many lines do we keep?
33     @twiddles = opts.member?(:twiddles) ? opts[:twiddles] : true
34     super()
35   end
36
37   def rightcol; @leftcol + buffer.content_width; end
38
39   def draw
40     ensure_mode_validity
41     (@topline ... @botline).each { |ln| draw_line ln }
42     ((@botline - @topline) ... buffer.content_height).each do |ln|
43       if @twiddles
44         buffer.write ln, 0, "~", :color => :twiddle_color
45       else
46         buffer.write ln, 0, ""
47       end
48     end
49     @status = "lines #{@topline + 1}:#{@botline}/#{lines}"
50   end
51
52   def col_left
53     return unless @leftcol > 0
54     @leftcol -= COL_JUMP
55     buffer.mark_dirty
56   end
57
58   def col_right
59     @leftcol += COL_JUMP
60     buffer.mark_dirty
61   end
62
63   def jump_to_col col
64     buffer.mark_dirty unless @leftcol == col
65     @leftcol = col
66   end
67
68   def jump_to_left; jump_to_col 0; end
69
70   ## set top line to l
71   def jump_to_line l
72     l = l.clamp 0, lines - 1
73     return if @topline == l
74     @topline = l
75     @botline = [l + buffer.content_height, lines].min
76     buffer.mark_dirty
77   end
78
79   def at_top?; @topline == 0 end
80   def at_bottom?; @botline == lines end
81
82   def line_down; jump_to_line @topline + 1; end
83   def line_up;  jump_to_line @topline - 1; end
84   def page_down; jump_to_line @topline + buffer.content_height - @slip_rows; end
85   def page_up; jump_to_line @topline - buffer.content_height + @slip_rows; end
86   def jump_to_start; jump_to_line 0; end
87   def jump_to_end; jump_to_line lines - buffer.content_height; end
88
89   def ensure_mode_validity
90     @topline = @topline.clamp 0, [lines - 1, 0].max
91     @botline = [@topline + buffer.content_height, lines].min
92   end
93
94   def resize *a
95     super(*a)
96     ensure_mode_validity
97   end
98
99 protected
100
101   def draw_line ln, opts={}
102     case(s = self[ln])
103     when String
104       buffer.write ln - @topline, 0, s[@leftcol .. -1],
105                    :highlight => opts[:highlight]
106     when Array
107       xpos = 0
108
109       ## speed test
110       # str = s.map { |color, text| text }.join
111       # buffer.write ln - @topline, 0, str, :color => :none, :highlight => opts[:highlight]
112       # return
113
114       s.each do |color, text|
115         raise "nil text for color '#{color}'" if text.nil? # good for debugging
116         if xpos + text.length < @leftcol
117           buffer.write ln - @topline, 0, "", :color => color,
118                        :highlight => opts[:highlight]
119           xpos += text.length
120         elsif xpos < @leftcol
121           ## partial
122           buffer.write ln - @topline, 0, text[(@leftcol - xpos) .. -1],
123                        :color => color,
124                        :highlight => opts[:highlight]
125           xpos += text.length
126         else
127           buffer.write ln - @topline, xpos - @leftcol, text,
128                        :color => color, :highlight => opts[:highlight]
129           xpos += text.length
130         end
131
132       end
133     end
134   end
135 end
136
137 end