From c034be42821637990ac1d4c0f0329be0e98f70b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Sat, 27 Sep 2014 17:12:40 +0200 Subject: Add text objects for word (lowercase) variant --- config.def.h | 6 ++++-- text-motions.c | 2 +- text-motions.h | 3 +++ text-objects.c | 40 +++++++++++++++++++++++++--------------- text-objects.h | 5 ++--- vis.c | 4 +++- 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/config.def.h b/config.def.h index 655442d..87bff1f 100644 --- a/config.def.h +++ b/config.def.h @@ -155,7 +155,8 @@ static KeyBinding vis_movements[] = { }; static KeyBinding vis_textobjs[] = { - { { NONE('a'), NONE('w') }, textobj, { .i = TEXT_OBJ_LONGWORD } }, + { { NONE('a'), NONE('w') }, textobj, { .i = TEXT_OBJ_WORD } }, + { { NONE('a'), NONE('W') }, textobj, { .i = TEXT_OBJ_LONGWORD } }, { { NONE('a'), NONE('s') }, textobj, { .i = TEXT_OBJ_SENTENCE } }, { { NONE('a'), NONE('p') }, textobj, { .i = TEXT_OBJ_PARAGRAPH } }, { { NONE('a'), NONE('[') }, textobj, { .i = TEXT_OBJ_OUTER_SQUARE_BRACKET } }, @@ -175,7 +176,8 @@ static KeyBinding vis_textobjs[] = { }; static KeyBinding vis_inner_textobjs[] = { - { { NONE('i'), NONE('w') }, textobj, { .i = TEXT_OBJ_LONGWORD } }, + { { NONE('i'), NONE('w') }, textobj, { .i = TEXT_OBJ_WORD } }, + { { NONE('i'), NONE('W') }, textobj, { .i = TEXT_OBJ_LONGWORD } }, { { NONE('i'), NONE('s') }, textobj, { .i = TEXT_OBJ_SENTENCE } }, { { NONE('i'), NONE('p') }, textobj, { .i = TEXT_OBJ_PARAGRAPH } }, { { NONE('i'), NONE('[') }, textobj, { .i = TEXT_OBJ_INNER_SQUARE_BRACKET } }, diff --git a/text-motions.c b/text-motions.c index 3dbd4c5..8462fff 100644 --- a/text-motions.c +++ b/text-motions.c @@ -19,7 +19,7 @@ #include "util.h" // TODO: specify this per file type? -static int is_word_boundry(int c) { +int is_word_boundry(int c) { return ISASCII(c) && !(('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')); diff --git a/text-motions.h b/text-motions.h index eb6ae8f..e69a073 100644 --- a/text-motions.h +++ b/text-motions.h @@ -81,4 +81,7 @@ size_t text_bracket_match(Text*, size_t pos); size_t text_search_forward(Text *txt, size_t pos, Regex *regex); size_t text_search_backward(Text *txt, size_t pos, Regex *regex); +/* is c a special symbol delimiting a word? */ +int is_word_boundry(int c); + #endif diff --git a/text-objects.c b/text-objects.c index c37c233..a8aef0a 100644 --- a/text-objects.c +++ b/text-objects.c @@ -18,7 +18,7 @@ #include "text-objects.h" #include "util.h" -Filerange text_object_word(Text *txt, size_t pos) { +Filerange text_object_longword(Text *txt, size_t pos) { Filerange r; char c, prev = '0', next = '0'; Iterator it = text_iterator_get(txt, pos); @@ -51,33 +51,43 @@ Filerange text_object_word(Text *txt, size_t pos) { return r; } -Filerange text_object_longword_raw(Text *txt, size_t pos) { +Filerange text_object_word(Text *txt, size_t pos) { + #define isboundry is_word_boundry + Filerange r; char c, prev = '0', next = '0'; - Filerange r = text_range_empty(); Iterator it = text_iterator_get(txt, pos); if (!text_iterator_byte_get(&it, &c)) - return r; + return text_range_empty(); if (text_iterator_byte_prev(&it, &prev)) text_iterator_byte_next(&it, NULL); text_iterator_byte_next(&it, &next); if (isspace(c)) { - return r; - } else if (isspace(prev) && isspace(next)) { - /* on a single character */ - r.start = pos; - r.end = text_char_next(txt, pos); - } else if (isspace(prev)) { + /* middle of two words, include leading white space */ + r.start = text_char_next(txt, text_word_end_prev(txt, pos)); + r.end = text_word_end_next(txt, pos); + if (!text_byte_get(txt, r.end, &c) && !isboundry(c)) + r.end = text_char_next(txt, r.end); + } else if (isboundry(prev) && isboundry(next)) { + if (isboundry(c)) { + r.start = text_word_end_prev(txt, pos); + r.end = text_char_next(txt, text_word_end_next(txt, pos)); + } else { + /* on a single character */ + r.start = pos; + r.end = text_char_next(txt, pos); + } + } else if (isboundry(prev)) { /* at start of a word */ r.start = pos; - r.end = text_char_next(txt, text_longword_end_next(txt, pos)); - } else if (isspace(next)) { + r.end = text_char_next(txt, text_word_end_next(txt, pos)); + } else if (isboundry(next)) { /* at end of a word */ - r.start = text_longword_start_prev(txt, pos); + r.start = text_word_start_prev(txt, pos); r.end = text_char_next(txt, pos); } else { /* in the middle of a word */ - r.start = text_longword_start_prev(txt, pos); - r.end = text_char_next(txt, text_longword_end_next(txt, pos)); + r.start = text_word_start_prev(txt, pos); + r.end = text_char_next(txt, text_word_end_next(txt, pos)); } return r; diff --git a/text-objects.h b/text-objects.h index 2a37090..cb11f41 100644 --- a/text-objects.h +++ b/text-objects.h @@ -13,9 +13,8 @@ * happens to be a whitespace include all neighbouring leading whitespaces * and the following word. */ Filerange text_object_word(Text*, size_t pos); -/* word which happens to be at pos, _not_ including any white spaces. if pos - * is not part of a word, an empty range is returned */ -Filerange text_object_longword_raw(Text*, size_t pos); +/* same semantics as above but for a longword (i.e. delimited by whitespaces) */ +Filerange text_object_longword(Text*, size_t pos); Filerange text_object_line(Text*, size_t pos); Filerange text_object_sentence(Text*, size_t pos); Filerange text_object_paragraph(Text*, size_t pos); diff --git a/vis.c b/vis.c index a700166..58cf0a3 100644 --- a/vis.c +++ b/vis.c @@ -309,6 +309,7 @@ static Movement moves[] = { /* these can be passed as int argument to textobj(&(const Arg){ .i = TEXT_OBJ_* }) */ enum { + TEXT_OBJ_WORD, TEXT_OBJ_LONGWORD, TEXT_OBJ_LINE_UP, TEXT_OBJ_LINE_DOWN, @@ -331,7 +332,8 @@ enum { }; static TextObject textobjs[] = { - [TEXT_OBJ_LONGWORD] = { text_object_word }, + [TEXT_OBJ_WORD] = { text_object_word }, + [TEXT_OBJ_LONGWORD] = { text_object_longword }, [TEXT_OBJ_LINE_UP] = { text_object_line }, [TEXT_OBJ_LINE_DOWN] = { text_object_line }, [TEXT_OBJ_SENTENCE] = { text_object_sentence }, -- cgit v1.2.3