There currently are a number of differences between tmux's jump commands
[fFtT,;] in copy mode and the behavior of the corresponding keys in vi:
1. The repeat count is not reset after a jump with [fFtT], but it is
reset after the `repeat movement' keys [;,]. For example, in tmux
`3fa;;' jumps to the seventh (3+3+1) occurrence of `a' whereas vi
would jump to the fifth (3+1+1).
2. The repeat count to [tT] has no effect: the cursor gets stuck in
front of the first match and the count is then decremented to zero
with no further movement. In vi, t and T are equivalent to f and F
plus one step back in the direction of the original cursor position.
3. If the repeat count for [fF] exceeds the number of matching
characters in the direction of the movement, the cursor is moved to
the last match. vi wouldn't move the cursor at all.
This patch does a number of things (the first two are cosmetic):
a. Rename WINDOW_COPY_JUMPFORWARD to WINDOW_COPY_JUMP in order to match
the corresponding MODEKEYCOPY_JUMP and window_copy_cursor_jump()
more closely. Similarly for WINDOW_COPY_JUMPTOFORWARD.
b. Replace a few if .. else if .. snakes by equivalent switch
statements.
c. Fix 1. by setting data->numprefix = -1 after a jump.
d. Take care of the repeat count inside the jump{,_back} routines to be
able to fix 3. without too much hassle. Use the same logic inside
window_copy_cursor_jump() and window_copy_cursor_jump_back().
e. Eliminate essentially duplicated code by handling the jump_to{,_back}
movements by combining jump{,_back} with cursor_{left,right}. To do
so, add a return value to jump{,_back} indicating success (cursor
movement). This fixes 2.
In case the current behavior in 3. should be desired in emacs mode, I
have an additional diff ready for that.
Index: window-copy.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window-copy.c,v
retrieving revision 1.120
diff -u -p -r1.120 window-copy.c
--- window-copy.c 9 Nov 2014 15:13:01 -0000 1.120
+++ window-copy.c 10 Nov 2014 11:14:42 -0000
@@ -73,8 +73,8 @@ void window_copy_cursor_left(struct wind
void window_copy_cursor_right(struct window_pane *);
void window_copy_cursor_up(struct window_pane *, int);
void window_copy_cursor_down(struct window_pane *, int);
-void window_copy_cursor_jump(struct window_pane *);
-void window_copy_cursor_jump_back(struct window_pane *);
+int window_copy_cursor_jump(struct window_pane *);
+int window_copy_cursor_jump_back(struct window_pane *);
void window_copy_cursor_jump_to(struct window_pane *);
void window_copy_cursor_jump_to_back(struct window_pane *);
void window_copy_cursor_next_word(struct window_pane *, const char *);
@@ -99,9 +99,9 @@ enum window_copy_input_type {
WINDOW_COPY_NUMERICPREFIX,
WINDOW_COPY_SEARCHUP,
WINDOW_COPY_SEARCHDOWN,
- WINDOW_COPY_JUMPFORWARD,
+ WINDOW_COPY_JUMP,
WINDOW_COPY_JUMPBACK,
- WINDOW_COPY_JUMPTOFORWARD,
+ WINDOW_COPY_JUMPTO,
WINDOW_COPY_JUMPTOBACK,
WINDOW_COPY_GOTOLINE,
};
@@ -375,46 +375,52 @@ window_copy_key(struct window_pane *wp,
enum mode_key_cmd cmd;
const char *arg, *ss;
- np = data->numprefix;
- if (np <= 0)
- np = 1;
-
- if (data->inputtype == WINDOW_COPY_JUMPFORWARD ||
- data->inputtype == WINDOW_COPY_JUMPBACK ||
- data->inputtype == WINDOW_COPY_JUMPTOFORWARD ||
- data->inputtype == WINDOW_COPY_JUMPTOBACK) {
+ switch (data->inputtype) {
+ case WINDOW_COPY_OFF:
+ break;
+ case WINDOW_COPY_JUMP:
+ case WINDOW_COPY_JUMPBACK:
+ case WINDOW_COPY_JUMPTO:
+ case WINDOW_COPY_JUMPTOBACK:
/* Ignore keys with modifiers. */
if ((key & KEYC_MASK_MOD) == 0) {
data->jumpchar = key;
- if (data->inputtype == WINDOW_COPY_JUMPFORWARD) {
- for (; np != 0; np--)
- window_copy_cursor_jump(wp);
- } else if (data->inputtype == WINDOW_COPY_JUMPBACK) {
- for (; np != 0; np--)
- window_copy_cursor_jump_back(wp);
- } else if (data->inputtype ==
WINDOW_COPY_JUMPTOFORWARD) {
- for (; np != 0; np--)
- window_copy_cursor_jump_to(wp);
- } else if (data->inputtype == WINDOW_COPY_JUMPTOBACK) {
- for (; np != 0; np--)
- window_copy_cursor_jump_to_back(wp);
+ switch (data->inputtype) {
+ case WINDOW_COPY_JUMP:
+ (void)window_copy_cursor_jump(wp);
+ break;
+ case WINDOW_COPY_JUMPBACK:
+ (void)window_copy_cursor_jump_back(wp);
+ break;
+ case WINDOW_COPY_JUMPTO:
+ window_copy_cursor_jump_to(wp);
+ break;
+ case WINDOW_COPY_JUMPTOBACK:
+ window_copy_cursor_jump_to_back(wp);
+ break;
}
}
data->jumptype = data->inputtype;
data->inputtype = WINDOW_COPY_OFF;
+ data->numprefix = -1;
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return;
- } else if (data->inputtype == WINDOW_COPY_NUMERICPREFIX) {
+ case WINDOW_COPY_NUMERICPREFIX:
if (window_copy_key_numeric_prefix(wp, key) == 0)
return;
data->inputtype = WINDOW_COPY_OFF;
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
- } else if (data->inputtype != WINDOW_COPY_OFF) {
+ break;
+ default:
if (window_copy_key_input(wp, key) != 0)
goto input_off;
return;
}
+ np = data->numprefix;
+ if (np <= 0)
+ np = 1;
+
cmd = mode_key_lookup(&data->mdata, key, &arg);
switch (cmd) {
case MODEKEYCOPY_APPENDSELECTION:
@@ -611,42 +617,44 @@ window_copy_key(struct window_pane *wp,
for (; np != 0; np--)
window_copy_cursor_previous_word(wp, word_separators);
break;
- case MODEKEYCOPY_JUMP:
- data->inputtype = WINDOW_COPY_JUMPFORWARD;
- data->inputprompt = "Jump Forward";
- *data->inputstr = '\0';
- window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
- return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPAGAIN:
- if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
- for (; np != 0; np--)
- window_copy_cursor_jump(wp);
- } else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
- for (; np != 0; np--)
- window_copy_cursor_jump_back(wp);
- } else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
- for (; np != 0; np--)
- window_copy_cursor_jump_to(wp);
- } else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
- for (; np != 0; np--)
- window_copy_cursor_jump_to_back(wp);
+ switch (data->jumptype) {
+ case WINDOW_COPY_JUMP:
+ (void)window_copy_cursor_jump(wp);
+ break;
+ case WINDOW_COPY_JUMPBACK:
+ (void)window_copy_cursor_jump_back(wp);
+ break;
+ case WINDOW_COPY_JUMPTO:
+ window_copy_cursor_jump_to(wp);
+ break;
+ case WINDOW_COPY_JUMPTOBACK:
+ window_copy_cursor_jump_to_back(wp);
+ break;
}
break;
case MODEKEYCOPY_JUMPREVERSE:
- if (data->jumptype == WINDOW_COPY_JUMPFORWARD) {
- for (; np != 0; np--)
- window_copy_cursor_jump_back(wp);
- } else if (data->jumptype == WINDOW_COPY_JUMPBACK) {
- for (; np != 0; np--)
- window_copy_cursor_jump(wp);
- } else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
- for (; np != 0; np--)
- window_copy_cursor_jump_to_back(wp);
- } else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
- for (; np != 0; np--)
- window_copy_cursor_jump_to(wp);
+ switch (data->jumptype) {
+ case WINDOW_COPY_JUMP:
+ (void)window_copy_cursor_jump_back(wp);
+ break;
+ case WINDOW_COPY_JUMPBACK:
+ (void)window_copy_cursor_jump(wp);
+ break;
+ case WINDOW_COPY_JUMPTO:
+ window_copy_cursor_jump_to_back(wp);
+ break;
+ case WINDOW_COPY_JUMPTOBACK:
+ window_copy_cursor_jump_to(wp);
+ break;
}
break;
+ case MODEKEYCOPY_JUMP:
+ data->inputtype = WINDOW_COPY_JUMP;
+ data->inputprompt = "Jump Forward";
+ *data->inputstr = '\0';
+ window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
+ return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPBACK:
data->inputtype = WINDOW_COPY_JUMPBACK;
data->inputprompt = "Jump Back";
@@ -654,7 +662,7 @@ window_copy_key(struct window_pane *wp,
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPTO:
- data->inputtype = WINDOW_COPY_JUMPTOFORWARD;
+ data->inputtype = WINDOW_COPY_JUMPTO;
data->inputprompt = "Jump To";
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
@@ -678,9 +686,9 @@ window_copy_key(struct window_pane *wp,
switch (data->searchtype) {
case WINDOW_COPY_OFF:
case WINDOW_COPY_GOTOLINE:
- case WINDOW_COPY_JUMPFORWARD:
+ case WINDOW_COPY_JUMP:
case WINDOW_COPY_JUMPBACK:
- case WINDOW_COPY_JUMPTOFORWARD:
+ case WINDOW_COPY_JUMPTO:
case WINDOW_COPY_JUMPTOBACK:
case WINDOW_COPY_NAMEDBUFFER:
case WINDOW_COPY_NUMERICPREFIX:
@@ -803,9 +811,9 @@ window_copy_key_input(struct window_pane
switch (data->inputtype) {
case WINDOW_COPY_OFF:
- case WINDOW_COPY_JUMPFORWARD:
+ case WINDOW_COPY_JUMP:
case WINDOW_COPY_JUMPBACK:
- case WINDOW_COPY_JUMPTOFORWARD:
+ case WINDOW_COPY_JUMPTO:
case WINDOW_COPY_JUMPTOBACK:
case WINDOW_COPY_NUMERICPREFIX:
break;
@@ -1915,7 +1923,7 @@ window_copy_cursor_down(struct window_pa
window_copy_cursor_start_of_line(wp);
}
-void
+int
window_copy_cursor_jump(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
@@ -1923,26 +1931,35 @@ window_copy_cursor_jump(struct window_pa
const struct grid_cell *gc;
struct utf8_data ud;
u_int px, py, xx;
+ int np;
+
+ if ((np = data->numprefix) <= 0)
+ np = 1;
- px = data->cx + 1;
+ px = data->cx;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
- while (px < xx) {
+ while (px < xx - 1 && np > 0) {
+ px++;
gc = grid_peek_cell(back_s->grid, px, py);
grid_cell_get(gc, &ud);
if (!(gc->flags & GRID_FLAG_PADDING) &&
- ud.size == 1 && *ud.data == data->jumpchar) {
- window_copy_update_cursor(wp, px, data->cy);
- if (window_copy_update_selection(wp, 1))
- window_copy_redraw_lines(wp, data->cy, 1);
- return;
- }
- px++;
+ ud.size == 1 && *ud.data == data->jumpchar)
+ np--;
}
+
+ if (np == 0) {
+ window_copy_update_cursor(wp, px, data->cy);
+ if (window_copy_update_selection(wp, 1))
+ window_copy_redraw_lines(wp, data->cy, 1);
+ return (0);
+ }
+
+ return (1);
}
-void
+int
window_copy_cursor_jump_back(struct window_pane *wp)
{
struct window_copy_mode_data *data = wp->modedata;
@@ -1950,85 +1967,45 @@ window_copy_cursor_jump_back(struct wind
const struct grid_cell *gc;
struct utf8_data ud;
u_int px, py;
+ int np;
+
+ if ((np = data->numprefix) <= 0)
+ np = 1;
px = data->cx;
py = screen_hsize(back_s) + data->cy - data->oy;
- if (px > 0)
+ while (px > 0 && np > 0) {
px--;
-
- for (;;) {
gc = grid_peek_cell(back_s->grid, px, py);
grid_cell_get(gc, &ud);
if (!(gc->flags & GRID_FLAG_PADDING) &&
- ud.size == 1 && *ud.data == data->jumpchar) {
- window_copy_update_cursor(wp, px, data->cy);
- if (window_copy_update_selection(wp, 1))
- window_copy_redraw_lines(wp, data->cy, 1);
- return;
- }
- if (px == 0)
- break;
- px--;
+ ud.size == 1 && *ud.data == data->jumpchar)
+ np--;
+ }
+
+ if (np == 0) {
+ window_copy_update_cursor(wp, px, data->cy);
+ if (window_copy_update_selection(wp, 1))
+ window_copy_redraw_lines(wp, data->cy, 1);
+ return (0);
}
+
+ return (1);
}
void
window_copy_cursor_jump_to(struct window_pane *wp)
{
- struct window_copy_mode_data *data = wp->modedata;
- struct screen *back_s = data->backing;
- const struct grid_cell *gc;
- struct utf8_data ud;
- u_int px, py, xx;
-
- px = data->cx + 1;
- py = screen_hsize(back_s) + data->cy - data->oy;
- xx = window_copy_find_length(wp, py);
-
- while (px < xx) {
- gc = grid_peek_cell(back_s->grid, px, py);
- grid_cell_get(gc, &ud);
- if (!(gc->flags & GRID_FLAG_PADDING) &&
- ud.size == 1 && *ud.data == data->jumpchar) {
- window_copy_update_cursor(wp, px - 1, data->cy);
- if (window_copy_update_selection(wp, 1))
- window_copy_redraw_lines(wp, data->cy, 1);
- return;
- }
- px++;
- }
+ if (window_copy_cursor_jump(wp) == 0) /* cursor moved to the right */
+ window_copy_cursor_left(wp); /* one step back */
}
void
window_copy_cursor_jump_to_back(struct window_pane *wp)
{
- struct window_copy_mode_data *data = wp->modedata;
- struct screen *back_s = data->backing;
- const struct grid_cell *gc;
- struct utf8_data ud;
- u_int px, py;
-
- px = data->cx;
- py = screen_hsize(back_s) + data->cy - data->oy;
-
- if (px > 0)
- px--;
-
- for (;;) {
- gc = grid_peek_cell(back_s->grid, px, py);
- grid_cell_get(gc, &ud);
- if (!(gc->flags & GRID_FLAG_PADDING) &&
- ud.size == 1 && *ud.data == data->jumpchar) {
- window_copy_update_cursor(wp, px + 1, data->cy);
- if (window_copy_update_selection(wp, 1))
- window_copy_redraw_lines(wp, data->cy, 1);
- return;
- }
- if (px == 0)
- break;
- px--;
- }
+ if (window_copy_cursor_jump_back(wp) == 0) /* cursor moved left */
+ window_copy_cursor_right(wp); /* one step forward */
}
void