2
\$\begingroup\$

I have written a vimscript for learning purposes. The script displays the content of registers in a side bar by polling all registers periodically and redrawing the side bar when any changes happens. I want to get a review.

My Vim version is 8.0.

I know about the latest version and some features, which can be useful in this script, like deletebufline(), but I decided to stick to a more common version.

At this moment I use this script by such way:

  1. Open source file show_regs.vim.
  2. Do a :so % | Showreg command.

Also, it can be converted to a plugin and placed into an autoload directory I think.

The script is capable to execute three commands:

  1. Showreg - creates the side bar
  2. Unshowreg - removes the side bar
  3. Cleanregs - cleans all numbered and lettered registers.

function! s:Update_reg_dict(timer)
    " If the register's bar was deleted manually,
    " stop update function's timer and remove all script's variables 
    if !buflisted(s:buf_name)
        call s:Unshow_reg_bar()
        return
    endif

    let l:flag = 0
    " The previous highlight dictionary should be discarded every time
    let s:highlght = {}

    " Comparison of current register values with stored in the dictionary
    for [l:key, l:val] in items(s:reg_dict)
        let l:new_val = strtrans(getreg(l:key))
        if l:val !=# l:new_val
            let s:reg_dict[l:key] = l:new_val
            " Adds a changed register to the highlight dictionary
            let s:highlght[l:key] = '*'
            let l:flag = 1
        endif
    endfor
    " if any register was changed, rewrite a bar
    if l:flag
        call s:Write_reg_dict_to_bar()
    endif
endfunction

function! s:Create_reg_bar()
    " if the register's bar doesn't exist
    if buflisted(s:buf_name)
        return
    endif

    execute 'rightbelow ' s:reg_bar_size.'vnew' s:buf_name

    set winfixwidth
    set nonu
    set nowrap

    " A changed registers highlight color
    highlight MyGroup ctermbg=green
    " Special characters colorizing
    highlight Escaped_chars ctermfg=blue

    call matchadd('MyGroup', '^\*".')
    call matchadd('Escaped_chars', '\^[\[ICWLPMV@H]')

    execute 'wincmd p'
endfunction

function! s:Write_reg_dict_to_bar()
    let l:num = 1
    for l:key in split(s:reg_names, '\zs')
        let l:val = s:reg_dict[l:key]
        if l:val != ''
            " If a register was changed, then put a mark '*' to the beginning of line
            let l:mark = get(s:highlght, l:key, ' ')
            call setbufline(s:buf_name, l:num, printf('%s"%s| %s', l:mark, l:key, l:val))
            let l:num += 1
        endif
    endfor
    " Clean up all unneeded lines, which are left from the previous update
    " vim 8.1 has a special delete function 'deletebufline()', but I use vim 8.0
    while l:num < len(s:reg_dict)
        call setbufline(s:buf_name, l:num, '')
        let l:num += 1
    endwhile

endfunction

function! s:Create_reg_dict()
    if exists('s:reg_dict')
        return
    endif

    let s:reg_dict = {}

    for l:char in split(s:reg_names[1:], '\zs')
        " 'strtrans' is used to make register content printable
        let s:reg_dict[l:char] = strtrans(getreg(l:char))
    endfor
    " Unnamed register should be treated separately
    let s:reg_dict['"'] = strtrans(getreg(''))
endfunction

function! s:Unshow_reg_bar()
    if !exists('s:reg_dict')
        return
    endif

    if buflisted(s:buf_name)
        execute 'bdelete!' s:buf_name
    endif

    call s:Timer_stop()
    " Cleaning up of script's variables scope
    for l:variable in keys(s:)
        execute 'unlet s:'.l:variable
    endfor

" Other way to clean
"       unlet s:buf_name
"       unlet s:reg_names
"       unlet s:reg_dict
"       unlet s:highlght
"       unlet s:timer
"       unlet s:reg_bar_size
"       unlet s:update_time
endfunction

function! s:Timer_start()
    let s:timer = timer_start(s:update_time, function('s:Update_reg_dict'), {'repeat': -1})
endfunction

function! s:Timer_stop()
    call timer_stop(s:timer)
endfunction

function! s:Clean_regs()
    if !exists('s:reg_dict')
        return
    endif

    " Only numbered and lettered registers are cleaned
    for l:char in split(s:reg_names[1:-7], '\zs')
        call setreg(l:char, '')
    endfor
endfunction

" Main function
function! s:Show_reg_bar(...)
    if exists('s:reg_dict')
        return
    endif

    let s:reg_bar_size = a:0 >= 1 ? a:1 : 30
    let s:update_time = 100
    let s:buf_name = 'reg_bar'
    let s:reg_names = '"0123456789abcdefghijklmnopqrstuvwxyz-.:%#/='
    let s:highlght = {}
    let s:timer = ''

    call s:Create_reg_bar()
    call s:Create_reg_dict()
    call s:Write_reg_dict_to_bar()
    call s:Timer_start()

endfunction

command! -nargs=* Showreg call s:Show_reg_bar(<f-args>)
command! Unshowreg call s:Unshow_reg_bar()
command! Cleanregs call s:Clean_regs()

Demonstration

enter image description here

\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.