diff options
-rw-r--r-- | src/nvim/buffer.c | 176 | ||||
-rw-r--r-- | test/old/testdir/test_cmdline.vim | 32 |
2 files changed, 113 insertions, 95 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index bf1d2ac6dd..ac6ccf223c 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -2377,10 +2377,8 @@ static int buf_time_compare(const void *s1, const void *s2) /// @return OK if matches found, FAIL otherwise. int ExpandBufnames(char *pat, int *num_file, char ***file, int options) { - int count = 0; - int round; - char *p; bufmatch_T *matches = NULL; + bool to_free = false; *num_file = 0; // return values in case of FAIL *file = NULL; @@ -2392,125 +2390,115 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options) const bool fuzzy = cmdline_fuzzy_complete(pat); char *patc = NULL; + fuzmatch_str_T *fuzmatch = NULL; + regmatch_T regmatch; + // Make a copy of "pat" and change "^" to "\(^\|[\/]\)" (if doing regular // expression matching) if (!fuzzy) { - if (*pat == '^') { - patc = xmalloc(strlen(pat) + 11); - STRCPY(patc, "\\(^\\|[\\/]\\)"); - STRCPY(patc + 11, pat + 1); + if (*pat == '^' && pat[1] != NUL) { + patc = xstrdup(pat + 1); + to_free = true; + } else if (*pat == '^') { + patc = ""; } else { patc = pat; } + regmatch.regprog = vim_regcomp(patc, RE_MAGIC); } - fuzmatch_str_T *fuzmatch = NULL; - // attempt == 0: try match with '\<', match at start of word - // attempt == 1: try match without '\<', match anywhere - for (int attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) { - regmatch_T regmatch; - if (!fuzzy) { - if (attempt > 0 && patc == pat) { - break; // there was no anchor, no need to try again + int count = 0; + int score = 0; + // round == 1: Count the matches. + // round == 2: Build the array to keep the matches. + for (int round = 1; round <= 2; round++) { + count = 0; + FOR_ALL_BUFFERS(buf) { + if (!buf->b_p_bl) { // skip unlisted buffers + continue; } - regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC); - } - - int score = 0; - // round == 1: Count the matches. - // round == 2: Build the array to keep the matches. - for (round = 1; round <= 2; round++) { - count = 0; - FOR_ALL_BUFFERS(buf) { - if (!buf->b_p_bl) { // skip unlisted buffers + if (options & BUF_DIFF_FILTER) { + // Skip buffers not suitable for + // :diffget or :diffput completion. + if (buf == curbuf || !diff_mode_buf(buf)) { continue; } - if (options & BUF_DIFF_FILTER) { - // Skip buffers not suitable for - // :diffget or :diffput completion. - if (buf == curbuf || !diff_mode_buf(buf)) { - continue; - } - } + } - if (!fuzzy) { - if (regmatch.regprog == NULL) { - // invalid pattern, possibly after recompiling - if (patc != pat) { - xfree(patc); - } - return FAIL; - } - p = buflist_match(®match, buf, p_wic); - } else { - p = NULL; - // first try matching with the short file name - if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) { - p = buf->b_sfname; + char *p = NULL; + if (!fuzzy) { + if (regmatch.regprog == NULL) { + // invalid pattern, possibly after recompiling + if (to_free) { + xfree(patc); } - if (p == NULL) { - // next try matching with the full path file name - if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) { - p = buf->b_ffname; - } - } - } - - if (p == NULL) { - continue; - } - - if (round == 1) { - count++; - continue; + return FAIL; } - - if (options & WILD_HOME_REPLACE) { - p = home_replace_save(buf, p); - } else { - p = xstrdup(p); + p = buflist_match(®match, buf, p_wic); + } else { + p = NULL; + // first try matching with the short file name + if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) { + p = buf->b_sfname; } - - if (!fuzzy) { - if (matches != NULL) { - matches[count].buf = buf; - matches[count].match = p; - count++; - } else { - (*file)[count++] = p; + if (p == NULL) { + // next try matching with the full path file name + if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) { + p = buf->b_ffname; } - } else { - fuzmatch[count].idx = count; - fuzmatch[count].str = p; - fuzmatch[count].score = score; - count++; } } - if (count == 0) { // no match found, break here - break; + + if (p == NULL) { + continue; } + if (round == 1) { - if (!fuzzy) { - *file = xmalloc((size_t)count * sizeof(**file)); - if (options & WILD_BUFLASTUSED) { - matches = xmalloc((size_t)count * sizeof(*matches)); - } + count++; + continue; + } + + if (options & WILD_HOME_REPLACE) { + p = home_replace_save(buf, p); + } else { + p = xstrdup(p); + } + + if (!fuzzy) { + if (matches != NULL) { + matches[count].buf = buf; + matches[count].match = p; + count++; } else { - fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T)); + (*file)[count++] = p; } + } else { + fuzmatch[count].idx = count; + fuzmatch[count].str = p; + fuzmatch[count].score = score; + count++; } } - - if (!fuzzy) { - vim_regfree(regmatch.regprog); - if (count) { // match(es) found, break here - break; + if (count == 0) { // no match found, break here + break; + } + if (round == 1) { + if (!fuzzy) { + *file = xmalloc((size_t)count * sizeof(**file)); + if (options & WILD_BUFLASTUSED) { + matches = xmalloc((size_t)count * sizeof(*matches)); + } + } else { + fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T)); } } } - if (!fuzzy && patc != pat) { - xfree(patc); + if (!fuzzy) { + vim_regfree(regmatch.regprog); + if (to_free) { + xfree(patc); + } } if (!fuzzy) { diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim index f62a89aec8..268e5ca7a1 100644 --- a/test/old/testdir/test_cmdline.vim +++ b/test/old/testdir/test_cmdline.vim @@ -679,7 +679,7 @@ func Test_getcompletion() bw Xtest\ endif - call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:') + call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E866:') call assert_fails('call getcompletion("", "burp")', 'E475:') call assert_fails('call getcompletion("abc", [])', 'E1174:') endfunc @@ -3918,4 +3918,34 @@ func Test_custom_completion_with_glob() delfunc TestGlobComplete endfunc +func Test_window_size_stays_same_after_changing_cmdheight() + set laststatus=2 + let expected = winheight(0) + function! Function_name() abort + call feedkeys(":"..repeat('x', &columns), 'x') + let &cmdheight=2 + let &cmdheight=1 + redraw + endfunction + call Function_name() + call assert_equal(expected, winheight(0)) +endfunc + +" verify that buffer-completion finds all buffer names matching a pattern +func Test_buffer_completion() + " should return empty list + call assert_equal([], getcompletion('', 'buffer')) + + call mkdir('Xbuf_complete', 'R') + e Xbuf_complete/Foobar.c + e Xbuf_complete/MyFoobar.c + e AFoobar.h + let expected = ["Xbuf_complete/Foobar.c", "Xbuf_complete/MyFoobar.c", "AFoobar.h"] + + call assert_equal(3, len(getcompletion('Foo', 'buffer'))) + call assert_equal(expected, getcompletion('Foo', 'buffer')) + call feedkeys(":b Foo\<C-A>\<C-B>\"\<CR>", 'xt') + call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:) +endfunc + " vim: shiftwidth=2 sts=2 expandtab |