aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/map.txt53
-rw-r--r--runtime/doc/options.txt2
-rw-r--r--runtime/menu.vim7
3 files changed, 44 insertions, 18 deletions
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index b495b355cf..b51268eebf 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -872,35 +872,56 @@ Here is an example that counts the number of spaces with <F4>: >
" doubling <F4> works on a line
nnoremap <expr> <F4><F4> CountSpaces() .. '_'
- function CountSpaces(virtualedit = '', irregular_block = v:false, type = '') abort
+ function CountSpaces(context = {}, type = '') abort
if a:type == ''
- let &operatorfunc = function('CountSpaces', [&virtualedit, v:false])
+ let context = #{
+ \ dot_command: v:false,
+ \ extend_block: '',
+ \ virtualedit: [&l:virtualedit, &g:virtualedit],
+ \ }
+ let &operatorfunc = function('CountSpaces', [context])
set virtualedit=block
return 'g@'
endif
- let cb_save = &clipboard
- let sel_save = &selection
- let reg_save = getreginfo('"')
- let visual_marks_save = [getpos("'<"), getpos("'>")]
+ let save = #{
+ \ clipboard: &clipboard,
+ \ selection: &selection,
+ \ virtualedit: [&l:virtualedit, &g:virtualedit],
+ \ register: getreginfo('"'),
+ \ visual_marks: [getpos("'<"), getpos("'>")],
+ \ }
try
set clipboard= selection=inclusive virtualedit=
- let commands = #{line: "'[V']", char: "`[v`]", block: "`[\<C-V>`]"}->get(a:type, 'v')
- if getpos("']")[-1] != 0 || a:irregular_block
- let commands ..= 'oO$'
- let &operatorfunc = function('CountSpaces', [a:virtualedit, v:true])
+ let commands = #{
+ \ line: "'[V']",
+ \ char: "`[v`]",
+ \ block: "`[\<C-V>`]",
+ \ }[a:type]
+ let [_, _, col, off] = getpos("']")
+ if off != 0
+ let vcol = getline("'[")->strpart(0, col + off)->strdisplaywidth()
+ if vcol >= [line("'["), '$']->virtcol() - 1
+ let a:context.extend_block = '$'
+ else
+ let a:context.extend_block = vcol .. '|'
+ endif
+ endif
+ if a:context.extend_block != ''
+ let commands ..= 'oO' .. a:context.extend_block
endif
let commands ..= 'y'
execute 'silent noautocmd keepjumps normal! ' .. commands
echomsg getreg('"')->count(' ')
finally
- call setreg('"', reg_save)
- call setpos("'<", visual_marks_save[0])
- call setpos("'>", visual_marks_save[1])
- let &clipboard = cb_save
- let &selection = sel_save
- let &virtualedit = a:virtualedit
+ call setreg('"', save.register)
+ call setpos("'<", save.visual_marks[0])
+ call setpos("'>", save.visual_marks[1])
+ let &clipboard = save.clipboard
+ let &selection = save.selection
+ let [&l:virtualedit, &g:virtualedit] = get(a:context.dot_command ? save : a:context, 'virtualedit')
+ let a:context.dot_command = v:true
endtry
endfunction
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 17b91fe2b6..2e5381e5fe 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -324,7 +324,7 @@ the name, e.g. "<lambda>123". Examples:
set opfunc={a\ ->\ MyOpFunc(a)}
" set using a funcref variable
let Fn = function('MyTagFunc')
- let &tagfunc = string(Fn)
+ let &tagfunc = Fn
" set using a lambda expression
let &tagfunc = {t -> MyTagFunc(t)}
" set using a variable with lambda expression
diff --git a/runtime/menu.vim b/runtime/menu.vim
index 187818b41d..1c48d617eb 100644
--- a/runtime/menu.vim
+++ b/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: 2020 Sep 28
+" Last Change: 2021 Dec 22
" 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.
@@ -717,6 +717,11 @@ func s:BMCanAdd(name, num)
return 0
endif
+ " no name with control characters
+ if a:name =~ '[\x01-\x1f]'
+ return 0
+ endif
+
" no special buffer, such as terminal or popup
let buftype = getbufvar(a:num, '&buftype')
if buftype != '' && buftype != 'nofile' && buftype != 'nowrite'