The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Decl::Semantics::Commandline - implements a command line parser in an event context, using Getopt::Lucid

VERSION

Version 0.01

SYNOPSIS

When running any script, the command line provides a first-line configuration and specification mechanism for the action to be taken. Perl simply provides the usual @ARGV list that C also does (granted, Perl does some of the irritating tasks for you that C doesn't), but it's up to you to do something sensible with that list.

This module allows you to define a command-line tag that extracts various sorts of parameters from the command line, then takes the remaining parts of the list and treats it as a command to be executed.

It also provides a command loop (an internal command line) that can be embedded into any program to provide interactive services. A default set of commands could be provided as a debugger, for instance. (TODO: write a default set of commands as a debugger.)

Here's an example:

   command-line argv (loop)
      switch version "version|-V"
      counter verbose "verbose|-v"
      param config (anycase) "config|c"
      list libraries "lib"
      keypair def "define"
      
      command start "start something" {
         # Start something
      }
      command help "get help" {
         # Print a help text
      }
      
      do {
         # Handle unknown commands
      }
      

The top five lines in our specification represent the five types of named command line argument supported. Anything left on the command line after all the named parameters have been consumed is treated as a command and passed to the appropriate "on" event. The search order is the usual one: if a like-named event isn't found in the command line, the parent node will be searched, and so on up to the root. If no matching "on" is found, the arglist is passed to the "do" handler, if there is one.

If a command is on the command line, it executes only after all parsing is finished; that is, the command is executed as the "start" action of the program.

If there is no command and "loop" is specified, the start action passes control to a Term::Shell REPL loop using the same event logic. If "loop=always" is specified, the loop will run even if an initial command is given. The shell will use the quoted labels of the events as summary text for the help system; for longer texts, a "help" tag must be given, like this:

   command-line (loop)
      command start "start something"
         help
            The "start" command is used to start something
            and its help text may be multi-line.  It is not
            parsed.
         do { # start something }
         

If no command was found on the command line, and no loop is specified, then the command line will not be marked as callable, so the program won't call it as its start action and will have to look elsewhere. If you never want the command line to be the start action, you can flag it:

   command-line (nocall)
         

Normally, if not used as a command loop, the command line is just treated as a data source by name to permit its values to be queried from code elsewhere in the program. You can also specify a target data source like this:

   command-line (store=system.argv)
      switch verbose (anycase) "verbose|V"
      

There are four modifiers that can be added to named arguments:

   command-line
      switch parm1 (anycase) "parm1"
      keypair parm2 (required) "parm2"
      switch parm3 (needs=parm4) "parm3"
      param parm4 (valid="\d+") "parm4"
      

The anycase modifier makes the parameter case-insensitive. The required modifier means that this value must be specified or an error is raised. The needs modifier means that if parm3 is specified, then parm4 must also be specified or an error is raised. Finally, the valid modifier is a regexp that must be matched or (wait for it ...) an error is raised.

One or more named error handlers may be provided:

   command-line
      keypair parm2 (required, needs=parm3) "parm2"
         on error required {
            print STDERR "You need to specify parm2.\n"
         }
         on error needs {
            print STDERR "You can't specify parm2 without defining parm3.\n";
         }
      param parm3 (valid="\d+") "parm3"
         on error valid {
            print STDERR "parm3 must be numeric\n";
         }
         

You can also provide a more heavy-duty validator:

   command-line
      param configfile "config"
         valid { -r }
         on error valid {
            print STDERR "The configuration file you specified does not exist.\n";
         }
         

Almost all of that is just the semantics of Getopt::Lucid, which really is the end-all and be-all of command line parsing.

defines(), tags_defined()

Called by Decl::Semantics during import, to find out what xmlapi tags this plugin claims to implement.

post_build

All the work is done in the post_build stage.

go

Called when the element is run (that is, when the shell is invoked, if any).

THE TERMINAL

The standard shell

STANDARD COMMANDS

The default command line provides debugging and introspection tools - a REPL - along with whatever commands you define. Those commands are defined in this section. They can be disabled for a given command line with (debug=no).

run_show, smry_show, help_show

The show command shows the text of the current node (pages if necessary). If you give it one argument (e.g. "show code") it will use the argument to access the node's hashref and display the results. If the results are undefined, it will say so. If they're a scalar, it will print the scalar (through paging). If they're a ref, it will print the output of Data::Dumper (again through paging).

run_list, smry_list, help_list

The list command lists the text of the current node (pages if necessary). With a single argument, lists the nodes with that tag.

run_goto, smry_goto, help_goto

The goto command changes the current node by applying a "find" to the current node and switching the current node if it succeeds. If you provide neither [] nor (), the command assumes [].

prompt_str()

Returns the current prompt. TODO: make this overridable from the node definition.

AUTHOR

Michael Roberts, <michael at vivtek.com>

BUGS

Please report any bugs or feature requests to bug-decl at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Decl. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

LICENSE AND COPYRIGHT

Copyright 2010 Michael Roberts.

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See http://dev.perl.org/licenses/ for more information.