Argstring
Parse a single-line string into a structured set of sub-strings representing positional arguments, named arguments and flags.
Supports:
- configurable separators (e.g. space, comma)
- configurable assignment operators (e.g.
=,:) - quoted / enclosed tokens (e.g.
"a b",{a, b}) - escaping (e.g.
"a \" b") - duplicate named argument handling (e.g.
a=1 a=2 a=3)
Basic usage
parser = Argstring::Parser.new
result = parser.parse('arg1 foo=bar "a b"=c')
result.valid? # => true
result.position[1].text # => "arg1"
result.name["foo"].text # => "bar"
result.name["a b"].text # => "c"Everything stays as strings
Note that no type coercion takes place, so a=1 is a named argument a with the string value "1". If you want to interpret values as other types you can handle that in your own further processing step.
Argument types
Argstring recognizes three kinds of arguments:
Positional arguments
arg1 arg2 arg3
Each positional argument:
- is indexed starting at 1
- is available via
result.position[index] - is also optionally treated as a flag (see below)
Example:
result.position[1].text # => "arg1"Named arguments
key=value
-
keyandvalueare always strings - assignment operators are configurable
- exactly one assignment operator per argument is allowed
Example:
foo=bar
"a b"="c d"Access via:
result.name["foo"].textFlags
By default, every positional argument is also treated as a flag:
verbose
Equivalent to:
{ "verbose" => true }Access via:
result.flag["verbose"] # => trueFlags can be disabled via configuration.
Configuration
You can override the default configuration to modify how the arg string is parsed:
parser = Argstring::Parser.new(
separator: /\s/,
escape: "\\",
assignment: ["="],
enclosers: [{open: '"', close: '"' }, {open: "'", close: "'"}],
duplicates: :last,
flags: true,
positional: true
)separator
: Defines how arguments are split. /\s/ splits on whitespace (collapsed). A non-whitespace character (e.g. ",") splits only on that character, allows empty arguments, ignores surrounding whitespace, and permits spaces inside arguments.
assignment
: Array of characters that are used to assign a named argument. Set to the empty array to disable named arguments.
escape
: Specify the single character that is the escape character. Set to the empty string to disable escaping.
enclosers
: Array of hashes each with keys open and close, providing the characters that can be used to enclose (quote) part of the string, forcing it to be treated as a single token.
duplicates: :last or :first
: Controls which value is effective as Argument#value when a named argument appears multiple times. All values are preserved in Argument#values.
flags
: When enabled, positional arguments also emit boolean flags using their value as the flag name.
positional
: Controls whether positional arguments are recorded and indexed.
Result object
Parser#parse returns an Argstring::Arguments instance.
Core properties
result.valid? # boolean
result.errors # array of error messages
result.all # all Argument objects in encounter orderFiltered collections
result.positional # positional Argument objects
result.named # named Argument objects
result.flags # flag Argument objectsConvenience accessors
result.position[1] # => Value of first positional argument
result.name["foo"] # => Value of named 'foo' argument
result.flag["bar"] # => true if flag was setArgument objects
Each argument is represented by an Argument instance:
arg.kind # :positional | :named | :flag
arg.position # integer (positional only)
arg.name # Name token (named/flag only)
arg.value # Value token
arg.values # array of Value tokensToken metadata
Name and Value tokens expose:
token.text # the parsed string value
token.raw # the part of the original arg string that was parsed
token.enclosed? # was this token enclosed (e.g. in quotes)
token.enclosure # { open: "..", close: ".."} or nil: details of the enclosure if it was enclosedEnclosures (e.g. quotes)
Enclosures allow tokens to contain separators, whitespace, or assignment operators.
Default enclosers:
"double quotes"
'single quotes'Examples:
"a b"
key="c d"
'a=b'
'contains "double quotes" here'
Note that an unterminated enclosure will cause a parsing failure.
Escaping
Default escape character:
escape: "\\" # a single backslashYou can escape enclosure markers, assignment operators and the escape character itself. You can't escape whitespace if it's used as the argument separator.
Examples:
a\=b # => positional "a=b" rather than named
"a \"quote\"" # => value: a "quote"
Separators
The separator determines how arguments are split. Only separators create new arguments.
Whitespace separator (default)
separator: /\s/- Any whitespace splits arguments
- Runs of whitespace are collapsed
- Whitespace cannot appear inside tokens unless enclosed
Examples:
a b c # => 3 positional arguments
a=b c=d # => 2 named arguments
a b=c # => positional "a", named "b"
Important behaviors:
a = b # => positional "a", positional "=", positional "b"
"a b"=c # => named "a b"
"a b = c" # => a single positional argument with the value "a b = c"
Non-whitespace separator (e.g. comma)
separator: ","- Arguments are split only on the separator character
- Whitespace around segments is ignored
- Whitespace around assignment operators is ignored
- Whitespace inside segments is preserved
Examples:
a,b,c # => 3 positional
a, b , c # => same
a=b,c=d # => 2 named
a = b , c = d # => same as above
Assignment operators
By default:
assignment: ["="]You may supply multiple operators:
assignment: ["=", ":"]Rules:
- At most one assignment operator per argument
- Assignment operators inside enclosures are ignored
- Assignment operators can be escaped
Duplicate named arguments
Controlled via:
duplicates: :last # defaultOptions:
-
:last: last value wins -
:first: first value wins
Regardless of mode:
- all values are preserved in
Argument#values -
Argument#valueis the effective value
Example:
a=1 a=2 a=3
arg = result.named.first
arg.value.text # => "3" (with :last)
arg.values.map(&:text) # => ["3", "2", "1"]