Vim的滚动条(基于curs的滚动条,不是gvim)?


10

作为Linux用户,我对CLI和TUI工具非常满意,但是我几乎错过了几乎每个GUI程序中的滚动条。相对于“ 9752行,占24%”,从滚动条中知道文件有多长时间以及我在哪里一直很容易。

我期望的是一个看起来像ASCII的滚动条

|
|
|
|
#
#
#
|
|
|

并且我可以配置为显示在左侧或右侧(如果在左侧,则为行号和折叠标记的相对位置)。已经有一个Vim插件可以做到这一点,或者我该如何编写自己的插件?Vim的插件框架似乎并不直接支持此类UI修改。

Answers:


3

如果您正在考虑“编写自己的插件”路线,那么Vim的“签名”功能可能是一个不错的起点。此功能就是语法检查插件突出显示错误的方式。

vim标志示例

一个简单的方法来放置标志是:

  1. 确定您在文件中的位置百分比 p
  2. 确定在vim窗口中可见多少行 L
  3. 在最靠近的行号上放置一个符号 int(p*L)
  4. 重新计算文件周围的运动

谢谢!这与我声明的要求非常接近,尽管从文档看来似乎只能在左侧绘制符号。很好的答案,被接受!
xiaq 2012年

10

可以将状态栏用作滚动条。我曾经在我的.vimrc文件中添加了以下内容,它模拟了一个滚动条(它也只是水平放置,但效果出奇的好)。最初几年前在vim_use Mailinglist上进行了讨论。

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。


我非常喜欢这种解决方案,因为它将滚动条放置在不占用编码窗口任何空间的位置。谢谢,克里斯蒂安!
dotancohen 2012年

我喜欢这个主意,甚至可以使用水平伪滚动条。但是@redacted提出的解决方案更接近我的要求。虽然您的答案是+1。谢谢!
xiaq 2012年

如何设置滚动位置标记的BG的颜色?使用kde上的日光化主题,它与酒吧的其余部分几乎没有区别。
迈克(Mike)

从最后几行猜测,使用了突出显示组User1和User2。您可以重新定义它们。
克里斯汀·布拉班德

6

我试图赎回以前的假人....

我喜欢这个主意,所以今天我为VIM编写了一个插件,使用vim的signs功能显示滚动条“ thumb”。

它仍然是非常beta,但是现在可以使用,我还有很多工作要做,包括输入所有文档,评论和内容。

我将在此处发布源代码,但是也欢迎您从我的Hg Repo中提取源代码。(别为其他东西而笑)

记住...非常beta,考虑到我以前从未写过插件,多年来一直只涉足VimL。(从概念到制作原型,不到12小时!是的!)

我会继续努力,整洁。颜色扎眼是有原因的,很容易看到变化。它现在有一个大错误,您无法通过切换它来消除所有迹象。我知道如何实施,只是想分享。


图片很有用:

Vim滚动条的作用


VIM诅咒滚动条-v0.1-L Nix-lornix@lornix.com Hg回购

" Vim global plugin to display a curses scrollbar
" Version:      0.1.1
" Last Change:  2012 Jul 06
" Author:       Loni Nix <lornix@lornix.com>
"
" 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:

您的意思是guioptions,正如帮助明确指出的那样,这仅适用于vim的gui版本。
Christian Brabandt 2012年

真好 我已经在DynamicSigns插件中实现了类似的功能。顺便说一句:请注意,没有在折叠线上画出标志。
Christian Brabandt 2012年

谢谢!我认为我应该早些弥补我的foobar,然后对它更加感兴趣...所以我写了它。和往常一样,最初的工作很容易...使它们变得整洁和美观是令人沮丧的部分。(没有褶皱迹象...已注明)
lornix

谢谢!但是从@rededed数据来看,它比您更早地启用了符号功能,因此接受他的回答也许更有礼貌。已为您的答案+1。
xiaq 2012年

1
您的仓库已被删除。如果您可以将它放在github之类的地方,并让其他人为它贡献一点,那就太好了。我真的认为它看起来很棒。
迈克

0

这不是一个理想的解决方案,但是您可以通过以下方式找到文件在状态行中的位置:

set statusline=%<%m\ %f\ %y\ %{&ff}\ \%=\ row:%l\ of\ %L\ col:%c%V\ %P

set number用于在每行之前添加行号。

除非您修改了vim源(ncurses),否则我认为这是不可能的,但我可能是错的。


谢谢,但是我已经知道了……我只是在寻找更轻松的东西。
xiaq 2011年

这是一个远射。
Sardathrion-反对SE滥用2011年

0

这是可以用鼠标拖动的版本。它也仅在使用滚轮时更新-如果需要滚动条,无论如何,您的手都应该在鼠标上。

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

这确实适用于鼠标,但是使用Ctrl + F滚动时不会更新。该标记似乎保留在其原始行号中。这样做:call UpdateScrollbox()是可行的,但并不友好。可能需要在所有移动键上都设置钩子,或者,如果可能的话,最好在滚动事件上使用一个钩子。
罗斯兰
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.