Barra di scorrimento per vim (uno basato su maledizioni, non gvim)?


10

Come utente Linux, mi sono sentito abbastanza a mio agio con gli strumenti CLI e TUI, ma mi manca la piccola barra di scorrimento presente in quasi tutti i programmi della GUI. È sempre stato più facile per me sapere quanto è lungo il file e dove sono dalla barra di scorrimento anziché "9752 righe, 24%".

Quello che mi aspetto è una barra di scorrimento ASCII che assomigli

|
|
|
|
#
#
#
|
|
|

e posso configurare per apparire a sinistra oa destra (e se a sinistra, la posizione relativa ai numeri di riga e ai segni di piegatura). Esiste già un plug-in Vim per farlo o come posso scriverne uno mio? Il framework dei plugin di Vim non sembra supportare direttamente tali modifiche dell'interfaccia utente.

Risposte:


3

Se stai considerando il percorso "scrivi il tuo plug-in", la funzione 'sign' di Vim potrebbe essere un buon punto di partenza. Questa funzione spiega come, ad esempio, i plugin di controllo della sintassi evidenziano errori.

esempio di segno vim

Un semplice approccio per posizionare il segno sarebbe quindi:

  1. Determina la posizione in cui ti trovi nel file in percentuale p
  2. Determina quante linee sono visibili nelle finestre di VIM L
  3. Posiziona un segno al numero di riga più vicino a int(p*L)
  4. Ricalcola il movimento attorno al file

Grazie! Questo è molto vicino al mio requisito dichiarato, anche se dal documento sembra che i segni possano essere disegnati solo sul lato sinistro. Buona risposta però, accettata!
xiaq,

10

È possibile utilizzare la linea di stato come barra di scorrimento. Avevo il seguente nel mio .vimrc, che emula una barra di scorrimento (inoltre è solo in orizzontale, ma funziona sorprendentemente bene). Questo è stato originariamente discusso sulla Mailinglist vim_use alcuni anni fa.

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

Assicurati di avere l' laststatusopzione impostata su 2.


Mi piace molto questa soluzione poiché mette la barra di scorrimento in un posto in cui non occupa spazio dalla finestra di codifica. Grazie Christian!
dotancohen,

Mi piace l'idea e forse posso persino vivere con una pseudo-barra di scorrimento orizzontale. Ma @redacted ha presentato una soluzione più vicina al mio requisito dichiarato. hai +1 sulla tua risposta però. Grazie!
xiaq,

Come si imposta il colore della BG dell'indicatore della posizione di scorrimento? È quasi indistinguibile dal resto della barra usando il tema solarizzato su kde.
Mike

Indovina dalle ultime righe che vengono utilizzati i gruppi di evidenziazione User1 e User2. Puoi ridefinirli.
Christian Brabandt,

6

Il mio tentativo di redenzione del mio precedente passo falso ...

L'idea mi è piaciuta, quindi oggi ho scritto un plug-in per VIM per mostrare un 'pollice' della barra di scorrimento usando la funzione sign di vim.

È ancora MOLTO beta, ma è utilizzabile in questo momento, ho ancora del lavoro da fare su di esso, incluso scrivere tutti i documenti, i commenti e le cose.

Pubblicherò qui la fonte, ma sei il benvenuto per estrarla dal mio Hg Repo . (Non ridere troppo delle altre cose)

Ricorda ... MOLTO beta, considerando che non ho mai scritto un plugin prima, dilettandosi con VimL nel corso degli anni. (meno di 12 ore dal concept al prototipo funzionante! yay!)

Continuerò a lavorarci, un po 'pulito. I colori sono sgargianti per un motivo, facile vedere cosa cambia. Al momento ha un grosso bug, non puoi far sparire tutti i segni disattivandolo. So come implementarlo, volevo solo condividere.


Le immagini sono utili:

Vim-Scrollbar in azione


Barra di scorrimento delle maledizioni 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:

Intendi guioptionse come dice chiaramente l'aiuto, questo funziona solo per la versione gui di vim.
Christian Brabandt,

Bello. Ho implementato qualcosa di simile nel plug-in DynamicSigns. A proposito: nota che i segni non vengono disegnati, su linee piegate.
Christian Brabandt,

Grazie! Ho pensato che avrei dovuto rimediare al mio foobar prima, poi mi sono interessato di più ... quindi l'ho scritto. Come sempre, il lavoro iniziale è facile ... ottenere tutto ciò che è frustrante e di bell'aspetto è la parte frustrante. (nessun segno sulle pieghe ... annotato)
lornix

Grazie! Ma a giudicare dai dati @redacted ha fatto apparire la funzionalità del segno prima di te, quindi forse è più educato accettare la sua risposta. Hai + 1 sulla tua risposta.
xiaq,

1
Il tuo repository è stato rimosso. Sarebbe bello se potessi metterlo da qualche parte come Github e lasciare che gli altri contribuiscano ad esso. Penso davvero che sia fantastico.
Mike,

0

Non è una soluzione ideale, ma puoi scoprire dove ti trovi nella riga di stato con qualcosa di simile

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

o usando set numberper avere un numero di riga prima di ogni riga.

A meno che tu non abbia modificato vim source (ncurses), non penso che ciò sia possibile, ma potrei sbagliarmi.


Grazie ma lo sapevo già ... Stavo solo cercando qualcosa di più facile per gli occhi.
xiaq,

È stato un colpo lungo.
Sardathrion - contro l'abuso di SE

0

Ecco una versione trascinabile con il mouse. Si aggiorna anche solo quando si utilizza la rotella di scorrimento - se è necessaria una barra di scorrimento, la mano dovrebbe essere comunque sul mouse.

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

Questo funziona per il mouse, ma non viene aggiornato quando si scorre con ad es. Ctrl + F. Il marker sembra rimanere nel suo numero di riga originale. Fare :call UpdateScrollbox()funziona, ma non è facile da usare. Potrebbe essere necessario un hook su tutti i tasti di movimento o, meglio, un hook su un evento scroll, se possibile.
Ruslan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.