vi-style B, W and E keys in copy mode to navigate between words treating only

spaces as word separators. Also add . to the list of word separators for
standard word navigation.

From Micah Cowan, tweaked slightly by me.
This commit is contained in:
Nicholas Marriott 2010-02-04 20:00:26 +00:00
parent e7c6f81016
commit 5e6a7c85cc
4 changed files with 53 additions and 24 deletions

View File

@ -91,9 +91,12 @@ struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
{ MODEKEYCOPY_LEFT, "cursor-left" },
{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
{ MODEKEYCOPY_NEXTPAGE, "page-down" },
{ MODEKEYCOPY_NEXTSPACE, "next-space" },
{ MODEKEYCOPY_NEXTSPACEEND, "next-space-end" },
{ MODEKEYCOPY_NEXTWORD, "next-word" },
{ MODEKEYCOPY_NEXTWORDEND, "next-word-end" },
{ MODEKEYCOPY_PREVIOUSPAGE, "page-up" },
{ MODEKEYCOPY_PREVIOUSSPACE, "previous-space" },
{ MODEKEYCOPY_PREVIOUSWORD, "previous-word" },
{ MODEKEYCOPY_RIGHT, "cursor-right" },
{ MODEKEYCOPY_SCROLLDOWN, "scroll-down" },
@ -175,12 +178,15 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ '0', 0, MODEKEYCOPY_STARTOFLINE },
{ ':', 0, MODEKEYCOPY_GOTOLINE },
{ '?', 0, MODEKEYCOPY_SEARCHUP },
{ 'B', 0, MODEKEYCOPY_PREVIOUSSPACE },
{ 'E', 0, MODEKEYCOPY_NEXTSPACEEND },
{ 'G', 0, MODEKEYCOPY_HISTORYBOTTOM },
{ 'H', 0, MODEKEYCOPY_TOPLINE },
{ 'J', 0, MODEKEYCOPY_SCROLLDOWN },
{ 'K', 0, MODEKEYCOPY_SCROLLUP },
{ 'L', 0, MODEKEYCOPY_BOTTOMLINE },
{ 'M', 0, MODEKEYCOPY_MIDDLELINE },
{ 'W', 0, MODEKEYCOPY_NEXTSPACE },
{ '\002' /* C-b */, 0, MODEKEYCOPY_PREVIOUSPAGE },
{ '\003' /* C-c */, 0, MODEKEYCOPY_CANCEL },
{ '\004' /* C-d */, 0, MODEKEYCOPY_HALFPAGEDOWN },

17
tmux.1
View File

@ -535,7 +535,7 @@ The keys available depend on whether emacs or vi mode is selected
.Ic mode-keys
option).
The following keys are supported as appropriate for the mode:
.Bl -column "FunctionXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
.Bl -column "FunctionXXXXXXXXXXXXXX" "viXXXXXXXXXX" "emacs" -offset indent
.It Sy "Function" Ta Sy "vi" Ta Sy "emacs"
.It Li "Back to indentation" Ta "^" Ta "M-m"
.It Li "Bottom of history" Ta "G" Ta "M-<"
@ -555,11 +555,14 @@ 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 "Next page" Ta "C-f" Ta "Page down"
.It Li "Next space" Ta "W" Ta ""
.It Li "Next space, end of word" Ta "E" Ta ""
.It Li "Next word" Ta "w" Ta ""
.It Li "Next word end" Ta "e" Ta "M-f"
.It Li "Paste buffer" Ta "p" Ta "C-y"
.It Li "Previous page" Ta "C-b" Ta "Page up"
.It Li "Previous word" Ta "b" Ta "M-b"
.It Li "Previous space" Ta "B" Ta ""
.It Li "Quit mode" Ta "q" Ta "Escape"
.It Li "Scroll down" Ta "C-Down or C-e" Ta "C-Down"
.It Li "Scroll up" Ta "C-Up or C-y" Ta "C-Up"
@ -572,6 +575,18 @@ The following keys are supported as appropriate for the mode:
.It Li "Transpose chars" Ta "" Ta "C-t"
.El
.Pp
The next and previous word keys use space and the
.Ql - ,
.Ql _ ,
.Ql \&"
and
.Ql @
characters as word delimiters.
Next word moves to the start of the next word, next word end to the end of the
next word and previous word to the start of the previous word.
The three next and previous space keys work similarly but use a space alone as
the word separator.
.Pp
These key bindings are defined in a set of named tables:
.Em vi-edit
and

3
tmux.h
View File

