From 8b0e1f941a419258b0877d9a5f71373d76472043 Mon Sep 17 00:00:00 2001 From: Tom Picton Date: Sat, 17 Apr 2021 04:48:10 -0700 Subject: [PATCH] [vim] Support relative-to-window positioning of popup (#2443) Co-authored-by: Junegunn Choi --- README-VIM.md | 10 +++++++++- doc/fzf.txt | 16 ++++++++++++---- plugin/fzf.vim | 16 ++++++++++++---- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/README-VIM.md b/README-VIM.md index b934c232..b54c4fae 100644 --- a/README-VIM.md +++ b/README-VIM.md @@ -127,9 +127,15 @@ let g:fzf_action = { \ 'ctrl-v': 'vsplit' } " Default fzf layout -" - Popup window +" - Popup window (center of the screen) let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } +" - Popup window (center of the current window) +let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6, 'relative': v:true } } + +" - Popup window (anchored to the bottom of the current window) +let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6, 'relative': v:true, 'yoffset': 1.0 } } + " - down / up / left / right let g:fzf_layout = { 'down': '40%' } @@ -302,6 +308,7 @@ following options are allowed: - Optional: - `yoffset` [float default 0.5 range [0 ~ 1]] - `xoffset` [float default 0.5 range [0 ~ 1]] + - `relative` [boolean default v:false] - `border` [string default `rounded`]: Border style - `rounded` / `sharp` / `horizontal` / `vertical` / `top` / `bottom` / `left` / `right` / `no[ne]` @@ -410,6 +417,7 @@ The latest versions of Vim and Neovim include builtin terminal emulator " Optional: " - xoffset [float default 0.5 range [0 ~ 1]] " - yoffset [float default 0.5 range [0 ~ 1]] +" - relative [boolean default v:false] " - border [string default 'rounded']: Border style " - 'rounded' / 'sharp' / 'horizontal' / 'vertical' / 'top' / 'bottom' / 'left' / 'right' let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } diff --git a/doc/fzf.txt b/doc/fzf.txt index 43ebb1c4..ed8a9e3a 100644 --- a/doc/fzf.txt +++ b/doc/fzf.txt @@ -1,4 +1,4 @@ -fzf.txt fzf Last change: January 3 2021 +fzf.txt fzf Last change: April 17 2021 FZF - TABLE OF CONTENTS *fzf* *fzf-toc* ============================================================================== @@ -155,9 +155,15 @@ Examples~ \ 'ctrl-v': 'vsplit' } " Default fzf layout - " - Popup window + " - Popup window (center of the screen) let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } + " - Popup window (center of the current window) + let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6, 'relative': v:true } } + + " - Popup window (anchored to the bottom of the current window) + let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6, 'relative': v:true, 'yoffset': 1.0 } } + " - down / up / left / right let g:fzf_layout = { 'down': '40%' } @@ -318,6 +324,7 @@ following options are allowed: - Optional: - `yoffset` [float default 0.5 range [0 ~ 1]] - `xoffset` [float default 0.5 range [0 ~ 1]] + - `relative` [boolean default v:false] - `border` [string default `rounded`]: Border style - `rounded` / `sharp` / `horizontal` / `vertical` / `top` / `bottom` / `left` / `right` / `no[ne]` @@ -372,7 +379,7 @@ last `fullscreen` argument of `fzf#wrap` (see :help ). Our `:LS` command will be much more useful if we can pass a directory argument to it, so that something like `:LS /tmp` is possible. > - command! -bang -complete=dir -nargs=* LS + command! -bang -complete=dir -nargs=? LS \ call fzf#run(fzf#wrap({'source': 'ls', 'dir': }, 0)) < Lastly, if you have enabled `g:fzf_history_dir`, you might want to assign a @@ -380,7 +387,7 @@ unique name to our command and pass it as the first argument to `fzf#wrap`. > " The query history for this command will be stored as 'ls' inside g:fzf_history_dir. " The name is ignored if g:fzf_history_dir is not defined. - command! -bang -complete=dir -nargs=* LS + command! -bang -complete=dir -nargs=? LS \ call fzf#run(fzf#wrap('ls', {'source': 'ls', 'dir': }, 0)) < @@ -423,6 +430,7 @@ Starting fzf in a popup window~ " Optional: " - xoffset [float default 0.5 range [0 ~ 1]] " - yoffset [float default 0.5 range [0 ~ 1]] + " - relative [boolean default v:false] " - border [string default 'rounded']: Border style " - 'rounded' / 'sharp' / 'horizontal' / 'vertical' / 'top' / 'bottom' / 'left' / 'right' let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } } diff --git a/plugin/fzf.vim b/plugin/fzf.vim index 26dcf974..9cebed48 100644 --- a/plugin/fzf.vim +++ b/plugin/fzf.vim @@ -972,11 +972,19 @@ else endif function! s:popup(opts) abort + let xoffset = get(a:opts, 'xoffset', 0.5) + let yoffset = get(a:opts, 'yoffset', 0.5) + let relative = get(a:opts, 'relative', 0) + + " Use current window size for positioning relatively positioned popups + let columns = relative ? winwidth(0) : &columns + let lines = relative ? winheight(0) : &lines + " Size and position - let width = min([max([8, a:opts.width > 1 ? a:opts.width : float2nr(&columns * a:opts.width)]), &columns]) - let height = min([max([4, a:opts.height > 1 ? a:opts.height : float2nr(&lines * a:opts.height)]), &lines - has('nvim')]) - let row = float2nr(get(a:opts, 'yoffset', 0.5) * (&lines - height)) - let col = float2nr(get(a:opts, 'xoffset', 0.5) * (&columns - width)) + let width = min([max([8, a:opts.width > 1 ? a:opts.width : float2nr(columns * a:opts.width)]), columns]) + let height = min([max([4, a:opts.height > 1 ? a:opts.height : float2nr(lines * a:opts.height)]), lines - has('nvim')]) + let row = float2nr(yoffset * (lines - height)) + (relative ? win_screenpos(0)[0] : 0) + let col = float2nr(xoffset * (columns - width)) + (relative ? win_screenpos(0)[1] : 0) " Managing the differences let row = min([max([0, row]), &lines - has('nvim') - height])