From 7ceb58b2aadfcf0f5e99da83626cf88d282159b2 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Tue, 4 Feb 2020 00:35:57 +0900 Subject: [vim] Popup window support for both Vim and Neovim e.g. let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } Based on the code from https://github.com/junegunn/fzf.vim/issues/821#issuecomment-581273191 by @lacygoill. --- plugin/fzf.vim | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'plugin') diff --git a/plugin/fzf.vim b/plugin/fzf.vim index 21b7d66b..a646432b 100644 --- a/plugin/fzf.vim +++ b/plugin/fzf.vim @@ -650,7 +650,11 @@ function! s:split(dict) let ppos = s:getpos() try if s:present(a:dict, 'window') - execute 'keepalt' a:dict.window + if type(a:dict.window) == type({}) + call s:popup(a:dict.window) + else + execute 'keepalt' a:dict.window + endif elseif !s:splittable(a:dict) execute (tabpagenr()-1).'tabnew' else @@ -798,6 +802,69 @@ function! s:callback(dict, lines) abort endif endfunction +if has('nvim') + function s:create_popup(hl, opts) abort + let buf = nvim_create_buf(v:false, v:true) + let opts = extend({'relative': 'editor', 'style': 'minimal'}, a:opts) + let border = has_key(opts, 'border') ? remove(opts, 'border') : [] + let win = nvim_open_win(buf, v:true, opts) + call setwinvar(win, '&winhighlight', 'NormalFloat:'..a:hl) + call setwinvar(win, '&colorcolumn', '') + if !empty(border) + call nvim_buf_set_lines(buf, 0, -1, v:true, border) + endif + return buf + endfunction +else + function! s:create_popup(hl, opts) abort + let is_frame = has_key(a:opts, 'border') + let buf = is_frame ? '' : term_start(&shell, #{hidden: 1}) + let id = popup_create(buf, #{ + \ line: a:opts.row, + \ col: a:opts.col, + \ minwidth: a:opts.width, + \ minheight: a:opts.height, + \ zindex: 50 - is_frame, + \ }) + + if is_frame + call setwinvar(id, '&wincolor', a:hl) + call setbufline(winbufnr(id), 1, a:opts.border) + execute 'autocmd BufWipeout * ++once call popup_close('..id..')' + else + execute 'autocmd BufWipeout * ++once bwipeout! '..buf + endif + return winbufnr(id) + endfunction +endif + +function! s:popup(opts) abort + " Size and position + let width = float2nr(&columns * a:opts.width) + let height = float2nr(&lines * a:opts.height) + let row = float2nr((&lines - height) / 2) + let col = float2nr((&columns - width) / 2) + + " Border + let edges = get(a:opts, 'rounded', 1) ? ['╭', '╮', '╰', '╯'] : ['┌', '┐', '└', '┘'] + let bar = repeat('─', width - 2) + let top = edges[0] .. bar .. edges[1] + let mid = '│' .. repeat(' ', width - 2) .. '│' + let bot = edges[2] .. bar .. edges[3] + let border = [top] + repeat([mid], height - 2) + [bot] + + let highlight = get(a:opts, 'highlight', 'Comment') + let frame = s:create_popup(highlight, { + \ 'row': row, 'col': col, 'width': width, 'height': height, 'border': border + \ }) + call s:create_popup('Normal', { + \ 'row': row + 1, 'col': col + 2, 'width': width - 4, 'height': height - 2 + \ }) + if has('nvim') + execute 'autocmd BufWipeout bwipeout '..frame + endif +endfunction + let s:default_action = { \ 'ctrl-t': 'tab split', \ 'ctrl-x': 'split', -- cgit v1.2.3