On this page:
12.1 Command Line Flags
cli-flag
cli-flag-state
all-flags
find-cli-flag
make-cli-flag-table
cli-flag-strings
shortest-cli-flag
format-cli-flags
call-with-bound-cli-flags
12.2 Command Line Utilities
12.2.1 CLI Value Types
exit-code/  c
exit-handler/  c
bound-program/  c
arguments/  c
argument-parser/  c
program-log/  c
12.2.2 CLI Flow Control
run-entry-point!
cli
12.2.3 CLI Messages
$cli
$cli:  undefined-command
$cli:  show-help
12.3 Command Line Argument Parsers
top-level-cli
do-command
gc-command
show-command
fetch-command
mkinput-command
8.0

12 Command Line Interface

Xiden’s command line interface emphasizes full control over the runtime configuration at the cost of short commands. All commands generate exact program definitions, such that unit tests can verify the full behavior of a Xiden process.

This API is private, and may change. To understand this section, you must understand parse-command-line.

12.1 Command Line Flags

 (require xiden/cli-flag) package: xiden

When parsing command line flags, Xiden does not store user-defined values as a side effect. Instead, it defers binding values from a command line to settings. Once a process is ready to determine a runtime configuration, it binds values from a command line using call-with-bound-cli-flags.

In addition to the below, xiden/cli-flag provides many identifiers bound to element of all-flags.

struct

