summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-choose-tree.c12
-rw-r--r--mode-tree.c85
-rw-r--r--tmux.133
-rw-r--r--tmux.h9
-rw-r--r--window-buffer.c29
-rw-r--r--window-client.c21
-rw-r--r--window-tree.c84
7 files changed, 164 insertions, 109 deletions
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index f8f24f12..873b0286 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -30,8 +30,8 @@ const struct cmd_entry cmd_choose_tree_entry = {
.name = "choose-tree",
.alias = NULL,
- .args = { "st:w", 0, 1 },
- .usage = "[-sw] " 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 = { "t:", 0, 1 },
- .usage = 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 = { "t:", 0, 1 },
- .usage = 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/mode-tree.c b/mode-tree.c
index 1093aff3..10a56304 100644
--- a/mode-tree.c
+++ b/mode-tree.c
@@ -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 {
@@ -273,12 +275,15 @@ 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),
+mode_tree_start(struct window_pane *wp, struct args *args,
+ 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)
{
struct mode_tree_data *mtd;
+ const char *sort;
+ u_int i;
mtd = xcalloc(1, sizeof *mtd);
mtd->references = 1;
@@ -290,6 +295,19 @@ mode_tree_start(struct window_pane *wp, void (*buildcb)(void *, u_int,
mtd->sort_size = sort_size;
mtd->sort_type = 0;
+ sort = args_get(args, 'O');
+ if (sort != NULL) {
+ for (i = 0; i < sort_size; i++) {
+ if (strcasecmp(sort, sort_list[i]) == 0)
+ mtd->sort_type = i;
+ }
+ }
+
+ 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;
@@ -317,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);
@@ -351,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);
}
@@ -564,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;
@@ -590,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);
@@ -616,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
@@ -631,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);
@@ -648,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)
@@ -801,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/tmux.1 b/tmux.1
index 88aefe88..26dc7a77 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1358,6 +1358,8 @@ 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
.Xc
@@ -1380,6 +1382,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
@@ -1393,10 +1396,21 @@ If
.Ar template
is not given, "detach-client -t '%%'" is used.
.Pp
+.Fl O
+specifies the initial sort order: one of
+.Ql name ,
+.Ql size ,
+.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
.Xc
@@ -1432,6 +1446,14 @@ If
.Ar template
is not given, "switch-client -t '%%'" is used.
.Pp
+.Fl O
+specifies the initial sort order: one of
+.Ql index ,
+.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
@@ -3963,6 +3985,8 @@ 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
.Xc
@@ -3981,6 +4005,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
@@ -3994,6 +4019,14 @@ If
.Ar template
is not given, "paste-buffer -b '%%'" is used.
.Pp
+.Fl O
+specifies the initial sort order: one of
+.Ql time ,
+.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/tmux.h b/tmux.h
index c9b42306..0da7080f 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2205,10 +2205,11 @@ void mode_tree_each_tagged(struct mode_tree_data *, void (*)(void *, void *,
key_code), key_code, int);
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), int (*)(void *, void *, const char *),
- void *, const char **, u_int, struct screen **);
+struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
+ 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/window-buffer.c b/window-buffer.c
index daceafbe..cc05ceef 100644
--- a/window-buffer.c
+++ b/window-buffer.c
@@ -45,13 +45,13 @@ const struct window_mode window_buffer_mode = {
};
enum window_buffer_sort_type {
- WINDOW_BUFFER_BY_NAME,
WINDOW_BUFFER_BY_TIME,
+ WINDOW_BUFFER_BY_NAME,
WINDOW_BUFFER_BY_SIZE,
};
static const char *window_buffer_sort_list[] = {
- "name",
"time",
+ "name",
"size"
};
@@ -124,14 +124,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]);
@@ -166,6 +167,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';
@@ -256,7 +273,7 @@ window_buffer_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
else
data->command = xstrdup(args->argv[0]);
- data->data = mode_tree_start(wp, window_buffer_build,
+ data->data = mode_tree_start(wp, args, window_buffer_build,
window_buffer_draw, window_buffer_search, data,
window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
diff --git a/window-client.c b/window-client.c
index 483ce8fe..9da8431e 100644
--- a/window-client.c
+++ b/window-client.c
@@ -54,8 +54,8 @@ enum window_client_sort_type {
static const char *window_client_sort_list[] = {
"name",
"size",
- "creation time",
- "activity time"
+ "creation",
+ "activity"
};
struct window_client_itemdata {
@@ -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';
@@ -247,7 +256,7 @@ window_client_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
else
data->command = xstrdup(args->argv[0]);
- data->data = mode_tree_start(wp, window_client_build,
+ data->data = mode_tree_start(wp, args, window_client_build,
window_client_draw, NULL, data, window_client_sort_list,
nitems(window_client_sort_list), &s);
diff --git a/window-tree.c b/window-tree.c
index b19ee9e6..d8ff061e 100644
--- a/window-tree.c
+++ b/window-tree.c
@@ -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,18 +485,13 @@ 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
data->command = xstrdup(args->argv[0]);
- data->data = mode_tree_start(wp, window_tree_build, window_tree_draw,
- window_tree_search, data, window_tree_sort_list,
+ data->data = mode_tree_start(wp, args, 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);
@@ -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)