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