From 4e3596db35cdda92782255fcf1ff5564b81d597f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Wed, 8 Dec 2021 16:14:00 +0100 Subject: Add rudimentary incremental search facility --- nncmpp.actions | 1 + nncmpp.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/nncmpp.actions b/nncmpp.actions index c59113f..2fde391 100644 --- a/nncmpp.actions +++ b/nncmpp.actions @@ -38,6 +38,7 @@ CHOOSE, Choose item DELETE, Delete item UP, Go up a level MULTISELECT, Toggle multiselect +INCREMENTAL_SEARCH, Incremental search SCROLL_UP, Scroll up SCROLL_DOWN, Scroll down diff --git a/nncmpp.c b/nncmpp.c index 0065d3e..9dc9752 100644 --- a/nncmpp.c +++ b/nncmpp.c @@ -2319,7 +2319,7 @@ app_setvol (int value) } static void -app_on_editor_end (bool confirmed) +app_on_mpd_command_editor_end (bool confirmed) { struct mpd_client *c = &g.client; if (!confirmed) @@ -2334,6 +2334,49 @@ app_on_editor_end (bool confirmed) mpd_client_idle (c, 0); } +static size_t +incremental_search_match (const ucs4_t *needle, size_t len, + const struct row_buffer *row) +{ + // TODO: case-insensitive search, wilcards, regexps, something easy to use + size_t i = 0; + for (; i < len && i < row->chars_len; i++) + if (needle[i] != row->chars[i].c) + break; + return i; +} + +static void +incremental_search_on_changed (void) +{ + struct tab *tab = g.active_tab; + if (!tab->item_count) + return; + + size_t best = 0, current = 0, index = MAX (tab->item_selected, 0), i = 0; + while (i++ < tab->item_count) + { + struct row_buffer buf = row_buffer_make (); + tab->on_item_draw (index, &buf, COLS); + current = incremental_search_match (g.editor.line, g.editor.len, &buf); + row_buffer_free (&buf); + if (best < current) + { + best = current; + tab->item_selected = index; + app_move_selection (0); + } + index = (index + 1) % tab->item_count; + } +} + +static void +incremental_search_on_end (bool confirmed) +{ + (void) confirmed; + // Required callback, nothing to do here. +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static bool @@ -2376,7 +2419,7 @@ app_process_action (enum action action) return true; case ACTION_MPD_COMMAND: line_editor_start (&g.editor, ':'); - g.editor.on_end = app_on_editor_end; + g.editor.on_end = app_on_mpd_command_editor_end; app_invalidate (); return true; default: @@ -2393,6 +2436,12 @@ app_process_action (enum action action) else tab->item_mark = tab->item_selected; return true; + case ACTION_INCREMENTAL_SEARCH: + line_editor_start (&g.editor, '/'); + g.editor.on_changed = incremental_search_on_changed; + g.editor.on_end = incremental_search_on_end; + app_invalidate (); + return true; case ACTION_TAB_LAST: if (!g.last_tab) @@ -2683,6 +2732,7 @@ g_normal_defaults[] = { "M-Up", ACTION_UP }, { "Backspace", ACTION_UP }, { "v", ACTION_MULTISELECT }, + { "C-s", ACTION_INCREMENTAL_SEARCH }, { "/", ACTION_MPD_SEARCH }, { "a", ACTION_MPD_ADD }, { "r", ACTION_MPD_REPLACE }, -- cgit v1.2.3