This patch allows the user to specify what characters are considered
"word separators" for the purposes of the next and previous word
commands in copy mode (bound to M-b and M-f in emacs-copy; w, b and e in
vi-copy).

Since the space character is no longer guaranteed to be one of the word
separator characters, the next and previous word functions had to be
adjusted so that both of the loops explicitly check whether they're past
the line (this may have been necessary anyway? I experienced an
apparently related crash once, but couldn't reproduce it). This makes
the two loops in each function identical, apart from whether they are or
aren't looking for word-separators, so I merged them into one loop, with
an outer loop that runs them twice (once looking for one kind of
character, once looking for the other).

The man page said that the quote character '"' is among those used by
previous and next word, but it has not been, so I removed that from the
list in the manpage.

While testing, I noticed that the semicolon character in the string
argument to set-w word-separators is ignored if it appears at the end of
the (quoted) string... the message bar tells me that it set it to the
string sans semicolon. Will investigate, but not related to my patch.

-- 
Micah J. Cowan
http://micah.cowan.name/
Index: tmux.c
===================================================================
--- tmux.c.orig
+++ tmux.c
@@ -421,6 +421,7 @@
 	options_set_number(wo, "window-status-fg", 8);
 	options_set_string(wo, "window-status-format", "#I:#W#F");
 	options_set_string(wo, "window-status-current-format", "#I:#W#F");
+	options_set_string(wo, "word-separators", " -_@");
 	options_set_number(wo, "xterm-keys", 0);
 	options_set_number(wo, "remain-on-exit", 0);
 	options_set_number(wo, "synchronize-panes", 0);
Index: window-copy.c
===================================================================
--- window-copy.c.orig
+++ window-copy.c
@@ -320,7 +320,7 @@
 void
 window_copy_key(struct window_pane *wp, struct client *c, int key)
 {
-	const char			*word_separators = " -_@";
+	const char			*word_separators;
 	struct window_copy_mode_data	*data = wp->modedata;
 	struct screen			*s = &data->screen;
 	u_int				 n;
@@ -450,15 +450,21 @@
 		window_copy_cursor_next_word_end(wp, " ");
 		break;
 	case MODEKEYCOPY_NEXTWORD:
+		word_separators =
+		    options_get_string(&wp->window->options, "word-separators");
 		window_copy_cursor_next_word(wp, word_separators);
 		break;
 	case MODEKEYCOPY_NEXTWORDEND:
+		word_separators =
+		    options_get_string(&wp->window->options, "word-separators");
 		window_copy_cursor_next_word_end(wp, word_separators);
 		break;
 	case MODEKEYCOPY_PREVIOUSSPACE:
 		window_copy_cursor_previous_word(wp, " ");
 		break;
 	case MODEKEYCOPY_PREVIOUSWORD:
+		word_separators =
+		    options_get_string(&wp->window->options, "word-separators");
 		window_copy_cursor_previous_word(wp, word_separators);
 		break;
 	case MODEKEYCOPY_SEARCHUP:
@@ -1347,30 +1353,33 @@
 	struct window_copy_mode_data	*data = wp->modedata;
 	struct screen			*back_s = data->backing;
 	u_int				 px, py, xx, yy;
+	int				 expected = 0;
 
 	px = data->cx;
 	py = screen_hsize(back_s) + data->cy - data->oy;
 	xx = window_copy_find_length(wp, py);
 	yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
 
-	/* Are we in a word? Skip it! */
-	while (!window_copy_in_set(wp, px, py, separators))
-		px++;
-
-	/* Find the start of a word. */
-	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)
-				return;
-			window_copy_cursor_down(wp, 0);
-			px = 0;
+	/* First skip past any word chars, then skip past any non-word
+	 * chars. */
+	do {
+		while (px > xx
+		       || (window_copy_in_set(wp, px, py, separators)
+			   == expected)) {
+			/* Move down if we're past the end of the line. */
+			if (px > xx) {
+				if (py == yy)
+					return;
+				window_copy_cursor_down(wp, 0);
+				px = 0;
 
-			py = screen_hsize(back_s) + data->cy - data->oy;
-			xx = window_copy_find_length(wp, py);
+				py = screen_hsize(back_s) + data->cy - data->oy;
+				xx = window_copy_find_length(wp, py);
+			}
+			px++;
 		}
-		px++;
-	}
+		expected = !expected;
+	} while (expected == 1);
 
 	window_copy_update_cursor(wp, px, data->cy);
 	if (window_copy_update_selection(wp))
@@ -1383,30 +1392,33 @@
 	struct window_copy_mode_data	*data = wp->modedata;
 	struct screen			*back_s = data->backing;
 	u_int				 px, py, xx, yy;
+	int				 expected = 1;
 
 	px = data->cx;
 	py = screen_hsize(back_s) + data->cy - data->oy;
 	xx = window_copy_find_length(wp, py);
 	yy = screen_hsize(back_s) + screen_size_y(back_s) - 1;
 
-	/* Are we on spaces? Skip 'em! */
-	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)
-				return;
-			window_copy_cursor_down(wp, 0);
-			px = 0;
+	/* First skip past any non-word chars, then skip past any word
+	 * chars. */
+	do {
+		while (px > xx
+		       || (window_copy_in_set(wp, px, py, separators)
+			   == expected)) {
+			/* Move down if we're past the end of the line. */
+			if (px > xx) {
+				if (py == yy)
+					return;
+				window_copy_cursor_down(wp, 0);
+				px = 0;
 
-			py = screen_hsize(back_s) + data->cy - data->oy;
-			xx = window_copy_find_length(wp, py);
+				py = screen_hsize(back_s) + data->cy - data->oy;
+				xx = window_copy_find_length(wp, py);
+			}
+			px++;
 		}
-		px++;
-	}
-
-	/* Find the end of this word. */
-	while (!window_copy_in_set(wp, px, py, separators))
-		px++;
+		expected = !expected;
+	} while (expected == 0);
 
 	window_copy_update_cursor(wp, px, data->cy);
 	if (window_copy_update_selection(wp))
Index: cmd-set-option.c
===================================================================
--- cmd-set-option.c.orig
+++ cmd-set-option.c
@@ -165,6 +165,7 @@
 	{ "window-status-current-format", SET_OPTION_STRING, 0, 0, NULL },
 	{ "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
 	{ "window-status-format", SET_OPTION_STRING, 0, 0, NULL },
+	{ "word-separators", SET_OPTION_STRING, 0, 0, NULL },
 	{ "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
 	{ NULL, 0, 0, 0, NULL }
 };
Index: tmux.1
===================================================================
--- tmux.1.orig
+++ tmux.1
@@ -579,11 +579,13 @@
 .Pp
 The next and previous word keys use space and the
 .Ql - ,
-.Ql _ ,
-.Ql \&"
+.Ql _
 and
 .Ql @
-characters as word delimiters.
+characters as word delimiters by default, but this can be adjusted by
+setting the
+.Em word-separators
+window option.
 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
@@ -1948,6 +1950,12 @@
 .Ar window-status-format ,
 but is the format used when the window is the current window.
 .Pp
+.It Ic word-separators Ar string
+Sets the window's conception of what characters are considered word
+separators, for the purposes of the next and previous word commands in
+copy mode. The default is
+.Ql \ -_@ .
+.Pp
 .It Xo Ic xterm-keys
 .Op Ic on | off
 .Xc
------------------------------------------------------------------------------
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to