diff --git a/autoload/SpaceVim/api/neovim/floating.vim b/autoload/SpaceVim/api/neovim/floating.vim index f2a9aec37..cfe6b9cbe 100644 --- a/autoload/SpaceVim/api/neovim/floating.vim +++ b/autoload/SpaceVim/api/neovim/floating.vim @@ -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 diff --git a/autoload/SpaceVim/api/vim/floating.vim b/autoload/SpaceVim/api/vim/floating.vim new file mode 100644 index 000000000..5f3b3222a --- /dev/null +++ b/autoload/SpaceVim/api/vim/floating.vim @@ -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 + + + diff --git a/autoload/SpaceVim/api/vim/statusline.vim b/autoload/SpaceVim/api/vim/statusline.vim index d82d30a20..840c9aed2 100644 --- a/autoload/SpaceVim/api/vim/statusline.vim +++ b/autoload/SpaceVim/api/vim/statusline.vim @@ -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 diff --git a/autoload/SpaceVim/mapping/guide.vim b/autoload/SpaceVim/mapping/guide.vim index ae5749ced..ba43aab98 100644 --- a/autoload/SpaceVim/mapping/guide.vim +++ b/autoload/SpaceVim/mapping/guide.vim @@ -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, '|', '', '') 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 - cnoremap paging_help + 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() diff --git a/autoload/SpaceVim/plugins/flygrep.vim b/autoload/SpaceVim/plugins/flygrep.vim index 035c01caf..f9c5ef21d 100644 --- a/autoload/SpaceVim/plugins/flygrep.vim +++ b/autoload/SpaceVim/plugins/flygrep.vim @@ -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')