How do I non-interactively call a user defined vimscript function, and pass it the buffer?

My best guess is below, but it doesn't work:

echo "110511093 some dude" | vim -es ':call TwiddleCase(%)' '+%print' '+:q!' /dev/stdin | cat

function! TwiddleCase(str)
    if a:str ==# toupper(a:str)
        let result = tolower(a:str)
    elseif a:str ==# tolower(a:str)
        let result = substitute(a:str,'\(\<\w\+\>\)', '\u\1', 'g')
        let result = toupper(a:str)
     return result
vnoremap ~ y:call setreg('', TwiddleCase(@"), getregtype(''))<CR>gv""Pgv
  • Are you sure that :call TwiddleCase(%) would work if you call it interactively?
    – Maxim Kim
    Commented Aug 30, 2021 at 19:17
  • It would be helpful to show TwiddleCase
    – D. Ben Knoble
    Commented Aug 30, 2021 at 21:55
  • @D.BenKnoble There ya go!
    – leeand00
    Commented Aug 30, 2021 at 22:01
  • 1
    I posted an answer that corrects an obvious omission in your command line but I don't think the function call is correct. What you are trying to do exactly?
    – B Layer
    Commented Aug 31, 2021 at 6:53
  • @BLayer I'm trying to twiddle the case between Proper-Case and UPPER CASE. And I realize that the function just jumps between three states Proper, Upper and Lower.
    – leeand00
    Commented Aug 31, 2021 at 12:24

1 Answer 1


For starters, the first command (:call TwiddleCase(%)) is missing the + (or -c) that must precede all commands.

And you shouldn't need that trailing cat.

Oh and stylistically, IMO, it's a little clearer to keep the +s outside the command-enclosing quotes.


echo "110511093 some dude" | vim -es +'call TwiddleCase(%)' +'%print' +':q!' /dev/stdin

HOWEVER, there is something wrong with your approach. I'm not sure % is doing what you expect. I asked you about it in a comment and I'll update this answer as needed.

If I had to guess, based on "pass the buffer" and use of the %print command, you want to run the buffer's contents through your function and then replace the buffer with that. That requires a lot more than what you have. For your example the function call would be something like...

call setline(1, TwiddleCase(getline(1)))

If your real world case involves multiple lines then you could use the g[lobal] command to do something like the above against every non-empty line:

g/./ call setline(".", TwiddleCase(getline(".")))

Also, where is TwiddleCase defined? Because vim -e doesn't look for a vimrc like vim does. You could load your personal vimrc using -u ~/.vimrc (*nix style). Otherwise, you'll have to do something like + 'source {file}' before the other + params, where {file} is a path to a file containing the TwiddleCase code.

So here's what the complete Vim invocation would look like if my assumptions are correct:

vim -es -u ~/.vimrc +'g/./ call setline(".", TwiddleCase(getline(".")))' +'%print' +':q!' /dev/stdin
  • I am still confused with the fact you all can call a function like that -- it gives me Invalid expression: "%)"
    – Maxim Kim
    Commented Aug 31, 2021 at 6:53
  • @MaximKim Check out the comment I just posted. I agree that something ain't right here. (OTOH, I do not get that error message...even with -s removed.)
    – B Layer
    Commented Aug 31, 2021 at 6:54
  • @MaximKim Ah, you mean when run interactively, I suppose. Yes, I get that. It's obviously syntatically wrong. I'm guessing they mean "all buffer lines" though they're off track there.
    – B Layer
    Commented Aug 31, 2021 at 7:02
  • I didn't know that .vimrc isn't loaded with vim -e
    – leeand00
    Commented Aug 31, 2021 at 12:39
  • Yes, though strangely I can't find explicit/correct mention in the help docs. I see under :h vimrc, If Vim was started in Ex mode with the "-s" argument [normal vimrc search doesn't happen]. But my testing show it's the same with or without "-s". ("started in Ex mode" is when you run vim -e or, alternatively, ex.)
    – B Layer
    Commented Aug 31, 2021 at 13:53

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.