Merge branch 'master' of ssh://git.code.sf.net/p/tmux/tmux-code

This commit is contained in:
Nicholas Marriott 2014-12-15 09:24:15 +00:00
commit f495b150fa
10 changed files with 190 additions and 81 deletions

View File

@ -37,8 +37,8 @@ void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = { const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if", "if-shell", "if",
"bt:", 2, 3, "bFt:", 2, 3,
"[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]", "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0, 0,
cmd_if_shell_exec cmd_if_shell_exec
}; };
@ -56,7 +56,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
{ {
struct args *args = self->args; struct args *args = self->args;
struct cmd_if_shell_data *cdata; struct cmd_if_shell_data *cdata;
char *shellcmd; char *shellcmd, *cmd, *cause;
struct cmd_list *cmdlist;
struct client *c; struct client *c;
struct session *s = NULL; struct session *s = NULL;
struct winlink *wl = NULL; struct winlink *wl = NULL;
@ -84,6 +85,26 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
shellcmd = format_expand(ft, args->argv[0]); shellcmd = format_expand(ft, args->argv[0]);
format_free(ft); format_free(ft);
if (args_has(args, 'F')) {
cmd = NULL;
if (*shellcmd != '0' && *shellcmd != '\0')
cmd = args->argv[1];
else if (args->argc == 3)
cmd = args->argv[2];
if (cmd == NULL)
return (CMD_RETURN_NORMAL);
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) {
cmdq_error(cmdq, "%s", cause);
free(cause);
}
return (CMD_RETURN_ERROR);
}
cmdq_run(cmdq, cmdlist);
cmd_list_free(cmdlist);
return (CMD_RETURN_NORMAL);
}
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd_if = xstrdup(args->argv[1]); cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3) if (args->argc == 3)

View File

@ -36,8 +36,8 @@ enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_split_window_entry = { const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw", "split-window", "splitw",
"c:dF:l:hp:Pt:v", 0, -1, "bc:dF:l:hp:Pt:v", 0, -1,
"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] " "[-bdhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
CMD_TARGET_PANE_USAGE " [command]", CMD_TARGET_PANE_USAGE " [command]",
0, 0,
cmd_split_window_exec cmd_split_window_exec
@ -144,7 +144,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
if (*shell == '\0' || areshell(shell)) if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL; shell = _PATH_BSHELL;
if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) { lc = layout_split_pane(wp, type, size, args_has(args, 'b'));
if (lc == NULL) {
cause = xstrdup("pane too small"); cause = xstrdup("pane too small");
goto error; goto error;
} }

View File

