From 024c311a845aceb9006eee42585000674918f9dc Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 9 Jun 2017 16:01:39 +0000 Subject: [PATCH] Extend filters (f key) to buffer and client mode and add -f flag to specify to command. --- usr.bin/tmux/cmd-choose-tree.c | 14 +++--- usr.bin/tmux/mode-tree.c | 74 ++++++++++++++++++++++++------ usr.bin/tmux/tmux.1 | 13 +++++- usr.bin/tmux/tmux.h | 9 ++-- usr.bin/tmux/window-buffer.c | 25 +++++++++-- usr.bin/tmux/window-client.c | 17 +++++-- usr.bin/tmux/window-tree.c | 82 ++++------------------------------ 7 files changed, 128 insertions(+), 106 deletions(-) diff --git a/usr.bin/tmux/cmd-choose-tree.c b/usr.bin/tmux/cmd-choose-tree.c index a8268ff4fa3..124e51c1235 100644 --- a/usr.bin/tmux/cmd-choose-tree.c +++ b/usr.bin/tmux/cmd-choose-tree.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-choose-tree.c,v 1.36 2017/06/09 15:29:15 nicm Exp $ */ +/* $OpenBSD: cmd-choose-tree.c,v 1.37 2017/06/09 16:01:39 nicm Exp $ */ /* * Copyright (c) 2012 Thomas Adam @@ -30,8 +30,8 @@ const struct cmd_entry cmd_choose_tree_entry = { .name = "choose-tree", .alias = NULL, - .args = { "O:st:w", 0, 1 }, - .usage = "[-sw] [-O sort-order] " CMD_TARGET_PANE_USAGE, + .args = { "f:O:st:w", 0, 1 }, + .usage = "[-sw] [-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -43,8 +43,8 @@ const struct cmd_entry cmd_choose_client_entry = { .name = "choose-client", .alias = NULL, - .args = { "O:t:", 0, 1 }, - .usage = "[-O sort-order] " CMD_TARGET_PANE_USAGE, + .args = { "f:O:t:", 0, 1 }, + .usage = "[-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -56,8 +56,8 @@ const struct cmd_entry cmd_choose_buffer_entry = { .name = "choose-buffer", .alias = NULL, - .args = { "O:t:", 0, 1 }, - .usage = "[-O sort-order] " CMD_TARGET_PANE_USAGE, + .args = { "f:O:t:", 0, 1 }, + .usage = "[-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/usr.bin/tmux/mode-tree.c b/usr.bin/tmux/mode-tree.c index b9ffe63a931..85077c6f18a 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.5 2017/06/09 15:29:15 nicm Exp $ */ +/* $OpenBSD: mode-tree.c,v 1.6 2017/06/09 16:01:39 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -39,7 +39,8 @@ struct mode_tree_data { u_int sort_size; u_int sort_type; - void (*buildcb)(void *, u_int, uint64_t *); + void (*buildcb)(void *, u_int, uint64_t *, + const char *); struct screen *(*drawcb)(void *, void *, u_int, u_int); int (*searchcb)(void*, void *, const char *); @@ -59,7 +60,8 @@ struct mode_tree_data { struct screen screen; - char *ss; + char *search; + char *filter; }; struct mode_tree_item { @@ -274,7 +276,7 @@ mode_tree_each_tagged(struct mode_tree_data *mtd, void (*cb)(void *, void *, struct mode_tree_data * mode_tree_start(struct window_pane *wp, struct args *args, - void (*buildcb)(void *, u_int, uint64_t *), + void (*buildcb)(void *, u_int, uint64_t *, const char *), struct screen *(*drawcb)(void *, void *, u_int, u_int), int (*searchcb)(void *, void *, const char *), void *modedata, const char **sort_list, u_int sort_size, struct screen **s) @@ -301,6 +303,11 @@ mode_tree_start(struct window_pane *wp, struct args *args, } } + if (args_has(args, 'f')) + mtd->filter = xstrdup(args_get(args, 'f')); + else + mtd->filter = NULL; + mtd->buildcb = buildcb; mtd->drawcb = drawcb; mtd->searchcb = searchcb; @@ -328,7 +335,9 @@ mode_tree_build(struct mode_tree_data *mtd) TAILQ_CONCAT(&mtd->saved, &mtd->children, entry); TAILQ_INIT(&mtd->children); - mtd->buildcb(mtd->modedata, mtd->sort_type, &tag); + mtd->buildcb(mtd->modedata, mtd->sort_type, &tag, mtd->filter); + if (TAILQ_EMPTY(&mtd->children)) + mtd->buildcb(mtd->modedata, mtd->sort_type, &tag, NULL); mode_tree_free_items(&mtd->saved); TAILQ_INIT(&mtd->saved); @@ -362,6 +371,9 @@ mode_tree_free(struct mode_tree_data *mtd) mode_tree_clear_lines(mtd); screen_free(&mtd->screen); + free(mtd->search); + free(mtd->filter); + mtd->dead = 1; mode_tree_remove_ref(mtd); } @@ -575,7 +587,7 @@ mode_tree_search_for(struct mode_tree_data *mtd) { struct mode_tree_item *mti, *last, *next; - if (mtd->ss == NULL) + if (mtd->search == NULL) return (NULL); mti = last = mtd->line_list[mtd->current].item; @@ -601,11 +613,11 @@ mode_tree_search_for(struct mode_tree_data *mtd) break; if (mtd->searchcb == NULL) { - if (strstr(mti->name, mtd->ss) != NULL) + if (strstr(mti->name, mtd->search) != NULL) return (mti); continue; } - if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->ss)) + if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search)) return (mti); } return (NULL); @@ -627,10 +639,11 @@ mode_tree_search_set(struct mode_tree_data *mtd) loop->expanded = 1; loop = loop->parent; } - mode_tree_build(mtd); + mode_tree_build(mtd); mode_tree_set_current(mtd, tag); mode_tree_draw(mtd); + mtd->wp->flags |= PANE_REDRAW; } static int @@ -642,12 +655,12 @@ mode_tree_search_callback(__unused struct client *c, void *data, const char *s, if (mtd->dead) return (0); - free(mtd->ss); - if (*s == '\0') { - mtd->ss = NULL; + free(mtd->search); + if (s == NULL || *s == '\0') { + mtd->search = NULL; return (0); } - mtd->ss = xstrdup(s); + mtd->search = xstrdup(s); mode_tree_search_set(mtd); return (0); @@ -659,6 +672,35 @@ mode_tree_search_free(void *data) mode_tree_remove_ref(data); } +static int +mode_tree_filter_callback(__unused struct client *c, void *data, const char *s, + __unused int done) +{ + struct mode_tree_data *mtd = data; + + if (mtd->dead) + return (0); + + if (mtd->filter != NULL) + free(mtd->filter); + if (s == NULL || *s == '\0') + mtd->filter = NULL; + else + mtd->filter = xstrdup(s); + + mode_tree_build(mtd); + mode_tree_draw(mtd); + mtd->wp->flags |= PANE_REDRAW; + + return (0); +} + +static void +mode_tree_filter_free(void *data) +{ + mode_tree_remove_ref(data); +} + int mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, struct mouse_event *m) @@ -812,6 +854,12 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, case 'n': mode_tree_search_set(mtd); break; + case 'f': + mtd->references++; + status_prompt_set(c, "(filter) ", mtd->filter, + mode_tree_filter_callback, mode_tree_filter_free, mtd, + PROMPT_NOFORMAT); + break; } return (0); } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 310640a8248..f10db6d247d 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.561 2017/06/09 15:29:15 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.562 2017/06/09 16:01:39 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -1354,6 +1354,7 @@ the end of the visible pane. The default is to capture only the visible contents of the pane. .It Xo .Ic choose-client +.Op Fl f Ar filter .Op Fl O Ar sort-order .Op Fl t Ar target-pane .Op Ar template @@ -1377,6 +1378,7 @@ The following keys may be used in client mode: .It Li "X" Ta "Detach and HUP tagged clients" .It Li "z" Ta "Suspend selected client" .It Li "Z" Ta "Suspend tagged clients" +.It Li "f" Ta "Enter a format to filter items" .It Li "O" Ta "Change sort order" .It Li "q" Ta "Exit mode" .El @@ -1397,10 +1399,13 @@ specifies the initial sort order: one of .Ql creation , or .Ql activity . +.Fl f +specifies an initial filter. This command works only if at least one client is attached. .It Xo .Ic choose-tree .Op Fl sw +.Op Fl f Ar filter .Op Fl O Ar sort-order .Op Fl t Ar target-pane .Op Ar template @@ -1443,6 +1448,8 @@ specifies the initial sort order: one of .Ql name , or .Ql time . +.Fl f +specifies an initial filter. This command works only if at least one client is attached. .It Xo .Ic display-panes @@ -3972,6 +3979,7 @@ The buffer commands are as follows: .Bl -tag -width Ds .It Xo .Ic choose-buffer +.Op Fl f Ar filter .Op Fl O Ar sort-order .Op Fl t Ar target-pane .Op Ar template @@ -3991,6 +3999,7 @@ The following keys may be used in buffer mode: .It Li "C-t" Ta "Tag all buffers" .It Li "d" Ta "Delete selected buffer" .It Li "D" Ta "Delete tagged buffers" +.It Li "f" Ta "Enter a format to filter items" .It Li "O" Ta "Change sort order" .It Li "q" Ta "Exit mode" .El @@ -4010,6 +4019,8 @@ specifies the initial sort order: one of .Ql name or .Ql size . +.Fl f +specifies an initial filter. This command works only if at least one client is attached. .It Ic clear-history Op Fl t Ar target-pane .D1 (alias: Ic clearhist ) diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 00b1ad9fa2d..dacca80a120 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.784 2017/06/09 15:29:15 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.785 2017/06/09 16:01:39 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -2202,9 +2202,10 @@ void mode_tree_each_tagged(struct mode_tree_data *, void (*)(void *, void *, 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 *, struct args *, - void (*)(void *, u_int, uint64_t *), struct screen *(*)(void *, - void *, u_int, u_int), int (*)(void *, void *, const char *), - void *, const char **, u_int, struct screen **); + void (*)(void *, u_int, uint64_t *, const char *), + struct screen *(*)(void *, 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); diff --git a/usr.bin/tmux/window-buffer.c b/usr.bin/tmux/window-buffer.c index 12995e64695..8aab9f051cc 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.7 2017/06/09 15:29:15 nicm Exp $ */ +/* $OpenBSD: window-buffer.c,v 1.8 2017/06/09 16:01:39 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -125,14 +125,15 @@ window_buffer_cmp_size(const void *a0, const void *b0) } static void -window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag) +window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag, + const char *filter) { struct window_buffer_modedata *data = modedata; struct window_buffer_itemdata *item; u_int i; struct paste_buffer *pb; - char *tim; - char *text; + char *tim, *text, *cp; + struct format_tree *ft; for (i = 0; i < data->item_size; i++) window_buffer_free_item(data->item_list[i]); @@ -167,6 +168,22 @@ window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag) for (i = 0; i < data->item_size; i++) { item = data->item_list[i]; + if (filter != NULL) { + pb = paste_get_name(item->name); + if (pb == NULL) + continue; + ft = format_create(NULL, NULL, FORMAT_NONE, 0); + format_defaults_paste_buffer(ft, pb); + cp = format_expand(ft, filter); + if (!format_true(cp)) { + free(cp); + format_free(ft); + continue; + } + free(cp); + format_free(ft); + } + tim = ctime(&item->created); *strchr(tim, '\n') = '\0'; diff --git a/usr.bin/tmux/window-client.c b/usr.bin/tmux/window-client.c index e3feb401446..25d2f389d12 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.5 2017/06/09 15:29:15 nicm Exp $ */ +/* $OpenBSD: window-client.c,v 1.6 2017/06/09 16:01:39 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -141,14 +141,14 @@ window_client_cmp_activity_time(const void *a0, const void *b0) } static void -window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag) +window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag, + const char *filter) { struct window_client_modedata *data = modedata; struct window_client_itemdata *item; u_int i; struct client *c; - char *tim; - char *text; + char *tim, *text, *cp; for (i = 0; i < data->item_size; i++) window_client_free_item(data->item_list[i]); @@ -189,6 +189,15 @@ window_client_build(void *modedata, u_int sort_type, __unused uint64_t *tag) item = data->item_list[i]; c = item->c; + if (filter != NULL) { + cp = format_single(NULL, filter, c, NULL, NULL, NULL); + if (!format_true(cp)) { + free(cp); + continue; + } + free(cp); + } + tim = ctime(&c->activity_time.tv_sec); *strchr(tim, '\n') = '\0'; diff --git a/usr.bin/tmux/window-tree.c b/usr.bin/tmux/window-tree.c index aed2e49e7bc..3f1f6d19a52 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.4 2017/06/09 15:29:15 nicm Exp $ */ +/* $OpenBSD: window-tree.c,v 1.5 2017/06/09 16:01:39 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -81,8 +81,6 @@ struct window_tree_modedata { struct client *client; const char *entered; - char *filter; - struct cmd_find_state fs; enum window_tree_type type; }; @@ -227,7 +225,7 @@ window_tree_build_pane(struct session *s, struct winlink *wl, static int window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, - u_int sort_type, struct mode_tree_item *parent, int no_filter) + u_int sort_type, struct mode_tree_item *parent, const char *filter) { struct window_tree_modedata *data = modedata; struct window_tree_itemdata *item; @@ -261,8 +259,8 @@ window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, l = NULL; n = 0; TAILQ_FOREACH(wp, &wl->window->panes, entry) { - if (!no_filter && data->filter != NULL) { - cp = format_single(NULL, data->filter, NULL, s, wl, wp); + if (filter != NULL) { + cp = format_single(NULL, filter, NULL, s, wl, wp); if (!format_true(cp)) { free(cp); continue; @@ -298,7 +296,7 @@ window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, static void window_tree_build_session(struct session *s, void* modedata, - u_int sort_type, int no_filter) + u_int sort_type, const char *filter) { struct window_tree_modedata *data = modedata; struct window_tree_itemdata *item; @@ -349,7 +347,7 @@ window_tree_build_session(struct session *s, void* modedata, empty = 0; for (i = 0; i < n; i++) { if (!window_tree_build_window(s, l[i], modedata, sort_type, mti, - no_filter)) + filter)) empty++; } if (empty == n) { @@ -361,14 +359,13 @@ window_tree_build_session(struct session *s, void* modedata, } static void -window_tree_build(void *modedata, u_int sort_type, uint64_t *tag) +window_tree_build(void *modedata, u_int sort_type, uint64_t *tag, + const char *filter) { struct window_tree_modedata *data = modedata; struct session *s, **l; u_int n, i; - int no_filter = 0; -restart: for (i = 0; i < data->item_size; i++) window_tree_free_item(data->item_list[i]); free(data->item_list); @@ -393,14 +390,9 @@ restart: } for (i = 0; i < n; i++) - window_tree_build_session(l[i], modedata, sort_type, no_filter); + window_tree_build_session(l[i], modedata, sort_type, filter); free(l); - if (!no_filter && data->item_size == 0) { - no_filter = 1; - goto restart; - } - switch (data->type) { case WINDOW_TREE_NONE: break; @@ -493,11 +485,6 @@ window_tree_init(struct window_pane *wp, struct cmd_find_state *fs, data->wp = wp; data->references = 1; - if (args_has(args, 'f')) - data->filter = xstrdup(args_get(args, 'f')); - else - data->filter = NULL; - if (args == NULL || args->argc == 0) data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND); else @@ -529,8 +516,6 @@ window_tree_destroy(struct window_tree_modedata *data) window_tree_free_item(data->item_list[i]); free(data->item_list); - free(data->filter); - free(data->command); free(data); } @@ -653,37 +638,6 @@ window_tree_command_free(void *modedata) window_tree_destroy(data); } -static int -window_tree_filter_callback(__unused struct client *c, void *modedata, - const char *s, __unused int done) -{ - struct window_tree_modedata *data = modedata; - - if (data->dead) - return (0); - - if (data->filter != NULL) - free(data->filter); - if (s == NULL || *s == '\0') - data->filter = NULL; - else - data->filter = xstrdup(s); - - mode_tree_build(data->data); - mode_tree_draw(data->data); - data->wp->flags |= PANE_REDRAW; - - return (0); -} - -static void -window_tree_filter_free(void *modedata) -{ - struct window_tree_modedata *data = modedata; - - window_tree_destroy(data); -} - static void window_tree_key(struct window_pane *wp, struct client *c, __unused struct session *s, key_code key, struct mouse_event *m) @@ -695,26 +649,8 @@ window_tree_key(struct window_pane *wp, struct client *c, int finished; u_int tagged; - /* - * t = toggle tag - * T = tag none - * C-t = tag all - * q = exit - * O = change sort order - * - * Enter = select item - * : = enter command - * f = enter filter - */ - finished = mode_tree_key(data->data, c, &key, m); switch (key) { - case 'f': - data->references++; - status_prompt_set(c, "(filter) ", data->filter, - window_tree_filter_callback, window_tree_filter_free, data, - PROMPT_NOFORMAT); - break; case ':': tagged = mode_tree_count_tagged(data->data); if (tagged != 0) -- 2.20.1