Add a mark in copy mode. Set with set-mark command (bound to 'X') by default

and the mark and cursor position are swapped with 'jump-to-mark' (bound to
M-x). The line containing the mark is shown in copy-mode-mark-style with the
horizontal position in reverse.

From Anindya Mukherjee in GitHub issue 2209.
This commit is contained in:
Nicholas Marriott 2020-05-13 06:29:57 +01:00
parent 9d44df9da9
commit 6214cd0726
4 changed files with 121 additions and 9 deletions

View File

@ -426,6 +426,7 @@ key_bindings_init(void)
"bind -Tcopy-mode N send -X search-reverse", "bind -Tcopy-mode N send -X search-reverse",
"bind -Tcopy-mode R send -X rectangle-toggle", "bind -Tcopy-mode R send -X rectangle-toggle",
"bind -Tcopy-mode T command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"'", "bind -Tcopy-mode T command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"'",
"bind -Tcopy-mode X send -X set-mark",
"bind -Tcopy-mode f command-prompt -1p'(jump forward)' 'send -X jump-forward \"%%%\"'", "bind -Tcopy-mode f command-prompt -1p'(jump forward)' 'send -X jump-forward \"%%%\"'",
"bind -Tcopy-mode g command-prompt -p'(goto line)' 'send -X goto-line \"%%%\"'", "bind -Tcopy-mode g command-prompt -p'(goto line)' 'send -X goto-line \"%%%\"'",
"bind -Tcopy-mode n send -X search-again", "bind -Tcopy-mode n send -X search-again",
@ -467,6 +468,7 @@ key_bindings_init(void)
"bind -Tcopy-mode M-r send -X middle-line", "bind -Tcopy-mode M-r send -X middle-line",
"bind -Tcopy-mode M-v send -X page-up", "bind -Tcopy-mode M-v send -X page-up",
"bind -Tcopy-mode M-w send -X copy-pipe-and-cancel", "bind -Tcopy-mode M-w send -X copy-pipe-and-cancel",
"bind -Tcopy-mode M-x send -X jump-to-mark",
"bind -Tcopy-mode 'M-{' send -X previous-paragraph", "bind -Tcopy-mode 'M-{' send -X previous-paragraph",
"bind -Tcopy-mode 'M-}' send -X next-paragraph", "bind -Tcopy-mode 'M-}' send -X next-paragraph",
"bind -Tcopy-mode M-Up send -X halfpage-up", "bind -Tcopy-mode M-Up send -X halfpage-up",
@ -521,6 +523,7 @@ key_bindings_init(void)
"bind -Tcopy-mode-vi T command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"'", "bind -Tcopy-mode-vi T command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"'",
"bind -Tcopy-mode-vi V send -X select-line", "bind -Tcopy-mode-vi V send -X select-line",
"bind -Tcopy-mode-vi W send -X next-space", "bind -Tcopy-mode-vi W send -X next-space",
"bind -Tcopy-mode-vi X send -X set-mark",
"bind -Tcopy-mode-vi ^ send -X back-to-indentation", "bind -Tcopy-mode-vi ^ send -X back-to-indentation",
"bind -Tcopy-mode-vi b send -X previous-word", "bind -Tcopy-mode-vi b send -X previous-word",
"bind -Tcopy-mode-vi e send -X next-word-end", "bind -Tcopy-mode-vi e send -X next-word-end",
@ -554,6 +557,7 @@ key_bindings_init(void)
"bind -Tcopy-mode-vi Down send -X cursor-down", "bind -Tcopy-mode-vi Down send -X cursor-down",
"bind -Tcopy-mode-vi Left send -X cursor-left", "bind -Tcopy-mode-vi Left send -X cursor-left",
"bind -Tcopy-mode-vi Right send -X cursor-right", "bind -Tcopy-mode-vi Right send -X cursor-right",
"bind -Tcopy-mode-vi M-x send -X jump-to-mark",
"bind -Tcopy-mode-vi C-Up send -X scroll-up", "bind -Tcopy-mode-vi C-Up send -X scroll-up",
"bind -Tcopy-mode-vi C-Down send -X scroll-down", "bind -Tcopy-mode-vi C-Down send -X scroll-down",
}; };

View File

@ -794,6 +794,15 @@ const struct options_table_entry options_table[] = {
.text = "Style of the current search match in copy mode." .text = "Style of the current search match in copy mode."
}, },
{ .name = "copy-mode-mark-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "bg=red,fg=black",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of the marked line in copy mode."
},
{ .name = "main-pane-height", { .name = "main-pane-height",
.type = OPTIONS_TABLE_STRING, .type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW, .scope = OPTIONS_TABLE_WINDOW,

10
tmux.1
View File

@ -1555,6 +1555,7 @@ The following commands are supported in copy mode:
.It Li "jump-reverse" Ta "," Ta "," .It Li "jump-reverse" Ta "," Ta ","
.It Li "jump-to-backward <to>" Ta "T" Ta "" .It Li "jump-to-backward <to>" Ta "T" Ta ""
.It Li "jump-to-forward <to>" Ta "t" Ta "" .It Li "jump-to-forward <to>" Ta "t" Ta ""
.It Li "jump-to-mark" Ta "M-x" Ta "M-x"
.It Li "middle-line" Ta "M" Ta "M-r" .It Li "middle-line" Ta "M" Ta "M-r"
.It Li "next-matching-bracket" Ta "%" Ta "M-C-f" .It Li "next-matching-bracket" Ta "%" Ta "M-C-f"
.It Li "next-paragraph" Ta "}" Ta "M-}" .It Li "next-paragraph" Ta "}" Ta "M-}"
@ -1585,6 +1586,7 @@ The following commands are supported in copy mode:
.It Li "search-reverse" Ta "N" Ta "N" .It Li "search-reverse" Ta "N" Ta "N"
.It Li "select-line" Ta "V" Ta "" .It Li "select-line" Ta "V" Ta ""
.It Li "select-word" Ta "" Ta "" .It Li "select-word" Ta "" Ta ""
.It Li "set-mark" Ta "X" Ta "X"
.It Li "start-of-line" Ta "0" Ta "C-a" .It Li "start-of-line" Ta "0" Ta "C-a"
.It Li "stop-selection" Ta "" Ta "" .It Li "stop-selection" Ta "" Ta ""
.It Li "top-line" Ta "H" Ta "M-R" .It Li "top-line" Ta "H" Ta "M-R"
@ -3817,6 +3819,14 @@ see the
.Sx STYLES .Sx STYLES
section. section.
.Pp .Pp
.It Ic copy-mode-mark-style Ar style
Set the style of the line containing the mark in copy mode.
For how to specify
.Ar style ,
see the
.Sx STYLES
section.
.Pp
.It Ic copy-mode-current-match-style Ar style .It Ic copy-mode-current-match-style Ar style
Set the style of the current search match in copy mode. Set the style of the current search match in copy mode.
For how to specify For how to specify

View File

@ -131,6 +131,7 @@ static void window_copy_rectangle_toggle(struct window_mode_entry *);
static void window_copy_move_mouse(struct mouse_event *); static void window_copy_move_mouse(struct mouse_event *);
static void window_copy_drag_update(struct client *, struct mouse_event *); static void window_copy_drag_update(struct client *, struct mouse_event *);
static void window_copy_drag_release(struct client *, struct mouse_event *); static void window_copy_drag_release(struct client *, struct mouse_event *);
static void window_copy_jump_to_mark(struct window_mode_entry *);
const struct window_mode window_copy_mode = { const struct window_mode window_copy_mode = {
.name = "copy-mode", .name = "copy-mode",
@ -254,6 +255,10 @@ struct window_copy_mode_data {
u_int lastcx; /* position in last line w/ content */ u_int lastcx; /* position in last line w/ content */
u_int lastsx; /* size of last line w/ content */ u_int lastsx; /* size of last line w/ content */
u_int mx; /* mark position */
u_int my;
int showmark;
int searchtype; int searchtype;
int searchregex; int searchregex;
char *searchstr; char *searchstr;
@ -424,6 +429,9 @@ window_copy_init(struct window_mode_entry *wme,
data->screen.cx = data->cx; data->screen.cx = data->cx;
data->screen.cy = data->cy; data->screen.cy = data->cy;
data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy;
data->showmark = 0;
screen_write_start(&ctx, &data->screen); screen_write_start(&ctx, &data->screen);
for (i = 0; i < screen_size_y(&data->screen); i++) for (i = 0; i < screen_size_y(&data->screen); i++)
@ -448,6 +456,9 @@ window_copy_view_init(struct window_mode_entry *wme,
data->backing = s = xmalloc(sizeof *data->backing); data->backing = s = xmalloc(sizeof *data->backing);
screen_init(s, screen_size_x(base), screen_size_y(base), UINT_MAX); screen_init(s, screen_size_x(base), screen_size_y(base), UINT_MAX);
data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy;
data->showmark = 0;
return (&data->screen); return (&data->screen);
} }
@ -1733,6 +1744,17 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_REDRAW); return (WINDOW_COPY_CMD_REDRAW);
} }
static enum window_copy_cmd_action
window_copy_cmd_set_mark(struct window_copy_cmd_state *cs)
{
struct window_copy_mode_data *data = cs->wme->data;
data->mx = data->cx;
data->my = screen_hsize(data->backing) + data->cy - data->oy;
data->showmark = 1;
return (WINDOW_COPY_CMD_REDRAW);
}
static enum window_copy_cmd_action static enum window_copy_cmd_action
window_copy_cmd_start_of_line(struct window_copy_cmd_state *cs) window_copy_cmd_start_of_line(struct window_copy_cmd_state *cs)
{ {
@ -1877,6 +1899,15 @@ window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs)
return (WINDOW_COPY_CMD_NOTHING); return (WINDOW_COPY_CMD_NOTHING);
} }
static enum window_copy_cmd_action
window_copy_cmd_jump_to_mark(struct window_copy_cmd_state *cs)
{
struct window_mode_entry *wme = cs->wme;
window_copy_jump_to_mark(wme);
return (WINDOW_COPY_CMD_NOTHING);
}
static enum window_copy_cmd_action static enum window_copy_cmd_action
window_copy_cmd_search_backward(struct window_copy_cmd_state *cs) window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
{ {
@ -2154,6 +2185,8 @@ static const struct {
window_copy_cmd_jump_to_backward }, window_copy_cmd_jump_to_backward },
{ "jump-to-forward", 1, 1, 1, { "jump-to-forward", 1, 1, 1,
window_copy_cmd_jump_to_forward }, window_copy_cmd_jump_to_forward },
{ "jump-to-mark", 0, 0, 0,
window_copy_cmd_jump_to_mark },
{ "middle-line", 0, 0, 1, { "middle-line", 0, 0, 1,
window_copy_cmd_middle_line }, window_copy_cmd_middle_line },
{ "next-matching-bracket", 0, 0, 0, { "next-matching-bracket", 0, 0, 0,
@ -2214,6 +2247,8 @@ static const struct {
window_copy_cmd_select_line }, window_copy_cmd_select_line },
{ "select-word", 0, 0, 0, { "select-word", 0, 0, 0,
window_copy_cmd_select_word }, window_copy_cmd_select_word },
{ "set-mark", 0, 0, 0,
window_copy_cmd_set_mark },
{ "start-of-line", 0, 0, 1, { "start-of-line", 0, 0, 1,
window_copy_cmd_start_of_line }, window_copy_cmd_start_of_line },
{ "stop-selection", 0, 0, 0, { "stop-selection", 0, 0, 0,
@ -3129,11 +3164,26 @@ window_copy_match_at_cursor(struct window_copy_mode_data *data)
static void static void
window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy, window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
struct grid_cell *gc, const struct grid_cell *mgc, struct grid_cell *gc, const struct grid_cell *mgc,
const struct grid_cell *cgc) const struct grid_cell *cgc, const struct grid_cell *mkgc)
{ {
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
u_int mark, start, end, cy, cursor, current; u_int mark, start, end, cy, cursor, current;
u_int sx = screen_size_x(data->backing); u_int sx = screen_size_x(data->backing);
int inv = 0;
if (data->showmark && fy == data->my) {
gc->attr = mkgc->attr;
if (fx == data->mx)
inv = 1;
if (inv) {
gc->fg = mkgc->bg;
gc->bg = mkgc->fg;
}
else {
gc->fg = mkgc->fg;
gc->bg = mkgc->bg;
}
}
if (data->searchmark == NULL) if (data->searchmark == NULL)
return; return;
@ -3150,21 +3200,34 @@ window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
window_copy_match_start_end(data, cursor, &start, &end); window_copy_match_start_end(data, cursor, &start, &end);
if (current >= start && current <= end) { if (current >= start && current <= end) {
gc->attr = cgc->attr; gc->attr = cgc->attr;
gc->fg = cgc->fg; if (inv) {
gc->bg = cgc->bg; gc->fg = cgc->bg;
gc->bg = cgc->fg;
}
else {
gc->fg = cgc->fg;
gc->bg = cgc->bg;
}
return; return;
} }
} }
gc->attr = mgc->attr; gc->attr = mgc->attr;
gc->fg = mgc->fg; if (inv) {
gc->bg = mgc->bg; gc->fg = mgc->bg;
gc->bg = mgc->fg;
}
else {
gc->fg = mgc->fg;
gc->bg = mgc->bg;
}
} }
static void static void
window_copy_write_one(struct window_mode_entry *wme, window_copy_write_one(struct window_mode_entry *wme,
struct screen_write_ctx *ctx, u_int py, u_int fy, u_int nx, struct screen_write_ctx *ctx, u_int py, u_int fy, u_int nx,
const struct grid_cell *mgc, const struct grid_cell *cgc) const struct grid_cell *mgc, const struct grid_cell *cgc,
const struct grid_cell *mkgc)
{ {
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
struct grid *gd = data->backing->grid; struct grid *gd = data->backing->grid;
@ -3175,7 +3238,8 @@ window_copy_write_one(struct window_mode_entry *wme,
for (fx = 0; fx < nx; fx++) { for (fx = 0; fx < nx; fx++) {
grid_get_cell(gd, fx, fy, &gc); grid_get_cell(gd, fx, fy, &gc);
if (fx + gc.data.width <= nx) { if (fx + gc.data.width <= nx) {
window_copy_update_style(wme, fx, fy, &gc, mgc, cgc); window_copy_update_style(wme, fx, fy, &gc, mgc, cgc,
mkgc);
screen_write_cell(ctx, &gc); screen_write_cell(ctx, &gc);
} }
} }
@ -3189,7 +3253,7 @@ window_copy_write_line(struct window_mode_entry *wme,
struct window_copy_mode_data *data = wme->data; struct window_copy_mode_data *data = wme->data;
struct screen *s = &data->screen; struct screen *s = &data->screen;
struct options *oo = wp->window->options; struct options *oo = wp->window->options;
struct grid_cell gc, mgc, cgc; struct grid_cell gc, mgc, cgc, mkgc;
char hdr[512]; char hdr[512];
size_t size = 0; size_t size = 0;
u_int hsize = screen_hsize(data->backing); u_int hsize = screen_hsize(data->backing);
@ -3200,6 +3264,8 @@ window_copy_write_line(struct window_mode_entry *wme,
mgc.flags |= GRID_FLAG_NOPALETTE; mgc.flags |= GRID_FLAG_NOPALETTE;
style_apply(&cgc, oo, "copy-mode-current-match-style", NULL); style_apply(&cgc, oo, "copy-mode-current-match-style", NULL);
cgc.flags |= GRID_FLAG_NOPALETTE; cgc.flags |= GRID_FLAG_NOPALETTE;
style_apply(&mkgc, oo, "copy-mode-mark-style", NULL);
mkgc.flags |= GRID_FLAG_NOPALETTE;
if (py == 0 && s->rupper < s->rlower && !data->hide_position) { if (py == 0 && s->rupper < s->rlower && !data->hide_position) {
if (data->searchmark == NULL) { if (data->searchmark == NULL) {
@ -3233,7 +3299,7 @@ window_copy_write_line(struct window_mode_entry *wme,
if (size < screen_size_x(s)) { if (size < screen_size_x(s)) {
window_copy_write_one(wme, ctx, py, hsize - data->oy + py, window_copy_write_one(wme, ctx, py, hsize - data->oy + py,
screen_size_x(s) - size, &mgc, &cgc); screen_size_x(s) - size, &mgc, &cgc, &mkgc);
} }
if (py == data->cy && data->cx == screen_size_x(s)) { if (py == data->cy && data->cx == screen_size_x(s)) {
@ -4687,3 +4753,26 @@ window_copy_drag_release(struct client *c, struct mouse_event *m)
data = wme->data; data = wme->data;
evtimer_del(&data->dragtimer); evtimer_del(&data->dragtimer);
} }
static void
window_copy_jump_to_mark(struct window_mode_entry *wme)
{
struct window_copy_mode_data *data = wme->data;
u_int tmx, tmy;
tmx = data->cx;
tmy = screen_hsize(data->backing) + data->cy - data->oy;
data->cx = data->mx;
if (data->my < screen_hsize(data->backing)) {
data->cy = 0;
data->oy = screen_hsize(data->backing) - data->my;
} else {
data->cy = data->my - screen_hsize(data->backing);
data->oy = 0;
}
data->mx = tmx;
data->my = tmy;
data->showmark = 1;
window_copy_update_selection(wme, 0, 0);
window_copy_redraw_screen(wme);
}