cmp-cmdline
cmp-cmdline copied to clipboard
Can't cycle through history with Ctrl-N and Ctrl-P in command-line mode
Hello,
I can't use Ctrl-P to cycle through my ex-command history, I think due to some poor interaction with this plugin. For example, when type : and then repeatedly hit Ctrl-P, this happens:
https://github.com/hrsh7th/cmp-cmdline/assets/2729079/7b7b205e-33fe-4368-ad67-f3fc0b5cf534
When I comment out the cmdline source (see the top right pane), instead I can do:
https://github.com/hrsh7th/cmp-cmdline/assets/2729079/3ac3de56-52e1-4156-b97b-a333cb7a19a9
Here's some information about my setup:
:set
--- Options ---
cmdheight=0 cursorcolumn filetype=lua lines=63 relativenumber noshowmode suffixesadd=.lua termguicolors
columns=166 cursorline helplang=en noloadplugins scroll=10 showtabline=2 noswapfile window=62
comments=:-- expandtab inccommand=split number shiftwidth=2 softtabstop=2 tabstop=2 nowrap
commentstring=-- %s
completeopt=menu,menuone,noselect
define=\<function\|\<local\%(\s\+function\)\=
fileencoding=utf-8
formatexpr=v:lua.vim.lsp.formatexpr
formatoptions=jcroql
includeexpr=tr(v:fname,'.','/')
indentexpr=GetLuaIndent()
indentkeys=0{,0},0),0],:,0#,!^F,o,O,e,0=end,0=until
omnifunc=v:lua.vim.lsp.omnifunc
operatorfunc=<SNR>14_go
packpath=~/code/nvim-macos/share/nvim/runtime
runtimepath=~/.config/nvim,~/.local/share/nvim/lazy/lazy.nvim,~/.local/share/nvim/lazy/indent-blankline.nvim,~/.local/share/nvim/lazy/fzf,~/.local/share/nvim/lazy/v
im-obsession,~/.local/share/nvim/lazy/cmp-nvim-lsp,~/.local/share/nvim/lazy/lspkind.nvim,~/.local/share/nvim/lazy/trouble.nvim,~/.local/share/nvim/lazy/nvim-cmp,~/.lo
cal/share/nvim/lazy/vim-vsnip,~/.local/share/nvim/lazy/nvim-treesitter,~/.local/share/nvim/lazy/vim-tmux-navigator,~/.local/share/nvim/lazy/vim-commentary,~/.local/sh
are/nvim/lazy/cmp-path,~/.local/share/nvim/lazy/nvim-lspconfig,~/.local/share/nvim/lazy/bufferline.nvim,~/.local/share/nvim/lazy/cmp-buffer,~/.local/share/nvim/lazy/c
mp-vsnip,~/.local/share/nvim/lazy/nvim-surround,~/.local/share/nvim/lazy/vim-move,~/.local/share/nvim/lazy/cmp-cmdline,~/.local/share/nvim/lazy/kanagawa.nvim,~/.local
/share/nvim/lazy/cmp-emoji,~/.local/share/nvim/lazy/nvim-autopairs,~/.local/share/nvim/lazy/cmp-nvim-lua,~/.local/share/nvim/lazy/nvim-web-devicons,~/.local/share/nvi
m/lazy/lualine.nvim,~/.local/share/nvim/lazy/vim-snipe,~/.local/share/nvim/lazy/fzf.vim,~/.local/share/nvim/lazy/vim-tmux,~/code/nvim-macos/share/nvim/runtime,~/code/
nvim-macos/share/nvim/runtime/pack/dist/opt/matchit,~/code/nvim-macos/lib/nvim,~/.local/share/nvim/lazy/indent-blankline.nvim/after,~/.local/share/nvim/lazy/cmp-nvim-
lsp/after,~/.local/share/nvim/lazy/cmp-path/after,~/.local/share/nvim/lazy/cmp-buffer/after,~/.local/share/nvim/lazy/cmp-vsnip/after,~/.local/share/nvim/lazy/cmp-cmdl
ine/after,~/.local/share/nvim/lazy/cmp-emoji/after,~/.local/share/nvim/lazy/cmp-nvim-lua/after,~/.config/nvim/after,~/.local/state/nvim/lazy/readme
shortmess=linFTotfOcx
spelloptions=noplainbuffer
statusline=%#lualine_a_command# COMMAND %#lualine_transitional_lualine_a_command_to_lualine_b_command#%#lualine_b_command# [$] %#lualine_transitional_lualine_b_com
mand_to_lualine_c_normal#%<%#lualine_c_normal# nvim/.config/nvim/lua/settings.lua %#lualine_c_normal#%=%#lualine_c_normal# utf-8 %#lualine_c_normal# %#lualine_x_
filetype_DevIconLua_command# %#lualine_c_normal# lua %#lualine_transitional_lualine_b_command_to_lualine_c_normal#%#lualine_b_command# 64%% %#lualine_transitional_l
ualine_a_command_to_lualine_b_command#%#lualine_a_command# 18:1
tagfunc=v:lua.vim.lsp.tagfunc
tabline=%!v:lua.nvim_bufferline()
wildignore=*.o,*.a,*.obj,__pycache__
Press ENTER or type command to continue
Also here's the result of :checkhealth:
==============================================================================
lazy: require("lazy.health").check()
lazy.nvim ~
- OK Git installed
- OK no existing packages found by other package managers
- OK packer_compiled.lua not found
==============================================================================
nvim: require("nvim.health").check()
Configuration ~
- OK no issues found
Runtime ~
- OK $VIMRUNTIME: /Users/yangmillstheory/code/nvim-macos/share/nvim/runtime
Performance ~
- OK Build type: Release
Remote Plugins ~
- OK Up to date
terminal ~
- key_backspace (kbs) terminfo entry: `key_backspace=\177`
- key_dc (kdch1) terminfo entry: `key_dc=\E[3~`
- $TERM_PROGRAM="tmux"
- $COLORTERM="truecolor"
tmux ~
- OK escape-time: 1
- OK focus-events: on
- $TERM: alacritty
- ERROR $TERM should be "screen-256color" or "tmux-256color" in tmux. Colors might look wrong.
- ADVICE:
- Set default-terminal in ~/.tmux.conf:
set-option -g default-terminal "screen-256color"
- https://github.com/neovim/neovim/wiki/Building-Neovim#optimized-builds
==============================================================================
nvim-treesitter: require("nvim-treesitter.health").check()
Installation ~
- WARNING `tree-sitter` executable not found (parser generator, only needed for :TSInstallFromGrammar, not required for :TSInstall)
- WARNING `node` executable not found (only needed for :TSInstallFromGrammar, not required for :TSInstall)
- OK `git` executable found.
- OK `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" }
Version: Apple clang version 15.0.0 (clang-1500.1.0.2.5)
- OK Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI.
OS Info:
{
machine = "x86_64",
release = "22.6.0",
sysname = "Darwin",
version = "Darwin Kernel Version 22.6.0: Sun Dec 17 22:18:09 PST 2023; root:xnu-8796.141.3.703.2~2/RELEASE_X86_64"
} ~
Parser/Features H L F I J
- c ✓ ✓ ✓ ✓ ✓
- cpp ✓ ✓ ✓ ✓ ✓
- go ✓ ✓ ✓ ✓ ✓
- lua ✓ ✓ ✓ ✓ ✓
- python ✓ ✓ ✓ ✓ ✓
- query ✓ ✓ ✓ ✓ ✓
- vim ✓ ✓ ✓ . ✓
- vimdoc x . . . ✓
Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
+) multiple parsers found, only one will be used
x) errors found in the query, try to run :TSUpdate {lang} ~
The following errors have been detected: ~
- ERROR vimdoc(highlights): ...im-macos/share/nvim/runtime/lua/vim/treesitter/query.lua:259: query: invalid node type at position 746 for language vimdoc
vimdoc(highlights) is concatenated from the following files:
| [ERROR]:"/Users/yangmillstheory/.local/share/nvim/lazy/nvim-treesitter/queries/vimdoc/highlights.scm", failed to load: ...im-macos/share/nvim/runtime/lua/vim/treesitter/query.lua:259: query: invalid node type at position 746 for language vimdoc
==============================================================================
provider: health#provider#check
- ERROR Failed to run healthcheck for "provider" plugin. Exception:
function health#check[25]..health#provider#check[4]..<SNR>88_check_ruby, line 15
Vim(let):E117: Unknown function: provider#ruby#Detect
==============================================================================
vim.lsp: require("vim.lsp.health").check()
- LSP log level : WARN
- Log path: /Users/yangmillstheory/.local/state/nvim/lsp.log
- Log size: 0 KB
vim.lsp: Active Clients ~
- lua_ls (id=1, root_dir=/Users/yangmillstheory/code/dotfiles/nvim/.config/nvim/lua/)
==============================================================================
vim.treesitter: require("vim.treesitter.health").check()
- Nvim runtime ABI version: 14
- OK Parser: cpp ABI: 14, path: /Users/yangmillstheory/.local/share/nvim/lazy/nvim-treesitter/parser/cpp.so
- OK Parser: go ABI: 14, path: /Users/yangmillstheory/.local/share/nvim/lazy/nvim-treesitter/parser/go.so
- OK Parser: lua ABI: 14, path: /Users/yangmillstheory/.local/share/nvim/lazy/nvim-treesitter/parser/lua.so
- OK Parser: python ABI: 14, path: /Users/yangmillstheory/.local/share/nvim/lazy/nvim-treesitter/parser/python.so
- OK Parser: vim ABI: 14, path: /Users/yangmillstheory/.local/share/nvim/lazy/nvim-treesitter/parser/vim.so
- OK Parser: c ABI: 14, path: /Users/yangmillstheory/code/nvim-macos/lib/nvim/parser/c.so
- OK Parser: lua ABI: 14, path: /Users/yangmillstheory/code/nvim-macos/lib/nvim/parser/lua.so
- OK Parser: query ABI: 14, path: /Users/yangmillstheory/code/nvim-macos/lib/nvim/parser/query.so
- OK Parser: vim ABI: 14, path: /Users/yangmillstheory/code/nvim-macos/lib/nvim/parser/vim.so
- OK Parser: vimdoc ABI: 14, path: /Users/yangmillstheory/code/nvim-macos/lib/nvim/parser/vimdoc.so
When I run :cmap, it looks like the binding comes from nvim-cmp:
However, commenting out the cmdline source fixes the issue, so I'm filing the bug here. Please let me know how I can help.
I just did disabled the built in mappings for the cmdline preset.
cmp.setup.cmdline(":", {
mapping = cmp.mapping.preset.cmdline({
-- Use default nvim history scrolling
["<C-n>"] = {
c = false,
},
["<C-p>"] = {
c = false,
},
}),
sources = cmp.config.sources({
{ name = "path" },
}, {
{ name = "cmdline" },
}),
})
Might solve ur usecase. Nvim Config
Thanks @adinhodovic, this looks like it works with no observable downsides. I wonder what the intent of the C-n / C-p mappings that we're overriding were? Because I guess the downside of the override, is that we're losing whatever benefit would be otherwise provided. So far I can't find any.
Thanks @adinhodovic, this looks like it works with no observable downsides. I wonder what the intent of the C-n / C-p mappings that we're overriding were? Because I guess the downside of the override, is that we're losing whatever benefit would be otherwise provided. So far I can't find any.
I think they're used for scrolling up and down in the completion list, why I'm not sure.
I see. In that case I'm still able to use <Tab> and <S-Tab> to cycle forwards and backwards through the completion list, so no harm done.
I do think this is still a bug that should be resolved.
Thanks!
@yangmillstheory, how do you cycle backwards and forwards now? With the mapping proposed by @adinhodovic, I can't do that anymore.
I use <Tab> and <S-Tab>. I thought I mentioned that above, but I guess I didn't.
I've faced a similar problem, but in a slightly different context. I'm used to navigating history with C-N/C-P and also using them for selecting completions in vim popup windows. So, I developed a solution that lets me do both simultaneously.
Here's the trick: With the code snippet below, C-N/C-P will navigate through the command line history (like in shell), unless you start typing a character. When you start typing, C-N/C-P switches to selecting completions instead of navigating history. This way, you get the best of both worlds. The may not be the setup OP is looking for, however, someone may find it useful one day, so I decided to share it here :)
-- For command line
-- This custom mappig setup causes CTRL-P, CTRL-N to fallback to history
-- browsing, unless user has explicitly typed something in the cmdline, then
-- these two activate to browse completion options.
local cmdline_cmp_state = "has_not_typed"
vim.api.nvim_create_autocmd({ "CmdlineEnter" }, {
command = "lua cmdline_cmp_state = 'has_not_typed'",
})
vim.api.nvim_create_autocmd({ "CmdlineChanged" }, {
callback = function()
if cmdline_cmp_state == "has_not_typed" then
cmdline_cmp_state = "has_typed"
elseif cmdline_cmp_state == "has_browsed_history" then
cmdline_cmp_state = "has_not_typed"
end
end,
})
local function select_or_fallback(select_action)
return cmp.mapping(function(fallback)
if cmdline_cmp_state == "has_typed" and cmp.visible() then
select_action()
else
cmdline_cmp_state = "has_browsed_history"
cmp.close()
fallback()
end
end, { "i", "c" })
end
cmp.setup.cmdline(":", {
mapping = cmp.mapping.preset.cmdline({
["<C-n>"] = select_or_fallback(cmp.select_next_item),
["<C-p>"] = select_or_fallback(cmp.select_prev_item),
}),
sources = cmp.config.sources({
{ name = "path" },
}, {
{ name = "cmdline" },
}),
})
I've faced a similar problem, but in a slightly different context. I'm used to navigating history with C-N/C-P and also using them for selecting completions in vim popup windows. So, I developed a solution that lets me do both simultaneously.
@maciejzj, I was facing this exact same issue and saw your solution, which works great! However, after some digging around I found a simpler configuration that achieves the same thing (for me, at least). Posting it here if it can be useful:
-- Use cmdline & path source for ':'
cmp.setup.cmdline(":", {
-- C-n/C-p cycle through completions if a character has been typed and through
-- command history if not (from https://www.reddit.com/r/neovim/comments/v5pfmy/comment/ibb61w3/)
mapping = cmp.mapping.preset.cmdline({
["<C-n>"] = { c = cmp.mapping.select_next_item() },
["<C-p>"] = { c = cmp.mapping.select_prev_item() },
}),
sources = cmp.config.sources({
{ name = "path" },
}, {
{ name = "cmdline" },
}),
})
@plt3 Thanks a lot, this will slim down my init.lua a bit :))
It would be great to see this setup in some more visible place like the README. I guess many users would want this behaviour and it seems rather unobvious how to achieve it (TBH I would have never figured out that specifying that next/prev should explicitly work in "command mode" would result in this behaviour overall and still don't fully get it 🙃).
@plt3 @maciejzj guys, you're the best,
Also, your solution have these attrs:
- supports all three
:,?,/, not just: - preset keymaps doesn't override Up&Down arrows, so it supports Up, Down arrows to search history based on history filtered by already entered substring: i.e.
:echopressUpto search through history of commands that starts withecho.
I will also share my snippet that I based on your work: I don't use preset, only set maps that I use.
-- Declare only keys that I actually use
-- Based on https://github.com/hrsh7th/cmp-cmdline/issues/108#issuecomment-2052449375
-- C-n/C-p cycle through completions if a character has been typed and through
-- command history if not (from https://www.reddit.com/r/neovim/comments/v5pfmy/comment/ibb61w3/)
local cmd_mapping = {
["<C-Space>"] = { c = cmp.mapping.complete({}) },
["<C-n>"] = { c = cmp.mapping.select_next_item() },
["<C-p>"] = { c = cmp.mapping.select_prev_item() },
["<C-e>"] = { c = cmp.mapping.abort() },
["<C-y>"] = {
c = cmp.mapping.confirm({
behavior = cmp.ConfirmBehavior.Insert,
select = true,
}),
},
}
-- Use buffer source for `/` and `?`
cmp.setup.cmdline({ "/", "?" }, {
mapping = cmd_mapping,
sources = {
{ name = "buffer" },
},
})
-- Use cmdline & path source for ':'
cmp.setup.cmdline(":", {
mapping = cmd_mapping,
sources = cmp.config.sources({
{ name = "path" },
}, {
{ name = "cmdline" },
}),
})
Wow @plt3 I cannot tell you how much you saved me here! I have been trying to figure this out off and on for weeks! For me it was not being able to use the Up / Down arrows to cycle through "/" search history. Your suggestion allowed me to figure it out with this below!
I still don't quite understand why this works! I thought select_next_item() would do exactly what I was trying to prevent... opening the cmp menu and selecting the next completion suggestion! But if it works, it works! Thanks!
mapping = cmp.mapping.preset.cmdline({
["<Up>"] = { c = cmp.mapping.select_next_item() },
["<Down>"] = { c = cmp.mapping.select_prev_item() },
}),