aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-01-13 19:41:56 +0100
committerMarc André Tanner <mat@brain-dump.org>2015-01-13 23:01:09 +0100
commitff587fb25a56656a9a426a5086b47a5cf891092b (patch)
tree911915a3d8ecca9f48effe889bd069776d0f2472
parentcad4ad2c4e9de198ca78958b4db79886ffb81c56 (diff)
downloadvis-ff587fb25a56656a9a426a5086b47a5cf891092b.tar.gz
vis-ff587fb25a56656a9a426a5086b47a5cf891092b.tar.xz
Add new logical linewise movements
The column position is currently not correctly preserved when there are lines with multibyte characters involved spanning multiple screen lines. In general this might still be a bit fragile.
-rw-r--r--text-motions.c9
-rw-r--r--text-motions.h1
-rw-r--r--vis.c6
-rw-r--r--window.c24
-rw-r--r--window.h2
5 files changed, 42 insertions, 0 deletions
diff --git a/text-motions.c b/text-motions.c
index 3a970e8..00e3cc8 100644
--- a/text-motions.c
+++ b/text-motions.c
@@ -154,6 +154,15 @@ size_t text_line_next(Text *txt, size_t pos) {
return it.pos;
}
+size_t text_line_offset(Text *txt, size_t pos, size_t off) {
+ char c;
+ size_t bol = text_line_begin(txt, pos);
+ Iterator it = text_iterator_get(txt, bol);
+ while (off-- > 0 && text_iterator_byte_get(&it, &c) && c != '\r' && c != '\n')
+ text_iterator_byte_next(&it, NULL);
+ return it.pos;
+}
+
static size_t text_customword_start_next(Text *txt, size_t pos, int (*isboundry)(int)) {
char c;
Iterator it = text_iterator_get(txt, pos);
diff --git a/text-motions.h b/text-motions.h
index e69a073..dca9fac 100644
--- a/text-motions.h
+++ b/text-motions.h
@@ -34,6 +34,7 @@ size_t text_line_finish(Text*, size_t pos);
size_t text_line_lastchar(Text*, size_t pos);
size_t text_line_end(Text*, size_t pos);
size_t text_line_next(Text*, size_t pos);
+size_t text_line_offset(Text*, size_t pos, size_t off);
/*
* A longword consists of a sequence of non-blank characters, separated with
* white space. TODO?: An empty line is also considered to be a word.
diff --git a/vis.c b/vis.c
index 8845209..e32835e 100644
--- a/vis.c
+++ b/vis.c
@@ -202,6 +202,8 @@ static Operator ops[] = {
/* these can be passed as int argument to movement(&(const Arg){ .i = MOVE_* }) */
enum {
+ MOVE_LINE_DOWN,
+ MOVE_LINE_UP,
MOVE_SCREEN_LINE_UP,
MOVE_SCREEN_LINE_DOWN,
MOVE_SCREEN_LINE_BEGIN,
@@ -281,6 +283,8 @@ static size_t window_lines_middle(const Arg *arg);
static size_t window_lines_bottom(const Arg *arg);
static Movement moves[] = {
+ [MOVE_LINE_UP] = { .win = window_line_up },
+ [MOVE_LINE_DOWN] = { .win = window_line_down },
[MOVE_SCREEN_LINE_UP] = { .win = window_screenline_up },
[MOVE_SCREEN_LINE_DOWN] = { .win = window_screenline_down },
[MOVE_SCREEN_LINE_BEGIN] = { .win = window_screenline_begin, .type = CHARWISE },
@@ -380,6 +384,8 @@ static TextObject textobjs[] = {
/* if some movements are forced to be linewise, they are translated to text objects */
static TextObject *moves_linewise[] = {
+ [MOVE_LINE_UP] = &textobjs[TEXT_OBJ_LINE_UP],
+ [MOVE_LINE_DOWN] = &textobjs[TEXT_OBJ_LINE_DOWN],
[MOVE_SCREEN_LINE_UP] = &textobjs[TEXT_OBJ_LINE_UP],
[MOVE_SCREEN_LINE_DOWN] = &textobjs[TEXT_OBJ_LINE_DOWN],
};
diff --git a/window.c b/window.c
index d546780..47fad1a 100644
--- a/window.c
+++ b/window.c
@@ -788,6 +788,30 @@ size_t window_scroll_down(Win *win, int lines) {
return cursor->pos;
}
+size_t window_line_up(Win *win) {
+ Cursor *cursor = &win->cursor;
+ if (cursor->line->prev && cursor->line->prev->prev &&
+ cursor->line->lineno != cursor->line->prev->lineno &&
+ cursor->line->prev->lineno != cursor->line->prev->prev->lineno)
+ return window_screenline_up(win);
+ size_t bol = text_line_begin(win->text, cursor->pos);
+ size_t prev = text_line_prev(win->text, bol);
+ size_t pos = text_line_offset(win->text, prev, cursor->pos - bol);
+ window_cursor_to(win, pos);
+ return cursor->pos;
+}
+
+size_t window_line_down(Win *win) {
+ Cursor *cursor = &win->cursor;
+ if (!cursor->line->next || cursor->line->next->lineno != cursor->line->lineno)
+ return window_screenline_down(win);
+ size_t bol = text_line_begin(win->text, cursor->pos);
+ size_t next = text_line_next(win->text, bol);
+ size_t pos = text_line_offset(win->text, next, cursor->pos - bol);
+ window_cursor_to(win, pos);
+ return cursor->pos;
+}
+
size_t window_screenline_up(Win *win) {
Cursor *cursor = &win->cursor;
if (!cursor->line->prev)
diff --git a/window.h b/window.h
index add8e2a..686f67f 100644
--- a/window.h
+++ b/window.h
@@ -36,6 +36,8 @@ void window_tabwidth_set(Win*, int tabwidth);
* they return new cursor postion */
size_t window_char_next(Win*);
size_t window_char_prev(Win*);
+size_t window_line_down(Win*);
+size_t window_line_up(Win*);
size_t window_screenline_down(Win*);
size_t window_screenline_up(Win*);
size_t window_screenline_begin(Win*);