diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 9c0015bf..bdb8245e 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = { .name = "copy-mode", .alias = NULL, - .args = { "eHMt:u", 0, 0 }, - .usage = "[-eHMu] " CMD_TARGET_PANE_USAGE, + .args = { "eHMt:uq", 0, 0 }, + .usage = "[-eHMuq] " CMD_TARGET_PANE_USAGE, .target = { 't', CMD_FIND_PANE, 0 }, @@ -61,6 +61,11 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) struct session *s; struct window_pane *wp = item->target.wp; + if (args_has(args, 'q')) { + window_pane_reset_mode_all(wp); + return (CMD_RETURN_NORMAL); + } + if (args_has(args, 'M')) { if ((wp = cmd_mouse_pane(&shared->mouse, &s, NULL)) == NULL) return (CMD_RETURN_NORMAL); diff --git a/format.c b/format.c index b6ac8dd5..b102d9eb 100644 --- a/format.c +++ b/format.c @@ -963,7 +963,6 @@ format_grid_word(struct grid *gd, u_int x, u_int y) ws = options_get_string(global_s_options, "word-separators"); - y = gd->hsize + y; for (;;) { grid_get_cell(gd, x, y, &gc); if (gc.flags & GRID_FLAG_PADDING) @@ -1024,6 +1023,7 @@ static void format_cb_mouse_word(struct format_tree *ft, struct format_entry *fe) { struct window_pane *wp; + struct grid *gd; u_int x, y; char *s; @@ -1032,12 +1032,19 @@ format_cb_mouse_word(struct format_tree *ft, struct format_entry *fe) wp = cmd_mouse_pane(&ft->m, NULL, NULL); if (wp == NULL) return; - if (!TAILQ_EMPTY (&wp->modes)) - return; if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0) return; - s = format_grid_word(wp->base.grid, x, y); + if (!TAILQ_EMPTY(&wp->modes)) { + if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode || + TAILQ_FIRST(&wp->modes)->mode == &window_view_mode) + s = window_copy_get_word(wp, x, y); + else + s = NULL; + } else { + gd = wp->base.grid; + s = format_grid_word(gd, x, gd->hsize + y); + } if (s != NULL) fe->value = s; } @@ -1052,7 +1059,6 @@ format_grid_line(struct grid *gd, u_int y) size_t size = 0; char *s = NULL; - y = gd->hsize + y; for (x = 0; x < grid_line_length(gd, y); x++) { grid_get_cell(gd, x, y, &gc); if (gc.flags & GRID_FLAG_PADDING) @@ -1074,6 +1080,7 @@ static void format_cb_mouse_line(struct format_tree *ft, struct format_entry *fe) { struct window_pane *wp; + struct grid *gd; u_int x, y; char *s; @@ -1082,12 +1089,19 @@ format_cb_mouse_line(struct format_tree *ft, struct format_entry *fe) wp = cmd_mouse_pane(&ft->m, NULL, NULL); if (wp == NULL) return; - if (!TAILQ_EMPTY (&wp->modes)) - return; if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0) return; - s = format_grid_line(wp->base.grid, y); + if (!TAILQ_EMPTY(&wp->modes)) { + if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode || + TAILQ_FIRST(&wp->modes)->mode == &window_view_mode) + s = window_copy_get_line(wp, y); + else + s = NULL; + } else { + gd = wp->base.grid; + s = format_grid_line(gd, gd->hsize + y); + } if (s != NULL) fe->value = s; } diff --git a/key-bindings.c b/key-bindings.c index 57b71c0f..a528a6c0 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -34,8 +34,8 @@ " 'New Session' 's' {new-session}" \ " 'New Window' 'w' {new-window}" #define DEFAULT_WINDOW_MENU \ - " 'Swap Left' 'l' {swap-window -t:-1}" \ - " 'Swap Right' 'r' {swap-window -t:+1}" \ + " '#{?#{>:#{session_windows},1},,-}Swap Left' 'l' {swap-window -t:-1}" \ + " '#{?#{>:#{session_windows},1},,-}Swap Right' 'r' {swap-window -t:+1}" \ " '#{?pane_marked_set,,-}Swap Marked' 's' {swap-window}" \ " ''" \ " 'Kill' 'X' {kill-window}" \ @@ -46,22 +46,25 @@ " 'New After' 'w' {new-window -a}" \ " 'New At End' 'W' {new-window}" #define DEFAULT_PANE_MENU \ - " '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {copy-mode -t=; send -Xt= search-backward \"#{q:mouse_word}\"}" \ - " '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {send-keys -l -- \"#{q:mouse_word}\"}" \ - " '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {set-buffer -- \"#{q:mouse_word}\"}" \ - " '#{?mouse_line,Copy Line,}' 'l' {set-buffer -- \"#{q:mouse_line}\"}" \ + " '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Top,}' '<' {send -X history-top}" \ + " '#{?#{m/r:(copy|view)-mode,#{pane_mode}},Go To Bottom,}' '>' {send -X history-bottom}" \ + " ''" \ + " '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {if -F '#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}' 'copy-mode -t='; send -Xt= search-backward \"#{q:mouse_word}\"}" \ + " '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {copy-mode -q; send-keys -l -- \"#{q:mouse_word}\"}" \ + " '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {copy-mode -q; set-buffer -- \"#{q:mouse_word}\"}" \ + " '#{?mouse_line,Copy Line,}' 'l' {copy-mode -q; set-buffer -- \"#{q:mouse_line}\"}" \ " ''" \ " 'Horizontal Split' 'h' {split-window -h}" \ " 'Vertical Split' 'v' {split-window -v}" \ " ''" \ - " 'Swap Up' 'u' {swap-pane -U}" \ - " 'Swap Down' 'd' {swap-pane -D}" \ + " '#{?#{>:#{window_panes},1},,-}Swap Up' 'u' {swap-pane -U}" \ + " '#{?#{>:#{window_panes},1},,-}Swap Down' 'd' {swap-pane -D}" \ " '#{?pane_marked_set,,-}Swap Marked' 's' {swap-pane}" \ " ''" \ " 'Kill' 'X' {kill-pane}" \ " 'Respawn' 'R' {respawn-pane -k}" \ " '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \ - " '#{?window_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}" + " '#{?#{>:#{window_panes},1},,-}#{?window_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}" static int key_bindings_cmp(struct key_binding *, struct key_binding *); RB_GENERATE_STATIC(key_bindings, key_binding, entry, key_bindings_cmp); @@ -354,7 +357,7 @@ key_bindings_init(void) "bind -n MouseDown3Status display-menu -t= -xW -yS -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU, /* Mouse button 3 down on pane. */ - "bind -n MouseDown3Pane if -Ft= '#{||:#{mouse_any_flag},#{pane_in_mode}}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", + "bind -n MouseDown3Pane if -Ft= '#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", "bind -n M-MouseDown3Pane display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU, /* Copy mode (emacs) keys. */ diff --git a/tmux.1 b/tmux.1 index c2fbad08..505fdf4c 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1565,7 +1565,7 @@ The synopsis for the command is: .Bl -tag -width Ds .It Xo Ic copy-mode -.Op Fl eHMu +.Op Fl eHMqu .Op Fl t Ar target-pane .Xc Enter copy mode. @@ -1577,6 +1577,8 @@ begins a mouse drag (only valid if bound to a mouse key binding, see .Sx MOUSE SUPPORT ) . .Fl H hides the position indicator in the top right. +.Fl q +cancels copy mode and any other modes. .Pp .Fl e specifies that scrolling to the bottom of the history (to the visible screen) diff --git a/tmux.h b/tmux.h index 4a3a6c3d..b9817c24 100644 --- a/tmux.h +++ b/tmux.h @@ -2638,6 +2638,8 @@ void printflike(2, 3) window_copy_add(struct window_pane *, const char *, ...); void window_copy_vadd(struct window_pane *, const char *, va_list); void window_copy_pageup(struct window_pane *, int); void window_copy_start_drag(struct client *, struct mouse_event *); +char *window_copy_get_word(struct window_pane *, u_int, u_int); +char *window_copy_get_line(struct window_pane *, u_int); /* names.c */ void check_window_name(struct window *); diff --git a/window-copy.c b/window-copy.c index c6d3612f..9fe4fcef 100644 --- a/window-copy.c +++ b/window-copy.c @@ -596,10 +596,31 @@ window_copy_next_paragraph(struct window_mode_entry *wme) window_copy_scroll_to(wme, ox, oy); } +char * +window_copy_get_word(struct window_pane *wp, u_int x, u_int y) +{ + struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); + struct window_copy_mode_data *data = wme->data; + struct grid *gd = data->screen.grid; + + return (format_grid_word(gd, x, gd->hsize + y)); +} + +char * +window_copy_get_line(struct window_pane *wp, u_int y) +{ + struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); + struct window_copy_mode_data *data = wme->data; + struct grid *gd = data->screen.grid; + + return (format_grid_line(gd, gd->hsize + y)); +} + static void window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft) { struct window_copy_mode_data *data = wme->data; + struct grid *gd = data->screen.grid; char *s; format_add(ft, "scroll_position", "%d", data->oy); @@ -619,13 +640,13 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft) } else format_add(ft, "selection_active", "%d", 0); - s = format_grid_word(data->screen.grid, data->cx, data->cy); + s = format_grid_word(gd, data->cx, gd->hsize + data->cy); if (s != NULL) { format_add(ft, "copy_cursor_word", "%s", s); free(s); } - s = format_grid_line(data->screen.grid, data->cy); + s = format_grid_line(gd, gd->hsize + data->cy); if (s != NULL) { format_add(ft, "copy_cursor_line", "%s", s); free(s);