AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[Lib] argp v3.0 Argument Options Parser

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Fri Nov 13, 2009 11:40 pm    Post subject: [Lib] argp v3.0 Argument Options Parser Reply with quote

Keywords: argument option switch parameter parse parser function lib library regex module read command string variable value name pair fast bobo download free gnu gpl

argp - Argument Options Parser Version: 3.0 (2010-01-30)

Download (~38 kb)
    The archive contains the library, examples, a test script using the UTest module by majkinetor and full documentation generated with custom installer of Natural Docs from majkinetor.

Online Documentation

LICENSE: Please note, the library is GNU LGPL licensed. Your script using this module do not need to be open source. See http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License

Syntax

Code:
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.

Description

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.

Specification

It works with complex option strings and the formatting is quite free. Any option must begin either with "-" or "/". Every option can have values. The spaces around values are lost, unless it is enclosed between single or double quotes. The name/value separator is optional and can be ":", "=" or " " (space). Spaces around the options are also optional. You see, its not that strict. This example string:
Code:
"-A -f:'file name.ahk'/i"

would be resolved to these 3 options
Code:
A
f
i

The option "f" would hold the value without quotes
Code:
file name.ahk

This nice example visualizes how the argp-functions sees the complex string. The green-parts are the parameter names. The orange-parts are the corresponding optional values of the parameters. Any grey-part is badly formatted and ignored, according the rules of the internally used regular expression. The red-parts are punctuation characters for separating the value from its name and marking the end of value.

This string:
Code:
-A='3/3'-/ c8-x'2 '-i--test.num: '44' /yy0 -f /f: c:"\tes"t-d\\E4 d\E\d -k:0/-t /file:'c:\t /e:1 st \file.ahk'  -e 2 /i -extra:'test/e:3 //e:4 /' /time:5:10 -date:11.08.2009

... would be seen as:
Code:
-A='3/3'-/ c8-x'2 '-i--test.num: '44' /yy0 -f /f: c:"\tes"t-d\\E4 d\E\d -k:0/-t /file:'c:\t /e:1 st \file.ahk'  -e 2 /i -extra:'test/e:3 //e:4 /' /time:5:10 -date:11.08.2009

"A", "x", "i", "test.num", "yy0", "f", "f", "d", "k", "t", "file", "e", "i", "extra", "time" and "date".
  1. An argument must start with "-" or "/".
  2. Then argument name consisting of these characters follows: a-z, A-Z, 0-9, _, ., ?, ! or @
  3. The value/name separator ":" "=" after the name is optional. A space can be used also for this.
  4. After the separator, the argument can have a value.
  5. The value can be enclosed between single or double quotes (then a separator ":" or "=" is needed).
  6. If the value is not enclosed between quotes, the next space or argument ends the value.
  7. Any space around the value is lost.

Some usage examples

The options variable holds the string given by the end user:
Code:
options := "-a:'foo -bar ' -B -c hello world"

  1. Get the count of found options. Restrict to a maximum of 8 items.
    Code:
    count := argp_parse(options, 8)

  2. Get a maximum of 3 options. Save the resulting names in variables 'name1' to 'name3' and corresponding values in 'value1' to 'value3'.
    Code:
    argp_parse(options, 3, name1, value1, name2, value2, name3, value3)

  3. Check if the options namely a", "b" and "c" exist and get a list with existing option names (with case sense on).
    Code:
    optlist := argp_getopt(options, "a b c")

The documentation contains usage examples and detailed descriptions of all functions.

Full usage example of argp_getopt() function

Code:
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
Code:
display("-caseMod 2 -html")

Last changes
  • breaks compatibility with last version
  • general rework at internal used regular expression
  • changed: renamed library and all functions from "args" to "argp" prefix and now args() is argp_parse() and args_names() is argp_getopt()
  • changed: the special optimization with 24 elements of argp_parse() is not longer present anymore, but added optimization maxcount "8" at argp_parse()
  • changed: the resulting (return value) list of argp_getopt() reflects the sorting order from original args source, and not from specified given list
  • new: first option of argp_getopt() (argp_parse() does not support this) can be a value without key, but it is not included in count and result is saved in ErrorLevel
  • extended: key names can contain one of these characters now a-z, A-Z, 0-9, _, ., ?, ! and @

Alternative libraries

You may also want to check Yook's Parameters and switches parser
or majkinetor's Parse
or ahklerner's options.ahkl - an options object for AutoHotkey_L libraries.