(struct cli-flag (setting
    kind
    additional-flag-strings
    arity
    convert
    help-strings)
    #:transparent)
  setting : setting?
  kind : (or/c 'once-each 'once-any 'multi)
  additional-flag-strings : (listof string?)
  arity : exact-nonnegative-integer?
  convert : procedure?
  help-strings : (listof string?)
Represents a command line flag.

An instance of this structure corresponds to a suitable flag table entry in parse-command-line. The value of kind has the same meaning as it does in parse-command-line.

An instance is used to generate deferred bindings for setting, such that the strings passed in the command line are turned into a Racket values for the setting using convert.

Each instance of cli-flag implicitly carries a longform flag equal to (format "--~a" (setting-id setting)). additional-flag-strings holds acceptable flags recognized by an instance.

convert and help-strings are related in the same way as they are in a program using parse-command-line (see example below). However, arity describes the number of formals accepted by convert minus the flag argument. Therefore it must be the case that (equal? (procedure-arity convert) (add1 arity)).

The below example shows a setting that holds a list of lists, where each sublist holds three numbers. The following cli-flag instance describes the corresponding command line flag and the conversion from user-provided strings to a valid value for the setting.

(define-setting TRIPLET_LIST
  (listof (list/c real? real? real?))
  null)
 
 
(define --triplet
  (cli-flag TRIPLET_LIST
            'multi
            '("-t" "--triplet")
            3
            (λ (flag a b c)
              (cons (list (string->number a)
                          (string->number b)
                          (string->number c))
                    (TRIPLET_LIST)))
            '("number" "number" "number")))

struct

(struct cli-flag-state (flag-string flag-definition bind)
    #:transparent)
  flag-string : string?
  flag-definition : cli-flag?
  bind : (-> (-> any) any)
Represents a deferred binding for a setting using flag-definition.

flag-string is bound to the exact flag used by the user. bind applies a given thunk such that the setting in flag-definition is bound to a user-defined value in the extent of said thunk.

A particular use of --triplet from the earlier example could generate this state.

; Generated from -t 9 7 22 -t 10 0 0 -t 2 4 5
(cli-flag-state "-t" --triplet
                (lambda (proc)
                  (TRIPLET_LIST '((2 4 5) (10 0 0) (9 7 22))
                  proc)))

A list of all built-in flags.

procedure

(find-cli-flag s)  (or/c #f cli-flag?)

  s : setting?
Returns an element of all-flags used to defer bindings to s, or #f if no such flag is defined.

procedure

(make-cli-flag-table c ...)  list?

  c : cli-flag?
Returns a list suitable for use as a flag table in parse-command-line.

procedure

(cli-flag-strings c)  (non-empty-listof string?)

  c : cli-flag?
Returns all possible command line flags that reference c, including the canonical flag derived from (cli-flag-setting c).

procedure

(shortest-cli-flag c)  string?

  c : cli-flag?
Returns the shortest element of (cli-flag-strings c).

procedure

(format-cli-flags c)  string?

  c : cli-flag?
Returns a single /-separated string that shows each element of (cli-flag-strings c) in order of shortest to longest.

procedure

(call-with-bound-cli-flags flag-states    
  continue)  any
  flag-states : (listof cli-flag-state?)
  continue : (-> any)
Applies continue in a parameterization where all settings affected by flag-states are bound to their corresponding values.

12.2 Command Line Utilities

 (require xiden/cmdline) package: xiden

xiden/cmdline provides all bindings from racket/cmdline, as well as the bindings documented in this section. Unlike xiden/cli, xiden/cmdline does not actually define a command line interface. It only helps xiden/cli do so.

12.2.1 CLI Value Types

value

exit-code/c : flat-contract? = (integer-in 0 255)

An exit code for use in an exit handler.

Xiden does not currently lean on the exit code to convey much meaning, so expect to see 1 (E_FAIL) to represent an error state. Lean on the program log for specifics.

A procedure that reacts to an exit code, like exit.

A procedure meant to run predetermined program logic in the context of a runtime configuration.

The only argument is a procedure (probably representing a continuation) that accepts an exit code and a messy log representing program output. That continuation will decide how to react to the given information.

Represents arguments provided in a command line. An argument list may be a vector or list of strings for flexibility reasons.

A procedure that parses command line arguments and plans further action.

A program log is a single message or list of messages that report exact program behavior.

12.2.2 CLI Flow Control

procedure

(run-entry-point! args    
  formatter    
  parse-args    
  on-exit)  any
  args : arguments/c
  formatter : message-formatter/c
  parse-args : argument-parser/c
  on-exit : exit-handler/c
This translates the given command-line arguments to a program to run in the relevant runtime configuration, and applies on-exit to the exit code of the process.

This module mimics production behavior.

(module+ main
  (run-entry-point! (current-command-line-arguments)
                    (get-message-formatter)
                    top-level-cli
                    exit))

procedure

(cli #:program program 
  [#:flags flags 
  #:args args 
  #:help-suffix-string-key help-suffix-string-key] 
  #:arg-help-strings arg-help-strings 
  handle-arguments) 
  
(listof cli-flag-state?) bound-program/c
  program : string?
  flags : list? = null
  args : (or/c (vector/c string?) (listof string?))
   = (current-command-line-arguments)
  help-suffix-string-key : (or/c #f symbol?) = #f
  arg-help-strings : (listof string?)
  handle-arguments : 
(->* ((listof cli-flag-state?)) () #:rest list?
(values (listof cli-flag-state?)
        bound-program/c))
cli does not actually run program logic. It only plans it in terms of command line arguments.

Applies the following expression:

(parse-command-line program argv flags handle-arguments arg-help-strings handle-help)

Note that some arguments used as-is. Others are computed towards the same ends.

argv is bound to a vector coerced from args.

handle-help is configured to generates a program that uses help-suffix-string-key to add localized contextual help. The exit code from such a program is 0 if the user actually requested help in args. 1 otherwise. The same help suffix is used in the event the user does not pass enough positional arguments for handle-arguments.

The following example shows the relationship between command line parsing, a runtime configuration based on flags, and actual program execution.

(define (say-hello . args)
  (cli #:program "hi"
       #:flags null
       #:args args
       #:arg-help-strings '("names")
       (lambda (flags . names)
         (values flags
                 (lambda (halt)
                    (halt 0
                          (for/list ([name names])
                            ($show-string (format "Hello, ~a!" name)))))))))
 
 
(define-values (flags program) (say-hello "john" "sage" "mary"))
(define message->string (get-message-formatter))
 
(call-with-bound-cli-flags flags
  (lambda ()
    (program (lambda (exit-code messages)
      (printf "Exit code: ~a~n" exit-code)
      (for ([m messages])
        (write-message m message->string))))))
12.2.3 CLI Messages

struct

(struct $cli $message ()
    #:prefab)
A message that pertains to a command line interface.

struct

(struct $cli:undefined-command $cli (command)
    #:prefab)
  command : string?
A user passed command as a subcommand, but it is not defined.

struct

(struct $cli:show-help $cli (body-string string-suffix-key)
    #:prefab)
  body-string : string?
  string-suffix-key : (or/c #f symbol?)
A message that formats as context-sensitive help. body-string is help content generated by parse-command-line. string-suffix-key is an internal value used to select a localized string to append to said help.

12.3 Command Line Argument Parsers

 (require xiden/cli) package: xiden

xiden/cli implements the command line parsers for Xiden in terms of xiden/cmdline. Each parser prepares a program that uses continuation passing style to return output and an exit code.

(submod xiden/cli main) is the entry point for the xiden and raco zcpkg commands.

value

top-level-cli : argument-parser/c

Returns a program based on the first argument, subcommand, with consideration to command line flags that apply to every possible subcommand. If subcommand is not defined, then the program halts with exit code 1 and output ($cli:undefined-command subcommand).

value

do-command : argument-parser/c

Creates a program that carries out work defined in args. In the event no work is possible, then the program will trivially halt with exit code 0 and produce no output.

Otherwise, the command will build a transaction where command-line flags add work to execute in reading order.

value

gc-command : argument-parser/c

Creates a program that collects garbage in a target workspace.

Assuming no exceptional behavior, the bound program halts with exit code 0 with output ($finished-collecting-garbage (xiden-collect-garbage)).

value

show-command : argument-parser/c

show-command creates a program with behavior based on the first argument A.

If A is "config", the program halts with exit code 0 and output ($show-datum (dump-xiden-settings)).

If A is "installed", the program halts with exit code 0 and output (list ($show-string S) ...), where S is a string formatted to show a package query, a package output and a directory path. The list represents all installed outputs in the target workspace.

If "links", the program halts with exit code 0 and output (list ($show-string L) ...), where L is a string containing a path to a symbolic link and a path to another filesystem entry referenced by that link. These symbolic links are special in that they are tracked by Xiden for garbage collection purposes.

If "workspace", the program halts with exit code 0 and output ($show-string (path->string (workspace-directory))).

In all other cases, the program halts with exit code 1 and output ($cli:undefined-command A).

value

fetch-command : argument-parser/c

Creates a program based on the first argument A.

A is treated as a string representation of a datum to evaluate using eval-untrusted-source-expression. If the result is a source and the evaluation produced no I/O (for security), then the command sents bytes produced from the source to (current-output-port). Information about the process is sent to (current-error-port).

This all happens under a runtime configuration, so transfers can be halted by settings like XIDEN_FETCH_TOTAL_SIZE_MB.

value

mkinput-command : argument-parser/c

Creates a program based that accepts any number of format arguments.

The program generates an input expression, with a sources form containing each of the arguments. The data used to compute the integrity and signature information is read from current-input-port.