Skip to content

Add completions for 21 macOS system utilities - #12874

Open
moonexpr wants to merge 22 commits into
fish-shell:masterfrom
moonexpr:macos-system-completions
Open

Add completions for 21 macOS system utilities#12874
moonexpr wants to merge 22 commits into
fish-shell:masterfrom
moonexpr:macos-system-completions

Conversation

@moonexpr

Copy link
Copy Markdown

Description

Adds completions for 21 macOS system tools that currently ship no completion (part of #3525):

codesign, csrutil, dscl, dseditgroup, fdesetup, hdiutil, installer, networksetup, osascript, pkgutil, pmset, profiles, screencapture, scutil, security, sips, softwareupdate, spctl, sysadminctl, system_profiler, systemsetup

One commit per completion so individual files can be dropped or amended easily.

Notes

  • Where useful, completions enumerate live values (network services, package ids, attached disk images, users/groups, signing identities, …) using only fast, unprivileged list commands, always guarded so tab completion never hangs, hits the network, or prompts for a password.
  • Helper functions use the __fish prefix and stay in their completion file; descriptions are kept short.
  • All files are fish_indent-formatted and source cleanly.
  • Every offered option and argument value was audited against the tool's man page, --help, and sub-help output (e.g. scutil --nc help, pmset -g cap) via a deterministic string-match audit, with the remainder reviewed by hand — no invented flags or values.

Happy to split this into smaller PRs, drop individual tools, or add a CHANGELOG entry if preferred.

@moonexpr

Copy link
Copy Markdown
Author

CI note: po_files_up_to_date is fixed (regenerated with cargo xtask gettext update). The remaining ubuntu-asan failure is a rustc nightly ICE ("the compiler unexpectedly panicked") while compiling the fish lib test — this PR touches only share/completions/ and localization/po/, no Rust, and the same ICE occurred on both runs.

@krobelus krobelus added this to the fish 4.9 milestone Jul 19, 2026
Comment thread share/completions/dscl.fish Outdated
Comment thread share/completions/dscl.fish Outdated
Comment thread share/completions/dscl.fish Outdated
Comment thread share/completions/dscl.fish Outdated
Comment thread share/completions/hdiutil.fish Outdated
Comment thread share/completions/profiles.fish Outdated
Comment thread share/completions/profiles.fish Outdated
Comment thread share/completions/scutil.fish Outdated
Comment thread share/completions/softwareupdate.fish Outdated
Comment thread share/completions/softwareupdate.fish Outdated
@moonexpr

moonexpr commented Jul 24, 2026

Copy link
Copy Markdown
Author

AGENTS.md — fish-shell

This file provides guidance to AGENTS (automated contributors / LLMs) working
in the fish-shell repository.

The authoritative source for contribution rules is
CONTRIBUTING.rst <CONTRIBUTING.rst>; for project orientation, see
README.rst <README.rst>
. This file condenses those rules to the checks an
agent must run, and adds k-shot examples of mistakes commonly made by
generated code, so they can be avoided.


Role

The AGENT is a contributor. It writes idiomatic Rust or fish script, runs the
formatters and tests below, and prepares commits that follow fish-shell's
linear, recipe-style history. A human contributor reviews the result and
opens the upstream PR; the AGENT never pushes or opens PRs itself.


Repository map

Area Where Language
Shell implementation src/ (unit tests inline in mod tests {}) Rust
Completions share/completions/ fish script
Runtime functions share/functions/ fish script
User documentation doc_src/ (Sphinx) reST
System tests tests/checks/ (littlecheck), tests/pexpects/ (pexpect) fish / Python
Translations localization/ PO / FTL

User-visible changes need a CHANGELOG.rst entry.


Build, format, test

cargo build                                  # debug build
cargo xtask format --all                     # rustfmt + fish_indent + ruff format
cargo test                                   # Rust unit tests
tests/test_driver.py target/debug            # system tests (or one: ... tests/checks/abbr.fish)
cargo xtask check                            # everything: all tests + linters

Rules that apply to every change:

  1. Every commit passes the checks. Formatted (cargo xtask format),
    parses/compiles, tests green — per commit, not just at branch tip.
  2. No fixup commits. On review feedback, rewrite the relevant commits
    directly (amend / interactive rebase). Rebase on master rather than
    merging. Never rewrite history that is already on master.
  3. Fixes #<n> at the end of the commit description when a commit closes
    an issue.
  4. Add tests with behavior changes. Prefer littlecheck tests in
    tests/checks (fish scripts with expected output in # CHECK: /
    # CHECKERR: comments); use pexpect only when real interactivity is
    required.
  5. If behavior cannot be verified — a flag's semantics, a platform
    difference, an untestable path — say so in the PR notes rather than
    guessing.

Contributing completions

The rest of this file covers share/completions/<command>.fish, the most
common target for generated contributions.

A completion script is ready for review when:

  1. It parses with fish -n and is formatted with fish_indent.
  2. It follows the conventions in CONTRIBUTING.rst.
  3. It avoids the bad patterns listed below.
  4. Descriptions are grounded in the command's man page, start with a capital
    letter, have no trailing period, and are short (aim ≤ 40 characters).

A minimal idiomatic completion, for shape:

complete -c mycmd -f
complete -c mycmd -s v -l verbose -d "Print more output"
complete -c mycmd -n __fish_use_subcommand -a start -d "Start the service"
complete -c mycmd -n "__fish_seen_subcommand_from start" -a "(mycmd --list 2>/dev/null)"

Principles

  1. Rely on exit status. A helper that finds a token returns it and exits 0;
    otherwise it exits non-zero. Do not add redundant empty-string guards.
  2. Use fish idioms. Prefer true/false over 0/1; use globs instead of
    parsing ls; redirect both streams with &>/dev/null.
  3. -xpc over -opc. Use commandline -xpc for predicates; it excludes the
    in-progress token, which is almost always the desired behavior.
  4. Locals only. Completion files are sourced into the user's shell. Never
    define global variables; use set -l and function --inherit-variable.
  5. One parser per grammar. If multiple helpers inspect the same command-line
    structure, extract a single parser and index it rather than re-walking tokens.
  6. Suppress a stream only when it needs suppressing. Silence stderr on
    commands that actually emit noise; never silence stdout you intend to
    capture, and never blanket-silence helpers that are already silent.
  7. Fast, unprivileged enumeration only. Completions run synchronously on
    every Tab press inside the user's interactive shell; anything slow,
    privileged, or networked degrades it.

Common mistakes (bad → good)

Mistake Bad Good
Redundant empty-string guard (helper already signals via exit status) test -n "$v" && test "$v" = "$argv[1]" test "$v" = "$argv[1]"
Token list includes the in-progress token commandline -opc commandline -xpc
Verbose redirect >/dev/null 2>&1 &>/dev/null
Parsing ls ls /Volumes | while read -l v for v in /Volumes/*
Suppressing stderr of a silent helper (__fish_pmset_action 2>/dev/null) (__fish_pmset_action)
Suppressing stdout of a live enumerator (discards its results) dscl . -list / &>/dev/null dscl . -list / 2>/dev/null

Three mistakes involve state and need full context.

0/1 boolean flags — use true/false, which are commands, so the
variable itself is the condition:

# Bad
set -l saw_g 0
if test $saw_g -eq 1
    ...
end

# Good
set -l saw_g false
if $saw_g
    ...
end

Global variables in completion files — completion files are sourced into
the user's shell, so a set -g leaks. Use a local set only on the found
path, then test with set -q:

# Bad
set -g __fish_dscl_ds_found 1

# Good
set -l ds_found
...
if set -q ds_found[1]
    ...
end

Duplicated command-line parsing — several helpers each re-walking the
tokens. Extract one parser and index it:

# Bad: __fish_dscl_datasource and __fish_dscl_command each walk the tokens.

# Good: one positional parser, thin accessors.
function __fish_dscl_at
    set -l pos (__fish_dscl_positionals)
    set -q pos[$argv[1]]; and echo $pos[$argv[1]]
end

function __fish_dscl_datasource
    __fish_dscl_at 1
end

function __fish_dscl_command
    set -l cmd (__fish_dscl_at 2)
    and string trim -l -c - -- $cmd
end

If a flag's behavior cannot be verified from the man page or --help output,
omit the completion or leave the description minimal and note the gap for the
reviewer — do not invent descriptions.

@moonexpr
moonexpr force-pushed the macos-system-completions branch from b521717 to 3e06d77 Compare July 25, 2026 00:08
@moonexpr

Copy link
Copy Markdown
Author

Rebased the branch in place to fold the review feedback into the original per-tool commits (no fixup commits, per CONTRIBUTING): b521717bb3e06d772c.

What changed across the 18 completions: exit-status contracts instead of redundant empty-string guards, commandline -xpc for predicates, &>/dev/null redirects, true/false booleans, globs instead of parsing ls, and shared single parsers where helpers were re-walking tokens. Every file passes fish -n and fish_indent --check.

One known gap: a number of -d descriptions changed, so the PO files in the localization commit may be stale against the new strings — I can regenerate them if that's preferred over dropping that commit.

@moonexpr
moonexpr requested a review from krobelus July 25, 2026 00:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants