If you want g:myvar
to be a string, you could define the following commands :AddMyvar
and :RemoveMyvar
:
command! -nargs=1 -complete=customlist,s:CompleteMyvar AddMyvar
\ if !exists('g:myvar') |
\ let g:myvar = '<args>' |
\ elseif !count(split(g:myvar, ','), '<args>') |
\ let g:myvar .= ',<args>' |
\ endif
command! -nargs=1 -complete=customlist,s:CompleteMyvar RemoveMyvar
\ if exists('g:myvar') |
\ let g:myvar = join(filter(split(g:myvar, ','), "v:val !=# '<args>'"), ',') |
\ endif
function! s:CompleteMyvar(A, L, P) abort
let mycandidates = ['foo', 'bar', 'baz']
return filter(mycandidates, 'v:val =~ "^" . a:A')
endfunction
If you want g:myvar
to be a list:
command! -nargs=1 -complete=customlist,s:CompleteMyvar AddMyvar
\ if !exists('g:myvar') |
\ let g:myvar = ['<args>'] |
\ elseif !count(g:myvar, '<args>') |
\ call add(g:myvar, '<args>') |
\ endif
command! -nargs=1 -complete=customlist,s:CompleteMyvar RemoveMyvar
\ if exists('g:myvar') |
\ call filter(g:myvar, "v:val !=# '<args>'") |
\ endif
function! s:CompleteMyvar(A, L, P) abort
let mycandidates = ['foo', 'bar', 'baz']
return filter(mycandidates, 'v:val =~ "^" . a:A')
endfunction
To use the commands, you would type:
:AddMyvar newitem
to add newitem
to g:myvar
:RemoveMyvar olditem
to remove olditem
from g:myvar
The tab completion is managed by the s:CompleteMyvar()
function, which returns the list of suggestions ['foo', 'bar', 'baz']
.
If you type something after one of the commands, it is compared with the beginning of each item in the list, and only the items which match it will be returned.
You would have to edit the list mycandidates
so that the function returns the suggestions you really want.
To explain how :AddMyvar
works a little:
command! -nargs=1 -complete=customlist,s:CompleteMyvar AddMyvar
define the :AddMyvar
command which waits for one argument (-nargs=1
) and will make suggestions when you hit Tab based on what the s:CompleteMyvar()
function returns,
\ if !exists('g:myvar') |
It tests if g:myvar
does not exist,
\ let g:myvar = ['<args>'] |
if it doesn't, g:myvar
is defined as a single-item list containing the argument you provided on the command line. So if g:myvar
does not exist and you type :AddMyvar foo
then g:myvar
will be ['foo']
,
\ elseif !count(g:myvar, '<args>') |
otherwise, it checks if the argument you provided is not already present inside g:myvar
to avoid adding the same item by mistake.
count()
is a function which returns the number of times an item is present inside a list.
In a test, a non-zero value is considered as true and a zero value as false.
By prefixing the function with a bang you invert the test. non-zero will be false and zero will be true.
\ call add(g:myvar, '<args>') |
Finally, if the argument you provided was absent from g:myvar
, it's added.
If you don't like the command spreading on several lines, you could wrap the code inside a function and make the command call the latter.
How :RemoveMyvar
works :
command! -nargs=1 -complete=customlist,s:CompleteMyvar RemoveMyvar
define a similar :RemoveMyvar
command,
\ if exists('g:myvar') |
which tests if g:myvar
exists,
\ call filter(g:myvar, "v:val !=# '<args>'") |
and if it does, removes any item from g:myvar
which is not different from the argument you provided.
filter()
is a function which can take each item of a list, here g:myvar
, and test it against an arbitrary condition, here v:val !=# '<args>'
.
Inside the condition, you refer to an item from the list with the internal variable v:val
.
If the test fails, filter()
removes the item from the list.
For more information, see:
:help :command-completion-customlist
:help exists()
:help count()
:help split()
:help filter()
:help join()