From 9e7c1aee484b87222856bad26cc1188bf090e4be Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 24 May 2024 12:39:06 +0000 Subject: [PATCH] Add N to search backwards in tree modes, from Fadi Afani in GitHub issue 3982. --- mode-tree.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- tmux.1 | 12 ++++++++---- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/mode-tree.c b/mode-tree.c index cebd4f05..5a4e3bbc 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -25,6 +25,11 @@ #include "tmux.h" +enum mode_tree_search_dir { + MODE_TREE_SEARCH_FORWARD, + MODE_TREE_SEARCH_BACKWARD +}; + struct mode_tree_item; TAILQ_HEAD(mode_tree_list, mode_tree_item); @@ -68,6 +73,7 @@ struct mode_tree_data { char *search; char *filter; int no_matches; + enum mode_tree_search_dir search_dir; }; struct mode_tree_item { @@ -786,7 +792,49 @@ done: } static struct mode_tree_item * -mode_tree_search_for(struct mode_tree_data *mtd) +mode_tree_search_backward(struct mode_tree_data *mtd) +{ + struct mode_tree_item *mti, *last, *prev; + + if (mtd->search == NULL) + return (NULL); + + mti = last = mtd->line_list[mtd->current].item; + for (;;) { + if ((prev = TAILQ_PREV(mti, mode_tree_list, entry)) != NULL) { + /* Point to the last child in the previous subtree. */ + while (!TAILQ_EMPTY(&prev->children)) + prev = TAILQ_LAST(&prev->children, mode_tree_list); + mti = prev; + } else { + /* If prev is NULL, jump to the parent. */ + mti = mti->parent; + } + + if (mti == NULL) { + /* Point to the last child in the last root subtree. */ + prev = TAILQ_LAST(&mtd->children, mode_tree_list); + while (!TAILQ_EMPTY(&prev->children)) + prev = TAILQ_LAST(&prev->children, mode_tree_list); + mti = prev; + } + if (mti == last) + break; + + if (mtd->searchcb == NULL) { + if (strstr(mti->name, mtd->search) != NULL) + return (mti); + continue; + } + if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search)) + return (mti); + } + return (NULL); +} + + +static struct mode_tree_item * +mode_tree_search_forward(struct mode_tree_data *mtd) { struct mode_tree_item *mti, *last, *next; @@ -832,7 +880,10 @@ mode_tree_search_set(struct mode_tree_data *mtd) struct mode_tree_item *mti, *loop; uint64_t tag; - mti = mode_tree_search_for(mtd); + if (mtd->search_dir == MODE_TREE_SEARCH_FORWARD) + mti = mode_tree_search_forward(mtd); + else + mti = mode_tree_search_backward(mtd); if (mti == NULL) return; tag = mti->tag; @@ -1165,6 +1216,11 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, PROMPT_NOFORMAT, PROMPT_TYPE_SEARCH); break; case 'n': + mtd->search_dir = MODE_TREE_SEARCH_FORWARD; + mode_tree_search_set(mtd); + break; + case 'N': + mtd->search_dir = MODE_TREE_SEARCH_BACKWARD; mode_tree_search_set(mtd); break; case 'f': diff --git a/tmux.1 b/tmux.1 index fc4f3616..9d7d8cbd 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2295,7 +2295,8 @@ The following keys may be used in client mode: .It Li "Up" Ta "Select previous client" .It Li "Down" Ta "Select next client" .It Li "C-s" Ta "Search by name" -.It Li "n" Ta "Repeat last search" +.It Li "n" Ta "Repeat last search forwards" +.It Li "N" Ta "Repeat last search backwards" .It Li "t" Ta "Toggle if client is tagged" .It Li "T" Ta "Tag no clients" .It Li "C-t" Ta "Tag all clients" @@ -2382,7 +2383,8 @@ The following keys may be used in tree mode: .It Li "C-s" Ta "Search by name" .It Li "m" Ta "Set the marked pane" .It Li "M" Ta "Clear the marked pane" -.It Li "n" Ta "Repeat last search" +.It Li "n" Ta "Repeat last search forwards" +.It Li "N" Ta "Repeat last search backwards" .It Li "t" Ta "Toggle if item is tagged" .It Li "T" Ta "Tag no items" .It Li "C-t" Ta "Tag all items" @@ -2460,7 +2462,8 @@ The following keys may be used in customize mode: .It Li "u" Ta "Unset an option (set to default value if global) or unbind a key" .It Li "U" Ta "Unset tagged options and unbind tagged keys" .It Li "C-s" Ta "Search by name" -.It Li "n" Ta "Repeat last search" +.It Li "n" Ta "Repeat last search forwards" +.It Li "N" Ta "Repeat last search backwards" .It Li "t" Ta "Toggle if item is tagged" .It Li "T" Ta "Tag no items" .It Li "C-t" Ta "Tag all items" @@ -6467,7 +6470,8 @@ The following keys may be used in buffer mode: .It Li "Up" Ta "Select previous buffer" .It Li "Down" Ta "Select next buffer" .It Li "C-s" Ta "Search by name or content" -.It Li "n" Ta "Repeat last search" +.It Li "n" Ta "Repeat last search forwards" +.It Li "N" Ta "Repeat last search backwards" .It Li "t" Ta "Toggle if buffer is tagged" .It Li "T" Ta "Tag no buffers" .It Li "C-t" Ta "Tag all buffers" -- 2.11.4.GIT