mirror of
https://github.com/neovim/neovim.git
synced 2025-10-05 01:16:31 +00:00

Problem: 'wildchar' does not work in search contexts
Solution: implement search completion when 'wildchar' is typed
(Girish Palya).
This change enhances Vim's command-line completion by extending
'wildmode' behavior to search pattern contexts, including:
- '/' and '?' search commands
- ':s', ':g', ':v', and ':vim' commands
Completions preserve the exact regex pattern typed by the user,
appending the completed word directly to the original input. This
ensures that all regex elements — such as '<', '^', grouping brackets
'()', wildcards '\*', '.', and other special characters — remain intact
and in their original positions.
---
**Use Case**
While searching (using `/` or `?`) for lines containing a pattern like
`"foobar"`, you can now type a partial pattern (e.g., `/f`) followed by
a trigger key (`wildchar`) to open a **popup completion menu** showing
all matching words.
This offers two key benefits:
1. **Precision**: Select the exact word you're looking for without
typing it fully.
2. **Memory aid**: When you can’t recall a full function or variable
name, typing a few letters helps you visually identify and complete the
correct symbol.
---
**What’s New**
Completion is now supported in the following contexts:
- `/` and `?` search commands
- `:s`, `:g`, `:v`, and `:vimgrep` ex-commands
---
**Design Notes**
- While `'wildchar'` (usually `<Tab>`) triggers completion, you'll have
to use `<CTRL-V><Tab>` or "\t" to search for a literal tab.
- **Responsiveness**: Search remains responsive because it checks for
user input frequently.
---
**Try It Out**
Basic setup using the default `<Tab>` as the completion trigger:
```vim
set wim=noselect,full wop=pum wmnu
```
Now type:
```
/foo<Tab>
```
This opens a completion popup for matches containing "foo".
For matches beginning with "foo" type `/\<foo<Tab>`.
---
**Optional: Autocompletion**
For automatic popup menu completion as you type in search or `:`
commands, include this in your `.vimrc`:
```vim
vim9script
set wim=noselect:lastused,full wop=pum wcm=<C-@> wmnu
autocmd CmdlineChanged [:/?] CmdComplete()
def CmdComplete()
var [cmdline, curpos, cmdmode] = [getcmdline(), getcmdpos(),
expand('<afile>') == ':']
var trigger_char = '\%(\w\|[*/:.-]\)$'
var not_trigger_char = '^\%(\d\|,\|+\|-\)\+$' # Exclude numeric range
if getchar(1, {number: true}) == 0 # Typehead is empty, no more
pasted input
&& !wildmenumode() && curpos == cmdline->len() + 1
&& (!cmdmode || (cmdline =~ trigger_char && cmdline !~
not_trigger_char))
SkipCmdlineChanged()
feedkeys("\<C-@>", "t")
timer_start(0, (_) => getcmdline()->substitute('\%x00', '',
'ge')->setcmdline()) # Remove <C-@>
endif
enddef
def SkipCmdlineChanged(key = ''): string
set ei+=CmdlineChanged
timer_start(0, (_) => execute('set ei-=CmdlineChanged'))
return key == '' ? '' : ((wildmenumode() ? "\<C-E>" : '') .. key)
enddef
**Optional: Preserve history recall behavior**
cnoremap <expr> <Up> SkipCmdlineChanged("\<Up>")
cnoremap <expr> <Down> SkipCmdlineChanged("\<Down>")
**Optional: Customize popup height**
autocmd CmdlineEnter : set bo+=error | exec $'set ph={max([10,
winheight(0) - 4])}'
autocmd CmdlineEnter [/?] set bo+=error | set ph=8
autocmd CmdlineLeave [:/?] set bo-=error ph&
```
closes: vim/vim#17570
6b49fba8c8
Co-authored-by: Girish Palya <girishji@gmail.com>
50 lines
1.4 KiB
C
50 lines
1.4 KiB
C
#pragma once
|
|
|
|
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
|
|
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
|
|
#include "nvim/ex_getln_defs.h" // IWYU pragma: keep
|
|
#include "nvim/garray_defs.h" // IWYU pragma: keep
|
|
#include "nvim/regexp_defs.h" // IWYU pragma: keep
|
|
#include "nvim/types_defs.h" // IWYU pragma: keep
|
|
|
|
// Values for nextwild() and ExpandOne(). See ExpandOne() for meaning.
|
|
|
|
enum {
|
|
WILD_FREE = 1,
|
|
WILD_EXPAND_FREE = 2,
|
|
WILD_EXPAND_KEEP = 3,
|
|
WILD_NEXT = 4,
|
|
WILD_PREV = 5,
|
|
WILD_ALL = 6,
|
|
WILD_LONGEST = 7,
|
|
WILD_ALL_KEEP = 8,
|
|
WILD_CANCEL = 9,
|
|
WILD_APPLY = 10,
|
|
WILD_PAGEUP = 11,
|
|
WILD_PAGEDOWN = 12,
|
|
WILD_PUM_WANT = 13,
|
|
};
|
|
|
|
enum {
|
|
WILD_LIST_NOTFOUND = 0x01,
|
|
WILD_HOME_REPLACE = 0x02,
|
|
WILD_USE_NL = 0x04,
|
|
WILD_NO_BEEP = 0x08,
|
|
WILD_ADD_SLASH = 0x10,
|
|
WILD_KEEP_ALL = 0x20,
|
|
WILD_SILENT = 0x40,
|
|
WILD_ESCAPE = 0x80,
|
|
WILD_ICASE = 0x100,
|
|
WILD_ALLLINKS = 0x200,
|
|
WILD_IGNORE_COMPLETESLASH = 0x400,
|
|
WILD_NOERROR = 0x800, ///< sets EW_NOERROR
|
|
WILD_BUFLASTUSED = 0x1000,
|
|
BUF_DIFF_FILTER = 0x2000,
|
|
WILD_KEEP_SOLE_ITEM = 0x4000,
|
|
WILD_MAY_EXPAND_PATTERN = 0x8000,
|
|
};
|
|
|
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
|
# include "cmdexpand.h.generated.h"
|
|
#endif
|