1

These are my scenarios and expected output

function! s:Foo(text)
    echoerr "'" . a:text . "'"
endfunction

command ... FooCommand ... (not sure what to write here)

FooCommand text

'text'

FooCommand text asdfsfd

'text asdfsfd'

(it's hard to see in stackoverflow but the next one has trailing whitespace)

FooCommand line with 4 trailing spaces    

'line with 4 trailing spaces '

FooCommand line with"quotes" here

'line with"quotes" here'

Nothing that I've tried works. I've tried <f-args>, <q-args>, <args> and I've tried manually adding ""s around the non q- versions. They all fail for some reason or another.

Either the function will say it didn't get enough args, Undefined variable, or including "s will cut off text at the first double-quote that's found.

The best combination I got was my first try - Use <q-args> and then manually escape "s all the time. But even then, <q-args> doesn't seem to allow trailing whitespace. So I can't use it for what I'm trying to do.

Is there any way for Vim to just let me pass everything as one big string to a function and it just escape everything properly? Including quotes. Including spaces. I just want Vim to take whatever I write and put it in a string.

ColinKennedy
  • 411
  • 2
  • 9

1 Answers1

3

You must add -nargs=1 to your command:

:command -nargs=1 FooCommand :call Foo(<q-args>)

This tells Vim not to treat white space as separator. Only white space between the command name and the first non-white space character is removed from the argument passed to Foo(). All other spaces and tabs, even trailing ones, are included in the argument.

Jürgen Krämer
  • 1,712
  • 1
  • 11
  • 12
  • Okay, that's definitely it. Thank you for your help. I tried this initially but got tripped up because I also included -bar in the command definition. If you do :command -bar -nargs=1 FooCommand :call Foo(<q-args>) then Vim errors with "E471: Argument required". Do you know how to make this work with -bar as well? – ColinKennedy Jul 04 '19 at 04:00
  • Okay, I think the reason is because -bar enables commenting. So Vim thinks that the quoted text "" is actually the start of a comment. I haven't figured out a way around it but it would at least explain why the function thinks it isn't getting any args – ColinKennedy Jul 04 '19 at 05:19
  • -bar is primarily there to allow a user-defined command to be followed by another command, e.g., :FooCommand Hello World | echo 'I just fooed "Hello World"'. A nice side effect of this is, that the second command can be an empty command with a comment, which can be used to comment the first command: :FooCommand Hello World | "I just fooed 'Hello World'. – Jürgen Krämer Jul 04 '19 at 05:58
  • I understand that. I wanted support for | which is why I originally included -bar. But as mentioned before, -bar changes the way "s are interpreted and causes a string to be interpreted as a comment. Also, even without any "s in the input, -bar removes trailing whitespace (third example in my original post). Is there a way to get the same functionality as before but including -bar? – ColinKennedy Jul 04 '19 at 15:48
  • If you add -bar to the command definition you will have to escape both | and " with a backslash (and, of course, backslashes, too), e.g., :FooCommand \"Hello \| World\" | echo 'I just fooed "Hello | World"'. Trailing whitespace will again be removed, though, and it seems it cannot be protected with backslashes. – Jürgen Krämer Jul 04 '19 at 17:22
  • But what do you want to achieve? Do you really need to follow :FooCommand ... with another command? Wouldn't it be easier to call the function directly and pass a single-quoted string? – Jürgen Krämer Jul 04 '19 at 17:24
  • Honestly there's not that much of a need. I could do the command followed by another. My use case is search and replace, basically :MyCoolQuickFixCommand "def " | cdo %s/def /chef/g. I had to write my own search function because the files are highly proprietary at my company and spread across multiple folders and files include other files recursively.

    Basically I was hoping for something idiomatic. What you've shown me gets me most of the way there (thank you for your help so far, by the way).

    – ColinKennedy Jul 05 '19 at 03:25