aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornicm <nicm>2020-05-16 16:10:28 +0000
committernicm <nicm>2020-05-16 16:10:28 +0000
commitff8dd150e0c59b37d9a4942e499a2a025820db8d (patch)
tree6bb50aa2be5983d21c8609ee58dacff1bca166fc
parentdceb6a15d04a2b2e050ab41816d0df3fe224b416 (diff)
downloadrtmux-ff8dd150e0c59b37d9a4942e499a2a025820db8d.tar.gz
rtmux-ff8dd150e0c59b37d9a4942e499a2a025820db8d.tar.bz2
rtmux-ff8dd150e0c59b37d9a4942e499a2a025820db8d.zip
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.
-rw-r--r--key-bindings.c4
-rw-r--r--options-table.c9
-rw-r--r--tmux.110
-rw-r--r--window-copy.c107
4 files changed, 121 insertions, 9 deletions
diff --git a/key-bindings.c b/key-bindings.c
index ecd2f7dc..05089bab 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -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",
};
diff --git a/options-table.c b/options-table.c
index 55eb5b9f..b1c4ec1b 100644
--- a/options-table.c
+++ b/options-table.c
@@ -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,
diff --git a/tmux.1 b/tmux.1
index 6c19283e..baa296fb 100644
--- a/tmux.1
+++ b/tmux.1
@@ -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
diff --git a/window-copy.c b/window-copy.c
index 95b4cc6e..e572eaa8 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -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);
}
@@ -1734,6 +1745,17 @@ window_copy_cmd_select_word(struct window_copy_cmd_state *cs)
}
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)
{
struct window_mode_entry *wme = cs->wme;
@@ -1878,6 +1900,15 @@ window_copy_cmd_jump_to_forward(struct window_copy_cmd_state *cs)
}
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)
{
struct window_mode_entry *wme = cs->wme;
@@ -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);
+}