@ -40,8 +40,26 @@ int format_replace(struct format_tree *, const char *, size_t, char **,
char *format_get_command(struct window_pane *); char *format_get_command(struct window_pane *);
void format_window_pane_tabs(struct format_tree *, struct window_pane *); void format_window_pane_tabs(struct format_tree *, struct window_pane *);
/* Entry in format tree. */
struct format_entry {
char *key;
char *value;
RB_ENTRY(format_entry) entry;
};
/* Tree of format entries. */
struct format_tree {
struct window *w;
struct session *s;
RB_HEAD(format_rb_tree, format_entry) tree;
};
/* Format key-value replacement entry. */ /* Format key-value replacement entry. */
RB_GENERATE(format_tree, format_entry, entry, format_cmp); int format_cmp(struct format_entry *, struct format_entry *);
RB_PROTOTYPE(format_rb_tree, format_entry, entry, format_cmp);
RB_GENERATE(format_rb_tree, format_entry, entry, format_cmp);
/* Format tree comparison function. */ /* Format tree comparison function. */
int int
@ -117,8 +135,8 @@ format_create(void)
struct format_tree *ft; struct format_tree *ft;
char host[MAXHOSTNAMELEN], *ptr; char host[MAXHOSTNAMELEN], *ptr;
ft = xmalloc(sizeof *ft); ft = xcalloc(1, sizeof *ft);
RB_INIT(ft); RB_INIT(&ft->tree);
if (gethostname(host, sizeof host) == 0) { if (gethostname(host, sizeof host) == 0) {
format_add(ft, "host", "%s", host); format_add(ft, "host", "%s", host);
@ -134,14 +152,10 @@ format_create(void)
void void
format_free(struct format_tree *ft) format_free(struct format_tree *ft)
{ {
struct format_entry *fe, *fe_next; struct format_entry *fe, *fe1;
fe_next = RB_MIN(format_tree, ft); RB_FOREACH_SAFE(fe, format_rb_tree, &ft->tree, fe1) {
while (fe_next != NULL) { RB_REMOVE(format_rb_tree, &ft->tree, fe);
fe = fe_next;
fe_next = RB_NEXT(format_tree, ft, fe);
RB_REMOVE(format_tree, ft, fe);
free(fe->value); free(fe->value);
free(fe->key); free(fe->key);
free(fe); free(fe);
@ -165,7 +179,7 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
xvasprintf(&fe->value, fmt, ap); xvasprintf(&fe->value, fmt, ap);
va_end(ap); va_end(ap);
fe_now = RB_INSERT(format_tree, ft, fe); fe_now = RB_INSERT(format_rb_tree, &ft->tree, fe);
if (fe_now != NULL) { if (fe_now != NULL) {
free(fe_now->value); free(fe_now->value);
fe_now->value = fe->value; fe_now->value = fe->value;
@ -179,9 +193,32 @@ const char *
format_find(struct format_tree *ft, const char *key) format_find(struct format_tree *ft, const char *key)
{ {
struct format_entry *fe, fe_find; struct format_entry *fe, fe_find;
struct options_entry *o;
static char s[16];
o = options_find(&global_options, key);
if (o == NULL && ft->w != NULL)
o = options_find(&ft->w->options, key);
if (o == NULL)
o = options_find(&global_w_options, key);
if (o == NULL && ft->s != NULL)
o = options_find(&ft->s->options, key);
if (o == NULL)
o = options_find(&global_s_options, key);
if (o != NULL) {
switch (o->type) {
case OPTIONS_STRING:
return (o->str);
case OPTIONS_NUMBER:
snprintf(s, sizeof s, "%lld", o->num);
return (s);
case OPTIONS_STYLE:
return (style_tostring(&o->style));
}
}
fe_find.key = (char *) key; fe_find.key = (char *) key;
fe = RB_FIND(format_tree, ft, &fe_find); fe = RB_FIND(format_rb_tree, &ft->tree, &fe_find);
if (fe == NULL) if (fe == NULL)
return (NULL); return (NULL);
return (fe->value); return (fe->value);
@ -206,7 +243,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
copy[keylen] = '\0'; copy[keylen] = '\0';
/* Is there a length limit or whatnot? */ /* Is there a length limit or whatnot? */
if (!islower((u_char) *copy) && *copy != '?') { if (!islower((u_char) *copy) && *copy != '@' && *copy != '?') {
while (*copy != ':' && *copy != '\0') { while (*copy != ':' && *copy != '\0') {
switch (*copy) { switch (*copy) {
case '=': case '=':
@ -389,6 +426,8 @@ format_session(struct format_tree *ft, struct session *s)
char *tim; char *tim;
time_t t; time_t t;
ft->s = s;
format_add(ft, "session_name", "%s", s->name); format_add(ft, "session_name", "%s", s->name);
format_add(ft, "session_windows", "%u", winlink_count(&s->windows)); format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
format_add(ft, "session_width", "%u", s->sx); format_add(ft, "session_width", "%u", s->sx);
@ -418,6 +457,9 @@ format_client(struct format_tree *ft, struct client *c)
time_t t; time_t t;
struct session *s; struct session *s;
if (ft->s == NULL)
ft->s = c->session;
format_add(ft, "client_height", "%u", c->tty.sy); format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx); format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL) if (c->tty.path != NULL)
@ -463,6 +505,8 @@ format_window(struct format_tree *ft, struct window *w)
{ {
char *layout; char *layout;
ft->w = w;
layout = layout_dump(w); layout = layout_dump(w);
format_add(ft, "window_id", "@%u", w->id); format_add(ft, "window_id", "@%u", w->id);
@ -471,6 +515,8 @@ format_window(struct format_tree *ft, struct window *w)
format_add(ft, "window_height", "%u", w->sy); format_add(ft, "window_height", "%u", w->sy);
format_add(ft, "window_layout", "%s", layout); format_add(ft, "window_layout", "%s", layout);
format_add(ft, "window_panes", "%u", window_count_panes(w)); format_add(ft, "window_panes", "%u", window_count_panes(w));
format_add(ft, "window_zoomed_flag", "%u",
!!(w->flags & WINDOW_ZOOMED));
free(layout); free(layout);
} }
@ -482,6 +528,9 @@ format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
struct window *w = wl->window; struct window *w = wl->window;
char *flags; char *flags;
if (ft->w == NULL)
ft->w = wl->window;
flags = window_printable_flags(s, wl); flags = window_printable_flags(s, wl);
format_window(ft, w); format_window(ft, w);
@ -498,8 +547,6 @@ format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
!!(wl->flags & WINLINK_SILENCE)); !!(wl->flags & WINLINK_SILENCE));
format_add(ft, "window_last_flag", "%u", format_add(ft, "window_last_flag", "%u",
!!(wl == TAILQ_FIRST(&s->lastw))); !!(wl == TAILQ_FIRST(&s->lastw)));
format_add(ft, "window_zoomed_flag", "%u",
!!(wl->flags & WINDOW_ZOOMED));
free(flags); free(flags);
} }
@ -536,6 +583,9 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
u_int i, idx; u_int i, idx;
char *cmd, *cwd; char *cmd, *cwd;
if (ft->w == NULL)
ft->w = wp->window;
size = 0; size = 0;
for (i = 0; i < gd->hsize; i++) { for (i = 0; i < gd->hsize; i++) {
gl = &gd->linedata[i]; gl = &gd->linedata[i];

View File

@ -184,7 +184,10 @@ grid_view_insert_cells(struct grid *gd, u_int px, u_int py, u_int nx)
px = grid_view_x(gd, px); px = grid_view_x(gd, px);
py = grid_view_y(gd, py); py = grid_view_y(gd, py);
sx = grid_view_x(gd, gd->sx); if (gd->linedata[py].cellsize + nx < gd->sx)
sx = grid_view_x(gd, gd->linedata[py].cellsize + nx);
else
sx = grid_view_x(gd, gd->sx);
if (px == sx - 1) if (px == sx - 1)
grid_clear(gd, px, py, 1, 1); grid_clear(gd, px, py, 1, 1);
@ -201,7 +204,9 @@ grid_view_delete_cells(struct grid *gd, u_int px, u_int py, u_int nx)
px = grid_view_x(gd, px); px = grid_view_x(gd, px);
py = grid_view_y(gd, py); py = grid_view_y(gd, py);
sx = grid_view_x(gd, gd->sx); sx = grid_view_x(gd, gd->linedata[py].cellsize);
if (sx < px + nx)
sx = px + nx;
grid_move_cells(gd, px, px + nx, py, sx - px - nx); grid_move_cells(gd, px, px + nx, py, sx - px - nx);
grid_clear(gd, sx - nx, py, px + nx - (sx - nx), 1); grid_clear(gd, sx - nx, py, px + nx - (sx - nx), 1);

2
log.c
View File

@ -46,7 +46,7 @@ log_open(const char *path)
if (log_file == NULL) if (log_file == NULL)
return; return;
setlinebuf(log_file); setvbuf(log_file, NULL, _IOLBF, 0);
event_set_log_callback(log_event_cb); event_set_log_callback(log_event_cb);
tzset(); tzset();

View File

@ -50,7 +50,7 @@ recalculate_sizes(void)
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
u_int i, j, ssx, ssy, has, limit; u_int i, j, ssx, ssy, has, limit;
int flag, has_status, is_zoomed; int flag, has_status, is_zoomed, forced;
RB_FOREACH(s, sessions, &sessions) { RB_FOREACH(s, sessions, &sessions) {
has_status = options_get_number(&s->options, "status"); has_status = options_get_number(&s->options, "status");
@ -116,18 +116,26 @@ recalculate_sizes(void)
if (ssx == UINT_MAX || ssy == UINT_MAX) if (ssx == UINT_MAX || ssy == UINT_MAX)
continue; continue;
forced = 0;
limit = options_get_number(&w->options, "force-width"); limit = options_get_number(&w->options, "force-width");
if (limit >= PANE_MINIMUM && ssx > limit) if (limit >= PANE_MINIMUM && ssx > limit) {
ssx = limit; ssx = limit;
forced |= WINDOW_FORCEWIDTH;
}
limit = options_get_number(&w->options, "force-height"); limit = options_get_number(&w->options, "force-height");
if (limit >= PANE_MINIMUM && ssy > limit) if (limit >= PANE_MINIMUM && ssy > limit) {
ssy = limit; ssy = limit;
forced |= WINDOW_FORCEHEIGHT;
}
if (w->sx == ssx && w->sy == ssy) if (w->sx == ssx && w->sy == ssy)
continue; continue;
log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx, log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx,
w->sy); w->sy);
w->flags &= ~(WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
w->flags |= forced;
is_zoomed = w->flags & WINDOW_ZOOMED; is_zoomed = w->flags & WINDOW_ZOOMED;
if (is_zoomed) if (is_zoomed)
window_unzoom(w); window_unzoom(w);

View File

@ -278,8 +278,37 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
struct options *oo = &c->session->options; struct options *oo = &c->session->options;
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct window_pane *wp; struct window_pane *wp;
struct grid_cell active_gc, other_gc; struct grid_cell active_gc, other_gc, msg_gc;
u_int i, j, type; u_int i, j, type, msgx = 0, msgy = 0;
int small, flags;
char msg[256];
const char *tmp;
size_t msglen = 0;
small = (tty->sy - status + top > w->sy) || (tty->sx > w->sx);
if (small) {
flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT))
tmp = "force-width, force-height";
else if (flags == WINDOW_FORCEWIDTH)
tmp = "force-width";
else if (flags == WINDOW_FORCEHEIGHT)
tmp = "force-height";
else
tmp = "a smaller client";
xsnprintf(msg, sizeof msg, "(size %ux%u from %s)",
w->sx, w->sy, tmp);
msglen = strlen(msg);
if (tty->sy - 1 - status + top > w->sy && tty->sx >= msglen) {
msgx = tty->sx - msglen;
msgy = tty->sy - 1 - status + top;
} else if (tty->sx - w->sx > msglen) {
msgx = tty->sx - msglen;
msgy = tty->sy - 1 - status + top;
} else
small = 0;
}
style_apply(&other_gc, oo, "pane-border-style"); style_apply(&other_gc, oo, "pane-border-style");
style_apply(&active_gc, oo, "pane-active-border-style"); style_apply(&active_gc, oo, "pane-active-border-style");
@ -290,6 +319,9 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
type = screen_redraw_check_cell(c, i, j, &wp); type = screen_redraw_check_cell(c, i, j, &wp);
if (type == CELL_INSIDE) if (type == CELL_INSIDE)
continue; continue;
if (type == CELL_OUTSIDE &&
small && i > msgx && j == msgy)
continue;
if (screen_redraw_check_active(i, j, type, w, wp)) if (screen_redraw_check_active(i, j, type, w, wp))
tty_attributes(tty, &active_gc); tty_attributes(tty, &active_gc);
else else
@ -298,6 +330,13 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
tty_putc(tty, CELL_BORDERS[type]); tty_putc(tty, CELL_BORDERS[type]);
} }
} }
if (small) {
memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc);
tty_attributes(tty, &msg_gc);
tty_cursor(tty, msgx, msgy);
tty_puts(tty, msg);
}
} }
/* Draw the panes. */ /* Draw the panes. */

40
tmux.1
View File

@ -1761,7 +1761,7 @@ is given and the selected window is already the current window,
the command behaves like the command behaves like
.Ic last-window . .Ic last-window .
.It Xo Ic split-window .It Xo Ic split-window
.Op Fl dhvP .Op Fl bdhvP
.Op Fl c Ar start-directory .Op Fl c Ar start-directory
.Oo Fl l .Oo Fl l
.Ar size | .Ar size |
@ -1785,6 +1785,10 @@ and
.Fl p .Fl p
options specify the size of the new pane in lines (for vertical split) or in options specify the size of the new pane in lines (for vertical split) or in
cells (for horizontal split), or as a percentage, respectively. cells (for horizontal split), or as a percentage, respectively.
The
.Fl b
option causes the new pane to be created to the left of or above
.Ar target-pane .
All other options have the same meaning as for the All other options have the same meaning as for the
.Ic new-window .Ic new-window
command. command.
@ -3039,12 +3043,17 @@ and
.Ql } , .Ql } ,
for example for example
.Ql #{session_name} . .Ql #{session_name} .
Some variables also have an shorter alias such as The possible variables are listed in the table below, or the name of a
.Ql #S . .Nm
option may be used for an option's value.
Some variables have a shorter alias such as
.Ql #S ,
and
.Ql ## .Ql ##
is replaced by a single is replaced by a single
.Ql # . .Ql # .
Conditionals are also accepted by prefixing with .Pp
Conditionals are available by prefixing with
.Ql \&? .Ql \&?
and separating two alternatives with a comma; and separating two alternatives with a comma;
if the specified variable exists and is not zero, the first alternative if the specified variable exists and is not zero, the first alternative
@ -3055,7 +3064,15 @@ will include the string
.Ql attached .Ql attached
if the session is attached and the string if the session is attached and the string
.Ql not attached .Ql not attached
if it is unattached. if it is unattached, or
.Ql #{?automatic-rename,yes,no}
will include
.Ql yes
if
.Ic automatic-rename
is enabled, or
.Ql no
if not.
A limit may be placed on the length of the resultant string by prefixing it A limit may be placed on the length of the resultant string by prefixing it
by an by an
.Ql = , .Ql = ,
@ -3577,7 +3594,7 @@ Miscellaneous commands are as follows:
.It Ic clock-mode Op Fl t Ar target-pane .It Ic clock-mode Op Fl t Ar target-pane
Display a large clock. Display a large clock.
.It Xo Ic if-shell .It Xo Ic if-shell
.Op Fl b .Op Fl bF
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Ar shell-command command .Ar shell-command command
.Op Ar command .Op Ar command
@ -3590,7 +3607,9 @@ if
returns success or the second returns success or the second
.Ar command .Ar command
otherwise. otherwise.
Before being executed, shell-command is expanded using the rules specified in the Before being executed,
.Ar shell-command
is expanded using the rules specified in the
.Sx FORMATS .Sx FORMATS
section, including those relevant to section, including those relevant to
.Ar target-pane . .Ar target-pane .
@ -3598,6 +3617,13 @@ With
.Fl b , .Fl b ,
.Ar shell-command .Ar shell-command
is run in the background. is run in the background.
.Pp
If
.Fl F
is given,
.Ar shell-command
is not executed but considered success if neither empty nor zero (after formats
are expanded).
.It Ic lock-server .It Ic lock-server
.D1 (alias: Ic lock ) .D1 (alias: Ic lock )
Lock each client individually by running the command specified by the Lock each client individually by running the command specified by the

19
tmux.h
View File

@ -944,7 +944,9 @@ struct window {
#define WINDOW_ACTIVITY 0x2 #define WINDOW_ACTIVITY 0x2
#define WINDOW_REDRAW 0x4 #define WINDOW_REDRAW 0x4
#define WINDOW_SILENCE 0x8 #define WINDOW_SILENCE 0x8
#define WINDOW_ZOOMED 0x10 #define WINDOW_ZOOMED 0x1000
#define WINDOW_FORCEWIDTH 0x2000
#define WINDOW_FORCEHEIGHT 0x4000
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE) #define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
struct options options; struct options options;
@ -1457,15 +1459,6 @@ struct options_table_entry {
const char *style; const char *style;
}; };
/* Tree of format entries. */
struct format_entry {
char *key;
char *value;
RB_ENTRY(format_entry) entry;
};
RB_HEAD(format_tree, format_entry);
/* Common command usages. */ /* Common command usages. */
#define CMD_TARGET_PANE_USAGE "[-t target-pane]" #define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#define CMD_TARGET_WINDOW_USAGE "[-t target-window]" #define CMD_TARGET_WINDOW_USAGE "[-t target-window]"
@ -1509,8 +1502,7 @@ void cfg_print_causes(struct cmd_q *);
void cfg_show_causes(struct session *); void cfg_show_causes(struct session *);
/* format.c */ /* format.c */
int format_cmp(struct format_entry *, struct format_entry *); struct format_tree;
RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
struct format_tree *format_create(void); struct format_tree *format_create(void);
void format_free(struct format_tree *); void format_free(struct format_tree *);
void printflike(3, 4) format_add(struct format_tree *, const char *, void printflike(3, 4) format_add(struct format_tree *, const char *,
@ -2232,9 +2224,6 @@ struct window_choose_data *window_choose_add_window(struct window_pane *,
struct window_choose_data *window_choose_add_session(struct window_pane *, struct window_choose_data *window_choose_add_session(struct window_pane *,
struct client *, struct session *, const char *, struct client *, struct session *, const char *,
const char *, u_int); const char *, u_int);
struct window_choose_data *window_choose_add_item(struct window_pane *,
struct client *, struct winlink *, const char *,
const char *, u_int);
void window_choose_expand_all(struct window_pane *); void window_choose_expand_all(struct window_pane *);
void window_choose_collapse_all(struct window_pane *); void window_choose_collapse_all(struct window_pane *);
void window_choose_set_current(struct window_pane *, u_int); void window_choose_set_current(struct window_pane *, u_int);

View File

@ -931,36 +931,6 @@ window_choose_add_session(struct window_pane *wp, struct client *c,
return (wcd); return (wcd);
} }
struct window_choose_data *
window_choose_add_item(struct window_pane *wp, struct client *c,
struct winlink *wl, const char *template, const char *action, u_int idx)
{
struct window_choose_data *wcd;
char *expanded;
wcd = window_choose_data_create(TREE_OTHER, c, c->session);
wcd->idx = wl->idx;
wcd->ft_template = xstrdup(template);
format_add(wcd->ft, "line", "%u", idx);
format_session(wcd->ft, wcd->start_session);
format_winlink(wcd->ft, wcd->start_session, wl);
format_window_pane(wcd->ft, wl->window->active);
/*
* 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);
return (wcd);
}
struct window_choose_data * struct window_choose_data *
window_choose_add_window(struct window_pane *wp, struct client *c, 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,