Skip to content

Commit

Permalink
Distinct between inner and outer word text objects
Browse files Browse the repository at this point in the history
  • Loading branch information
martanne committed Dec 23, 2014
1 parent 3314a28 commit 985a828
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ and their current support in vis.
p paragraph
[,], (,), {,}, <,>, ", ', ` block enclosed by these symbols

For word, sentence and paragraph there is no difference between the
For sentence and paragraph there is no difference between the
inner and normal variants.

Modes
Expand Down
8 changes: 4 additions & 4 deletions config.def.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ static KeyBinding vis_movements[] = {
};

static KeyBinding vis_textobjs[] = {
{ { NONE('a'), NONE('w') }, textobj, { .i = TEXT_OBJ_WORD } },
{ { NONE('a'), NONE('W') }, textobj, { .i = TEXT_OBJ_LONGWORD } },
{ { NONE('a'), NONE('w') }, textobj, { .i = TEXT_OBJ_OUTER_WORD } },
{ { NONE('a'), NONE('W') }, textobj, { .i = TEXT_OBJ_OUTER_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 } },
Expand All @@ -181,8 +181,8 @@ static KeyBinding vis_textobjs[] = {
};

static KeyBinding vis_inner_textobjs[] = {
{ { NONE('i'), NONE('w') }, textobj, { .i = TEXT_OBJ_WORD } },
{ { NONE('i'), NONE('W') }, textobj, { .i = TEXT_OBJ_LONGWORD } },
{ { NONE('i'), NONE('w') }, textobj, { .i = TEXT_OBJ_INNER_WORD } },
{ { NONE('i'), NONE('W') }, textobj, { .i = TEXT_OBJ_INNER_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 } },
Expand Down
84 changes: 78 additions & 6 deletions text-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,44 @@
#include "text-objects.h"
#include "util.h"

#define isboundry is_word_boundry

/* TODO: reduce code duplication? */

Filerange text_object_longword(Text *txt, size_t pos) {
Filerange r;
char c, prev = '0', next = '0';
Iterator it = text_iterator_get(txt, pos);
if (!text_iterator_byte_get(&it, &c))
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)) {
/* middle of two words */
r.start = text_char_next(txt, text_longword_end_prev(txt, pos));
r.end = text_longword_start_next(txt, pos);
} else if (isspace(prev) && isspace(next)) {
/* on a single character */
r.start = pos;
r.end = text_char_next(txt, pos);
} else if (isspace(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)) {
/* at end of a word */
r.start = text_longword_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));
}
return r;
}

Filerange text_object_longword_outer(Text *txt, size_t pos) {
Filerange r;
char c, prev = '0', next = '0';
Iterator it = text_iterator_get(txt, pos);
Expand Down Expand Up @@ -52,7 +89,6 @@ Filerange text_object_longword(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';
Iterator it = text_iterator_get(txt, pos);
Expand All @@ -62,14 +98,11 @@ Filerange text_object_word(Text *txt, size_t pos) {
text_iterator_byte_next(&it, NULL);
text_iterator_byte_next(&it, &next);
if (isspace(c)) {
/* 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);
r.end = text_word_start_next(txt, pos);
} else if (isboundry(prev) && isboundry(next)) {
if (isboundry(c)) {
r.start = text_word_end_prev(txt, pos);
r.start = text_char_next(txt, text_word_end_prev(txt, pos));
r.end = text_char_next(txt, text_word_end_next(txt, pos));
} else {
/* on a single character */
Expand All @@ -93,6 +126,45 @@ Filerange text_object_word(Text *txt, size_t pos) {
return r;
}

Filerange text_object_word_outer(Text *txt, size_t pos) {
Filerange r;
char c, prev = '0', next = '0';
Iterator it = text_iterator_get(txt, pos);
if (!text_iterator_byte_get(&it, &c))
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)) {
/* 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);
} else if (isboundry(prev) && isboundry(next)) {
if (isboundry(c)) {
r.start = text_char_next(txt, text_word_end_prev(txt, pos));
r.end = text_word_start_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_word_start_next(txt, text_word_end_next(txt, pos));
} else if (isboundry(next)) {
/* at end of a word */
r.start = text_word_start_prev(txt, pos);
r.end = text_word_start_next(txt, pos);
} else {
/* in the middle of a word */
r.start = text_word_start_prev(txt, pos);
r.end = text_word_start_next(txt, text_word_end_next(txt, pos));
}

return r;
}

Filerange text_object_line(Text *txt, size_t pos) {
Filerange r;
r.start = text_line_begin(txt, pos);
Expand Down
11 changes: 7 additions & 4 deletions text-objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
#include <stddef.h>
#include "text.h"

/* word which happens to be at pos, includes trailing white spaces. if at pos
* happens to be a whitespace include all neighbouring leading whitespaces
* and the following word. */
/* word which happens to be at pos without any neighbouring white spaces */
Filerange text_object_word(Text*, size_t pos);
/* same semantics as above but for a longword (i.e. delimited by whitespaces) */
/* includes trailing white spaces. if at pos happens to be a white space
* include all neighbouring leading white spaces and the following word. */
Filerange text_object_word_outer(Text*, size_t pos);
/* same semantics as above but for a longword (i.e. delimited by white spaces) */
Filerange text_object_longword(Text*, size_t pos);
Filerange text_object_longword_outer(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);
Expand Down
12 changes: 8 additions & 4 deletions vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,10 @@ 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_INNER_WORD,
TEXT_OBJ_OUTER_WORD,
TEXT_OBJ_INNER_LONGWORD,
TEXT_OBJ_OUTER_LONGWORD,
TEXT_OBJ_LINE_UP,
TEXT_OBJ_LINE_DOWN,
TEXT_OBJ_SENTENCE,
Expand All @@ -346,8 +348,10 @@ enum {
};

static TextObject textobjs[] = {
[TEXT_OBJ_WORD] = { text_object_word },
[TEXT_OBJ_LONGWORD] = { text_object_longword },
[TEXT_OBJ_INNER_WORD] = { text_object_word },
[TEXT_OBJ_OUTER_WORD] = { text_object_word_outer },
[TEXT_OBJ_INNER_LONGWORD] = { text_object_longword },
[TEXT_OBJ_OUTER_LONGWORD] = { text_object_longword_outer },
[TEXT_OBJ_LINE_UP] = { text_object_line },
[TEXT_OBJ_LINE_DOWN] = { text_object_line },
[TEXT_OBJ_SENTENCE] = { text_object_sentence },
Expand Down

0 comments on commit 985a828

Please sign in to comment.