aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nncmpp.actions1
-rw-r--r--nncmpp.c54
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 },