deploy command line
1.0.0A simple command line option interface for applications used with Deploy.
Table of Contents
About deploy-command-line
This is a simple command line arguments handling system to quickly extend your program shipped with Deploy and provide a set of extra commands that users might find useful.
How To
While not strictly necessary, it is expected that your application will make use of Deploy to be turned into a standalone binary. You can then make your system's :entry-point be org.shirakumo.deploy.command-line:toplevel to hook into the command line processing, or manually call it from your own entry point as desired.
By default only one command is defined, help, and a number of help sections are also defined for you based on information that ASDF and Deploy know about.
In order to define commands you can make use of define-command and define-class-command. It'll look much like a standard defun though with some extra metadata to handle the parsing of the arguments, help, and so on. Let's take a look at an example:
(command-line:define-command eval (&key ((load :load :l) NIL pathname "A file to load")
((print :print :p) NIL boolean "Whether to print the results of the forms")
((verbose :verbose :v) NIL boolean "Whether to print the forms being executed")
&rest (forms NIL "Lisp forms to evaluate"))
:aliases ("e" "evaluate")
:help "Evaluate an arbitrary Lisp form. May be useful for debugging purposes. Only advisable if you know exactly what you're doing!"
(when load
(when verbose (format *query-io* "~&; Loading ~a~%" load))
(load load :verbose verbose))
(dolist (form forms)
(with-input-from-string (stream form)
(loop for form = (read stream NIL #1='#:EOF)
until (eq form #1#)
do (when verbose (format *query-io* "~&; Evaluating ~a~%" load))
(let ((values (multiple-value-list (eval form))))
(when print (format *query-io* "~{~&~a~%~}" values)))))))This defines a command named eval that has three key arguments (&key) and takes an arbitrary number of arguments afterwards (&rest). The key arguments each have aliases (:load :l) so that the user can specify a shorter name on the command line too. Further, the key arguments are parsed according to their respective types (pathname) and have a help string ("A file to load").
Then we define alias names for the command itself ("e" "evaluate"), along with a help string (:help ...), and finally we actually define the code to run when the command is invoked.
The syntax for arguments in commands is as you expect, with required arguments, &optional, &key, and &rest all supported. All of those can be further specified to provide the extra metadata for the command line interface however, in the very least to provide the type name and help string.
On the command line itself, the order of arguments for required, optional, and rest arguments must be the same as specified in the lambda-list. However, all of those can be interspersed with key arguments. Keyword arguments also follow "standard" Unix command line syntax, with long keys requiring two dashes (--foo) and single-character keys requiring a single dash (-f). In the single dash case you can also bunch multiple keys together (-fbz). If a key's value has the type boolean it is treated as a flag and when present on the command line, the value of the key argument is the inverse of its default. Otherwise the key expects another argument immediately after, which is treated as the key's value (--foo value).
If you need to extend the types of arguments that can be parsed, you can do so by adding methods to parse-command-line-type, and should you need to manually invoke commands, you can do so with invoke-command.
For more low-level management, you can set or remove commands via the command accessor, and set the default command used if no command is provided by the user via *default-command*. All commands are named by case-insensitive strings. Trying to define another command with the same name as another will replace the previous command.
Finally, the default help command will either display help specific to another command, or a general overview in the style of Unix manual pages. Depending on the information in your system definition, the following sections will be provided, corresponding to typical man-pages sections.
name(only if there is a system present at all)synopsisdescription(only if the system has a long-description)commandsenvironment variablesauthors(only if the system has at least one author or maintainer)reporting bugs(only if there is a command named "bugs" or if the system has a bug-tracker)copyright(only if there is a command named "copyright" or if the system has a license)see also(only if the system has a homepage)
You can remove those sections by setting the help-section for them to NIL, or add your own via define-help-section:
(command-line:define-help-section files (stream)
:order 40
(command-line:with-help-section (stream ".my-rc" 2)
(f "Read when the program starts up to initialise the environment before anything else.")))By default any help output will automatically be line wrapped and indented nicely to follow the correct layout. The with-help-section macro also helps to indent inner sections properly.
Sometimes you may only want to show a help section depending on some runtime test. To do this, you can provide a :test body option, the form of which will be evaluated first to decide whether to print the section at all.
System Information
Definition Index
-
ORG.SHIRAKUMO.DEPLOY.COMMAND-LINE
No documentation provided.-
EXTERNAL SPECIAL-VARIABLE *COMMANDS*
The list of available commands. This list should be sorted by the NAME of the commands, and each NAME should be unique in the list. Typically you do not need to manage this list yourself, and can instead use COMMAND or DEFINE-COMMAND. See COMMAND See COMMAND (type)
-
EXTERNAL SPECIAL-VARIABLE *DEFAULT-COMMAND*
The name of the default command to invoke if the command line does not have any arguments provided. By default this is "help". See COMMAND
-
EXTERNAL SPECIAL-VARIABLE *HELP-SECTIONS*
The list of help sections. This list should be sorted by the ORDER of the sections, and each NAME should be unique in the list. Typically you do not need to manage this list yourself, and can instead use HELP-SECTION or DEFINE-HELP-SECTION. By default the following sections are defined: name (only if there is a system present at all) synopsis description (only if the system has a long-description) commands environment variables authors (only if the system has at least one author or maintainer) reporting bugs (only if there is a command named "bugs" or if the system has a bug-tracker) copyright (only if there is a command named "copyright" or if the system has a license) see also (only if the system has a homepage) Some of those sections only show up if DEPLOY is run using an ASDF system, and that system has specific metadata set. See HELP-SECTION See HELP-SECTION (type) -
EXTERNAL CLASS COMMAND
Representation of a command line command. An instance of this class holds the necessary information to execute the command and inspect its own argument structure. See NAME See ALIASES See HELP See ARGS See FUNC See DESCRIBE-COMMAND See INVOKE-COMMAND See DEFINE-COMMAND See DEFINE-CLASS-COMMAND
-
EXTERNAL CLASS HELP
Command that handles the display of the default help screen. If invoked with no argument will output a manpages-style screen of available commands, options, and other help information according to the defined help sections. If invoked with an argument, will try to find a command of that name and describe it. See COMMAND See DESCRIBE-COMMAND See COMMAND (type) See HELP-SECTION (type) See *HELP-SECTIONS*
-
EXTERNAL CLASS HELP-SECTION
Representation of a help section in the help command. See HELP-SECTION See NAME See HELP See TEST See ORDER See FUNC See DEFINE-HELP-SECTION See HELP (type)
-
EXTERNAL FUNCTION COMMAND
- NAME
- &OPTIONAL
- ERRORP
Access a command by name. If ERRORP is true and there is no command by the given name, an error is signalled. Otherwise if the command does not exist NIL is returned. When setting this place, setting to NIL will remove any command of that name, and otherwise it will update the associated command instance. Do note that no check for conflicting names is made within the commands' aliases. See COMMAND (type) See *COMMANDS* See NAME See ALIASES
-
EXTERNAL FUNCTION (SETF COMMAND)
- COMMAND
- NAME
No documentation provided. -
EXTERNAL FUNCTION HELP-SECTION
- NAME
- &OPTIONAL
- ERRORP
Access a help section by name. If ERRORP is true and there is no section by the given name, an error is signalled. Otherwise if the section does not exist NIL is returned. When setting this place, setting to NIL will remove any section of that name, and otherwise it will update the associated section instance. See HELP-SECTION (type) See *HELP-SECTIONS* See NAME
-
EXTERNAL FUNCTION (SETF HELP-SECTION)
- VALUE
- NAME
No documentation provided. -
EXTERNAL FUNCTION TOPLEVEL
- &OPTIONAL
- ARGS
- QUIT
Handles the command logic. Useful as an entry function. Calls INVOKE-COMMAND on the arguments, using the *DEFAULT-COMMAND* if the argument list is empty. Also sets up an error handler and handles the correct exit code if QUIT is true. See INVOKE-COMMAND See *DEFAULT-COMMAND*
-
EXTERNAL GENERIC-FUNCTION ALIASES
- OBJECT
Accesses the list of aliases for the command. Aliases provide alternative names for the command, which can be useful to provide short forms or common synonyms. See COMMAND (type) See NAME
-
EXTERNAL GENERIC-FUNCTION (SETF ALIASES)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION ARGS
- OBJECT
Accesses the argument list descriptor for the command. This descriptor is a plist of the following keys: :REQUIRED --- List of required arguments. Each argument must be of the form NAME | (NAME [TYPE [HELP]]) :OPTIONAL --- List of optional arguments. Each argument must be of the form NAME | (NAME DEFAULT [TYPE [HELP]]) :KEY --- List of keyword arguments. Each argument must be of the form NAME | (NAME/S DEFAULT [TYPE [HELP]] where NAME/S must be NAME | (VAR NAME...) :REST --- Rest argument, if used. Must be of the form NAME | (NAME [TYPE [HELP]]) See DEFINE-COMMAND See COMMAND (type) -
EXTERNAL GENERIC-FUNCTION (SETF ARGS)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION DESCRIBE-COMMAND
- COMMAND
- STREAM
- &KEY
- INCLUDE-HELP
- &ALLOW-OTHER-KEYS
Describe the given command and output the description to the stream. Prints a one-line command options summary by default. If INCLUDE-HELP is true however, it prints both the one-line summary, the command's help, and detailed type and help information for each argument. See COMMAND (type)
-
EXTERNAL GENERIC-FUNCTION FUNC
- OBJECT
Accesses the function that is invoked when the command is run. The lambda-list of the function should follow the specification from ARGS. You should not try to read this for commands you did not specify yourself, as other commands may instead override INVOKE-COMMAND to implement their execution functionality. See ARGS See INVOKE-COMMAND See DEFINE-COMMAND See COMMAND (type)
-
EXTERNAL GENERIC-FUNCTION (SETF FUNC)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION HELP
- OBJECT
Accesses the help for the object. May be either a function of one argument (the stream to output to) or a string. See COMMAND (type) See HELP-SECTION (type)
-
EXTERNAL GENERIC-FUNCTION (SETF HELP)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION INVOKE-COMMAND
- COMMAND
- &REST
- ARGS
Invoke the command with the given argument list. Typically first calls PARSE-COMMAND-ARGS and then invokes the command's FUNC with the parsed list. You may add additional methods to perform more controlled invocation logic. See COMMAND (type) See FUNC See PARSE-COMMAND-ARGS
-
EXTERNAL GENERIC-FUNCTION NAME
- OBJECT
The name of the object. The object can be invoked via this name, which is a case-insensitive string designator. See ALIASES See COMMAND (type) See HELP-SECTION (type)
-
EXTERNAL GENERIC-FUNCTION (SETF NAME)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION ORDER
- OBJECT
Accesses the ordering number of the section. The smaller the number is the earlier the section should appear in the help output. See HELP-SECTION (type)
-
EXTERNAL GENERIC-FUNCTION (SETF ORDER)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION PARSE-COMMAND-ARGS
- COMMAND
- ARGS
Parses the command line arguments from ARGS as appropriate for COMMAND. ARGS should be a list of strings to parse into a set of arguments to the function described by COMMAND. Returns the list of arguments with which to invoke the command. By default this implements a Unix-style command line argument syntax as follows: the order of arguments for required, optional, and rest arguments must be the same as specified in the command's args. However, all of those can be interspersed with key arguments. Keyword arguments also follow "standard" Unix command line syntax, with long keys requiring two dashes (--foo) and single-character keys requiring a single dash (-f). In the single dash case multiple keys can be specified together (-fbz). If a key's value has the type BOOLEAN it is treated as a flag and when present in the arguments, the value of the key argument is the inverse of its default. Otherwise the key expects another argument immediately after, which is treated as the key's value (--foo value). If your command requires specialised parsing logic, you may add methods to perform this logic. See COMMAND (type) See ARGS See PARSE-COMMAND-LINE-TYPE
-
EXTERNAL GENERIC-FUNCTION PARSE-COMMAND-LINE-TYPE
- VALUE
- TYPE
Parses a command line type from its string representation. You may define additional methods to parse additional types. The following types are handled by default: NIL / T / STRING BOOLEAN PATHNAME INTEGER KEYWORD SYMBOL See PARSE-COMMAND-ARGS
-
EXTERNAL GENERIC-FUNCTION TEST
- OBJECT
Accesses the test function for the help section. This function is called when trying to decide whether to display a help section or not. The function is called with no arguments and should return a boolean. See HELP-SECTION (type)
-
EXTERNAL GENERIC-FUNCTION (SETF TEST)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL MACRO DEFINE-CLASS-COMMAND
- NAME
- ARGS
- &BODY
- BODY
Define a new command with its own subclass. This is the same as DEFINE-COMMAND except: 1. A new class of NAME (or :CLASS in the body options) is created. 2. The class has superclass COMMAND (or :SUPERCLASS in the body options). 3. A method specialised on this new class is added to INVOKE-COMMAND to handle the command invocation and execution body. 4. If the body option :METHOD is provided, an extra method on the generic function of that name is created using the BODY forms. This is especially useful to allow subclassing and overriding parts of the behaviour of the command, or to further customise argument parsing logic. See COMMAND (type) See INVOKE-COMMAND See DEFINE-COMMAND -
EXTERNAL MACRO DEFINE-COMMAND
- NAME
- ARGS
- &BODY
- BODY
Define a new command. The ARGS should be a lambda-list with special syntax for each variable in the lambda-list (see ARGS) to provide the extra metadata. The BODY should be the forms to be evaluated when the command is invoked along with the following body options: :HELP --- The help to output when describing the command. Can either be a string or a function of one argument. :ALIASES --- A list of alias names for the command. :CLASS --- The name of the class to create an instance of to represent the command. Any other body option will be ignored and cause a warning to be signalled. See COMMAND (type) See COMMAND See ARGS See HELP See ALIASES See NAME See DEFINE-CLASS-COMMAND -
EXTERNAL MACRO DEFINE-HELP-SECTION
- NAME
- &OPTIONAL
- STREAM
- &BODY
- BODY
Define a new help section with the given name. The BODY should be the forms to be evaluated when the help section is output, along with the following body options: :TEST --- A form that should evaluate to a boolean. Decides whether to show the section or not. :ORDER --- The ordering number of this section. :CLASS --- The name of the class to create an instance of to represent the section. Any other body option will be ignored and cause a warning to be signalled. Within BODY, a function named F is available, which accepts a format string and arguments, to quickly output to the stream. When a help section is output, it is usually done so within a WITH-HELP-SECTION environment, using the section's name. See HELP-SECTION See HELP-SECTION (type) See NAME See TEST See ORDER See FUNC See WITH-HELP-SECTION -
EXTERNAL MACRO WITH-HELP-SECTION
- STREAM
- SECTION
- &OPTIONAL
- LEVEL
- TOP
- &BODY
- BODY
Handles setup of a help section. STREAM should be a variable holding the stream that is being output to. SECTION should be the name of the section to start. LEVEL should be the level of indentation to advance by for the body. Each indentation level corresponds to two spaces. TOP should be set to true if the current section is at the toplevel, in which case the inner body receives an additional space of indentation. The stream is rebound as a wrapping stream, which properly enforces line wrapping of the text output to the stream within the body. See DEFINE-HELP-SECTION See ORG.SHIRAKUMO.TEXT-DRAW:WRAPPED-STREAM
-