1
0
mirror of https://github.com/tmux/tmux.git synced 2025-03-24 06:48:48 +00:00

Extend filters (f key) to buffer and client mode and add -f flag to

specify to command.
This commit is contained in:
nicm 2017-06-09 16:01:39 +00:00
parent bab4da5133
commit adcd5aff6f
7 changed files with 121 additions and 99 deletions

View File

@ -30,8 +30,8 @@ const struct cmd_entry cmd_choose_tree_entry = {
.name = "choose-tree", .name = "choose-tree",
.alias = NULL, .alias = NULL,
.args = { "O:st:w", 0, 1 }, .args = { "f:O:st:w", 0, 1 },
.usage = "[-sw] [-O sort-order] " CMD_TARGET_PANE_USAGE, .usage = "[-sw] [-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@ -43,8 +43,8 @@ const struct cmd_entry cmd_choose_client_entry = {
.name = "choose-client", .name = "choose-client",
.alias = NULL, .alias = NULL,
.args = { "O:t:", 0, 1 }, .args = { "f:O:t:", 0, 1 },
.usage = "[-O sort-order] " CMD_TARGET_PANE_USAGE, .usage = "[-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
@ -56,8 +56,8 @@ const struct cmd_entry cmd_choose_buffer_entry = {
.name = "choose-buffer", .name = "choose-buffer",
.alias = NULL, .alias = NULL,
.args = { "O:t:", 0, 1 }, .args = { "f:O:t:", 0, 1 },
.usage = "[-O sort-order] " CMD_TARGET_PANE_USAGE, .usage = "[-f filter] [-O sort-order] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },

View File

@ -39,7 +39,8 @@ struct mode_tree_data {
u_int sort_size; u_int sort_size;
u_int sort_type; 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); struct screen *(*drawcb)(void *, void *, u_int, u_int);
int (*searchcb)(void*, void *, const char *); int (*searchcb)(void*, void *, const char *);
@ -59,7 +60,8 @@ struct mode_tree_data {
struct screen screen; struct screen screen;
char *ss; char *search;
char *filter;
}; };
struct mode_tree_item { 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 * struct mode_tree_data *
mode_tree_start(struct window_pane *wp, struct args *args, 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), struct screen *(*drawcb)(void *, void *, u_int, u_int),
int (*searchcb)(void *, void *, const char *), void *modedata, int (*searchcb)(void *, void *, const char *), void *modedata,
const char **sort_list, u_int sort_size, struct screen **s) 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->buildcb = buildcb;
mtd->drawcb = drawcb; mtd->drawcb = drawcb;
mtd->searchcb = searchcb; mtd->searchcb = searchcb;
@ -328,7 +335,9 @@ mode_tree_build(struct mode_tree_data *mtd)
TAILQ_CONCAT(&mtd->saved, &mtd->children, entry); TAILQ_CONCAT(&mtd->saved, &mtd->children, entry);
TAILQ_INIT(&mtd->children); 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); mode_tree_free_items(&mtd->saved);
TAILQ_INIT(&mtd->saved); TAILQ_INIT(&mtd->saved);
@ -362,6 +371,9 @@ mode_tree_free(struct mode_tree_data *mtd)
mode_tree_clear_lines(mtd); mode_tree_clear_lines(mtd);
screen_free(&mtd->screen); screen_free(&mtd->screen);
free(mtd->search);
free(mtd->filter);
mtd->dead = 1; mtd->dead = 1;
mode_tree_remove_ref(mtd); 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; struct mode_tree_item *mti, *last, *next;
if (mtd->ss == NULL) if (mtd->search == NULL)
return (NULL); return (NULL);
mti = last = mtd->line_list[mtd->current].item; mti = last = mtd->line_list[mtd->current].item;
@ -601,11 +613,11 @@ mode_tree_search_for(struct mode_tree_data *mtd)
break; break;
if (mtd->searchcb == NULL) { if (mtd->searchcb == NULL) {
if (strstr(mti->name, mtd->ss) != NULL) if (strstr(mti->name, mtd->search) != NULL)
return (mti); return (mti);
continue; continue;
} }
if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->ss)) if (mtd->searchcb(mtd->modedata, mti->itemdata, mtd->search))
return (mti); return (mti);
} }
return (NULL); return (NULL);
@ -627,10 +639,11 @@ mode_tree_search_set(struct mode_tree_data *mtd)
loop->expanded = 1; loop->expanded = 1;
loop = loop->parent; loop = loop->parent;
} }
mode_tree_build(mtd);
mode_tree_build(mtd);
mode_tree_set_current(mtd, tag); mode_tree_set_current(mtd, tag);
mode_tree_draw(mtd); mode_tree_draw(mtd);
mtd->wp->flags |= PANE_REDRAW;
} }
static int static int
@ -642,12 +655,12 @@ mode_tree_search_callback(__unused struct client *c, void *data, const char *s,
if (mtd->dead) if (mtd->dead)
return (0); return (0);
free(mtd->ss); free(mtd->search);
if (*s == '\0') { if (s == NULL || *s == '\0') {
mtd->ss = NULL; mtd->search = NULL;
return (0); return (0);
} }
mtd->ss = xstrdup(s); mtd->search = xstrdup(s);
mode_tree_search_set(mtd); mode_tree_search_set(mtd);
return (0); return (0);
@ -659,6 +672,35 @@ mode_tree_search_free(void *data)
mode_tree_remove_ref(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 int
mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
struct mouse_event *m) struct mouse_event *m)
@ -812,6 +854,12 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
case 'n': case 'n':
mode_tree_search_set(mtd); mode_tree_search_set(mtd);
break; 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); return (0);
} }

