aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2014-09-25 19:19:05 +0200
committerMarc André Tanner <mat@brain-dump.org>2014-09-25 19:19:05 +0200
commit62682f0d351890f3050b3251d5d26448bf922109 (patch)
treeea2b813f71abe6713308fe1a4675520b79e1247b
parent334e7f278f18889582c51bd9aceb469e716cddea (diff)
downloadvis-62682f0d351890f3050b3251d5d26448bf922109.tar.gz
vis-62682f0d351890f3050b3251d5d26448bf922109.tar.xz
Add infrastructure for word (lowercase) motions
This unfortunately doesn't work as is which is why it is not actually hooked up to key bindings.
-rw-r--r--config.def.h1
-rw-r--r--text-motions.c25
-rw-r--r--text-motions.h19
-rw-r--r--vis.c8
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 ')', ']', '"'
diff --git a/vis.c b/vis.c
index f933cee..16e7385 100644
--- a/vis.c
+++ b/vis.c
@@ -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 },