aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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*);