Repository navigation
Conversation
Dry::CLI#call and Command.new take `kernel:`, defaulting to Kernel. Help, errors and typos stop the CLI by raising a private Halt, which #call turns into kernel.exit, so a kernel whose exit returns (as Aruba's does) still stops the CLI. A command's own `exit` goes through its kernel too. Dry::CLI::Launcher[registry] runs a CLI with the arguments, streams and kernel in the order Aruba's in-process launcher passes them, so a CLI can be tested in the same process with StringIO streams.
Registry#tree, Dry::CLI#tree and Dry::CLI::Tree.for return a live view of the registered commands, for gems that describe a CLI rather than run it: help screens, shell completion, documentation generators. Until now they could only walk CommandRegistry internals. Tree::Node#resolve shares its lookup with dispatch (CommandRegistry.lookup), so the command it finds is the one the CLI would run. Tree::Param is a frozen snapshot of an option or argument, including every declared key.
Help and command listings are built as a Dry::CLI::Screen, passed through a renderer and a list of filters, then printed to the stream its status chooses. Renderer and filters are any #call(screen) -> screen, so they compose with >> (procs, dry-transformer functions). Dry::CLI.configure sets them process-wide; Dry.CLI(..., config:) per CLI. The default renderer wraps Banner and Usage, and the existing suite passes unchanged, so unconfigured output is byte-for-byte what it was. This replaces overriding the private #help and #spell_checker, which is what dry-cli-help has to do today.
Commands already work with dry-auto_inject and dry-system containers, through Command.new. Document how, including the one rule dry-auto_inject has for any class (a subclass's own #initialize must call super(**)), and pin it with specs, including the failure when that rule is broken. Also document memoizing objects built from a command's streams against the stream, since an instance command is reused across calls, and across tests when a CLI runs in-process.
kig/help-rendering-pipelinekig/help-rendering-pipeline
kig/help-rendering-pipelineCommand with dry-auto_inject (if accepted, stacks on top of #174)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposal 4 of 4 in the dry-cli plugin-hooks series. It should be stacked on #175, but I don't have permission to set the base to a branch on a fork, it seems. Upstream issue/forum thread: pending.
Why
It's pretty common from what I've seen, and useful, to be able to define your custom BaseCommand (typically abstract), that decorates all of the inheriting commands with a specific behavior. One of such cases is to set a
uiobject and make it available throughout command lifecycle, to show errors in boxes, progress bars and concurrenly updating multiple spinners, and so on.Other examples include injecting a database or Redis client driver.
Who uses it
Among my gems:
dry-cli-helpanddry-cli-uiSummary
No library code changes. Shared per-command objects are dry-rb's job already: commands work with dry-auto_inject (and so dry-system containers) through
Command.new. This PR documents it onCommandand pins it with specs.Objects built from a command's streams can't come from a container. The docs give the rule for memoizing them, since an instance command is reused across calls (and across tests with
Launcher):Evidence
Before: undocumented; a subclass
#initializewithoutsuper(**)fails withArgumentError: unknown keyword: :clock, with no guidance.After:
spec/integration/auto_inject_spec.rb(6): base-command injection, streams set before#initialize, instance commands, explicit keyword overriding the container, own#initializewithsuper(**), and the documented failure without it. The stream-memoization rule is exercised inlauncher_spec.rb(Basic commands #1). Full suite 687 examples, 0 failures; rubocop clean; no new undocumented YARD objects.Merge Danger
Docs and specs only;
dry-auto_injectis a new development-only dependency.