Allow choose commands to be used outside tmux, so long as at least one

client is attached.
pull/1/head
Nicholas Marriott 2013-03-21 16:09:59 +00:00
parent 8903c1f167
commit 180faf73af
8 changed files with 181 additions and 258 deletions

View File

@ -29,9 +29,6 @@
enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *); enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_buffer_callback(struct window_choose_data *);
void cmd_choose_buffer_free(struct window_choose_data *);
const struct cmd_entry cmd_choose_buffer_entry = { const struct cmd_entry cmd_choose_buffer_entry = {
"choose-buffer", NULL, "choose-buffer", NULL,
"F:t:", 0, 1, "F:t:", 0, 1,
@ -46,6 +43,7 @@ enum cmd_retval
cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c;
struct window_choose_data *cdata; struct window_choose_data *cdata;
struct winlink *wl; struct winlink *wl;
struct paste_buffer *pb; struct paste_buffer *pb;
@ -53,8 +51,8 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *template; const char *template;
u_int idx; u_int idx;
if (ctx->curclient == NULL) { if ((c = cmd_current_client(ctx)) == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -77,9 +75,8 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
idx = 0; idx = 0;
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) { while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
cdata = window_choose_data_create(ctx); cdata = window_choose_data_create(TREE_OTHER, c, c->session);
cdata->idx = idx - 1; cdata->idx = idx - 1;
cdata->client->references++;
cdata->ft_template = xstrdup(template); cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", idx - 1); format_add(cdata->ft, "line", "%u", idx - 1);
@ -93,34 +90,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
free(action); free(action);
window_choose_ready(wl->window->active, window_choose_ready(wl->window->active, 0, NULL);
0, cmd_choose_buffer_callback, cmd_choose_buffer_free);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
void
cmd_choose_buffer_callback(struct window_choose_data *cdata)
{
if (cdata == NULL)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
window_choose_ctx(cdata);
}
void
cmd_choose_buffer_free(struct window_choose_data *data)
{
struct window_choose_data *cdata = data;
if (cdata == NULL)
return;
cdata->client->references--;
free(cdata->command);
free(cdata->ft_template);
free(cdata);
}

View File

@ -30,7 +30,6 @@
enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_ctx *); enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_client_callback(struct window_choose_data *); void cmd_choose_client_callback(struct window_choose_data *);
void cmd_choose_client_free(struct window_choose_data *);
const struct cmd_entry cmd_choose_client_entry = { const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL, "choose-client", NULL,
@ -50,15 +49,16 @@ enum cmd_retval
cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c;
struct client *c1;
struct window_choose_data *cdata; struct window_choose_data *cdata;
struct winlink *wl; struct winlink *wl;
struct client *c;
const char *template; const char *template;
char *action; char *action;
u_int i, idx, cur; u_int i, idx, cur;
if (ctx->curclient == NULL) { if ((c = cmd_current_client(ctx)) == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -78,30 +78,29 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
cur = idx = 0; cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c1 = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL) if (c1 == NULL || c1->session == NULL)
continue; continue;
if (c == ctx->curclient) if (c1 == ctx->curclient)
cur = idx; cur = idx;
idx++; idx++;
cdata = window_choose_data_create(ctx); cdata = window_choose_data_create(TREE_OTHER, c, c->session);
cdata->idx = i; cdata->idx = i;
cdata->client->references++;
cdata->ft_template = xstrdup(template); cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", i); format_add(cdata->ft, "line", "%u", i);
format_session(cdata->ft, c->session); format_session(cdata->ft, c1->session);
format_client(cdata->ft, c); format_client(cdata->ft, c1);
cdata->command = cmd_template_replace(action, c->tty.path, 1); cdata->command = cmd_template_replace(action, c1->tty.path, 1);
window_choose_add(wl->window->active, cdata); window_choose_add(wl->window->active, cdata);
} }
free(action); free(action);
window_choose_ready(wl->window->active, window_choose_ready(wl->window->active, cur,
cur, cmd_choose_client_callback, cmd_choose_client_free); cmd_choose_client_callback);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
@ -113,7 +112,7 @@ cmd_choose_client_callback(struct window_choose_data *cdata)
if (cdata == NULL) if (cdata == NULL)
return; return;
if (cdata->client->flags & CLIENT_DEAD) if (cdata->start_client->flags & CLIENT_DEAD)
return; return;
if (cdata->idx > ARRAY_LENGTH(&clients) - 1) if (cdata->idx > ARRAY_LENGTH(&clients) - 1)
@ -122,19 +121,5 @@ cmd_choose_client_callback(struct window_choose_data *cdata)
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
return; return;
window_choose_ctx(cdata); window_choose_data_run(cdata);
}
void
cmd_choose_client_free(struct window_choose_data *cdata)
{
if (cdata == NULL)
return;
cdata->client->references--;
free(cdata->ft_template);
free(cdata->command);
format_free(cdata->ft);
free(cdata);
} }

View File

@ -33,9 +33,6 @@
enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_ctx *); enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_list_callback(struct window_choose_data *);
void cmd_choose_list_free(struct window_choose_data *);
const struct cmd_entry cmd_choose_list_entry = { const struct cmd_entry cmd_choose_list_entry = {
"choose-list", NULL, "choose-list", NULL,
"l:t:", 0, 1, "l:t:", 0, 1,
@ -50,13 +47,14 @@ enum cmd_retval
cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c;
struct winlink *wl; struct winlink *wl;
const char *list1; const char *list1;
char *template, *item, *copy, *list; char *template, *item, *copy, *list;
u_int idx; u_int idx;
if (ctx->curclient == NULL) { if ((c = cmd_current_client(ctx)) == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
@ -80,7 +78,7 @@ cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
if (*item == '\0') /* no empty entries */ if (*item == '\0') /* no empty entries */
continue; continue;
window_choose_add_item(wl->window->active, ctx, wl, item, window_choose_add_item(wl->window->active, c, wl, item,
template, idx); template, idx);
idx++; idx++;
} }
@ -92,32 +90,9 @@ cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
window_choose_ready(wl->window->active, 0, cmd_choose_list_callback, window_choose_ready(wl->window->active, 0, NULL);
cmd_choose_list_free);
free(template); free(template);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
void
cmd_choose_list_callback(struct window_choose_data *cdata)
{
if (cdata == NULL || (cdata->client->flags & CLIENT_DEAD))
return;
window_choose_ctx(cdata);
}
void
cmd_choose_list_free(struct window_choose_data *cdata)
{
cdata->session->references--;
cdata->client->references--;
free(cdata->ft_template);
free(cdata->command);
format_free(cdata->ft);
free(cdata);
}

View File

@ -34,9 +34,6 @@
enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_ctx *); enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_tree_callback(struct window_choose_data *);
void cmd_choose_tree_free(struct window_choose_data *);
const struct cmd_entry cmd_choose_tree_entry = { const struct cmd_entry cmd_choose_tree_entry = {
"choose-tree", NULL, "choose-tree", NULL,
"S:W:swub:c:t:", 0, 1, "S:W:swub:c:t:", 0, 1,
@ -74,6 +71,7 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx)
struct args *args = self->args; struct args *args = self->args;
struct winlink *wl, *wm; struct winlink *wl, *wm;
struct session *s, *s2; struct session *s, *s2;
struct client *c;
struct window_choose_data *wcd = NULL; struct window_choose_data *wcd = NULL;
const char *ses_template, *win_template; const char *ses_template, *win_template;
char *final_win_action, *cur_win_template; char *final_win_action, *cur_win_template;
@ -86,12 +84,13 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx)
ses_template = win_template = NULL; ses_template = win_template = NULL;
ses_action = win_action = NULL; ses_action = win_action = NULL;
if (ctx->curclient == NULL) { if ((c = cmd_current_client(ctx)) == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
s = ctx->curclient->session; if ((s = c->session) == NULL)
return (CMD_RETURN_ERROR);
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -175,7 +174,7 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
wcd = window_choose_add_session(wl->window->active, wcd = window_choose_add_session(wl->window->active,
ctx, s2, ses_template, (char *)ses_action, idx_ses); c, s2, ses_template, (char *)ses_action, idx_ses);
/* If we're just choosing sessions, skip choosing windows. */ /* If we're just choosing sessions, skip choosing windows. */
if (sflag && !wflag) { if (sflag && !wflag) {
@ -213,7 +212,7 @@ windows_only:
cur_win_template = final_win_template_last; cur_win_template = final_win_template_last;
window_choose_add_window(wl->window->active, window_choose_add_window(wl->window->active,
ctx, s2, wm, cur_win_template, c, s2, wm, cur_win_template,
final_win_action, final_win_action,
(wflag && !sflag) ? win_ses : idx_ses); (wflag && !sflag) ? win_ses : idx_ses);
@ -230,35 +229,10 @@ windows_only:
free(final_win_template_middle); free(final_win_template_middle);
free(final_win_template_last); free(final_win_template_last);
window_choose_ready(wl->window->active, cur_win, window_choose_ready(wl->window->active, cur_win, NULL);
cmd_choose_tree_callback, cmd_choose_tree_free);
if (args_has(args, 'u')) if (args_has(args, 'u'))
window_choose_expand_all(wl->window->active); window_choose_expand_all(wl->window->active);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
void
cmd_choose_tree_callback(struct window_choose_data *cdata)
{
if (cdata == NULL)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
window_choose_ctx(cdata);
}
void
cmd_choose_tree_free(struct window_choose_data *cdata)
{
cdata->session->references--;
cdata->client->references--;
free(cdata->ft_template);
free(cdata->command);
format_free(cdata->ft);
free(cdata);
}

View File

@ -31,7 +31,6 @@
enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_ctx *); enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_find_window_callback(struct window_choose_data *); void cmd_find_window_callback(struct window_choose_data *);
void cmd_find_window_free(struct window_choose_data *);
/* Flags for determining matching behavior. */ /* Flags for determining matching behavior. */
#define CMD_FIND_WINDOW_BY_TITLE 0x1 #define CMD_FIND_WINDOW_BY_TITLE 0x1
@ -131,6 +130,7 @@ enum cmd_retval
cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct args *args = self->args; struct args *args = self->args;
struct client *c;
struct window_choose_data *cdata; struct window_choose_data *cdata;
struct session *s; struct session *s;
struct winlink *wl, *wm; struct winlink *wl, *wm;
@ -139,11 +139,11 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
const char *template; const char *template;
u_int i, match_flags; u_int i, match_flags;
if (ctx->curclient == NULL) { if ((c = cmd_current_client(ctx)) == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "no client available");
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
s = ctx->curclient->session; s = c->session;
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
@ -180,9 +180,8 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
for (i = 0; i < ARRAY_LENGTH(&find_list); i++) { for (i = 0; i < ARRAY_LENGTH(&find_list); i++) {
wm = ARRAY_ITEM(&find_list, i).wl; wm = ARRAY_ITEM(&find_list, i).wl;
cdata = window_choose_data_create(ctx); cdata = window_choose_data_create(TREE_OTHER, c, c->session);
cdata->idx = wm->idx; cdata->idx = wm->idx;
cdata->client->references++;
cdata->wl = wm; cdata->wl = wm;
cdata->ft_template = xstrdup(template); cdata->ft_template = xstrdup(template);
@ -198,8 +197,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
window_choose_add(wl->window->active, cdata); window_choose_add(wl->window->active, cdata);
} }
window_choose_ready(wl->window->active, window_choose_ready(wl->window->active, 0, cmd_find_window_callback);
0, cmd_find_window_callback, cmd_find_window_free);
out: out:
ARRAY_FREE(&find_list); ARRAY_FREE(&find_list);
@ -215,7 +213,7 @@ cmd_find_window_callback(struct window_choose_data *cdata)
if (cdata == NULL) if (cdata == NULL)
return; return;
s = cdata->session; s = cdata->start_session;
if (!session_alive(s)) if (!session_alive(s))
return; return;
@ -228,16 +226,3 @@ cmd_find_window_callback(struct window_choose_data *cdata)
recalculate_sizes(); recalculate_sizes();
} }
} }
void
cmd_find_window_free(struct window_choose_data *cdata)
{
if (cdata == NULL)
return;
cdata->session->references--;
free(cdata->ft_template);
format_free(cdata->ft);
free(cdata);
}

21
tmux.1
View File

@ -1074,8 +1074,7 @@ For the meaning of the
flag, see the flag, see the
.Sx FORMATS .Sx FORMATS
section. section.
This command works only from inside This command works only if at least one client is attached.
.Nm .
.It Xo .It Xo
.Ic choose-list .Ic choose-list
.Op Fl l Ar items .Op Fl l Ar items
@ -1101,8 +1100,7 @@ also accepts format specifiers.
For the meaning of this see the For the meaning of this see the
.Sx FORMATS .Sx FORMATS
section. section.
This command works only from inside This command works only if at least one client is attached.
.Nm .
.It Xo .It Xo
.Ic choose-session .Ic choose-session
.Op Fl F Ar format .Op Fl F Ar format
@ -1124,8 +1122,7 @@ For the meaning of the
flag, see the flag, see the
.Sx FORMATS .Sx FORMATS
section. section.
This command works only from inside This command works only if at least one client is attached.
.Nm .
.It Xo .It Xo
.Ic choose-tree .Ic choose-tree
.Op Fl s .Op Fl s
@ -1189,8 +1186,7 @@ and
options, see the options, see the
.Sx FORMATS .Sx FORMATS
section. section.
This command only works from inside This command works only if at least one client is attached.
.Nm .
.It Xo .It Xo
.Ic choose-window .Ic choose-window
.Op Fl F Ar format .Op Fl F Ar format
@ -1212,8 +1208,7 @@ For the meaning of the
flag, see the flag, see the
.Sx FORMATS .Sx FORMATS
section. section.
This command works only from inside This command works only if at least one client is attached.
.Nm .
.It Ic display-panes Op Fl t Ar target-client .It Ic display-panes Op Fl t Ar target-client
.D1 (alias: Ic displayp) .D1 (alias: Ic displayp)
Display a visible indicator of each pane shown by Display a visible indicator of each pane shown by
@ -1257,8 +1252,7 @@ For the meaning of the
flag, see the flag, see the
.Sx FORMATS .Sx FORMATS
section. section.
This command only works from inside This command works only if at least one client is attached.
.Nm .
.It Xo Ic join-pane .It Xo Ic join-pane
.Op Fl bdhv .Op Fl bdhv
.Oo Fl l .Oo Fl l
@ -3306,8 +3300,7 @@ For the meaning of the
flag, see the flag, see the
.Sx FORMATS .Sx FORMATS
section. section.
This command works only from inside This command works only if at least one client is attached.
.Nm .
.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 )
Remove and free the history for the specified pane. Remove and free the history for the specified pane.

