diff options
| author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2021-04-13 06:25:59 +0100 |
|---|---|---|
| committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2021-04-13 06:25:59 +0100 |
| commit | c2048c5c65aea99f2b79290b87635cb1d90863a6 (patch) | |
| tree | 8aafdf588893ccdd65c8db53f5188f83f020675b | |
| parent | 46cbbe3d4566885b8ad4235598389936f63c2c01 (diff) | |
| parent | bedf2bd4372c60a525c22e6309f329cfd0bd07bc (diff) | |
| download | rtmux-c2048c5c65aea99f2b79290b87635cb1d90863a6.tar.gz rtmux-c2048c5c65aea99f2b79290b87635cb1d90863a6.tar.bz2 rtmux-c2048c5c65aea99f2b79290b87635cb1d90863a6.zip | |
Merge branch 'master' into 3.2-rc
| -rw-r--r-- | alerts.c | 9 | ||||
| -rw-r--r-- | cfg.c | 20 | ||||
| -rw-r--r-- | cmd-choose-tree.c | 18 | ||||
| -rw-r--r-- | cmd-display-message.c | 22 | ||||
| -rw-r--r-- | cmd-list-keys.c | 7 | ||||
| -rw-r--r-- | cmd-queue.c | 4 | ||||
| -rw-r--r-- | cmd-run-shell.c | 9 | ||||
| -rw-r--r-- | control-notify.c | 11 | ||||
| -rw-r--r-- | format.c | 34 | ||||
| -rw-r--r-- | grid-reader.c | 28 | ||||
| -rw-r--r-- | input-keys.c | 26 | ||||
| -rw-r--r-- | key-string.c | 17 | ||||
| -rw-r--r-- | log.c | 13 | ||||
| -rw-r--r-- | mode-tree.c | 70 | ||||
| -rw-r--r-- | notify.c | 2 | ||||
| -rw-r--r-- | screen.c | 4 | ||||
| -rw-r--r-- | server-client.c | 12 | ||||
| -rw-r--r-- | status.c | 7 | ||||
| -rw-r--r-- | tmux.1 | 45 | ||||
| -rw-r--r-- | tmux.h | 10 | ||||
| -rw-r--r-- | tty-keys.c | 61 | ||||
| -rw-r--r-- | tty.c | 38 | ||||
| -rw-r--r-- | window-buffer.c | 59 | ||||
| -rw-r--r-- | window-client.c | 43 | ||||
| -rw-r--r-- | window-copy.c | 257 | ||||
| -rw-r--r-- | window-customize.c | 8 | ||||
| -rw-r--r-- | window-tree.c | 52 |
27 files changed, 667 insertions, 219 deletions
@@ -314,10 +314,11 @@ alerts_set_message(struct winlink *wl, const char *type, const char *option) tty_putcode(&c->tty, TTYC_BEL); if (visual == VISUAL_OFF) continue; - if (c->session->curw == wl) - status_message_set(c, -1, 1, "%s in current window", type); - else { - status_message_set(c, -1, 1, "%s in window %d", type, + if (c->session->curw == wl) { + status_message_set(c, -1, 1, 0, "%s in current window", + type); + } else { + status_message_set(c, -1, 1, 0, "%s in window %d", type, wl->idx); } } @@ -102,6 +102,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags, struct cmd_parse_input pi; struct cmd_parse_result *pr; struct cmdq_item *new_item0; + struct cmdq_state *state; if (new_item != NULL) *new_item = NULL; @@ -135,12 +136,19 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags, return (0); } - new_item0 = cmdq_get_command(pr->cmdlist, NULL); + if (item != NULL) + state = cmdq_copy_state(cmdq_get_state(item)); + else + state = cmdq_new_state(NULL, NULL, 0); + cmdq_add_format(state, "current_file", "%s", pi.file); + + new_item0 = cmdq_get_command(pr->cmdlist, state); if (item != NULL) new_item0 = cmdq_insert_after(item, new_item0); else new_item0 = cmdq_append(NULL, new_item0); cmd_list_free(pr->cmdlist); + cmdq_free_state(state); if (new_item != NULL) *new_item = new_item0; @@ -155,6 +163,7 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path, struct cmd_parse_input pi; struct cmd_parse_result *pr; struct cmdq_item *new_item0; + struct cmdq_state *state; if (new_item != NULL) *new_item = NULL; @@ -181,12 +190,19 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path, return (0); } - new_item0 = cmdq_get_command(pr->cmdlist, NULL); + if (item != NULL) + state = cmdq_copy_state(cmdq_get_state(item)); + else + state = cmdq_new_state(NULL, NULL, 0); + cmdq_add_format(state, "current_file", "%s", pi.file); + + new_item0 = cmdq_get_command(pr->cmdlist, state); if (item != NULL) new_item0 = cmdq_insert_after(item, new_item0); else new_item0 = cmdq_append(NULL, new_item0); cmd_list_free(pr->cmdlist); + cmdq_free_state(state); if (new_item != NULL) *new_item = new_item0; diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c index a58469ac..81209ee3 100644 --- a/cmd-choose-tree.c +++ b/cmd-choose-tree.c @@ -30,9 +30,9 @@ const struct cmd_entry cmd_choose_tree_entry = { .name = "choose-tree", .alias = NULL, - .args = { "F:Gf:NO:rst:wZ", 0, 1 }, - .usage = "[-GNrswZ] [-F format] [-f filter] [-O sort-order] " - CMD_TARGET_PANE_USAGE " [template]", + .args = { "F:f:GK:NO:rst:wZ", 0, 1 }, + .usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] " + "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -44,9 +44,9 @@ const struct cmd_entry cmd_choose_client_entry = { .name = "choose-client", .alias = NULL, - .args = { "F:f:NO:rt:Z", 0, 1 }, - .usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] " - CMD_TARGET_PANE_USAGE " [template]", + .args = { "F:f:K:NO:rt:Z", 0, 1 }, + .usage = "[-NrZ] [-F format] [-f filter] [-K key-format] " + "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -58,9 +58,9 @@ const struct cmd_entry cmd_choose_buffer_entry = { .name = "choose-buffer", .alias = NULL, - .args = { "F:f:NO:rt:Z", 0, 1 }, - .usage = "[-NrZ] [-F format] [-f filter] [-O sort-order] " - CMD_TARGET_PANE_USAGE " [template]", + .args = { "F:f:K:NO:rt:Z", 0, 1 }, + .usage = "[-NrZ] [-F format] [-f filter] [-K key-format] " + "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]", .target = { 't', CMD_FIND_PANE, 0 }, diff --git a/cmd-display-message.c b/cmd-display-message.c index fc9c4851..0522d37f 100644 --- a/cmd-display-message.c +++ b/cmd-display-message.c @@ -39,11 +39,11 @@ const struct cmd_entry cmd_display_message_entry = { .name = "display-message", .alias = "display", - .args = { "acd:Ipt:F:v", 0, 1 }, - .usage = "[-aIpv] [-c target-client] [-d delay] [-F format] " + .args = { "acd:INpt:F:v", 0, 1 }, + .usage = "[-aINpv] [-c target-client] [-d delay] [-F format] " CMD_TARGET_PANE_USAGE " [message]", - .target = { 't', CMD_FIND_PANE, 0 }, + .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, .flags = CMD_AFTERHOOK|CMD_CLIENT_CFLAG|CMD_CLIENT_CANFAIL, .exec = cmd_display_message_exec @@ -73,6 +73,8 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) int flags; if (args_has(args, 'I')) { + if (wp == NULL) + return (CMD_RETURN_NORMAL); if (window_pane_start_input(wp, item, &cause) != 0) { cmdq_error(item, "%s", cause); free(cause); @@ -109,8 +111,10 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) */ if (tc != NULL && tc->session == s) c = tc; - else + else if (s != NULL) c = cmd_find_best_client(s); + else + c = NULL; if (args_has(args, 'v')) flags = FORMAT_VERBOSE; else @@ -124,10 +128,14 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) } msg = format_expand_time(ft, template); - if (args_has(args, 'p')) + if (cmdq_get_client(item) == NULL) + cmdq_error(item, "%s", msg); + else if (args_has(args, 'p')) cmdq_print(item, "%s", msg); - else if (tc != NULL) - status_message_set(tc, delay, 0, "%s", msg); + else if (tc != NULL) { + status_message_set(tc, delay, 0, args_has(args, 'N'), "%s", + msg); + } free(msg); format_free(ft); diff --git a/cmd-list-keys.c b/cmd-list-keys.c index dd82e57e..ca4bf752 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -113,9 +113,10 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args, else note = xstrdup(bd->note); tmp = utf8_padcstr(key, keywidth + 1); - if (args_has(args, '1') && tc != NULL) - status_message_set(tc, -1, 1, "%s%s%s", prefix, tmp, note); - else + if (args_has(args, '1') && tc != NULL) { + status_message_set(tc, -1, 1, 0, "%s%s%s", prefix, tmp, + note); + } else cmdq_print(item, "%s%s%s", prefix, tmp, note); free(tmp); free(note); diff --git a/cmd-queue.c b/cmd-queue.c index 05f439f5..54163919 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -276,7 +276,7 @@ cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft) const struct cmd_entry *entry; if (item->cmd != NULL) { - entry = cmd_get_entry (item->cmd); + entry = cmd_get_entry(item->cmd); format_add(ft, "command", "%s", entry->name); } if (item->state->formats != NULL) @@ -862,7 +862,7 @@ cmdq_error(struct cmdq_item *item, const char *fmt, ...) c->retval = 1; } else { *msg = toupper((u_char) *msg); - status_message_set(c, -1, 1, "%s", msg); + status_message_set(c, -1, 1, 0, "%s", msg); } free(msg); diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 4f30d05d..56d5f723 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -20,6 +20,7 @@ #include <sys/types.h> #include <sys/wait.h> +#include <ctype.h> #include <stdlib.h> #include <string.h> @@ -190,8 +191,12 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg) &error); } if (status == CMD_PARSE_ERROR) { - cmdq_error(cdata->item, "%s", error); - free(error); + if (cdata->item == NULL) { + *error = toupper((u_char)*error); + status_message_set(c, -1, 1, 0, "%s", error); + } else + cmdq_error(cdata->item, "%s", error); + free(error); } } diff --git a/control-notify.c b/control-notify.c index cc706ac2..6ff0e436 100644 --- a/control-notify.c +++ b/control-notify.c @@ -172,6 +172,17 @@ control_notify_client_session_changed(struct client *cc) } void +control_notify_client_detached(struct client *cc) +{ + struct client *c; + + TAILQ_FOREACH(c, &clients, entry) { + if (CONTROL_SHOULD_NOTIFY_CLIENT(c)) + control_write(c, "%%client-detached %s", cc->name); + } +} + +void control_notify_session_renamed(struct session *s) { struct client *c; @@ -100,6 +100,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2) #define FORMAT_QUOTE_STYLE 0x2000 #define FORMAT_WINDOW_NAME 0x4000 #define FORMAT_SESSION_NAME 0x8000 +#define FORMAT_CHARACTER 0x10000 /* Limit on recursion. */ #define FORMAT_LOOP_LIMIT 10 @@ -3522,7 +3523,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, /* * Modifiers are a ; separated list of the forms: - * l,m,C,b,d,n,t,w,q,E,T,S,W,P,<,> + * l,m,C,a,b,d,n,t,w,q,E,T,S,W,P,<,> * =a * =/a * =/a/ @@ -3539,7 +3540,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, cp++; /* Check single character modifiers with no arguments. */ - if (strchr("lbdnwETSWP<>", cp[0]) != NULL && + if (strchr("labdnwETSWP<>", cp[0]) != NULL && format_is_end(cp[1])) { format_add_modifier(&list, count, cp, 1, NULL, 0); cp++; @@ -3956,7 +3957,7 @@ format_replace_expression(struct format_modifier *mexp, mright = (long long)mright; } format_log(es, "expression left side is: %.*f", prec, mleft); - format_log(es, "expression right side is: %.*f", prec, mright); + format_log(es, "expression right side is: %.*f", prec, mright); switch (operator) { case ADD: @@ -4016,10 +4017,10 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, { struct format_tree *ft = es->ft; struct window_pane *wp = ft->wp; - const char *errptr, *copy, *cp, *marker = NULL; + const char *errstr, *copy, *cp, *marker = NULL; const char *time_format = NULL; char *copy0, *condition, *found, *new; - char *value, *left, *right; + char *value, *left, *right, c; size_t valuelen; int modifiers = 0, limit = 0, width = 0; int j; @@ -4063,8 +4064,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, if (fm->argc < 1) break; limit = strtonum(fm->argv[0], INT_MIN, INT_MAX, - &errptr); - if (errptr != NULL) + &errstr); + if (errstr != NULL) limit = 0; if (fm->argc >= 2 && fm->argv[1] != NULL) marker = fm->argv[1]; @@ -4073,8 +4074,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, if (fm->argc < 1) break; width = strtonum(fm->argv[0], INT_MIN, INT_MAX, - &errptr); - if (errptr != NULL) + &errstr); + if (errstr != NULL) width = 0; break; case 'w': @@ -4088,6 +4089,9 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, case 'l': modifiers |= FORMAT_LITERAL; break; + case 'a': + modifiers |= FORMAT_CHARACTER; + break; case 'b': modifiers |= FORMAT_BASENAME; break; @@ -4154,6 +4158,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, goto done; } + /* Is this a character? */ + if (modifiers & FORMAT_CHARACTER) { + new = format_expand1(es, copy); + c = strtonum(new, 32, 126, &errstr); + if (errstr != NULL) + value = xstrdup(""); + else + xasprintf(&value, "%c", c); + free (new); + goto done; + } + /* Is this a loop, comparison or condition? */ if (modifiers & FORMAT_SESSIONS) { value = format_loop_sessions(es, copy); diff --git a/grid-reader.c b/grid-reader.c index ae2f4d2b..89fe90fb 100644 --- a/grid-reader.c +++ b/grid-reader.c @@ -71,7 +71,7 @@ grid_reader_cursor_right(struct grid_reader *gr, int wrap, int all) /* Move cursor back one position. */ void -grid_reader_cursor_left(struct grid_reader *gr) +grid_reader_cursor_left(struct grid_reader *gr, int wrap) { struct grid_cell gc; @@ -81,7 +81,9 @@ grid_reader_cursor_left(struct grid_reader *gr) break; gr->cx--; } - if (gr->cx == 0 && gr->cy > 0) { + if (gr->cx == 0 && gr->cy > 0 && + (wrap || + grid_get_line(gr->gd, gr->cy - 1)->flags & GRID_LINE_WRAPPED)) { grid_reader_cursor_up(gr); grid_reader_cursor_end_of_line(gr, 0, 0); } else if (gr->cx > 0) @@ -363,3 +365,25 @@ grid_reader_cursor_jump_back(struct grid_reader *gr, const struct utf8_data *jc) } return 0; } + +/* Jump back to the first non-blank character of the line. */ +void +grid_reader_cursor_back_to_indentation(struct grid_reader *gr) +{ + struct grid_cell gc; + u_int px, py, xx, yy; + + yy = gr->gd->hsize + gr->gd->sy - 1; + grid_reader_cursor_start_of_line(gr, 1); + + for (py = gr->cy; py <= yy; py++) { + xx = grid_line_length(gr->gd, py); + for (px = 0; px < xx; px++) { + grid_get_cell(gr->gd, px, py, &gc); + if (gc.data.size != 1 || *gc.data.data != ' ') + break; + } + if (~grid_get_line(gr->gd, py)->flags & GRID_LINE_WRAPPED) + break; + } +} diff --git a/input-keys.c b/input-keys.c index 39a72cdc..a3252855 100644 --- a/input-keys.c +++ b/input-keys.c @@ -428,6 +428,14 @@ input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m) return (input_key(wp->screen, wp->event, key)); } +static void +input_key_write(const char *from, struct bufferevent *bev, const char *data, + size_t size) +{ + log_debug("%s: %.*s", from, (int)size, data); + bufferevent_write(bev, data, size); +} + /* Translate a key code into an output key sequence. */ int input_key(struct screen *s, struct bufferevent *bev, key_code key) @@ -444,7 +452,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) /* Literal keys go as themselves (can't be more than eight bits). */ if (key & KEYC_LITERAL) { ud.data[0] = (u_char)key; - bufferevent_write(bev, &ud.data[0], 1); + input_key_write(__func__, bev, &ud.data[0], 1); return (0); } @@ -463,16 +471,16 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) justkey = (key & ~(KEYC_META|KEYC_IMPLIED_META)); if (justkey <= 0x7f) { if (key & KEYC_META) - bufferevent_write(bev, "\033", 1); + input_key_write(__func__, bev, "\033", 1); ud.data[0] = justkey; - bufferevent_write(bev, &ud.data[0], 1); + input_key_write(__func__, bev, &ud.data[0], 1); return (0); } if (justkey > 0x7f && justkey < KEYC_BASE) { if (key & KEYC_META) - bufferevent_write(bev, "\033", 1); + input_key_write(__func__, bev, "\033", 1); utf8_to_data(justkey, &ud); - bufferevent_write(bev, ud.data, ud.size); + input_key_write(__func__, bev, ud.data, ud.size); return (0); } @@ -494,8 +502,8 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) if (ike != NULL) { log_debug("found key 0x%llx: \"%s\"", key, ike->data); if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META)) - bufferevent_write(bev, "\033", 1); - bufferevent_write(bev, ike->data, strlen(ike->data)); + input_key_write(__func__, bev, "\033", 1); + input_key_write(__func__, bev, ike->data, strlen(ike->data)); return (0); } @@ -560,7 +568,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) goto missing; } xsnprintf(tmp, sizeof tmp, "\033[%llu;%cu", outkey, modifier); - bufferevent_write(bev, tmp, strlen(tmp)); + input_key_write(__func__, bev, tmp, strlen(tmp)); return (0); missing: @@ -656,5 +664,5 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m) if (!input_key_get_mouse(s, m, x, y, &buf, &len)) return; log_debug("writing mouse %.*s to %%%u", (int)len, buf, wp->id); - bufferevent_write(wp->event, buf, len); + input_key_write(__func__, wp->event, buf, len); } diff --git a/key-string.c b/key-string.c index 194fdef2..8d60f132 100644 --- a/key-string.c +++ b/key-string.c @@ -45,9 +45,9 @@ static const struct { { "F11", KEYC_F11|KEYC_IMPLIED_META }, { "F12", KEYC_F12|KEYC_IMPLIED_META }, { "IC", KEYC_IC|KEYC_IMPLIED_META }, - { "Insert", KEYC_IC|KEYC_IMPLIED_META }, + { "Insert", KEYC_IC|KEYC_IMPLIED_META }, { "DC", KEYC_DC|KEYC_IMPLIED_META }, - { "Delete", KEYC_DC|KEYC_IMPLIED_META }, + { "Delete", KEYC_DC|KEYC_IMPLIED_META }, { "Home", KEYC_HOME|KEYC_IMPLIED_META }, { "End", KEYC_END|KEYC_IMPLIED_META }, { "NPage", KEYC_NPAGE|KEYC_IMPLIED_META }, @@ -70,7 +70,7 @@ static const struct { { "Right", KEYC_RIGHT|KEYC_CURSOR|KEYC_IMPLIED_META }, /* Numeric keypad. */ - { "KP/", KEYC_KP_SLASH|KEYC_KEYPAD }, + { "KP/", KEYC_KP_SLASH|KEYC_KEYPAD }, { "KP*", KEYC_KP_STAR|KEYC_KEYPAD }, { "KP-", KEYC_KP_MINUS|KEYC_KEYPAD }, { "KP7", KEYC_KP_SEVEN|KEYC_KEYPAD }, @@ -164,7 +164,7 @@ key_string_get_modifiers(const char **string) key_code key_string_lookup_string(const char *string) { - static const char *other = "!#()+,-.0123456789:;<=>'\r\t"; + static const char *other = "!#()+,-.0123456789:;<=>'\r\t\177"; key_code key, modifiers; u_int u, i; struct utf8_data ud, *udp; @@ -181,8 +181,8 @@ key_string_lookup_string(const char *string) /* Is this a hexadecimal value? */ if (string[0] == '0' && string[1] == 'x') { - if (sscanf(string + 2, "%x", &u) != 1) - return (KEYC_UNKNOWN); + if (sscanf(string + 2, "%x", &u) != 1) + return (KEYC_UNKNOWN); mlen = wctomb(m, u); if (mlen <= 0 || mlen > MB_LEN_MAX) return (KEYC_UNKNOWN); @@ -238,11 +238,12 @@ key_string_lookup_string(const char *string) } /* Convert the standard control keys. */ - if (key < KEYC_BASE && (modifiers & KEYC_CTRL) && !strchr(other, key)) { + if (key < KEYC_BASE && (modifiers & KEYC_CTRL) && + strchr(other, key) == NULL) { if (key >= 97 && key <= 122) key -= 96; else if (key >= 64 && key <= 95) - key -= 64; + key -= 64; else if (key == 32) key = 0; else if (key == 63) @@ -110,15 +110,16 @@ log_vwrite(const char *msg, va_list ap) return; if (vasprintf(&fmt, msg, ap) == -1) - exit(1); - if (stravis(&out, fmt, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) - exit(1); + return; + if (stravis(&out, fmt, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) { + free(fmt); + return; + } gettimeofday(&tv, NULL); if (fprintf(log_file, "%lld.%06d %s\n", (long long)tv.tv_sec, - (int)tv.tv_usec, out) == -1) - exit(1); - fflush(log_file); + (int)tv.tv_usec, out) != -1) + fflush(log_file); free(out); free(fmt); diff --git a/mode-tree.c b/mode-tree.c index a47c0c06..ca7f33a4 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -46,6 +46,7 @@ struct mode_tree_data { mode_tree_search_cb searchcb; mode_tree_menu_cb menucb; mode_tree_height_cb heightcb; + mode_tree_key_cb keycb; struct mode_tree_list children; struct mode_tree_list saved; @@ -74,6 +75,10 @@ struct mode_tree_item { void *itemdata; u_int line; + key_code key; + const char *keystr; + size_t keylen; + uint64_t tag; const char *name; const char *text; @@ -135,6 +140,7 @@ mode_tree_free_item(struct mode_tree_item *mti) free((void *)mti->name); free((void *)mti->text); + free((void *)mti->keystr); free(mti); } @@ -193,6 +199,26 @@ mode_tree_build_lines(struct mode_tree_data *mtd, flat = 0; if (mti->expanded) mode_tree_build_lines(mtd, &mti->children, depth + 1); + + if (mtd->keycb != NULL) { + mti->key = mtd->keycb(mtd->modedata, mti->itemdata, + mti->line); + if (mti->key == KEYC_UNKNOWN) + mti->key = KEYC_NONE; + } else if (mti->line < 10) + mti->key = '0' + mti->line; + else if (mti->line < 36) + mti->key = KEYC_META|('a' + mti->line - 10); + else + mti->key = KEYC_NONE; + if (mti->key != KEYC_NONE) { + mti->keystr = xstrdup(key_string_lookup_key(mti->key, + 0)); + mti->keylen = strlen(mti->keystr); + } else { + mti->keystr = NULL; + mti->keylen = 0; + } } TAILQ_FOREACH(mti, mtl, entry) { for (i = 0; i < mtd->line_size; i++) { @@ -363,7 +389,7 @@ struct mode_tree_data * mode_tree_start(struct window_pane *wp, struct args *args, mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb, mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, - mode_tree_height_cb heightcb, void *modedata, + mode_tree_height_cb heightcb, mode_tree_key_cb keycb, void *modedata, const struct menu_item *menu, const char **sort_list, u_int sort_size, struct screen **s) { @@ -402,6 +428,7 @@ mode_tree_start(struct window_pane *wp, struct args *args, mtd->searchcb = searchcb; mtd->menucb = menucb; mtd->heightcb = heightcb; + mtd->keycb = keycb; TAILQ_INIT(&mtd->children); @@ -596,10 +623,10 @@ mode_tree_draw(struct mode_tree_data *mtd) struct screen_write_ctx ctx; struct grid_cell gc0, gc; u_int w, h, i, j, sy, box_x, box_y, width; - char *text, *start, key[7]; + char *text, *start, *key; const char *tag, *symbol; size_t size, n; - int keylen; + int keylen, pad; if (mtd->line_size == 0) return; @@ -614,28 +641,30 @@ mode_tree_draw(struct mode_tree_data *mtd) screen_write_start(&ctx, s); screen_write_clearscreen(&ctx, 8); - if (mtd->line_size > 10) - keylen = 6; - else - keylen = 4; + keylen = 0; + for (i = 0; i < mtd->line_size; i++) { + mti = mtd->line_list[i].item; + if (mti->key == KEYC_NONE) + continue; + if ((int)mti->keylen + 3 > keylen) + keylen = mti->keylen + 3; + } for (i = 0; i < mtd->line_size; i++) { if (i < mtd->offset) continue; if (i > mtd->offset + h - 1) break; - line = &mtd->line_list[i]; mti = line->item; screen_write_cursormove(&ctx, 0, i - mtd->offset, 0); - if (i < 10) - snprintf(key, sizeof key, "(%c) ", '0' + i); - else if (i < 36) - snprintf(key, sizeof key, "(M-%c)", 'a' + (i - 10)); + pad = keylen - 2 - mti->keylen; + if (mti->key != KEYC_NONE) + xasprintf(&key, "(%s)%*s", mti->keystr, pad, ""); else - *key = '\0'; + key = xstrdup(""); if (line->flat) symbol = ""; @@ -698,6 +727,7 @@ mode_tree_draw(struct mode_tree_data *mtd) } } free(text); + free(key); if (mti->tagged) { gc.attr ^= GRID_ATTR_BRIGHT; @@ -951,7 +981,6 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, struct mode_tree_item *current, *parent, *mti; u_int i, x, y; int choice; - key_code tmp; if (KEYC_IS_MOUSE(*key) && m != NULL) { if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) { @@ -993,12 +1022,11 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, current = line->item; choice = -1; - if (*key >= '0' && *key <= '9') - choice = (*key) - '0'; - else if (((*key) & KEYC_MASK_MODIFIERS) == KEYC_META) { - tmp = (*key) & KEYC_MASK_KEY; - if (tmp >= 'a' && tmp <= 'z') - choice = 10 + (tmp - 'a'); + for (i = 0; i < mtd->line_size; i++) { + if (*key == mtd->line_list[i].item->key) { + choice = i; + break; + } } if (choice != -1) { if ((u_int)choice > mtd->line_size - 1) { @@ -1176,7 +1204,7 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs, if (status == CMD_PARSE_ERROR) { if (c != NULL) { *error = toupper((u_char)*error); - status_message_set(c, -1, 1, "%s", error); + status_message_set(c, -1, 1, 0, "%s", error); } free(error); } @@ -125,6 +125,8 @@ notify_callback(struct cmdq_item *item, void *data) control_notify_window_renamed(ne->window); if (strcmp(ne->name, "client-session-changed") == 0) control_notify_client_session_changed(ne->client); + if (strcmp(ne->name, "client-detached") == 0) + control_notify_client_detached(ne->client); if (strcmp(ne->name, "session-renamed") == 0) control_notify_session_renamed(ne->session); if (strcmp(ne->name, "session-created") == 0) @@ -153,8 +153,10 @@ screen_reset_tabs(struct screen *s) void screen_set_cursor_style(struct screen *s, u_int style) { - if (style <= 6) + if (style <= 6) { s->cstyle = style; + s->mode &= ~MODE_BLINKING; + } } /* Set screen cursor colour. */ diff --git a/server-client.c b/server-client.c index 96e1b584..d3ffd682 100644 --- a/server-client.c +++ b/server-client.c @@ -296,6 +296,9 @@ server_client_lost(struct client *c) TAILQ_REMOVE(&clients, c, entry); log_debug("lost client %p", c); + if (c->flags & CLIENT_ATTACHED) + notify_client("client-detached", c); + if (c->flags & CLIENT_CONTROL) control_stop(c); if (c->flags & CLIENT_TERMINAL) @@ -1305,7 +1308,11 @@ server_client_handle_key(struct client *c, struct key_event *event) * immediately rather than queued. */ if (~c->flags & CLIENT_READONLY) { - status_message_clear(c); + if (c->message_string != NULL) { + if (c->message_ignore_keys) + return (0); + status_message_clear(c); + } if (c->overlay_key != NULL) { switch (c->overlay_key(c, event)) { case 0: @@ -1766,9 +1773,6 @@ server_client_check_exit(struct client *c) if (EVBUFFER_LENGTH(cf->buffer) != 0) return; } - - if (c->flags & CLIENT_ATTACHED) - notify_client("client-detached", c); c->flags |= CLIENT_EXITED; switch (c->exit_type) { @@ -424,7 +424,7 @@ status_redraw(struct client *c) /* Set a status line message. */ void status_message_set(struct client *c, int delay, int ignore_styles, - const char *fmt, ...) + int ignore_keys, const char *fmt, ...) { struct timeval tv; va_list ap; @@ -433,7 +433,6 @@ status_message_set(struct client *c, int delay, int ignore_styles, status_push_screen(c); va_start(ap, fmt); - c->message_ignore_styles = ignore_styles; xvasprintf(&c->message_string, fmt, ap); va_end(ap); @@ -456,6 +455,10 @@ status_message_set(struct client *c, int delay, int ignore_styles, evtimer_add(&c->message_timer, &tv); } + if (delay != 0) + c->message_ignore_keys = ignore_keys; + c->message_ignore_styles = ignore_styles; + c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE); c->flags |= CLIENT_REDRAWSTATUS; } @@ -1985,12 +1985,17 @@ The default is to capture only the visible contents of the pane. .Op Fl NrZ .Op Fl F Ar format .Op Fl f Ar filter +.Op Fl K Ar key-format .Op Fl O |