mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 10:45:16 -07:00
vim-patch:8.2.0413: buffer menu does not handle special buffers properly
Problem: Buffer menu does not handle special buffers properly.
Solution: Keep a dictionary with buffer names to reliably keep track of
entries.
Also trigger BufFilePre and BufFilePost for command-line and
terminal buffers when the name changes.
5e94a29ebb
This commit is contained in:
parent
c1e1d16fca
commit
d985323c55
117
runtime/menu.vim
117
runtime/menu.vim
@ -2,7 +2,7 @@
|
||||
" You can also use this as a start for your own set of menus.
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2019 Dec 10
|
||||
" Last Change: 2020 Mar 19
|
||||
|
||||
" Note that ":an" (short for ":anoremenu") is often used to make a menu work
|
||||
" in all modes and avoid side effects from mappings defined by the user.
|
||||
@ -139,11 +139,11 @@ an 10.600 &File.-SEP4- <Nop>
|
||||
an 10.610 &File.Sa&ve-Exit<Tab>:wqa :confirm wqa<CR>
|
||||
an 10.620 &File.E&xit<Tab>:qa :confirm qa<CR>
|
||||
|
||||
func! <SID>SelectAll()
|
||||
func s:SelectAll()
|
||||
exe "norm! gg" . (&slm == "" ? "VG" : "gH\<C-O>G")
|
||||
endfunc
|
||||
|
||||
func! s:FnameEscape(fname)
|
||||
func s:FnameEscape(fname)
|
||||
if exists('*fnameescape')
|
||||
return fnameescape(a:fname)
|
||||
endif
|
||||
@ -356,7 +356,7 @@ endfun
|
||||
let s:did_setup_color_schemes = 0
|
||||
|
||||
" Setup the Edit.Color Scheme submenu
|
||||
func! s:SetupColorSchemes() abort
|
||||
func s:SetupColorSchemes() abort
|
||||
if s:did_setup_color_schemes
|
||||
return
|
||||
endif
|
||||
@ -388,7 +388,7 @@ endif
|
||||
if has("keymap")
|
||||
let s:did_setup_keymaps = 0
|
||||
|
||||
func! s:SetupKeymaps() abort
|
||||
func s:SetupKeymaps() abort
|
||||
if s:did_setup_keymaps
|
||||
return
|
||||
endif
|
||||
@ -454,7 +454,7 @@ if has("spell")
|
||||
an <silent> 40.335.270 &Tools.&Spelling.&Find\ More\ Languages :call <SID>SpellLang()<CR>
|
||||
|
||||
let s:undo_spelllang = ['aun &Tools.&Spelling.&Find\ More\ Languages']
|
||||
func! s:SpellLang()
|
||||
func s:SpellLang()
|
||||
for cmd in s:undo_spelllang
|
||||
exe "silent! " . cmd
|
||||
endfor
|
||||
@ -566,7 +566,7 @@ an <silent> 40.540 &Tools.Conve&rt\ Back<Tab>:%!xxd\ -r
|
||||
|
||||
" Use a function to do the conversion, so that it also works with 'insertmode'
|
||||
" set.
|
||||
func! s:XxdConv()
|
||||
func s:XxdConv()
|
||||
let mod = &mod
|
||||
if has("vms")
|
||||
%!mc vim:xxd
|
||||
@ -580,7 +580,7 @@ func! s:XxdConv()
|
||||
let &mod = mod
|
||||
endfun
|
||||
|
||||
func! s:XxdBack()
|
||||
func s:XxdBack()
|
||||
let mod = &mod
|
||||
if has("vms")
|
||||
%!mc vim:xxd -r
|
||||
@ -593,7 +593,7 @@ func! s:XxdBack()
|
||||
let &mod = mod
|
||||
endfun
|
||||
|
||||
func! s:XxdFind()
|
||||
func s:XxdFind()
|
||||
if !exists("g:xxdprogram")
|
||||
" On the PC xxd may not be in the path but in the install directory
|
||||
if has("win32") && !executable("xxd")
|
||||
@ -610,7 +610,7 @@ endfun
|
||||
let s:did_setup_compilers = 0
|
||||
|
||||
" Setup the Tools.Compiler submenu
|
||||
func! s:SetupCompilers() abort
|
||||
func s:SetupCompilers() abort
|
||||
if s:did_setup_compilers
|
||||
return
|
||||
endif
|
||||
@ -634,7 +634,7 @@ endif
|
||||
|
||||
" Load ColorScheme, Compiler Setting and Keymap menus when idle.
|
||||
if !exists("do_no_lazyload_menus")
|
||||
func! s:SetupLazyloadMenus()
|
||||
func s:SetupLazyloadMenus()
|
||||
call s:SetupColorSchemes()
|
||||
call s:SetupCompilers()
|
||||
if has("keymap")
|
||||
@ -656,51 +656,75 @@ if !exists("no_buffers_menu")
|
||||
" startup faster.
|
||||
let s:bmenu_wait = 1
|
||||
|
||||
" Dictionary of buffer number to name. This helps prevent problems where a
|
||||
" buffer as renamed and we didn't keep track of that.
|
||||
let s:bmenu_items = {}
|
||||
|
||||
if !exists("bmenu_priority")
|
||||
let bmenu_priority = 60
|
||||
endif
|
||||
|
||||
func! s:BMAdd()
|
||||
" invoked from a BufCreate or BufFilePost autocommand
|
||||
func s:BMAdd()
|
||||
if s:bmenu_wait == 0
|
||||
" when adding too many buffers, redraw in short format
|
||||
if s:bmenu_count == &menuitems && s:bmenu_short == 0
|
||||
call s:BMShow()
|
||||
else
|
||||
call <SID>BMFilename(expand("<afile>"), expand("<abuf>"))
|
||||
let s:bmenu_count = s:bmenu_count + 1
|
||||
let name = expand("<afile>")
|
||||
let num = expand("<abuf>")
|
||||
if s:BMCanAdd(name, num)
|
||||
call <SID>BMFilename(name, num)
|
||||
let s:bmenu_count += 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func! s:BMRemove()
|
||||
" invoked from a BufDelete or BufFilePre autocommand
|
||||
func s:BMRemove()
|
||||
if s:bmenu_wait == 0
|
||||
let name = expand("<afile>")
|
||||
if isdirectory(name)
|
||||
return
|
||||
let bufnum = expand("<abuf>")
|
||||
if s:bmenu_items->has_key(bufnum)
|
||||
let menu_name = s:bmenu_items[bufnum]
|
||||
exe 'silent! aun &Buffers.' . menu_name
|
||||
let s:bmenu_count = s:bmenu_count - 1
|
||||
unlet s:bmenu_items[bufnum]
|
||||
endif
|
||||
let munge = <SID>BMMunge(name, expand("<abuf>"))
|
||||
|
||||
if s:bmenu_short == 0
|
||||
exe 'silent! aun &Buffers.' . munge
|
||||
else
|
||||
exe 'silent! aun &Buffers.' . <SID>BMHash2(munge) . munge
|
||||
endif
|
||||
let s:bmenu_count = s:bmenu_count - 1
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Return non-zero if buffer with number "name" / "num" is useful to add in the
|
||||
" buffer menu.
|
||||
func s:BMCanAdd(name, num)
|
||||
" no directory or unlisted buffer
|
||||
if isdirectory(a:name) || !buflisted(a:num)
|
||||
return 0
|
||||
endif
|
||||
|
||||
" no special buffer, such as terminal or popup
|
||||
let buftype = getbufvar(a:num, '&buftype')
|
||||
if buftype != '' && buftype != 'nofile' && buftype != 'nowrite'
|
||||
return 0
|
||||
endif
|
||||
|
||||
" only existing buffers
|
||||
return bufexists(a:num)
|
||||
endfunc
|
||||
|
||||
" Create the buffer menu (delete an existing one first).
|
||||
func! s:BMShow(...)
|
||||
func s:BMShow(...)
|
||||
let s:bmenu_wait = 1
|
||||
let s:bmenu_short = 1
|
||||
let s:bmenu_count = 0
|
||||
let s:bmenu_items = {}
|
||||
"
|
||||
" get new priority, if exists
|
||||
if a:0 == 1
|
||||
let g:bmenu_priority = a:1
|
||||
endif
|
||||
|
||||
" Remove old menu, if exists; keep one entry to avoid a torn off menu to
|
||||
" Remove old menu, if it exists; keep one entry to avoid a torn off menu to
|
||||
" disappear. Use try/catch to avoid setting v:errmsg
|
||||
try | unmenu &Buffers | catch | endtry
|
||||
exe 'noremenu ' . g:bmenu_priority . ".1 &Buffers.Dummy l"
|
||||
@ -721,7 +745,7 @@ func! s:BMShow(...)
|
||||
" figure out how many buffers there are
|
||||
let buf = 1
|
||||
while buf <= bufnr('$')
|
||||
if bufexists(buf) && !isdirectory(bufname(buf)) && buflisted(buf)
|
||||
if s:BMCanAdd(bufname(buf), buf)
|
||||
let s:bmenu_count = s:bmenu_count + 1
|
||||
endif
|
||||
let buf = buf + 1
|
||||
@ -733,8 +757,9 @@ func! s:BMShow(...)
|
||||
" iterate through buffer list, adding each buffer to the menu:
|
||||
let buf = 1
|
||||
while buf <= bufnr('$')
|
||||
if bufexists(buf) && !isdirectory(bufname(buf)) && buflisted(buf)
|
||||
call <SID>BMFilename(bufname(buf), buf)
|
||||
let name = bufname(buf)
|
||||
if s:BMCanAdd(name, buf)
|
||||
call <SID>BMFilename(name, buf)
|
||||
endif
|
||||
let buf = buf + 1
|
||||
endwhile
|
||||
@ -746,7 +771,7 @@ func! s:BMShow(...)
|
||||
aug END
|
||||
endfunc
|
||||
|
||||
func! s:BMHash(name)
|
||||
func s:BMHash(name)
|
||||
" Make name all upper case, so that chars are between 32 and 96
|
||||
let nm = substitute(a:name, ".*", '\U\0', "")
|
||||
if has("ebcdic")
|
||||
@ -761,7 +786,7 @@ func! s:BMHash(name)
|
||||
return (char2nr(nm[0]) - sp) * 0x800000 + (char2nr(nm[1]) - sp) * 0x20000 + (char2nr(nm[2]) - sp) * 0x1000 + (char2nr(nm[3]) - sp) * 0x80 + (char2nr(nm[4]) - sp) * 0x20 + (char2nr(nm[5]) - sp)
|
||||
endfunc
|
||||
|
||||
func! s:BMHash2(name)
|
||||
func s:BMHash2(name)
|
||||
let nm = substitute(a:name, ".", '\L\0', "")
|
||||
" Not exactly right for EBCDIC...
|
||||
if nm[0] < 'a' || nm[0] > 'z'
|
||||
@ -781,22 +806,22 @@ func! s:BMHash2(name)
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" insert a buffer name into the buffer menu:
|
||||
func! s:BMFilename(name, num)
|
||||
if isdirectory(a:name)
|
||||
return
|
||||
endif
|
||||
" Insert a buffer name into the buffer menu.
|
||||
func s:BMFilename(name, num)
|
||||
let munge = <SID>BMMunge(a:name, a:num)
|
||||
let hash = <SID>BMHash(munge)
|
||||
if s:bmenu_short == 0
|
||||
let name = 'an ' . g:bmenu_priority . '.' . hash . ' &Buffers.' . munge
|
||||
let s:bmenu_items[a:num] = munge
|
||||
let cmd = 'an ' . g:bmenu_priority . '.' . hash . ' &Buffers.' . munge
|
||||
else
|
||||
let name = 'an ' . g:bmenu_priority . '.' . hash . '.' . hash . ' &Buffers.' . <SID>BMHash2(munge) . munge
|
||||
let menu_name = <SID>BMHash2(munge) . munge
|
||||
let s:bmenu_items[a:num] = menu_name
|
||||
let cmd = 'an ' . g:bmenu_priority . '.' . hash . '.' . hash . ' &Buffers.' . menu_name
|
||||
endif
|
||||
" set 'cpo' to include the <CR>
|
||||
let cpo_save = &cpo
|
||||
set cpo&vim
|
||||
exe name . ' :confirm b' . a:num . '<CR>'
|
||||
exe cmd . ' :confirm b' . a:num . '<CR>'
|
||||
let &cpo = cpo_save
|
||||
endfunc
|
||||
|
||||
@ -804,7 +829,7 @@ endfunc
|
||||
if !exists("g:bmenu_max_pathlen")
|
||||
let g:bmenu_max_pathlen = 35
|
||||
endif
|
||||
func! s:BMTruncName(fname)
|
||||
func s:BMTruncName(fname)
|
||||
let name = a:fname
|
||||
if g:bmenu_max_pathlen < 5
|
||||
let name = ""
|
||||
@ -824,7 +849,7 @@ func! s:BMTruncName(fname)
|
||||
return name
|
||||
endfunc
|
||||
|
||||
func! s:BMMunge(fname, bnum)
|
||||
func s:BMMunge(fname, bnum)
|
||||
let name = a:fname
|
||||
if name == ''
|
||||
if !exists("g:menutrans_no_file")
|
||||
@ -941,7 +966,7 @@ cnoremenu <script> <silent> 1.100 PopUp.Select\ &All <C-U>call <SID>SelectAll()<
|
||||
if has("spell")
|
||||
" Spell suggestions in the popup menu. Note that this will slow down the
|
||||
" appearance of the menu!
|
||||
func! <SID>SpellPopup()
|
||||
func s:SpellPopup()
|
||||
if exists("s:changeitem") && s:changeitem != ''
|
||||
call <SID>SpellDel()
|
||||
endif
|
||||
@ -997,7 +1022,7 @@ if has("spell")
|
||||
call cursor(0, curcol) " put the cursor back where it was
|
||||
endfunc
|
||||
|
||||
func! <SID>SpellReplace(n)
|
||||
func s:SpellReplace(n)
|
||||
let l = getline('.')
|
||||
" Move the cursor to the start of the word.
|
||||
call spellbadword()
|
||||
@ -1005,7 +1030,7 @@ if has("spell")
|
||||
\ . strpart(l, col('.') + len(s:fromword) - 1))
|
||||
endfunc
|
||||
|
||||
func! <SID>SpellDel()
|
||||
func s:SpellDel()
|
||||
exe "aunmenu PopUp." . s:changeitem
|
||||
exe "aunmenu PopUp." . s:additem
|
||||
exe "aunmenu PopUp." . s:ignoreitem
|
||||
|
@ -5639,7 +5639,9 @@ void wipe_buffer(buf_T *buf, bool aucmd)
|
||||
void buf_open_scratch(handle_T bufnr, char *bufname)
|
||||
{
|
||||
(void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
|
||||
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
|
||||
(void)setfname(curbuf, bufname, NULL, true);
|
||||
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
|
||||
set_option_value("bh", 0L, "hide", OPT_LOCAL);
|
||||
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
|
||||
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
||||
|
@ -9914,7 +9914,11 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
// at this point the buffer has no terminal instance associated yet, so unset
|
||||
// the 'swapfile' option to ensure no swap file will be created
|
||||
curbuf->b_p_swf = false;
|
||||
|
||||
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
|
||||
(void)setfname(curbuf, (char *)NameBuff, NULL, true);
|
||||
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
|
||||
|
||||
// Save the job id and pid in b:terminal_job_{id,pid}
|
||||
Error err = ERROR_INIT;
|
||||
// deprecated: use 'channel' buffer option
|
||||
|
@ -16,7 +16,6 @@ source test_ga.vim
|
||||
source test_glob2regpat.vim
|
||||
source test_global.vim
|
||||
source test_lispwords.vim
|
||||
source test_menu.vim
|
||||
source test_move.vim
|
||||
source test_put.vim
|
||||
source test_reltime.vim
|
||||
|
@ -19,6 +19,41 @@ func Test_load_menu()
|
||||
call assert_equal('', v:errmsg)
|
||||
endfunc
|
||||
|
||||
func Test_buffer_menu_special_buffers()
|
||||
" Load in runtime menus
|
||||
try
|
||||
source $VIMRUNTIME/menu.vim
|
||||
catch
|
||||
call assert_report('error while loading menus: ' . v:exception)
|
||||
endtry
|
||||
|
||||
let v:errmsg = ''
|
||||
doautocmd LoadBufferMenu VimEnter
|
||||
call assert_equal('', v:errmsg)
|
||||
|
||||
let orig_buffer_menus = execute("nmenu Buffers")
|
||||
|
||||
" Make a new command-line window, test that it does not create a new buffer
|
||||
" menu.
|
||||
call feedkeys("q::let cmdline_buffer_menus=execute('nmenu Buffers')\<CR>:q\<CR>", 'ntx')
|
||||
call assert_equal(len(split(orig_buffer_menus, "\n")), len(split(cmdline_buffer_menus, "\n")))
|
||||
call assert_equal(orig_buffer_menus, execute("nmenu Buffers"))
|
||||
|
||||
if has('terminal')
|
||||
" Open a terminal window and test that it does not create a buffer menu
|
||||
" item.
|
||||
terminal
|
||||
let term_buffer_menus = execute('nmenu Buffers')
|
||||
call assert_equal(len(split(orig_buffer_menus, "\n")), len(split(term_buffer_menus, "\n")))
|
||||
bwipe!
|
||||
call assert_equal(orig_buffer_menus, execute("nmenu Buffers"))
|
||||
endif
|
||||
|
||||
" Remove menus to clean up
|
||||
source $VIMRUNTIME/delmenu.vim
|
||||
call assert_equal('', v:errmsg)
|
||||
endfunc
|
||||
|
||||
func Test_translate_menu()
|
||||
if !has('multi_lang')
|
||||
return
|
||||
@ -121,6 +156,7 @@ endfunc
|
||||
" Test for menu item completion in command line
|
||||
func Test_menu_expand()
|
||||
" Create the menu itmes for test
|
||||
menu Dummy.Nothing lll
|
||||
for i in range(1, 4)
|
||||
let m = 'menu Xmenu.A' .. i .. '.A' .. i
|
||||
for j in range(1, 4)
|
||||
@ -146,7 +182,7 @@ func Test_menu_expand()
|
||||
" Test for <Up> to go up a menu
|
||||
call feedkeys(":emenu Xmenu.A\<Tab>\<Down>\<Up>\<Up>\<Up>" ..
|
||||
\ "\<C-A>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"emenu Buffers. Xmenu.', @:)
|
||||
call assert_equal('"emenu Dummy. Xmenu.', @:)
|
||||
|
||||
" Test for expanding only submenus
|
||||
call feedkeys(":popup Xmenu.\<C-A>\<C-B>\"\<CR>", 'xt')
|
||||
@ -166,6 +202,7 @@ func Test_menu_expand()
|
||||
|
||||
set wildmenu&
|
||||
unmenu Xmenu
|
||||
unmenu Dummy
|
||||
|
||||
" Test for expanding popup menus with some hidden items
|
||||
menu Xmenu.foo.A1 a1
|
||||
@ -175,7 +212,6 @@ func Test_menu_expand()
|
||||
call feedkeys(":popup Xmenu.\<C-A>\<C-B>\"\<CR>", 'xt')
|
||||
call assert_equal('"popup Xmenu.foo', @:)
|
||||
unmenu Xmenu
|
||||
|
||||
endfunc
|
||||
|
||||
" Test for the menu_info() function
|
||||
|
Loading…
Reference in New Issue
Block a user