vim 的滚动条(基于诅咒的滚动条,而不是 gvim)?

xia*_*iaq 11 vim scrollbar

作为 Linux 用户,我对 CLI 和 TUI 工具非常熟悉,但我想念几乎每个 GUI 程序中都有的小滚动条。我总是更容易知道文件有多长以及我从滚动条到哪里,而不是“9752 行,24%”。

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

|
|
|
|
#
#
#
|
|
|

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

Chr*_*ndt 11

可以将状态行用作滚动条。我曾经在我的 .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()
Run Code Online (Sandbox Code Playgroud)

确保您将laststatus选项设置为 2。


lor*_*nix 6

我试图赎回我早先的失礼......

我喜欢这个想法,所以今天我为 VIM 编写了一个插件,使用 vim 的标志功能来显示滚动条“拇指”。

它仍然是非常测试版,但现在可以使用,我还有工作要做,包括输入所有文档和评论等。

我会在这里发布源代码,但欢迎您从我的Hg Repo 中提取它。(不要对其他东西笑得太厉害)

记住......非常测试版,考虑到我以前从未编写过插件,多年来只涉足 VimL。(从概念到工作原型不到 12 小时!耶!)

我会继续努力,有点整洁。颜色很花哨是有原因的,很容易看出有什么变化。它现在有一个大错误,您无法通过将其关闭来使所有迹象消失。我知道如何实现这一点,只是想分享一下。


图片很有用:

Vim-Scrollbar 在行动


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

" 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:
Run Code Online (Sandbox Code Playgroud)


red*_*ted 5

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

vim 标志示例

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

  1. 以百分比的形式确定您在文件中的位置 p
  2. 确定 vim 窗口中可见的行数 L
  3. 在最接近的行号处放置一个标志 int(p*L)
  4. 重新计算文件周围的移动