summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Carbonneaux2014-11-17 13:52:44 -0500
committerQuentin Carbonneaux2014-11-17 13:55:53 -0500
commit14769dc6357f05fc18c9607515c2312d9b7905a1 (patch)
tree3cb86a7b84d6e6f44c6086d6f3fddf9f772733b0
parent6020f9b426d3d62bfdc897a986c00da65a59ccc5 (diff)
add reverse search command N
-rw-r--r--edit.c11
-rw-r--r--edit.h2
-rw-r--r--exec.c11
-rw-r--r--exec.h2
-rw-r--r--vicmd.w9
5 files changed, 18 insertions, 17 deletions
diff --git a/edit.c b/edit.c
index bb6b171..067d4f0 100644
--- a/edit.c
+++ b/edit.c
@@ -344,18 +344,19 @@ eb_getmark(EBuf *eb, Rune name)
}
unsigned
-eb_look(EBuf *eb, unsigned p, Rune *str, unsigned n)
+eb_look(EBuf *eb, unsigned p0, Rune *str, unsigned n, int rev)
{
- unsigned i, j;
+ unsigned i, j, l, x;
assert(str);
- while (p<eb->b.limbo) {
- i = p++;
+ l = eb->b.limbo;
+ for (x=1; x<l; x++) {
+ i = (p0 + (rev ? l-x : x)) % l;
j = 0;
while (buf_get(&eb->b, i++) == str[j++])
if (j == n)
- return p-1;
+ return i-n;
}
return -1u;
}
diff --git a/edit.h b/edit.h
index 0983020..752fa02 100644
--- a/edit.h
+++ b/edit.h
@@ -39,5 +39,5 @@ void eb_undo(EBuf *, int, unsigned *);
void eb_yank(EBuf *, unsigned, unsigned, YBuf *);
void eb_setmark(EBuf *, Rune, unsigned);
unsigned eb_getmark(EBuf *, Rune);
-unsigned eb_look(EBuf *, unsigned, Rune *, unsigned);
+unsigned eb_look(EBuf *, unsigned, Rune *, unsigned, int);
void eb_write(EBuf *, int);
diff --git a/exec.c b/exec.c
index da95c70..4e9e1b8 100644
--- a/exec.c
+++ b/exec.c
@@ -83,18 +83,17 @@ ex_run(W *w, unsigned p0)
/* ex_look - Look for a string [s] in window [w] and jump
* to the first match after the cursor position. The caller
- * is responsible to free the [s] buffer.
+ * is responsible to free the [s] buffer. If [rev] is true
+ * the search goes backward.
*/
int
-ex_look(W *w, Rune *s, unsigned n)
+ex_look(W *w, Rune *s, unsigned n, int rev)
{
unsigned p;
if (n == 0)
return 1;
- p = eb_look(w->eb, w->cu+1, s, n);
- if (p == -1u)
- p = eb_look(w->eb, 0, s, n);
+ p = eb_look(w->eb, w->cu, s, n, rev);
if (p != -1u) {
w->cu = p;
eb_setmark(w->eb, SelBeg, p);
@@ -351,7 +350,7 @@ look(W *w, EBuf *eb, unsigned p0)
return 0;
p1 = 1 + skipb(&eb->b, buf_eol(&eb->b, p0) - 1, -1);
eb_yank(eb, p0, p1, &b);
- e = ex_look(w, b.r, b.nr);
+ e = ex_look(w, b.r, b.nr, 0);
free(b.r);
if (e) {
err(eb, p0, errstr);
diff --git a/exec.h b/exec.h
index 1da01a3..677968d 100644
--- a/exec.h
+++ b/exec.h
@@ -1,5 +1,5 @@
int ex_run(W *, unsigned);
-int ex_look(W *, Rune *, unsigned);
+int ex_look(W *, Rune *, unsigned, int);
int ex_put(EBuf *, char *);
int ex_get(W *, char *);
void ex_cancel(Task *);
diff --git a/vicmd.w b/vicmd.w
index add0cba..4df8c66 100644
--- a/vicmd.w
+++ b/vicmd.w
@@ -858,7 +858,7 @@ the annonymous yank buffer. When a match is found the selection
is set to the matched text. If the search hits limbo it wraps around.
@<Subr...@>=
-static int m_n(int ismotion, Cmd c, Motion *m)
+static int m_nN(int ismotion, Cmd c, Motion *m)
{
YBuf b = {0, 0, 0, 0}, *pb = &yannon;
int err = 0;
@@ -869,7 +869,7 @@ static int m_n(int ismotion, Cmd c, Motion *m)
if (s0 < s1 && s0 != -1u && s1 != -1u)
eb_yank(curwin->eb, s0, s1, pb = &b);
while (c.count--)
- err |= ex_look(curwin, pb->r, pb->nr);
+ err |= ex_look(curwin, pb->r, pb->nr, c.chr == 'N');
free(b.r);
m->end = curwin->cu;
if (ismotion)
@@ -878,7 +878,7 @@ static int m_n(int ismotion, Cmd c, Motion *m)
}
@ @<Predecl...@>=
-static int m_n(int, Cmd, Motion *);
+static int m_nN(int, Cmd, Motion *);
@ Because the search functionality is different, the \./ command is free
to use. We reuse it as a motion that designates the whole selection.
@@ -1306,7 +1306,8 @@ union {
['%'] = Mtn(0, m_match), ['G'] = Mtn(CZeroCount, m_G),@/
['H'] = Mtn(0, m_HML), ['L'] = Mtn(0, m_HML),@/
['M'] = Mtn(0, m_HML),@/
-['n'] = Mtn(0, m_n), ['/'] = Mtn(0, m_sel),@/
+['n'] = Mtn(0, m_nN), ['N'] = Mtn(0, m_nN),@/
+['/'] = Mtn(0, m_sel),@/
['\''] = Mtn(CHasArg, m_mark), ['`'] = Mtn(CHasArg, m_mark),@/
['d'] = Act(CHasMotion, a_d), ['x'] = Act(0, a_d),@/
['c'] = Act(CHasMotion, a_c), ['y'] = Act(CHasMotion, a_y),@/