Pasek przewijania dla vima (oparty na klątwach, a nie gvim)?

10

Jako użytkownik Linuksa czułem się całkiem dobrze z narzędziami CLI i TUI, ale brakuje mi małego paska przewijania obecnego w prawie każdym programie GUI. Zawsze łatwiej mi było dowiedzieć się, jak długi jest plik i gdzie jestem z paska przewijania zamiast „9752 linii, 24%”.

Oczekuję, że wygląda pasek przewijania ASCII

|
|
|
|
#
#
#
|
|
|

i mogę skonfigurować, aby pojawiał się po lewej lub po prawej stronie (a jeśli po lewej, względna pozycja do numerów linii i znaków zagięcia). Czy jest już dostępna wtyczka Vima do tego celu lub jak mogę napisać własną? Struktura wtyczek Vima nie wydaje się bezpośrednio obsługiwać takich modyfikacji interfejsu użytkownika.

xiaq
źródło

Odpowiedzi:

3

Jeśli zastanawiasz się nad trasą „napisz własną wtyczkę”, dobrym pomysłem na początek może być „znak” Vima . Ta funkcja pozwala np. Wyróżnić błędy sprawdzania składni.

przykład znaku vim

Proste podejście do umieszczenia znaku byłoby wtedy:

  1. Określ procentowo miejsce w pliku p
  2. Określ, ile linii jest widocznych w oknach vima L
  3. Umieść znak przy numerze linii najbliższym int(p*L)
  4. Przelicz na podstawie ruchu wokół pliku
zredagowane
źródło
Dzięki! Jest to bardzo bliskie mojemu wymaganiu, choć z dokumentu wynika, że ​​znaki można narysować tylko po lewej stronie. Dobra odpowiedź, zaakceptowana!
xiaq
10

Można użyć linii statusu jako paska przewijania. Kiedyś miałem w moim .vimrc, który emuluje pasek przewijania (również jest tylko w poziomie, ale działa zaskakująco dobrze). Zostało to pierwotnie omówione na liście mailingowej vim_use kilka lat temu.

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()

Upewnij się, że masz laststatusopcję ustawioną na 2.

Christian Brabandt
źródło
Naprawdę podoba mi się to rozwiązanie, ponieważ umieszcza pasek przewijania w miejscu, w którym nie zajmuje miejsca w oknie kodowania. Dzięki, Christian!
dotancohen
Podoba mi się ten pomysł i być może mogę żyć z poziomym pseudo-przewijaniem. Ale @redacted przedstawił rozwiązanie bliższe moim określonym wymaganiom. mieć +1 na twojej odpowiedzi. Dzięki!
xiaq
Jak ustawić kolor znacznika pozycji przewijania BG? Jest prawie nie do odróżnienia od reszty paska za pomocą słonecznego motywu na kde.
Mike
Zgadnij z ostatnich wierszy, że używane są grupy wyróżnień Użytkownik1 i Użytkownik2. Możesz je przedefiniować.
Christian Brabandt,
6

Moja próba odkupienia mojej wcześniejszej faux pas ....

Podobał mi się ten pomysł, więc dzisiaj napisałem wtyczkę do VIM-a, która pokazuje „kciuk” paska przewijania za pomocą funkcji znaków vima.

To wciąż BARDZO wersja beta, ale teraz jest użyteczna, wciąż mam nad tym do zrobienia, w tym pisanie wszystkich dokumentów, komentarzy i innych rzeczy.

Zamieszczę tutaj źródło, ale możesz pobrać je z mojego repozytorium Hg . (Nie śmiej się zbyt mocno z innych rzeczy)

Pamiętaj ... BARDZO w wersji beta, biorąc pod uwagę, że nigdy wcześniej nie pisałem wtyczki, tylko przez lata zagłębiałem się w VimL. (mniej niż 12 godzin od koncepcji do działającego prototypu! tak!)

Nadal będę nad tym pracować, trochę fajnie. Kolory są jaskrawe z jakiegoś powodu, łatwo zobaczyć, jakie zmiany. Ma teraz duży błąd, nie można sprawić, że wszystkie znaki znikną, wyłączając go. Wiem, jak to wdrożyć, chciałem się tylko podzielić.


Zdjęcia są przydatne:

Pasek przewijania Vim w akcji


Pasek przewijania VIM Curses - v0.1 - L Nix - [email protected] Hg Repo

" 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:
lornix
źródło
Masz na myśli guioptionsi jak jasno stwierdza pomoc, działa to tylko w wersji GUI vima.
Christian Brabandt,
Miły. Zaimplementowałem coś podobnego we wtyczce DynamicSigns. BTW: pamiętaj, że znaki nie są narysowane, na złożonych liniach.
Christian Brabandt,
Dziękuję Ci! Pomyślałem, że powinienem wcześniej nadrobić swój foobar, potem zainteresowałem się nim ... więc napisałem to. Jak zawsze, początkowa praca jest łatwa ... frustrująca jest uciążliwość i fajny wygląd. (brak śladów na fałdach ... odnotowano)
lornix
Dzięki! Sądząc jednak z danych @redacted, przywołałem funkcję znaku wcześniej niż ty, więc być może bardziej uprzejmy jest zaakceptować jego odpowiedź. Daj +1 dla twojej odpowiedzi.
xiaq
1
Twoje repozytorium zostało usunięte. Byłoby wspaniale, gdybyś mógł postawić to gdzieś jak github i pozwolić innym się do tego przyczynić. Naprawdę myślę, że wygląda świetnie.
Mike
0

Nie jest to idealne rozwiązanie, ale możesz dowiedzieć się, gdzie w pliku znajdujesz się w linii statusu za pomocą czegoś takiego

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

lub używając set numbernumeru linii przed każdą linią.

Jeśli nie zmodyfikowałeś źródła vima (ncurses), to nie sądzę, że jest to możliwe, ale mogę się mylić.

Sardathrion - przeciw nadużyciom SE
źródło
Dzięki, ale już to wiedziałem ... Po prostu szukałem czegoś łatwiejszego dla oka.
xiaq
To był długi strzał.
Sardathrion - przeciwko nadużyciom SE
0

Oto wersja, którą można przeciągać myszą. Aktualizuje się także tylko wtedy, gdy używane jest kółko przewijania - jeśli potrzebujesz paska przewijania, i tak ręka powinna znajdować się na myszy.

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
źródło
Działa to w przypadku myszy, ale nie jest aktualizowane po przewinięciu za pomocą np. Ctrl + F. Znacznik wydaje się pozostawać w oryginalnym numerze linii. Robi :call UpdateScrollbox()działa, ale nie jest przyjazny dla użytkownika. Może potrzebować haczyków na wszystkich klawiszach ruchu, a najlepiej jednego haka na zdarzeniu przewijania, jeśli to możliwe.
Ruslan