# argp - Argument Options Parser

Parse an argument string with options and get keys and values.

#### License

© Copyright 2009, 2010 Tuncay

This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://www.gnu.org/licenses/.

See the file COPYING.txt and COPYING.LESSER.txt for license and copying conditions.

Summary

argp - Argument Options Parser | Parse an argument string with options and get keys and values.
Description | About the idea
Usage | How to use the functions
Specification | Argument string format
Functions |
argp_parse | Get optional keys and values as separate variables.
argp_getopt | Check for known keys and get list of them and all values as separate variables.

### Description

About the idea

#### Introduction

Sometimes we need to work with many optional parameters. Some of the parameters may be just logical flags only (true/false). If the function have too many such parameters, the usability is endangered. To workaround that disgrace, we can make one option string to the function. From now on, this string contains all parameters. This is comparable to the commandline.

It must be parsed to find all parts. Writing such parsers could become difficult and slow down the complete process. The parsing is tried to be made with one regex call only (with some other non dramatic lines). As long as the string is keeped simple, there should be no problem. But with growing complexity, with different values of subparameters, it is a pain to make the difference.

#### Who needs this?

This is not a parser for command line arguments of programs or scripts. It is similiar to Windows or Unix/Linux command line arguments, but different in some ways and less powerful. This library is for those ahk developers, who needs to write user defined functions with many options. With the parsing of just one real function parameter, it can be avoided to have a bunch of function parameters.

#### What it can do for you

The source will be parsed and all found options are given over to specified variables. The other work parsing these generated variables is left to the user.

- Pro: A standardized, simple and fast way of options handling.
- Contra: It isn`t a well known official standard.

#### History

This library is rewritten from scratch and the old BUG or LIMITATION is not present anymore. Not only that. It does work in a completly another way. After searching the web, I found a regular expression made by Richard Hauer at regexlib.com. I have modified it and now it is the backbone of my functions. One deserved credit goes to him.

The name of the library is changed again, from args to argp. The chosen name argp is a GNU C library for parsing arguments of programs. This AutoHotkey library is named like it, but there is no compatibility with the GNU C library. The name is an abbreviation for “ARGument Parser”.

#### Links

- Discussion: [http://www.autohotkey.com/forum/viewtopic.php?p=310409]
- License: [http://www.gnu.org/licenses/lgpl-3.0.html]
- Wikipedia - LGPL: [http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License]

#### Date

2010-01-30

#### Revision

3.0

#### Status

Release

#### Credits

- Tuncay, [tunc.nosp@m.ay.d@gmx.nosp@m..de] (Author)
- Richard Hauer [http://regexlib.com/REDetails.aspx?regexp_id=1220] (Author of original Regular Expression)

#### License

GNU Lesser General Public License 3.0 or higher [http://www.gnu.org/licenses/lgpl-3.0.html]

#### Category

String Manipulation

#### Type

Library

#### Tested AutoHotkey Version

1.0.48.05

#### Tested Platform

2000/XP

#### Standalone (such as no need for extern file or library)

Yes

#### StdLibConform (such as use of prefix and no globals use)

Yes

#### Related

Other Community Solutions

- Parameters and switches parser by Yook: [http://www.autohotkey.com/forum/viewtopic.php?t=50885]
- [function] Parse by majkinetor: [http://www.autohotkey.com/forum/viewtopic.php?t=49261]
- options.ahkl - an options object for AutoHotkey_L by ahklerner: [http://www.autohotkey.com/forum/viewtopic.php?t=49430]

### Usage

How to use the functions

#### Syntax

>     count := argp_parse( source [, maxcount, keyname1, value1, ... keyname32, value32] )

>     optlist := argp_getopt( source [, keylist, caseSense, value1, ... value32] )

There are two independently working functions. They have the same regular expression at the core, but the functionality and interface differs. One creates variables for each key name and the other one returns a list with names, checking against another list of possible names (either with case sense on or off and, removing dublicates).

After calling one of the functions, the variables or the list must be parsed. This is left to be done by the user. For the beginner, it is recommended to use argp_getopt() and then check with InStr() if a name exists in resulting list (with surrounding spaces).

No globals are created, no special objects or frameworks are needed.

#### Installation

Just name the library to “argp.ahk” and put it into the standard or user library folder. A call of one of these functions in this library will lead to automatically include it into the script at call time. The folder should reside under one of these paths:

>     %A_MyDocuments%\AutoHotkey\Lib\  ; User library.
>     path-to-the-currently-running-AutoHotkey.exe\Lib\  ; Standard library.

Alternatively you can include this library at any position of your script with the #include command:

>     #Include argp.ahk

#### Example 1

This is part of parsing the options parameter from hypotetical function set_clipboard(). The code demonstrates some aspects only, and it`s not optimized.

