ParseArgs

Summary: Description of ParseArgs function for parsing argument lists
Version:
Prerequisites: pmwiki-2.0.0
Status: Stable
Maintainer: Petko (original author: Pm)
Votes:
Discussion: ParseArgs-Talk

Questions answered by this recipe

  • Is there a function to make it easier to parse directive arguments when writing Cookbook recipes?
  • How do I make use of the ParseArgs() function?

Description

Since 2.0.beta25, PmWiki has a built-in function called ParseArgs() that simplifies the parsing of argument strings, e.g. for (:directives:). This recipe describes how ParseArgs() works and how it can be used.

For example, here's a directive for a list of all "normal" pages in the Cookbook:

(:pagelist group=Cookbook list=normal fmt=simple:)

Or, for a search of all pages in Main containing "apple" and "cherry" but not "apple pie":

(:searchresults group=Main apple -"apple pie" cherry:)

name= usage

The potential for items to be quoted is what makes parsing such arguments a challenge. This is where ParseArgs is useful -- it will accept a string containing name=value and other (possibly quoted) arguments, and return an array with the arguments all in place. For example, given

$args = ParseArgs('group=Cookbook list=normal fmt=simple');

the $args variable would then be set with:

    $args['group']     'Cookbook'
    $args['list']      'normal'
    $args['fmt']       'simple'

This makes it simple to grab options from a string:

$args = ParseArgs($x);      // $x is the string to be parsed
$group = $args['group'];
$list = $args['list'];
$fmt = $args['fmt']; 

Default values for options can also be easily handled:

$defaults = array('fmt'=>'bygroup', 'list'=>'all');
$args = array_merge($defaults, ParseArgs($x));
$group = $args['group'];   
$list = $args['list'];     
$fmt = $args['fmt']; 

Token usage

Arguments that don't have a name= or value: in front are placed into an '' array entry:

$args = ParseArgs('group=Main apple cherry');

resulting in

    $args['group']     'Main'
    $args['']          array('apple', 'cherry');

+ and - usage

Arguments preceded by '+' or '-' get their own array entries:

$args = ParseArgs('group=Main apple -"apple pie" cherry');
    $args['group']     'Main'
    $args['']          array('apple', 'cherry')
    $args['-']         array('apple pie')

Finally, if the order of all of the arguments needs to be known, a special '#' entry provides the complete ordering:

$args = ParseArgs('group=Main apple -"apple pie" cherry');
    $args['#']         array('group', 'Main', 
                         '', 'apple', 
                         '-', 'apple pie',
                         '', 'cherry')

Quoted usage

Quoted arguments have their matched single or double quotes removed, e.g.

$args = ParseArgs('label="an example" caption=\'descriptive phrase\'');
    $args['label']     'an example
    $args['caption']   'descriptive phrase

Notes

Note that the function uses both "=" and ":" as an assignment operator. Thus, if you want to have a string like an URL that starts with "https:" in a numbered array $args[""], you need to pass a second argument to ParseArgs:

$args = ParseArgs("https://www.pmwiki.org", '(?>(\\w+)=)');

This will return $args[""][0] = "https://www.pmwiki.org". Otherwise, you would obtain $args['https'] = "//www.pmwiki.org".

Demo

As an example, you can enter an argument string to be parsed in the box below and see the values that would result from calling ParseArgs with that string.

Key                 Value(s)
---------           --------
$arg['#']           (array) 'group' 'Main' '' 'apple' '-' 'apple pie' '' 'cherry' 
$arg['group']       'Main' 
$arg['']            (array) 'apple' 'cherry' 
$arg['-']           (array) 'apple pie' 

Restrictions

You can't have a parameter that has both a single and a double quote in it. (You can write "This ' is a single quote" and 'This " is a double quote', but you can't write "These '" are a single and a double quote"). In this, ParseArgs follows HTML conventions.

Examples

In this section we give more examples of calling ParseArgs to process arguments.

(Feel free to add questions or examples here.)

Hacks

There's a problem when the text field contains single or double quote to be displayed:

(:gma-point lat=yyy lon=xxx text="Vincent's home":)

Here is the hack (for version 2.1.2). In the file cookbook/GoogleMapAPI/gma-2.1.2.php

 line 181 in the if structure add the following lines:
 ->  
$m = preg_replace("/'/","\'", $m);
$m = preg_replace('/"/','\"', $m); 
line 304 before the call to the function parseArgs add the following lines: ->
//Hack for quotes
$args=stripslashes($args);
//end hack 

ParseArgs in PmWiki.php

function ParseArgs($x, $optpat = '(?>(\\w+)[:=])') {
  $z = array();
  preg_match_all("/($optpat|[-+])?(\"[^\"]*\"|'[^']*'|\\S+)/",
    $x, $terms, PREG_SET_ORDER);
  foreach($terms as $t) {
    $v = preg_replace('/^([\'"])?(.*)\\1$/', '$2', $t[3]);
    if ($t[2]) { $z['#'][] = $t[2]; $z[$t[2]] = $v; }
    else { $z['#'][] = $t[1]; $z[$t[1]][] = $v; }
    $z['#'][] = $v;
  }
  return $z;
}

$x, the subject, must be a string, the optional second parameter is the pattern that is matched.

See Also

Contributors

  • Pm, 2005-03-02