Skip to content

Commit

Permalink
Add new logical linewise movements
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
martanne committed Jan 13, 2015
1 parent cad4ad2 commit ff587fb
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 0 deletions.
9 changes: 9 additions & 0 deletions text-motions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions text-motions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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],
};
Expand Down
24 changes: 24 additions & 0 deletions window.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions window.h
Original file line number Diff line number Diff line change
Expand Up @@ -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*);
Expand Down

0 comments on commit ff587fb

Please sign in to comment.