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.
pull/865/merge
nicm 2017-06-07 14:37:30 +00:00
parent 50b27c8c0d
commit 405cc337f3
6 changed files with 209 additions and 25 deletions

View File

@ -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);
}

6
tmux.1
View File

@ -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"

6
tmux.h
View File

@ -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 *);

View File

@ -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);

View File

@ -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':

View File

@ -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++;