kabanus
kabanus

Reputation: 25980

Persistent (sticky) first line or column in VIM

This may be a stretch, but is there a chance to script a vim command such that the first (any?) row is constantly displayed at the top? The first (any) column (defined by a unique delimiter) be constantly displayed in the left?

The best I can manage is to split the screen and maximize the bottom one, so something like

split %
wincmd w
wincmd _

would be good for an upper row, but of course if the row is wider than the screen it doesn't work that well - unless there is a way to start a mode where two windows have their columns aligned.

For a persistent column I'm less sure. Need to somehow get the column of first delimiter (f command I thought, but I couldn't get it to work), vsplit % and vertical resize, then switch, wincmd l. Again this will only work if there are less rows then entire screen.

Doing both is even trickier, but possible using the above. I would also split the title row to make an empty cell at the corner. As far as synchronization, the title has to keep the row but sync on column, and vice-versa for the persistent column.

Is there a way to create such a persistent row+column setup that is synchronized with the main window? Also getting rid of the file names would be useful in this setup.

Upvotes: 0

Views: 964

Answers (1)

kabanus
kabanus

Reputation: 25980

This is the best I could do, thanks to @DoktorOSwaldo's comment above. F2 and F3 toggle between a bound first column (according to given delimiter) and a bound first row. F4 destroys both:

hi cursorcolumn ctermbg=red
function Title_destroy()
    if( winnr() == 1 )
        return 0
    endif
    let oldpos = getpos('.')
    wincmd k
    wincmd j
    hide
    call setpos('.',oldpos)
    set nocul
    set nocuc
endfunction
function Title_bar()
    if( winnr() > 1 )
        call Title_destroy()
    endif
    set nowrap
    split %
    set scb
    wincmd j
    set scb
    wincmd _
    set scrollopt=hor
    set cuc
endfunction
function Col_bar(delim)
    if( winnr() > 1 )
        call Title_destroy()
    endif
    set nowrap
    let oldpos = getpos('.')
    call setpos('.',[oldpos[0],oldpos[1],0,oldpos[3]])
    let width = searchpos(a:delim)[1]+3
    call setpos('.',oldpos)
    vsplit %
    exe 'vertical resize' width
    set scb
    wincmd l
    set scb
    set scrollopt=ver
    set cul
endfunction
nnoremap <F2> :call Title_bar()<CR>
nnoremap <F3> :call Col_bar(nr2char(getchar()))<CR>
nnoremap <F4> :call Title_destroy()<CR>

I couldn't figure out a way to do both at the same time, since scrollopt is a global thing. If anyone figures it out please leave a comment or answer. Maybe somehow overloading window scrolling to change the scrollopt according to the scroll direction. For now this is good enough for handling large tables (for me).

Upgrades

  1. It's fairly easy to accept a number optional argument - to change the row/column from just first.
  2. Having both a sticky row and a sticky column.

Upvotes: 1

Related Questions