diff --git a/cmd-display-message.c b/cmd-display-message.c index 7828f694..f5e91020 100644 --- a/cmd-display-message.c +++ b/cmd-display-message.c @@ -39,8 +39,8 @@ const struct cmd_entry cmd_display_message_entry = { .name = "display-message", .alias = "display", - .args = { "ac:d:INpt:F:v", 0, 1, NULL }, - .usage = "[-aINpv] [-c target-client] [-d delay] [-F format] " + .args = { "ac:d:lINpt:F:v", 0, 1, NULL }, + .usage = "[-aIlNpv] [-c target-client] [-d delay] [-F format] " CMD_TARGET_PANE_USAGE " [message]", .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, @@ -132,7 +132,11 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - msg = format_expand_time(ft, template); + if (args_has(args, 'l')) + msg = xstrdup(template); + else + msg = format_expand_time(ft, template); + if (cmdq_get_client(item) == NULL) cmdq_error(item, "%s", msg); else if (args_has(args, 'p')) diff --git a/cmd-find.c b/cmd-find.c index e98090d2..154cadac 100644 --- a/cmd-find.c +++ b/cmd-find.c @@ -587,22 +587,22 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane) return (-1); return (0); } else if (strcmp(pane, "{up-of}") == 0) { - fs->wp = window_pane_find_up(fs->current->wp); + fs->wp = window_pane_find_up(fs->w->active); if (fs->wp == NULL) return (-1); return (0); } else if (strcmp(pane, "{down-of}") == 0) { - fs->wp = window_pane_find_down(fs->current->wp); + fs->wp = window_pane_find_down(fs->w->active); if (fs->wp == NULL) return (-1); return (0); } else if (strcmp(pane, "{left-of}") == 0) { - fs->wp = window_pane_find_left(fs->current->wp); + fs->wp = window_pane_find_left(fs->w->active); if (fs->wp == NULL) return (-1); return (0); } else if (strcmp(pane, "{right-of}") == 0) { - fs->wp = window_pane_find_right(fs->current->wp); + fs->wp = window_pane_find_right(fs->w->active); if (fs->wp == NULL) return (-1); return (0); @@ -614,7 +614,7 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane) n = strtonum(pane + 1, 1, INT_MAX, NULL); else n = 1; - wp = fs->current->wp; + wp = fs->w->active; if (pane[0] == '+') fs->wp = window_pane_next_by_number(fs->w, wp, n); else diff --git a/control-notify.c b/control-notify.c index a252dd05..30f94194 100644 --- a/control-notify.c +++ b/control-notify.c @@ -244,6 +244,19 @@ control_notify_paste_buffer_changed(const char *name) if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) continue; - control_write(c, "%%paste-changed %s", name); + control_write(c, "%%paste-buffer-changed %s", name); + } +} + +void +control_notify_paste_buffer_deleted(const char *name) +{ + struct client *c; + + TAILQ_FOREACH(c, &clients, entry) { + if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) + continue; + + control_write(c, "%%paste-buffer-deleted %s", name); } } diff --git a/format.c b/format.c index 8041f728..ee6930b0 100644 --- a/format.c +++ b/format.c @@ -3575,7 +3575,32 @@ found: return (found); } -/* Remove escaped characters from string. */ +/* Unescape escaped characters. */ +static char * +format_unescape(const char *s) +{ + char *out, *cp; + int brackets = 0; + + cp = out = xmalloc(strlen(s) + 1); + for (; *s != '\0'; s++) { + if (*s == '#' && s[1] == '{') + brackets++; + if (brackets == 0 && + *s == '#' && + strchr(",#{}:", s[1]) != NULL) { + *cp++ = *++s; + continue; + } + if (*s == '}') + brackets--; + *cp++ = *s; + } + *cp = '\0'; + return (out); +} + +/* Remove escaped characters. */ static char * format_strip(const char *s) { @@ -4338,7 +4363,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, /* Is this a literal string? */ if (modifiers & FORMAT_LITERAL) { - value = xstrdup(copy); + format_log(es, "literal string is '%s'", copy); + value = format_unescape(copy); goto done; } diff --git a/input-keys.c b/input-keys.c index ebf61333..208eb360 100644 --- a/input-keys.c +++ b/input-keys.c @@ -306,6 +306,20 @@ static struct input_key_entry input_key_defaults[] = { }, { .key = KEYC_DC|KEYC_BUILD_MODIFIERS, .data = "\033[3;_~" + }, + + /* Tab and modifiers. */ + { .key = '\011'|KEYC_CTRL, + .data = "\011" + }, + { .key = '\011'|KEYC_CTRL|KEYC_EXTENDED, + .data = "\033[9;5u" + }, + { .key = '\011'|KEYC_CTRL|KEYC_SHIFT, + .data = "\011" + }, + { .key = '\011'|KEYC_CTRL|KEYC_SHIFT|KEYC_EXTENDED, + .data = "\033[1;5Z" } }; static const key_code input_key_modifiers[] = { @@ -416,7 +430,7 @@ input_key_write(const char *from, struct bufferevent *bev, const char *data, int input_key(struct screen *s, struct bufferevent *bev, key_code key) { - struct input_key_entry *ike; + struct input_key_entry *ike = NULL; key_code justkey, newkey, outkey, modifiers; struct utf8_data ud; char tmp[64], modifier; @@ -468,13 +482,18 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key) key &= ~KEYC_KEYPAD; if (~s->mode & MODE_KCURSOR) key &= ~KEYC_CURSOR; - ike = input_key_get(key); + if (s->mode & MODE_KEXTENDED) + ike = input_key_get(key|KEYC_EXTENDED); + if (ike == NULL) + ike = input_key_get(key); if (ike == NULL && (key & KEYC_META) && (~key & KEYC_IMPLIED_META)) ike = input_key_get(key & ~KEYC_META); if (ike == NULL && (key & KEYC_CURSOR)) ike = input_key_get(key & ~KEYC_CURSOR); if (ike == NULL && (key & KEYC_KEYPAD)) ike = input_key_get(key & ~KEYC_KEYPAD); + if (ike == NULL && (key & KEYC_EXTENDED)) + ike = input_key_get(key & ~KEYC_EXTENDED); if (ike != NULL) { log_debug("found key 0x%llx: \"%s\"", key, ike->data); if ((key & KEYC_META) && (~key & KEYC_IMPLIED_META)) diff --git a/input.c b/input.c index 174bf76d..419c2456 100644 --- a/input.c +++ b/input.c @@ -1755,7 +1755,6 @@ static void input_csi_dispatch_sm_private(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; - struct window_pane *wp = ictx->wp; struct grid_cell *gc = &ictx->cell.cell; u_int i; @@ -1797,17 +1796,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_MOUSE_ALL); break; case 1004: - if (sctx->s->mode & MODE_FOCUSON) - break; screen_write_mode_set(sctx, MODE_FOCUSON); - if (wp == NULL) - break; - if (!options_get_number(global_options, "focus-events")) - break; - if (wp->flags & PANE_FOCUSED) - bufferevent_write(wp->event, "\033[I", 3); - else - bufferevent_write(wp->event, "\033[O", 3); break; case 1005: screen_write_mode_set(sctx, MODE_MOUSE_UTF8); diff --git a/key-string.c b/key-string.c index 0ca91306..086c3ac4 100644 --- a/key-string.c +++ b/key-string.c @@ -460,6 +460,8 @@ out: strlcat(out, "I", sizeof out); if (saved & KEYC_BUILD_MODIFIERS) strlcat(out, "B", sizeof out); + if (saved & KEYC_EXTENDED) + strlcat(out, "E", sizeof out); strlcat(out, "]", sizeof out); } return (out); diff --git a/notify.c b/notify.c index dd20898c..97919487 100644 --- a/notify.c +++ b/notify.c @@ -152,6 +152,8 @@ notify_callback(struct cmdq_item *item, void *data) control_notify_session_window_changed(ne->session); if (strcmp(ne->name, "paste-buffer-changed") == 0) control_notify_paste_buffer_changed(ne->pbname); + if (strcmp(ne->name, "paste-buffer-deleted") == 0) + control_notify_paste_buffer_deleted(ne->pbname); notify_insert_hook(item, ne); @@ -306,10 +308,16 @@ notify_pane(const char *name, struct window_pane *wp) } void -notify_paste_buffer(const char *pbname) +notify_paste_buffer(const char *pbname, int deleted) { struct cmd_find_state fs; cmd_find_clear_state(&fs, 0); - notify_add("paste-buffer-changed", &fs, NULL, NULL, NULL, NULL, pbname); + if (deleted) { + notify_add("paste-buffer-deleted", &fs, NULL, NULL, NULL, NULL, + pbname); + } else { + notify_add("paste-buffer-changed", &fs, NULL, NULL, NULL, NULL, + pbname); + } } diff --git a/paste.c b/paste.c index 51c6b751..84cdecb0 100644 --- a/paste.c +++ b/paste.c @@ -150,7 +150,7 @@ paste_get_name(const char *name) void paste_free(struct paste_buffer *pb) { - notify_paste_buffer(pb->name); + notify_paste_buffer(pb->name, 1); RB_REMOVE(paste_name_tree, &paste_by_name, pb); RB_REMOVE(paste_time_tree, &paste_by_time, pb); @@ -209,7 +209,7 @@ paste_add(const char *prefix, char *data, size_t size) RB_INSERT(paste_name_tree, &paste_by_name, pb); RB_INSERT(paste_time_tree, &paste_by_time, pb); - notify_paste_buffer(pb->name); + notify_paste_buffer(pb->name, 0); } /* Rename a paste buffer. */ @@ -257,8 +257,8 @@ paste_rename(const char *oldname, const char *newname, char **cause) RB_INSERT(paste_name_tree, &paste_by_name, pb); - notify_paste_buffer(oldname); - notify_paste_buffer(newname); + notify_paste_buffer(oldname, 1); + notify_paste_buffer(newname, 0); return (0); } @@ -308,7 +308,7 @@ paste_set(char *data, size_t size, const char *name, char **cause) RB_INSERT(paste_name_tree, &paste_by_name, pb); RB_INSERT(paste_time_tree, &paste_by_time, pb); - notify_paste_buffer(name); + notify_paste_buffer(name, 0); return (0); } @@ -321,7 +321,7 @@ paste_replace(struct paste_buffer *pb, char *data, size_t size) pb->data = data; pb->size = size; - notify_paste_buffer(pb->name); + notify_paste_buffer(pb->name, 0); } /* Convert start of buffer into a nice string. */ diff --git a/tmux.1 b/tmux.1 index d61324fc..3e12b0a5 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5890,7 +5890,7 @@ The following keys are also available: .El .Tg display .It Xo Ic display-message -.Op Fl aINpv +.Op Fl aIlNpv .Op Fl c Ar target-client .Op Fl d Ar delay .Op Fl t Ar target-pane @@ -5912,7 +5912,12 @@ is not given, the option is used; a delay of zero waits for a key press. .Ql N ignores key presses and closes only after the delay expires. -The format of +If +.Fl l +is given, +.Ar message +is printed unchanged. +Otherwise, the format of .Ar message is described in the .Sx FORMATS @@ -6617,6 +6622,10 @@ has changed mode. Paste buffer .Ar name has been changed. +.It Ic %paste-buffer-deleted Ar name +Paste buffer +.Ar name +has been deleted. .It Ic %pause Ar pane-id The pane has been paused (if the .Ar pause-after diff --git a/tmux.h b/tmux.h index e205bcfa..41958938 100644 --- a/tmux.h +++ b/tmux.h @@ -139,6 +139,7 @@ struct winlink; #define KEYC_IMPLIED_META 0x08000000000000ULL #define KEYC_BUILD_MODIFIERS 0x10000000000000ULL #define KEYC_VI 0x20000000000000ULL +#define KEYC_EXTENDED 0x40000000000000ULL /* Masks for key bits. */ #define KEYC_MASK_MODIFIERS 0x00f00000000000ULL @@ -2184,7 +2185,7 @@ void notify_winlink(const char *, struct winlink *); void notify_session_window(const char *, struct session *, struct window *); void notify_window(const char *, struct window *); void notify_pane(const char *, struct window_pane *); -void notify_paste_buffer(const char *); +void notify_paste_buffer(const char *, int); /* options.c */ struct options *options_create(struct options *); @@ -3211,6 +3212,7 @@ void control_notify_session_created(struct session *); void control_notify_session_closed(struct session *); void control_notify_session_window_changed(struct session *); void control_notify_paste_buffer_changed(const char *); +void control_notify_paste_buffer_deleted(const char *); /* session.c */ extern struct sessions sessions; diff --git a/tty-keys.c b/tty-keys.c index 1e8cd99c..9e6f4134 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -208,6 +208,9 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = { /* Paste keys. */ { "\033[200~", KEYC_PASTE_START }, { "\033[201~", KEYC_PASTE_END }, + + /* Extended keys. */ + { "\033[1;5Z", '\011'|KEYC_CTRL|KEYC_SHIFT }, }; /* Default xterm keys. */ diff --git a/window-buffer.c b/window-buffer.c index 2f52ee3f..2e0a9e84 100644 --- a/window-buffer.c +++ b/window-buffer.c @@ -508,6 +508,11 @@ window_buffer_key(struct window_mode_entry *wme, struct client *c, struct window_buffer_itemdata *item; int finished; + if (paste_get_top(NULL) == NULL) { + finished = 1; + goto out; + } + finished = mode_tree_key(mtd, c, &key, m, NULL, NULL); switch (key) { case 'e': @@ -534,6 +539,8 @@ window_buffer_key(struct window_mode_entry *wme, struct client *c, finished = 1; break; } + +out: if (finished || paste_get_top(NULL) == NULL) window_pane_reset_mode(wp); else {