commit a3d6ea4087e8493d71b2e5154a04b1fc5a85827d
parent 55c9afceac1eda9f2a66023983ec05a55cd073a4
Author: Dan Callaghan <djc@djc.id.au>
Date: Sun, 5 Apr 2026 12:42:41 +1000
refactor LineCursorMode to handle initial load
Rather than having every calling site explicitly load the initial set of
threads whenever one of the subclasses of LineCursorMode is spawned,
make LineCursorMode itself handle the initial load. This way, the
logic for deciding how many threads to load at what time is consolidated
into LineCursorMode.
Diffstat:
9 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/bin/sup b/bin/sup
@@ -206,7 +206,10 @@ begin
end
end unless $opts[:no_initial_poll]
- imode.load_threads :num => ibuf.content_height, :when_done => lambda { |num| reporting_thread("poll after loading inbox") { sleep 1; PollManager.poll } unless $opts[:no_threads] || $opts[:no_initial_poll] }
+ reporting_thread("poll after loading inbox") do
+ sleep 1
+ PollManager.poll
+ end unless $opts[:no_threads] || $opts[:no_initial_poll]
if $opts[:compose]
to = Person.from_address_list $opts[:compose]
@@ -328,8 +331,7 @@ begin
BufferManager.spawn "Edit message", r
r.default_edit_message
else
- b, new = BufferManager.spawn_unless_exists("All drafts") { LabelSearchResultsMode.new [:draft] }
- b.mode.load_threads :num => b.content_height if new
+ BufferManager.spawn_unless_exists("All drafts") { LabelSearchResultsMode.new [:draft] }
end
when :show_inbox
BufferManager.raise_to_front ibuf
diff --git a/lib/sup/buffer.rb b/lib/sup/buffer.rb
@@ -330,6 +330,7 @@ EOS
w = Ncurses.stdscr
b = Buffer.new w, mode, width, height, :title => realtitle, :force_to_top => opts[:force_to_top], :system => opts[:system]
mode.buffer = b
+ mode.spawned
@name_map[realtitle] = b
@buffers.unshift b
diff --git a/lib/sup/mode.rb b/lib/sup/mode.rb
@@ -37,6 +37,7 @@ class Mode
def draw; end
def focus; end
def blur; end
+ def spawned; end
def cancel_search!; end
def in_search?; false end
def status; ""; end
diff --git a/lib/sup/modes/contact_list_mode.rb b/lib/sup/modes/contact_list_mode.rb
@@ -83,7 +83,6 @@ class ContactListMode < LineCursorMode
def multi_search people
mode = PersonSearchResultsMode.new people
BufferManager.spawn "search for #{people.map { |p| p.name }.join(', ')}", mode
- mode.load_threads :num => mode.buffer.content_height
end
def search
diff --git a/lib/sup/modes/label_search_results_mode.rb b/lib/sup/modes/label_search_results_mode.rb
@@ -29,8 +29,7 @@ class LabelSearchResultsMode < ThreadIndexMode
when :inbox
BufferManager.raise_to_front InboxMode.instance.buffer
else
- b, new = BufferManager.spawn_unless_exists("All threads with label '#{label}'") { LabelSearchResultsMode.new [label] }
- b.mode.load_threads :num => b.content_height if new
+ BufferManager.spawn_unless_exists("All threads with label '#{label}'") { LabelSearchResultsMode.new [label] }
end
end
end
diff --git a/lib/sup/modes/line_cursor_mode.rb b/lib/sup/modes/line_cursor_mode.rb
@@ -31,6 +31,8 @@ class LineCursorMode < ScrollMode
super opts
end
+ def spawned; call_load_more_callbacks buffer.content_height; end
+
def cleanup
@load_more_thread.kill
super
diff --git a/lib/sup/modes/search_results_mode.rb b/lib/sup/modes/search_results_mode.rb
@@ -49,7 +49,6 @@ class SearchResultsMode < ThreadIndexMode
short_text = text.length < 20 ? text : text[0 ... 20] + "..."
mode = SearchResultsMode.new query
BufferManager.spawn "search: \"#{short_text}\"", mode
- mode.load_threads :num => mode.buffer.content_height
rescue Index::ParseError => e
BufferManager.flash "Problem: #{e.message}!"
end
diff --git a/lib/sup/modes/thread_view_mode.rb b/lib/sup/modes/thread_view_mode.rb
@@ -205,7 +205,7 @@ EOS
@layout[m].state = (@layout[m].state == :detailed ? :open : :detailed)
update
end
-
+
def reload
update
end
@@ -298,7 +298,6 @@ EOS
p = @person_lines[curpos] or return
mode = PersonSearchResultsMode.new [p]
BufferManager.spawn "Search for #{p.name}", mode
- mode.load_threads :num => mode.buffer.content_height
end
def compose
diff --git a/test/unit/test_line_cursor_mode.rb b/test/unit/test_line_cursor_mode.rb
@@ -12,8 +12,9 @@ class TestLineCursorMode < Minitest::Test
}
Redwood::BufferManager.init
@modes_to_cleanup = []
- @lines = (0...40).map { |i| "line #{i}" }
+ @lines = []
@load_more = Thread::Queue.new
+ @buffer_height = 41 # 1 for status line, 40 usable lines
end
def teardown
@@ -29,7 +30,8 @@ class TestLineCursorMode < Minitest::Test
mode.define_singleton_method(:lines) { lines.length }
mode.define_singleton_method(:[]) { |i| lines[i] }
mode.send(:to_load_more) { |n| @load_more << n }
- mode.buffer = Redwood::DummyBuffer.new 100, lines.length + 1
+ mode.buffer = Redwood::DummyBuffer.new 100, @buffer_height
+ mode.spawned
mode.draw
mode
end
@@ -44,11 +46,13 @@ class TestLineCursorMode < Minitest::Test
end
refute_nil requested, "Expected load_more callbacks to fire"
assert_equal n, requested
- (0...n).map { |i| @lines << "more line #{i}" }
+ (0...n).map { |i| @lines << "line #{i}" }
end
def test_cursor_down
mode = make_mode
+ expect_load_more 40
+ mode.draw # curpos gets messed up without this call, why?
20.times do
mode.handle_input Ncurses::CharCode.character('j')
@@ -75,6 +79,7 @@ class TestLineCursorMode < Minitest::Test
def test_scroll_down
mode = make_mode
+ expect_load_more 40
## When the cursor is already at the top, it moves with the scroll.
assert_equal 0, mode.curpos
@@ -101,6 +106,7 @@ class TestLineCursorMode < Minitest::Test
def test_page_down
mode = make_mode
+ expect_load_more 40
## In theory, we should scroll a full page down. But because we always load
## exactly enough lines to fill one page, the first time we are off by one.
@@ -143,6 +149,7 @@ class TestLineCursorMode < Minitest::Test
def test_page_down_when_fully_populated
mode = make_mode
+ expect_load_more 40
(0...120).map { |i| @lines << "more line #{i}" } # enough for 4 full pages
mode.handle_input Ncurses::CharCode.keycode(Ncurses::KEY_NPAGE)