作为 Linux 用户,我对 CLI 和 TUI 工具已经相当熟悉,但我怀念几乎每个 GUI 程序中都有的小滚动条。我总是能从滚动条中更轻松地知道文件的长度以及我所处的位置,而不是“9752 行,24%”。
我期望的是一个 ASCII 滚动条,看起来像
| | | | # # # | | |
我可以配置显示在左侧还是右侧(如果显示在左侧,则配置相对于行号和折叠标记的位置)。是否有 Vim 插件可以执行此操作,或者我该如何编写自己的插件?Vim 的插件框架似乎不直接支持此类 UI 修改。
答案1
如果你正在考虑“编写自己的插件”路线,Vim 的‘符号’功能可能是个不错的起点。此功能是语法检查插件突出显示错误的方式。
放置标志的一个简单方法是:
- 确定您在文件中的位置(以百分比表示)
p
- 确定 vim 窗口中可见的行数
L
- 在最靠近的行号处放置一个标志
int(p*L)
- 根据文件周围的移动重新计算
答案2
可以将状态行用作滚动条。我以前在 .vimrc 中写过以下内容,它模拟了滚动条(虽然它只是水平滚动,但效果出奇地好)。这最初是在vim_use 邮件列表几年前。
func! STL()
let stl = '%f [%{(&fenc==""?&enc:&fenc).((exists("+bomb") && &bomb)?",B":"")}%M%R%H%W] %y [%l/%L,%v] [%p%%]'
let barWidth = &columns - 65 " <-- wild guess
let barWidth = barWidth < 3 ? 3 : barWidth
if line('$') > 1
let progress = (line('.')-1) * (barWidth-1) / (line('$')-1)
else
let progress = barWidth/2
endif
" line + vcol + %
let pad = strlen(line('$'))-strlen(line('.')) + 3 - strlen(virtcol('.')) + 3 - strlen(line('.')*100/line('$'))
let bar = repeat(' ',pad).' [%1*%'.barWidth.'.'.barWidth.'('
\.repeat('-',progress )
\.'%2*0%1*'
\.repeat('-',barWidth - progress - 1).'%0*%)%<]'
return stl.bar
endfun
hi def link User1 DiffAdd
hi def link User2 DiffDelete
set stl=%!STL()
确保将laststatus
选项设置为 2。
答案3
我试图弥补我之前的失礼行为......
我喜欢这个想法,所以今天我为 VIM 编写了一个插件,使用 vim 的符号功能显示滚动条“缩略图”。
它仍然处于测试阶段,但现在可以使用,我还有一些工作要做,包括输入所有文档和评论等等。
我将在这里发布源代码,但你可以从我的汞回购(其他的就别笑得太厉害了)
记住... 非常处于测试阶段,因为我之前从未编写过插件,多年来只是涉猎 VimL。(从概念到工作原型不到 12 小时!耶!)
我会继续努力,挺不错的。颜色很鲜艳是有原因的,很容易看出有什么变化。它现在有一个大错误,你不能通过关闭它来让所有标志都消失。我知道如何实现这一点,只是想分享一下。
图片很有用:
VIM Curses 滚动条 - v0.1 - L Nix -[电子邮件保护] 汞回购
" Vim global plugin to display a curses scrollbar
" Version: 0.1.1
" Last Change: 2012 Jul 06
" Author: Loni Nix <[email protected]>
"
" License: TODO: Have to put something here
"
"
if exists('g:loaded_scrollbar')
finish
endif
let g:loaded_scrollbar=1
"
" save cpoptions
let s:save_cpoptions=&cpoptions
set cpoptions&vim
"
" some global constants
if !exists('g:scrollbar_thumb')
let g:scrollbar_thumb='#'
endif
if !exists('g:scrollbar_clear')
let g:scrollbar_clear='|'
endif
"
"our highlighting scheme
highlight Scrollbar_Clear ctermfg=green ctermbg=black guifg=green guibg=black cterm=none
highlight Scrollbar_Thumb ctermfg=red ctermbg=black guifg=red guibg=black cterm=reverse
"
"the signs we're goint to use
exec "sign define sbclear text=".g:scrollbar_clear." texthl=Scrollbar_Clear"
exec "sign define sbthumb text=".g:scrollbar_thumb." texthl=Scrollbar_Thumb"
"
" set up a default mapping to toggle the scrollbar
" but only if user hasn't already done it
if !hasmapto('ToggleScrollbar')
map <silent> <unique> <leader>sb :call <sid>ToggleScrollbar()<cr>
endif
"
" start out activated or not?
if !exists('s:scrollbar_active')
let s:scrollbar_active=1
endif
"
function! <sid>ToggleScrollbar()
if s:scrollbar_active
let s:scrollbar_active=0
" clear out the autocmds
augroup Scrollbar_augroup
autocmd!
augroup END
"call <sid>ZeroSignList()
else
let s:scrollbar_active=1
call <sid>SetupScrollbar()
endif
endfunction
function! <sid>SetupScrollbar()
augroup Scrollbar_augroup
autocmd BufEnter * :call <sid>showScrollbar()
autocmd BufWinEnter * :call <sid>showScrollbar()
autocmd CursorHold * :call <sid>showScrollbar()
autocmd CursorHoldI * :call <sid>showScrollbar()
autocmd CursorMoved * :call <sid>showScrollbar()
autocmd CursorMovedI * :call <sid>showScrollbar()
autocmd FocusGained * :call <sid>showScrollbar()
autocmd VimResized * :call <sid>showScrollbar()
augroup END
call <sid>showScrollbar()
endfunction
"
function! <sid>showScrollbar()
" not active, go away
if s:scrollbar_active==0
return
endif
"
let bnum=bufnr("%")
let total_lines=line('$')
let current_line=line('.')
let win_height=winheight(0)
let win_start=line('w0')+0 "curious, this was only one had to be forced
let clear_top=float2nr((current_line * win_height) / total_lines) - 1
if clear_top < 0
let clear_top=0
elseif clear_top > (win_height - 1)
let clear_top=win_height - 1
endif
let thumb_height=float2nr((win_height * win_height) / total_lines)
if thumb_height < 1
let thumb_height=1
elseif thumb_height > win_height
let thumb_height=win_height
endif
let thumb_height=thumb_height + clear_top
let linectr=1
while linectr <= clear_top
let dest_line=win_start+linectr-1
exec ":sign place ".dest_line." line=".dest_line." name=sbclear buffer=".bnum
let linectr=linectr+1
endwhile
while linectr <= thumb_height
let dest_line=win_start+linectr-1
exec ":sign place ".dest_line." line=".dest_line." name=sbthumb buffer=".bnum
let linectr=linectr+1
endwhile
while linectr <= win_height
let dest_line=win_start+linectr-1
exec ":sign place ".dest_line." line=".dest_line." name=sbclear buffer=".bnum
let linectr=linectr+1
endwhile
endfunction
"
" fire it all up if we're 'active'
if s:scrollbar_active != 0
call <sid>SetupScrollbar()
endif
"
" restore cpoptions
let &cpoptions=s:save_cpoptions
unlet s:save_cpoptions
"
" vim: set filetype=vim fileformat=unix expandtab softtabstop=4 shiftwidth=4 tabstop=8:
答案4
这是可以用鼠标拖动的版本。它也只在使用滚轮时更新——如果需要滚动条,你的手无论如何都应该放在鼠标上。
sign define scrollbox texthl=Visual text=[]
fun! ScrollbarGrab()
if getchar()=="\<leftrelease>" || v:mouse_col!=1
return|en
while getchar()!="\<leftrelease>"
let pos=1+(v:mouse_lnum-line('w0'))*line('$')/winheight(0)
call cursor(pos,1)
sign unplace 789
exe "sign place 789 line=".(pos*winheight(0)/line('$')+line('w0')).b:scrollexpr
endwhile
endfun
fun! UpdateScrollbox()
sign unplace 789
exe "sign place 789 line=".(line('w0')*winheight(0)/line('$')+line('w0')).b:scrollexpr
endfun
fun! ToggleScrollbar()
if exists('b:opt_scrollbar')
unlet b:opt_scrollbar
nun <buffer> <leftmouse>
iun <buffer> <leftmouse>
nun <buffer> <scrollwheelup>
nun <buffer> <scrollwheeldown>
iun <buffer> <scrollwheelup>
iun <buffer> <scrollwheeldown>
exe "sign unplace 789 file=" . expand("%:p")
exe "sign unplace 788 file=" . expand("%:p")
el
let b:opt_scrollbar=1
nno <silent> <buffer> <leftmouse> <leftmouse>:call ScrollbarGrab()<cr>
ino <silent> <buffer> <leftmouse> <leftmouse><c-o>:call ScrollbarGrab()<cr>
nno <buffer> <scrollwheelup> <scrollwheelup>:call UpdateScrollbox()<cr>
nno <buffer> <scrollwheeldown> <scrollwheeldown>:call UpdateScrollbox()<cr>
ino <buffer> <scrollwheelup> <scrollwheelup><c-o>:call UpdateScrollbox()<cr>
ino <buffer> <scrollwheeldown> <scrollwheeldown><c-o>: call UpdateScrollbox()<cr>
let b:scrollexpr=" name=scrollbox file=".expand("%:p")
exe "sign place 789 line=".(line('w0')*winheight(0)/line('$')+line('w0')).b:scrollexpr
exe "sign place 788 line=1".b:scrollexpr
en
endfun