From 203e023022a2b53125bbb0adc39661d77e6f4526 Mon Sep 17 00:00:00 2001
From: Marcel Rodrigues <marcelgmr@gmail.com>
Date: Tue, 24 Mar 2015 16:18:22 -0300
Subject: [PATCH] Implement 'o' in visual mode: go to other end of selection.

---
 config.def.h |  1 +
 vis.c        | 16 ++++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/config.def.h b/config.def.h
index a0876be..88b6a67 100644
--- a/config.def.h
+++ b/config.def.h
@@ -447,6 +447,7 @@ static KeyBinding vis_mode_visual[] = {
 	{ { NONE('r')               }, operator,       { .i = OP_CHANGE            } },
 	{ { NONE('s')               }, operator,       { .i = OP_CHANGE            } },
 	{ { NONE('J')               }, operator,       { .i = OP_JOIN              } },
+	{ { NONE('o')               }, selection_end,  { NULL                      } },
 	{ /* empty last element, array terminator */                                 },
 };
 
diff --git a/vis.c b/vis.c
index 52974b8..7dd6f06 100644
--- a/vis.c
+++ b/vis.c
@@ -448,6 +448,8 @@ static void movement_key(const Arg *arg);
 static void movement(const Arg *arg);
 /* let the current operator affect the range indicated by the text object arg->i */
 static void textobj(const Arg *arg);
+/* move to the other end of selected text */
+static void selection_end(const Arg *arg);
 /* use register indicated by arg->i for the current operator */
 static void reg(const Arg *arg);
 /* perform a movement to mark arg->i */
@@ -958,6 +960,20 @@ static void textobj(const Arg *arg) {
 	action_do(&action);
 }
 
+static void selection_end(const Arg *arg) {
+	size_t pos = window_cursor_get(vis->win->win);
+	Filerange sel = window_selection_get(vis->win->win);
+	if (pos == sel.start) {
+		pos = text_char_prev(vis->win->text, sel.end);
+	} else {
+		pos = sel.start;
+		sel.start = text_char_prev(vis->win->text, sel.end);
+		sel.end = pos;
+	}
+	window_selection_set(vis->win->win, &sel);
+	window_cursor_to(vis->win->win, pos);
+}
+
 static void reg(const Arg *arg) {
 	action.reg = &vis->registers[arg->i];
 }
-- 
2.3.4

