vimtricks.wiki Concise Vim tricks, one at a time.

How do I make Tab and Enter behave differently when the completion popup menu is open?

Answer

pumvisible()

Explanation

The pumvisible() function returns 1 when the insert-mode completion popup menu (pum) is visible, and 0 otherwise. Combined with <expr> mappings, it lets you create context-aware keys: <Tab> cycles through completions when the menu is open, but inserts a literal tab otherwise; <CR> confirms a completion or inserts a newline.

How it works

Add these <expr> mappings to your vimrc / init.vim:

inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <CR>    pumvisible() ? "\<C-y>" : "\<CR>"

Key bindings used:

  • <C-n> — move to the next completion item
  • <C-p> — move to the previous completion item
  • <C-y>accept the currently highlighted completion
  • <C-e>cancel the popup without selecting (useful as an escape hatch)

Example

Typing sys and pressing <C-n> opens the completion popup. Now:

  • <Tab> cycles forward, <S-Tab> cycles backward
  • <CR> accepts and exits insert mode cleanly
  • Outside the popup, these keys behave normally

Tips

  • pumvisible() works with both <C-n>/<C-p> keyword completion and <C-x> sub-mode completions
  • For Neovim with a completion plugin (nvim-cmp, blink.cmp), the plugin handles this automatically — check its docs before adding manual mappings
  • If you want <Tab> to also trigger completion when the menu is closed, add: pumvisible() ? "\<C-n>" : "\<C-n>" but note this opens the menu unconditionally

Next

How do I open the directory containing the current file in netrw from within Vim?