From: nicm Date: Wed, 7 Jun 2017 14:37:30 +0000 (+0000) Subject: Add simple searching (C-s and n) to the various choose modes: by name X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=943a08b17c9c26a9e3af873d0b87346747b6bffd;p=openbsd Add simple searching (C-s and n) to the various choose modes: by name for client and tree, and by name and content for buffer. --- diff --git a/usr.bin/tmux/mode-tree.c b/usr.bin/tmux/mode-tree.c index dbd4d3627a9..d7e09571897 100644 --- a/usr.bin/tmux/mode-tree.c +++ b/usr.bin/tmux/mode-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mode-tree.c,v 1.2 2017/06/04 15:36:33 nicm Exp $ */ +/* $OpenBSD: mode-tree.c,v 1.3 2017/06/07 14:37:30 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -29,6 +29,9 @@ struct mode_tree_item; TAILQ_HEAD(mode_tree_list, mode_tree_item); struct mode_tree_data { + int dead; + u_int references; + struct window_pane *wp; void *modedata; @@ -38,6 +41,7 @@ struct mode_tree_data { void (*buildcb)(void *, u_int, uint64_t *); struct screen *(*drawcb)(void *, void *, u_int, u_int); + int (*searchcb)(void*, void *, const char *); struct mode_tree_list children; struct mode_tree_list saved; @@ -54,6 +58,8 @@ struct mode_tree_data { u_int current; struct screen screen; + + char *ss; }; struct mode_tree_item { @@ -171,6 +177,27 @@ mode_tree_clear_tagged(struct mode_tree_list *mtl) } } +static void +mode_tree_set_current(struct mode_tree_data *mtd, uint64_t tag) +{ + u_int i; + + for (i = 0; i < mtd->line_size; i++) { + if (mtd->line_list[i].item->tag == tag) + break; + } + if (i != mtd->line_size) { + mtd->current = i; + if (mtd->current > mtd->height - 1) + mtd->offset = 1 + mtd->current - mtd->height; + else + mtd->offset = 0; + } else { + mtd->current = 0; + mtd->offset = 0; + } +} + void mode_tree_up(struct mode_tree_data *mtd, int wrap) { @@ -248,11 +275,14 @@ mode_tree_each_tagged(struct mode_tree_data *mtd, void (*cb)(void *, void *, struct mode_tree_data * mode_tree_start(struct window_pane *wp, void (*buildcb)(void *, u_int, uint64_t *), struct screen *(*drawcb)(void *, void *, u_int, u_int), - void *modedata, const char **sort_list, u_int sort_size, struct screen **s) + int (*searchcb)(void *, void *, const char *), void *modedata, + const char **sort_list, u_int sort_size, struct screen **s) { struct mode_tree_data *mtd; mtd = xcalloc(1, sizeof *mtd); + mtd->references = 1; + mtd->wp = wp; mtd->modedata = modedata; @@ -262,6 +292,7 @@ mode_tree_start(struct window_pane *wp, void (*buildcb)(void *, u_int, mtd->buildcb = buildcb; mtd->drawcb = drawcb; + mtd->searchcb = searchcb; TAILQ_INIT(&mtd->children); @@ -277,7 +308,6 @@ mode_tree_build(struct mode_tree_data *mtd) { struct screen *s = &mtd->screen; uint64_t tag; - u_int i; if (mtd->line_list != NULL) tag = mtd->line_list[mtd->current].item->tag; @@ -295,16 +325,7 @@ mode_tree_build(struct mode_tree_data *mtd) mode_tree_clear_lines(mtd); mode_tree_build_lines(mtd, &mtd->children, 0); - for (i = 0; i < mtd->line_size; i++) { - if (mtd->line_list[i].item->tag == tag) - break; - } - if (i != mtd->line_size) - mtd->current = i; - else { - mtd->current = 0; - mtd->offset = 0; - } + mode_tree_set_current(mtd, tag); mtd->width = screen_size_x(s); mtd->height = (screen_size_y(s) / 3) * 2; @@ -316,13 +337,22 @@ mode_tree_build(struct mode_tree_data *mtd) mtd->height = screen_size_y(s); } +static void +mode_tree_remove_ref(struct mode_tree_data *mtd) +{ + if (--mtd->references == 0) + free(mtd); +} + void mode_tree_free(struct mode_tree_data *mtd) { mode_tree_free_items(&mtd->children); mode_tree_clear_lines(mtd); screen_free(&mtd->screen); - free(mtd); + + mtd->dead = 1; + mode_tree_remove_ref(mtd); } void @@ -529,8 +559,98 @@ mode_tree_draw(struct mode_tree_data *mtd) screen_write_stop(&ctx); } +static struct mode_tree_item * +mode_tree_search_for(struct mode_tree_data *mtd) +{ + struct mode_tree_item *mti, *last, *next; + + if (mtd->ss == NULL) + return (NULL); + + mti = last = mtd->line_list[mtd->current].item; + for (;;) { + if (!TAILQ_EMPTY(&mti->children)) + mti = TAILQ_FIRST(&mti->children); + else if ((next = TAILQ_NEXT(mti, entry)) != NULL) + mti = next; + else { + for (;;) { + mti = mti->parent; + if (mti == NULL) + break; + if ((next = TAILQ_NEXT(mti, entry)) != NULL) { + mti = next; + break; + } + } + } + if (mti == NULL) + mti = TAILQ_FIRST(&mtd->children); + if (mti == last) + break; + + if (mtd->searchcb == NULL) { + if (strstr(mti->name, mtd->ss) != NULL) + return (mti); + continue; + } + if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->ss)) + return (mti); + } + return (NULL); +} + +static void +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 (mti == NULL) + return; + tag = mti->tag; + + loop = mti->parent; + while (loop != NULL) { + loop->expanded = 1; + loop = loop->parent; + } + mode_tree_build(mtd); + + mode_tree_set_current(mtd, tag); + mode_tree_draw(mtd); +} + +static int +mode_tree_search_callback(__unused struct client *c, void *data, const char *s, + __unused int done) +{ + struct mode_tree_data *mtd = data; + + if (mtd->dead) + return (0); + + free(mtd->ss); + if (*s == '\0') { + mtd->ss = NULL; + return (0); + } + mtd->ss = xstrdup(s); + mode_tree_search_set(mtd); + + return (0); +} + +static void +mode_tree_search_free(void *data) +{ + mode_tree_remove_ref(data); +} + int -mode_tree_key(struct mode_tree_data *mtd, key_code *key, struct mouse_event *m) +mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, + struct mouse_event *m) { struct mode_tree_line *line; struct mode_tree_item *current, *parent; @@ -672,6 +792,15 @@ mode_tree_key(struct mode_tree_data *mtd, key_code *key, struct mouse_event *m) mode_tree_build(mtd); } break; + case '\023': /* C-s */ + mtd->references++; + status_prompt_set(c, "(search) ", "", + mode_tree_search_callback, mode_tree_search_free, mtd, + PROMPT_NOFORMAT); + break; + case 'n': + mode_tree_search_set(mtd); + break; } return (0); } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 5fc01f3d6dc..00f59f2d06c 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.558 2017/06/04 08:25:57 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.559 2017/06/07 14:37:30 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 4 2017 $ +.Dd $Mdocdate: June 7 2017 $ .Dt TMUX 1 .Os .Sh NAME @@ -1365,6 +1365,8 @@ The following keys may be used in client mode: .It Li "Enter" Ta "Choose selected client" .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 "t" Ta "Toggle if client is tagged" .It Li "T" Ta "Tag no clients" .It Li "C-t" Ta "Tag all clients" @@ -1406,6 +1408,8 @@ The following keys may be used in tree mode: .It Li "Enter" Ta "Choose selected item" .It Li "Up" Ta "Select previous item" .It Li "Down" Ta "Select next item" +.It Li "C-s" Ta "Search by name" +.It Li "n" Ta "Repeat last search" .It Li "t" Ta "Toggle if item is tagged" .It Li "T" Ta "Tag no items" .It Li "C-t" Ta "Tag all items" @@ -3958,6 +3962,8 @@ The following keys may be used in buffer mode: .It Li "Enter" Ta "Choose selected buffer" .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 "t" Ta "Toggle if buffer is tagged" .It Li "T" Ta "Tag no buffers" .It Li "C-t" Ta "Tag all buffers" diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index b80ee654350..96cbf39c0bd 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.781 2017/06/04 09:02:36 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.782 2017/06/07 14:37:30 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -2203,8 +2203,8 @@ void mode_tree_up(struct mode_tree_data *, int); void mode_tree_down(struct mode_tree_data *, int); struct mode_tree_data *mode_tree_start(struct window_pane *, void (*)(void *, u_int, uint64_t *), struct screen *(*)(void *, - void *, u_int, u_int), void *, const char **, u_int, - struct screen **); + void *, u_int, u_int), int (*)(void *, void *, const char *), + void *, const char **, u_int, struct screen **); void mode_tree_build(struct mode_tree_data *); void mode_tree_free(struct mode_tree_data *); void mode_tree_resize(struct mode_tree_data *, u_int, u_int); @@ -2213,7 +2213,7 @@ struct mode_tree_item *mode_tree_add(struct mode_tree_data *, const char *, int); void mode_tree_remove(struct mode_tree_data *, struct mode_tree_item *); void mode_tree_draw(struct mode_tree_data *); -int mode_tree_key(struct mode_tree_data *, key_code *, +int mode_tree_key(struct mode_tree_data *, struct client *, key_code *, struct mouse_event *); void mode_tree_run_command(struct client *, struct cmd_find_state *, const char *, const char *); diff --git a/usr.bin/tmux/window-buffer.c b/usr.bin/tmux/window-buffer.c index 0782227cc96..9ef3ea86106 100644 --- a/usr.bin/tmux/window-buffer.c +++ b/usr.bin/tmux/window-buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-buffer.c,v 1.3 2017/05/31 17:56:48 nicm Exp $ */ +/* $OpenBSD: window-buffer.c,v 1.4 2017/06/07 14:37:30 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -227,6 +227,22 @@ window_buffer_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy) return (&s); } +static int +window_buffer_search(__unused void *modedata, void *itemdata, const char *ss) +{ + struct window_buffer_itemdata *item = itemdata; + struct paste_buffer *pb; + const char *bufdata; + size_t bufsize; + + if ((pb = paste_get_name(item->name)) == NULL) + return (0); + if (strstr(item->name, ss) != NULL) + return (0); + bufdata = paste_buffer_data(pb, &bufsize); + return (memmem(bufdata, bufsize, ss, strlen(ss)) != NULL); +} + static struct screen * window_buffer_init(struct window_pane *wp, __unused struct cmd_find_state *fs, struct args *args) @@ -242,8 +258,8 @@ window_buffer_init(struct window_pane *wp, __unused struct cmd_find_state *fs, data->command = xstrdup(args->argv[0]); data->data = mode_tree_start(wp, window_buffer_build, - window_buffer_draw, data, window_buffer_sort_list, - nitems(window_buffer_sort_list), &s); + window_buffer_draw, window_buffer_search, data, + window_buffer_sort_list, nitems(window_buffer_sort_list), &s); mode_tree_build(data->data); mode_tree_draw(data->data); @@ -312,7 +328,7 @@ window_buffer_key(struct window_pane *wp, struct client *c, * Enter = paste buffer */ - finished = mode_tree_key(data->data, &key, m); + finished = mode_tree_key(data->data, c, &key, m); switch (key) { case 'd': item = mode_tree_get_current(data->data); diff --git a/usr.bin/tmux/window-client.c b/usr.bin/tmux/window-client.c index 585435b954e..6cc2b0574bc 100644 --- a/usr.bin/tmux/window-client.c +++ b/usr.bin/tmux/window-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-client.c,v 1.2 2017/05/31 15:27:57 nicm Exp $ */ +/* $OpenBSD: window-client.c,v 1.3 2017/06/07 14:37:30 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -224,7 +224,7 @@ window_client_init(struct window_pane *wp, __unused struct cmd_find_state *fs, data->command = xstrdup(args->argv[0]); data->data = mode_tree_start(wp, window_client_build, - window_client_draw, data, window_client_sort_list, + window_client_draw, NULL, data, window_client_sort_list, nitems(window_client_sort_list), &s); mode_tree_build(data->data); @@ -301,7 +301,7 @@ window_client_key(struct window_pane *wp, struct client *c, * Enter = detach client */ - finished = mode_tree_key(data->data, &key, m); + finished = mode_tree_key(data->data, c, &key, m); switch (key) { case 'd': case 'x': diff --git a/usr.bin/tmux/window-tree.c b/usr.bin/tmux/window-tree.c index 9f7d9304327..fea32793b0f 100644 --- a/usr.bin/tmux/window-tree.c +++ b/usr.bin/tmux/window-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-tree.c,v 1.2 2017/06/06 15:07:35 nicm Exp $ */ +/* $OpenBSD: window-tree.c,v 1.3 2017/06/07 14:37:30 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -440,6 +440,39 @@ window_tree_draw(__unused void *modedata, void *itemdata, u_int sx, u_int sy) return (&s); } +static int +window_tree_search(__unused void *modedata, void *itemdata, const char *ss) +{ + struct window_tree_itemdata *item = itemdata; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + const char *cmd; + + window_tree_pull_item(item, &s, &wl, &wp); + + switch (item->type) { + case WINDOW_TREE_NONE: + return (0); + case WINDOW_TREE_SESSION: + if (s == NULL) + return (0); + return (strstr(s->name, ss) != NULL); + case WINDOW_TREE_WINDOW: + if (s == NULL || wl == NULL) + return (0); + return (strstr(wl->window->name, ss) != NULL); + case WINDOW_TREE_PANE: + if (s == NULL || wl == NULL || wp == NULL) + break; + cmd = get_proc_name(wp->fd, wp->tty); + if (cmd == NULL || *cmd == '\0') + return (0); + return (strstr(cmd, ss) != NULL); + } + return (0); +} + static struct screen * window_tree_init(struct window_pane *wp, struct cmd_find_state *fs, struct args *args) @@ -470,8 +503,8 @@ window_tree_init(struct window_pane *wp, struct cmd_find_state *fs, else data->command = xstrdup(args->argv[0]); - data->data = mode_tree_start(wp, window_tree_build, - window_tree_draw, data, window_tree_sort_list, + data->data = mode_tree_start(wp, window_tree_build, window_tree_draw, + window_tree_search, data, window_tree_sort_list, nitems(window_tree_sort_list), &s); mode_tree_build(data->data); @@ -674,7 +707,7 @@ window_tree_key(struct window_pane *wp, struct client *c, * f = enter filter */ - finished = mode_tree_key(data->data, &key, m); + finished = mode_tree_key(data->data, c, &key, m); switch (key) { case 'f': data->references++;