mirror of
https://github.com/tmux/tmux.git
synced 2024-12-13 10:08:47 +00:00
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:
parent
9d44df9da9
commit
6214cd0726
@ -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",
|
||||||
};
|
};
|
||||||
|
@ -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
10
tmux.1
@ -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
|
||||||
|
@ -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;
|
||||||
|
if (inv) {
|
||||||
|
gc->fg = cgc->bg;
|
||||||
|
gc->bg = cgc->fg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
gc->fg = cgc->fg;
|
gc->fg = cgc->fg;
|
||||||
gc->bg = cgc->bg;
|
gc->bg = cgc->bg;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gc->attr = mgc->attr;
|
gc->attr = mgc->attr;
|
||||||
|
if (inv) {
|
||||||
|
gc->fg = mgc->bg;
|
||||||
|
gc->bg = mgc->fg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
gc->fg = mgc->fg;
|
gc->fg = mgc->fg;
|
||||||
gc->bg = mgc->bg;
|
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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user