diff options
| -rw-r--r-- | config.def.h | 1 | ||||
| -rw-r--r-- | text-motions.c | 25 | ||||
| -rw-r--r-- | text-motions.h | 19 | ||||
| -rw-r--r-- | vis.c | 8 |
4 files changed, 44 insertions, 9 deletions
diff --git a/config.def.h b/config.def.h index 6b70da1..035f7c9 100644 --- a/config.def.h +++ b/config.def.h @@ -125,6 +125,7 @@ static KeyBinding vis_movements[] = { { { NONE('w') }, movement, { .i = MOVE_LONGWORD_START_NEXT } }, { { NONE('W') }, movement, { .i = MOVE_LONGWORD_START_NEXT } }, { { NONE('g'), NONE('e') }, movement, { .i = MOVE_LONGWORD_END_PREV } }, + { { NONE('g'), NONE('E') }, movement, { .i = MOVE_LONGWORD_END_PREV } }, { { NONE('e') }, movement, { .i = MOVE_LONGWORD_END_NEXT } }, { { NONE('E') }, movement, { .i = MOVE_LONGWORD_END_NEXT } }, { { NONE('{') }, movement, { .i = MOVE_PARAGRAPH_PREV } }, diff --git a/text-motions.c b/text-motions.c index bee4a34..0d121fd 100644 --- a/text-motions.c +++ b/text-motions.c @@ -18,6 +18,13 @@ #include "text-motions.h" #include "util.h" +// TODO: specify this per file type? +static int is_word_boundry(int c) { + return !(('0' <= c && c <= '9') || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z')); +} + // TODO: consistent usage of iterators either char or byte based where appropriate. size_t text_begin(Text *txt, size_t pos) { @@ -154,6 +161,7 @@ size_t text_line_next(Text *txt, size_t pos) { size_t text_word_boundry_start_next(Text *txt, size_t pos, int (*isboundry)(int)) { char c; Iterator it = text_iterator_get(txt, pos); + text_iterator_byte_next(&it, NULL); while (text_iterator_byte_get(&it, &c) && !isboundry(c)) text_iterator_byte_next(&it, NULL); while (text_iterator_byte_get(&it, &c) && isboundry(c)) @@ -202,6 +210,23 @@ size_t text_longword_start_prev(Text *txt, size_t pos) { return text_word_boundry_start_prev(txt, pos, isspace); } +// TODO: this actually doesn't work that way -> rewrite +size_t text_word_end_next(Text *txt, size_t pos) { + return text_word_boundry_end_next(txt, pos, is_word_boundry); +} + +size_t text_word_end_prev(Text *txt, size_t pos) { + return text_word_boundry_end_prev(txt, pos, is_word_boundry); +} + +size_t text_word_start_next(Text *txt, size_t pos) { + return text_word_boundry_start_next(txt, pos, is_word_boundry); +} + +size_t text_word_start_prev(Text *txt, size_t pos) { + return text_word_boundry_start_prev(txt, pos, is_word_boundry); +} + static size_t text_paragraph_sentence_next(Text *txt, size_t pos, bool sentence) { char c; bool content = false, paragraph = false; diff --git a/text-motions.h b/text-motions.h index e182e2e..eb6ae8f 100644 --- a/text-motions.h +++ b/text-motions.h @@ -35,8 +35,8 @@ 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); /* - * A word consists of a sequence of non-blank characters, separated with white - * space. TODO?: An empty line is also considered to be a word. + * 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. * This is equivalant to a WORD in vim terminology. */ size_t text_longword_end_next(Text*, size_t pos); @@ -44,14 +44,15 @@ size_t text_longword_end_prev(Text*, size_t pos); size_t text_longword_start_next(Text*, size_t pos); size_t text_longword_start_prev(Text*, size_t pos); /* - * These are variants of the above with the additional possibility to implement - * a custom word detection logic. Can be used to implment the equivalent of a - * what vim reconizes as a word (lowercase). + * A word consists of a sequence of letters, digits and underscores, or a + * sequence of other non-blank characters, separated with white space. + * TODO?: An empty line is also considered to be a word. + * This is equivalant to a word (lowercase) in vim terminology. */ -size_t text_word_boundry_end_next(Text*, size_t pos, int (*isboundry)(int)); -size_t text_word_boundry_end_prev(Text*, size_t pos, int (*isboundry)(int)); -size_t text_word_boundry_start_next(Text*, size_t pos, int (*isboundry)(int)); -size_t text_word_boundry_start_prev(Text*, size_t pos, int (*isboundry)(int)); +size_t text_word_end_next(Text*, size_t pos); +size_t text_word_end_prev(Text*, size_t pos); +size_t text_word_start_next(Text*, size_t pos); +size_t text_word_start_prev(Text*, size_t pos); /* TODO: implement the following semantics * A sentence is defined as ending at a '.', '!' or '?' followed by either the * end of a line, or by a space or tab. Any number of closing ')', ']', '"' @@ -203,6 +203,10 @@ enum { MOVE_COLUMN, MOVE_CHAR_PREV, MOVE_CHAR_NEXT, + MOVE_WORD_START_NEXT, + MOVE_WORD_END_PREV, + MOVE_WORD_END_NEXT, + MOVE_WORD_START_PREV, MOVE_LONGWORD_START_PREV, MOVE_LONGWORD_START_NEXT, MOVE_LONGWORD_END_PREV, @@ -274,6 +278,10 @@ static Movement moves[] = { [MOVE_COLUMN] = { .cmd = column, .type = CHARWISE|IDEMPOTENT}, [MOVE_CHAR_PREV] = { .win = window_char_prev }, [MOVE_CHAR_NEXT] = { .win = window_char_next }, + [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 }, |
