diff options
-rw-r--r-- | .github/CONTRIBUTING.md | 9 | ||||
-rw-r--r-- | .github/ISSUE_TEMPLATE.md | 3 | ||||
-rw-r--r-- | .github/README.md | 12 | ||||
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | arguments.c | 2 | ||||
-rw-r--r-- | cfg.c | 1 | ||||
-rw-r--r-- | cmd-attach-session.c | 27 | ||||
-rw-r--r-- | cmd-display-message.c | 3 | ||||
-rw-r--r-- | cmd-find.c | 73 | ||||
-rw-r--r-- | cmd-if-shell.c | 13 | ||||
-rw-r--r-- | cmd-new-session.c | 7 | ||||
-rw-r--r-- | cmd-parse.y | 58 | ||||
-rw-r--r-- | cmd-source-file.c | 6 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | input.c | 1 | ||||
-rw-r--r-- | layout-custom.c | 5 | ||||
-rw-r--r-- | mode-tree.c | 2 | ||||
-rw-r--r-- | options.c | 3 | ||||
-rw-r--r-- | regress/command-order.sh | 6 | ||||
-rw-r--r-- | regress/conf/21867280ff7e99631046f9cc669b80d2.conf | 8 | ||||
-rw-r--r-- | regress/xenl-terminal.sh | 29 | ||||
-rw-r--r-- | server-client.c | 15 | ||||
-rw-r--r-- | server.c | 10 | ||||
-rw-r--r-- | tmux.1 | 26 | ||||
-rw-r--r-- | tmux.h | 5 | ||||
-rw-r--r-- | tty-term.c | 2 | ||||
-rw-r--r-- | tty.c | 11 | ||||
-rw-r--r-- | window-buffer.c | 2 | ||||
-rw-r--r-- | window.c | 34 |
29 files changed, 244 insertions, 138 deletions
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 49e2b90b..3a589484 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,13 +2,20 @@ Before opening an issue, please ensure that: +- Your problem is a specific problem or question or suggestion, not a general + complaint. + - `$TERM` inside tmux is screen, screen-256color, tmux or tmux-256color. Check by running `echo $TERM` inside tmux. - You can reproduce the problem with the latest tmux release, or a build from Git master. -- Your question or issue is not covered in the manual (run man tmux). +- Your question or issue is not covered [in the + manual](https://man.openbsd.org/tmux.1) (run `man tmux`). + +- Your problem is not mentioned in the [CHANGES + file](https://raw.githubusercontent.com/tmux/tmux/master/CHANGES) file. - Nobody else has opened the same issue recently. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index ee457237..8bf1e66a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -3,6 +3,9 @@ Please read https://github.com/tmux/tmux/blob/master/.github/CONTRIBUTING.md before opening an issue. +If you have upgraded, make sure your issue is not covered in the CHANGES file +for your version: https://raw.githubusercontent.com/tmux/tmux/master/CHANGES + Describe the problem and the steps to reproduce. Add a minimal tmux config if necessary. Screenshots can be helpful, but no more than one or two. diff --git a/.github/README.md b/.github/README.md index 6e262ef5..ce12f6aa 100644 --- a/.github/README.md +++ b/.github/README.md @@ -50,14 +50,12 @@ welcome. Please send by email to: tmux-users@googlegroups.com -Or open a GitHub issue or pull request. +Or open a GitHub issue or pull request. **Please read [this +document](CONTRIBUTING.md) before opening an issue.** -There is [a TODO list](https://github.com/tmux/tmux/wiki/Contributing) which -explains some ideas for tmux not yet developed. Please feel free to ask for -clarifications on the mailing list if you're thinking of working on these or -need further information. - -Please read the CONTRIBUTING file before opening an issue. +There is [a list of suggestions for contributions](https://github.com/tmux/tmux/wiki/Contributing). +Please feel free to ask on the mailing list if you're thinking of working on something or need +further information. ## Documentation @@ -1,3 +1,10 @@ +CHANGES FROM 3.0 to X.X + +* Add new-session -X and attach-session -x to send SIGHUP to parent when + detaching (like detach-client -P). + +* Support for octal escapes in strings (such as \007). + CHANGES FROM 2.9 to 3.0 * INCOMPATIBLE: Add a new {} syntax to the configuration file. This is a string diff --git a/arguments.c b/arguments.c index 38e50829..c8a6ab45 100644 --- a/arguments.c +++ b/arguments.c @@ -217,7 +217,7 @@ args_escape(const char *s) return (escaped); } - flags = VIS_OCTAL|VIS_TAB|VIS_NL; + flags = VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL; if (s[strcspn(s, quoted)] != '\0') flags |= VIS_DQ; utf8_stravis(&escaped, s, flags); @@ -126,6 +126,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags, pi.flags = flags; pi.file = path; pi.line = 1; + pi.item = item; pr = cmd_parse_from_file(f, &pi); fclose(f); diff --git a/cmd-attach-session.c b/cmd-attach-session.c index bcd6d895..6de734e5 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -37,8 +37,8 @@ const struct cmd_entry cmd_attach_session_entry = { .name = "attach-session", .alias = "attach", - .args = { "c:dErt:", 0, 0 }, - .usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE, + .args = { "c:dErt:x", 0, 0 }, + .usage = "[-dErx] [-c working-directory] " CMD_TARGET_SESSION_USAGE, /* -t is special */ @@ -48,7 +48,7 @@ const struct cmd_entry cmd_attach_session_entry = { enum cmd_retval cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, - int rflag, const char *cflag, int Eflag) + int xflag, int rflag, const char *cflag, int Eflag) { struct cmd_find_state *current = &item->shared->current; enum cmd_find_type type; @@ -58,6 +58,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, struct winlink *wl; struct window_pane *wp; char *cause; + enum msgtype msgtype; if (RB_EMPTY(&sessions)) { cmdq_error(item, "no sessions"); @@ -102,11 +103,15 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, c->last_session = c->session; if (c->session != NULL) { - if (dflag) { + if (dflag || xflag) { + if (xflag) + msgtype = MSG_DETACHKILL; + else + msgtype = MSG_DETACH; TAILQ_FOREACH(c_loop, &clients, entry) { if (c_loop->session != s || c == c_loop) continue; - server_client_detach(c_loop, MSG_DETACH); + server_client_detach(c_loop, msgtype); } } if (!Eflag) @@ -131,11 +136,15 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, if (rflag) c->flags |= CLIENT_READONLY; - if (dflag) { + if (dflag || xflag) { + if (xflag) + msgtype = MSG_DETACHKILL; + else + msgtype = MSG_DETACH; TAILQ_FOREACH(c_loop, &clients, entry) { if (c_loop->session != s || c == c_loop) continue; - server_client_detach(c_loop, MSG_DETACH); + server_client_detach(c_loop, msgtype); } } if (!Eflag) @@ -169,6 +178,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmdq_item *item) struct args *args = self->args; return (cmd_attach_session(item, args_get(args, 't'), - args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c'), - args_has(args, 'E'))); + args_has(args, 'd'), args_has(args, 'x'), args_has(args, 'r'), + args_get(args, 'c'), args_has(args, 'E'))); } diff --git a/cmd-display-message.c b/cmd-display-message.c index 8c1ad5f6..4d9bccb6 100644 --- a/cmd-display-message.c +++ b/cmd-display-message.c @@ -109,8 +109,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) format_defaults(ft, target_c, s, wl, wp); if (args_has(args, 'a')) { - if (item != NULL) - format_each(ft, cmd_display_message_each, item); + format_each(ft, cmd_display_message_each, item); return (CMD_RETURN_NORMAL); } @@ -75,38 +75,12 @@ static const char *cmd_find_pane_table[][2] = { { NULL, NULL } }; -/* Get session from TMUX if present. */ -static struct session * -cmd_find_try_TMUX(struct client *c) -{ - struct environ_entry *envent; - char tmp[256]; - long long pid; - u_int session; - struct session *s; - - envent = environ_find(c->environ, "TMUX"); - if (envent == NULL) - return (NULL); - - if (sscanf(envent->value, "%255[^,],%lld,%d", tmp, &pid, &session) != 3) - return (NULL); - if (pid != getpid()) - return (NULL); - log_debug("%s: client %p TMUX %s (session $%u)", __func__, c, - envent->value, session); - - s = session_find_by_id(session); - if (s != NULL) - log_debug("%s: session $%u still exists", __func__, s->id); - return (s); -} - /* Find pane containing client if any. */ static struct window_pane * cmd_find_inside_pane(struct client *c) { struct window_pane *wp; + struct environ_entry *envent; if (c == NULL) return (NULL); @@ -115,6 +89,11 @@ cmd_find_inside_pane(struct client *c) if (wp->fd != -1 && strcmp(wp->tty, c->ttyname) == 0) break; } + if (wp == NULL) { + envent = environ_find(c->environ, "TMUX_PANE"); + if (envent != NULL) + wp = window_pane_find_by_id_str(envent->value); + } if (wp != NULL) log_debug("%s: got pane %%%u (%s)", __func__, wp->id, wp->tty); return (wp); @@ -879,8 +858,6 @@ cmd_find_from_mouse(struct cmd_find_state *fs, struct mouse_event *m, int flags) int cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags) { - struct session *s; - struct winlink *wl; struct window_pane *wp; /* If no client, treat as from nothing. */ @@ -902,30 +879,6 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags) if (wp == NULL) goto unknown_pane; - /* If we have a session in TMUX, see if it has this pane. */ - s = cmd_find_try_TMUX(c); - if (s != NULL) { - RB_FOREACH(wl, winlinks, &s->windows) { - if (window_has_pane(wl->window, wp)) - break; - } - if (wl != NULL) { - log_debug("%s: session $%u has pane %%%u", __func__, - s->id, wp->id); - - fs->s = s; - fs->wl = s->curw; /* use current session */ - fs->w = fs->wl->window; - fs->wp = fs->w->active; /* use active pane */ - - cmd_find_log_state(__func__, fs); - return (0); - } else { - log_debug("%s: session $%u does not have pane %%%u", - __func__, s->id, wp->id); - } - } - /* * Don't have a session, or it doesn't have this pane. Try all * sessions. @@ -947,17 +900,7 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags) return (0); unknown_pane: - /* - * We're not running in a known pane, but maybe this client has TMUX - * in the environment. That'd give us a session. - */ - s = cmd_find_try_TMUX(c); - if (s != NULL) { - cmd_find_from_session(fs, s, flags); - return (0); - } - - /* Otherwise we need to guess. */ + /* We can't find the pane so need to guess. */ return (cmd_find_from_nothing(fs, flags)); } @@ -1005,6 +948,8 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item, strlcat(tmp, "CANFAIL,", sizeof tmp); if (*tmp != '\0') tmp[strlen(tmp) - 1] = '\0'; + else + strlcat(tmp, "NONE", sizeof tmp); log_debug("%s: target %s, type %s, item %p, flags %s", __func__, target == NULL ? "none" : target, s, item, tmp); diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 84f66657..f795575a 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -67,10 +67,11 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) struct cmd_if_shell_data *cdata; char *shellcmd, *cmd; struct cmdq_item *new_item; + struct cmd_find_state *fs = &item->target; struct client *c = cmd_find_client(item, NULL, 1); - struct session *s = item->target.s; - struct winlink *wl = item->target.wl; - struct window_pane *wp = item->target.wp; + struct session *s = fs->s; + struct winlink *wl = fs->wl; + struct window_pane *wp = fs->wp; struct cmd_parse_input pi; struct cmd_parse_result *pr; @@ -92,7 +93,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) pi.line = self->line; pi.item = item; pi.c = c; - cmd_find_copy_state(&pi.fs, &item->target); + cmd_find_copy_state(&pi.fs, fs); pr = cmd_parse_from_string(cmd, &pi); switch (pr->status) { @@ -103,7 +104,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) free(pr->error); return (CMD_RETURN_ERROR); case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, NULL, m, 0); + new_item = cmdq_get_command(pr->cmdlist, fs, m, 0); cmdq_insert_after(item, new_item); cmd_list_free(pr->cmdlist); break; @@ -137,7 +138,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) cdata->input.c = c; if (cdata->input.c != NULL) cdata->input.c->references++; - cmd_find_copy_state(&cdata->input.fs, &item->target); + cmd_find_copy_state(&cdata->input.fs, fs); if (job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL, cmd_if_shell_callback, cmd_if_shell_free, cdata, 0) == NULL) { diff --git a/cmd-new-session.c b/cmd-new-session.c index 559c268c..e0540815 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -39,8 +39,8 @@ const struct cmd_entry cmd_new_session_entry = { .name = "new-session", .alias = "new", - .args = { "Ac:dDEF:n:Ps:t:x:y:", 0, -1 }, - .usage = "[-AdDEP] [-c start-directory] [-F format] [-n window-name] " + .args = { "Ac:dDEF:n:Ps:t:x:Xy:", 0, -1 }, + .usage = "[-AdDEPX] [-c start-directory] [-F format] [-n window-name] " "[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] " "[-y height] [command]", @@ -105,7 +105,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) if (args_has(args, 'A')) { retval = cmd_attach_session(item, newname, args_has(args, 'D'), - 0, NULL, args_has(args, 'E')); + args_has(args, 'X'), 0, NULL, + args_has(args, 'E')); free(newname); return (retval); } diff --git a/cmd-parse.y b/cmd-parse.y index 6feeb35a..a7c12f62 100644 --- a/cmd-parse.y +++ b/cmd-parse.y @@ -76,6 +76,8 @@ static char *cmd_parse_get_error(const char *, u_int, const char *); static void cmd_parse_free_command(struct cmd_parse_command *); static struct cmd_parse_commands *cmd_parse_new_commands(void); static void cmd_parse_free_commands(struct cmd_parse_commands *); +static void cmd_parse_print_commands(struct cmd_parse_input *, u_int, + struct cmd_list *); %} @@ -498,6 +500,19 @@ cmd_parse_get_error(const char *file, u_int line, const char *error) } static void +cmd_parse_print_commands(struct cmd_parse_input *pi, u_int line, + struct cmd_list *cmdlist) +{ + char *s; + + if (pi->item != NULL && (pi->flags & CMD_PARSE_VERBOSE)) { + s = cmd_list_print(cmdlist, 0); + cmdq_print(pi->item, "%u: %s", line, s); + free(s); + } +} + +static void cmd_parse_free_command(struct cmd_parse_command *cmd) { free(cmd->name); @@ -653,6 +668,7 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, if (cmdlist == NULL || cmd->line != line) { if (cmdlist != NULL) { + cmd_parse_print_commands(pi, line, cmdlist); cmd_list_move(result, cmdlist); cmd_list_free(cmdlist); } @@ -672,6 +688,7 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, cmd_list_append(cmdlist, add); } if (cmdlist != NULL) { + cmd_parse_print_commands(pi, line, cmdlist); cmd_list_move(result, cmdlist); cmd_list_free(cmdlist); } @@ -1110,17 +1127,54 @@ error: static int yylex_token_escape(char **buf, size_t *len) { - int ch, type; + int ch, type, o2, o3; u_int size, i, tmp; char s[9]; struct utf8_data ud; - switch (ch = yylex_getc()) { + ch = yylex_getc(); + + if (ch >= '4' && ch <= '7') { + yyerror("invalid octal escape"); + return (0); + } + if (ch >= '0' && ch <= '3') { + o2 = yylex_getc(); + if (o2 >= '0' && o2 <= '7') { + o3 = yylex_getc(); + if (o3 >= '0' && o3 <= '7') { + ch = 64 * (ch - '0') + + 8 * (o2 - '0') + + (o3 - '0'); + yylex_append1(buf, len, ch); + return (1); + } + } + yyerror("invalid octal escape"); + return (0); + } + + switch (ch) { case EOF: return (0); + case 'a': + ch = '\a'; + break; + case 'b': + ch = '\b'; + break; case 'e': ch = '\033'; break; + case 'f': + ch = '\f'; + break; + case 's': + ch = ' '; + break; + case 'v': + ch = '\v'; + break; case 'r': ch = '\r'; break; diff --git a/cmd-source-file.c b/cmd-source-file.c index 38aede0c..2e01ae67 100644 --- a/cmd-source-file.c +++ b/cmd-source-file.c @@ -37,8 +37,8 @@ const struct cmd_entry cmd_source_file_entry = { .name = "source-file", .alias = "source", - .args = { "nq", 1, -1 }, - .usage = "[-nq] path ...", + .args = { "nqv", 1, -1 }, + .usage = "[-nqv] path ...", .flags = 0, .exec = cmd_source_file_exec @@ -62,6 +62,8 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item) flags |= CMD_PARSE_QUIET; if (args_has(args, 'n')) flags |= CMD_PARSE_PARSEONLY; + if (args_has(args, 'v')) + flags |= CMD_PARSE_VERBOSE; utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB); retval = CMD_RETURN_NORMAL; diff --git a/configure.ac b/configure.ac index 8ff6d16e..5fba1eaf 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT([tmux], 3.0-rc2) +AC_INIT([tmux], next-3.1) AC_PREREQ([2.60]) AC_CONFIG_AUX_DIR(etc) @@ -2409,7 +2409,6 @@ input_osc_52(struct input_ctx *ictx, const char *p) outlen = 4 * ((len + 2) / 3) + 1; out = xmalloc(outlen); if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) { - abort(); free(out); return; } diff --git a/layout-custom.c b/layout-custom.c index 9886afe1..4d9e818b 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -168,10 +168,7 @@ layout_parse(struct window *w, const char *layout) /* Update pane offsets and sizes. */ layout_fix_offsets(lc); layout_fix_panes(w); - - /* Then resize the layout back to the original window size. */ - layout_resize(w, sx, sy); - window_resize(w, sx, sy); + recalculate_sizes(); layout_print_cell(lc, __func__, 0); diff --git a/mode-tree.c b/mode-tree.c index 75034675..20ac3226 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -480,7 +480,7 @@ mode_tree_add(struct mode_tree_data *mtd, struct mode_tree_item *parent, saved = mode_tree_find_item(&mtd->saved, tag); if (saved != NULL) { - if (parent == NULL || (parent != NULL && parent->expanded)) + if (parent == NULL || parent->expanded) mti->tagged = saved->tagged; mti->expanded = saved->expanded; } else if (expanded == -1) @@ -365,7 +365,8 @@ options_array_set(struct options_entry *o, u_int idx, const char *value, pr = cmd_parse_from_string(value, NULL); switch (pr->status) { case CMD_PARSE_EMPTY: - *cause = xstrdup("empty command"); + if (cause != NULL) + *cause = xstrdup("empty command"); return (-1); case CMD_PARSE_ERROR: if (cause != NULL) diff --git a/regress/command-order.sh b/regress/command-order.sh index fb4e0324..04046f0d 100644 --- a/regress/command-order.sh +++ b/regress/command-order.sh @@ -1,7 +1,5 @@ #!/bin/sh -# new-session without clients should be the right size - PATH=/bin:/usr/bin TERM=screen @@ -19,6 +17,7 @@ EOF $TMUX -f$TMP start </dev/null || exit 1 sleep 1 $TMUX lsw -aF '#{session_name},#{window_name}'|sort >$TMP || exit 1 +$TMUX kill-server 2>/dev/null cat <<EOF|cmp -s $TMP - || exit 1 bar,bar0 bar,bar1 @@ -27,7 +26,6 @@ foo,foo0 foo,foo1 foo,foo2 EOF -$TMUX kill-server 2>/dev/null cat <<EOF >$TMP new -sfoo -nfoo0 @@ -40,6 +38,7 @@ EOF $TMUX -f$TMP start </dev/null || exit 1 sleep 1 $TMUX lsw -aF '#{session_name},#{window_name}'|sort >$TMP || exit 1 +$TMUX kill-server 2>/dev/null cat <<EOF|cmp -s $TMP - || exit 1 bar,bar0 bar,bar1 @@ -48,6 +47,5 @@ foo,foo0 foo,foo1 foo,foo2 EOF -$TMUX kill-server 2>/dev/null exit 0 diff --git a/regress/conf/21867280ff7e99631046f9cc669b80d2.conf b/regress/conf/21867280ff7e99631046f9cc669b80d2.conf new file mode 100644 index 00000000..43b142b4 --- /dev/null +++ b/regress/conf/21867280ff7e99631046f9cc669b80d2.conf @@ -0,0 +1,8 @@ +%if #{l:1} +set -g status-style fg=cyan,bg='#001040' +%elif #{l:1} +set -g status-style fg=white,bg='#400040' +%else +set -g status-style fg=white,bg='#800000' +%endif +bind ^X last-window diff --git a/regress/xenl-terminal.sh b/regress/xenl-terminal.sh new file mode 100644 index 00000000..07469ceb --- /dev/null +++ b/regress/xenl-terminal.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -Ltest" +$TMUX kill-server 2>/dev/null +TMUX2="$TEST_TMUX -Ltest2" +$TMUX2 kill-server 2>/dev/null + +TMP=$(mktemp) +trap "rm -f $TMP" 0 1 15 + +$TMUX2 -f/dev/null new -d || exit 1 +$TMUX2 set -as terminal-overrides ',*:xenl@' || exit 1 +$TMUX2 set -g status-right 'RRR' || exit 1 +$TMUX2 set -g status-left 'LLL' || exit 1 +$TMUX2 set -g window-status-current-format 'WWW' || exit 1 +$TMUX -f/dev/null new -x20 -y2 -d "$TMUX2 attach" || exit 1 +sleep 1 +$TMUX capturep -p|tail -1 >$TMP || exit 1 +$TMUX kill-server 2>/dev/null +$TMUX2 kill-server 2>/dev/null +cat <<EOF|cmp -s $TMP - || exit 1 +LLLWWW RR +EOF + +exit 0 diff --git a/server-client.c b/server-client.c index 7381eb52..ae41278a 100644 --- a/server-client.c +++ b/server-client.c @@ -1239,6 +1239,8 @@ server_client_loop(void) struct client *c; struct window *w; struct window_pane *wp; + struct winlink *wl; + struct session *s; int focus; TAILQ_FOREACH(c, &clients, entry) { @@ -1255,8 +1257,13 @@ server_client_loop(void) */ focus = options_get_number(global_options, "focus-events"); RB_FOREACH(w, windows, &windows) { + TAILQ_FOREACH(wl, &w->winlinks, wentry) { + s = wl->session; + if (s->attached != 0 && s->curw == wl) + break; + } TAILQ_FOREACH(wp, &w->panes, entry) { - if (wp->fd != -1) { + if (wl != NULL && wp->fd != -1) { if (focus) server_client_check_focus(wp); server_client_check_resize(wp); @@ -1521,7 +1528,9 @@ server_client_click_timer(__unused int fd, __unused short events, void *data) static void server_client_check_exit(struct client *c) { - if (!(c->flags & CLIENT_EXIT)) + if (~c->flags & CLIENT_EXIT) + return; + if (c->flags & CLIENT_EXITED) return; if (EVBUFFER_LENGTH(c->stdin_data) != 0) @@ -1534,7 +1543,7 @@ server_client_check_exit(struct client *c) if (c->flags & CLIENT_ATTACHED) notify_client("client-detached", c); proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval); - c->flags &= ~CLIENT_EXIT; + c->flags |= CLIENT_EXITED; } /* Redraw timer callback. */ @@ -43,7 +43,7 @@ struct clients clients; struct tmuxproc *server_proc; -static int server_fd; +static int server_fd = -1; static int server_exit; static struct event server_ev_accept; @@ -207,11 +207,10 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd, cmdq_append(c, cmdq_get_error(cause)); free(cause); c->flags |= CLIENT_EXIT; - } + } else + start_cfg(); - start_cfg(); server_add_accept(0); - proc_loop(server_proc, server_loop); job_kill_all(); @@ -363,6 +362,9 @@ server_add_accept(int timeout) { struct timeval tv = { timeout, 0 }; + if (server_fd == -1) + return; + if (event_initialized(&server_ev_accept)) event_del(&server_ev_accept); @@ -520,7 +520,11 @@ the given four or eight digit hexadecimal number. When preceded (escaped) by a \e, the following characters are replaced: \ee by the escape character; \er by a carriage return; \en by a newline; and \et by a tab. -.Pp +.It +\eooo is replaced by a character of the octal value ooo. +Three octal digits are required, for example \e001. +The largest valid character is \e377. +.It Any other characters preceded by \e are replaced by themselves (that is, the \e is removed) and are not treated as having any special meaning - so for example \e; will not mark a command sequence and \e$ will not expand an environment @@ -919,7 +923,7 @@ section. The following commands are available to manage clients and sessions: .Bl -tag -width Ds .It Xo Ic attach-session -.Op Fl dEr +.Op Fl dErx .Op Fl c Ar working-directory .Op Fl t Ar target-session .Xc @@ -932,6 +936,10 @@ If used from inside, switch the current client. If .Fl d is specified, any other clients attached to the session are detached. +If +.Fl x +is given, send SIGHUP to the parent process of the client as well as +detaching the client, typically causing it to exit. .Fl r signifies the client is read-only (only keys bound to the .Ic detach-client @@ -1049,7 +1057,7 @@ command. Lock all clients attached to .Ar target-session . .It Xo Ic new-session -.Op Fl AdDEP +.Op Fl AdDEPX .Op Fl c Ar start-directory .Op Fl F Ar format .Op Fl n Ar window-name @@ -1106,6 +1114,12 @@ already exists; in this case, behaves like .Fl d to +.Ic attach-session , +and +.Fl X +behaves like +.Fl x +to .Ic attach-session . .Pp If @@ -1242,7 +1256,7 @@ and .Fl T show debugging information about jobs and terminals. .It Xo Ic source-file -.Op Fl nq +.Op Fl nqv .Ar path .Ar ... .Xc @@ -1260,6 +1274,8 @@ does not exist. With .Fl n , the file is parsed but no commands are executed. +.Fl v +shows the parsed commands and line numbers if possible. .It Ic start-server .D1 (alias: Ic start ) Start the @@ -4328,7 +4344,7 @@ Align text to the left, centre or right of the available space if appropriate. .It Xo Ic list=on , .Ic list=focus , .Ic list=left-marker , -.Ic list=right=marker , +.Ic list=right-marker , .Ic nolist .Xc Mark the position of the various window list components in the @@ -1326,6 +1326,7 @@ struct cmd_parse_input { #define CMD_PARSE_QUIET 0x1 #define CMD_PARSE_PARSEONLY 0x2 #define CMD_PARSE_NOALIAS 0x4 +#define CMD_PARSE_VERBOSE 0x8 const char *file; u_int line; @@ -1491,7 +1492,7 @@ struct client { #define CLIENT_REPEAT 0x20 #define CLIENT_SUSPENDED 0x40 #define CLIENT_ATTACHED 0x80 -/* 0x100 unused */ +#define CLIENT_EXITED 0x100 #define CLIENT_DEAD 0x200 #define CLIENT_REDRAWBORDERS 0x400 #define CLIENT_READONLY 0x800 @@ -2011,7 +2012,7 @@ extern const struct cmd_entry *cmd_table[]; /* cmd-attach-session.c */ enum cmd_retval cmd_attach_session(struct cmdq_item *, const char *, int, int, - const char *, int); + int, const char *, int); /* cmd-parse.c */ void cmd_parse_empty(struct cmd_parse_input *); @@ -691,7 +691,7 @@ tty_term_describe(struct tty_term *term, enum tty_code_code code) break; case TTYCODE_STRING: strnvis(out, term->codes[code].value.string, sizeof out, - VIS_OCTAL|VIS_TAB|VIS_NL); + VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL); xsnprintf(s, sizeof s, "%4u: %s: (string) %s", code, tty_term_codes[code].name, out); @@ -527,6 +527,12 @@ tty_putc(struct tty *tty, u_char ch) { const char *acs; + if ((tty->term->flags & TERM_EARLYWRAP) && + ch >= 0x20 && ch != 0x7f && + tty->cy == tty->sy - 1 && + tty->cx + 1 >= tty->sx) + return; + if (tty->cell.attr & GRID_ATTR_CHARSET) { acs = tty_acs_get(tty, ch); if (acs != NULL) @@ -557,6 +563,11 @@ tty_putc(struct tty *tty, u_char ch) void tty_putn(struct tty *tty, const void *buf, size_t len, u_int width) { + if ((tty->term->flags & TERM_EARLYWRAP) && + tty->cy == tty->sy - 1 && + tty->cx + len >= tty->sx) + len = tty->sx - tty->cx - 1; + tty_add(tty, buf, len); if (tty->cx + width > tty->sx) { tty->cx = (tty->cx + width) - tty->sx; diff --git a/window-buffer.c b/window-buffer.c index d65916b5..224dfedb 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -245,7 +245,7 @@ window_buffer_draw(__unused void *modedata, void *itemdata, at = 0; while (end != pdata + psize && *end != '\n') { if ((sizeof line) - at > 5) { - cp = vis(line + at, *end, VIS_TAB|VIS_OCTAL, 0); + cp = vis(line + at, *end, VIS_OCTAL|VIS_TAB, 0); at = cp - line; } end++; @@ -802,6 +802,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp->pipe_event = NULL; wp->saved_grid = NULL; + wp->saved_cx = UINT_MAX; + wp->saved_cy = UINT_MAX; style_set(&wp->style, &grid_default_cell); @@ -963,10 +965,25 @@ window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc, struct screen *s = &wp->base; u_int sx, sy; - if (wp->saved_grid == NULL) - return; if (!options_get_number(wp->window->options, "alternate-screen")) return; + + /* + * Restore the cursor position and cell. This happens even if not + * currently in the alternate screen. + */ + if (cursor && wp->saved_cx != UINT_MAX && wp->saved_cy != UINT_MAX) { + s->cx = wp->saved_cx; + if (s->cx > screen_size_x(s) - 1) + s->cx = screen_size_x(s) - 1; + s->cy = wp->saved_cy; + if (s->cy > screen_size_y(s) - 1) + s->cy = screen_size_y(s) - 1; + memcpy(gc, &wp->saved_cell, sizeof *gc); + } + + if (wp->saved_grid == NULL) + return; sx = screen_size_x(s); sy = screen_size_y(s); @@ -977,17 +994,8 @@ window_pane_alternate_off(struct window_pane *wp, struct grid_cell *gc, if (sy > wp->saved_grid->sy) screen_resize(s, sx, wp->saved_grid->sy, 1); - /* Restore the grid, cursor position and cell. */ + /* Restore the saved grid. */ grid_duplicate_lines(s->grid, screen_hsize(s), wp->saved_grid, 0, sy); - if (cursor) - s->cx = wp->saved_cx; - if (s->cx > screen_size_x(s) - 1) - s->cx = screen_size_x(s) - 1; - if (cursor) - s->cy = wp->saved_cy; - if (s->cy > screen_size_y(s) - 1) - s->cy = screen_size_y(s) - 1; - memcpy(gc, &wp->saved_cell, sizeof *gc); /* * Turn history back on (so resize can use it) and then resize back to @@ -1137,7 +1145,7 @@ window_pane_reset_mode(struct window_pane *wp) } else { log_debug("%s: next mode is %s", __func__, next->mode->name); wp->screen = next->screen; - if (next != NULL && next->mode->resize != NULL) + if (next->mode->resize != NULL) next->mode->resize(next, wp->sx, wp->sy); } wp->flags |= (PANE_REDRAW|PANE_CHANGED); |