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:
nicm 2020-05-16 16:10:28 +00:00
parent dceb6a15d0
commit ff8dd150e0
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 R send -X rectangle-toggle",
"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 g command-prompt -p'(goto line)' 'send -X goto-line \"%%%\"'",
"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-v send -X page-up",
"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 next-paragraph",
"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 V send -X select-line",
"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 b send -X previous-word",
"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 Left send -X cursor-left",
"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-Down send -X scroll-down",
};

View File

@ -795,6 +795,15 @@ const struct options_table_entry options_table[] = {
.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",
.type = OPTIONS_TABLE_STRING,
.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-to-backward <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 "next-matching-bracket" Ta "%" Ta "M-C-f"
.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 "select-line" Ta "V" 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 "stop-selection" Ta "" Ta ""
.It Li "top-line" Ta "H" Ta "M-R"
@ -3817,6 +3819,14 @@ see the
.Sx STYLES
section.
.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
Set the style of the current search match in copy mode.
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_drag_update(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 = {
.name = "copy-mode",
@ -254,6 +255,10 @@ struct window_copy_mode_data {
u_int lastcx; /* position in 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 searchregex;
char *searchstr;
@ -424,6 +429,9 @@ window_copy_init(struct window_mode_entry *wme,
data->screen.cx = data->cx;
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);
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);
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);
}
@ -1733,6 +1744,17 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
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
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);
}
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
window_copy_cmd_search_backward(struct window_copy_cmd_state *cs)
{
@ -2154,6 +2185,8 @@ static const struct {
window_copy_cmd_jump_to_backward },
{ "jump-to-forward", 1, 1, 1,
window_copy_cmd_jump_to_forward },
{ "jump-to-mark", 0, 0, 0,
window_copy_cmd_jump_to_mark },
{ "middle-line", 0, 0, 1,
window_copy_cmd_middle_line },
{ "next-matching-bracket", 0, 0, 0,
@ -2214,6 +2247,8 @@ static const struct {
window_copy_cmd_select_line },
{ "select-word", 0, 0, 0,
window_copy_cmd_select_word },
{ "set-mark", 0, 0, 0,
window_copy_cmd_set_mark },
{ "start-of-line", 0, 0, 1,
window_copy_cmd_start_of_line },
{ "stop-selection", 0, 0, 0,
@ -3129,11 +3164,26 @@ window_copy_match_at_cursor(struct window_copy_mode_data *data)
static void
window_copy_update_style(struct window_mode_entry *wme, u_int fx, u_int fy,
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;
u_int mark, start, end, cy, cursor, current;
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)
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);
if (current >= start && current <= end) {
gc->attr = cgc->attr;
gc->fg = cgc->fg;
gc->bg = cgc->bg;
if (inv) {
gc->fg = cgc->bg;
gc->bg = cgc->fg;
}
else {
gc->fg = cgc->fg;
gc->bg = cgc->bg;
}
return;
}
}
gc->attr = mgc->attr;
gc->fg = mgc->fg;
gc->bg = mgc->bg;
if (inv) {
gc->fg = mgc->bg;
gc->bg = mgc->fg;
}
else {
gc->fg = mgc->fg;
gc->bg = mgc->bg;
}
}
static void
window_copy_write_one(struct window_mode_entry *wme,
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 grid *gd = data->backing->grid;
@ -3175,7 +3238,8 @@ window_copy_write_one(struct window_mode_entry *wme,
for (fx = 0; fx < nx; fx++) {
grid_get_cell(gd, fx, fy, &gc);
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);
}
}
@ -3189,7 +3253,7 @@ window_copy_write_line(struct window_mode_entry *wme,
struct window_copy_mode_data *data = wme->data;
struct screen *s = &data->screen;
struct options *oo = wp->window->options;
struct grid_cell gc, mgc, cgc;
struct grid_cell gc, mgc, cgc, mkgc;
char hdr[512];
size_t size = 0;
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;
style_apply(&cgc, oo, "copy-mode-current-match-style", NULL);
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 (data->searchmark == NULL) {
@ -3233,7 +3299,7 @@ window_copy_write_line(struct window_mode_entry *wme,
if (size < screen_size_x(s)) {
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)) {
@ -4687,3 +4753,26 @@ window_copy_drag_release(struct client *c, struct mouse_event *m)
data = wme->data;
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);
}