summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2020-02-04 00:35:57 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2020-02-04 00:35:57 +0900
commit7ceb58b2aadfcf0f5e99da83626cf88d282159b2 (patch)
tree814a058c79dcb2e8a2b7a79d3977109675fb5c95
parent293dd76af14ff47cde08281b0e2d5f7dd1ce46af (diff)
[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.
-rw-r--r--README-VIM.md56
-rw-r--r--doc/fzf.txt47
-rw-r--r--plugin/fzf.vim69
3 files changed, 111 insertions, 61 deletions
diff --git a/README-VIM.md b/README-VIM.md
index 554d748a..103b8e52 100644
--- a/README-VIM.md
+++ b/README-VIM.md
@@ -184,6 +184,7 @@ The following table summarizes the available options.
| `dir` | string | Working directory |
| `up`/`down`/`left`/`right` | number/string | (Layout) Window position and size (e.g. `20`, `50%`) |
| `window` (Vim 8 / Neovim) | string | (Layout) Command to open fzf window (e.g. `vertical aboveleft 30new`) |
+| `window` (Vim 8 / Neovim) | dict | (Layout) Popup window settings (e.g. `{'width': 0.9, 'height': 0.6}`) |
`options` entry can be either a string or a list. For simple cases, string
should suffice, but prefer to use list type to avoid escaping issues.
@@ -193,6 +194,16 @@ call fzf#run({'options': '--reverse --prompt "C:\\Program Files\\"'})
call fzf#run({'options': ['--reverse', '--prompt', 'C:\Program Files\']})
```
+When `window` entry is a dictionary, fzf will start in a popup window. The
+following options are allowed:
+
+- Required:
+ - `width` [float]
+ - `height` [float]
+- Optional:
+ - `highlight` [string default `'Comment'`]: Highlight group for border
+ - `rounded` [boolean default `v:true`]: Use rounded border
+
`fzf#wrap`
----------
@@ -276,44 +287,17 @@ The latest versions of Vim and Neovim include builtin terminal emulator
- On Terminal Vim with a non-default layout
- `call fzf#run({'left': '30%'})` or `let g:fzf_layout = {'left': '30%'}`
-#### Starting fzf in Neovim floating window
+#### Starting fzf in a popup window
```vim
-" Using floating windows of Neovim to start fzf
-if has('nvim')
- function! FloatingFZF(width, height, border_highlight)
- function! s:create_float(hl, opts)
- let buf = nvim_create_buf(v:false, v:true)
- let opts = extend({'relative': 'editor', 'style': 'minimal'}, a:opts)
- let win = nvim_open_win(buf, v:true, opts)
- call setwinvar(win, '&winhighlight', 'NormalFloat:'.a:hl)
- call setwinvar(win, '&colorcolumn', '')
- return buf
- endfunction
-
- " Size and position
- let width = float2nr(&columns * a:width)
- let height = float2nr(&lines * a:height)
- let row = float2nr((&lines - height) / 2)
- let col = float2nr((&columns - width) / 2)
-
- " Border
- let top = '╭' . repeat('─', width - 2) . '╮'
- let mid = '│' . repeat(' ', width - 2) . '│'
- let bot = '╰' . repeat('─', width - 2) . '╯'
- let border = [top] + repeat([mid], height - 2) + [bot]
-
- " Draw frame
- let s:frame = s:create_float(a:border_highlight, {'row': row, 'col': col, 'width': width, 'height': height})
- call nvim_buf_set_lines(s:frame, 0, -1, v:true, border)
-
- " Draw viewport
- call s:create_float('Normal', {'row': row + 1, 'col': col + 2, 'width': width - 4, 'height': height - 2})
- autocmd BufWipeout <buffer> execute 'bwipeout' s:frame
- endfunction
-
- let g:fzf_layout = { 'window': 'call FloatingFZF(0.9, 0.6, "Comment")' }
-endif
+" Required:
+" - width [float]
+" - height [float]
+"
+" Optional:
+" - highlight [string default 'Comment']: Highlight group for border
+" - rounded [boolean default v:true]: Use rounded border
+let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } }
```
#### Hide statusline
diff --git a/doc/fzf.txt b/doc/fzf.txt
index d0744c73..51f0d43f 100644
--- a/doc/fzf.txt
+++ b/doc/fzf.txt
@@ -1,4 +1,4 @@
-fzf.txt fzf Last change: November 23 2019
+fzf.txt fzf Last change: February 3 2020
FZF - TABLE OF CONTENTS *fzf* *fzf-toc*
==============================================================================
@@ -11,7 +11,7 @@ FZF - TABLE OF CONTENTS *fzf* *fzf-to
fzf#wrap
Tips
fzf inside terminal buffer
- Starting fzf in Neovim floating window
+ Starting fzf in a popup window
Hide statusline
License
@@ -204,6 +204,7 @@ The following table summarizes the available options.
`dir` | string | Working directory
`up` / `down` / `left` / `right` | number/string | (Layout) Window position and size (e.g. `20` , `50%` )
`window` (Vim 8 / Neovim) | string | (Layout) Command to open fzf window (e.g. `vertical aboveleft 30new` )
+ `window` (Vim 8 / Neovim) | dict | (Layout) Popup window settings (e.g. `{'width': 0.9, 'height': 0.6}` )
---------------------------+---------------+----------------------------------------------------------------------
`options` entry can be either a string or a list. For simple cases, string
@@ -212,6 +213,16 @@ should suffice, but prefer to use list type to avoid escaping issues.
call fzf#run({'options': '--reverse --prompt "C:\\Program Files\\"'})
call fzf#run({'options': ['--reverse', '--prompt', 'C:\Program Files\']})
<
+When `window` entry is a dictionary, fzf will start in a popup window. The
+following options are allowed:
+
+ - Required:
+ - `width` [float]
+ - `height` [float]
+ - Optional:
+ - `highlight` [string default `'Comment'`]: Highlight group for border
+ - `rounded` [boolean default `v:true`]: Use rounded border
+
FZF#WRAP
==============================================================================
@@ -291,29 +302,17 @@ The latest versions of Vim and Neovim include builtin terminal emulator
- `call fzf#run({'left': '30%'})` or `let g:fzf_layout = {'left': '30%'}`
-Starting fzf in Neovim floating window~
- *fzf-starting-fzf-in-neovim-floating-window*
+Starting fzf in a popup window~
+ *fzf-starting-fzf-in-a-popup-window*
>
- " Using floating windows of Neovim to start fzf
- if has('nvim')
- let $FZF_DEFAULT_OPTS .= ' --border --margin=0,2'
-
- function! FloatingFZF()
- let width = float2nr(&columns * 0.9)
- let height = float2nr(&lines * 0.6)
- let opts = { 'relative': 'editor',
- \ 'row': (&lines - height) / 2,
- \ 'col': (&columns - width) / 2,
- \ 'width': width,
- \ 'height': height }
-
- let win = nvim_open_win(nvim_create_buf(v:false, v:true), v:true, opts)
- call setwinvar(win, '&winhighlight', 'NormalFloat:Normal')
- endfunction
-
- let g:fzf_layout = { 'window': 'call FloatingFZF()' }
- endif
-
+ " Required:
+ " - width [float]
+ " - height [float]
+ "
+ " Optional:
+ " - highlight [string default 'Comment']: Highlight group for border
+ " - rounded [boolean default v:true]: Use rounded border
+ let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } }
<
Hide statusline~
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 <buffer> bwipeout '..frame
+ endif
+endfunction
+
let s:default_action = {
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',