theme: add default low color theme
[vis.git] / vis-motions.c
blob754b132e63f6edc9a908e2017aa71f73cf12d9e2
1 #include <regex.h>
2 #include "vis-core.h"
3 #include "text-motions.h"
4 #include "text-objects.h"
5 #include "text-util.h"
7 /** utility functions */
9 static char *get_word_at(Text *txt, size_t pos) {
10 Filerange word = text_object_word(txt, pos);
11 if (!text_range_valid(&word))
12 return NULL;
13 size_t len = word.end - word.start;
14 char *buf = malloc(len+1);
15 if (!buf)
16 return NULL;
17 len = text_bytes_get(txt, word.start, len, buf);
18 buf[len] = '\0';
19 return buf;
22 /** motion implementations */
24 static size_t search_word_forward(Vis *vis, Text *txt, size_t pos) {
25 char *word = get_word_at(txt, pos);
26 if (word && !text_regex_compile(vis->search_pattern, word, REG_EXTENDED))
27 pos = text_search_forward(txt, pos, vis->search_pattern);
28 free(word);
29 return pos;
32 static size_t search_word_backward(Vis *vis, Text *txt, size_t pos) {
33 char *word = get_word_at(txt, pos);
34 if (word && !text_regex_compile(vis->search_pattern, word, REG_EXTENDED))
35 pos = text_search_backward(txt, pos, vis->search_pattern);
36 free(word);
37 return pos;
40 static size_t search_forward(Vis *vis, Text *txt, size_t pos) {
41 return text_search_forward(txt, pos, vis->search_pattern);
44 static size_t search_backward(Vis *vis, Text *txt, size_t pos) {
45 return text_search_backward(txt, pos, vis->search_pattern);
48 static size_t mark_goto(Vis *vis, File *file, size_t pos) {
49 return text_mark_get(file->text, file->marks[vis->action.mark]);
52 static size_t mark_line_goto(Vis *vis, File *file, size_t pos) {
53 return text_line_start(file->text, mark_goto(vis, file, pos));
56 static size_t to(Vis *vis, Text *txt, size_t pos) {
57 char c;
58 size_t hit = text_line_find_next(txt, pos+1, vis->search_char);
59 if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
60 return pos;
61 return hit;
64 static size_t till(Vis *vis, Text *txt, size_t pos) {
65 size_t hit = to(vis, txt, pos);
66 if (hit != pos)
67 return text_char_prev(txt, hit);
68 return pos;
71 static size_t to_left(Vis *vis, Text *txt, size_t pos) {
72 char c;
73 if (pos == 0)
74 return pos;
75 size_t hit = text_line_find_prev(txt, pos-1, vis->search_char);
76 if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
77 return pos;
78 return hit;
81 static size_t till_left(Vis *vis, Text *txt, size_t pos) {
82 size_t hit = to_left(vis, txt, pos);
83 if (hit != pos)
84 return text_char_next(txt, hit);
85 return pos;
88 static size_t line(Vis *vis, Text *txt, size_t pos) {
89 return text_pos_by_lineno(txt, vis->action.count);
92 static size_t column(Vis *vis, Text *txt, size_t pos) {
93 return text_line_offset(txt, pos, vis->action.count);
96 static size_t view_lines_top(Vis *vis, View *view) {
97 return view_screenline_goto(view, vis->action.count);
100 static size_t view_lines_middle(Vis *vis, View *view) {
101 int h = view_height_get(view);
102 return view_screenline_goto(view, h/2);
105 static size_t view_lines_bottom(Vis *vis, View *view) {
106 int h = view_height_get(vis->win->view);
107 return view_screenline_goto(vis->win->view, h - vis->action.count);
110 static size_t window_changelist_next(Vis *vis, Win *win, size_t pos) {
111 ChangeList *cl = &win->changelist;
112 Text *txt = win->file->text;
113 time_t state = text_state(txt);
114 if (cl->state != state)
115 cl->index = 0;
116 else if (cl->index > 0 && pos == cl->pos)
117 cl->index--;
118 size_t newpos = text_history_get(txt, cl->index);
119 if (newpos == EPOS)
120 cl->index++;
121 else
122 cl->pos = newpos;
123 cl->state = state;
124 return cl->pos;
127 static size_t window_changelist_prev(Vis *vis, Win *win, size_t pos) {
128 ChangeList *cl = &win->changelist;
129 Text *txt = win->file->text;
130 time_t state = text_state(txt);
131 if (cl->state != state)
132 cl->index = 0;
133 else if (pos == cl->pos)
134 win->changelist.index++;
135 size_t newpos = text_history_get(txt, cl->index);
136 if (newpos == EPOS)
137 cl->index--;
138 else
139 cl->pos = newpos;
140 cl->state = state;
141 return cl->pos;
144 static size_t window_jumplist_next(Vis *vis, Win *win, size_t cur) {
145 while (win->jumplist) {
146 Mark mark = ringbuf_next(win->jumplist);
147 if (!mark)
148 return cur;
149 size_t pos = text_mark_get(win->file->text, mark);
150 if (pos != EPOS && pos != cur)
151 return pos;
153 return cur;
156 static size_t window_jumplist_prev(Vis *vis, Win *win, size_t cur) {
157 while (win->jumplist) {
158 Mark mark = ringbuf_prev(win->jumplist);
159 if (!mark)
160 return cur;
161 size_t pos = text_mark_get(win->file->text, mark);
162 if (pos != EPOS && pos != cur)
163 return pos;
165 return cur;
168 static size_t window_nop(Vis *vis, Win *win, size_t pos) {
169 return pos;
172 Movement moves[] = {
173 [VIS_MOVE_LINE_UP] = { .cur = view_line_up, .type = LINEWISE },
174 [VIS_MOVE_LINE_DOWN] = { .cur = view_line_down, .type = LINEWISE },
175 [VIS_MOVE_SCREEN_LINE_UP] = { .cur = view_screenline_up, },
176 [VIS_MOVE_SCREEN_LINE_DOWN] = { .cur = view_screenline_down, },
177 [VIS_MOVE_SCREEN_LINE_BEGIN] = { .cur = view_screenline_begin, .type = CHARWISE },
178 [VIS_MOVE_SCREEN_LINE_MIDDLE] = { .cur = view_screenline_middle, .type = CHARWISE },
179 [VIS_MOVE_SCREEN_LINE_END] = { .cur = view_screenline_end, .type = CHARWISE|INCLUSIVE },
180 [VIS_MOVE_LINE_PREV] = { .txt = text_line_prev, },
181 [VIS_MOVE_LINE_BEGIN] = { .txt = text_line_begin, },
182 [VIS_MOVE_LINE_START] = { .txt = text_line_start, },
183 [VIS_MOVE_LINE_FINISH] = { .txt = text_line_finish, .type = INCLUSIVE },
184 [VIS_MOVE_LINE_LASTCHAR] = { .txt = text_line_lastchar, .type = INCLUSIVE },
185 [VIS_MOVE_LINE_END] = { .txt = text_line_end, },
186 [VIS_MOVE_LINE_NEXT] = { .txt = text_line_next, },
187 [VIS_MOVE_LINE] = { .vis = line, .type = LINEWISE|IDEMPOTENT|JUMP },
188 [VIS_MOVE_COLUMN] = { .vis = column, .type = CHARWISE|IDEMPOTENT },
189 [VIS_MOVE_CHAR_PREV] = { .txt = text_char_prev, .type = CHARWISE },
190 [VIS_MOVE_CHAR_NEXT] = { .txt = text_char_next, .type = CHARWISE },
191 [VIS_MOVE_LINE_CHAR_PREV] = { .txt = text_line_char_prev, .type = CHARWISE },
192 [VIS_MOVE_LINE_CHAR_NEXT] = { .txt = text_line_char_next, .type = CHARWISE },
193 [VIS_MOVE_WORD_START_PREV] = { .txt = text_word_start_prev, .type = CHARWISE },
194 [VIS_MOVE_WORD_START_NEXT] = { .txt = text_word_start_next, .type = CHARWISE },
195 [VIS_MOVE_WORD_END_PREV] = { .txt = text_word_end_prev, .type = CHARWISE|INCLUSIVE },
196 [VIS_MOVE_WORD_END_NEXT] = { .txt = text_word_end_next, .type = CHARWISE|INCLUSIVE },
197 [VIS_MOVE_LONGWORD_START_PREV] = { .txt = text_longword_start_prev, .type = CHARWISE },
198 [VIS_MOVE_LONGWORD_START_NEXT] = { .txt = text_longword_start_next, .type = CHARWISE },
199 [VIS_MOVE_LONGWORD_END_PREV] = { .txt = text_longword_end_prev, .type = CHARWISE|INCLUSIVE },
200 [VIS_MOVE_LONGWORD_END_NEXT] = { .txt = text_longword_end_next, .type = CHARWISE|INCLUSIVE },
201 [VIS_MOVE_SENTENCE_PREV] = { .txt = text_sentence_prev, .type = LINEWISE },
202 [VIS_MOVE_SENTENCE_NEXT] = { .txt = text_sentence_next, .type = LINEWISE },
203 [VIS_MOVE_PARAGRAPH_PREV] = { .txt = text_paragraph_prev, .type = LINEWISE|JUMP },
204 [VIS_MOVE_PARAGRAPH_NEXT] = { .txt = text_paragraph_next, .type = LINEWISE|JUMP },
205 [VIS_MOVE_FUNCTION_START_PREV] = { .txt = text_function_start_prev, .type = LINEWISE|JUMP },
206 [VIS_MOVE_FUNCTION_START_NEXT] = { .txt = text_function_start_next, .type = LINEWISE|JUMP },
207 [VIS_MOVE_FUNCTION_END_PREV] = { .txt = text_function_end_prev, .type = LINEWISE|JUMP },
208 [VIS_MOVE_FUNCTION_END_NEXT] = { .txt = text_function_end_next, .type = LINEWISE|JUMP },
209 [VIS_MOVE_BRACKET_MATCH] = { .txt = text_bracket_match, .type = INCLUSIVE|JUMP },
210 [VIS_MOVE_FILE_BEGIN] = { .txt = text_begin, .type = LINEWISE|JUMP },
211 [VIS_MOVE_FILE_END] = { .txt = text_end, .type = LINEWISE|JUMP },
212 [VIS_MOVE_LEFT_TO] = { .vis = to_left, },
213 [VIS_MOVE_RIGHT_TO] = { .vis = to, .type = INCLUSIVE },
214 [VIS_MOVE_LEFT_TILL] = { .vis = till_left, },
215 [VIS_MOVE_RIGHT_TILL] = { .vis = till, .type = INCLUSIVE },
216 [VIS_MOVE_MARK] = { .file = mark_goto, .type = JUMP|IDEMPOTENT },
217 [VIS_MOVE_MARK_LINE] = { .file = mark_line_goto, .type = LINEWISE|JUMP|IDEMPOTENT },
218 [VIS_MOVE_SEARCH_WORD_FORWARD] = { .vis = search_word_forward, .type = JUMP },
219 [VIS_MOVE_SEARCH_WORD_BACKWARD]= { .vis = search_word_backward, .type = JUMP },
220 [VIS_MOVE_SEARCH_NEXT] = { .vis = search_forward, .type = JUMP },
221 [VIS_MOVE_SEARCH_PREV] = { .vis = search_backward, .type = JUMP },
222 [VIS_MOVE_WINDOW_LINE_TOP] = { .view = view_lines_top, .type = LINEWISE|JUMP|IDEMPOTENT },
223 [VIS_MOVE_WINDOW_LINE_MIDDLE] = { .view = view_lines_middle, .type = LINEWISE|JUMP|IDEMPOTENT },
224 [VIS_MOVE_WINDOW_LINE_BOTTOM] = { .view = view_lines_bottom, .type = LINEWISE|JUMP|IDEMPOTENT },
225 [VIS_MOVE_CHANGELIST_NEXT] = { .win = window_changelist_next, .type = INCLUSIVE },
226 [VIS_MOVE_CHANGELIST_PREV] = { .win = window_changelist_prev, .type = INCLUSIVE },
227 [VIS_MOVE_JUMPLIST_NEXT] = { .win = window_jumplist_next, .type = INCLUSIVE },
228 [VIS_MOVE_JUMPLIST_PREV] = { .win = window_jumplist_prev, .type = INCLUSIVE },
229 [VIS_MOVE_NOP] = { .win = window_nop, .type = IDEMPOTENT },