Last edited by Tuncay on Sat Jan 30, 2010 11:41 pm; edited 16 times in total
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Fri Nov 20, 2009 11:28 pm    Post subject: Update Reply with quote

Version 1.0

Last changes
  • Added: New parameter "caseSensitive" to enable the case insensitive option.
  • Improved: It should work better, with less possible bugs.
  • Change: Renamed the library from "param" to "args". Functions renamed to "args()" and "args_p()".
  • Bug: Spaces inside values are now catched properly.
  • Bug: The character sequence "\E" should not make any problems anymore.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 4052
Location: Belgrade

PostPosted: Sat Nov 21, 2009 11:28 am    Post subject: Reply with quote

Very much needed. Thanks.

I suggest you to use UTest for testing in this case, for both regression bugs and user satisfaction.
_________________
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Sat Nov 21, 2009 10:09 pm    Post subject: Update Reply with quote

Version 0.3

Last changes
  • Improved: More robust with values of parameters.
  • Change: Status and revision of library downgraded back to Beta.

First post updated completly. Downgraded back to Beta state, because it is not that stable as I thought.

majkinetor, a quick look at your UTest library looks promising. Something like that is what I need, but I was not able to work with it. I am not really understanding it. Can you show me an example how to work with it? I mean, an real world example, not just the template found in documentation.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 4052
Location: Belgrade

PostPosted: Sun Nov 22, 2009 8:22 pm    Post subject: Reply with quote

Sure. Ill add unit test for your option parser. Few samples, then you can extend it yourself.

Cheers.
_________________
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 4052
Location: Belgrade

PostPosted: Sun Nov 22, 2009 9:07 pm    Post subject: Reply with quote

Args with unittest and single doc file

Notes.

1. To create documentation as single file, you run "mkdoc s"
2. Just execute _Test.ahk in UTest folder. There is only 1 simple test from which you can understand how testing work. If you are still confused I suggest you search some Unit Testing tutorial. You will ideally have every important thing in some test function and when you change the code, you run tests again and make sure non of them failes (big FAIL or OK on the bottom is overall indicator).
3. Perhaps you should provide an option to get several parameters instead of just one. I usualy do that via "Query" parameter, pQ that contains list of things I want to extract. I am also concerned about many RegEx calls you will get when you get ALL of your parameters.
4. You will need to fix your "Known BUG or LIMITATION". This makes system not generally usable, as even file paths can contain - char.


BTW, if you didn't see, it, I made Parse function. The purpose is not the same, but its similar. Parse does its job in AHK manner, while your function does its jub in the cmd.exe manner.
Parse also contains UTests so you can see detailed example there.
_________________
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Sun Nov 22, 2009 9:39 pm    Post subject: Reply with quote

  1. I am working with Natural Docs. What do you mean by >>run "mkdoc s" << ? I am creating all documentation with MakeDoc.bat:
    Code:
    @echo off
    echo.
    echo Creating documentation....
    echo.

    ::path to the natural doc folder
    SET NDPATH=C:\Programme\NaturalDocs

    ::project root path
    SET ROOT=%CD%

    ::documentation folder
    SET DOC=doc



    mkdir "%ROOT%\%DOC%\_ndProj" 2>nul
    pushd "%NDPATH%"
    call NaturalDocs -i "%ROOT%" -o HTML "%ROOT%\%DOC%" -p "%ROOT%\%DOC%\_ndProj"

    popd

    ::create link to the index.html in root
    ::nircmdc shortcut "%ROOT%\%DOC%\index.html" "%ROOT%" Manual


  2. No, I am not confused. Now I understand the concept better. I had played with the function and was near to use it correctly.
  3. This project started for privately own usage, for a very simple object. The main purpose was just to check if an option exist, not to extract additional arguments or values. But it growed and the purpose seems to change a bit. Now, I am at the limit of my knowledge. I don`t like the fact to call it several times also. But before all that, the bug have to be fixed.
  4. Yes, we are of the same opinion about the BUG.


I have seen your Parse function already and added a link into the documentation.

majkinetor, thx for all what you have done here. Later, if I have more time, then I`ll have to add the Unit-Tests.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 4052
Location: Belgrade

PostPosted: Mon Nov 23, 2009 11:58 am    Post subject: Reply with quote

Quote:
What do you mean by >>run "mkdoc s" <<

Info is here: NDoc custom installer

Quote:
Now, I am at the limit of my knowledge.

Thats the best way to improve it.

Cheers.
_________________
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Sun Nov 29, 2009 10:53 pm    Post subject: Update Reply with quote

Version 2.0

Last changes
  • Completly rewritten.

The source is completly rewritten with a complete another regular expression and core. The aim is also changed and the way its work is not the same. Before this update, every option had to be checked with every call. Now, with one function call, all up to 24 options with its value can be retrieved. There are two similair functions now.

The old known BUG is not present anymore! It seems as if everything works as it should. There is no official test code, but I have tested the functions a bit and have not found any bug yet. Test code will follow.

The first post and documentation showing and explaining all in detail. Please give feedback, if someone uses this or want to use.
_________________
Now, I am at the limit of my knowledge.

Thats the best way to improve it.
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Wed Dec 02, 2009 11:28 am    Post subject: Update Reply with quote

Version 2.1

Last changes
  • There was a bug at args_names(), which prevented to save the right value of an option with value. Not sure if this works now.
  • Spaces around the return value are not deleted anymore, for use to check with InStr(options, " A ")

_________________
Now, I am at the limit of my knowledge.

Thats the best way to improve it.
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Wed Dec 02, 2009 8:44 pm    Post subject: Update Reply with quote

from 2.1 to 2.1.1 ... small update, now it works.
_________________
Now, I am at the limit of my knowledge.

Thats the best way to improve it.
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Sat Dec 05, 2009 3:52 pm    Post subject: Reply with quote

If someone tries this, please report. I would like to know if this someone needs or uses.

Note: Currently the functions uses "Critical" command of AutoHotkey. This does affect the whole thread at call place. It is planned to remove this or make use of following methode: Old_IsCritical := A_IsCritical followed later by Critical %Old_IsCritical%
_________________
Now, I am at the limit of my knowledge.

Thats the best way to improve it.
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Mon Dec 14, 2009 10:47 pm    Post subject: Update Reply with quote

Version 2.2

Last changes
  • The internal used Critical command is disabled now. This is, because it would change it for the whole thread
  • At the args() function, now VarSetCapacity() is used if not optimized option number (16, 24, 32) is specified.
  • The maximum possible number of options is changed from 24 to 32.


Usage Example of args_names()

Code:
; After call of args_names(): names contains a space separated list of case sensitive words or letters,
; with one space at beginning and end of string. Any in second parameter of args_names() defined options
; are checked for existence.  (3 possible options, 2 of them can have additional arguments)
names := args_names(_options                 ; String with the options.
    , "H m i"                                ; Options to search for.
    , true                                   ; Makes case sensitive.
    , opt_withFileNameMode, opt_maxCount)    ; Option arguments.
; Every option is checked with caseSens on and space around for existence in names.

opt_withFileName := (InStr(names, " H ", true) ? true : false)
; Use default value, if not specified with argument at "H".
If (opt_withFileNameMode = "")
{
    opt_withFileNameMode := 1
}

opt_useMaxCount := (InStr(names, " m ", true) ? true : false)
; Use default value, if not specified with argument at "m".
If (opt_maxCount = "")
{
    opt_maxCount := 1
}

; Default is case sensitive search.
opt_caseSensitive := (InStr(names, " i ", true) ? false : true) ; false : true


Later in code, you can easily check if a option was specified with
Code:
If (opt_useMaxCount = true)
{
    Loop, %opt_maxCount%
        ... { do something stupid }
}

_________________
Now, I am at the limit of my knowledge.

Thats the best way to improve it.
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 753
Location: Berlin, DE

PostPosted: Sat Jan 30, 2010 10:50 pm    Post subject: Update Reply with quote

Version 3.0

Last changes
  • breaks compatibility with last version
  • general rework at internal used regular expression
  • changed: renamed library and all functions from "args" to "argp" prefix and now args() is argp_parse() and args_names() is argp_getopt()
  • changed: the special optimization with 24 elements of argp_parse() is not longer present anymore, but added optimization maxcount "8" at argp_parse()
  • changed: the resulting (return value) list of argp_getopt() reflects the sorting order from original args source, and not from specified given list
  • new: first option of argp_getopt() (argp_parse() does not support this) can be a value without key, but it is not included in count and result is saved in ErrorLevel
  • extended: key names can contain one of these characters now a-z, A-Z, 0-9, _, ., ?, ! and @

Major update! I would say it is stable now. Also the license is changed to GNU Lesser General Public License, which allows everyone using this module. Your own scripts do not need to be open source and can have any license.
_________________
Now, I am at the limit of my knowledge.

Thats the best way to improve it.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group