Three global registries in one place: channels, providers, commands.
Each is a small, self-contained piece - keyword id, a spec for the descriptor map, a process-level atom holding the registered entries, and a handful of fns for register / deregister / lookup. Putting them together means one file owns every "this is the canonical shape of an extension contribution" decision and one file owns every place an extension's contribution lands at runtime.
Channel registry (:channel/id keyword):
channel build + validate a descriptor
register-channel! register, idempotent on :channel/id
deregister-channel! remove by id
registered-channels all entries, vec
channel-by-id lookup by id
by-cmd lookup by :channel/cmd
Provider registry (:provider/id keyword):
provider build + validate a descriptor
register-provider! register, idempotent on :provider/id
deregister-provider! remove by id
registered-providers all entries, vec
provider-by-id lookup by id
Command registry ([:cmd/parent :cmd/name] tuple key):
command build + validate a descriptor
resolve-subcommands static vec or dynamic 0-arg fn -> vec
register-cmd! register, idempotent on [parent name]
deregister-cmd! remove by [parent name]
registered-commands all entries, vec (registration order)
registered-under filter by parent path
Channel mounting:
channel-subcommands compose vis channels subcommand vec
from the channel registry + any commands
registered with :cmd/parent ["channels"].
Loading this ns also registers the
vis channels parent itself.
Specs for keyword fields (:channel/id, :provider/id, :cmd/name,
..., plus the descriptor specs ::channel, ::provider, ::command,
::arg) live here too - the spec IS the registry's contract.
Parsing / help rendering / dispatch utilities live in
com.blockether.vis.internal.commandline. Classpath manifest
scanning lives in com.blockether.vis.internal.manifest; the
extension layer that wraps it (and re-exports discover-extensions!)
lives in com.blockether.vis.internal.extension.
Three global registries in one place: channels, providers, commands.
Each is a small, self-contained piece - keyword id, a spec for the
descriptor map, a process-level atom holding the registered entries,
and a handful of fns for register / deregister / lookup. Putting
them together means one file owns every "this is the canonical
shape of an extension contribution" decision and one file owns
every place an extension's contribution lands at runtime.
Channel registry (`:channel/id` keyword):
channel build + validate a descriptor
register-channel! register, idempotent on :channel/id
deregister-channel! remove by id
registered-channels all entries, vec
channel-by-id lookup by id
by-cmd lookup by :channel/cmd
Provider registry (`:provider/id` keyword):
provider build + validate a descriptor
register-provider! register, idempotent on :provider/id
deregister-provider! remove by id
registered-providers all entries, vec
provider-by-id lookup by id
Command registry (`[:cmd/parent :cmd/name]` tuple key):
command build + validate a descriptor
resolve-subcommands static vec or dynamic 0-arg fn -> vec
register-cmd! register, idempotent on [parent name]
deregister-cmd! remove by [parent name]
registered-commands all entries, vec (registration order)
registered-under filter by parent path
Channel mounting:
channel-subcommands compose `vis channels` subcommand vec
from the channel registry + any commands
registered with `:cmd/parent ["channels"]`.
Loading this ns also registers the
`vis channels` parent itself.
Specs for keyword fields (`:channel/id`, `:provider/id`, `:cmd/name`,
..., plus the descriptor specs `::channel`, `::provider`, `::command`,
`::arg`) live here too - the spec IS the registry's contract.
Parsing / help rendering / dispatch utilities live in
`com.blockether.vis.internal.commandline`. Classpath manifest
scanning lives in `com.blockether.vis.internal.manifest`; the
extension layer that wraps it (and re-exports `discover-extensions!`)
lives in `com.blockether.vis.internal.extension`.(by-cmd cmd)Lookup the channel whose :channel/cmd equals cmd. Returns nil
when no channel claims that command.
Lookup the channel whose :channel/cmd equals `cmd`. Returns nil when no channel claims that command.
(channel spec)Build and validate a channel descriptor map.
Build and validate a channel descriptor map.
(channel-by-id id)Lookup the channel by :channel/id. Returns nil when absent.
Lookup the channel by :channel/id. Returns nil when absent.
(channel-subcommands)Compose subcommands for the vis channels parent from TWO sources:
:cmd/parent ["channels"] (escape hatch for non-channel
adapters that still want to live under vis channels)Source #1 wins on name collision - channels are first-class so a stray extension can't shadow a real channel name. Both sorted together so help output is alphabetic.
Compose subcommands for the `vis channels` parent from TWO sources:
1. Every entry in the channel registry (TUI, Telegram, web, ...)
2. Every commandline extension registered with
`:cmd/parent ["channels"]` (escape hatch for non-channel
adapters that still want to live under `vis channels`)
Source #1 wins on name collision - channels are first-class so a
stray extension can't shadow a real channel name. Both sorted
together so help output is alphabetic.(command spec)Build and validate a command map. Children are NOT validated
recursively; they're checked the first time dispatch! or
render-help walks into them, which keeps dynamic subcommands
from forcing their fn at build time.
Build and validate a command map. Children are NOT validated recursively; they're checked the first time `dispatch!` or `render-help` walks into them, which keeps dynamic subcommands from forcing their fn at build time.
(deregister-cmd! nm)(deregister-cmd! parent nm)Remove a registered command. parent defaults to [] (top-level).
Remove a registered command. `parent` defaults to `[]` (top-level).
(provider spec)Build and validate a provider descriptor.
Build and validate a provider descriptor.
(provider-by-id id)Lookup a provider by :provider/id. Returns nil when absent.
Lookup a provider by `:provider/id`. Returns nil when absent.
(register-channel! spec)Register a channel in the global registry. Idempotent on :channel/id - re-registering replaces the prior spec. Returns the validated channel.
Register a channel in the global registry. Idempotent on :channel/id - re-registering replaces the prior spec. Returns the validated channel.
(register-cmd! spec)Register a command in the global registry. Idempotent on
[:cmd/parent :cmd/name] - re-registering replaces the prior
entry, useful for REPL-driven development. Returns the validated
command map.
Register a command in the global registry. Idempotent on `[:cmd/parent :cmd/name]` - re-registering replaces the prior entry, useful for REPL-driven development. Returns the validated command map.
(register-provider! spec)Register a provider in the global registry. Idempotent on
:provider/id - re-registering replaces the previous descriptor.
Returns the validated provider.
Register a provider in the global registry. Idempotent on `:provider/id` - re-registering replaces the previous descriptor. Returns the validated provider.
(registered-channels)All globally registered channels as a vector.
All globally registered channels as a vector.
(registered-commands)Return all registered commands as a vector, in registration order.
Return all registered commands as a vector, in registration order.
(registered-under parent-path)Return the vector of registered commands whose :cmd/parent equals
parent-path (a vector of names). Use this from a parent command's
:cmd/subcommands slot - typically as a 0-arg fn so newly
registered children appear immediately:
{:cmd/name "ext"
:cmd/doc "Run an extension command."
:cmd/subcommands #(registered-under ["ext"])}
Return the vector of registered commands whose `:cmd/parent` equals
`parent-path` (a vector of names). Use this from a parent command's
`:cmd/subcommands` slot - typically as a 0-arg fn so newly
registered children appear immediately:
{:cmd/name "ext"
:cmd/doc "Run an extension command."
:cmd/subcommands #(registered-under ["ext"])}(resolve-subcommands cmd)Return the static vector of subcommands, calling the dynamic fn
when needed. Returns [] when the command has no children.
Return the static vector of subcommands, calling the dynamic fn when needed. Returns `[]` when the command has no children.
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 |