diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-23 09:24:40 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-23 09:24:40 +0200 |
| commit | 6159042d0cb3870e6a7c6f8d9a97e175d59e6f80 (patch) | |
| tree | c6422654298a744b0a791de8f1e8ccb8e1c55071 /tests | |
| parent | 53071bb69f5d21b35b8a61c2b1dd18832ce781d4 (diff) | |
| download | bokf-6159042d0cb3870e6a7c6f8d9a97e175d59e6f80.tar.gz bokf-6159042d0cb3870e6a7c6f8d9a97e175d59e6f80.zip | |
tui: 'g' + a letter searches list rows
The goto prompt decides on its first key: digits jump to a row number as
before, any other printable key searches the row texts of the list or
menu (case-insensitive, also åäö), with up/down stepping through the
matches. Keys typed into the prompt no longer reach the screen's key
hook, and Enter in the action menu closes an open prompt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_tui.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/tests/test_tui.c b/tests/test_tui.c index 7ab969b..d01a546 100644 --- a/tests/test_tui.c +++ b/tests/test_tui.c @@ -453,6 +453,98 @@ static void test_sticky(void) static const unsigned char SECTION_FLAGS[5] = { 0, 1, 1, 0, 1 }; +static void test_goto_search(void) +{ + const char *rows[] = { + " x A1 2026-01-01 Golden verifikat", + " A2 2026-01-05 Hyra kontor", + " A10 2026-02-01 Företagsförsäkring", + " F1 2026-02-03 Faktura 1 Testkund AB", + " A11 2026-03-01 Hyra kontor mars", + }; + struct tui_list_nav v; + nav_init(&v, 5); + v.items = rows; + + /* case-insensitive, also for åäö */ + CHECK(tui_text_match("Företagsförsäkring", "FÖRSÄK")); + CHECK(tui_text_match("ÅRSREDOVISNING", "årsred")); + CHECK(tui_text_match("abc", "")); + CHECK(!tui_text_match("abc", "abd")); + CHECK(!tui_text_match(NULL, "a")); + + /* a letter first makes the prompt a search from the top */ + CHECK(tui_nav_key(&v, 'g', 0, 0, 0, 0) == TUI_NAV_NONE && v.goto_active); + CHECK(tui_nav_key(&v, 'h', 0, 0, 0, 0) == TUI_NAV_NONE); + CHECK(v.goto_search && v.sel == 1); + tui_nav_key(&v, 'y', 0, 0, 0, 0); + tui_nav_key(&v, 'r', 0, 0, 0, 0); + CHECK(v.sel == 1 && !v.goto_miss); + /* down/up step through the matches and wrap */ + tui_nav_key(&v, KEY_DOWN, 0, 0, 0, 0); + CHECK(v.sel == 4); + tui_nav_key(&v, KEY_DOWN, 0, 0, 0, 0); + CHECK(v.sel == 1); + tui_nav_key(&v, KEY_UP, 0, 0, 0, 0); + CHECK(v.sel == 4); + /* digits, 'g' and 'q' are text once searching */ + tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0); + tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0); + tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0); + CHECK(!v.goto_search && v.goto_active && v.gotobuf[0] == '\0'); + tui_nav_key(&v, 'a', 0, 0, 0, 0); + tui_nav_key(&v, '1', 0, 0, 0, 0); + tui_nav_key(&v, '0', 0, 0, 0, 0); + CHECK(v.goto_search && v.sel == 2 && strcmp(v.gotobuf, "a10") == 0); + /* no match keeps the selection and flags the miss */ + tui_nav_key(&v, 'q', 0, 0, 0, 0); + CHECK(v.goto_active && v.goto_miss && v.sel == 2); + tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0); + CHECK(!v.goto_miss); + /* multi-byte input searches once the character is complete */ + tui_nav_key(&v, 21, 0, 0, 0, 0); /* ^U is ignored in the prompt */ + while (v.gotobuf[0]) + tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0); + tui_nav_key(&v, 0xC3, 0, 0, 0, 0); /* "ö" */ + tui_nav_key(&v, 0xB6, 0, 0, 0, 0); + CHECK(v.goto_search && v.sel == 2 && strcmp(v.gotobuf, "ö") == 0); + tui_nav_key(&v, KEY_BACKSPACE, 0, 0, 0, 0); + CHECK(v.gotobuf[0] == '\0' && !v.goto_search); + /* Enter closes without opening; the selection stays */ + tui_nav_key(&v, 'f', 0, 0, 0, 0); + tui_nav_key(&v, '1', 0, 0, 0, 0); + CHECK(v.sel == 3); + CHECK(tui_nav_key(&v, '\n', 0, 0, 0, 0) == TUI_NAV_NONE); + CHECK(!v.goto_active && !v.goto_search && v.gotobuf[0] == '\0' && + v.sel == 3); + + /* digits first still jump to a row number */ + tui_nav_key(&v, 'g', 0, 0, 0, 0); + tui_nav_key(&v, '2', 0, 0, 0, 0); + CHECK(!v.goto_search && v.sel == 1); + tui_nav_key(&v, 'g', 0, 0, 0, 0); /* 'g' closes a number prompt */ + CHECK(!v.goto_active); + + /* without row texts a letter does not search */ + v.items = NULL; + tui_nav_key(&v, 'g', 0, 0, 0, 0); + tui_nav_key(&v, 'h', 0, 0, 0, 0); + CHECK(v.goto_active && !v.goto_search && v.sel == 1); + tui_nav_key(&v, 27, 0, 0, 0, 0); + CHECK(!v.goto_active); + + /* menu section headers are never a match */ + const char *menu[] = { "\001Hyra", "Hyra kontor", "Övrigt" }; + const unsigned char sel[] = { 0, 1, 1 }; + nav_init(&v, 3); + v.items = menu; + v.selectable = sel; + v.sel = 2; + tui_nav_key(&v, 'g', 0, 0, 0, 0); + tui_nav_key(&v, 'h', 0, 0, 0, 0); + CHECK(v.sel == 1); +} + static void test_nav_sections(void) { struct tui_list_nav v; @@ -1001,6 +1093,7 @@ int main(void) test_sticky(); test_nav(); test_nav_sections(); + test_goto_search(); test_form_nav(); test_form_actions(); test_form_focus(); |
