aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cfg.c11
-rw-r--r--cmd-run-shell.c45
-rw-r--r--cmd-source-file.c41
-rw-r--r--cmd.c36
-rw-r--r--names.c2
-rw-r--r--options-table.c15
-rw-r--r--status.c11
-rw-r--r--tmux.119
-rw-r--r--tmux.c12
-rw-r--r--tmux.h1
-rw-r--r--window-copy.c4
11 files changed, 142 insertions, 55 deletions
diff --git a/cfg.c b/cfg.c
index 17287d86..74570e36 100644
--- a/cfg.c
+++ b/cfg.c
@@ -34,9 +34,10 @@
void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
-char *cfg_cause;
-int cfg_finished;
-struct causelist cfg_causes = ARRAY_INITIALIZER;
+char *cfg_cause;
+int cfg_finished;
+int cfg_references;
+struct causelist cfg_causes;
/* ARGSUSED */
void printflike2
@@ -89,6 +90,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
}
n = 0;
+ cfg_references++;
+
line = NULL;
retval = CMD_RETURN_NORMAL;
while ((buf = fgetln(f, &len))) {
@@ -171,6 +174,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
}
fclose(f);
+ cfg_references--;
+
return (retval);
}
diff --git a/cmd-run-shell.c b/cmd-run-shell.c
index 130a5411..44e796df 100644
--- a/cmd-run-shell.c
+++ b/cmd-run-shell.c
@@ -30,13 +30,15 @@
*/
enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmd_ctx *);
-void cmd_run_shell_callback(struct job *);
-void cmd_run_shell_free(void *);
+
+void cmd_run_shell_callback(struct job *);
+void cmd_run_shell_free(void *);
+void cmd_run_shell_print(struct job *, const char *);
const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run",
- "", 1, 1,
- "command",
+ "t:", 1, 1,
+ CMD_TARGET_PANE_USAGE " command",
0,
NULL,
NULL,
@@ -46,17 +48,42 @@ const struct cmd_entry cmd_run_shell_entry = {
struct cmd_run_shell_data {
char *cmd;
struct cmd_ctx ctx;
+ u_int wp_id;
};
+void
+cmd_run_shell_print(struct job *job, const char *msg)
+{
+ struct cmd_run_shell_data *cdata = job->data;
+ struct cmd_ctx *ctx = &cdata->ctx;
+ struct window_pane *wp;
+
+ wp = window_pane_find_by_id(cdata->wp_id);
+ if (wp == NULL) {
+ ctx->print(ctx, "%s", msg);
+ return;
+ }
+
+ if (window_pane_set_mode(wp, &window_copy_mode) == 0)
+ window_copy_init_for_output(wp);
+ if (wp->mode == &window_copy_mode)
+ window_copy_add(wp, "%s", msg);
+}
+
enum cmd_retval
cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct cmd_run_shell_data *cdata;
const char *shellcmd = args->argv[0];
+ struct window_pane *wp;
+
+ if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
+ return (CMD_RETURN_ERROR);
cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(args->argv[0]);
+ cdata->wp_id = wp->id;
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
if (ctx->cmdclient != NULL)
@@ -87,7 +114,7 @@ cmd_run_shell_callback(struct job *job)
lines = 0;
do {
if ((line = evbuffer_readline(job->event->input)) != NULL) {
- ctx->print(ctx, "%s", line);
+ cmd_run_shell_print (job, line);
lines++;
}
} while (line != NULL);
@@ -98,7 +125,7 @@ cmd_run_shell_callback(struct job *job)
memcpy(line, EVBUFFER_DATA(job->event->input), size);
line[size] = '\0';
- ctx->print(ctx, "%s", line);
+ cmd_run_shell_print(job, line);
lines++;
free(line);
@@ -115,10 +142,10 @@ cmd_run_shell_callback(struct job *job)
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
}
if (msg != NULL) {
- if (lines != 0)
- ctx->print(ctx, "%s", msg);
- else
+ if (lines == 0)
ctx->info(ctx, "%s", msg);
+ else
+ cmd_run_shell_print(job, msg);
free(msg);
}
}
diff --git a/cmd-source-file.c b/cmd-source-file.c
index 12ed3de2..220ec89c 100644
--- a/cmd-source-file.c
+++ b/cmd-source-file.c
@@ -42,35 +42,32 @@ enum cmd_retval
cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
- struct causelist causes;
- char *cause;
- struct window_pane *wp;
int retval;
u_int i;
+ char *cause;
- ARRAY_INIT(&causes);
+ retval = load_cfg(args->argv[0], ctx, &cfg_causes);
- retval = load_cfg(args->argv[0], ctx, &causes);
- if (ARRAY_EMPTY(&causes))
+ /*
+ * If the context for the cmdclient came from tmux's configuration
+ * file, then return the status of this command now, regardless of the
+ * error condition. Any errors from parsing a configuration file at
+ * startup will be handled for us by the server.
+ */
+ if (cfg_references > 0 ||
+ (ctx->curclient == NULL && ctx->cmdclient == NULL))
return (retval);
- if (retval == 1 && !RB_EMPTY(&sessions) && ctx->cmdclient != NULL) {
- wp = RB_MIN(sessions, &sessions)->curw->window->active;
- window_pane_set_mode(wp, &window_copy_mode);
- window_copy_init_for_output(wp);
- for (i = 0; i < ARRAY_LENGTH(&causes); i++) {
- cause = ARRAY_ITEM(&causes, i);
- window_copy_add(wp, "%s", cause);
- free(cause);
- }
- } else {
- for (i = 0; i < ARRAY_LENGTH(&causes); i++) {
- cause = ARRAY_ITEM(&causes, i);
- ctx->print(ctx, "%s", cause);
- free(cause);
- }
+ /*
+ * We were called from the command-line in which case print the errors
+ * gathered here directly.
+ */
+ for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
+ cause = ARRAY_ITEM(&cfg_causes, i);
+ ctx->print(ctx, "%s", cause);
+ free(cause);
}
- ARRAY_FREE(&causes);
+ ARRAY_FREE(&cfg_causes);
return (retval);
}
diff --git a/cmd.c b/cmd.c
index 4a17ddc3..79ac3386 100644
--- a/cmd.c
+++ b/cmd.c
@@ -115,6 +115,7 @@ const struct cmd_entry *cmd_table[] = {
NULL
};
+int cmd_session_better(struct session *, struct session *, int);
struct session *cmd_choose_session_list(struct sessionslist *);
struct session *cmd_choose_session(int);
struct client *cmd_choose_client(struct clients *);
@@ -370,6 +371,24 @@ cmd_current_session(struct cmd_ctx *ctx, int prefer_unattached)
return (cmd_choose_session(prefer_unattached));
}
+/* Is this session better? */
+int
+cmd_session_better(struct session *s, struct session *best,
+ int prefer_unattached)
+{
+ if (best == NULL)
+ return 1;
+ if (prefer_unattached) {
+ if (!(best->flags & SESSION_UNATTACHED) &&
+ (s->flags & SESSION_UNATTACHED))
+ return 1;
+ else if ((best->flags & SESSION_UNATTACHED) &&
+ !(s->flags & SESSION_UNATTACHED))
+ return 0;
+ }
+ return (timercmp(&s->activity_time, &best->activity_time, >));
+}
+
/*
* Find the most recently used session, preferring unattached if the flag is
* set.
@@ -377,21 +396,14 @@ cmd_current_session(struct cmd_ctx *ctx, int prefer_unattached)
struct session *
cmd_choose_session(int prefer_unattached)
{
- struct session *s, *sbest;
- struct timeval *tv = NULL;
+ struct session *s, *best;
- sbest = NULL;
+ best = NULL;
RB_FOREACH(s, sessions, &sessions) {
- if (tv == NULL || timercmp(&s->activity_time, tv, >) ||
- (prefer_unattached &&
- !(sbest->flags & SESSION_UNATTACHED) &&
- (s->flags & SESSION_UNATTACHED))) {
- sbest = s;
- tv = &s->activity_time;
- }
+ if (cmd_session_better(s, best, prefer_unattached))
+ best = s;
}
-
- return (sbest);
+ return (best);
}
/* Find the most recently used session from a list. */
diff --git a/names.c b/names.c
index b86d1b01..72f1ad17 100644
--- a/names.c
+++ b/names.c
@@ -76,7 +76,7 @@ window_name_callback(unused int fd, unused short events, void *data)
name != NULL && name[0] == '-' && name[1] != '\0')
wname = parse_window_name(name + 1);
else
- wname = parse_window_name(name);
+ wname = parse_window_name(name);
free(name);
}
diff --git a/options-table.c b/options-table.c
index 8ce838a6..4d1edbd5 100644
--- a/options-table.c
+++ b/options-table.c
@@ -685,6 +685,21 @@ const struct options_table_entry window_options_table[] = {
.default_str = "#I:#W#F"
},
+ { .name = "window-status-last-attr",
+ .type = OPTIONS_TABLE_ATTRIBUTES,
+ .default_num = 0
+ },
+
+ { .name = "window-status-last-bg",
+ .type = OPTIONS_TABLE_COLOUR,
+ .default_num = 8
+ },
+
+ { .name = "window-status-last-fg",
+ .type = OPTIONS_TABLE_COLOUR,
+ .default_num = 8
+ },
+
{ .name = "window-status-fg",
.type = OPTIONS_TABLE_COLOUR,
.default_num = 8
diff --git a/status.c b/status.c
index e841d804..88ab68d1 100644
--- a/status.c
+++ b/status.c
@@ -705,6 +705,17 @@ status_print(
gc->attr = attr;
fmt = options_get_string(oo, "window-status-current-format");
}
+ if (wl == TAILQ_FIRST(&s->lastw)) {
+ fg = options_get_number(oo, "window-status-last-fg");
+ if (fg != 8)
+ colour_set_fg(gc, fg);
+ bg = options_get_number(oo, "window-status-last-bg");
+ if (bg != 8)
+ colour_set_bg(gc, bg);
+ attr = options_get_number(oo, "window-status-last-attr");
+ if (attr != 0)
+ gc->attr = attr;
+ }
if (wl->flags & WINLINK_BELL) {
fg = options_get_number(oo, "window-status-bell-fg");
diff --git a/tmux.1 b/tmux.1
index 9ad40e07..499a924d 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2827,6 +2827,15 @@ Like
.Ar window-status-format ,
but is the format used when the window is the current window.
.Pp
+.It Ic window-status-last-attr Ar attributes
+Set status line attributes for the last active window.
+.Pp
+.It Ic window-status-last-bg Ar colour
+Set status line background colour for the last active window.
+.Pp
+.It Ic window-status-last-fg Ar colour
+Set status line foreground colour for the last active window.
+.Pp
.It Ic window-status-fg Ar colour
Set status line foreground colour for a single window.
.Pp
@@ -3389,12 +3398,18 @@ otherwise.
Lock each client individually by running the command specified by the
.Ic lock-command
option.
-.It Ic run-shell Ar shell-command
+.It Xo Ic run-shell
+.Op Fl t Ar target-pane
+.Ar shell-command
+.Xc
.D1 (alias: Ic run )
Execute
.Ar shell-command
in the background without creating a window.
-After it finishes, any output to stdout is displayed in copy mode.
+After it finishes, any output to stdout is displayed in copy mode (in the pane
+specified by
+.Fl t
+or the current pane if omitted).
If the command doesn't return success, the exit status is also displayed.
.It Ic server-info
.D1 (alias: Ic info )
diff --git a/tmux.c b/tmux.c
index 5a773f6d..4b58abad 100644
--- a/tmux.c
+++ b/tmux.c
@@ -162,7 +162,7 @@ parseenvironment(void)
char *
makesocketpath(const char *label)
{
- char base[MAXPATHLEN], *path, *s;
+ char base[MAXPATHLEN], realbase[MAXPATHLEN], *path, *s;
struct stat sb;
u_int uid;
@@ -186,7 +186,10 @@ makesocketpath(const char *label)
return (NULL);
}
- xasprintf(&path, "%s/%s", base, label);
+ if (realpath(base, realbase) == NULL)
+ strlcpy(realbase, base, sizeof realbase);
+
+ xasprintf(&path, "%s/%s", realbase, label);
return (path);
}
@@ -333,6 +336,8 @@ main(int argc, char **argv)
options_init(&global_w_options, NULL);
options_table_populate_tree(window_options_table, &global_w_options);
+ ARRAY_INIT(&cfg_causes);
+
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
if (flags & IDENTIFY_UTF8) {
options_set_number(&global_s_options, "status-utf8", 1);
@@ -390,8 +395,7 @@ main(int argc, char **argv)
}
}
free(label);
- if (realpath(path, socket_path) == NULL)
- strlcpy(socket_path, path, sizeof socket_path);
+ strlcpy(socket_path, path, sizeof socket_path);
free(path);
#ifdef HAVE_SETPROCTITLE
diff --git a/tmux.h b/tmux.h
index faab3fee..a0fda8b9 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1513,6 +1513,7 @@ __dead void shell_exec(const char *, const char *);
/* cfg.c */
extern int cfg_finished;
+extern int cfg_references;
extern struct causelist cfg_causes;
void printflike2 cfg_add_cause(struct causelist *, const char *, ...);
int load_cfg(const char *, struct cmd_ctx *, struct causelist *);
diff --git a/window-copy.c b/window-copy.c
index 480fdc70..b3780409 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -832,10 +832,10 @@ window_copy_mouse(
if (m->event == MOUSE_EVENT_WHEEL) {
if (m->wheel == MOUSE_WHEEL_UP) {
for (i = 0; i < 5; i++)
- window_copy_cursor_up(wp, 0);
+ window_copy_cursor_up(wp, 1);
} else if (m->wheel == MOUSE_WHEEL_DOWN) {
for (i = 0; i < 5; i++)
- window_copy_cursor_down(wp, 0);
+ window_copy_cursor_down(wp, 1);
if (data->oy == 0)
goto reset_mode;
}