Parse
This is the frontend @cast and @main of Comonicon.
The @main command will use generate the following functions in the module:
- the entry function for CLI command_main.
- comonicon_install: for command build and installation.
- comonicon_install_path: for path build and installation.
- julia_main: for building standalone applications.
And a registry constant CASTED_COMMANDS in the module, one can find the original Comonicon AST by indexing CASTED_COMMANDS by your command name.
References
Comonicon.Comonicon — ModuleAll the terminals are under my command. Comonicon is a CLI (Command Line Interface) generator that features light-weight dependency (optional to have zero dependency), fast start-up time and easy to use. See the website for more info.
Comonicon.CommandError — Typestruct CommandError <: CommandExceptionException type for general CLI compatible errors thrown by cmd_error.
Comonicon.CommandException — TypeCommandException <: ExceptionAbstract type for command exceptions. All command exceptions should contain an exitcode field.
Comonicon.CommandExit — Typestruct CommandExit <: CommandExceptionException type for cmd_exit.
Comonicon.cmd_error — Functioncmd_error(msg::String, code::Int = 1)Throw a CommandError with message msg and return code code. This is preferred as exception handle when writing a CLI compatible Julia program.
When the program is running in normal Julia execution the error will print as normal Julia exception with stacktrace.
When the progrm is running from a CLI entry, the exception is printed as standard CLI exceptions with exit code (default is 1). Then the corresponding help message is printed.
Comonicon.cmd_exit — Functioncmd_exit(code::Int = 0)Exit the CLI program with code. This method is preferred over exit to make sure the program won't exit directly without handling the exception.
Comonicon.default_name — Methoddefault_name(x::String)Return the lowercase of a given package name. It will ignore the suffix if it ends with ".jl".
Comonicon.get_version — Methodget_version(m::Module)Get the version of a given module. It will try to find the version of Project.toml if the given module is a project module. If fails, it returns v"0.0.0".
Comonicon.parse_kwargs — Methodparse_kwargs(fn::JLFunction) -> flags, optionsParse the keyword arguments of function expression fn into intermediate Julia CLI objects JLFlag and JLOption.
Comonicon.rm_format — Functionrm_format(md)Remove Markdown DOM and flatten to strings.
Comonicon.set_cmd! — Functionset_cmd!(cmds::Dict, cmd)register cmd in the command registry cmds, which usually is a constant CASTED_COMMANDS under given module.
Comonicon.write_cmd — Methodwrite_cmd(filename, cmd::Entry)Write a command to filename.
Comonicon.@cast — Macro@cast <function definition>
@cast <module definition>Denote a Julia expression is a command. If the expression is a function definition, it will be parsed as a leaf command, if the expression is a module definition or module name, it will be parsed as a node command. This macro must be used with @main to create a multi-command CLI.
Quick Example
# in a script or module
"""
sum two numbers.
# Args
- `x`: first number
- `y`: second number
# Options
- `-p, --precision=<type>`: precision of the calculation.
# Flags
- `-f, --fastmath`: enable fastmath.
"""
@cast function sum(x, y; precision::String="float32", fastmath::Bool=false)
    # implementation
    return
end
"product two numbers"
@cast function prod(x, y)
    return
end
@mainComonicon.@lazyload — Macro@lazyload expr @cast <valid castable expr>Evaluate expr if command f is called. This is useful for reducing the latency of scripts that has subcmds depend on plotting, serialization etc.
Please see @cast for valid expression specifications.
This macro only works at top-level command and thus can only be used in Main and only works in scripts. Using this macro in any other module or a project module will not work.
Comonicon.@main — Macro@main
@main <function definition>Main entry of the CLI application.
Quick Example
# in a script or module
"""
sum two numbers.
# Args
- `x`: first number
- `y`: second number
# Options
- `-p, --precision=<type>`: precision of the calculation.
# Flags
- `-f, --fastmath`: enable fastmath.
"""
@main function sum(x, y; precision::String="float32", fastmath::Bool=false)
    # implementation
    return
endCLI Definitions and Julia Syntax Mapping
positional arguments normal inputs, these are mapped as Julia function arguments, e.g
sum 1 2sum is the command, and 1, 2 are positional arguments.
options arguments with syntax --<name>=<value> or --<name> <value>, these are mapped as Julia keyword arguments, e.g
sum --precision=float32 1 2--precision is the option of command sum and has value float32.
short options arguments with syntax -<letter>=<value> or -<letter><value> or --<letter> <value>, the letter is usually the first character of a normal option, e.g
sum -pfloat32 1 2-p is the same as --precision, but in short hand, this is enabled by writing corresponding docstring (see the next section on docstring syntax).
flags like options, but without any value, e.g --<name>, this is mapped to a special type of keyword argument that is of type Bool and has default value false, e.g
sum --fastmathshort flags flags with syntax -<letter>, the letter should be the first character of the corresponding normal flag, e.g
sum -fDoc String Syntax
Each different kind of inputs must have a different level-1 section (markdown syntax #<section name>).
The docstring must have section name:
- #Argsor- #Argumentsto declare the documentation of positional arguments.
- #Optionsto declare the documentation of options.
- #Flagsto declare the documentation of flags.
Examples
The simplest usage is creating the following commands
"""
an example command
# Args
- `x`: first argument
- `y`: second argument
- `z`: last argument
# Flags
- `-f, --flag`: a flag, optionally can be a short flag.
# Options
- `-o, --option=<int>`: an option, optionally can be short option.
"""
@cast function mycommand(x, y, z; flag::Bool=false, option::Int=2)
    # some implementation
    return
end
@cast function myothercommand(xs...)
    # another command with variatic arguments
    return
end
"""
My main command.
"""
@main # declare the entrythis can be used in command line as mycommand 1 2 3 --flag, you can also just type -h to check the detailed help info.
The command line documentation will be generated automatically from your Julia docstring.
If you have deeper hierachy of commands, you can also put @cast on a Julia module.
using Comonicon
@cast module NodeCommand
using Comonicon
@cast module NodeSubCommand
using Comonicon
@cast bar(x) = println("bar $x")
end
@cast foo(x) = println("foo $x")
@main
end
NodeCommand.command_main()