Files
ghostty-rs/crates/ghostty-build-data/src/bash.rs
T
ddidderr 126da77a37 style: apply nightly rustfmt import grouping across the workspace
rustfmt.toml sets group_imports, imports_granularity and imports_layout,
which are nightly-only; agents formatted with stable rustfmt, which
ignored them. This is a formatting-only pass with `cargo +nightly fmt`.

Test Plan:
- cargo clippy --workspace --all-targets -- -D warnings
- cargo test --workspace
2026-10-12 05:03:37 +02:00

135 lines
3.9 KiB
Rust

//! Bash completions (port of `extra/bash.zig`).
use std::fmt::Write as _;
use ghostty_config::cli_args::FieldKind;
use crate::{
actions,
chunks_bash::{C0, C1, C2, C3, C4, C5, C6},
config_fields,
join_names,
join_packed,
};
const COMPGEN_PREFIX: &str = "_compreply compgen -W \"";
const COMPGEN_SUFFIX: &str = "\" -- \"$cur\"; _add_spaces ;;";
fn is_flag(kind: FieldKind) -> bool {
matches!(kind, FieldKind::Bool | FieldKind::OptionalBool)
}
#[must_use]
pub fn completions() -> String {
let pad1 = " ";
let pad2 = " ";
let pad3 = " ";
let pad4 = " ";
let pad5 = " ";
let mut w = String::new();
let fields = config_fields();
w.push_str(C0);
for f in &fields {
if is_flag(f.kind) {
let _ = writeln!(w, "{pad2}config+=\" '--{} '\"", f.name);
} else {
let _ = writeln!(w, "{pad2}config+=\" --{}=\"", f.name);
}
}
w.push_str(C1);
for f in &fields {
let _ = write!(w, "{pad3}--{}) ", f.name);
if f.name.starts_with("font-family") {
w.push_str("_fonts ;;");
} else if f.name == "theme" {
w.push_str("_themes ;;");
} else if f.name == "working-directory" {
w.push_str("_dirs ;;");
} else if f.kind == FieldKind::RepeatablePath {
w.push_str("_files ;;");
} else {
match f.kind {
FieldKind::Enum(names) => {
let _ = write!(w, "{COMPGEN_PREFIX}{}{COMPGEN_SUFFIX}", join_names(names));
}
FieldKind::Packed(names) => {
let _ = write!(w, "{COMPGEN_PREFIX}{}{COMPGEN_SUFFIX}", join_packed(names));
}
_ => w.push_str("return ;;"),
}
}
w.push('\n');
}
w.push_str(C2);
let acts = actions();
for a in acts {
let opts = a.option_fields();
if opts.is_empty() {
continue;
}
let bash_name = a.name().replace('-', "_");
let _ = write!(w, "{pad2}local {bash_name}=\"");
for (count, (name, kind)) in opts.iter().enumerate() {
if count > 0 {
w.push(' ');
}
if is_flag(*kind) {
let _ = write!(w, "'--{name} '");
} else {
let _ = write!(w, "--{name}=");
}
}
w.push_str(" --help\"\n");
}
w.push_str(C3);
for a in acts {
let opts = a.option_fields();
if opts.is_empty() {
continue;
}
let bash_name = a.name().replace('-', "_");
let _ = writeln!(w, "{pad3}+{})", a.name());
let _ = writeln!(w, "{pad4}case $prev in");
for (name, kind) in &opts {
let _ = write!(w, "{pad5}--{name}) ");
match kind {
FieldKind::Bool => w.push_str("return ;;"),
FieldKind::Enum(names) | FieldKind::OptionalEnum(names) => {
let _ = write!(w, "{COMPGEN_PREFIX}{}{COMPGEN_SUFFIX}", join_names(names));
}
FieldKind::OptionalBool | FieldKind::OptionalOther => {
if *name == "config-file" {
w.push_str("return ;;");
} else {
w.push_str("return;;");
}
}
_ => {
if *name == "config-file" {
w.push_str("_files ;;");
} else {
w.push_str("return;;");
}
}
}
w.push('\n');
}
let _ = writeln!(
w,
"{pad5}*) _compreply compgen -W \"${bash_name}\" -- \"$cur\" ;;"
);
w.push_str(C4);
}
w.push_str(C5);
for a in acts {
let _ = writeln!(w, "{pad1}topLevel+=\" +{}\"", a.name());
}
w.push_str(C6);
w
}