ArgumentParser @Option arguments that contain spaces and treat them as a single value

Let's say I have a command that accepts an option such as -o in SSH as in the command below. You can pass multiple configurable options like ProxyCommand="ssh firewall nc remote 22".

let sampleCommand = "ssh -o ProxyCommand=\"ssh firewall nc remote 22\" server"

This command option clashes with the parse function as it only takes in an array of Strings to parse the given command.

`MyCommand.parse(commandString.components(separatedBy: " "))`

Passing the sampleCommand to the parse function breaks the meaning of the command as the individual elements in the array don't make sense, if you take them in a String they make sense as the content of ProxyCommand should be treated as a single string to be sent not as an array. Also, this parameter ProxyCommand can vary and be other one such as Host="17.123.123.123".

Is it possible for my ParsableCommand model to parse command values that contains spaces such as 'ssh firewall nc remote 22' as shown before? I don't know if a valid option would be to treat the -o as a separate subcommand and how to deal with the variability of arguments it take would be handled by ArgumentParser.

Thanks!

When you run an executable from a shell (e.g. bash or zsh), the shell will split the line into parts, and when ArgumentParser runs, it expects to receive these parts.

In other words: splitting the string into parts / components is not something ArgumentParser will do — or should do. The splitting while respecting quoting and escaping is entirely handled inside the calling process, i.e. bash / zsh.

The question, thus: why are you using .components(separatedBy: " ") — where is commandString coming from? If you need to / want to handle quoting / escaping, you’ll have to do that part yourself. It’s (intentionally) not part of the ArgumentParser.

Hi @deggert thanks for jumping in,

I am using Argument Parser to help me parse some commands in a CLI iOS app I'm working on hence my initial syntax of passing the command String already split. The sampleCommand String is something a user would enter in a terminal environment.

As I am not using ArgumentParser as a CLI app but using it on an iOS app to help me with parsing the Options & Flags I am calling the .parse() function every time a user enters a command the way I quote on my original post.

As per your last paragraph I am afraid that'd be my own task to do and differentiate each quoting/escaping option that might appear in the command. Is there a better way to parse a command String for this case?

There isn't a standard method that will help with this, unfortunately. You'll need to decide on what kind of quoting grammar you want to support (nesting? escaping? single/double/both?) and implement your own splitting routine that can handle your requirements:

Input: "ssh -o ProxyCommand=\"ssh firewall nc remote 22\" server"
Output: ["ssh", "-o", "ProxyCommand=\"ssh firewall nc remote 22\"", "server"]

This can be a fun project, depending on your definition of "fun"!

1 Like

That definitely sounds like a fun thing :) , thank you both @nnnnnnnn & @deggert for your help!