Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating Windows Support VIM Popup #821

Closed
3 of 9 tasks
blayz3r opened this issue Jun 6, 2019 · 41 comments
Closed
3 of 9 tasks

Floating Windows Support VIM Popup #821

blayz3r opened this issue Jun 6, 2019 · 41 comments

Comments

@blayz3r
Copy link

blayz3r commented Jun 6, 2019

  • Category
    • Question
    • Bug
    • Suggestion
  • OS
    • Linux
    • macOS
    • Windows
    • Etc.
  • Vim
    • Vim
    • Neovim

Does the new VIM popup feature enable FZF to float in VIM

@junegunn
Copy link
Owner

junegunn commented Jun 8, 2019

the new VIM popup feature

If floating windows of Neovim is what you meant, see #664.

@blayz3r
Copy link
Author

blayz3r commented Jun 8, 2019

I meant Vim proper. Can the same be achieved with Vim's Popup feature?

@junegunn
Copy link
Owner

junegunn commented Jun 8, 2019

I don't know about "the new VIM popup feature". Can you explain what it is? Any reference?

@blayz3r
Copy link
Author

blayz3r commented Jun 8, 2019

There was discussion here vim/vim#4063 and possible with use with FZF like plugins here vim/vim#4063 (comment)

@dkarter
Copy link

dkarter commented Aug 2, 2019

@junegunn it looks something like this:

It is supported in both NeoVim and Vim.

Plugins such as denite.nvim, coc.nvim, vimgon-quest-menu, etc have already implemented it if you are curious to see how it's done.

@blayz3r
Copy link
Author

blayz3r commented Oct 6, 2019

like liuchengxu/vim-clap

@dkarter
Copy link

dkarter commented Oct 7, 2019

for those of you who are still looking, check out this config from the creator of FZF (@junegunn): https://github.com/junegunn/dotfiles/commit/9545174d0e34075d16c1d6a01eed820bce9d6cc0

@tracyone
Copy link

tracyone commented Oct 7, 2019

@dkarter

    if has('nvim') && exists('&winblend') && &termguicolors

Only for neovim, but we want vim too

@dkarter
Copy link

dkarter commented Oct 7, 2019

Right. Didn't realize that - my bad.

@dpretet
Copy link

dpretet commented Oct 10, 2019

Would love to this setup/feature possible with Vim8! Any news?

@runar
Copy link

runar commented Oct 27, 2019

I spent a few hours on this today, but ended up with nothing: The results from fzf is printed in the background with the popup (floating window) hovering on top of it. I couldn’t get the result to fill the popup, so it seems I’ll have to leave this to someone more experienced than myself.

@dpretet
Copy link

dpretet commented Oct 27, 2019

@runar can you share your code please? I don’t have so much experience on vim plugin but if I can help :)

@runar
Copy link

runar commented Oct 27, 2019

@damofthemoon There’s not really any code to share, as all I did was read the Vim documentation on popup windows and try to convert this function to use popup_create().

I don’t understand what the second parameter (call FloatingFZF()) of the below line should be. Is it expecting a window id or buffer number, or a window or buffer instance? What should FloatingFZF() return for this to work?