>     ; Set default values prior to parsing argument string.
>     opt_wait_use := false
>     opt_errorlevel_set := false

>     ; Analyze the variable argument for existence of options namely "wait" and "errorlevel".
>     ; Save the value of "wait" into variable wait_value.
>     ; After that, a new list with option names is get and saved into variable optlist.
>     optlist := argp_getopt(argument, "wait errorlevel", false, wait_value)

>     ; Now, parse the list and set options for programs usage.
>     If InStr(optlist, " wait ")
>     {
>         opt_wait_use := true
>         opt_wait_value := wait_value
>     }

>     If InStr(optlist, " errorlevel ")
>     {
>         opt_errorlevel_set := true
>     }

If the set_clipboard() function was called with following options

>     "-w:2"

Then the following variables are set

>     opt_wait_use := true
>     opt_wait_value := 2
>     opt_errorlevel_set := false

#### Example 2

The next example shall show how to translate an usual function to argp_getopt() powered function. One function could look like this (very boring I know):

>     display(sentence = "hello world", caseMod = 0, html = 0)
>     {
>         If (caseMod = 1)
>             StringUpper, sentence, sentence, T
>         Else If (caseMod = 2)
>             StringUpper, sentence, sentence
>         Else If (caseMod = 3)
>             StringLower, sentence, sentence
>         If ( html)
>             Transform, sentence, HTML, %sentence%
>         MsgBox %sentence%
>     }

A call could look like this

>     display("hello world", 1, 1)

Next code is one possible version with argp

>     display(options)
>     {
>         ; Default values of options.
>         sentence = hello world

>         ; Parsing options.
>         optlist := argp_getopt(options, "sentence caseMod html", false, sentence_value, caseMod_value)

>         Loop, Parse, optlist, %A_Space%, %A_Space%
>         {
>             If ("sentence" = A_LoopField)
>                 sentence := sentence_value
>             Else If ("caseMod" = A_LoopField)
>             {
>                 If (caseMod_value = 1)
>                     StringUpper, sentence, sentence, T
>                 Else If (caseMod_value = 2)
>                     StringUpper, sentence, sentence
>                 Else If (caseMod_value = 3)
>                     StringLower, sentence, sentence
>             }
>             Else If ("html" = A_LoopField)
>                 Transform, sentence, HTML, %sentence%
>         }

>         MsgBox %sentence%
>     }

Lets see how a call could look now

>     display("-caseMod 2 -html")

What is done there? First we have changed from multiple function parameters to single parameter. All the necessary default parameters are set in the function body. Then the argp_getopt() is used to parse options variable. The third parameter (here set to false) is for doing the parse without case sensitivity. All the parameters after that, are variables for holding possible values of the options. That is, because every option can have its own value.

After this process, the resulting optlist variable holds the found names of options (given are the three “sentence caseMod html”). As a next step, this optlist variable must be parsed manually for checking which options are found actually and doing the right actions. In this example, a Loop, Parse command is chosen. There are other possibilities like multiple InStr() checks.

### Specification

Argument string format

#### Basic structure

Any option must begin either with a hypghen “-” or slash “/”, to be recognized as an option. It doesn`t matter which of the two is used. The following character or word until next option or space is the key name of that option. In example:

>     -a -b

and

>     -a-b

would be resolved to these keys

>     a
>     b

Although space is not required, you can write without it.

Normally parts in string that are not recognized as options should be ignored. In such a case, the resulting variable and value is allways empty.

#### Values added to keys

Every option can have its own assigned value. The value can be delimited from its key name with a space “ “, a double colon “:” or an equality sign “=”. If it is enclosed in quotes, then no delimiter is needed. The value is read until one space is found (or another option starts). In example:

>     -a test1 -b

would be resolved to these keys

>     a
>     b

Where “a” holds the value “test1”.

Normally spaces around a value are lost. The value can be optionally enclosed between a pair of single or double quotes. That way spaces inside the quotes are saved.

>     -a:'foo -bar ' -B -c hello world

would be resolved to these keys

>     a
>     B
>     c

Where a holds the value “foo -bar “ and c the value “hello”.

If a value contains one of these characters -, /, :, =, ‘ or “, then it is best to enclose the whole value between quotes (single or double).

#### Dublicate keys

argp_parse() and argp_getopt() treat duplicate definitions of option names in different ways. argp_parse() sees every key separately. And argp_getopt() sees the first definition only. This is important if they have values. In example:

>     -a:foo -a:bar -A

would argp_getopt() resolve to

>     a
>     A

where a would holds the value “foo” and A would have an empty value. In contrast argp_parse() resolves to

>     a
>     a
>     A

first a holds “foo” and second a holds “bar”. Again, the last A have an empty value.

#### Key naming

These characters in key name are allowed: a-z, A-Z, 0-9, _, ., ?, ! and @. Some examples:

>     -a
>     -test
>     /test.example
>     /?
>     -64
>     -@section

#### The one special value without key name

There is one exception in argp_parse() function only. Any string before first option is treated as a special value without a key name. That value is parsed like any other value. In example:

>     hello -a

would be resolved to these keys

>     a

The key “a” does have an empty value and the first special value “hello” is saved in ErrorLevel. This is supported by argp_parse() function exclusively.

### Functions

### argp_parse

> argp_parse( | ByRef | _args, |  |
> |  | _maxcount | = | 32,
> | ByRef | _n1 | = | "",
> | ByRef | _v1 | = | "",
> | ByRef | _n2 | = | "",
> | ByRef | _v2 | = | "",
> | ByRef | _n3 | = | "",
> | ByRef | _v3 | = | "",
> | ByRef | _n4 | = | "",
> | ByRef | _v4 | = | "",
> | ByRef | _n5 | = | "",
> | ByRef | _v5 | = | "",
> | ByRef | _n6 | = | "",
> | ByRef | _v6 | = | "",
> | ByRef | _n7 | = | "",
> | ByRef | _v7 | = | "",
> | ByRef | _n8 | = | "",
> | ByRef | _v8 | = | "",
> | ByRef | _n9 | = | "",
> | ByRef | _v9 | = | "",
> | ByRef | _n10 | = | "",
> | ByRef | _v10 | = | "",
> | ByRef | _n11 | = | "",
> | ByRef | _v11 | = | "",
> | ByRef | _n12 | = | "",
> | ByRef | _v12 | = | "",
> | ByRef | _n13 | = | "",
> | ByRef | _v13 | = | "",
> | ByRef | _n14 | = | "",
> | ByRef | _v14 | = | "",
> | ByRef | _n15 | = | "",
> | ByRef | _v15 | = | "",
> | ByRef | _n16 | = | "",
> | ByRef | _v16 | = | "",
> | ByRef | _n17 | = | "",
> | ByRef | _v17 | = | "",
> | ByRef | _n18 | = | "",
> | ByRef | _v18 | = | "",
> | ByRef | _n19 | = | "",
> | ByRef | _v19 | = | "",
> | ByRef | _n20 | = | "",
> | ByRef | _v20 | = | "",
> | ByRef | _n21 | = | "",
> | ByRef | _v21 | = | "",
> | ByRef | _n22 | = | "",
> | ByRef | _v22 | = | "",
> | ByRef | _n23 | = | "",
> | ByRef | _v23 | = | "",
> | ByRef | _n24 | = | "",
> | ByRef | _v24 | = | "",
> | ByRef | _n25 | = | "",
> | ByRef | _v25 | = | "",
> | ByRef | _n26 | = | "",
> | ByRef | _v26 | = | "",
> | ByRef | _n27 | = | "",
> | ByRef | _v27 | = | "",
> | ByRef | _n28 | = | "",
> | ByRef | _v28 | = | "",
> | ByRef | _n29 | = | "",
> | ByRef | _v29 | = | "",
> | ByRef | _n30 | = | "",
> | ByRef | _v30 | = | "",
> | ByRef | _n31 | = | "",
> | ByRef | _v31 | = | "",
> | ByRef | _n32 | = | "",
> | ByRef | _v32 | = | "" | )

Get optional keys and values as separate variables.

#### Syntax

>     count := argp_parse( args [, maxcount, n1, v1, ... n32, v32] )

#### Parameters

args | Variable [string] input: Source String variable with options to parse. See above at “Specification”, which is a description about the format.
maxcount | Optional [integer] input: Specifies how many options to get. Anything below ‘1’ or above ‘32’ defaults to ‘32’.
n1-n32 | Variable Optional [string] output: Stores the key name of option into variable. Variable n1 would hold first found name of option (i.e. “A”).
v1-v32 | Variable Optional [string] output: Stores the value of an option into variable. Variable v1 would hold value of first found option (i.e. “33”).

#### Returns

Number of retrieved options, or ‘0’ otherwise.

#### Remarks

maxcount can be set to an integer value between 1 and 32. That restricts the number of options to extract from source string. In example, if specified to 8, then the first 8 options are seen and the rest is ignored. This is an optimization. Maximum possible of 6 options to parse is faster than to parse 26 options. Plus, there are special optimizations to 8, 16 and 32, so they are faster in execution against values near to them. These values (8, 16, 32) are highly recommended.

#### ErrorLevel

ErrorLevel is set to the first special value without key name. Otherwise it is empty. With following example:

>     get -i

it would hold “get”. With next example

>     -i get

ErrorLevel would be empty.

#### Examples

>     options = -A='33' -i /f:c:\test -time:5:10 -x /date:11:08:2009
>     count := argp_parse(options, 8, n1, v1, n2, v2, n3, v3, n4, v4, n5, v5, n6, v6, n7, v7, n8, v8)
>     Text =
>     (
>     Number of options in source (options):
>     %count%

>     Name of key 3 (n3):
>     %n3%

>     Value of key 3 (v3):
>     %v3%
>     )
>     MsgBox %Text%

Output:

>     Number of options in source (options):
>     6

>     Name of key 3 (n3):
>     f

>     Value of key 3 (v3):
>     c:\test

### argp_getopt

> argp_getopt( | ByRef | _args, |  |
> |  | _keylist | = | "",
> |  | _case | = | true,
> | ByRef | _1 | = | "",
> | ByRef | _2 | = | "",
> | ByRef | _3 | = | "",
> | ByRef | _4 | = | "",
> | ByRef | _5 | = | "",
> | ByRef | _6 | = | "",
> | ByRef | _7 | = | "",
> | ByRef | _8 | = | "",
> | ByRef | _9 | = | "",
> | ByRef | _10 | = | "",
> | ByRef | _11 | = | "",
> | ByRef | _12 | = | "",
> | ByRef | _13 | = | "",
> | ByRef | _14 | = | "",
> | ByRef | _15 | = | "",
> | ByRef | _16 | = | "",
> | ByRef | _17 | = | "",
> | ByRef | _18 | = | "",
> | ByRef | _19 | = | "",
> | ByRef | _20 | = | "",
> | ByRef | _21 | = | "",
> | ByRef | _22 | = | "",
> | ByRef | _23 | = | "",
> | ByRef | _24 | = | "",
> | ByRef | _25 | = | "",
> | ByRef | _26 | = | "",
> | ByRef | _27 | = | "",
> | ByRef | _28 | = | "",
> | ByRef | _29 | = | "",
> | ByRef | _30 | = | "",
> | ByRef | _31 | = | "",
> | ByRef | _32 | = | "" | )

Check for known keys and get list of them and all values as separate variables.

#### Syntax

>     optlist := argp_getopt( source [, keylist, caseSense, value1, ... value32] )

#### Parameters

args | Variable [string] input: Source String variable with options to parse. See above at “Specification”, which is a description about the format.
keyList | Optional [string] input: A space separated list of option names. Every key in options source string args will be in returning optlist. All values are written to output variables from number 1 to 32. The third item in this list relates to third output variable. If the keylist is empty “”, then all existing key names are get.
case | Optional [flag] input: Case sensitivity of names checking; sensitiv at default (true or 1) leads to let “a” as a different option as “A”.
1-32 | Variable Optional [string] output: Stores the value of option into variable. Variable number 1 would hold value (i.e. “33”) of first defined option (i.e. “A”).

#### Returns

Get a space separated list of matching names. This means, all not found option names are filtered out from keyList. Duplicate names are not found and first one is used instead. (In example: “A file A c i”, these are the names of 4 options.)

If keyList is empty, then all options found in source is returned. Order of corresponding values (specified variables 1-32) reflects the order in source. But if keyList is a non empty list, then all options specified in this list are returned.

#### Remarks

Other than argp_parse(), this function awaits a list of option names in keyList. That keylist is compared against all found option names from source. All matching keys are copied to resulting return list.

The returning list have spaces around also (at begin of list and end of). That allows checking for existency of keys with

>     InStr(keylist, " A ")

Any existing value corresponding to the key name is copied to output variable ranging from 1 to 32. In example second options value belongs to second variable, even if there is no value. In that case, the value is an empty string (blank value).

#### ErrorLevel

ErrorLevel is set to the number of matching option names. Duplicates are not counted. If nothing is found, it is set to ‘0’. It is not the count of resulting keylist, but the count of keys in source string args.

#### Examples

>     options = -A='33' -i /f:c:\test -time:5:10 -x /date:11:08:2009
>     optlist := argp_getopt(options, "s i test a", false, v1, v2, v3, v4)
>     Text =
>     (
>     Number of options in source (options):
>     %count%

>     List of all matching key names (optlist):
>     %optlist%

>     Value of key 4 (v4):
>     %v4%
>     )
>     MsgBox %Text%

Output:

>     Number of options in source (options):
>     6

>     List of all matching key names (optlist):
>      a i

>     Value of key 4 (v4):
>     33

> argp_parse( | ByRef | _args, |  |
> |  | _maxcount | = | 32,
> | ByRef | _n1 | = | "",
> | ByRef | _v1 | = | "",
> | ByRef | _n2 | = | "",
> | ByRef | _v2 | = | "",
> | ByRef | _n3 | = | "",
> | ByRef | _v3 | = | "",
> | ByRef | _n4 | = | "",
> | ByRef | _v4 | = | "",
> | ByRef | _n5 | = | "",
> | ByRef | _v5 | = | "",
> | ByRef | _n6 | = | "",
> | ByRef | _v6 | = | "",
> | ByRef | _n7 | = | "",
> | ByRef | _v7 | = | "",
> | ByRef | _n8 | = | "",
> | ByRef | _v8 | = | "",
> | ByRef | _n9 | = | "",
> | ByRef | _v9 | = | "",
> | ByRef | _n10 | = | "",
> | ByRef | _v10 | = | "",
> | ByRef | _n11 | = | "",
> | ByRef | _v11 | = | "",
> | ByRef | _n12 | = | "",
> | ByRef | _v12 | = | "",
> | ByRef | _n13 | = | "",
> | ByRef | _v13 | = | "",
> | ByRef | _n14 | = | "",
> | ByRef | _v14 | = | "",
> | ByRef | _n15 | = | "",
> | ByRef | _v15 | = | "",
> | ByRef | _n16 | = | "",
> | ByRef | _v16 | = | "",
> | ByRef | _n17 | = | "",
> | ByRef | _v17 | = | "",
> | ByRef | _n18 | = | "",
> | ByRef | _v18 | = | "",
> | ByRef | _n19 | = | "",
> | ByRef | _v19 | = | "",
> | ByRef | _n20 | = | "",
> | ByRef | _v20 | = | "",
> | ByRef | _n21 | = | "",
> | ByRef | _v21 | = | "",
> | ByRef | _n22 | = | "",
> | ByRef | _v22 | = | "",
> | ByRef | _n23 | = | "",
> | ByRef | _v23 | = | "",
> | ByRef | _n24 | = | "",
> | ByRef | _v24 | = | "",
> | ByRef | _n25 | = | "",
> | ByRef | _v25 | = | "",
> | ByRef | _n26 | = | "",
> | ByRef | _v26 | = | "",
> | ByRef | _n27 | = | "",
> | ByRef | _v27 | = | "",
> | ByRef | _n28 | = | "",
> | ByRef | _v28 | = | "",
> | ByRef | _n29 | = | "",
> | ByRef | _v29 | = | "",
> | ByRef | _n30 | = | "",
> | ByRef | _v30 | = | "",
> | ByRef | _n31 | = | "",
> | ByRef | _v31 | = | "",
> | ByRef | _n32 | = | "",
> | ByRef | _v32 | = | "" | )

Get optional keys and values as separate variables.

> argp_getopt( | ByRef | _args, |  |
> |  | _keylist | = | "",
> |  | _case | = | true,
> | ByRef | _1 | = | "",
> | ByRef | _2 | = | "",
> | ByRef | _3 | = | "",
> | ByRef | _4 | = | "",
> | ByRef | _5 | = | "",
> | ByRef | _6 | = | "",
> | ByRef | _7 | = | "",
> | ByRef | _8 | = | "",
> | ByRef | _9 | = | "",
> | ByRef | _10 | = | "",
> | ByRef | _11 | = | "",
> | ByRef | _12 | = | "",
> | ByRef | _13 | = | "",
> | ByRef | _14 | = | "",
> | ByRef | _15 | = | "",
> | ByRef | _16 | = | "",
> | ByRef | _17 | = | "",
> | ByRef | _18 | = | "",
> | ByRef | _19 | = | "",
> | ByRef | _20 | = | "",
> | ByRef | _21 | = | "",
> | ByRef | _22 | = | "",
> | ByRef | _23 | = | "",
> | ByRef | _24 | = | "",
> | ByRef | _25 | = | "",
> | ByRef | _26 | = | "",
> | ByRef | _27 | = | "",
> | ByRef | _28 | = | "",
> | ByRef | _29 | = | "",
> | ByRef | _30 | = | "",
> | ByRef | _31 | = | "",
> | ByRef | _32 | = | "" | )

Check for known keys and get list of them and all values as separate variables.
Close