aboutsummaryrefslogtreecommitdiff
path: root/vis-motions.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-11-06 22:05:44 +0100
committerMarc André Tanner <mat@brain-dump.org>2015-11-07 08:52:50 +0100
commitd34ed26989a4775c3b5fd97355d72ef4a6552c71 (patch)
tree4a4077a40ac481cef3e4df70fa7b8d969805043c /vis-motions.c
parentfa1eb7921e7c35a0d587a5c0da30a4c47d65a848 (diff)
downloadvis-d34ed26989a4775c3b5fd97355d72ef4a6552c71.tar.gz
vis-d34ed26989a4775c3b5fd97355d72ef4a6552c71.tar.xz
vis: move motions to separate file
Diffstat (limited to 'vis-motions.c')
-rw-r--r--vis-motions.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/vis-motions.c b/vis-motions.c
new file mode 100644
index 0000000..b0a6f09
--- /dev/null
+++ b/vis-motions.c
@@ -0,0 +1,269 @@
+#include "vis-core.h"
+#include "text-motions.h"
+#include "text-objects.h"
+#include "text-util.h"
+
+/** movements which can be used besides the one in text-motions.h and view.h */
+
+/* search in forward direction for the word under the cursor */
+static size_t search_word_forward(Vis*, Text *txt, size_t pos);
+/* search in backward direction for the word under the cursor */
+static size_t search_word_backward(Vis*, Text *txt, size_t pos);
+/* search again for the last used search pattern */
+static size_t search_forward(Vis*, Text *txt, size_t pos);
+static size_t search_backward(Vis*, Text *txt, size_t pos);
+/* goto action.mark */
+static size_t mark_goto(Vis*, File *txt, size_t pos);
+/* goto first non-blank char on line pointed by action.mark */
+static size_t mark_line_goto(Vis*, File *txt, size_t pos);
+/* goto to next occurence of action.key to the right */
+static size_t to(Vis*, Text *txt, size_t pos);
+/* goto to position before next occurence of action.key to the right */
+static size_t till(Vis*, Text *txt, size_t pos);
+/* goto to next occurence of action.key to the left */
+static size_t to_left(Vis*, Text *txt, size_t pos);
+/* goto to position after next occurence of action.key to the left */
+static size_t till_left(Vis*, Text *txt, size_t pos);
+/* goto line number action.count */
+static size_t line(Vis*, Text *txt, size_t pos);
+/* goto to byte action.count on current line */
+static size_t column(Vis*, Text *txt, size_t pos);
+/* goto the action.count-th line from top of the focused window */
+static size_t view_lines_top(Vis*, View*);
+/* goto the start of middle line of the focused window */
+static size_t view_lines_middle(Vis*, View*);
+/* goto the action.count-th line from bottom of the focused window */
+static size_t view_lines_bottom(Vis*, View*);
+/* navigate the change list */
+static size_t window_changelist_next(Vis*, Win*, size_t pos);
+static size_t window_changelist_prev(Vis*, Win*, size_t pos);
+/* navigate the jump list */
+static size_t window_jumplist_next(Vis*, Win*, size_t pos);
+static size_t window_jumplist_prev(Vis*, Win*, size_t pos);
+static size_t window_nop(Vis*, Win*, size_t pos);
+
+Movement moves[] = {
+ [MOVE_LINE_UP] = { .cur = view_line_up, .type = LINEWISE },
+ [MOVE_LINE_DOWN] = { .cur = view_line_down, .type = LINEWISE },
+ [MOVE_SCREEN_LINE_UP] = { .cur = view_screenline_up, },
+ [MOVE_SCREEN_LINE_DOWN] = { .cur = view_screenline_down, },
+ [MOVE_SCREEN_LINE_BEGIN] = { .cur = view_screenline_begin, .type = CHARWISE },
+ [MOVE_SCREEN_LINE_MIDDLE] = { .cur = view_screenline_middle, .type = CHARWISE },
+ [MOVE_SCREEN_LINE_END] = { .cur = view_screenline_end, .type = CHARWISE|INCLUSIVE },
+ [MOVE_LINE_PREV] = { .txt = text_line_prev, },
+ [MOVE_LINE_BEGIN] = { .txt = text_line_begin, },
+ [MOVE_LINE_START] = { .txt = text_line_start, },
+ [MOVE_LINE_FINISH] = { .txt = text_line_finish, .type = INCLUSIVE },
+ [MOVE_LINE_LASTCHAR] = { .txt = text_line_lastchar, .type = INCLUSIVE },
+ [MOVE_LINE_END] = { .txt = text_line_end, },
+ [MOVE_LINE_NEXT] = { .txt = text_line_next, },
+ [MOVE_LINE] = { .vis = line, .type = LINEWISE|IDEMPOTENT|JUMP},
+ [MOVE_COLUMN] = { .vis = column, .type = CHARWISE|IDEMPOTENT},
+ [MOVE_CHAR_PREV] = { .txt = text_char_prev, .type = CHARWISE },
+ [MOVE_CHAR_NEXT] = { .txt = text_char_next, .type = CHARWISE },
+ [MOVE_LINE_CHAR_PREV] = { .txt = text_line_char_prev, .type = CHARWISE },
+ [MOVE_LINE_CHAR_NEXT] = { .txt = text_line_char_next, .type = CHARWISE },
+ [MOVE_WORD_START_PREV] = { .txt = text_word_start_prev, .type = CHARWISE },
+ [MOVE_WORD_START_NEXT] = { .txt = text_word_start_next, .type = CHARWISE },
+ [MOVE_WORD_END_PREV] = { .txt = text_word_end_prev, .type = CHARWISE|INCLUSIVE },
+ [MOVE_WORD_END_NEXT] = { .txt = text_word_end_next, .type = CHARWISE|INCLUSIVE },
+ [MOVE_LONGWORD_START_PREV] = { .txt = text_longword_start_prev, .type = CHARWISE },
+ [MOVE_LONGWORD_START_NEXT] = { .txt = text_longword_start_next, .type = CHARWISE },
+ [MOVE_LONGWORD_END_PREV] = { .txt = text_longword_end_prev, .type = CHARWISE|INCLUSIVE },
+ [MOVE_LONGWORD_END_NEXT] = { .txt = text_longword_end_next, .type = CHARWISE|INCLUSIVE },
+ [MOVE_SENTENCE_PREV] = { .txt = text_sentence_prev, .type = LINEWISE },
+ [MOVE_SENTENCE_NEXT] = { .txt = text_sentence_next, .type = LINEWISE },
+ [MOVE_PARAGRAPH_PREV] = { .txt = text_paragraph_prev, .type = LINEWISE|JUMP },
+ [MOVE_PARAGRAPH_NEXT] = { .txt = text_paragraph_next, .type = LINEWISE|JUMP },
+ [MOVE_FUNCTION_START_PREV] = { .txt = text_function_start_prev, .type = LINEWISE|JUMP },
+ [MOVE_FUNCTION_START_NEXT] = { .txt = text_function_start_next, .type = LINEWISE|JUMP },
+ [MOVE_FUNCTION_END_PREV] = { .txt = text_function_end_prev, .type = LINEWISE|JUMP },
+ [MOVE_FUNCTION_END_NEXT] = { .txt = text_function_end_next, .type = LINEWISE|JUMP },
+ [MOVE_BRACKET_MATCH] = { .txt = text_bracket_match, .type = INCLUSIVE|JUMP },
+ [MOVE_FILE_BEGIN] = { .txt = text_begin, .type = LINEWISE|JUMP },
+ [MOVE_FILE_END] = { .txt = text_end, .type = LINEWISE|JUMP },
+ [MOVE_LEFT_TO] = { .vis = to_left, },
+ [MOVE_RIGHT_TO] = { .vis = to, .type = INCLUSIVE },
+ [MOVE_LEFT_TILL] = { .vis = till_left, },
+ [MOVE_RIGHT_TILL] = { .vis = till, .type = INCLUSIVE },
+ [MOVE_MARK] = { .file = mark_goto, .type = JUMP|IDEMPOTENT },
+ [MOVE_MARK_LINE] = { .file = mark_line_goto, .type = LINEWISE|JUMP|IDEMPOTENT},
+ [MOVE_SEARCH_WORD_FORWARD] = { .vis = search_word_forward, .type = JUMP },
+ [MOVE_SEARCH_WORD_BACKWARD]= { .vis = search_word_backward, .type = JUMP },
+ [MOVE_SEARCH_NEXT] = { .vis = search_forward, .type = JUMP },
+ [MOVE_SEARCH_PREV] = { .vis = search_backward, .type = JUMP },
+ [MOVE_WINDOW_LINE_TOP] = { .view = view_lines_top, .type = LINEWISE|JUMP|IDEMPOTENT },
+ [MOVE_WINDOW_LINE_MIDDLE] = { .view = view_lines_middle, .type = LINEWISE|JUMP|IDEMPOTENT },
+ [MOVE_WINDOW_LINE_BOTTOM] = { .view = view_lines_bottom, .type = LINEWISE|JUMP|IDEMPOTENT },
+ [MOVE_CHANGELIST_NEXT] = { .win = window_changelist_next, .type = INCLUSIVE },
+ [MOVE_CHANGELIST_PREV] = { .win = window_changelist_prev, .type = INCLUSIVE },
+ [MOVE_JUMPLIST_NEXT] = { .win = window_jumplist_next, .type = INCLUSIVE },
+ [MOVE_JUMPLIST_PREV] = { .win = window_jumplist_prev, .type = INCLUSIVE },
+ [MOVE_NOP] = { .win = window_nop, .type = IDEMPOTENT },
+};
+
+/** utility functions */
+
+static char *get_word_at(Text *txt, size_t pos) {
+ Filerange word = text_object_word(txt, pos);
+ if (!text_range_valid(&word))
+ return NULL;
+ size_t len = word.end - word.start;
+ char *buf = malloc(len+1);
+ if (!buf)
+ return NULL;
+ len = text_bytes_get(txt, word.start, len, buf);
+ buf[len] = '\0';
+ return buf;
+}
+
+/** movement implementations */
+
+static size_t search_word_forward(Vis *vis, Text *txt, size_t pos) {
+ char *word = get_word_at(txt, pos);
+ if (word && !text_regex_compile(vis->search_pattern, word, REG_EXTENDED))
+ pos = text_search_forward(txt, pos, vis->search_pattern);
+ free(word);
+ return pos;
+}
+
+static size_t search_word_backward(Vis *vis, Text *txt, size_t pos) {
+ char *word = get_word_at(txt, pos);
+ if (word && !text_regex_compile(vis->search_pattern, word, REG_EXTENDED))
+ pos = text_search_backward(txt, pos, vis->search_pattern);
+ free(word);
+ return pos;
+}
+
+static size_t search_forward(Vis *vis, Text *txt, size_t pos) {
+ return text_search_forward(txt, pos, vis->search_pattern);
+}
+
+static size_t search_backward(Vis *vis, Text *txt, size_t pos) {
+ return text_search_backward(txt, pos, vis->search_pattern);
+}
+
+static size_t mark_goto(Vis *vis, File *file, size_t pos) {
+ return text_mark_get(file->text, file->marks[vis->action.mark]);
+}
+
+static size_t mark_line_goto(Vis *vis, File *file, size_t pos) {
+ return text_line_start(file->text, mark_goto(vis, file, pos));
+}
+
+static size_t to(Vis *vis, Text *txt, size_t pos) {
+ char c;
+ size_t hit = text_line_find_next(txt, pos+1, vis->search_char);
+ if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
+ return pos;
+ return hit;
+}
+
+static size_t till(Vis *vis, Text *txt, size_t pos) {
+ size_t hit = to(vis, txt, pos);
+ if (hit != pos)
+ return text_char_prev(txt, hit);
+ return pos;
+}
+
+static size_t to_left(Vis *vis, Text *txt, size_t pos) {
+ char c;
+ if (pos == 0)
+ return pos;
+ size_t hit = text_line_find_prev(txt, pos-1, vis->search_char);
+ if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
+ return pos;
+ return hit;
+}
+
+static size_t till_left(Vis *vis, Text *txt, size_t pos) {
+ size_t hit = to_left(vis, txt, pos);
+ if (hit != pos)
+ return text_char_next(txt, hit);
+ return pos;
+}
+
+static size_t line(Vis *vis, Text *txt, size_t pos) {
+ return text_pos_by_lineno(txt, vis->action.count);
+}
+
+static size_t column(Vis *vis, Text *txt, size_t pos) {
+ return text_line_offset(txt, pos, vis->action.count);
+}
+
+static size_t view_lines_top(Vis *vis, View *view) {
+ return view_screenline_goto(view, vis->action.count);
+}
+
+static size_t view_lines_middle(Vis *vis, View *view) {
+ int h = view_height_get(view);
+ return view_screenline_goto(view, h/2);
+}
+
+static size_t view_lines_bottom(Vis *vis, View *view) {
+ int h = view_height_get(vis->win->view);
+ return view_screenline_goto(vis->win->view, h - vis->action.count);
+}
+
+static size_t window_changelist_next(Vis *vis, Win *win, size_t pos) {
+ ChangeList *cl = &win->changelist;
+ Text *txt = win->file->text;
+ time_t state = text_state(txt);
+ if (cl->state != state)
+ cl->index = 0;
+ else if (cl->index > 0 && pos == cl->pos)
+ cl->index--;
+ size_t newpos = text_history_get(txt, cl->index);
+ if (newpos == EPOS)
+ cl->index++;
+ else
+ cl->pos = newpos;
+ cl->state = state;
+ return cl->pos;
+}
+
+static size_t window_changelist_prev(Vis *vis, Win *win, size_t pos) {
+ ChangeList *cl = &win->changelist;
+ Text *txt = win->file->text;
+ time_t state = text_state(txt);
+ if (cl->state != state)
+ cl->index = 0;
+ else if (pos == cl->pos)
+ win->changelist.index++;
+ size_t newpos = text_history_get(txt, cl->index);
+ if (newpos == EPOS)
+ cl->index--;
+ else
+ cl->pos = newpos;
+ cl->state = state;
+ return cl->pos;
+}
+
+static size_t window_jumplist_next(Vis *vis, Win *win, size_t cur) {
+ while (win->jumplist) {
+ Mark mark = ringbuf_next(win->jumplist);
+ if (!mark)
+ return cur;
+ size_t pos = text_mark_get(win->file->text, mark);
+ if (pos != EPOS && pos != cur)
+ return pos;
+ }
+ return cur;
+}
+
+static size_t window_jumplist_prev(Vis *vis, Win *win, size_t cur) {
+ while (win->jumplist) {
+ Mark mark = ringbuf_prev(win->jumplist);
+ if (!mark)
+ return cur;
+ size_t pos = text_mark_get(win->file->text, mark);
+ if (pos != EPOS && pos != cur)
+ return pos;
+ }
+ return cur;
+}
+
+static size_t window_nop(Vis *vis, Win *win, size_t pos) {
+ return pos;
+}
+