cmp-cmdline
cmp-cmdline copied to clipboard
"E141: No file name for buffer nn" on attempt to exit
Disclaimer: I'm not super familiar with lua or vimscript or the inner workings of vim. I just use vim a lot.
I recently setup neovim with nvim-cmp (love it! great work!). However, when I enable cmp-cmdline I can no longer exit vim with :wqa. I get the following error:
E141: No file name for buffer nn
Then I essentially have to :q! everything individually until I hit the last buffer which appears to be the options listed for cmp-cmdline.
I wanted to guess that the buffer wasn't set to nofile, but I cannot find where that would even happen. Is very possible its outside this plugin completely. However, when I disable this plugin I have no problem.
Steps to Repro:
- Set-up
nvim-cmpusing the recommended configuration here: https://github.com/hrsh7th/nvim-cmp - Open two files (using
:vsor:spl) - Try to exit using
:wqa(or:qaor:qa!)
Notice
E141: No file name for buffer 2 is shown
Expected
Vim would exit
I can't reproduce this issue.
https://user-images.githubusercontent.com/629908/139784957-bfd480bf-76f5-44e8-881f-8acf9c017d74.mp4
It seems to be an issue with the following config (I have the lines commented out that cause me trouble):
-- Use cmdline & path source for ':'.
cmp.setup.cmdline(':', {
sources = cmp.config.sources({
{ name = 'path' }
-- }, {
-- { name = 'cmdline' }
})
})
My minimal init.vim looks like this (just like the suggestion on the website, but with things commented out to avoid problem):
call plug#begin('~/.config/nvim/plugged')
Plug 'neovim/nvim-lspconfig'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
"Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-vsnip'
Plug 'hrsh7th/vim-vsnip'
call plug#end()
set completeopt=menu,menuone,noselect
lua <<EOF
-- Setup nvim-cmp.
local cmp = require'cmp'
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
-- require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
-- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
-- require'snippy'.expand_snippet(args.body) -- For `snippy` users.
end,
},
mapping = {
['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
['<C-y>'] = cmp.config.disable, -- If you want to remove the default `<C-y>` mapping, You can specify `cmp.config.disable` value.
['<C-e>'] = cmp.mapping({
i = cmp.mapping.abort(),
c = cmp.mapping.close(),
}),
['<CR>'] = cmp.mapping.confirm({ select = true }),
},
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'vsnip' }, -- For vsnip users.
-- { name = 'luasnip' }, -- For luasnip users.
-- { name = 'ultisnips' }, -- For ultisnips users.
-- { name = 'snippy' }, -- For snippy users.
}, {
{ name = 'buffer' },
})
})
-- Use buffer source for `/`.
cmp.setup.cmdline('/', {
sources = {
{ name = 'buffer' }
}
})
-- Use cmdline & path source for ':'.
cmp.setup.cmdline(':', {
sources = cmp.config.sources({
{ name = 'path' }
-- }, {
-- { name = 'cmdline' }
})
})
-- Setup lspconfig.
local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())
capabilities.textDocument.completion.completionItem.snippetSupport = true
require('lspconfig').tsserver.setup {
capabilities = capabilities
}
require('lspconfig').html.setup {
capabilities = capabilities
}
EOF
I have the same issue with cmp, but not specifically cmp-cmdline.
I'll post it here for now because I suspect it's the same underlying issue in cmp.
Please let me know if you'd rather I open a new issue elsewhere.
When I :wall as part of my workflow, I get the same E141 re trying to save a buffer without a filename:
E141: No file name for buffer 24
:ls / :buffers does not list it, but :ls! / :buffers! does:
24u h + "[No Name]" line 1
I see the u means “unlisted buffers”, which explains why it doesn't list normally.
And h is hidden (backgrounded), + is modified, and it has no filename.
When I switch to it with :b24 I see content like this:
func(s string) int
─────────────────────────────────────────────
"Safe" parseint for parsing ANSI instructions
That's the second-level popover describing an auto-complete option from LSP, for example:

