1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-02 22:10:06 +08:00

Add floating windows support vim (#3612)

This commit is contained in:
Wang Shidong 2020-07-07 23:15:53 +08:00 committed by GitHub
parent 96da1ed022
commit 2c96390ba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 213 additions and 45 deletions

View File

@ -8,6 +8,10 @@
let s:self = {}
function! s:self.exists() abort
return exists('*nvim_open_win')
endfunction
" in old version nvim_open_win api is:
" call nvim_open_win(s:bufnr, v:true, &columns, 12,
" \ {
@ -64,6 +68,16 @@ function! s:self.win_config(winid, opt) abort
endfunction
function! s:self.win_close(id, focuce) abort
return nvim_win_close(a:id, a:focuce)
" @fixme: nvim_win_close only support one argv in old version
try
return nvim_win_close(a:id, a:focuce)
catch /^Vim\%((\a\+)\)\=:E118/
return nvim_win_close(a:id)
endtry
endfunction
function! SpaceVim#api#neovim#floating#get() abort
return deepcopy(s:self)
endfunction

View File

@ -0,0 +1,130 @@
"=============================================================================
" floating.vim --- vim floating api
" Copyright (c) 2016-2019 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
let s:self = {}
" this api is based on neovim#floating api
" options:
" 1. col
" 2. row
" 3. width
" 3. height
" 4. relative
" {config} Map defining the window configuration. Keys:
" • `relative`: Sets the window layout to "floating", placed
" at (row,col) coordinates relative to:
" • "editor" The global editor grid
" • "win" Window given by the `win` field, or
" current window.
" • "cursor" Cursor position in current window.
"
" • `win` : |window-ID| for relative="win".
" • `anchor`: Decides which corner of the float to place
" at (row,col):
" • "NW" northwest (default)
" • "NE" northeast
" • "SW" southwest
" • "SE" southeast
"
" • `width` : Window width (in character cells).
" Minimum of 1.
" • `height` : Window height (in character cells).
" Minimum of 1.
" • `bufpos` : Places float relative to buffer
" text (only when relative="win"). Takes a tuple
" of zero-indexed [line, column]. `row` and
" `col` if given are applied relative to this
" position, else they default to `row=1` and
" `col=0` (thus like a tooltip near the buffer
" text).
" • `row` : Row position in units of "screen cell
" height", may be fractional.
" • `col` : Column position in units of "screen
" cell width", may be fractional.
" • `focusable` : Enable focus by user actions
" (wincmds, mouse events). Defaults to true.
" Non-focusable windows can be entered by
" |nvim_set_current_win()|.
" • `external` : GUI should display the window as
" an external top-level window. Currently
" accepts no other positioning configuration
" together with this.
" • `style`: Configure the appearance of the window.
" Currently only takes one non-empty value:
" • "minimal" Nvim will display the window with
" many UI options disabled. This is useful
" when displaying a temporary float where the
" text should not be edited. Disables
" 'number', 'relativenumber', 'cursorline',
" 'cursorcolumn', 'foldcolumn', 'spell' and
" 'list' options. 'signcolumn' is changed to
" `auto` and 'colorcolumn' is cleared. The
" end-of-buffer region is hidden by setting
" `eob` flag of 'fillchars' to a space char,
" and clearing the |EndOfBuffer| region in
" 'winhighlight'.
"
" Return: ~
" Window handle, or 0 on error
function! s:self.open_win(buffer, focuce, options) abort
let col = get(a:options, 'col', 1)
let row = get(a:options, 'row', 1)
let width = get(a:options, 'width', 1)
let height = get(a:options, 'height', 1)
let relative = get(a:options, 'relative', 'editor')
if relative ==# 'win'
elseif relative ==# 'cursor'
elseif relative ==# 'editor'
let opt = {
\ 'line' : row + 1,
\ 'col' : col,
\ 'maxheight' : height,
\ 'minheight' : height,
\ 'maxwidth' : width,
\ 'minwidth' : width,
\ }
endif
return popup_create(a:buffer, opt)
endfunction
function! s:self.win_config(winid, options) abort
let col = get(a:options, 'col', 1)
let row = get(a:options, 'row', 1)
let width = get(a:options, 'width', 1)
let height = get(a:options, 'height', 1)
let relative = get(a:options, 'relative', 'editor')
if relative ==# 'win'
elseif relative ==# 'cursor'
elseif relative ==# 'editor'
let opt = {
\ 'line' : row + 1,
\ 'col' : col,
\ 'maxheight' : height,
\ 'minheight' : height,
\ 'maxwidth' : width,
\ 'minwidth' : width,
\ }
endif
return popup_setoptions(a:winid, opt)
endfunction
function! s:self.exists() abort
return exists('*popup_create')
endfunction
function! s:self.win_close(id, focuce) abort
return popup_close(a:id)
endfunction
function! SpaceVim#api#vim#floating#get() abort
return deepcopy(s:self)
endfunction

View File

@ -7,7 +7,12 @@
"=============================================================================
let s:self = {}
let s:self.__floating = SpaceVim#api#import('neovim#floating')
if has('nvim')
let s:self.__floating = SpaceVim#api#import('neovim#floating')
else
let s:self.__floating = SpaceVim#api#import('vim#floating')
endif
let s:self.__buffer = SpaceVim#api#import('vim#buffer')
function! s:self.check_width(len, sec, winwidth) abort
@ -88,9 +93,13 @@ function! s:self.build(left_sections, right_sections, lsep, rsep, fname, tag, hi
return l[:-4]
endfunction
function! s:self.support_float() abort
return exists('*nvim_buf_set_virtual_text')
endfunction
function! s:self.open_float(st) abort
if !has_key(self, '__bufnr') || !bufexists(self.__bufnr)
let self.__bufnr = nvim_create_buf(0,0)
let self.__bufnr = self.__buffer.bufadd('')
endif
if has_key(self, '__winid') && win_id2tabwin(self.__winid)[0] == tabpagenr()
else
@ -109,7 +118,9 @@ function! s:self.open_float(st) abort
call setbufvar(self.__bufnr, '&bufhidden', 'wipe')
call setbufvar(self.__bufnr, '&cursorline', 0)
call setbufvar(self.__bufnr, '&modifiable', 0)
call setwinvar(win_id2win(self.__winid), '&winhighlight', 'Normal:SpaceVim_statusline_a_bold')
if exists('&winhighlight')
call setwinvar(win_id2win(self.__winid), '&winhighlight', 'Normal:SpaceVim_statusline_a_bold')
endif
call setwinvar(win_id2win(self.__winid), '&cursorline', 0)
call nvim_buf_set_virtual_text(
\ self.__bufnr,
@ -120,14 +131,9 @@ function! s:self.open_float(st) abort
redraw!
endfunction
if exists('*nvim_win_close')
if s:self.__floating.exists()
function! s:self.close_float() abort
" @fixme: nvim_win_close only support one argv in old version
try
call nvim_win_close(self.__winid, 1)
catch /^Vim\%((\a\+)\)\=:E118/
call nvim_win_close(self.__winid)
endtry
call self.__floating.win_close(self.__winid, 1)
endfunction
else
function! s:self.close_float() abort

View File

@ -15,8 +15,13 @@ scriptencoding utf-8
let s:CMP = SpaceVim#api#import('vim#compatible')
let s:STR = SpaceVim#api#import('data#string')
let s:KEY = SpaceVim#api#import('vim#key')
let s:FLOATING = SpaceVim#api#import('neovim#floating')
if has('nvim')
let s:FLOATING = SpaceVim#api#import('neovim#floating')
else
let s:FLOATING = SpaceVim#api#import('vim#floating')
endif
let s:SL = SpaceVim#api#import('vim#statusline')
let s:BUFFER = SpaceVim#api#import('vim#buffer')
" guide specific var
@ -245,7 +250,6 @@ function! s:escape_keys(inp) abort " {{{
return substitute(ret, '|', '<Bar>', '')
endfunction " }}}
function! s:calc_layout() abort " {{{
let ret = {}
let smap = filter(copy(s:lmap), 'v:key !=# "name"')
@ -260,8 +264,8 @@ function! s:calc_layout() abort " {{{
let ret.col_width = maxlength
let ret.win_dim = ret.n_cols * ret.col_width
else
let ret.n_cols = winwidth(0) >= maxlength ? winwidth(0) / maxlength : 1
let ret.col_width = winwidth(0) / ret.n_cols
let ret.n_cols = winwidth(s:winid) >= maxlength ? winwidth(s:winid) / maxlength : 1
let ret.col_width = winwidth(s:winid) / ret.n_cols
let ret.n_rows = ret.n_items / ret.n_cols + (fmod(ret.n_items,ret.n_cols) > 0 ? 1 : 0)
let ret.win_dim = ret.n_rows
endif
@ -340,10 +344,7 @@ function! s:create_string(layout) abort " {{{
let mlen = strdisplaywidth(line)
endif
endfor
call insert(r, '')
let output = join(r, "\n ")
cnoremap <nowait> <buffer> <Space> <Space><CR>
cnoremap <nowait> <buffer> <silent> <C-h> <LGCMD>paging_help<CR>
let output = join(r, "\n")
return output
endfunction " }}}
@ -390,7 +391,7 @@ function! s:start_buffer() abort " {{{
let s:winv = winsaveview()
let s:winnr = winnr()
let s:winres = winrestcmd()
call s:winopen()
let [s:winid, s:bufnr] = s:winopen()
let layout = s:calc_layout()
let string = s:create_string(layout)
@ -398,9 +399,9 @@ function! s:start_buffer() abort " {{{
let layout.win_dim = min([g:leaderGuide_max_size, layout.win_dim])
endif
setlocal modifiable
if exists('*nvim_open_win')
call s:FLOATING.win_config(win_getid(s:winid),
call setbufvar(s:bufnr, '&modifiable', 1)
if s:FLOATING.exists()
let rst = s:FLOATING.win_config(s:winid,
\ {
\ 'relative': 'editor',
\ 'width' : &columns,
@ -408,7 +409,6 @@ function! s:start_buffer() abort " {{{
\ 'row' : &lines - layout.win_dim - 4,
\ 'col' : 0
\ })
else
if g:leaderGuide_vertical
noautocmd execute 'vert res '.layout.win_dim
@ -416,15 +416,14 @@ function! s:start_buffer() abort " {{{
noautocmd execute 'res '.layout.win_dim
endif
endif
normal! gg"_dd
if exists('*nvim_open_win')
if s:FLOATING.exists()
" when using floating windows, and the flaating windows do not support
" statusline, add extra black line at top and button of the content.
call setline(1, [''] + split(string, "\n") + [''])
call s:BUFFER.buf_set_lines(s:bufnr, 0, -1, 0, [''] + split(string, "\n") + [''])
else
call setline(1, split(string, "\n"))
call s:BUFFER.buf_set_lines(s:bufnr, 0, -1, 0, split(string, "\n"))
endif
setlocal nomodifiable
call setbufvar(s:bufnr, '&modifiable', 0)
redraw!
call s:wait_for_input()
endfunction " }}}
@ -511,12 +510,15 @@ function! s:build_mpt(mpt) abort
echohl NONE
endfunction
" change this func, do not focus to the new windows, and return winid.
function! s:winopen() abort " {{{
call s:highlight_cursor()
let pos = g:leaderGuide_position ==? 'topleft' ? 'topleft' : 'botright'
if exists('*nvim_open_win')
if s:FLOATING.exists()
if !bufexists(s:bufnr)
let s:bufnr = nvim_create_buf(v:false,v:false)
let s:bufnr = s:BUFFER.bufadd('')
endif
let s:winid = s:FLOATING.open_win(s:bufnr, v:true,
\ {
@ -549,21 +551,33 @@ function! s:winopen() abort " {{{
let s:winid = winnr()
endif
let s:guide_help_mode = 0
setlocal filetype=leaderGuide
call setbufvar(s:bufnr, '&filetype', 'leaderGuide')
call setbufvar(s:bufnr, '&number', 0)
call setbufvar(s:bufnr, '&relativenumber', 0)
call setbufvar(s:bufnr, '&list', 0)
call setbufvar(s:bufnr, '&modeline', 0)
call setbufvar(s:bufnr, '&wrap', 0)
call setbufvar(s:bufnr, '&buflisted', 0)
call setbufvar(s:bufnr, '&buftype', 'nofile')
call setbufvar(s:bufnr, '&bufhidden', 'unload')
call setbufvar(s:bufnr, '&swapfile', 0)
call setbufvar(s:bufnr, '&cursorline', 0)
call setbufvar(s:bufnr, '&cursorcolumn', 0)
call setbufvar(s:bufnr, '&colorcolumn', '')
call setbufvar(s:bufnr, '&winfixwidth', 1)
call setbufvar(s:bufnr, '&winfixheight', 1)
if exists('&winhighlight')
set winhighlight=Normal:Pmenu
endif
setlocal nonumber norelativenumber nolist nomodeline nowrap
setlocal nobuflisted buftype=nofile bufhidden=unload noswapfile
setlocal nocursorline nocursorcolumn colorcolumn=
setlocal winfixwidth winfixheight
" @fixme not sure if the listchars should be changed!
" setlocal listchars=
call s:updateStatusline()
call s:toggle_hide_cursor()
return [s:winid, s:bufnr]
endfunction " }}}
if exists('*nvim_open_win')
if s:SL.support_float()
function! s:updateStatusline() abort
call SpaceVim#mapping#guide#theme#hi()
let gname = get(s:guide_group, 'name', '')
@ -596,13 +610,13 @@ else
endif
let keys = get(s:, 'prefix_key_inp', '')
let keys = substitute(keys, '\', '\\\', 'g')
exe 'setlocal statusline=%#LeaderGuiderPrompt#\ Guide:\ ' .
call setbufvar(s:bufnr, '&statusline', '%#LeaderGuiderPrompt#\ Guide:\ ' .
\ '%#LeaderGuiderSep1#' . s:lsep .
\ '%#LeaderGuiderName#\ ' .
\ SpaceVim#mapping#leader#getName(s:prefix_key)
\ . keys . gname
\ . '\ %#LeaderGuiderSep2#' . s:lsep . '%#LeaderGuiderFill#'
\ . s:guide_help_msg(1)
\ . s:guide_help_msg(1))
endfunction
endif
@ -629,9 +643,11 @@ endfunction
function! s:winclose() abort " {{{
call s:toggle_hide_cursor()
if exists('*nvim_win_close')
call nvim_win_close(s:winid, 1)
call s:close_float_statusline()
if s:FLOATING.exists()
call s:FLOATING.win_close(s:winid, 1)
if s:SL.support_float()
call s:close_float_statusline()
endif
else
noautocmd execute s:winid.'wincmd w'
if s:winid == winnr()

View File

@ -245,7 +245,7 @@ function! s:start_replace() abort
catch
endtr
if s:grepid != 0
call s:JOB.stop(s:grepid)
call s:JOB.stop(s:grepid)
endif
let replace_text = s:current_grep_pattern
if !empty(replace_text)
@ -308,7 +308,7 @@ let s:MPT._prompt.mpt = g:spacevim_commandline_prompt . ' '
function! s:close_buffer() abort
" NOTE: the jobid maybe -1, that is means the cmd is not executable.
if s:grepid > 0
call s:JOB.stop(s:grepid)
call s:JOB.stop(s:grepid)
endif
call timer_stop(s:grep_timer_id)
call timer_stop(s:preview_timer_id)
@ -730,7 +730,7 @@ function! SpaceVim#plugins#flygrep#open(argv) abort
" set default handle func: s:flygrep
let s:MPT._handle_fly = function('s:flygrep')
if exists('*nvim_open_win')
let s:buffer_id = nvim_create_buf(v:false, v:false)
let s:buffer_id = s:BUFFER.bufadd('')
let flygrep_win_height = 16
let s:flygrep_win_id = s:FLOATING.open_win(s:buffer_id, v:true,
\ {
@ -798,7 +798,9 @@ function! SpaceVim#plugins#flygrep#open(argv) abort
" sometimes user can not see the flygrep windows, redraw only once.
redraw
call s:MPT.open()
call s:close_statusline()
if s:SL.support_float()
call s:close_statusline()
endif
call SpaceVim#logger#info('FlyGrep ending ===========================')
let &t_ve = save_tve
if has('gui_running')