github jdx/usage v6.1.1
v6.1.1: Windows path fixes and slimmer derived binaries

3 hours ago

A patch release focused on making usage a good citizen on Windows and shrinking the code the derive macro generates. Five separator- and prefix-aware fixes across complete, config and argv land alongside two derive perf passes that trim ~16.5% off a mise-scale stripped binary.

Fixed

  • Path completion keeps the separator you typed. complete_path already accepted / or \ on Windows on the way in, but wrote back the platform separator for the middle of the path and a hard-coded / for the trailing directory marker, so typing target/de/inc came back as target\debug\incremental/ — a spelling no shell will match. Output now uses the same separator the token already contains (#1230 by @JamBalaya56562).
  • Config paths lose the verbatim prefix. normalize still canonicalizes for boundary checks, but strips the Windows \\?\ / UNC extended-length prefix before returning, so FileLayer::paths — which config explain reports as provenance — matches what a caller built with current_dir().join(…) (#1232 by @JamBalaya56562).
  • Install plans respect the target platform. plan takes a Platform for a reason: an install plan is made for a machine, not on one. Three places had regressed to using the host's separator (and Path::is_absolute / Path::ends_with in tests) — a Linux plan made on Windows was emitting fpath+=('/home/u\.local\share\zsh\site-functions'). All fixed to route through Platform::separator and the crate's own platform-aware helpers (#1233 by @JamBalaya56562).
  • Simpler completion-script headers. Rust and Go generators now emit a single @generated by … marker line instead of the extra "do not edit / no cached spec" preamble (#1226 by @jdx).
  • Cleaner flag reference docs. Generated Markdown headings show only the canonical short and long form; additional visible spellings move to a dedicated Aliases line. Hidden-alias filtering and interactive help are unchanged (#1228 by @jdx).

Performance

Two stacked derive-macro passes shrink the code every generated build() carries, without changing behavior or error messages:

  • Cold error construction moves out of line into four #[cold] #[inline(never)] builders in usage-argv (invalid_utf8_value, invalid_parsed_value, invalid_choice_value, invalid_os_value). On a mise-sized shadow binary this drops the stripped size from 1,579 KB to 1,369 KB (−210 KB, −13.3%) and roughly halves generated build() code. Cold parse instructions dip 0.9%; wall time is unchanged within noise (#1235 by @jdx).
  • Repeated-value collection loops are shared through four monomorphized helpers (utf8_values, parsed_values, os_values, spec::choice_values) with an inlined is_empty() fast path that avoids paying for a call when a Vec-shaped field received nothing. Another −51 KB on top, for a cumulative −261 KB (−16.5%) across the stack; instruction counts end up below the pre-stack baseline (#1236 by @jdx).

Tests

  • Joined Windows test paths component-by-component so a self-comparison stops disagreeing with itself, and scoped the "refuse to skip under CI" guard for zsh/fish/bash-completion to Unix — Git for Windows does not ship bash-completion, and the workflow does not install POSIX shells on Windows either (#1229 by @JamBalaya56562).
  • Silenced two Windows-only warnings (unused import: WarningKind, enum_variant_names on Shell::PowerShell) so cargo clippy --all-targets -- -D warnings passes there (#1234 by @JamBalaya56562).

Between them, these three test PRs take a windows-latest cargo test --all --all-features run from 2,383 pass / 5 fail to 2,393 pass / 0 fail, clearing the way for a real Windows CI job.

Full Changelog: v6.1.0...v6.1.1

💚 Sponsor usage

usage is maintained by @jdx, an open source developer for entire.io, the title sponsor of the jdx.dev open source tools including mise, aube, hk, and more. Work on usage is funded by sponsorships.

If usage powers CLI specs, docs, or completions for a tool you maintain or use, please consider sponsoring at jdx.dev. Every sponsorship helps the project stay independent and moving.

Don't miss a new usage release

NewReleases is sending notifications on new releases.