let g:fzf_layout = { 'window': 'call FloatingFZF()’ }

@dpretet
Copy link

dpretet commented Oct 28, 2019

No better result than you @runar... I can't figure out how it could work for Vim8, I suspect Nvim handles differently pop-up feature 🤔

@runar
Copy link

runar commented Nov 29, 2019

@lightalchemist I'm aware of that, which is why I’m referencing the same commit (where FloatingFZF() is defined) as you do. The problem, as I wrote in my post, is that I’m unable to rewrite the function to make it work for Vim.

What I don't know, is what kind of values g:fzf_layout expects. The first one should be window, but what kind of value is expected where call FloatingFZF() is used? A window id? Buffer number? Or a window or buffer instance? I’ve tried them all without success.

@junegunn
Copy link
Owner

Repository owner deleted a comment from srijanshetty Nov 29, 2019
@runar
Copy link

runar commented Nov 29, 2019

@junegunn Just what I needed, thank you! I will take a new look at this later.

@dpretet
Copy link

dpretet commented Nov 29, 2019

I can only create a popup with Vim8 but not fill it with FZF output. Another thing disturbing me is the popup needs to be clear with popup_clear() function, it doesn't disappear automatically. Can we access a kind of callback to clean that @junegunn? Any idea why we can't fill the popup with FZF?

@junegunn
Copy link
Owner

junegunn commented Dec 2, 2019

I'm a Neovim user, and I have no experience with Vim popups. You might want to read the linked issue above.

vim/vim#4063 (comment)

Bram doesn't seem to understand why we want to open a terminal buffer (running fzf) inside a popup window.

@dpretet
Copy link

dpretet commented Dec 2, 2019

Thanks for pointing this problem @junegunn, now I understand the problem better. I see in the issue tracking a solution could exist but it sounds to me tricky while it's simple to open FZF in a pane (I did try with let g:fzf_layout = { 'window': 'vs' } and it works like a charm). Maybe that's a good opportunity to switch to Neovim 🤓.

@blayz3r
Copy link
Author

blayz3r commented Dec 4, 2019

Yggdroot/LeaderF and liuchengxu/vim-clap have workarounds

@junegunn
Copy link
Owner

junegunn commented Dec 4, 2019

@blayz3r They are native Vim plugins unlike fzf, so they don't have the problem.

@blayz3r
Copy link
Author

blayz3r commented Feb 1, 2020

vim/vim@219c7d0

@lacygoill
Copy link

lacygoill commented Feb 3, 2020

FWIW, this seems to make fzf display its terminal buffer in a Vim popup window:

fu s:snr() abort
    return matchstr(expand('<sfile>'), '.*\zs<SNR>\d\+_')
endfu
let s:snr = get(s:, 'snr', s:snr())
let g:fzf_layout = {'window': 'call '..s:snr..'fzf_window(0.9, 0.6, "Comment")'}

fu s:fzf_window(width, height, border_highlight) abort
    let width = float2nr(&columns * a:width)
    let height = float2nr(&lines * a:height)
    let row = float2nr((&lines - height) / 2)
    let col = float2nr((&columns - width) / 2)
    let top = '┌' . repeat('─', width - 2) . '┐'
    let mid = '│' . repeat(' ', width - 2) . '│'
    let bot = '└' . repeat('─', width - 2) . '┘'
    let border = [top] + repeat([mid], height - 2) + [bot]
    let frame = s:create_popup_window(a:border_highlight, {
        \ 'line': row,
        \ 'col': col,
        \ 'width': width,
        \ 'height': height,
        \ 'is_frame': 1,
        \ })
    call setbufline(frame, 1, border)
    call s:create_popup_window('Normal', {
        \ 'line': row + 1,
        \ 'col': col + 2,
        \ 'width': width - 4,
        \ 'height': height - 2,
        \ })
endfu

fu s:create_popup_window(hl, opts) abort
    if has_key(a:opts, 'is_frame')
        let id = popup_create('', #{
            \ line: a:opts.line,
            \ col: a:opts.col,
            \ minwidth: a:opts.width,
            \ minheight: a:opts.height,
            \ zindex: 50,
            \ })
        call setwinvar(id, '&wincolor', a:hl)
        exe 'au BufWipeout * ++once call popup_close('..id..')'
        return winbufnr(id)
    else
        let buf = term_start(&shell, #{hidden: 1})
        call popup_create(buf, #{
            \ line: a:opts.line,
            \ col: a:opts.col,
            \ minwidth: a:opts.width,
            \ minheight: a:opts.height,
            \ zindex: 51,
            \ })
        exe 'au BufWipeout * ++once bw! '..buf
    endif
endfu

The code is similar to the one for Nvim documented in the wiki. You can configure the width and the height of the window (as a percentage of the total width/height available), as well as the color of the border, by changing the arguments passed to s:fzf_window():

let g:fzf_layout = {'window': 'call '..s:snr..'fzf_window(0.9, 0.6, "Comment")'}
                                                          │    │     │
                                                          │    │     └ border's highlight group
                                                          │    └ height
                                                          └ width

To support both Vim and Neovim:

fu s:snr() abort
    return matchstr(expand('<sfile>'), '.*\zs<SNR>\d\+_')
endfu
let s:snr = get(s:, 'snr', s:snr())
let g:fzf_layout = {'window': 'call '..s:snr..'fzf_window(0.9, 0.6, "Comment")'}

fu s:fzf_window(width, height, border_highlight) abort
    let width = float2nr(&columns * a:width)
    let height = float2nr(&lines * a:height)
    let row = float2nr((&lines - height) / 2)
    let col = float2nr((&columns - width) / 2)
    let top = '┌' . repeat('─', width - 2) . '┐'
    let mid = '│' . repeat(' ', width - 2) . '│'
    let bot = '└' . repeat('─', width - 2) . '┘'
    let border = [top] + repeat([mid], height - 2) + [bot]
    if has('nvim')
        let frame = s:create_float(a:border_highlight, {
            \ 'row': row,
            \ 'col': col,
            \ 'width': width,
            \ 'height': height,
            \ })
        call nvim_buf_set_lines(frame, 0, -1, v:true, border)
        call s:create_float('Normal', {
            \ 'row': row + 1,
            \ 'col': col + 2,
            \ 'width': width - 4,
            \ 'height': height - 2,
            \ })
        exe 'au BufWipeout <buffer> bw '..frame
    else
        let frame = s:create_popup_window(a:border_highlight, {
            \ 'line': row,
            \ 'col': col,
            \ 'width': width,
            \ 'height': height,
            \ 'is_frame': 1,
            \ })
        call setbufline(frame, 1, border)
        call s:create_popup_window('Normal', {
            \ 'line': row + 1,
            \ 'col': col + 2,
            \ 'width': width - 4,
            \ 'height': height - 2,
            \ })
    endif
endfu

fu s:create_float(hl, opts) abort
    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)
    return buf
endfu

fu s:create_popup_window(hl, opts) abort
    if has_key(a:opts, 'is_frame')
        let id = popup_create('', #{
            \ line: a:opts.line,
            \ col: a:opts.col,
            \ minwidth: a:opts.width,
            \ minheight: a:opts.height,
            \ zindex: 50,
            \ })
        call setwinvar(id, '&wincolor', a:hl)
        exe 'au BufWipeout * ++once call popup_close('..id..')'
        return winbufnr(id)
    else
        let buf = term_start(&shell, #{hidden: 1})
        call popup_create(buf, #{
            \ line: a:opts.line,
            \ col: a:opts.col,
            \ minwidth: a:opts.width,
            \ minheight: a:opts.height,
            \ zindex: 51,
            \ })
        exe 'au BufWipeout * ++once bw! '..buf
    endif
endfu

If I find issues, I'll try to fix them here and here.

@blayz3r
Copy link
Author

blayz3r commented Feb 3, 2020

@lacygoill Excellent works flawlessly
image

@blayz3r blayz3r closed this as completed Feb 3, 2020
@junegunn
Copy link
Owner

junegunn commented Feb 3, 2020

@lacygoill Thanks, I'll consider adding that to the main fzf repo so anyone can easily use it.

junegunn added a commit to junegunn/fzf that referenced this issue Feb 3, 2020
e.g.
  let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } }

Based on the code from junegunn/fzf.vim#821 (comment)
by @lacygoill.
@junegunn
Copy link
Owner

junegunn commented Feb 3, 2020

Popup support added in junegunn/fzf@7ceb58b.

let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } }

" Border color
let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6, 'highlight': 'Todo' } }

" Border style (rounded / sharp / horizontal)
let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6, 'highlight': 'Todo', 'border': 'sharp' } }

Works for me fine both on Vim and Neovim. 😄

evantravers added a commit to evantravers/dotfiles that referenced this issue Feb 3, 2020
@jesseleite
Copy link
Contributor

Is it still possible to align the fzf results at the bottom, but still as a popup to prevent fzf from pushing the active buffer upwards off the screen?

@mhanberg
Copy link

mhanberg commented Feb 4, 2020

@junegunn will you be releasing a new version of fzf soon so I can take advantage of this behavior? I use fzf through homebrew.

Thanks!

@junegunn
Copy link
Owner

junegunn commented Feb 4, 2020

@mhanberg Yes, I will. But there are some nice stuff on the review queue that I'd like to include in the next release, so it will take a few more days. You might already know this, but you can still use the latest vim plugin of fzf even if you installed the binary via Homebrew. Plug 'junegunn/fzf' will make vim-plug clone the main fzf repo on a separate directory and load the vim plugin file from there while using the binary on $PATH. You might want to take a look at the updated installation instruction which hopefully clears up some confusion: https://github.com/junegunn/fzf.vim#installation

@jesseleite While the above dictionary form ({ 'window': { ... } }) currently doesn't support options for positioning the window, you can still write a function that does that and use it as the layout. But yeah, it's a bit of a hassle, do you have any suggestions? Would yoffset suffice?

@097115
Copy link

097115 commented Feb 4, 2020

@junegunn, if you don't mind, I'm not exactly getting why fzf ships with some additional Vim plugin? Why fzf.vim is not enough, is not the only place for al the Vim-related stuff?

Just trying to clarify the structure in my head :)

Thanks.

@henrebotha
Copy link

The new feature crashed my machine before I updated my Vim to 8.2. I think a feature guard of some description is in order!

@rogchap
Copy link

rogchap commented Feb 4, 2020

I have a local fzf#run() is there a way to get this to except the window dictionary for it's layout?
eg:

 fzf#run({'source': l:mysource, 'sink': function("mysink"), 'window': { ... } })

@ghost
Copy link

ghost commented Feb 4, 2020

How to make it float relative to the current buffer/window rather than the entire editor?

@mhanberg
Copy link

mhanberg commented Feb 4, 2020

I am able to get this to work in NeoVim, but when using Vim I run into the following error when calling :Files. (I use NeoVim in the terminal, but prefer to use MacVim for normal usage).

The following was produced using the current Vim as installed by Homebrew (MacVim is not updated as of yet).

Screenshot
image

GIF of the error
fzf-popup-error

Any ideas? Thanks!

This is the fzf configuration that I use

" .vimrc
function! RipgrepFzf(query, fullscreen)
  let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case %s || true'
  let initial_command = printf(command_fmt, shellescape(a:query))
  let reload_command = printf(command_fmt, '{q}')
  let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command], 'window': { 'width': 0.9, 'height': 0.6 }}
  call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen)
endfunction

command! -nargs=* -bang RG call RipgrepFzf(<q-args>, <bang>0)

silent! nnoremap <c-p> :Files<cr>
nnoremap gl :BLines<cr>
nnoremap <leader>a :RG<cr>

let g:fzf_layout = { 'window': { 'width': 0.5, 'height': 0.6 } }
# .zshrc
export FZF_DEFAULT_COMMAND="rg --files --hidden --glob '!.git/'"
Vim Version
⚡︎/usr/local/bin/vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Feb  3 2020 01:40:55)
macOS version
Included patches: 1-200
Compiled by Homebrew
Huge version without GUI.  Features included (+) or not (-):
+acl               -farsi             -mouse_sysmouse    -tag_old_static
+arabic            +file_in_path      +mouse_urxvt       -tag_any_white
+autocmd           +find_in_path      +mouse_xterm       -tcl
+autochdir         +float             +multi_byte        +termguicolors
-autoservername    +folding           +multi_lang        +terminal
-balloon_eval      -footer            -mzscheme          +terminfo
+balloon_eval_term +fork()            +netbeans_intg     +termresponse
-browse            +gettext           +num64             +textobjects
++builtin_terms    -hangul_input      +packages          +textprop
+byte_offset       +iconv             +path_extra        +timers
+channel           +insert_expand     +perl              +title
+cindent           +job               +persistent_undo   -toolbar
-clientserver      +jumplist          +popupwin          +user_commands
+clipboard         +keymap            +postscript        +vartabs
+cmdline_compl     +lambda            +printer           +vertsplit
+cmdline_hist      +langmap           +profile           +virtualedit
+cmdline_info      +libcall           -python            +visual
+comments          +linebreak         +python3           +visualextra
+conceal           +lispindent        +quickfix          +viminfo
+cryptv            +listcmds          +reltime           +vreplace
+cscope            +localmap          +rightleft         +wildignore
+cursorbind        +lua               +ruby              +wildmenu
+cursorshape       +menu              +scrollbind        +windows
+dialog_con        +mksession         +signs             +writebackup
+diff              +modify_fname      +smartindent       -X11
+digraphs          +mouse             -sound             -xfontset
-dnd               -mouseshape        +spell             -xim
-ebcdic            +mouse_dec         +startuptime       -xpm
+emacs_tags        -mouse_gpm         +statusline        -xsmp
+eval              -mouse_jsbterm     -sun_workshop      -xterm_clipboard
+ex_extra          +mouse_netterm     +syntax            -xterm_save
+extra_search      +mouse_sgr         +tag_binary
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/local/share/vim"
Compilation: clang -c -I. -Iproto -DHAVE_CONFIG_H   -DMACOS_X -DMACOS_X_DARWIN  -g -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: clang   -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/readline/lib  -L/usr/local/lib -o vim        -lncurses -liconv -lintl -framework AppKit  -L/usr/local/opt/lua/lib -llua5.3 -mmacosx-version-min=10.15 -fstack-protector-strong -L/usr/local/lib  -L/usr/local/Cellar/perl/5.30.1/lib/perl5/5.30.1/darwin-thread-multi-2level/CORE -lperl -lm -lutil -lc  -L/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/config-3.7m-darwin -lpython3.7m -framework CoreFoundation  -lruby.2.6

@ardenzhan
Copy link

@mhanberg I have the same problem. Workaround for me is to do :set hidden. Which I found by doing :h E948 and then following the link for |abandon|. I haven't read enough of the manual / debugged further to figure out what the actual problem is though.

@junegunn
Copy link
Owner

junegunn commented Feb 5, 2020

@mhanberg @ardenzhan Added junegunn/fzf@0896036 to workaround the issue.

@bluz71
Copy link

bluz71 commented Feb 5, 2020

@junegunn,

Your latest commits fix the issue (at least for me). I had the same error as @mhanberg, but now resolved. Many thanks.

@mhanberg
Copy link

mhanberg commented Feb 5, 2020

@junegunn thank you! That solves the problem for me as well.

@josefson
Copy link

I have just tried this feature, but under vim 8.2 it's thowing me this error where it's trying to open a shell in the popup window when trying any Fzf command.
image
It actually opens the popup blank and the shells as buffers
image

@mhanberg
Copy link

@josefson make sure you have this patch vim/vim@3c01c4a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests