Skip to main content

Crate shellcomp

Crate shellcomp 

Source
Expand description

shellcomp is a deployment layer for shell completion scripts in Rust CLI projects.

It does not generate completions. Instead, it focuses on the operational work around completions:

  • choosing managed default install paths,
  • writing completion files idempotently,
  • wiring shell startup files when necessary,
  • detecting current activation state,
  • removing managed files and managed startup blocks,
  • returning structured reports and structured failures for caller-side rendering.

Pair it with clap_complete or any other generator when you need to render the script bytes.

§Scope And Non-Goals

shellcomp intentionally keeps a narrow scope:

  • it is not a shell completion generator;
  • it is not a generic shell configuration manager;
  • it does not attempt to understand arbitrary user shell customizations;
  • it only modifies completion files it was asked to manage and startup blocks it can identify with stable markers.

This is why the crate can stay small while still being production-usable.

§Supported Shells

Production support currently covers Shell::Bash, Shell::Zsh, Shell::Fish, Shell::Powershell, and Shell::Elvish. Shell::Other remains the explicit escape hatch for unsupported shells.

Managed behavior for the supported shells:

  • Shell::Bash: writes to the XDG data completion directory, then prefers a system bash-completion loader and falls back to a managed ~/.bashrc block when no loader is detected.
  • Shell::Zsh: writes _binary-name into the managed zsh completion directory and maintains a managed ~/.zshrc block that updates fpath and runs compinit -i when needed.
  • Shell::Fish: writes directly into Fish’s native completions directory and does not manage a shell startup file.
  • Shell::Powershell: writes a managed completion script file and maintains a managed CurrentUserAllHosts profile block.
  • Shell::Elvish: writes a managed completion script file and maintains a managed rc.elv block.

§Public API

The crate is intentionally small:

§Reading Reports

The public report types are designed so callers can render UX without parsing display strings:

  • InstallReport::file_change tells you whether the completion file was created, updated, or already matched.
  • ActivationReport::mode tells you how the shell will load the completion.
  • ActivationReport::availability tells you whether it is active now, available after a new shell, available after sourcing a file, or still requires manual work.
  • ActivationPolicy lets callers choose whether installation to a custom path should still attempt managed shell wiring when the shell supports it.
  • RemoveReport::cleanup separates startup wiring cleanup from completion file removal so a caller can preserve partial progress.
  • FailureReport carries structured failure kind, relevant paths, and suggested next steps.

§Typical Integration Flow

  1. Render a completion script with your preferred generator.
  2. Call install to place the script into a managed location.
  3. Show the returned ActivationReport to the user.
  4. Optionally call detect_activation later to re-check availability.
  5. Call uninstall to remove both the completion file and any managed activation wiring.

§Install Example

use shellcomp::{InstallRequest, Shell, install};

let script = b"complete -F _demo demo\n";
let report = install(InstallRequest {
    shell: Shell::Bash,
    program_name: "demo",
    script,
    path_override: None,
})?;

println!("installed to {}", report.target_path.display());
println!("activation: {:?}", report.activation);

§clap Integration Example

With the clap feature enabled, you can keep the generator-facing shell value under shellcomp::clap_complete::Shell and convert it into Shell only when you call the deployment API.

use clap::Parser;
use shellcomp::{InstallRequest, install, render_clap_completion};

#[derive(Parser)]
struct Cli {
    #[arg(long)]
    verbose: bool,
}

let generator_shell = shellcomp::clap_complete::Shell::Zsh;
let script = render_clap_completion::<Cli>(generator_shell, "demo")?;
let report = install(InstallRequest {
    shell: generator_shell.into(),
    program_name: "demo",
    script: &script,
    path_override: None,
})?;

println!("installed to {}", report.target_path.display());

§Custom Path Example

Passing InstallRequest::path_override usually tells shellcomp to skip startup wiring and report manual activation explicitly. The one exception is an override that exactly matches the shell’s managed default path, which still keeps the default activation semantics.

use std::path::PathBuf;

use shellcomp::{ActivationMode, Availability, InstallRequest, Shell, install};

let report = install(InstallRequest {
    shell: Shell::Fish,
    program_name: "demo",
    script: b"complete -c demo\n",
    path_override: Some(PathBuf::from("/tmp/demo.fish")),
})?;

assert_eq!(report.activation.mode, ActivationMode::Manual);
assert_eq!(report.activation.availability, Availability::ManualActionRequired);

§Structured Error Handling

High-level operational failures are returned as Error::Failure with a stable FailureKind. That lets callers keep their own presentation layer while still branching on machine-readable failure categories.

use std::path::PathBuf;

use shellcomp::{Error, FailureKind, InstallRequest, Shell, install};

let error = install(InstallRequest {
    shell: Shell::Fish,
    program_name: "demo",
    script: b"complete -c demo\n",
    path_override: Some(PathBuf::from("/")),
})
.expect_err("path without parent should fail structurally");

match error {
    Error::Failure(report) => {
        assert_eq!(report.kind, FailureKind::InvalidTargetPath);
    }
    other => panic!("unexpected error: {other}"),
}

Not every error becomes Error::Failure: immediate validation problems like Error::InvalidProgramName are returned directly.

§Idempotency

Repeating the same install or uninstall operation is expected to be safe:

This makes the crate suitable for CLI commands that users may run multiple times.

Modules§

clap_completeclap
Re-exported clap_complete shell type for callers that want a namespaced integration surface.

Structs§

ActivationReport
Structured activation status for an installed completion.
CleanupReport
Structured cleanup status for activation wiring removal.
FailureReport
Structured failure report for recoverable operational errors.
InstallReport
Structured result of a completion install operation.
InstallRequest
Input for a completion install operation.
LegacyManagedBlock
Caller-provided marker pair for a legacy managed shell block.
MigrateManagedBlocksReport
Structured result of migrating legacy managed startup blocks into shellcomp.
MigrateManagedBlocksRequest
Input for managed-block migration into shellcomp markers.
RemoveReport
Structured result of a completion uninstall operation.
UninstallRequest
Input for a completion uninstall operation.

Enums§

ActivationMode
How a completion becomes active for a shell.
ActivationPolicy
Whether shellcomp should try to manage activation wiring automatically.
Availability
Availability state for an installed completion.
Error
Errors returned by shellcomp operations.
FailureKind
Stable failure kinds for recoverable operational errors.
FileChange
Result of a file mutation.
Operation
High-level operation associated with a structured failure.
Shell
Supported shells for completion installation and detection.

Functions§

default_install_path
Returns the default managed install path for a shell and binary name.
detect_activation
Detects how a completion would be activated for the current environment.
detect_activation_at_path
Detects activation state for an explicit completion file path.
install
Installs a completion script and returns a structured report.
install_with_policy
Installs a completion script with explicit activation intent.
migrate_managed_blocks
Removes caller-provided legacy managed markers and upserts the equivalent shellcomp block.
render_clap_completionclap
Renders a completion script from a clap::CommandFactory implementation.
uninstall
Removes a previously managed completion script and any managed activation wiring.
uninstall_with_policy
Removes a completion script with explicit activation cleanup intent.

Type Aliases§

Result
Convenience result type used by all public shellcomp APIs.