diff options
| author | Julian Hurst <julian.hurst@digdash.com> | 2025-03-20 12:33:13 +0100 |
|---|---|---|
| committer | Julian Hurst <julian.hurst@digdash.com> | 2025-03-20 12:33:13 +0100 |
| commit | ddac62a2a43ee62da4f5302e9cb2958f6ff82cea (patch) | |
| tree | 1a0e7d0dd485d5a4a1879f05bdefd79b3e4bbf0b | |
| parent | 6e8a2af6bd47fd05e6b22937c5da7397549e7cbb (diff) | |
| download | hare-tui-ddac62a2a43ee62da4f5302e9cb2958f6ff82cea.tar.gz | |
Add setcursor and reframe to scrolllist and flesh out il
| -rw-r--r-- | cmd/il.ha | 59 | ||||
| -rw-r--r-- | tui/widget/list/scrolllist.ha | 18 |
2 files changed, 77 insertions, 0 deletions
@@ -5,6 +5,7 @@ use bufio; use os; use strings; use fmt; +use io; export fn main() void = { const scanner = bufio::newscanner(os::stdin); @@ -28,6 +29,9 @@ export fn main() void = { vl.layout.print(&vl); + let term: (str | void) = void; + defer if (term is str) free(term as str) else void; + let revsearch = false; for (true) { const r = tui::read(&state)!; if (r == 'j') { @@ -55,6 +59,61 @@ export fn main() void = { fmt::println(li.items[li.cursor])!; break; }; + if (r == '/' || r == '?') { + revsearch = r == '?'; + term = search(&state, &li, r as rune); + if (revsearch) prevsearch(&li, term) else nextsearch(&li, term); + }; + if (r == 'n') { + if (revsearch) prevsearch(&li, term) else nextsearch(&li, term); + }; + if (r == 'N') { + if (!revsearch) prevsearch(&li, term) else nextsearch(&li, term); + }; vl.layout.print(&vl); }; }; + +fn search(state: *tui::tui, li: *list::scrolllist, prefix: (str | rune) = '/') (str | void) = { + tui::unraw(state); + defer tui::raw(state)!; + fmt::fprint(state.out, prefix)!; + const uline = match (bufio::read_line(state.out)!) { + case let u: []u8 => + yield u; + case io::EOF => + return; + }; + defer free(uline); + return strings::dup(strings::fromutf8(uline)!); +}; + +fn nextsearch(li: *list::scrolllist, term: (str | void)) void = { + const term = match (term) { + case let term: str => + yield term; + case void => + return; + }; + for (let i = li.cursor + 1; i < len(li.items); i += 1) { + if (strings::contains(li.items[i], term)) { + list::setcursor(li, i: u16); + return; + }; + }; +}; + +fn prevsearch(li: *list::scrolllist, term: (str | void)) void = { + const term = match (term) { + case let term: str => + yield term; + case void => + return; + }; + for (let i: int = li.cursor: int - 1; i >= 0; i -= 1) { + if (strings::contains(li.items[i], term)) { + list::setcursor(li, i: u16); + return; + }; + }; +}; diff --git a/tui/widget/list/scrolllist.ha b/tui/widget/list/scrolllist.ha index 3aaad87..d08c7d7 100644 --- a/tui/widget/list/scrolllist.ha +++ b/tui/widget/list/scrolllist.ha @@ -115,6 +115,24 @@ export fn bottom(li: *scrolllist) void = { li.frame.start = len(li.items): u16 - sz; }; +export fn setcursor(li: *scrolllist, newpos: u16) void = { + li.cursor = newpos; + reframe(li); +}; + +fn reframe(li: *scrolllist) void = { + if (li.cursor > li.frame.end) { + const diff = li.frame.end - li.frame.start; + li.frame.start = li.cursor; + li.frame.end = li.frame.start + diff; + }; + if (li.cursor < li.frame.start) { + const diff = li.frame.end - li.frame.start; + li.frame.end = li.cursor; + li.frame.start = li.frame.end - diff; + }; +}; + fn stylesscrolllist(widget: *widget::widget, txt: str, idx: size) str = { const list = widget: *scrolllist; const idx = idx + list.frame.start; |