35
tmux.h
View File

@ -883,18 +883,24 @@ struct window_mode {
/* Structures for choose mode. */ /* Structures for choose mode. */
struct window_choose_data { struct window_choose_data {
struct client *client; struct client *start_client;
struct session *session; /* Session of current client. */ struct session *start_session;
struct session *tree_session; /* Session of items in tree. */
struct format_tree *ft;
struct winlink *wl;
char *ft_template;
char *command;
u_int idx; u_int idx;
int type; int type;
#define TREE_OTHER 0x0
#define TREE_WINDOW 0x1 #define TREE_WINDOW 0x1
#define TREE_SESSION 0x2 #define TREE_SESSION 0x2
struct session *tree_session; /* session of items in tree */
struct winlink *wl;
int pane_id; int pane_id;
char *ft_template;
struct format_tree *ft;
char *command;
}; };
struct window_choose_mode_item { struct window_choose_mode_item {
@ -2196,18 +2202,19 @@ extern const struct window_mode window_choose_mode;
void window_choose_add(struct window_pane *, void window_choose_add(struct window_pane *,
struct window_choose_data *); struct window_choose_data *);
void window_choose_ready(struct window_pane *, void window_choose_ready(struct window_pane *,
u_int, void (*)(struct window_choose_data *), u_int, void (*)(struct window_choose_data *));
void (*)(struct window_choose_data *)); struct window_choose_data *window_choose_data_create (int,
struct window_choose_data *window_choose_data_create(struct cmd_ctx *); struct client *, struct session *);
void window_choose_ctx(struct window_choose_data *); void window_choose_data_free(struct window_choose_data *);
void window_choose_data_run(struct window_choose_data *);
struct window_choose_data *window_choose_add_window(struct window_pane *, struct window_choose_data *window_choose_add_window(struct window_pane *,
struct cmd_ctx *, struct session *, struct winlink *, struct client *, struct session *, struct winlink *,
const char *, char *, u_int); const char *, char *, u_int);
struct window_choose_data *window_choose_add_session(struct window_pane *, struct window_choose_data *window_choose_add_session(struct window_pane *,
struct cmd_ctx *, struct session *, const char *, struct client *, struct session *, const char *,
char *, u_int); char *, u_int);
struct window_choose_data *window_choose_add_item(struct window_pane *, struct window_choose_data *window_choose_add_item(struct window_pane *,
struct cmd_ctx *, struct winlink *, const char *, struct client *, struct winlink *, const char *,
char *, u_int); char *, u_int);
void window_choose_expand_all(struct window_pane *); void window_choose_expand_all(struct window_pane *);

View File

@ -31,6 +31,8 @@ void window_choose_key(struct window_pane *, struct session *, int);
void window_choose_mouse( void window_choose_mouse(
struct window_pane *, struct session *, struct mouse_event *); struct window_pane *, struct session *, struct mouse_event *);
void window_choose_default_callback(struct window_choose_data *);
void window_choose_fire_callback( void window_choose_fire_callback(
struct window_pane *, struct window_choose_data *); struct window_pane *, struct window_choose_data *);
void window_choose_redraw_screen(struct window_pane *); void window_choose_redraw_screen(struct window_pane *);
@ -101,8 +103,7 @@ window_choose_add(struct window_pane *wp, struct window_choose_data *wcd)
void void
window_choose_ready(struct window_pane *wp, u_int cur, window_choose_ready(struct window_pane *wp, u_int cur,
void (*callbackfn)(struct window_choose_data *), void (*callbackfn)(struct window_choose_data *))
void (*freefn)(struct window_choose_data *))
{ {
struct window_choose_mode_data *data = wp->modedata; struct window_choose_mode_data *data = wp->modedata;
struct screen *s = &data->screen; struct screen *s = &data->screen;
@ -112,7 +113,8 @@ window_choose_ready(struct window_pane *wp, u_int cur,
data->top = ARRAY_LENGTH(&data->list) - screen_size_y(s); data->top = ARRAY_LENGTH(&data->list) - screen_size_y(s);
data->callbackfn = callbackfn; data->callbackfn = callbackfn;
data->freefn = freefn; if (data->callbackfn == NULL)
data->callbackfn = window_choose_default_callback;
ARRAY_CONCAT(&data->old_list, &data->list); ARRAY_CONCAT(&data->old_list, &data->list);
@ -154,24 +156,95 @@ window_choose_init(struct window_pane *wp)
} }
struct window_choose_data * struct window_choose_data *
window_choose_data_create(struct cmd_ctx *ctx) window_choose_data_create(int type, struct client *c, struct session *s)
{ {
struct window_choose_data *wcd; struct window_choose_data *wcd;
wcd = xmalloc(sizeof *wcd); wcd = xmalloc(sizeof *wcd);
wcd->type = type;
wcd->ft = format_create(); wcd->ft = format_create();
wcd->ft_template = NULL; wcd->ft_template = NULL;
wcd->command = NULL; wcd->command = NULL;
wcd->wl = NULL; wcd->wl = NULL;
wcd->tree_session = NULL; wcd->pane_id = -1;
wcd->client = ctx->curclient;
wcd->session = ctx->curclient->session;
wcd->idx = -1; wcd->idx = -1;
wcd->type = 0;
wcd->tree_session = NULL;
wcd->start_client = c;
wcd->start_client->references++;
wcd->start_session = s;
wcd->start_session->references++;
return (wcd); return (wcd);
} }
void
window_choose_data_free(struct window_choose_data *wcd)
{
wcd->start_client->references--;
wcd->start_session->references--;
if (wcd->tree_session != NULL)
wcd->tree_session->references--;
free(wcd->ft_template);
format_free(wcd->ft);
free(wcd->command);
free(wcd);
}
void
window_choose_data_run(struct window_choose_data *cdata)
{
struct cmd_ctx ctx;
struct cmd_list *cmdlist;
char *cause;
/*
* The command template will have already been replaced. But if it's
* NULL, bail here.
*/
if (cdata->command == NULL)
return;
if (cmd_string_parse(cdata->command, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->start_client, "%s", cause);
free(cause);
}
return;
}
ctx.msgdata = NULL;
ctx.curclient = cdata->start_client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
window_choose_default_callback(struct window_choose_data *wcd)
{
if (wcd == NULL)
return;
if (wcd->start_client->flags & CLIENT_DEAD)
return;
window_choose_data_run(wcd);
}
void void
window_choose_free(struct window_pane *wp) window_choose_free(struct window_pane *wp)
{ {
@ -181,8 +254,7 @@ window_choose_free(struct window_pane *wp)
for (i = 0; i < ARRAY_LENGTH(&data->old_list); i++) { for (i = 0; i < ARRAY_LENGTH(&data->old_list); i++) {
item = &ARRAY_ITEM(&data->old_list, i); item = &ARRAY_ITEM(&data->old_list, i);
if (data->freefn != NULL && item->wcd != NULL) window_choose_data_free(item->wcd);
data->freefn(item->wcd);
free(item->name); free(item->name);
} }
ARRAY_FREE(&data->list); ARRAY_FREE(&data->list);
@ -209,7 +281,7 @@ window_choose_resize(struct window_pane *wp, u_int sx, u_int sy)
void void
window_choose_fire_callback( window_choose_fire_callback(
struct window_pane *wp, struct window_choose_data *wcd) struct window_pane *wp, struct window_choose_data *wcd)
{ {
struct window_choose_mode_data *data = wp->modedata; struct window_choose_mode_data *data = wp->modedata;
const struct window_mode *oldmode; const struct window_mode *oldmode;
@ -299,7 +371,7 @@ window_choose_collapse_all(struct window_pane *wp)
struct session *s, *chosen; struct session *s, *chosen;
u_int i; u_int i;
chosen = ARRAY_ITEM(&data->list, data->selected).wcd->session; chosen = ARRAY_ITEM(&data->list, data->selected).wcd->start_session;
RB_FOREACH(s, sessions, &sessions) RB_FOREACH(s, sessions, &sessions)
window_choose_collapse(wp, s); window_choose_collapse(wp, s);
@ -790,58 +862,23 @@ window_choose_scroll_down(struct window_pane *wp)
screen_write_stop(&ctx); screen_write_stop(&ctx);
} }
void
window_choose_ctx(struct window_choose_data *cdata)
{
struct cmd_ctx ctx;
struct cmd_list *cmdlist;
char *cause;
/* The command template will have already been replaced. But if it's
* NULL, bail here.
*/
if (cdata->command == NULL)
return;
if (cmd_string_parse(cdata->command, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
free(cause);
}
return;
}
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
struct window_choose_data * struct window_choose_data *
window_choose_add_session(struct window_pane *wp, struct cmd_ctx *ctx, window_choose_add_session(struct window_pane *wp, struct client *c,
struct session *s, const char *template, char *action, u_int idx) struct session *s, const char *template, char *action, u_int idx)
{ {
struct window_choose_data *wcd; struct window_choose_data *wcd;
wcd = window_choose_data_create(ctx); wcd = window_choose_data_create(TREE_SESSION, c, c->session);
wcd->idx = s->idx; wcd->idx = s->idx;
wcd->tree_session = s; wcd->tree_session = s;
wcd->type = TREE_SESSION; wcd->tree_session->references++;
wcd->command = cmd_template_replace(action, s->name, 1);
wcd->ft_template = xstrdup(template); wcd->ft_template = xstrdup(template);
format_add(wcd->ft, "line", "%u", idx); format_add(wcd->ft, "line", "%u", idx);
format_session(wcd->ft, s); format_session(wcd->ft, s);
wcd->client->references++; wcd->command = cmd_template_replace(action, s->name, 1);
wcd->session->references++;
window_choose_add(wp, wcd); window_choose_add(wp, wcd);
@ -849,63 +886,60 @@ window_choose_add_session(struct window_pane *wp, struct cmd_ctx *ctx,
} }
struct window_choose_data * struct window_choose_data *
window_choose_add_item(struct window_pane *wp, struct cmd_ctx *ctx, window_choose_add_item(struct window_pane *wp, struct client *c,
struct winlink *wl, const char *template, char *action, u_int idx) struct winlink *wl, const char *template, char *action, u_int idx)
{ {
struct window_choose_data *wcd; struct window_choose_data *wcd;
char *action_data; char *expanded;
wcd = window_choose_data_create(ctx); wcd = window_choose_data_create(TREE_OTHER, c, c->session);
wcd->idx = wl->idx; wcd->idx = wl->idx;
wcd->ft_template = xstrdup(template); wcd->ft_template = xstrdup(template);
format_add(wcd->ft, "line", "%u", idx); format_add(wcd->ft, "line", "%u", idx);
format_session(wcd->ft, wcd->session); format_session(wcd->ft, wcd->start_session);
format_winlink(wcd->ft, wcd->session, wl); format_winlink(wcd->ft, wcd->start_session, wl);
format_window_pane(wcd->ft, wl->window->active); format_window_pane(wcd->ft, wl->window->active);
wcd->client->references++; /*
wcd->session->references++; * Interpolate action here, since the data we pass back is the expanded
* template itself.
*/
xasprintf(&expanded, "%s", format_expand(wcd->ft, wcd->ft_template));
wcd->command = cmd_template_replace(action, expanded, 1);
free(expanded);
window_choose_add(wp, wcd); window_choose_add(wp, wcd);
/*
* Interpolate action_data here, since the data we pass back is the
* expanded template itself.
*/
xasprintf(&action_data, "%s", format_expand(wcd->ft, wcd->ft_template));
wcd->command = cmd_template_replace(action, action_data, 1);
free(action_data);
return (wcd); return (wcd);
} }
struct window_choose_data * struct window_choose_data *
window_choose_add_window(struct window_pane *wp, struct cmd_ctx *ctx, window_choose_add_window(struct window_pane *wp, struct client *c,
struct session *s, struct winlink *wl, const char *template, struct session *s, struct winlink *wl, const char *template,
char *action, u_int idx) char *action, u_int idx)
{ {
struct window_choose_data *wcd; struct window_choose_data *wcd;
char *action_data; char *expanded;
wcd = window_choose_data_create(ctx);
xasprintf(&action_data, "%s:%d", s->name, wl->idx);
wcd->command = cmd_template_replace(action, action_data, 1);
free(action_data);
wcd = window_choose_data_create(TREE_WINDOW, c, c->session);
wcd->idx = wl->idx; wcd->idx = wl->idx;
wcd->wl = wl; wcd->wl = wl;
wcd->tree_session = s; wcd->tree_session = s;
wcd->type = TREE_WINDOW; wcd->tree_session->references++;
wcd->ft_template = xstrdup(template); wcd->ft_template = xstrdup(template);
format_add(wcd->ft, "line", "%u", idx); format_add(wcd->ft, "line", "%u", idx);
format_session(wcd->ft, s); format_session(wcd->ft, s);
format_winlink(wcd->ft, s, wl); format_winlink(wcd->ft, s, wl);
format_window_pane(wcd->ft, wl->window->active); format_window_pane(wcd->ft, wl->window->active);
wcd->client->references++; xasprintf(&expanded, "%s:%d", s->name, wl->idx);
wcd->session->references++; wcd->command = cmd_template_replace(action, expanded, 1);
free(expanded);
window_choose_add(wp, wcd); window_choose_add(wp, wcd);