Support "jump to" like vi in copy mode using t and T keys. Also add x

and X for delete in edit mode.

From Ben Boeckel, thanks.
pull/1/head
Nicholas Marriott 2011-12-04 16:18:01 +00:00
parent c44d2d854f
commit e04d13f6a6
4 changed files with 111 additions and 3 deletions

View File

@ -98,6 +98,8 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
{ MODEKEYCOPY_JUMPAGAIN, "jump-again" },
{ MODEKEYCOPY_JUMPREVERSE, "jump-reverse" },
{ MODEKEYCOPY_JUMPBACK, "jump-backward" },
{ MODEKEYCOPY_JUMPTO, "jump-to-forward" },
{ MODEKEYCOPY_JUMPTOBACK, "jump-to-backward" },
{ MODEKEYCOPY_LEFT, "cursor-left" },
{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
@ -147,6 +149,7 @@ const struct mode_key_entry mode_key_vi_edit[] = {
{ '$', 1, MODEKEYEDIT_ENDOFLINE },
{ '0', 1, MODEKEYEDIT_STARTOFLINE },
{ 'D', 1, MODEKEYEDIT_DELETETOENDOFLINE },
{ 'X', 1, MODEKEYEDIT_BACKSPACE },
{ '\003' /* C-c */, 1, MODEKEYEDIT_CANCEL },
{ '\010' /* C-h */, 1, MODEKEYEDIT_BACKSPACE },
{ '\r', 1, MODEKEYEDIT_ENTER },
@ -162,6 +165,7 @@ const struct mode_key_entry mode_key_vi_edit[] = {
{ 'l', 1, MODEKEYEDIT_CURSORRIGHT },
{ 'p', 1, MODEKEYEDIT_PASTE },
{ 'w', 1, MODEKEYEDIT_NEXTWORD },
{ 'x', 1, MODEKEYEDIT_DELETE },
{ KEYC_BSPACE, 1, MODEKEYEDIT_BACKSPACE },
{ KEYC_DC, 1, MODEKEYEDIT_DELETE },
{ KEYC_DOWN, 1, MODEKEYEDIT_HISTORYDOWN },
@ -225,6 +229,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ 'L', 0, MODEKEYCOPY_BOTTOMLINE },
{ 'M', 0, MODEKEYCOPY_MIDDLELINE },
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
{ 'W', 0, MODEKEYCOPY_NEXTSPACE },
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
@ -246,6 +251,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ 'k', 0, MODEKEYCOPY_UP },
{ 'l', 0, MODEKEYCOPY_RIGHT },
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
{ 't', 0, MODEKEYCOPY_JUMPTO },
{ 'q', 0, MODEKEYCOPY_CANCEL },
{ 'v', 0, MODEKEYCOPY_RECTANGLETOGGLE },
{ 'w', 0, MODEKEYCOPY_NEXTWORD },
@ -339,6 +345,7 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
{ 'N', 0, MODEKEYCOPY_SEARCHREVERSE },
{ 'R' | KEYC_ESCAPE, 0, MODEKEYCOPY_TOPLINE },
{ 'R', 0, MODEKEYCOPY_RECTANGLETOGGLE },
{ 'T', 0, MODEKEYCOPY_JUMPTOBACK },
{ '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
{ '\001' /* C-a */, 0, MODEKEYCOPY_STARTOFLINE },
{ '\002' /* C-b */, 0, MODEKEYCOPY_LEFT },
@ -363,6 +370,7 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
{ 'n', 0, MODEKEYCOPY_SEARCHAGAIN },
{ 'q', 0, MODEKEYCOPY_CANCEL },
{ 'r' | KEYC_ESCAPE, 0, MODEKEYCOPY_MIDDLELINE },
{ 't', 0, MODEKEYCOPY_JUMPTO },
{ 'v' | KEYC_ESCAPE, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ 'w' | KEYC_ESCAPE, 0, MODEKEYCOPY_COPYSELECTION },
{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },

2
tmux.1
View File

@ -803,7 +803,9 @@ The following keys are supported as appropriate for the mode:
.It Li "Half page down" Ta "C-d" Ta "M-Down"
.It Li "Half page up" Ta "C-u" Ta "M-Up"
.It Li "Jump forward" Ta "f" Ta "f"
.It Li "Jump to forward" Ta "t" Ta ""
.It Li "Jump backward" Ta "F" Ta "F"
.It Li "Jump to backward" Ta "T" Ta ""
.It Li "Jump again" Ta ";" Ta ";"
.It Li "Jump again in reverse" Ta "," Ta ","
.It Li "Next page" Ta "C-f" Ta "Page down"

2
tmux.h
View File

@ -485,6 +485,8 @@ enum mode_key_cmd {
MODEKEYCOPY_JUMPAGAIN,
MODEKEYCOPY_JUMPREVERSE,
MODEKEYCOPY_JUMPBACK,
MODEKEYCOPY_JUMPTO,
MODEKEYCOPY_JUMPTOBACK,
MODEKEYCOPY_LEFT,
MODEKEYCOPY_MIDDLELINE,
MODEKEYCOPY_NEXTPAGE,

View File

@ -67,6 +67,8 @@ 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 *);
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 *);
void window_copy_cursor_next_word_end(struct window_pane *, const char *);
void window_copy_cursor_previous_word(struct window_pane *, const char *);
@ -90,6 +92,8 @@ enum window_copy_input_type {
WINDOW_COPY_SEARCHDOWN,
WINDOW_COPY_JUMPFORWARD,
WINDOW_COPY_JUMPBACK,
WINDOW_COPY_JUMPTOFORWARD,
WINDOW_COPY_JUMPTOBACK,
WINDOW_COPY_GOTOLINE,
};
@ -132,7 +136,7 @@ struct window_copy_mode_data {
enum window_copy_input_type inputtype;
const char *inputprompt;
char *inputstr;
char *inputstr;
int numprefix;
@ -367,16 +371,24 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
np = 1;
if (data->inputtype == WINDOW_COPY_JUMPFORWARD ||
data->inputtype == WINDOW_COPY_JUMPBACK) {
data->inputtype == WINDOW_COPY_JUMPBACK ||
data->inputtype == WINDOW_COPY_JUMPTOFORWARD ||
data->inputtype == 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 {
} 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);
}
}
data->jumptype = data->inputtype;
@ -581,6 +593,12 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
} 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);
}
break;
case MODEKEYCOPY_JUMPREVERSE:
@ -590,6 +608,12 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
} 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);
}
break;
case MODEKEYCOPY_JUMPBACK:
@ -598,6 +622,18 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPTO:
data->inputtype = WINDOW_COPY_JUMPTOFORWARD;
data->inputprompt = "Jump To";
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_JUMPTOBACK:
data->inputtype = WINDOW_COPY_JUMPTOBACK;
data->inputprompt = "Jump To Back";
*data->inputstr = '\0';
window_copy_redraw_lines(wp, screen_size_y(s) - 1, 1);
return; /* skip numprefix reset */
case MODEKEYCOPY_SEARCHUP:
data->inputtype = WINDOW_COPY_SEARCHUP;
data->inputprompt = "Search Up";
@ -613,6 +649,8 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
case WINDOW_COPY_GOTOLINE:
case WINDOW_COPY_JUMPFORWARD:
case WINDOW_COPY_JUMPBACK:
case WINDOW_COPY_JUMPTOFORWARD:
case WINDOW_COPY_JUMPTOBACK:
case WINDOW_COPY_NUMERICPREFIX:
break;
case WINDOW_COPY_SEARCHUP:
@ -719,6 +757,8 @@ window_copy_key_input(struct window_pane *wp, int key)
case WINDOW_COPY_OFF:
case WINDOW_COPY_JUMPFORWARD:
case WINDOW_COPY_JUMPBACK:
case WINDOW_COPY_JUMPTOFORWARD:
case WINDOW_COPY_JUMPTOBACK:
case WINDOW_COPY_NUMERICPREFIX:
break;
case WINDOW_COPY_SEARCHUP:
@ -1712,6 +1752,62 @@ window_copy_cursor_jump_back(struct window_pane *wp)
}
}
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;
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);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
&& gc->data == data->jumpchar) {
window_copy_update_cursor(wp, px - 1, data->cy);
if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1);
return;
}
px++;
}
}
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;
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);
if ((gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8)) == 0
&& gc->data == data->jumpchar) {
window_copy_update_cursor(wp, px + 1, data->cy);
if (window_copy_update_selection(wp))
window_copy_redraw_lines(wp, data->cy, 1);
return;
}
if (px == 0)
break;
px--;
}
}
void
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
{