1

So i found the following vimscript code:

let s:mappings = {
        \ 'k': {id -> s:scroll_line(id, -1)},
        \ 'j': {id -> s:scroll_line(id, 1)},
        \ 'd': {id -> s:scroll_page(id, 0.5)},
        \ 'u': {id -> s:scroll_page(id, -0.5)},
        \ 'f': {id -> s:scroll_page(id, 1)},
        \ 'b': {id -> s:scroll_page(id, -1)},
        \ 'g': {id -> popup_setoptions(id, #{firstline: 1})},
        \ 'G': {id -> s:bottom(id)},
        \ 'q': {id -> popup_close(id)}
        \ }

function! s:scroll_line(winid, step) abort
    let line = popup_getoptions(a:winid).firstline
    if a:step < 0
        let newline = (line + a:step) > 0 ? (line + a:step) : 1
    else
        let nlines = line('$', a:winid)
        let newline = (line + a:step) <= nlines ? (line + a:step) : nlines
    endif
    call popup_setoptions(a:winid, #{firstline: newline})
endfunction

function! s:scroll_page(winid, size) abort
    let height = popup_getpos(a:winid).core_height
    let step = float2nr(height*a:size)
    call s:scroll_line(a:winid, step)
endfunction

function! s:bottom(winid) abort
    let height = popup_getpos(a:winid).core_height
    let nlines = line('$', a:winid)
    let newline = (nlines - height) >= 0 ? (nlines - height + 1) : 1
    call popup_setoptions(a:winid, #{firstline: newline})
endfunction

function! s:popup_filter(winid, key) abort
    if has_key(s:mappings, a:key)
        call get(s:mappings, a:key)(a:winid)
        return v:true
    endif
    return v:false
endfunction

let text = range(50)->map({_,i -> string(i)})
call popup_create(text, #{
        \ minwidth: 40,
        \ maxwidth: 40,
        \ minheight: 8,
        \ maxheight: 8,
        \ firstline: 1,
        \ scrollbar: 1,
        \ mapping: v:false,
        \ filter: funcref('s:popup_filter')
        \ })

which run successfully if i run it with vim --clean popup.vim -c "source %" when put inside a file called popup.vim but fail if run by yanking and doing @", with the following error E120: Using <SID> not in a script context: s:scroll_line.

I basically want to run it in the commandline, so i can do faster testing when adding/removing code, instead of saving/opening the file it reside at...(eg: fast prototyping etc)

How can i run this snippet on the Vim commandline?

1

TL;DR: Use :source % instead.

Local functions and variables are indeed a limitation of the :@ approach. As I actually mentioned in my answer to your previous question:

There are some limitations, such as you can't define local functions and variables (in the s: namespace.)

If you want to be able to only load parts of it using the :@ command, then you should turn the functions into global functions (without the s:, and starting with an uppercase letter), or perhaps using a namespace autoload-style function name will work (as in mylinenumbers#scroll_page, etc.) In either case, you'll have to go through all the call sites for every function to adapt them to the new style, which is not great...

Since you're editing them from a *.vim file, though, perhaps the best approach is to reload it using :source % every time you want to reload it. I don't see any reason why this wouldn't work, in fact I'd say that's probably the easiest approach of all.

3
  • 2
    Or :Runtime, if you use tpope/scriptease. – D. Ben Knoble Sep 15 '20 at 0:39
  • Using :source % was fine until i noticed you had to save first for it to work :/. At least i can make a mapping out of it that save first, and using tpope's scriptease work great too, as an alternative. – Nordine Lotfi Sep 16 '20 at 19:25
  • 1
    Actually it seems like :Runtime need the file to be saved first (afaik). Guess I'll post something related to that. :D – Nordine Lotfi Sep 16 '20 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.