Create a messagebox-like interface in vim

This commit is contained in:
Ben Jackson 2021-03-06 20:24:24 +00:00 committed by Ben Jackson
commit 4fbafaa462
4 changed files with 87 additions and 16 deletions

View file

@ -72,11 +72,7 @@ function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort
\ 'mapping': 0
\ }
" When ambiwidth is single, use prettier characters for the border. This
" would look silly when ambiwidth is double.
if &ambiwidth ==# 'single' && &encoding ==? 'utf-8'
let config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ]
endif
let config = vimspector#internal#popup#SetBorderChars( config )
if a:is_hover
let config[ 'filter' ] = 'vimspector#internal#balloon#MouseFilter'

View file

@ -83,6 +83,9 @@ endfunction
function! vimspector#internal#neopopup#Confirm( confirm_id,
\ text,
\ default_value ) abort
" Neovim doesn't have an equivalent of popup_dialog, and it's way too much
" effort to write one, so we just use confirm().
let result = confirm( a:text, '&Yes &No &Default', 3 )
" Map the results to what popup_menu_filter would return (ok s:ConfirmCallback

View file

@ -32,9 +32,32 @@ function! vimspector#internal#popup#HideSplash( id ) abort
call popup_hide( a:id )
endfunction
let s:current_selection = 0
let s:selections = []
let s:text = []
function! s:UpdatePopup( id )
let buf = copy( s:text )
call extend( buf, s:DrawButtons() )
call popup_settext( a:id, buf )
endfunction
function! s:YesNoDefaultFilter( default_value, id, key ) abort
if a:key ==# "\<CR>" || a:key ==# 'D' || a:key ==# 'd'
if a:key ==# "\<CR>"
call popup_close( a:id, s:current_selection + 1 )
return 1
elseif a:key ==# 'D' || a:key ==# 'd'
call popup_close( a:id, a:default_value )
return 1
elseif index( [ "\<Tab>", "\<Right>" ], a:key ) >= 0
let s:current_selection = ( s:current_selection + 1 ) % len( s:selections )
call s:UpdatePopup( a:id )
return 1
elseif index( [ "\<S-Tab>", "\<Left>" ], a:key ) >= 0
let s:current_selection = s:current_selection == 0
\ ? len( s:selections ) - 1: s:current_selection - 1
call s:UpdatePopup( a:id )
return 1
endif
return popup_filter_yesno( a:id, a:key )
@ -46,23 +69,68 @@ function! s:ConfirmCallback( confirm_id, id, result ) abort
\ int( vim.eval( 'a:result' ) ) )
endfunction
function! s:SelectionPosition( idx ) abort
return a:idx == 0 ? 0 : len( join( s:selections[ : a:idx - 1 ], ' ' ) ) + 1
endfunction
function! s:DrawButtons() abort
return [ {
\ 'text': join( s:selections, ' ' ),
\ 'props': [
\ {
\ 'col': s:SelectionPosition( s:current_selection ) + 1,
\ 'length': len( s:selections[ s:current_selection ] ),
\ 'type': 'VimspectorSelectedItem'
\ },
\ ]
\ } ]
endfunction
function! vimspector#internal#popup#Confirm(
\ confirm_id,
\ text,
\ options,
\ default_value ) abort
let text = a:text
if type( a:text ) != v:t_list
let text = [ a:text ]
silent! call prop_type_add( 'VimspectorSelectedItem', {
\ 'highlight': 'PMenuSel'
\ } )
let lines = split( a:text, "\n", v:true )
let buf = []
for line in lines
call add( buf, { 'text': line, 'props': [] } )
endfor
call add( buf, { 'text': '', 'props': [] } )
let s:selections = a:options
let s:current_selection = ( a:default_value - 1 )
let s:text = copy( buf )
call extend( buf, s:DrawButtons() )
let config = {
\ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ),
\ 'filter': function( 's:YesNoDefaultFilter', [ a:default_value ] ),
\ 'mapping': v:false,
\ }
let config = vimspector#internal#popup#SetBorderChars( config )
return popup_dialog( buf, config )
endfunction
function! vimspector#internal#popup#SetBorderChars( config )
" When ambiwidth is single, use prettier characters for the border. This
" would look silly when ambiwidth is double.
if &ambiwidth ==# 'single' && &encoding ==? 'utf-8'
let a:config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ]
endif
call extend( text, [ '', '(Y)es (N)o (D)efault' ] )
return popup_dialog( text, {
\ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ),
\ 'filter': function( 's:YesNoDefaultFilter', [ a:default_value ] )
\ } )
return a:config
endfunction
" Boilerplate {{{
let &cpoptions=s:save_cpo
unlet s:save_cpo

View file

@ -390,13 +390,17 @@ def ConfirmCallback( confirm_id, result ):
handler( result )
def Confirm( api_prefix, prompt, handler, default_value = 1 ):
def Confirm( api_prefix, prompt, handler, default_value = 3, options = None ):
global CONFIRM_ID
if not options:
options = [ '(Y)es', '(N)o', '(D)efault' ]
CONFIRM_ID += 1
CONFIRM[ CONFIRM_ID ] = handler
Call( f'vimspector#internal#{ api_prefix }popup#Confirm',
CONFIRM_ID,
prompt,
options,
default_value )