Skip to content

ConvincibleMedia/ruby-gem-argstring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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
  • key and value are 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"].text

Flags

By default, every positional argument is also treated as a flag:

verbose

Equivalent to:

{ "verbose" => true }

Access via:

result.flag["verbose"] # => true

Flags 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 order

Filtered collections

result.positional # positional Argument objects
result.named      # named Argument objects
result.flags      # flag Argument objects

Convenience accessors

result.position[1]    # => Value of first positional argument
result.name["foo"]    # => Value of named 'foo' argument
result.flag["bar"]    # => true if flag was set

Argument 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 tokens

Token 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 enclosed

Enclosures (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 backslash

You 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   # default

Options:

  • :last: last value wins
  • :first: first value wins

Regardless of mode:

  • all values are preserved in Argument#values
  • Argument#value is 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"]

About

Configurable parser for single-line argument strings, returning a structured set of sub-strings representing positional arguments, named arguments and flags.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages