3 ## extends ScrollMode to have a line-based cursor.
4 class LineCursorMode < ScrollMode
6 ## overwrite scrollmode binding on arrow keys for cursor movement
7 ## but j and k still scroll!
8 k.add :cursor_down, "Move cursor down one line", :down, 'j'
9 k.add :cursor_up, "Move cursor up one line", :up, 'k'
10 k.add :select, "Select this item", :enter
15 def initialize cursor_top=0, opts={}
16 @cursor_top = cursor_top
18 @load_more_callbacks = []
19 @load_more_callbacks_m = Mutex.new
20 @load_more_callbacks_active = false
31 ## callbacks when the cursor is asked to go beyond the bottom
33 @load_more_callbacks << b
36 def draw_line ln, opts={}
38 super ln, :highlight => true, :debug => opts[:debug]
44 def ensure_mode_validity
46 raise @curpos.inspect unless @curpos.is_a?(Integer)
47 c = @curpos.clamp topline, botline - 1
48 c = @cursor_top if c < @cursor_top
49 buffer.mark_dirty unless c == @curpos
54 return if @curpos == p
55 @curpos = p.clamp @cursor_top, lines
59 def line_down # overwrite scrollmode
61 call_load_more_callbacks([topline + buffer.content_height - lines, 10].max) if topline + buffer.content_height > lines
62 set_cursor_pos topline if @curpos < topline
65 def line_up # overwrite scrollmode
67 set_cursor_pos botline - 1 if @curpos > botline - 1
71 call_load_more_callbacks buffer.content_height if @curpos == lines - 1
72 return false unless @curpos < lines - 1
74 if @curpos >= botline - 1
76 set_cursor_pos topline
90 return false unless @curpos > @cursor_top
94 set_cursor_pos [old_topline - 1, topline].max
107 def page_up # overwrite
108 if topline <= @cursor_top
109 set_cursor_pos @cursor_top
111 relpos = @curpos - topline
113 set_cursor_pos topline + relpos
117 ## more complicated than one might think. three behaviors.
119 ## if we're on the last page, and it's not a full page, just move
120 ## the cursor down to the bottom and assume we can't load anything
121 ## else via the callbacks.
122 if topline > lines - buffer.content_height
123 set_cursor_pos(lines - 1)
125 ## if we're on the last page, and it's a full page, try and load
126 ## more lines via the callbacks and then shift the page down
127 elsif topline == lines - buffer.content_height
128 call_load_more_callbacks buffer.content_height
131 ## otherwise, just move down
133 relpos = @curpos - topline
135 set_cursor_pos [topline + relpos, lines - 1].min
141 set_cursor_pos @cursor_top
145 super if topline < (lines - buffer.content_height)
146 set_cursor_pos(lines - 1)
153 @status = l > 0 ? "line #{@curpos + 1} of #{l}" : ""
156 def call_load_more_callbacks size
158 @load_more_callbacks_m.synchronize do
159 if @load_more_callbacks_active
162 @load_more_callbacks_active = true
168 @load_more_callbacks.each { |c| c.call size }
169 @load_more_callbacks_active = false