@ -462,9 +462,12 @@ enum mode_key_cmd {
MODEKEYCOPY_LEFT,
MODEKEYCOPY_MIDDLELINE,
MODEKEYCOPY_NEXTPAGE,
MODEKEYCOPY_NEXTSPACE,
MODEKEYCOPY_NEXTSPACEEND,
MODEKEYCOPY_NEXTWORD,
MODEKEYCOPY_NEXTWORDEND,
MODEKEYCOPY_PREVIOUSPAGE,
MODEKEYCOPY_PREVIOUSSPACE,
MODEKEYCOPY_PREVIOUSWORD,
MODEKEYCOPY_RIGHT,
MODEKEYCOPY_SCROLLDOWN,

View File

@ -54,7 +54,7 @@ int window_copy_update_selection(struct window_pane *);
void window_copy_copy_selection(struct window_pane *, struct client *);
void window_copy_copy_line(
struct window_pane *, char **, size_t *, u_int, u_int, u_int);
int window_copy_is_space(struct window_pane *, u_int, u_int);
int window_copy_in_set(struct window_pane *, u_int, u_int, const char *);
u_int window_copy_find_length(struct window_pane *, u_int);
void window_copy_cursor_start_of_line(struct window_pane *);
void window_copy_cursor_back_to_indentation(struct window_pane *);
@ -63,9 +63,9 @@ void window_copy_cursor_left(struct window_pane *);
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_next_word(struct window_pane *);
void window_copy_cursor_next_word_end(struct window_pane *);
void window_copy_cursor_previous_word(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 *);
void window_copy_scroll_up(struct window_pane *, u_int);
void window_copy_scroll_down(struct window_pane *, u_int);
@ -214,6 +214,7 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
void
window_copy_key(struct window_pane *wp, struct client *c, int key)
{
const char *word_separators = " -_@";
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
u_int n;
@ -334,14 +335,23 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
case MODEKEYCOPY_ENDOFLINE:
window_copy_cursor_end_of_line(wp);
break;
case MODEKEYCOPY_NEXTSPACE:
window_copy_cursor_next_word(wp, " ");
break;
case MODEKEYCOPY_NEXTSPACEEND:
window_copy_cursor_next_word_end(wp, " ");
break;
case MODEKEYCOPY_NEXTWORD:
window_copy_cursor_next_word(wp);
window_copy_cursor_next_word(wp, word_separators);
break;
case MODEKEYCOPY_NEXTWORDEND:
window_copy_cursor_next_word_end(wp);
window_copy_cursor_next_word_end(wp, word_separators);
break;
case MODEKEYCOPY_PREVIOUSSPACE:
window_copy_cursor_previous_word(wp, " ");
break;
case MODEKEYCOPY_PREVIOUSWORD:
window_copy_cursor_previous_word(wp);
window_copy_cursor_previous_word(wp, word_separators);
break;
case MODEKEYCOPY_SEARCHUP:
data->inputtype = WINDOW_COPY_SEARCHUP;
@ -965,17 +975,16 @@ window_copy_copy_line(struct window_pane *wp,
}
int
window_copy_is_space(struct window_pane *wp, u_int px, u_int py)
window_copy_in_set(struct window_pane *wp, u_int px, u_int py, const char *set)
{
const struct grid_cell *gc;
const char *spaces = " -_@";
gc = grid_peek_cell(wp->base.grid, px, py);
if (gc->flags & (GRID_FLAG_PADDING|GRID_FLAG_UTF8))
return (0);
if (gc->data == 0x00 || gc->data == 0x7f)
return (0);
return (strchr(spaces, gc->data) != NULL);
return (strchr(set, gc->data) != NULL);
}
u_int
@ -1025,10 +1034,6 @@ window_copy_cursor_back_to_indentation(struct window_pane *wp)
py = screen_hsize(&wp->base) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
/*
* Don't use window_copy_is_space because that treats some word
* delimiters as spaces.
*/
while (px < xx) {
gc = grid_peek_cell(wp->base.grid, px, py);
if (gc->flags & GRID_FLAG_UTF8)
@ -1162,7 +1167,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
}
void
window_copy_cursor_next_word(struct window_pane *wp)
window_copy_cursor_next_word(struct window_pane *wp, const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
@ -1174,11 +1179,11 @@ window_copy_cursor_next_word(struct window_pane *wp)
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
/* Are we in a word? Skip it! */
while (!window_copy_is_space(wp, px, py))
while (!window_copy_in_set(wp, px, py, separators))
px++;
/* Find the start of a word. */
while (px > xx || window_copy_is_space(wp, px, py)) {
while (px > xx || window_copy_in_set(wp, px, py, separators)) {
/* Past the end of the line? Nothing but spaces. */
if (px > xx) {
if (py == yy)
@ -1198,7 +1203,7 @@ window_copy_cursor_next_word(struct window_pane *wp)
}
void
window_copy_cursor_next_word_end(struct window_pane *wp)
window_copy_cursor_next_word_end(struct window_pane *wp, const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *base_s = &wp->base;
@ -1210,7 +1215,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp)
yy = screen_hsize(base_s) + screen_size_y(base_s) - 1;
/* Are we on spaces? Skip 'em! */
while (px > xx || window_copy_is_space(wp, px, py)) {
while (px > xx || window_copy_in_set(wp, px, py, separators)) {
/* Nothing but spaces past the end of the line, so move down. */
if (px > xx) {
if (py == yy)
@ -1225,7 +1230,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp)
}
/* Find the end of this word. */
while (!window_copy_is_space(wp, px, py))
while (!window_copy_in_set(wp, px, py, separators))
px++;
window_copy_update_cursor(wp, px, data->cy);
@ -1235,7 +1240,7 @@ window_copy_cursor_next_word_end(struct window_pane *wp)
/* Move to the previous place where a word begins. */
void
window_copy_cursor_previous_word(struct window_pane *wp)
window_copy_cursor_previous_word(struct window_pane *wp, const char *separators)
{
struct window_copy_mode_data *data = wp->modedata;
u_int px, py;
@ -1247,7 +1252,7 @@ window_copy_cursor_previous_word(struct window_pane *wp)
for (;;) {
if (px > 0) {
px--;
if (!window_copy_is_space(wp, px, py))
if (!window_copy_in_set(wp, px, py, separators))
break;
} else {
if (data->cy == 0 &&
@ -1262,7 +1267,7 @@ window_copy_cursor_previous_word(struct window_pane *wp)
}
/* Move back to the beginning of this word. */
while (px > 0 && !window_copy_is_space(wp, px - 1, py))
while (px > 0 && !window_copy_in_set(wp, px - 1, py, separators))
px--;
out: