我正在开发一个vim插件。配置参数有一组有效选项。我希望用户能够从列表中选择他们想要的选项。
这与inputlist
类似,但inputlist
仅返回单个所选元素的索引。我更喜欢它返回所有选定元素的索引。
我如何在vim中创建mutliselect?
答案 0 :(得分:2)
我不确切地知道你想要哪种界面,但是既然你提到了inputlist()
,我认为你可以简单地编写一个循环,它的主体会调用它。
也许是这样的:
let options_chosen = []
let options_valid = [
\ 'foo',
\ 'bar',
\ 'baz',
\ 'qux',
\ 'norf'
\ ]
for i in range(1,len(options_valid))
let choice = inputlist([ 'Select your options:' ]
\ + map(copy(options_valid), '(v:key+1).". ".v:val'))
if choice >= 1 && choice <= len(copy(options_valid))
let options_chosen += [copy(options_valid)[choice - 1]]
let options_valid = filter(options_valid, 'v:val !=# options_chosen[-1]')
else
break
endif
redraw
endfor
如果您执行此代码,则应该允许您从列表options_valid
中选择一个选项。在每次迭代之后,它应该在列表options_chosen
中添加所选项,并将其从列表options_valid
中删除。循环最初迭代的次数与options_valid
中的项目一样多。完成后,您可以点击Escape
。
它可能不是你想要的,因为我不知道你想向用户呈现什么接口:命令,映射,交互式缓冲......但它可能是一个开始,你可以建立别的东西。
以交互式缓冲区作为界面,我提出了这个:
let s:options_valid = ['foo', 'bar', 'baz', 'qux', 'norf']
com! MultipleOptions call s:multiple_options()
fu! s:multiple_options() abort
vnew | exe 'vert resize '.(&columns/3)
setl bh=wipe bt=nofile nobl noswf nowrap
if !bufexists('Multiple Options') | sil file Multiple\ Options | endif
sil! 0put =s:options_valid
sil! $d_
setl noma ro
nno <silent> <buffer> <nowait> q :<c-u>close<cr>
nno <silent> <buffer> <nowait> <cr> :<c-u>call <sid>toggle_option()<cr>
augroup multi_op_close
au!
au WinLeave <buffer> call s:close()
augroup END
endfu
fu! s:close() abort
let g:selected_options = exists('w:options_chosen')
\ ? map(w:options_chosen.lines, 's:options_valid[v:val-1]')
\ : []
au! multi_op_close | aug! multi_op_close
close
endfu
fu! s:toggle_option() abort
if !exists('w:options_chosen')
let w:options_chosen = { 'lines' : [], 'pattern' : '', 'id' : 0 }
else
if w:options_chosen.id
call matchdelete(w:options_chosen.id)
let w:options_chosen.pattern .= '|'
endif
endif
if !empty(w:options_chosen.lines) && count(w:options_chosen.lines, line('.'))
call filter(w:options_chosen.lines, "v:val != line('.')")
else
let w:options_chosen.lines += [ line('.') ]
endif
let w:options_chosen.pattern = '\v'.join(map(
\ copy(w:options_chosen.lines),
\ "'%'.v:val.'l'"
\ ), '|')
let w:options_chosen.id = !empty(w:options_chosen.lines)
\ ? matchadd('IncSearch', w:options_chosen.pattern)
\ : 0
endfu
如果执行命令:MultipleOptions
,它应该打开一个临时垂直视口,其中应显示存储在列表s:options_valid
中的选项。
从那里,您可以点击Enter
来选择或取消选择当前行。选择某个选项后,其行将使用突出显示组IncSearch
进行着色。
完成后,您可以关闭窗口q
,所有选择的选项都应在g:selected_options
内。
答案 1 :(得分:2)
在lh-vim-lib中,我提供了一个lh#ui#check()
功能。其行为类似于文本模式中的confirm()
。即我依靠一个破坏状态线的旧技巧。 (这需要使用"\r"
,:redraw
等等)
您可以在screencast I've made for lh-tags中看到它。等待“你想要显示哪种?”题。 (在截屏视频中,您应该看到包含CHECK
,CONFIRM
和CHOOSE
的旧代码
BTW,也可以使用lh-tags中用于选择一个条目的对话框(将tagged
参数设置为1)一次选择多个条目。