Skip to content

Commit

Permalink
VS.Vim.Window.FloatingWindow: Support / as callback
Browse files Browse the repository at this point in the history
  • Loading branch information
hrsh7th committed Jan 10, 2021
1 parent 16b7734 commit 500db6a
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 103 deletions.
163 changes: 62 additions & 101 deletions autoload/vital/__vital__/VS/Vim/Window/FloatingWindow.vim
Original file line number Diff line number Diff line change
@@ -1,96 +1,93 @@
"
" _vital_loaded
" is_available
"
function! s:_vital_loaded(V) abort
let s:Window = a:V.import('VS.Vim.Window')
let s:Markdown = a:V.import('VS.Vim.Syntax.Markdown')
function! s:is_available() abort
if has('nvim')
return v:true
endif
return exists('*popup_create') && exists('*popup_hide') && exists('*popup_move') && exists('*popup_getpos')
endfunction

"
" _vital_depends
" managed floating windows.
"
function! s:_vital_depends() abort
return ['VS.Vim.Window', 'VS.Vim.Syntax.Markdown']
endfunction
let s:floating_windows = {}

let s:id = 0
"
" new
"
function! s:new(...) abort
call s:_init()

return s:FloatingWindow.new(get(a:000, 0, {}))
endfunction

"
" is_available
" _notify_opened
"
function! s:is_available() abort
if has('nvim')
return v:true
endif
return has('*popup_create') && has('*popup_hide') && has('*popup_move') && has('*popup_getpos')
" @param {number} win
" @param {VS.Vim.Window.FloatingWindow} floating_window
"
function! s:_notify_opened(win, floating_window) abort
let s:floating_windows[a:win] = a:floating_window
call a:floating_window.on_opened(a:floating_window)
endfunction

"
" new
" _notify_closed
"
function! s:new() abort
return s:FloatingWindow.new()
function! s:_notify_closed() abort
for [l:win, l:floating_window] in items(s:floating_windows)
if win_id2win(l:win) == 0
call l:floating_window.on_closed(l:floating_window)
unlet s:floating_windows[l:win]
endif
endfor
endfunction

let s:FloatingWindow = {}

"
" new
"
function! s:FloatingWindow.new() abort
let s:id += 1

let l:buf = bufnr(printf('VS.Vim.Window.FloatingWindow-%s', s:id), v:true)
call setbufvar(l:buf, '&buflisted', 0)
call setbufvar(l:buf, '&modeline', 0)
call setbufvar(l:buf, '&buftype', 'nofile')
call setbufvar(l:buf, '&bufhidden', 'hide')

" @param {function?} args.on_opened
" @param {function?} args.on_closed
"
function! s:FloatingWindow.new(args) abort
return extend(deepcopy(s:FloatingWindow), {
\ 'id': s:id,
\ 'buf': l:buf,
\ 'win': v:null,
\ 'on_opened': get(a:args, 'on_opened', { -> {} }),
\ 'on_closed': get(a:args, 'on_closed', { -> {} }),
\ })
endfunction

"
" open
"
" @param {number} args.row
" @param {number} args.col
" @param {string} args.filetype
" @param {string[]} args.contents
" @param {number?} args.maxwidth
" @param {number?} args.minwidth
" @param {number?} args.maxheight
" @param {number?} args.minheight
" @param {number} args.row 0-based indexing
" @param {number} args.col 0-based indexing
" @param {number} args.width
" @param {number} args.height
" @param {string} args.winhl
" @param {number} args.bufnr
"
function! s:FloatingWindow.open(args) abort
let a:args.contents = type(a:args.contents) == type('')
\ ? split(a:args.contents, "\n", v:true)
\ : a:args.contents

let l:size = self.get_size(a:args)
let l:style = {
\ 'row': a:args.row,
\ 'col': a:args.col,
\ 'width': l:size.width,
\ 'height': l:size.height,
\ 'width': a:args.width,
\ 'height': a:args.height,
\ }

if self.is_visible()
call s:_move(self.win, l:style)
else
let self.win = s:_open(self.buf, l:style)
call setwinvar(self.win, '&conceallevel', 2)
call setwinvar(self.win, '&wrap', 1)
let self.win = s:_open(a:args.bufnr, l:style)
if has('nvim')
call setwinvar(self.win, '&winhighlight', get(a:args, 'winhl', ''))
endif
call s:_notify_opened(self.win, self)
endif

