diff --git a/main.c b/main.c index 87ae64f1d..7dc7b65fd 100644 --- a/main.c +++ b/main.c @@ -1154,6 +1154,8 @@ static const char *key2register(Vis *vis, const char *keys, enum VisRegister *re *reg = VIS_REG_ZERO; else if (keys[0] == '@') *reg = VIS_MACRO_LAST_RECORDED; + else if (keys[0] == '/') + *reg = VIS_REG_SEARCH; return keys+1; } diff --git a/vis-cmds.c b/vis-cmds.c index 38c810fe7..0fb31dfdc 100644 --- a/vis-cmds.c +++ b/vis-cmds.c @@ -1177,13 +1177,10 @@ static Filepos parse_pos(Win *win, char **cmd) { if (!pattern_end) return EPOS; *pattern_end++ = '\0'; - Regex *regex = text_regex_new(); + Regex *regex = vis_regex(win->vis, *cmd); if (!regex) return EPOS; - if (!text_regex_compile(regex, *cmd, 0)) { - *cmd = pattern_end; - pos = text_search_forward(txt, view_cursor_get(view), regex); - } + pos = text_search_forward(txt, view_cursor_get(view), regex); text_regex_free(regex); break; case '+': diff --git a/vis-motions.c b/vis-motions.c index e62dc35c8..5bff026b7 100644 --- a/vis-motions.c +++ b/vis-motions.c @@ -9,44 +9,56 @@ /** utility functions */ -static bool search_word(Vis *vis, Text *txt, size_t pos) { +static Regex *search_word(Vis *vis, Text *txt, size_t pos) { char expr[512]; Filerange word = text_object_word(txt, pos); if (!text_range_valid(&word)) - return false; + return NULL; char *buf = text_bytes_alloc0(txt, word.start, text_range_size(&word)); if (!buf) - return false; + return NULL; snprintf(expr, sizeof(expr), "[[:<:]]%s[[:>:]]", buf); - bool ret = text_regex_compile(vis->search_pattern, expr, REG_EXTENDED) == 0; - if (!ret) { + Regex *regex = vis_regex(vis, expr); + if (!regex) { snprintf(expr, sizeof(expr), "\\<%s\\>", buf); - ret = text_regex_compile(vis->search_pattern, expr, REG_EXTENDED) == 0; + regex = vis_regex(vis, expr); } free(buf); - return ret; + return regex; } /** motion implementations */ static size_t search_word_forward(Vis *vis, Text *txt, size_t pos) { - if (search_word(vis, txt, pos)) - pos = text_search_forward(txt, pos, vis->search_pattern); + Regex *regex = search_word(vis, txt, pos); + if (regex) + pos = text_search_forward(txt, pos, regex); + text_regex_free(regex); return pos; } static size_t search_word_backward(Vis *vis, Text *txt, size_t pos) { - if (search_word(vis, txt, pos)) - pos = text_search_backward(txt, pos, vis->search_pattern); + Regex *regex = search_word(vis, txt, pos); + if (regex) + pos = text_search_backward(txt, pos, regex); + text_regex_free(regex); return pos; } static size_t search_forward(Vis *vis, Text *txt, size_t pos) { - return text_search_forward(txt, pos, vis->search_pattern); + Regex *regex = vis_regex(vis, NULL); + if (regex) + pos = text_search_forward(txt, pos, regex); + text_regex_free(regex); + return pos; } static size_t search_backward(Vis *vis, Text *txt, size_t pos) { - return text_search_backward(txt, pos, vis->search_pattern); + Regex *regex = vis_regex(vis, NULL); + if (regex) + pos = text_search_backward(txt, pos, regex); + text_regex_free(regex); + return pos; } static size_t mark_goto(Vis *vis, File *file, size_t pos) { @@ -245,10 +257,12 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) { case VIS_MOVE_SEARCH_BACKWARD: { const char *pattern = va_arg(ap, char*); - if (text_regex_compile(vis->search_pattern, pattern, REG_EXTENDED|REG_NEWLINE)) { + Regex *regex = vis_regex(vis, pattern); + if (!regex) { vis_cancel(vis); goto err; } + text_regex_free(regex); if (motion == VIS_MOVE_SEARCH_FORWARD) motion = VIS_MOVE_SEARCH_NEXT; else diff --git a/vis.c b/vis.c index 7bb5d6a8f..7c04347ba 100644 --- a/vis.c +++ b/vis.c @@ -1112,6 +1112,20 @@ void vis_insert_nl(Vis *vis) { copy_indent_from_previous_line(vis->win); } +Regex *vis_regex(Vis *vis, const char *pattern) { + if (!pattern && !(pattern = register_get(vis, &vis->registers[VIS_REG_SEARCH], NULL))) + return NULL; + Regex *regex = text_regex_new(); + if (!regex) + return NULL; + if (text_regex_compile(regex, pattern, REG_EXTENDED|REG_NEWLINE) != 0) { + text_regex_free(regex); + return NULL; + } + register_put(vis, &vis->registers[VIS_REG_SEARCH], pattern, strlen(pattern)+1); + return regex; +} + Text *vis_text(Vis *vis) { return vis->win->file->text; } diff --git a/vis.h b/vis.h index fad7ecad0..0bafe685e 100644 --- a/vis.h +++ b/vis.h @@ -11,6 +11,7 @@ typedef struct Win Win; #include "ui.h" #include "view.h" +#include "text-regex.h" typedef struct { void (*vis_start)(Vis*); @@ -351,6 +352,7 @@ enum VisRegister { VIS_REG_PROMPT, /* internal register which shadows DEFAULT in PROMPT mode */ VIS_MACRO_OPERATOR, /* records entered keys after an operator */ VIS_MACRO_REPEAT, /* copy of the above macro once the recording is finished */ + VIS_REG_SEARCH, VIS_REG_INVALID, /* has to be the last 'real' register */ VIS_REG_A, VIS_REG_B, VIS_REG_C, VIS_REG_D, VIS_REG_E, VIS_REG_F, VIS_REG_G, VIS_REG_H, VIS_REG_I, VIS_REG_J, @@ -412,6 +414,9 @@ bool vis_keys_inject(Vis*, const char *pos, const char *input); * was handled by vis */ bool vis_signal_handler(Vis*, int signum, const siginfo_t *siginfo, const void *context); +/* remember last search pattern, freeing the regex is the callers responsibility */ +Regex *vis_regex(Vis*, const char *pattern); + /* TODO: expose proper API to iterate through files etc */ Text *vis_text(Vis*); View *vis_view(Vis*);