Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
* :tool-options-handler - callback function for handling extra tool options
* :transformer provides a function to add additional commands and groups after namespaces are loaded
* :source-dirs specifies extra directories to consider when caching
* :pre-dispatch - callback function invoked before dispatch
* :pre-invoke - callback function invoked before the dispatched command function is invoked
* Can now handle "messy" case where a command has the same name as a group
* Cache files are now stored in `~/.cache/net.lewisship.cli-tools` by default
* Added initial support for commands defined as Babashka CLI functions
Expand Down
16 changes: 16 additions & 0 deletions doc/dispatch.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,19 @@ If :doc is omitted, then `dispatch` will search the group's namespaces, and use
it finds.

If :title is omitted, then the first line of the docstring, up to the first `.`, will be used as the title.

## Callbacks

Certain options define callbacks that will be invoked during dispatch. These are optional.

Any return value from the callbacks is ignored.

The :pre-dispatch callback is invoked once all command data has been assembled (possibly, by loading from cache).
It is passed the full dispatch options.

After :pre-dispatch, `dispatch` will start to consume command line arguments to identify the specific command function
to invoke.

The :pre-invoke callback is invoked once a specific command function is identified.
The callback is invoked immediately before the command function is invoked; it is passed the
command map, and a seq of remaining arguments (that will be passed to the command function).
4 changes: 2 additions & 2 deletions src/net/lewisship/cli_tools.clj
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
(merge {:tool-name tool-name'
:cache-digest digest
:command-root command-root}
(select-keys options [:doc :arguments :tool-summary :pre-dispatch]))))
(select-keys options [:doc :arguments :tool-summary :pre-dispatch :pre-invoke]))))

(defn- dispatch*
"Called (indirectly/anonymously) from a tool handler to process remaining command line arguments."
Expand Down Expand Up @@ -258,7 +258,7 @@
(as identified by the first command line argument) and processes CLI options and arguments.

dispatch-options:

- :tool-name (optional, string) - used in command summary and errors
- :doc (optional, string) - used in help summary
- :arguments - command line arguments to parse (defaults to `*command-line-args*`)
Expand Down
4 changes: 3 additions & 1 deletion src/net/lewisship/cli_tools/impl.clj
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@
help-suffix)))

(defn dispatch
[{:keys [command-root arguments tool-name] :as options}]
[{:keys [command-root arguments tool-name pre-invoke] :as options}]
(binding [*tool-options* options]
(let [command-name (first arguments)]
(if (or (nil? command-name)
Expand Down Expand Up @@ -933,6 +933,8 @@

(:fn matched-command)
(let [invoke-command #(binding [*command-map* matched-command]
(when pre-invoke
(pre-invoke matched-command remaining-args))
(apply (-> matched-command :fn requiring-resolve) remaining-args))]
;; It's a command, but has :subs, so it's also a group (this is the "messy" scenario)
(if (-> matched-command :subs seq)
Expand Down
8 changes: 7 additions & 1 deletion src/net/lewisship/cli_tools/specs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
::tool-options-handler
::extra-tool-options
::source-dirs
::cache-dir]))
::cache-dir
::pre-dispatch
::pre-invoke]))

(s/def ::non-blank-string (s/and string?
#(not (str/blank? %))))
Expand All @@ -39,6 +41,10 @@

(s/def ::tool-options-handler fn?)

(s/def ::pre-dispatch fn?)

(s/def ::pre-invoke fn?)

(s/def ::source-dirs (s/coll-of string?))

;; dispatch doesn't return
Expand Down
14 changes: 14 additions & 0 deletions test/net/lewisship/cli_tools_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,20 @@
:namespaces '[net.lewisship.cli-tools.colors]
:arguments ["-h"]}))))

(deftest pre-invoke-callback
(let [*args (atom nil)
callback (fn [command-map remaining-args]
(reset! *args [command-map remaining-args]))]
(is (match? {:status 0}
(dispatch {:tool-name "callback"
:pre-invoke callback
:namespaces '[net.lewisship.cli-tools.colors]
:arguments ["colors" "-h"]})))

(is (match? [{:command-path ["colors"]}
["-h"]]
@*args))))

(defcommand set-mode
"Sets the execution mode"
[mode ["-m" "--mode MODE" (str "Execution mode, one of " mode-names)
Expand Down