call self.set_contents(a:args.filetype, a:args.contents)
endfunction

"
Expand All @@ -99,6 +96,7 @@ endfunction
function! s:FloatingWindow.close() abort
if self.is_visible()
call s:_close(self.win)
call s:_notify_closed()
endif
let self.win = v:null
endfunction
Expand All @@ -117,58 +115,6 @@ function! s:FloatingWindow.is_visible() abort
return s:_exists(self.win) ? v:true : v:false
endfunction

"
" get_size
"
function! s:FloatingWindow.get_size(args) abort
let a:args.contents = type(a:args.contents) == type('')
\ ? split(a:args.contents, "\n", v:true)
\ : a:args.contents

let l:maxwidth = get(a:args, 'maxwidth', -1)
let l:minwidth = get(a:args, 'minwidth', -1)
let l:maxheight = get(a:args, 'maxheight', -1)
let l:minheight = get(a:args, 'minheight', -1)

" width
let l:width = 0
for l:content in a:args.contents
let l:width = max([l:width, strdisplaywidth(l:content)])
endfor
let l:width = l:minwidth == -1 ? l:width : max([l:minwidth, l:width])
let l:width = l:maxwidth == -1 ? l:width : min([l:maxwidth, l:width])

" height
let l:height = len(a:args.contents)
for l:content in a:args.contents
let l:wrap = float2nr(ceil(strdisplaywidth(l:content) / str2float('' . l:width)))
if l:wrap > 1
let l:height += l:wrap - 1
endif
endfor
let l:height = l:minheight == -1 ? l:height : max([l:minheight, l:height])
let l:height = l:maxheight == -1 ? l:height : min([l:maxheight, l:height])

return {
\ 'width': max([1, l:width]),
\ 'height': max([1, l:height]),
\ }
endfunction

"
" set_contents
"
function! s:FloatingWindow.set_contents(filetype, contents) abort
call deletebufline(self.buf, '^', '$')
call setbufline(self.buf, 1, a:contents)

if a:filetype ==# 'markdown'
call s:Window.do(self.win, { -> s:Markdown.apply(join(a:contents, "\n")) })
else
call setbufvar(self.buf, '&filetype', a:filetype)
endif
endfunction

"
" open
"
Expand Down Expand Up @@ -266,3 +212,18 @@ else
endfunction
endif

"
" init
"
let s:has_init = v:false
function! s:_init() abort
if s:has_init
return
endif
let s:has_init = v:true
augroup printf('<sfile>')
autocmd!
autocmd WinEnter * call <SID>_notify_closed()
augroup END
endfunction

46 changes: 44 additions & 2 deletions autoload/vital/__vital__/VS/Vim/Window/FloatingWindow.vimspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,57 @@ Describe vital#__vital__#VS#Vim#Window#FloatingWindow
call l:win.open({
\ 'row': 1,
\ 'col': 1,
\ 'filetype': 'text',
\ 'contents': ['Hello, World!'],
\ 'width': 10,
\ 'height': 10,
\ 'bufnr': bufnr('test', v:true),
\ })
call s:expect(l:win.is_visible()).to_equal(v:true)
call l:win.close()
call s:expect(l:win.is_visible()).to_equal(v:false)
End
End

Describe #on_close
It should callback on window was method
let l:bufnr = bufnr('test', v:true)
let s:closed = v:false
let l:win = s:FloatingWindow.new({
\ 'on_closed': { win -> execute('let s:closed = v:true') }
\ })
call l:win.open({
\ 'row': 1,
\ 'col': 1,
\ 'width': 10,
\ 'height': 10,
\ 'bufnr': l:bufnr,
\ })
call l:win.close()
call s:expect(s:closed).to_equal(v:true)
End
It should callback on window was closed by command (nvim only)
if !has('nvim')
return
endif

let l:bufnr = bufnr('test', v:true)
let s:closed = v:false
let l:win = s:FloatingWindow.new({
\ 'on_closed': { win -> execute('let s:closed = v:true') }
\ })
call l:win.open({
\ 'row': 1,
\ 'col': 1,
\ 'width': 10,
\ 'height': 10,
\ 'bufnr': l:bufnr,
\ })
call l:win.enter()
call s:expect(bufnr('%')).to_equal(l:bufnr)
call execute('close')
call s:expect(s:closed).to_equal(v:true)
End
End

End


0 comments on commit 500db6a

Please sign in to comment.