diff options
Diffstat (limited to 'src/nvim/search.c')
-rw-r--r-- | src/nvim/search.c | 192 |
1 files changed, 65 insertions, 127 deletions
diff --git a/src/nvim/search.c b/src/nvim/search.c index a758e02105..8ba888841c 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -79,23 +79,6 @@ * Henry Spencer's regular expression library. See regexp.c. */ -/* The offset for a search command is store in a soff struct */ -/* Note: only spats[0].off is really used */ -struct soffset { - int dir; /* search direction, '/' or '?' */ - int line; /* search has line offset */ - int end; /* search set cursor at end */ - long off; /* line or char offset */ -}; - -/* A search pattern and its attributes are stored in a spat struct */ -struct spat { - char_u *pat; /* the pattern (in allocated memory) or NULL */ - int magic; /* magicness of the pattern */ - int no_scs; /* no smartcase for this pattern */ - struct soffset off; -}; - /* * Two search patterns are remembered: One for the :substitute command and * one for other searches. last_idx points to the one that was used the last @@ -103,8 +86,10 @@ struct spat { */ static struct spat spats[2] = { - {NULL, TRUE, FALSE, {'/', 0, 0, 0L}}, /* last used search pat */ - {NULL, TRUE, FALSE, {'/', 0, 0, 0L}} /* last used substitute pat */ + // Last used search pattern + [0] = {NULL, true, false, 0, {'/', false, false, 0L}, NULL}, + // Last used substitute pattern + [1] = {NULL, true, false, 0, {'/', false, false, 0L}, NULL} }; static int last_idx = 0; /* index in spats[] for RE_LAST */ @@ -256,10 +241,12 @@ char_u *reverse_text(char_u *s) FUNC_ATTR_NONNULL_RET void save_re_pat(int idx, char_u *pat, int magic) { if (spats[idx].pat != pat) { - xfree(spats[idx].pat); + free_spat(&spats[idx]); spats[idx].pat = vim_strsave(pat); spats[idx].magic = magic; spats[idx].no_scs = no_smartcase; + spats[idx].timestamp = os_time(); + spats[idx].additional_data = NULL; last_idx = idx; /* If 'hlsearch' set and search pat changed: need redraw. */ if (p_hls) @@ -291,21 +278,29 @@ void save_search_patterns(void) void restore_search_patterns(void) { if (--save_level == 0) { - xfree(spats[0].pat); + free_spat(&spats[0]); spats[0] = saved_spats[0]; set_vv_searchforward(); - xfree(spats[1].pat); + free_spat(&spats[1]); spats[1] = saved_spats[1]; last_idx = saved_last_idx; SET_NO_HLSEARCH(saved_no_hlsearch); } } +static inline void free_spat(struct spat *const spat) +{ + xfree(spat->pat); + dict_unref(spat->additional_data); +} + #if defined(EXITFREE) void free_search_patterns(void) { - xfree(spats[0].pat); - xfree(spats[1].pat); + free_spat(&spats[0]); + free_spat(&spats[1]); + + memset(spats, 0, sizeof(spats)); if (mr_pattern_alloced) { xfree(mr_pattern); @@ -414,17 +409,19 @@ void reset_search_dir(void) } /* - * Set the last search pattern. For ":let @/ =" and viminfo. + * Set the last search pattern. For ":let @/ =" and ShaDa file. * Also set the saved search pattern, so that this works in an autocommand. */ void set_last_search_pat(const char_u *s, int idx, int magic, int setlast) { - xfree(spats[idx].pat); + free_spat(&spats[idx]); /* An empty string means that nothing should be matched. */ if (*s == NUL) spats[idx].pat = NULL; else spats[idx].pat = (char_u *) xstrdup((char *) s); + spats[idx].timestamp = os_time(); + spats[idx].additional_data = NULL; spats[idx].magic = magic; spats[idx].no_scs = FALSE; spats[idx].off.dir = '/'; @@ -435,7 +432,7 @@ void set_last_search_pat(const char_u *s, int idx, int magic, int setlast) if (setlast) last_idx = idx; if (save_level) { - xfree(saved_spats[idx].pat); + free_spat(&saved_spats[idx]); saved_spats[idx] = spats[0]; if (spats[idx].pat == NULL) saved_spats[idx].pat = NULL; @@ -1053,7 +1050,7 @@ int do_search( else if ((options & SEARCH_OPT) && (*p == 'e' || *p == 's' || *p == 'b')) { if (*p == 'e') /* end */ - spats[0].off.end = SEARCH_END; + spats[0].off.end = true; ++p; } if (ascii_isdigit(*p) || *p == '+' || *p == '-') { /* got an offset */ @@ -1166,12 +1163,13 @@ int do_search( lrFswap(searchstr,0); c = searchit(curwin, curbuf, &pos, dirc == '/' ? FORWARD : BACKWARD, - searchstr, count, spats[0].off.end + (options & - (SEARCH_KEEP + SEARCH_PEEK + - SEARCH_HIS - + SEARCH_MSG + SEARCH_START - + ((pat != NULL && *pat == - ';') ? 0 : SEARCH_NOOF))), + searchstr, count, (spats[0].off.end * SEARCH_END + + (options & + (SEARCH_KEEP + SEARCH_PEEK + + SEARCH_HIS + + SEARCH_MSG + SEARCH_START + + ((pat != NULL && *pat == + ';') ? 0 : SEARCH_NOOF)))), RE_LAST, (linenr_T)0, tm); if (dircp != NULL) @@ -4605,105 +4603,45 @@ static void show_pat_in_path(char_u *line, int type, int did_show, int action, F } } -int read_viminfo_search_pattern(vir_T *virp, int force) +/// Get last search pattern +void get_search_pattern(SearchPattern *const pat) { - char_u *lp; - int idx = -1; - int magic = FALSE; - int no_scs = FALSE; - int off_line = FALSE; - int off_end = 0; - long off = 0; - int setlast = FALSE; - static int hlsearch_on = FALSE; - char_u *val; + memcpy(pat, &(spats[0]), sizeof(spats[0])); +} - /* - * Old line types: - * "/pat", "&pat": search/subst. pat - * "~/pat", "~&pat": last used search/subst. pat - * New line types: - * "~h", "~H": hlsearch highlighting off/on - * "~<magic><smartcase><line><end><off><last><which>pat" - * <magic>: 'm' off, 'M' on - * <smartcase>: 's' off, 'S' on - * <line>: 'L' line offset, 'l' char offset - * <end>: 'E' from end, 'e' from start - * <off>: decimal, offset - * <last>: '~' last used pattern - * <which>: '/' search pat, '&' subst. pat - */ - lp = virp->vir_line; - if (lp[0] == '~' && (lp[1] == 'm' || lp[1] == 'M')) { /* new line type */ - if (lp[1] == 'M') /* magic on */ - magic = TRUE; - if (lp[2] == 's') - no_scs = TRUE; - if (lp[3] == 'L') - off_line = TRUE; - if (lp[4] == 'E') - off_end = SEARCH_END; - lp += 5; - off = getdigits_long(&lp); - } - if (lp[0] == '~') { /* use this pattern for last-used pattern */ - setlast = TRUE; - lp++; - } - if (lp[0] == '/') - idx = RE_SEARCH; - else if (lp[0] == '&') - idx = RE_SUBST; - else if (lp[0] == 'h') /* ~h: 'hlsearch' highlighting off */ - hlsearch_on = FALSE; - else if (lp[0] == 'H') /* ~H: 'hlsearch' highlighting on */ - hlsearch_on = TRUE; - if (idx >= 0) { - if (force || spats[idx].pat == NULL) { - val = viminfo_readstring(virp, (int)(lp - virp->vir_line + 1), TRUE); - set_last_search_pat(val, idx, magic, setlast); - xfree(val); - spats[idx].no_scs = no_scs; - spats[idx].off.line = off_line; - spats[idx].off.end = off_end; - spats[idx].off.off = off; - if (setlast) { - SET_NO_HLSEARCH(!hlsearch_on); - } - } - } - return viminfo_readline(virp); +/// Get last substitute pattern +void get_substitute_pattern(SearchPattern *const pat) +{ + memcpy(pat, &(spats[1]), sizeof(spats[1])); + memset(&(pat->off), 0, sizeof(pat->off)); } -void write_viminfo_search_pattern(FILE *fp) +/// Set last search pattern +void set_search_pattern(const SearchPattern pat) { - if (get_viminfo_parameter('/') != 0) { - fprintf(fp, "\n# hlsearch on (H) or off (h):\n~%c", - (no_hlsearch || find_viminfo_parameter('h') != NULL) ? 'h' : 'H'); - wvsp_one(fp, RE_SEARCH, "", '/'); - wvsp_one(fp, RE_SUBST, _("Substitute "), '&'); - } + free_spat(&spats[0]); + memcpy(&(spats[0]), &pat, sizeof(spats[0])); } -static void -wvsp_one ( - FILE *fp, /* file to write to */ - int idx, /* spats[] index */ - char *s, /* search pat */ - int sc /* dir char */ -) +/// Set last substitute pattern +void set_substitute_pattern(const SearchPattern pat) { - if (spats[idx].pat != NULL) { - fprintf(fp, _("\n# Last %sSearch Pattern:\n~"), s); - /* off.dir is not stored, it's reset to forward */ - fprintf(fp, "%c%c%c%c%" PRId64 "%s%c", - spats[idx].magic ? 'M' : 'm', /* magic */ - spats[idx].no_scs ? 's' : 'S', /* smartcase */ - spats[idx].off.line ? 'L' : 'l', /* line offset */ - spats[idx].off.end ? 'E' : 'e', /* offset from end */ - (int64_t)spats[idx].off.off, /* offset */ - last_idx == idx ? "~" : "", /* last used pat */ - sc); - viminfo_writestring(fp, spats[idx].pat); - } + free_spat(&spats[1]); + memcpy(&(spats[1]), &pat, sizeof(spats[1])); + memset(&(spats[1].off), 0, sizeof(spats[1].off)); +} + +/// Set last used search pattern +/// +/// @param[in] is_substitute_pattern If true set substitute pattern as last +/// used. Otherwise sets search pattern. +void set_last_used_pattern(const bool is_substitute_pattern) +{ + last_idx = (is_substitute_pattern ? 1 : 0); +} + +/// Returns true if search pattern was the last used one +bool search_was_last_used(void) +{ + return last_idx == 0; } |