11
tmux.1
View File

@ -1354,6 +1354,7 @@ the end of the visible pane.
The default is to capture only the visible contents of the pane. The default is to capture only the visible contents of the pane.
.It Xo .It Xo
.Ic choose-client .Ic choose-client
.Op Fl f Ar filter
.Op Fl O Ar sort-order .Op Fl O Ar sort-order
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Op Ar template .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 "X" Ta "Detach and HUP tagged clients"
.It Li "z" Ta "Suspend selected client" .It Li "z" Ta "Suspend selected client"
.It Li "Z" Ta "Suspend tagged clients" .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 "O" Ta "Change sort order"
.It Li "q" Ta "Exit mode" .It Li "q" Ta "Exit mode"
.El .El
@ -1397,10 +1399,13 @@ specifies the initial sort order: one of
.Ql creation , .Ql creation ,
or or
.Ql activity . .Ql activity .
.Fl f
specifies an initial filter.
This command works only if at least one client is attached. This command works only if at least one client is attached.
.It Xo .It Xo
.Ic choose-tree .Ic choose-tree
.Op Fl sw .Op Fl sw
.Op Fl f Ar filter
.Op Fl O Ar sort-order .Op Fl O Ar sort-order
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Op Ar template .Op Ar template
@ -1443,6 +1448,8 @@ specifies the initial sort order: one of
.Ql name , .Ql name ,
or or
.Ql time . .Ql time .
.Fl f
specifies an initial filter.
This command works only if at least one client is attached. This command works only if at least one client is attached.
.It Xo .It Xo
.Ic display-panes .Ic display-panes
@ -3972,6 +3979,7 @@ The buffer commands are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo .It Xo
.Ic choose-buffer .Ic choose-buffer
.Op Fl f Ar filter
.Op Fl O Ar sort-order .Op Fl O Ar sort-order
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Op Ar template .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 "C-t" Ta "Tag all buffers"
.It Li "d" Ta "Delete selected buffer" .It Li "d" Ta "Delete selected buffer"
.It Li "D" Ta "Delete tagged buffers" .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 "O" Ta "Change sort order"
.It Li "q" Ta "Exit mode" .It Li "q" Ta "Exit mode"
.El .El
@ -4010,6 +4019,8 @@ specifies the initial sort order: one of
.Ql name .Ql name
or or
.Ql size . .Ql size .
.Fl f
specifies an initial filter.
This command works only if at least one client is attached. This command works only if at least one client is attached.
.It Ic clear-history Op Fl t Ar target-pane .It Ic clear-history Op Fl t Ar target-pane
.D1 (alias: Ic clearhist ) .D1 (alias: Ic clearhist )

7
tmux.h
View File

@ -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_up(struct mode_tree_data *, int);
void mode_tree_down(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 *, struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
void (*)(void *, u_int, uint64_t *), struct screen *(*)(void *, void (*)(void *, u_int, uint64_t *, const char *),
void *, u_int, u_int), int (*)(void *, void *, const char *), struct screen *(*)(void *, void *, u_int, u_int),
void *, const char **, u_int, struct screen **); int (*)(void *, void *, const char *), void *, const char **,
u_int, struct screen **);
void mode_tree_build(struct mode_tree_data *); void mode_tree_build(struct mode_tree_data *);
void mode_tree_free(struct mode_tree_data *); void mode_tree_free(struct mode_tree_data *);
void mode_tree_resize(struct mode_tree_data *, u_int, u_int); void mode_tree_resize(struct mode_tree_data *, u_int, u_int);

View File

