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.
|(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.
#: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?)
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.
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")))
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)))
(call-with-bound-cli-flags flag-states continue) → any flag-states : (listof cli-flag-state?) continue : (-> any)
|(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.
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.
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.
= (-> arguments/c (values (listof cli-flag-state?) bound-program/c))
(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 module mimics production behavior.
(module+ main (run-entry-point! (current-command-line-arguments) (get-message-formatter) top-level-cli exit))
(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?)
(->* ((listof cli-flag-state?)) () #:rest list? (values (listof cli-flag-state?) bound-program/c))
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))))))
|(require xiden/cli)||package: xiden|
(submod xiden/cli main) is the entry point for the xiden and raco zcpkg commands.
top-level-cli : argument-parser/c
do-command : argument-parser/c
Otherwise, the command will build a transaction where command-line flags add work to execute in reading order.
gc-command : argument-parser/c
Assuming no exceptional behavior, the bound program halts with exit code 0 with output ($finished-collecting-garbage (xiden-collect-garbage)).
show-command : argument-parser/c
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.
In all other cases, the program halts with exit code 1 and output ($cli:undefined-command A).
fetch-command : argument-parser/c
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).
mkinput-command : argument-parser/c