On this occasion it's Go's gopls, but I have the same issue with all the LSP backends I use (e.g. Go, Ruby, Rust). I think the only unusual part of my workflow is frequent :wall while triggering async tests.
I'm happy to do more debugging, but I'm not very familiar with nvim/cmp internals.
Here's the LSP/cmp relevant part of my init.lua
----------
-- plugins
local lspconfig = require("lspconfig")
local capabilities = require("cmp_nvim_lsp").update_capabilities(vim.lsp.protocol.make_client_capabilities())
for _, server in ipairs({ "gopls", "rust_analyzer", "yamlls", "solargraph" }) do
lspconfig[server].setup { capabilities = capabilities }
end
-- vim-go
require("lspconfig").gopls.setup{}
vim.g.go_auto_sameids = 1 -- highlight other instances of identifier under cursor
vim.g.go_updatetime = 200 -- delay (ms) for sameids, type_info etc (default 800)
vim.g.go_gopls_complete_unimported = 1 -- include suggestions from unimported packages
-- fzf
vim.api.nvim_set_keymap("n", "<C-p>", ":Files<CR>", {})
-- vim-asm_ca65
vim.g.asm_ca65_wdc = true
vim.cmd "filetype plugin indent on"
vim.cmd [[
augroup filetypedetect
autocmd BufEnter *.s setlocal filetype=asm_ca65 colorcolumn=17,41
autocmd BufEnter *.s highlight ColorColumn ctermbg=232
autocmd BufLeave *.s highlight ColorColumn ctermbg=0
augroup END
]]
-- rust.vim
vim.g.rustfmt_autosave = true
require("lspconfig").rust_analyzer.setup{}
-- redhat-developer/yaml-language-store
require("lspconfig").yamlls.setup {
settings = {
yaml = {
{schemaStore = {enable = true}},
},
}
}
-- ruby LSP
require("lspconfig").solargraph.setup {}
vim.opt.completeopt = "menu,menuone,noselect"
local cmp = require("cmp")
local luasnip = require("luasnip")
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = {
["<C-p>"] = cmp.mapping.select_prev_item(),
["<C-n>"] = cmp.mapping.select_next_item(),
["<C-d>"] = cmp.mapping.scroll_docs(-4),
["<C-f>"] = cmp.mapping.scroll_docs(4),
["<C-Space>"] = cmp.mapping.complete(),
["<C-e>"] = cmp.mapping.close(),
-- ["<CR>"] = cmp.mapping.confirm {
-- behavior = cmp.ConfirmBehavior.Replace,
-- select = true,
-- },
['<Tab>'] = function(fallback)
if cmp.visible() then
cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then
luasnip.expand_or_jump()
else
fallback()
end
end,
['<S-Tab>'] = function(fallback)
if cmp.visible() then
cmp.select_prev_item()
elseif luasnip.jumpable(-1) then
luasnip.jump(-1)
else
fallback()
end
end,
},
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = 'luasnip' },
{ name = "buffer", option = {
get_bufnrs = function() return vim.api.nvim_list_bufs() end
}},
})
})
Hrmm, I can't reproduce it after restarting vim, but this does hit me most days.
My guess is that an unlisted scratch buffer is somehow losing its buftype=nofile Scratch status, and so it becomes a normal dirty buffer that requires saving before close. I don't know how it would be losing buftype=nofile though. Maybe some kind of race condition?
I had been trying to fix it by :bd 24 the buffer, but finding it stuck again the next time an auto-complete pops up. Having read the :bdelete manual more closely, that makes sense:
Actually, the buffer isn't completely deleted, it is removed from the buffer list |unlisted-buffer| and option values, variables and mappings/abbreviations for the buffer are cleared.
So for an already-unlisted buffer, all it was doing was clearing the unsaved changes, but presumably the same buffer gets reused for the next completion, and it remains in non-scratch state.
I suppose :bwipeout would be the more effective workaround short of restarting neovim.
I'll keep looking around and see what I can figure out.
(And apologies in advance if it turns out to be a problem unrelated to cmp…)