@ -125,14 +125,15 @@ window_buffer_cmp_size(const void *a0, const void *b0)
} }
static void 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_modedata *data = modedata;
struct window_buffer_itemdata *item; struct window_buffer_itemdata *item;
u_int i; u_int i;
struct paste_buffer *pb; struct paste_buffer *pb;
char *tim; char *tim, *text, *cp;
char *text; struct format_tree *ft;
for (i = 0; i < data->item_size; i++) for (i = 0; i < data->item_size; i++)
window_buffer_free_item(data->item_list[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++) { for (i = 0; i < data->item_size; i++) {
item = data->item_list[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); tim = ctime(&item->created);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';

View File

@ -141,14 +141,14 @@ window_client_cmp_activity_time(const void *a0, const void *b0)
} }
static void 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_modedata *data = modedata;
struct window_client_itemdata *item; struct window_client_itemdata *item;
u_int i; u_int i;
struct client *c; struct client *c;
char *tim; char *tim, *text, *cp;
char *text;
for (i = 0; i < data->item_size; i++) for (i = 0; i < data->item_size; i++)
window_client_free_item(data->item_list[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]; item = data->item_list[i];
c = item->c; 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); tim = ctime(&c->activity_time.tv_sec);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';

View File

@ -81,8 +81,6 @@ struct window_tree_modedata {
struct client *client; struct client *client;
const char *entered; const char *entered;
char *filter;
struct cmd_find_state fs; struct cmd_find_state fs;
enum window_tree_type type; enum window_tree_type type;
}; };
@ -227,7 +225,7 @@ window_tree_build_pane(struct session *s, struct winlink *wl,
static int static int
window_tree_build_window(struct session *s, struct winlink *wl, void* modedata, 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_modedata *data = modedata;
struct window_tree_itemdata *item; struct window_tree_itemdata *item;
@ -261,8 +259,8 @@ window_tree_build_window(struct session *s, struct winlink *wl, void* modedata,
l = NULL; l = NULL;
n = 0; n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) { TAILQ_FOREACH(wp, &wl->window->panes, entry) {
if (!no_filter && data->filter != NULL) { if (filter != NULL) {
cp = format_single(NULL, data->filter, NULL, s, wl, wp); cp = format_single(NULL, filter, NULL, s, wl, wp);
if (!format_true(cp)) { if (!format_true(cp)) {
free(cp); free(cp);
continue; continue;
@ -298,7 +296,7 @@ window_tree_build_window(struct session *s, struct winlink *wl, void* modedata,
static void static void
window_tree_build_session(struct session *s, void* modedata, 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_modedata *data = modedata;
struct window_tree_itemdata *item; struct window_tree_itemdata *item;
@ -349,7 +347,7 @@ window_tree_build_session(struct session *s, void* modedata,
empty = 0; empty = 0;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (!window_tree_build_window(s, l[i], modedata, sort_type, mti, if (!window_tree_build_window(s, l[i], modedata, sort_type, mti,
no_filter)) filter))
empty++; empty++;
} }
if (empty == n) { if (empty == n) {
@ -361,14 +359,13 @@ window_tree_build_session(struct session *s, void* modedata,
} }
static void 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 window_tree_modedata *data = modedata;
struct session *s, **l; struct session *s, **l;
u_int n, i; u_int n, i;
int no_filter = 0;
restart:
for (i = 0; i < data->item_size; i++) for (i = 0; i < data->item_size; i++)
window_tree_free_item(data->item_list[i]); window_tree_free_item(data->item_list[i]);
free(data->item_list); free(data->item_list);
@ -393,14 +390,9 @@ restart:
} }
for (i = 0; i < n; i++) 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); free(l);
if (!no_filter && data->item_size == 0) {
no_filter = 1;
goto restart;
}
switch (data->type) { switch (data->type) {
case WINDOW_TREE_NONE: case WINDOW_TREE_NONE:
break; break;
@ -493,11 +485,6 @@ window_tree_init(struct window_pane *wp, struct cmd_find_state *fs,
data->wp = wp; data->wp = wp;
data->references = 1; 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) if (args == NULL || args->argc == 0)
data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND); data->command = xstrdup(WINDOW_TREE_DEFAULT_COMMAND);
else else
@ -529,8 +516,6 @@ window_tree_destroy(struct window_tree_modedata *data)
window_tree_free_item(data->item_list[i]); window_tree_free_item(data->item_list[i]);
free(data->item_list); free(data->item_list);
free(data->filter);
free(data->command); free(data->command);
free(data); free(data);
} }
@ -653,37 +638,6 @@ window_tree_command_free(void *modedata)
window_tree_destroy(data); 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 static void
window_tree_key(struct window_pane *wp, struct client *c, window_tree_key(struct window_pane *wp, struct client *c,
__unused struct session *s, key_code key, struct mouse_event *m) __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; int finished;
u_int tagged; 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); finished = mode_tree_key(data->data, c, &key, m);
switch (key) { 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 ':': case ':':
tagged = mode_tree_count_tagged(data->data); tagged = mode_tree_count_tagged(data->data);
if (tagged != 0) if (tagged != 0)