aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2014-12-15 09:24:15 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2014-12-15 09:24:15 +0000
commitf495b150fa06cf0556159fe15e0dd2e0a09bb445 (patch)
tree7c48105f6febbe65b9cbed3027bffc1b8bc6e0d5
parent3771ab7c67ed002faa980b353bcc858669131b58 (diff)
parentccbe2545d9857e03731eddb9757989b9f52dc785 (diff)
downloadrtmux-f495b150fa06cf0556159fe15e0dd2e0a09bb445.tar.gz
rtmux-f495b150fa06cf0556159fe15e0dd2e0a09bb445.tar.bz2
rtmux-f495b150fa06cf0556159fe15e0dd2e0a09bb445.zip
Merge branch 'master' of ssh://git.code.sf.net/p/tmux/tmux-code
-rw-r--r--cmd-if-shell.c27
-rw-r--r--cmd-split-window.c7
-rw-r--r--format.c80
-rw-r--r--grid-view.c9
-rw-r--r--log.c2
-rw-r--r--resize.c14
-rw-r--r--screen-redraw.c43
-rw-r--r--tmux.140
-rw-r--r--tmux.h19
-rw-r--r--window-choose.c30
10 files changed, 190 insertions, 81 deletions
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index da0220ca..15432919 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -37,8 +37,8 @@ void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
- "bt:", 2, 3,
- "[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
+ "bFt:", 2, 3,
+ "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0,
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 cmd_if_shell_data *cdata;
- char *shellcmd;
+ char *shellcmd, *cmd, *cause;
+ struct cmd_list *cmdlist;
struct client *c;
struct session *s = 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]);
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->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
diff --git a/cmd-split-window.c b/cmd-split-window.c
index f88b2f65..6b901254 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -36,8 +36,8 @@ enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw",
- "c:dF:l:hp:Pt:v", 0, -1,
- "[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
+ "bc:dF:l:hp:Pt:v", 0, -1,
+ "[-bdhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_split_window_exec
@@ -144,7 +144,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
if (*shell == '\0' || areshell(shell))
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");
goto error;
}
diff --git a/format.c b/format.c
index e7fd3e1f..fff9a695 100644
--- a/format.c
+++ b/format.c
@@ -40,8 +40,26 @@ int format_replace(struct format_tree *, const char *, size_t, char **,
char *format_get_command(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. */
-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. */
int
@@ -117,8 +135,8 @@ format_create(void)
struct format_tree *ft;
char host[MAXHOSTNAMELEN], *ptr;
- ft = xmalloc(sizeof *ft);
- RB_INIT(ft);
+ ft = xcalloc(1, sizeof *ft);
+ RB_INIT(&ft->tree);
if (gethostname(host, sizeof host) == 0) {
format_add(ft, "host", "%s", host);
@@ -134,14 +152,10 @@ format_create(void)
void
format_free(struct format_tree *ft)
{
- struct format_entry *fe, *fe_next;
+ struct format_entry *fe, *fe1;
- fe_next = RB_MIN(format_tree, ft);
- while (fe_next != NULL) {
- fe = fe_next;
- fe_next = RB_NEXT(format_tree, ft, fe);
-
- RB_REMOVE(format_tree, ft, fe);
+ RB_FOREACH_SAFE(fe, format_rb_tree, &ft->tree, fe1) {
+ RB_REMOVE(format_rb_tree, &ft->tree, fe);
free(fe->value);
free(fe->key);
free(fe);
@@ -165,7 +179,7 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
xvasprintf(&fe->value, fmt, 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) {
free(fe_now->value);
fe_now->value = fe->value;
@@ -179,9 +193,32 @@ const char *
format_find(struct format_tree *ft, const char *key)
{
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 = RB_FIND(format_tree, ft, &fe_find);
+ fe = RB_FIND(format_rb_tree, &ft->tree, &fe_find);
if (fe == NULL)
return (NULL);
return (fe->value);
@@ -206,7 +243,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
copy[keylen] = '\0';
/* Is there a length limit or whatnot? */
- if (!islower((u_char) *copy) && *copy != '?') {
+ if (!islower((u_char) *copy) && *copy != '@' && *copy != '?') {
while (*copy != ':' && *copy != '\0') {
switch (*copy) {
case '=':
@@ -389,6 +426,8 @@ format_session(struct format_tree *ft, struct session *s)
char *tim;
time_t t;
+ ft->s = s;
+
format_add(ft, "session_name", "%s", s->name);
format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
format_add(ft, "session_width", "%u", s->sx);
@@ -418,6 +457,9 @@ format_client(struct format_tree *ft, struct client *c)
time_t t;
struct session *s;
+ if (ft->s == NULL)
+ ft->s = c->session;
+
format_add(ft, "client_height", "%u", c->tty.sy);
format_add(ft, "client_width", "%u", c->tty.sx);
if (c->tty.path != NULL)
@@ -463,6 +505,8 @@ format_window(struct format_tree *ft, struct window *w)
{
char *layout;
+ ft->w = w;
+
layout = layout_dump(w);
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_layout", "%s", layout);
format_add(ft, "window_panes", "%u", window_count_panes(w));
+ format_add(ft, "window_zoomed_flag", "%u",
+ !!(w->flags & WINDOW_ZOOMED));
free(layout);
}
@@ -482,6 +528,9 @@ format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
struct window *w = wl->window;
char *flags;
+ if (ft->w == NULL)
+ ft->w = wl->window;
+
flags = window_printable_flags(s, wl);
format_window(ft, w);
@@ -498,8 +547,6 @@ format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
!!(wl->flags & WINLINK_SILENCE));
format_add(ft, "window_last_flag", "%u",
!!(wl == TAILQ_FIRST(&s->lastw)));
- format_add(ft, "window_zoomed_flag", "%u",
- !!(wl->flags & WINDOW_ZOOMED));
free(flags);
}
@@ -536,6 +583,9 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
u_int i, idx;
char *cmd, *cwd;
+ if (ft->w == NULL)
+ ft->w = wp->window;
+
size = 0;
for (i = 0; i < gd->hsize; i++) {
gl = &gd->linedata[i];
diff --git a/grid-view.c b/grid-view.c
index badabd56..078a0da4 100644
--- a/grid-view.c
+++ b/grid-view.c
@@ -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);
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)
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);
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_clear(gd, sx - nx, py, px + nx - (sx - nx), 1);
diff --git a/log.c b/log.c
index 250a1da2..066165e8 100644
--- a/log.c
+++ b/log.c
@@ -46,7 +46,7 @@ log_open(const char *path)
if (log_file == NULL)
return;
- setlinebuf(log_file);
+ setvbuf(log_file, NULL, _IOLBF, 0);
event_set_log_callback(log_event_cb);
tzset();
diff --git a/resize.c b/resize.c
index 73a728fa..9ad73c81 100644
--- a/resize.c
+++ b/resize.c
@@ -50,7 +50,7 @@ recalculate_sizes(void)
struct window *w;
struct window_pane *wp;
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) {
has_status = options_get_number(&s->options, "status");
@@ -116,18 +116,26 @@ recalculate_sizes(void)
if (ssx == UINT_MAX || ssy == UINT_MAX)
continue;
+ forced = 0;
limit = options_get_number(&w->options, "force-width");
- if (limit >= PANE_MINIMUM && ssx > limit)
+ if (limit >= PANE_MINIMUM && ssx > limit) {
ssx = limit;
+ forced |= WINDOW_FORCEWIDTH;
+ }
limit = options_get_number(&w->options, "force-height");
- if (limit >= PANE_MINIMUM && ssy > limit)
+ if (limit >= PANE_MINIMUM && ssy > limit) {
ssy = limit;
+ forced |= WINDOW_FORCEHEIGHT;
+ }
if (w->sx == ssx && w->sy == ssy)
continue;
log_debug("window size %u,%u (was %u,%u)", ssx, ssy, w->sx,
w->sy);
+ w->flags &= ~(WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
+ w->flags |= forced;
+
is_zoomed = w->flags & WINDOW_ZOOMED;
if (is_zoomed)
window_unzoom(w);
diff --git a/screen-redraw.c b/screen-redraw.c
index a7f713a5..ef9e539d 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -278,8 +278,37 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
struct options *oo = &c->session->options;
struct tty *tty = &c->tty;
struct window_pane *wp;
- struct grid_cell active_gc, other_gc;
- u_int i, j, type;
+ struct grid_cell active_gc, other_gc, msg_gc;
+ 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(&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);
if (type == CELL_INSIDE)
continue;
+ if (type == CELL_OUTSIDE &&
+ small && i > msgx && j == msgy)
+ continue;
if (screen_redraw_check_active(i, j, type, w, wp))
tty_attributes(tty, &active_gc);
else
@@ -298,6 +330,13 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
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. */
diff --git a/tmux.1 b/tmux.1
index fb708ded..726f23a1 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1761,7 +1761,7 @@ is given and the selected window is already the current window,
the command behaves like
.Ic last-window .
.It Xo Ic split-window
-.Op Fl dhvP
+.Op Fl bdhvP
.Op Fl c Ar start-directory
.Oo Fl l
.Ar size |
@@ -1785,6 +1785,10 @@ and
.Fl p
options specify the size of the new pane in lines (for vertical split) or in
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
.Ic new-window
command.
@@ -3039,12 +3043,17 @@ and
.Ql } ,
for example
.Ql #{session_name} .
-Some variables also have an shorter alias such as
-.Ql #S .
+The possible variables are listed in the table below, or the name of a
+.Nm
+option may be used for an option's value.
+Some variables have a shorter alias such as
+.Ql #S ,
+and
.Ql ##
is replaced by a single
.Ql # .
-Conditionals are also accepted by prefixing with
+.Pp
+Conditionals are available by prefixing with
.Ql \&?
and separating two alternatives with a comma;
if the specified variable exists and is not zero, the first alternative
@@ -3055,7 +3064,15 @@ will include the string
.Ql attached
if the session is attached and the string
.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
by an
.Ql = ,
@@ -3577,7 +3594,7 @@ Miscellaneous commands are as follows:
.It Ic clock-mode Op Fl t Ar target-pane
Display a large clock.
.It Xo Ic if-shell
-.Op Fl b
+.Op Fl bF
.Op Fl t Ar target-pane
.Ar shell-command command
.Op Ar command
@@ -3590,7 +3607,9 @@ if
returns success or the second
.Ar command
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
section, including those relevant to
.Ar target-pane .
@@ -3598,6 +3617,13 @@ With
.Fl b ,
.Ar shell-command
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
.D1 (alias: Ic lock )
Lock each client individually by running the command specified by the
diff --git a/tmux.h b/tmux.h
index 57077a65..61f2ca7c 100644
--- a/tmux.h
+++ b/tmux.h
@@ -944,7 +944,9 @@ struct window {
#define WINDOW_ACTIVITY 0x2
#define WINDOW_REDRAW 0x4
#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)
struct options options;
@@ -1457,15 +1459,6 @@ struct options_table_entry {
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. */
#define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#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 *);
/* format.c */
-int format_cmp(struct format_entry *, struct format_entry *);
-RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
+struct format_tree;
struct format_tree *format_create(void);
void format_free(struct format_tree *);
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 client *, struct session *, const char *,
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_collapse_all(struct window_pane *);
void window_choose_set_current(struct window_pane *, u_int);
diff --git a/window-choose.c b/window-choose.c
index db092872..56016394 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -932,36 +932,6 @@ window_choose_add_session(struct window_pane *wp, struct client *c,
}
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 *
window_choose_add_window(struct window_pane *wp, struct client *c,
struct session *s, struct winlink *wl, const char *template,
const char *action, u_int idx)