Полоса прокрутки для vim (на основе проклятий, а не gvim)?

10

Как пользователь Linux, мне было довольно удобно с инструментами CLI и TUI, но я скучаю по маленькой полосе прокрутки, присутствующей почти во всех программах с графическим интерфейсом. Мне всегда было проще узнать, как долго файл и где я на полосе прокрутки, а не "9752 строки, 24%".

То, что я ожидаю, является полосой прокрутки ASCII, которая выглядит как

|
|
|
|
#
#
#
|
|
|

и я могу настроить отображение слева или справа (и если слева, относительное положение к номерам линий и меткам сгиба). Уже есть плагин Vim для этого или как я могу написать свой собственный? Плагин Vim, похоже, не поддерживает такие модификации пользовательского интерфейса напрямую.

xiaq
источник

Ответы:

3

Если вы рассматриваете маршрут «напишите свой собственный плагин», неплохо бы начать с функции «sign» в Vim . Эта особенность, например, в том, что плагины проверки синтаксиса выделяют ошибки.

пример vim sign

Простой подход для размещения знака будет следующим:

  1. Определите, где вы находитесь в файле в процентах p
  2. Определите, сколько строк видно в окнах vim. L
  3. Поместите знак на номер строки, ближайший к int(p*L)
  4. Пересчитать при перемещении по файлу
УДАЛЕНО
источник
Спасибо! Это очень близко к моему заявленному требованию, хотя из документа кажется, что знаки могут быть нарисованы только на левой стороне. Хороший ответ, хотя, принято!
Сяк
10

Можно использовать строку состояния в качестве полосы прокрутки. Раньше у меня было следующее .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.

Кристиан Брабандт
источник
Мне очень нравится это решение, поскольку оно помещает полосу прокрутки в такое место, где оно не занимает места в окне кодирования. Спасибо, Кристиан!
dotancohen
Мне нравится эта идея, и я могу даже жить с горизонтальной псевдо-полосой прокрутки. Но @redacted представил решение ближе к моему заявленному требованию. +1 на ваш ответ, хотя. Спасибо!
Сяк
Как установить цвет BG маркера положения прокрутки? Это почти неотличимо от остальной части бара, использующего соляризованную тему на kde.
Майк
По последним строкам угадайте, что используются группы подсветки User1 и User2. Вы можете переопределить их.
Кристиан Брабандт
6

Моя попытка выкупа моих ранее поддельных па ....

Идея мне понравилась, поэтому сегодня я написал плагин для VIM, чтобы показать «большой палец» полосы прокрутки, используя функцию знаков vim.

Это все еще ОЧЕНЬ бета-версия, но сейчас ее можно использовать, у меня еще есть над чем поработать, включая ввод всех документов, комментариев и прочего.

Я опубликую источник здесь, но вы можете извлечь его из моего Hg Repo . (Не смейтесь слишком сильно над другими вещами)

Помните ... ОЧЕНЬ бета, учитывая, что я никогда не писал плагин раньше, только баловался VimL на протяжении многих лет. (Менее 12 часов от концепции до рабочего прототипа! ууу!)

Я буду продолжать работать над этим, вроде как. Цвета яркие по причине, легко увидеть, что меняется. У него сейчас есть большая ошибка, вы не можете заставить знаки исчезнуть, выключив их. Я знаю, как это реализовать, просто хотел поделиться.


Картинки полезны:

Vim-Scrollbar в действии


Полоса прокрутки VIM Curses - 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:
lornix
источник
Вы имеете в виду, guioptionsи, как ясно говорится в справке, это работает только для графической версии vim.
Кристиан Брабандт
Ницца. Я реализовал нечто подобное в плагине DynamicSigns. Кстати, обратите внимание, что на сложенных линиях знаки не нарисованы.
Кристиан Брабандт
Спасибо! Я решил, что должен восполнить свой foobar раньше, затем я стал больше интересоваться этим ... так что я написал это. Как всегда, начальная работа проста ... получение всего этого элегантного и крутого вида - расстраивающая часть. (нет признаков складок ... отмечено)
lornix
Спасибо! Но, судя по данным, @redacted включил функцию подписи раньше, чем вы, так что, возможно, более вежливо принять его ответ. +1 к вашему ответу
Сяк
1
Ваш репо был удален. Было бы здорово, если бы вы могли поставить это где-то наподобие github и позволить другим внести свой вклад в это. Я действительно думаю, что это выглядит великолепно.
Майк
0

Не идеальное решение, но вы можете узнать, где в файле вы находитесь в строке состояния с чем-то вроде

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

или использовать, set numberчтобы иметь номер строки перед каждой строкой.

Если вы не изменили исходный код vim (ncurses), я не думаю, что это возможно, но я могу ошибаться.

Сардатрион - против злоупотребления SE
источник
Спасибо, но я уже знал это ... Я просто искал что-то проще для глаз.
Сяк
Это был длинный выстрел.
Сардатрион - против злоупотребления SE
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
q335r49
источник
Это работает для мыши, но не обновляется при прокрутке, например, Ctrl + F. Маркер, кажется, остается в своем первоначальном номере строки. Делать :call UpdateScrollbox()работает, но не удобно для пользователя. Возможно, понадобятся зацепки для всех клавиш перемещения или, что лучше, один зацепок для события прокрутки, если это возможно.
Руслан