Skip to content

Commit

Permalink
Add parse-cmd-dsl
Browse files Browse the repository at this point in the history
  • Loading branch information
ruricolist committed Oct 27, 2024
1 parent 059b36c commit 0e505da
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ Arguments are handled as follows:
expecting a file – use `psub-echo` or `psub-format`, which don’t
actually call an external program.)

### Parsing the `cmd` DSL

You can use the `cmd` DSL in your own programs with `cmd:parse-cmd-dsl`. This takes a list of arguments and returns two values: a fully-tokenized list of command arguments and a list of keyword arguments, both suitable for passsing to `uiop:launch-program`.

``` lisp
(parse-cmd-dsl '("echo 'hello world' > myfile"))
=> ("echo" "hello world"), (:OUTPUT "myfile")
```

## The external program’s working directory

Cmd is designed with multi-threaded programs in mind. It always runs
Expand Down
13 changes: 13 additions & 0 deletions cmd.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
(:export
:cmd :$cmd :cmd? :cmd! :cmd&
:sh :$sh :sh? :sh! :sh&
:parse-cmd-dsl
:with-cmd-dir
:with-working-directory
:current-directory
Expand Down Expand Up @@ -555,6 +556,18 @@ Except that it doesn't actually launch an external program."
(receive (argv kwargs) (argv+kwargs args)
(make 'cmd :argv argv :kwargs kwargs)))

(defun parse-cmd-dsl (command)
"Parse COMMAND like `cmd' does.
Returns two values: the fully tokenized command, and a list of
redirection arguments (in the format expected by
`uiop:launch-program').
This can be used to write your own functions that support the `cmd' DSL."
(check-type command list)
(let ((cmd (parse-cmd command)))
(values (flatten-string-tokens (cmd-argv cmd))
(flatten-string-tokens (cmd-kwargs cmd)))))

(defun split-pipeline (args)
"Split ARGS into two values: the last command in the pipeline, and any previous commands."
(let* ((args (parse-cmd-args args))
Expand Down
22 changes: 15 additions & 7 deletions test.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
(:use :cl :cmd/cmd :fiveam :alexandria :serapeum)
;; Internal symbols.
(:import-from
:cmd/cmd
:expand-keyword-aliases
:split-cmd
:flatten-string-tokens
:kill-process-group
:wrap-cmd-env
:vterm-terminal)
:cmd/cmd
:parse-cmd-dsl
:expand-keyword-aliases
:flatten-string-tokens
:kill-process-group
:split-cmd
:vterm-terminal
:wrap-cmd-env)
(:import-from :uiop :os-unix-p :subprocess-error)
(:export :run-tests))
(in-package :cmd/test)
Expand Down Expand Up @@ -239,3 +240,10 @@
(is (string= "a file" ($cmd "ls" #p"foo bar")))
(locally (declare (notinline $cmd))
(is (string= "a file" ($cmd "ls" #p"foo bar"))))))

(test parse-cmd-dsl
(is (equal
(multiple-value-list
(parse-cmd-dsl '("echo 'hello world' > myfile")))
'(("echo" "hello world")
(:output "myfile")))))

0 comments on commit 0e505da

Please sign in to comment.