Command contributions to a composite tool.
An addon contributes named subcommands to a host tool, so
analysis command="lint ..." reaches the contributing addon's handler.
Each contribution records the contributing addon so shutdown can retract
everything that addon added.
Shape: {tool-name {command-name {:handler fn :params {} :description str :addon addon-id}}}
Command contributions to a composite tool.
An addon contributes named subcommands to a host tool, so
`analysis command="lint ..."` reaches the contributing addon's handler.
Each contribution records the contributing addon so shutdown can retract
everything that addon added.
Shape: {tool-name {command-name {:handler fn :params {} :description str
:addon addon-id}}}Tools whose branches are off on this thread: a re-entry into the host's own verb.
Tools whose branches are off on this thread: a re-entry into the host's own verb.
(add-listener! listener-id f)Register f, called with a contribution event after every mutation here.
This seam exists because the STORE alone is not the whole concept. A host advertises a tool surface built from these contributions, and a contribution that arrives AFTER that surface was built has to tell it so. While only the host had listeners, an addon that migrated to this registry kept working at boot (the surface is assembled later anyway) and silently failed for any post-boot contribution, which is the worst shape of failure: correct on the path everyone tests, wrong on the path nobody does.
Idempotent by id: re-registering an id replaces its fn rather than stacking.
f MUST NOT THROW. This namespace is in the portable three-host stratum and
carries no reader conditionals, so it cannot catch a platform exception class
on the caller's behalf. A listener that can fail wraps itself; a JVM host
registers an already-guarded fn. A throwing listener will propagate out of
the contribute!/retract! that triggered it.
Register `f`, called with a contribution event after every mutation here. This seam exists because the STORE alone is not the whole concept. A host advertises a tool surface built from these contributions, and a contribution that arrives AFTER that surface was built has to tell it so. While only the host had listeners, an addon that migrated to this registry kept working at boot (the surface is assembled later anyway) and silently failed for any post-boot contribution, which is the worst shape of failure: correct on the path everyone tests, wrong on the path nobody does. Idempotent by id: re-registering an id replaces its fn rather than stacking. `f` MUST NOT THROW. This namespace is in the portable three-host stratum and carries no reader conditionals, so it cannot catch a platform exception class on the caller's behalf. A listener that can fail wraps itself; a JVM host registers an already-guarded fn. A throwing listener will propagate out of the contribute!/retract! that triggered it.
(around! tool path {:keys [wrap owner] :as spec})Wrap PATH of TOOL, and everything below it, in SPEC's :wrap, (fn [next] handler);
an empty path wraps the whole tool. Several owners may wrap one path; lowest :order
runs outermost; the same owner replaces. Refused over a protect!ed path.
Returns {:ok? true ...} or {:ok? false :reason kw :message s}.
Wrap PATH of TOOL, and everything below it, in SPEC's :wrap, (fn [next] handler);
an empty path wraps the whole tool. Several owners may wrap one path; lowest :order
runs outermost; the same owner replaces. Refused over a `protect!`ed path.
Returns {:ok? true ...} or {:ok? false :reason kw :message s}.(branch-refusals tool)The branches of TOOL that did not route at its latest composition.
The branches of TOOL that did not route at its latest composition.
(branches-of tool)Every branch registered on TOOL.
Every branch registered on TOOL.
(clear!)Remove every contribution. Returns nil.
Remove every contribution. Returns nil.
(clear-branches!)Drop every branch, refusal, protection and the host. For tests.
Drop every branch, refusal, protection and the host. For tests.
(composed? tool)Has anything read TOOL's composed commands since forget-composition!? A tool that
took a call and did not never reads this store, and no branch can reach it.
Has anything read TOOL's composed commands since `forget-composition!`? A tool that took a call and did not never reads this store, and no branch can reach it.
(contribute! tool-name addon-id commands)Merge COMMANDS into TOOL-NAME's command tree on behalf of ADDON-ID. Notifies listeners afterwards. Returns the contributed command names.
Merge COMMANDS into TOOL-NAME's command tree on behalf of ADDON-ID. Notifies listeners afterwards. Returns the contributed command names.
(contribute-from! tool-name addon-id contribution-sym resolve-fn)Like contribute!, but the command map is the value of the var named by CONTRIBUTION-SYM, read through RESOLVE-FN (sym -> value, or nil). The name is remembered, so refresh-namespaces! can re-read it after that namespace is reloaded in place: handlers in the map then close over the NEW vars. Returns the contributed command names, or nil when the symbol does not resolve (nothing is contributed).
Like contribute!, but the command map is the value of the var named by CONTRIBUTION-SYM, read through RESOLVE-FN (sym -> value, or nil). The name is remembered, so refresh-namespaces! can re-read it after that namespace is reloaded in place: handlers in the map then close over the NEW vars. Returns the contributed command names, or nil when the symbol does not resolve (nothing is contributed).
(contributed-tool-names)Every tool name carrying contributions or branches.
Every tool name carrying contributions or branches.
(drop-owner-branches! owner)Drop every branch OWNER registered. Returns the tools it touched.
Drop every branch OWNER registered. Returns the tools it touched.
(forget-composition! tool)Forget that TOOL composed its branches, so composed? answers for the next read.
Forget that TOOL composed its branches, so `composed?` answers for the next read.
(get-commands tool-name)The contributed command tree for TOOL-NAME with its runtime branches composed in,
or nil. Raw inside *bypass*. Composed per read, so a branch survives a remount of
the addon it extends and a reload of either side is seen by the next read.
The contributed command tree for TOOL-NAME with its runtime branches composed in, or nil. Raw inside `*bypass*`. Composed per read, so a branch survives a remount of the addon it extends and a reload of either side is seen by the next read.
(graft! tool path {:keys [handler owner] :as spec})Route PATH of TOOL to SPEC's :handler, a handler or verb map, for its :owner.
Refused, with nothing written, for an empty path, an uninvocable handler, a blank
owner, or a leaf another owner grafted. The same owner replaces. A route that
exists is judged per composition: branch-refusals names it.
Returns {:ok? true ...} or {:ok? false :reason kw :message s}.
Route PATH of TOOL to SPEC's :handler, a handler or verb map, for its :owner.
Refused, with nothing written, for an empty path, an uninvocable handler, a blank
owner, or a leaf another owner grafted. The same owner replaces. A route that
exists is judged per composition: `branch-refusals` names it.
Returns {:ok? true ...} or {:ok? false :reason kw :message s}.(listener-ids)Every registered listener id.
Every registered listener id.
(protect! tool path)Refuse any around over PATH of TOOL, or over a path containing it, so the verb that removes a broken around stays reachable.
Refuse any around over PATH of TOOL, or over a path containing it, so the verb that removes a broken around stays reachable.
(prune! tool path owner)Withdraw OWNER's branches at exactly PATH of TOOL. Returns how many went.
Withdraw OWNER's branches at exactly PATH of TOOL. Returns how many went.
(refresh-namespaces! ns-strs resolve-fn)Re-run every contribute-from! whose contribution symbol lives in one of NS-STRS (reloaded namespace names) and that is still contributed. Each is retracted and contributed again from (RESOLVE-FN sym), keeping its addon attribution, so listeners see the change. Returns {tool-name [command ...]} of what was refreshed; {} when nothing applies.
Re-run every contribute-from! whose contribution symbol lives in one of
NS-STRS (reloaded namespace names) and that is still contributed. Each is
retracted and contributed again from (RESOLVE-FN sym), keeping its addon
attribution, so listeners see the change. Returns {tool-name [command ...]}
of what was refreshed; {} when nothing applies.(remove-listener! listener-id)Drop a listener. Returns the id. Safe when absent.
Drop a listener. Returns the id. Safe when absent.
(retract! tool-name addon-id)Remove every command ADDON-ID contributed to TOOL-NAME. Notifies listeners afterwards. Returns nil.
Remove every command ADDON-ID contributed to TOOL-NAME. Notifies listeners afterwards. Returns nil.
(retract-all! addon-id)Remove every command ADDON-ID contributed to any tool, and every runtime branch it registered. Notifies listeners once per tool the addon had actually touched. Returns nil.
The touched set is read BEFORE the retraction, or there is nothing left to attribute the notifications to.
Remove every command ADDON-ID contributed to any tool, and every runtime branch it registered. Notifies listeners once per tool the addon had actually touched. Returns nil. The touched set is read BEFORE the retraction, or there is nothing left to attribute the notifications to.
(set-branch-host! host)Tell the store how to reach a tool from outside: a map of
:tool-handler (fn [tool]) -> its handler,
:routes (fn [tool]) -> the command strings it routes, called inside *bypass*,
:guard (fn [branch tool f]) -> f as dispatched.
Without one, a branch can only touch a root an addon contributed.
Tell the store how to reach a tool from outside: a map of :tool-handler (fn [tool]) -> its handler, :routes (fn [tool]) -> the command strings it routes, called inside `*bypass*`, :guard (fn [branch tool f]) -> f as dispatched. Without one, a branch can only touch a root an addon contributed.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |