From ab4a4b2ad0ce2c8fdb485bc0fe871571181eace8 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 5 Apr 2017 10:45:39 +0000 Subject: cfg_file can be static. --- cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cfg.c b/cfg.c index c55a5dd4..5ad9916a 100644 --- a/cfg.c +++ b/cfg.c @@ -28,7 +28,7 @@ #include "tmux.h" -char *cfg_file; +static char *cfg_file; int cfg_finished; static char **cfg_causes; static u_int cfg_ncauses; -- cgit From 9b28200578670183a0dc70f1d16d5642101a6982 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 5 Apr 2017 10:49:46 +0000 Subject: Give each client a name. This defaults to the tty name as before but falls back to an alternative if the tty name is not available. This is clearer than overloading the client ttyname member and allows us to remove the path stored in the tty struct, it should always be the same as the client. --- cmd-choose-client.c | 6 +++--- cmd-find.c | 23 +++++++++++------------ cmd-list-clients.c | 2 +- format.c | 4 ++-- screen-redraw.c | 2 +- server-client.c | 19 +++++++++++++------ tmux.1 | 4 +++- tmux.h | 2 +- tty.c | 46 ++++++++++++++++++++++++++-------------------- 9 files changed, 61 insertions(+), 47 deletions(-) diff --git a/cmd-choose-client.c b/cmd-choose-client.c index 2a64da69..96a79534 100644 --- a/cmd-choose-client.c +++ b/cmd-choose-client.c @@ -28,7 +28,7 @@ */ #define CHOOSE_CLIENT_TEMPLATE \ - "#{client_tty}: #{session_name} " \ + "#{client_name}: #{session_name} " \ "[#{client_width}x#{client_height} #{client_termname}]" \ "#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \ "(last used #{t:client_activity})" @@ -85,7 +85,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmdq_item *item) cur = idx = 0; TAILQ_FOREACH(c1, &clients, entry) { - if (c1->session == NULL || c1->tty.path == NULL) + if (c1->session == NULL) continue; if (c1 == item->client) cur = idx; @@ -97,7 +97,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmdq_item *item) format_add(cdata->ft, "line", "%u", idx); format_defaults(cdata->ft, c1, NULL, NULL, NULL); - cdata->command = cmd_template_replace(action, c1->tty.path, 1); + cdata->command = cmd_template_replace(action, c1->name, 1); window_choose_add(wl->window->active, cdata); diff --git a/cmd-find.c b/cmd-find.c index 2f28a028..5c60f200 100644 --- a/cmd-find.c +++ b/cmd-find.c @@ -256,9 +256,9 @@ cmd_find_current_session_with_client(struct cmd_find_state *fs) * sessions to those containing that pane (we still use the current * window in the best session). */ - if (fs->item != NULL && fs->item->client->tty.path != NULL) { + if (fs->item != NULL) { RB_FOREACH(wp, window_pane_tree, &all_window_panes) { - if (strcmp(wp->tty, fs->item->client->tty.path) == 0) + if (strcmp(wp->tty, fs->item->client->ttyname) == 0) break; } } else @@ -1248,7 +1248,6 @@ cmd_find_client(struct cmdq_item *item, const char *target, int quiet) struct client *c; char *copy; size_t size; - const char *path; /* A NULL argument means the current client. */ if (item != NULL && target == NULL) { @@ -1265,20 +1264,20 @@ cmd_find_client(struct cmdq_item *item, const char *target, int quiet) if (size != 0 && copy[size - 1] == ':') copy[size - 1] = '\0'; - /* Check path of each client. */ + /* Check name and path of each client. */ TAILQ_FOREACH(c, &clients, entry) { - if (c->session == NULL || c->tty.path == NULL) + if (c->session == NULL) continue; - path = c->tty.path; - - /* Try for exact match. */ - if (strcmp(copy, path) == 0) + if (strcmp(copy, c->name) == 0) break; - /* Try without leading /dev. */ - if (strncmp(path, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0) + if (*c->ttyname == '\0') + continue; + if (strcmp(copy, c->ttyname) == 0) + break; + if (strncmp(c->ttyname, _PATH_DEV, (sizeof _PATH_DEV) - 1) != 0) continue; - if (strcmp(copy, path + (sizeof _PATH_DEV) - 1) == 0) + if (strcmp(copy, c->ttyname + (sizeof _PATH_DEV) - 1) == 0) break; } diff --git a/cmd-list-clients.c b/cmd-list-clients.c index faf39931..ca34bf25 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -29,7 +29,7 @@ */ #define LIST_CLIENTS_TEMPLATE \ - "#{client_tty}: #{session_name} " \ + "#{client_name}: #{session_name} " \ "[#{client_width}x#{client_height} #{client_termname}]" \ "#{?client_utf8, (utf8),} #{?client_readonly, (ro),}" diff --git a/format.c b/format.c index 7e78897f..5844a6ab 100644 --- a/format.c +++ b/format.c @@ -1139,11 +1139,11 @@ format_defaults_client(struct format_tree *ft, struct client *c) if (ft->s == NULL) ft->s = c->session; + format_add(ft, "client_name", "%s", c->name); format_add(ft, "client_pid", "%ld", (long) c->pid); format_add(ft, "client_height", "%u", tty->sy); format_add(ft, "client_width", "%u", tty->sx); - if (tty->path != NULL) - format_add(ft, "client_tty", "%s", tty->path); + format_add(ft, "client_tty", "%s", c->ttyname); format_add(ft, "client_control_mode", "%d", !!(c->flags & CLIENT_CONTROL)); diff --git a/screen-redraw.c b/screen-redraw.c index c2e39410..699a9191 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -423,7 +423,7 @@ screen_redraw_pane(struct client *c, struct window_pane *wp) if (status_at_line(c) == 0) yoff++; - log_debug("%s: redraw pane %%%u (at %u,%u)", c->tty.path, wp->id, + log_debug("%s: redraw pane %%%u (at %u,%u)", c->name, wp->id, wp->xoff, yoff); for (i = 0; i < wp->sy; i++) diff --git a/server-client.c b/server-client.c index a2dc79c7..6be467af 100644 --- a/server-client.c +++ b/server-client.c @@ -99,15 +99,12 @@ server_client_check_nested(struct client *c) struct environ_entry *envent; struct window_pane *wp; - if (c->tty.path == NULL) - return (0); - envent = environ_find(c->environ, "TMUX"); if (envent == NULL || *envent->value == '\0') return (0); RB_FOREACH(wp, window_pane_tree, &all_window_panes) { - if (strcmp(wp->tty, c->tty.path) == 0) + if (strcmp(wp->tty, c->ttyname) == 0) return (1); } return (0); @@ -322,8 +319,10 @@ server_client_free(__unused int fd, __unused short events, void *arg) if (!TAILQ_EMPTY(&c->queue)) fatalx("queue not empty"); - if (c->references == 0) + if (c->references == 0) { + free((void *)c->name); free(c); + } } /* Detach a client. */ @@ -1470,6 +1469,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) const char *data, *home; size_t datalen; int flags; + char *name; if (c->flags & CLIENT_IDENTIFIED) fatalx("out-of-order identify message"); @@ -1535,6 +1535,13 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) return; c->flags |= CLIENT_IDENTIFIED; + if (*c->ttyname != '\0') + name = xstrdup(c->ttyname); + else + xasprintf(&name, "client-%ld", (long)c->pid); + c->name = name; + log_debug("client %p name is %s", c, c->name); + if (c->flags & CLIENT_CONTROL) { c->stdin_callback = control_callback; @@ -1685,7 +1692,7 @@ server_client_add_message(struct client *c, const char *fmt, ...) xvasprintf(&s, fmt, ap); va_end(ap); - log_debug("%s: message %s", c->tty.path, s); + log_debug("message %s (client %p)", s, c); msg = xcalloc(1, sizeof *msg); msg->msg_time = time(NULL); diff --git a/tmux.1 b/tmux.1 index 6d035573..07a31d7d 100644 --- a/tmux.1 +++ b/tmux.1 @@ -367,7 +367,8 @@ or These specify the client, session, window or pane which a command should affect. .Pp .Ar target-client -should be the name of the +should be the name of the client, +typically the .Xr pty 4 file to which the client is connected, for example either of .Pa /dev/ttyp1 @@ -3510,6 +3511,7 @@ The following variables are available, where appropriate: .It Li "client_height" Ta "" Ta "Height of client" .It Li "client_key_table" Ta "" Ta "Current key table" .It Li "client_last_session" Ta "" Ta "Name of the client's last session" +.It Li "client_name" Ta "" Ta "Name of client" .It Li "client_pid" Ta "" Ta "PID of client process" .It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed" .It Li "client_readonly" Ta "" Ta "1 if client is readonly" diff --git a/tmux.h b/tmux.h index dab15b3a..509497bb 100644 --- a/tmux.h +++ b/tmux.h @@ -1021,7 +1021,6 @@ LIST_HEAD(tty_terms, tty_term); struct tty { struct client *client; - char *path; u_int sx; u_int sy; @@ -1285,6 +1284,7 @@ struct cmd_entry { /* Client connection. */ struct client { + const char *name; struct tmuxpeer *peer; struct cmdq_list queue; diff --git a/tty.c b/tty.c index 8d54007b..04a673fc 100644 --- a/tty.c +++ b/tty.c @@ -94,8 +94,6 @@ tty_create_log(void) int tty_init(struct tty *tty, struct client *c, int fd, char *term) { - char *path; - if (!isatty(fd)) return (-1); @@ -105,12 +103,10 @@ tty_init(struct tty *tty, struct client *c, int fd, char *term) tty->term_name = xstrdup("unknown"); else tty->term_name = xstrdup(term); + tty->fd = fd; tty->client = c; - if ((path = ttyname(fd)) == NULL) - return (-1); - tty->path = xstrdup(path); tty->cstyle = 0; tty->ccolour = xstrdup(""); @@ -125,8 +121,9 @@ tty_init(struct tty *tty, struct client *c, int fd, char *term) int tty_resize(struct tty *tty) { - struct winsize ws; - u_int sx, sy; + struct client *c = tty->client; + struct winsize ws; + u_int sx, sy; if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) { sx = ws.ws_col; @@ -139,7 +136,8 @@ tty_resize(struct tty *tty) sx = 80; sy = 24; } - log_debug("%s: %s now %ux%u", __func__, tty->path, sx, sy); + log_debug("%s: %s now %ux%u", __func__, c->name, sx, sy); + if (!tty_set_size(tty, sx, sy)) return (0); tty_invalidate(tty); @@ -160,13 +158,14 @@ static void tty_read_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; + struct client *c = tty->client; size_t size = EVBUFFER_LENGTH(tty->in); int nread; nread = evbuffer_read(tty->in, tty->fd, -1); if (nread == -1) return; - log_debug("%s: read %d bytes (already %zu)", tty->path, nread, size); + log_debug("%s: read %d bytes (already %zu)", c->name, nread, size); while (tty_keys_next(tty)) ; @@ -176,13 +175,14 @@ static void tty_write_callback(__unused int fd, __unused short events, void *data) { struct tty *tty = data; + struct client *c = tty->client; size_t size = EVBUFFER_LENGTH(tty->out); int nwrite; nwrite = evbuffer_write(tty->out, tty->fd); if (nwrite == -1) return; - log_debug("%s: wrote %d bytes (of %zu)", tty->path, nwrite, size); + log_debug("%s: wrote %d bytes (of %zu)", c->name, nwrite, size); if (EVBUFFER_LENGTH(tty->out) != 0) event_add(&tty->event_out, NULL); @@ -351,7 +351,6 @@ tty_free(struct tty *tty) tty_close(tty); free(tty->ccolour); - free(tty->path); free(tty->term_name); } @@ -424,8 +423,10 @@ tty_putcode_ptr2(struct tty *tty, enum tty_code_code code, const void *a, static void tty_add(struct tty *tty, const char *buf, size_t len) { + struct client *c = tty->client; + evbuffer_add(tty->out, buf, len); - log_debug("%s: %.*s", tty->path, (int)len, (const char *)buf); + log_debug("%s: %.*s", c->name, (int)len, (const char *)buf); if (tty_log_fd != -1) write(tty_log_fd, buf, len); @@ -602,8 +603,17 @@ tty_emulate_repeat(struct tty *tty, enum tty_code_code code, static void tty_repeat_space(struct tty *tty, u_int n) { - while (n-- > 0) - tty_putc(tty, ' '); + static char s[500]; + + if (*s != ' ') + memset(s, ' ', sizeof s); + + while (n > sizeof s) { + tty_putn(tty, s, sizeof s, sizeof s); + n -= sizeof s; + } + if (n != 0) + tty_putn(tty, s, n, n); } /* @@ -856,8 +866,6 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) { - u_int i; - tty_attributes(tty, &grid_default_cell, ctx->wp); tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); @@ -865,10 +873,8 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx) if (tty_term_has(tty->term, TTYC_ECH) && !tty_fake_bce(tty, ctx->wp, ctx->bg)) tty_putcode1(tty, TTYC_ECH, ctx->num); - else { - for (i = 0; i < ctx->num; i++) - tty_putc(tty, ' '); - } + else + tty_repeat_space(tty, ctx->num); } void -- cgit From 36882ec789f29882ab7241e5d4c0572799163437 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 5 Apr 2017 11:04:48 +0000 Subject: Try again to resolve problems with mistaking sessions for windows: now do not look up windows as sessions (and panes as windows) when they are qualified with a ':' or a '.'. So 'foo' as a window target will look for windows and sessions called 'foo', but ':foo' will only look for windows, and 'foo:' only for sessions. This means the common case of using an unadorned session as a window target (send -tfoo) should continue to work, but an explicit window will not get confused with a session (send -t:foo). --- cmd-find.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cmd-find.c b/cmd-find.c index 5c60f200..877af492 100644 --- a/cmd-find.c +++ b/cmd-find.c @@ -43,10 +43,10 @@ static struct client *cmd_find_current_client(struct cmdq_item *); static const char *cmd_find_map_table(const char *[][2], const char *); static int cmd_find_get_session(struct cmd_find_state *, const char *); -static int cmd_find_get_window(struct cmd_find_state *, const char *); +static int cmd_find_get_window(struct cmd_find_state *, const char *, int); static int cmd_find_get_window_with_session(struct cmd_find_state *, const char *); -static int cmd_find_get_pane(struct cmd_find_state *, const char *); +static int cmd_find_get_pane(struct cmd_find_state *, const char *, int); static int cmd_find_get_pane_with_session(struct cmd_find_state *, const char *); static int cmd_find_get_pane_with_window(struct cmd_find_state *, @@ -464,7 +464,7 @@ cmd_find_get_session(struct cmd_find_state *fs, const char *session) /* Find window from string. Fills in s, wl, w. */ static int -cmd_find_get_window(struct cmd_find_state *fs, const char *window) +cmd_find_get_window(struct cmd_find_state *fs, const char *window, int only) { log_debug("%s: %s", __func__, window); @@ -484,7 +484,7 @@ cmd_find_get_window(struct cmd_find_state *fs, const char *window) return (0); /* Otherwise try as a session itself. */ - if (cmd_find_get_session(fs, window) == 0) { + if (!only && cmd_find_get_session(fs, window) == 0) { fs->wl = fs->s->curw; fs->w = fs->wl->window; if (~fs->flags & CMD_FIND_WINDOW_INDEX) @@ -651,7 +651,7 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window) /* Find pane from string. Fills in s, wl, w, wp. */ static int -cmd_find_get_pane(struct cmd_find_state *fs, const char *pane) +cmd_find_get_pane(struct cmd_find_state *fs, const char *pane, int only) { log_debug("%s: %s", __func__, pane); @@ -675,7 +675,7 @@ cmd_find_get_pane(struct cmd_find_state *fs, const char *pane) return (0); /* Otherwise try as a window itself (this will also try as session). */ - if (cmd_find_get_window(fs, pane) == 0) { + if (!only && cmd_find_get_window(fs, pane, 0) == 0) { fs->wp = fs->w->active; return (0); } @@ -982,6 +982,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, struct mouse_event *m; char *colon, *period, *copy = NULL; const char *session, *window, *pane; + int window_only = 0, pane_only = 0; /* Log the arguments. */ if (target == NULL) @@ -1066,13 +1067,17 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, if (colon != NULL && period != NULL) { session = copy; window = colon; + window_only = 1; pane = period; + pane_only = 1; } else if (colon != NULL && period == NULL) { session = copy; window = colon; + window_only = 1; } else if (colon == NULL && period != NULL) { window = copy; pane = period; + pane_only = 1; } else { if (*copy == '$') session = copy; @@ -1179,7 +1184,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, /* No session. If window and pane, try them. */ if (window != NULL && pane != NULL) { /* This will fill in session, winlink and window. */ - if (cmd_find_get_window(fs, window) != 0) + if (cmd_find_get_window(fs, window, window_only) != 0) goto no_window; /* This will fill in pane. */ if (cmd_find_get_pane_with_window(fs, pane) != 0) @@ -1190,7 +1195,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, /* If just window is present, try it. */ if (window != NULL && pane == NULL) { /* This will fill in session, winlink and window. */ - if (cmd_find_get_window(fs, window) != 0) + if (cmd_find_get_window(fs, window, window_only) != 0) goto no_window; fs->wp = fs->wl->window->active; goto found; @@ -1199,7 +1204,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current, /* If just pane is present, try it. */ if (window == NULL && pane != NULL) { /* This will fill in session, winlink, window and pane. */ - if (cmd_find_get_pane(fs, pane) != 0) + if (cmd_find_get_pane(fs, pane, pane_only) != 0) goto no_pane; goto found; } -- cgit From 94b71bcb6403d381515319b08a85878b829785d5 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 5 Apr 2017 12:14:18 +0000 Subject: Add Home and End for copy mode. --- key-bindings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/key-bindings.c b/key-bindings.c index d96b51f6..37ff7fe7 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -260,6 +260,8 @@ key_bindings_init(void) "bind -Tcopy-mode n send -X search-again", "bind -Tcopy-mode q send -X cancel", "bind -Tcopy-mode t command-prompt -1p'jump to forward' 'send -X jump-to-forward \"%%%\"'", + "bind -Tcopy-mode Home send -X start-of-line", + "bind -Tcopy-mode End send -X end-of-line", "bind -Tcopy-mode MouseDown1Pane select-pane", "bind -Tcopy-mode MouseDrag1Pane select-pane\\; send -X begin-selection", "bind -Tcopy-mode MouseDragEnd1Pane send -X copy-selection-and-cancel", -- cgit