我正在为gvim编写一个小插件,根据垂直分割的数量自动增加或减少gui的宽度。该插件的工作原理如下
if has("gui_running")
augroup resize
autocmd WinEnter * call <SID>ResizeSplits()
autocmd WinLeave * call <SID>ResizeSplits()
autocmd BufLeave * call <SID>ResizeSplits()
augroup END
endif
这里ResizeSplits()
是调整gui窗口大小的函数:
function! s:ResizeSplits()
let l:count = 0
windo if winwidth(winnr()) < &columns |
\ let l:count += 1 |
\ endif
if l:count > 0
let l:totwidth = l:count - 1 + l:count*80
else
let l:totwidth = 80
endif
if &columns != l:totwidth
execute 'set co=' . l:totwidth
endif
endfunction
该插件几乎可以按照我的要求运行,但并不完全。似乎BufLeave
事件(和类似的事件)有时会在窗口关闭之前执行。这是一个问题,例如当我<c-w>o
或:only
时。问题是ResizeSplits
函数不起作用,因为它仍然计算旧的窗口数。
是否有另一个自动命令可用于检测窗口的数量何时发生了变化,还是一个BufLeave
- 类似的事件,保证在窗口被销毁/删除后执行?
让我的插件使用映射是微不足道的,但是我无法使用:only
和:close
之类的ex命令使其可靠地工作。
答案 0 :(得分:1)
:close
/ :quit
没有确切的事件;最接近的是BufWinLeave
,但是当缓冲区仍然在另一个缓冲区中可见时,它不会触发。您可以将其与BufLeave
组合,但必须检查缓冲区是否实际上不再可见。
要仅处理不公开的缓冲区,您可以在执行的autocmd中添加检查'buflisted'
的条件。
我认为没有办法拦截你所描述的角落案例。特别是:only
可能很棘手。我只能建议在CursorHold
和CursorMoved
上使用其他autocmds解决此问题。这样,不正确的状态只会持续很短的时间。
答案 1 :(得分:1)
我找到了一个似乎运作良好的解决方案。首先,我重写了ResizeSplits
函数:
function! s:ResizeSplits()
let l:curwin = winnr()
let l:colwidth = 80 + &foldcolumn
if &number
let l:colwidth += &numberwidth
endif
let l:count = 0
windo if winwidth(winnr()) < &columns |
\ let l:count += getwinvar(winnr(), 'count') |
\ endif
if l:count > 0
let l:totwidth = l:count - 1 + l:count*l:colwidth
else
let l:totwidth = l:colwidth
endif
if &columns != l:totwidth
silent! execute 'set co=' . l:totwidth
silent! execute 'wincmd ='
endif
silent! execute l:curwin . 'wincmd w'
endfunction
重要的变化是我定义了一个0或1的变量w:count
。该函数与以下自动命令一起使用:
if has("gui_running")
augroup vimrc_autocommands
autocmd WinEnter * let w:count = 1 | call <SID>ResizeSplits()
autocmd BufEnter * let w:count = 1 | call <SID>ResizeSplits()
autocmd WinLeave * call <SID>ResizeSplits()
autocmd BufHidden * let w:count = 0 | call <SID>ResizeSplits()
autocmd BufWinLeave * let w:count = 0 | call <SID>ResizeSplits()
augroup END
endif
这似乎适用于我尝试过的几乎所有情况。只有一种情况:only
和<c-w>o
仍然不起作用:如果窗口具有相同的缓冲区。一个简单的映射可以解决<c-w>o
:
nnoremap <c-w>o <c-w>o:call <sid>ResizeSplits()<cr>
如果有人找到更好的解决方案,我当然会很高兴。