2

Let's take a look at the example below.

function! Print (text)
    echo a:text
endfunction

function! Mapping_test (parameter)
    nnoremap m1 :call Print (a:parameter)<CR>
    nnoremap m2 :call Print ("hello")<CR>
    execute 'nnoremap m3 :call Print ("' . a:parameter . '")<CR>'
    execute 'command! -nargs=0 MTest :call Print ("' . a:parameter . '")'
endfunction

call Mapping_test ("hello world")

m1 mapping produces two errors:

E121: Undefined variable: a:parameter                                                                                                                                                                                                               
E116: Invalid arguments for function Print

m2 and m3 work fine. So calling function with string literal is fine, using execute is also ok, but why m1 does not work?

Basically, I could take m3 and be happy, but if I change argument of Mapping_test() from string literal to an array then m3 does not work either.

call Mapping_test (["hello world"])

produces

E730: Using a List as a String

I even tried to use command, but result is the same, when passing List as a:parameter, error occurs.

So, is there any possible way I can pass argument (here a:parameter) to a function call (in a mapping) which type is not a String?

0

1 Answer 1

1

Mappings always execute in the global context. That is, they don't "remember" that they were defined inside a function, so they can't access a: variables directly.

As for the E730: Using a List as a String error, you can try using type() and join():

function! Mapping_test (parameter)
    nnoremap m1 :call Print (a:parameter)<CR>
    nnoremap m2 :call Print ("hello")<CR>
    execute 'nnoremap m3 :call Print ("' . (type(a:parameter) == type([]) ? join(a:parameter, '') : a:parameter) . '")<CR>'
    execute 'command! -nargs=0 MTest :call Print ("' . (type(a:parameter) == type([]) ? join(a:parameter, '') : a:parameter) . '")'
endfunction
3
  • 1
    and probably don't forget to escape all the stuff inside parameter so it doesn't get interpreted by :map, unless you want that!
    – D. Ben Knoble
    Sep 28, 2023 at 14:18
  • I thought about converting it to string in the first place, but supposed it is a workaround solution. Seems to be the one for now. Oct 1, 2023 at 17:56
  • Basically since you're using :execute it requires a string argument, and you were trying to drop in a non-string type. Depending on what you're really trying to do you can get around it, but I wanted to keep my answer simple.
    – Heptite
    Oct 1, 2023 at 19:14

Your Answer

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

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