From 70923a0fad3d409069bd9d0b492e6a9b7b113261 Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Mon, 9 Oct 2023 13:20:51 +0200 Subject: [PATCH 1/4] feat: add shell completions for bash --- Cargo.lock | 10 ++ Cargo.toml | 257 ++++++++++++++++++++++++------------ src/plumbing/main.rs | 36 ++++- src/plumbing/options/mod.rs | 3 + 4 files changed, 218 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a08226543b..d920f9db258 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -482,6 +482,15 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.3.12" @@ -1148,6 +1157,7 @@ version = "0.30.0" dependencies = [ "anyhow", "clap", + "clap_complete", "crosstermion", "document-features", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 79101aa00a1..414ea72f2b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,12 @@ default = ["max"] ## Everything, all at once. ## ## As fast as possible, tracing, with TUI progress, progress line rendering with auto-configuration, all transports based on their most mature implementation (HTTP), all `ein` tools, CLI colors and local-time support, JSON output, regex support for rev-specs. -max = ["max-control", "fast", "gitoxide-core-blocking-client", "http-client-curl"] +max = [ + "max-control", + "fast", + "gitoxide-core-blocking-client", + "http-client-curl", +] ## Like `max`, but only Rust is allowed. ## @@ -41,22 +46,55 @@ max = ["max-control", "fast", "gitoxide-core-blocking-client", "http-client-curl ## transports as it uses Rust's HTTP implementation. ## ## As fast as possible, with TUI progress, progress line rendering with auto-configuration, all transports available but less mature pure Rust HTTP implementation, all `ein` tools, CLI colors and local-time support, JSON output, regex support for rev-specs. -max-pure = ["max-control", "gix-features/rustsha1", "gix-features/zlib-rust-backend", "http-client-reqwest", "gitoxide-core-blocking-client" ] +max-pure = [ + "max-control", + "gix-features/rustsha1", + "gix-features/zlib-rust-backend", + "http-client-reqwest", + "gitoxide-core-blocking-client", +] ## Like `max`, but with more control for configuration. See the *Package Maintainers* headline for more information. -max-control = ["tracing", "fast-safe", "pretty-cli", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-tools", "prodash-render-line", "prodash-render-tui", "prodash/render-line-autoconfigure", "gix/revparse-regex" ] +max-control = [ + "tracing", + "fast-safe", + "pretty-cli", + "gitoxide-core-tools-query", + "gitoxide-core-tools-corpus", + "gitoxide-core-tools", + "prodash-render-line", + "prodash-render-tui", + "prodash/render-line-autoconfigure", + "gix/revparse-regex", +] ## All of the good stuff, with less fanciness for smaller binaries. ## ## As fast as possible, progress line rendering, all transports based on their most mature implementation (HTTP), all `ein` tools, CLI colors and local-time support, JSON output. -lean = ["fast", "tracing", "pretty-cli", "http-client-curl", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-tools", "gitoxide-core-blocking-client", "prodash-render-line" ] +lean = [ + "fast", + "tracing", + "pretty-cli", + "http-client-curl", + "gitoxide-core-tools-query", + "gitoxide-core-tools-corpus", + "gitoxide-core-tools", + "gitoxide-core-blocking-client", + "prodash-render-line", +] ## The smallest possible build, best suitable for small single-core machines. ## ## This build is essentially limited to local operations without any fanciness. ## ## Optimized for size, no parallelism thus much slower, progress line rendering. -small = ["pretty-cli", "gix-features/rustsha1", "gix-features/zlib-rust-backend", "prodash-render-line", "is-terminal" ] +small = [ + "pretty-cli", + "gix-features/rustsha1", + "gix-features/zlib-rust-backend", + "prodash-render-line", + "is-terminal", +] ## Like lean, but uses Rusts async implementations for networking. ## @@ -67,7 +105,16 @@ small = ["pretty-cli", "gix-features/rustsha1", "gix-features/zlib-rust-backend" ## ## Due to async client-networking not being implemented for most transports, this one supports only the 'git+tcp' and HTTP transport. ## It uses, however, a fully asynchronous networking implementation which can serve a real-world example on how to implement custom async transports. -lean-async = ["fast", "tracing", "pretty-cli", "gitoxide-core-tools", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-async-client", "prodash-render-line"] +lean-async = [ + "fast", + "tracing", + "pretty-cli", + "gitoxide-core-tools", + "gitoxide-core-tools-query", + "gitoxide-core-tools-corpus", + "gitoxide-core-async-client", + "prodash-render-line", +] #! ### Package Maintainers #! `*-control` features leave it to you to configure C libraries, involving choices for `zlib`, ! hashing and transport implementation. @@ -106,29 +153,62 @@ fast = ["gix/max-performance", "gix/comfort"] fast-safe = ["gix/max-performance-safe", "gix/comfort"] ## Enable tracing in `gitoxide-core`. -tracing = ["dep:tracing-forest", "dep:tracing-subscriber", "dep:tracing", "gix-features/tracing", "gix-features/tracing-detail" ] +tracing = [ + "dep:tracing-forest", + "dep:tracing-subscriber", + "dep:tracing", + "gix-features/tracing", + "gix-features/tracing-detail", +] ## Use `clap` 3.0 to build the prettiest, best documented and most user-friendly CLI at the expense of binary size. ## Provides a terminal user interface for detailed and exhaustive progress. ## Provides a line renderer for leaner progress display, without the need for a full-blown TUI. -pretty-cli = [ "gitoxide-core/serde", "prodash/progress-tree", "prodash/progress-tree-log", "prodash/local-time", "env_logger/humantime", "env_logger/color", "env_logger/auto-color" ] +pretty-cli = [ + "gitoxide-core/serde", + "prodash/progress-tree", + "prodash/progress-tree-log", + "prodash/local-time", + "env_logger/humantime", + "env_logger/color", + "env_logger/auto-color", +] ## The `--verbose` flag will be powered by an interactive progress mechanism that doubles as log as well as interactive progress ## that appears after a short duration. -prodash-render-line-crossterm = ["prodash-render-line", "prodash/render-line-crossterm", "prodash/signal-hook", "is-terminal", "crosstermion"] +prodash-render-line-crossterm = [ + "prodash-render-line", + "prodash/render-line-crossterm", + "prodash/signal-hook", + "is-terminal", + "crosstermion", +] ## Progress reporting with a TUI, can then be enabled with the `--progress` flag. -prodash-render-tui = ["prodash/render-tui", "prodash/render-tui-crossterm", "gix/progress-tree", "futures-lite"] +prodash-render-tui = [ + "prodash/render-tui", + "prodash/render-tui-crossterm", + "gix/progress-tree", + "futures-lite", +] ## Progress reporting by visually drawing lines into the terminal without switching to an alternate window. -prodash-render-line = ["prodash/render-line", "prodash-render-line-crossterm", "gix/progress-tree"] +prodash-render-line = [ + "prodash/render-line", + "prodash-render-line-crossterm", + "gix/progress-tree", +] ## Prints statistical information to inform about cache efficiency when those are dropped. ## Use this as a way to understand if bigger caches actually produce greater yiedls. cache-efficiency-debug = ["gix-features/cache-efficiency-debug"] ## A way to enable most `gitoxide-core` tools found in `ein tools`, namely `organize` and `estimate hours`. -gitoxide-core-tools = ["gitoxide-core/organize", "gitoxide-core/estimate-hours", "gitoxide-core-tools-archive"] +gitoxide-core-tools = [ + "gitoxide-core/organize", + "gitoxide-core/estimate-hours", + "gitoxide-core-tools-archive", +] ## A program to perform analytics on a `git` repository, using an auto-maintained sqlite database gitoxide-core-tools-query = ["gitoxide-core/query"] @@ -168,11 +248,14 @@ gix = { version = "^0.54.1", path = "gix", default-features = false } time = "0.3.23" clap = { version = "4.1.1", features = ["derive", "cargo"] } +clap_complete = "4.4.3" prodash = { workspace = true, optional = true } is-terminal = { version = "0.4.0", optional = true } env_logger = { version = "0.10.0", default-features = false } crosstermion = { version = "0.11.0", optional = true, default-features = false } -futures-lite = { version = "1.12.0", optional = true, default-features = false, features = ["std"] } +futures-lite = { version = "1.12.0", optional = true, default-features = false, features = [ + "std", +] } # for 'tracing' tracing-forest = { version = "0.1.5", features = ["serde"], optional = true } @@ -216,80 +299,80 @@ build-override = { opt-level = 0 } [workspace] members = [ - "gix-actor", - "gix-url", - "gix-hash", - "gix-validate", - "gix-ref", - "gix-command", - "gix-config", - "gix-config-value", - "gix-discover", - "gix-features", - "gix-trace", - "gix-commitgraph", - "gix-chunk", - "gix-quote", - "gix-object", - "gix-glob", - "gix-diff", - "gix-date", - "gix-traverse", - "gix-index", - "gix-bitmap", - "gix-worktree", - "gix-worktree-state", - "gix-status", - "gix-revision", - "gix-packetline", - "gix-packetline-blocking", - "gix-mailmap", - "gix-macros", - "gix-note", - "gix-negotiate", - "gix-fetchhead", - "gix-prompt", - "gix-filter", - "gix-sec", - "gix-lfs", - "gix-rebase", - "gix-sequencer", - "gix-submodule", - "gix-transport", - "gix-credentials", - "gix-protocol", - "gix-pack", - "gix-odb", - "gix-tempfile", - "gix-lock", - "gix-attributes", - "gix-ignore", - "gix-pathspec", - "gix-refspec", - "gix-path", - "gix-utils", - "gix-fs", - "gix", - "gitoxide-core", - "gix-hashtable", - "gix-tui", - "gix-tix", - "gix-archive", - "gix-worktree-stream", - "gix-revwalk", - - "tests/tools", - - "gix-diff/tests", - "gix-pack/tests", - "gix-odb/tests", - "gix-worktree-state/tests", - "gix-status/tests", - "gix-worktree/tests", - "gix-index/tests", - "gix-ref/tests", - "gix-config/tests", - "gix-traverse/tests", + "gix-actor", + "gix-url", + "gix-hash", + "gix-validate", + "gix-ref", + "gix-command", + "gix-config", + "gix-config-value", + "gix-discover", + "gix-features", + "gix-trace", + "gix-commitgraph", + "gix-chunk", + "gix-quote", + "gix-object", + "gix-glob", + "gix-diff", + "gix-date", + "gix-traverse", + "gix-index", + "gix-bitmap", + "gix-worktree", + "gix-worktree-state", + "gix-status", + "gix-revision", + "gix-packetline", + "gix-packetline-blocking", + "gix-mailmap", + "gix-macros", + "gix-note", + "gix-negotiate", + "gix-fetchhead", + "gix-prompt", + "gix-filter", + "gix-sec", + "gix-lfs", + "gix-rebase", + "gix-sequencer", + "gix-submodule", + "gix-transport", + "gix-credentials", + "gix-protocol", + "gix-pack", + "gix-odb", + "gix-tempfile", + "gix-lock", + "gix-attributes", + "gix-ignore", + "gix-pathspec", + "gix-refspec", + "gix-path", + "gix-utils", + "gix-fs", + "gix", + "gitoxide-core", + "gix-hashtable", + "gix-tui", + "gix-tix", + "gix-archive", + "gix-worktree-stream", + "gix-revwalk", + + "tests/tools", + + "gix-diff/tests", + "gix-pack/tests", + "gix-odb/tests", + "gix-worktree-state/tests", + "gix-status/tests", + "gix-worktree/tests", + "gix-index/tests", + "gix-ref/tests", + "gix-config/tests", + "gix-traverse/tests", ] [workspace.dependencies] diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index a7c8d8a69bc..fe842bfc4df 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -8,7 +8,8 @@ use std::{ }; use anyhow::{Context, Result}; -use clap::Parser; +use clap::{CommandFactory, Parser}; +use clap_complete::{generate, shells::Bash}; use gitoxide_core as core; use gitoxide_core::{pack::verify, repository::PathsOrPatterns}; use gix::bstr::{io::BufReadExt, BString}; @@ -1219,6 +1220,39 @@ pub fn main() -> Result<()> { }, ), }, + Subcommands::GenerateCompletions => { + let mut app = Args::command(); + + let bin_name = "gix"; + + app.set_bin_name(bin_name); + + // TODO: For additonal shells, find preferred completion workflow + let outdir = std::path::Path::new("/etc/").join("bash_completion.d/"); + + match &mut std::fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&outdir.join(bin_name)) + { + Ok(write_buffer) => { + generate(Bash, &mut app, bin_name, write_buffer); + // generate(Fish, &mut app, bin_name, write_buffer); + // generate(Zsh, &mut app, bin_name, write_buffer); + // generate(PowerShell, &mut app, bin_name, write_buffer); + // generate(Elvish, &mut app, bin_name, write_buffer); + + println!("completion file generated in: {outdir:?}"); + } + Err(e) => { + eprintln!("failed to open path '{outdir:?}': {}", e); + std::process::exit(1); + } + }; + + Ok(()) + } }?; Ok(()) } diff --git a/src/plumbing/options/mod.rs b/src/plumbing/options/mod.rs index 64c67e43e5a..5fa3613f92e 100644 --- a/src/plumbing/options/mod.rs +++ b/src/plumbing/options/mod.rs @@ -134,6 +134,9 @@ pub enum Subcommands { /// Subcommands that need no git repository to run. #[clap(subcommand)] Free(free::Subcommands), + /// Generate shell completions in `/etc/bash_completion.d/gix.bash`. + /// NOTE: Requires `sudo` to write to `/etc/`. + GenerateCompletions, } #[cfg(feature = "gitoxide-core-tools-archive")] From 6c913bfa36a2b66dc305c8542fe7a5e072f1efdb Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Mon, 9 Oct 2023 13:29:31 +0200 Subject: [PATCH 2/4] undo formatting changes --- Cargo.toml | 256 ++++++++++++++++++----------------------------------- 1 file changed, 87 insertions(+), 169 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 414ea72f2b1..31adeb9447b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,12 +33,7 @@ default = ["max"] ## Everything, all at once. ## ## As fast as possible, tracing, with TUI progress, progress line rendering with auto-configuration, all transports based on their most mature implementation (HTTP), all `ein` tools, CLI colors and local-time support, JSON output, regex support for rev-specs. -max = [ - "max-control", - "fast", - "gitoxide-core-blocking-client", - "http-client-curl", -] +max = ["max-control", "fast", "gitoxide-core-blocking-client", "http-client-curl"] ## Like `max`, but only Rust is allowed. ## @@ -46,55 +41,22 @@ max = [ ## transports as it uses Rust's HTTP implementation. ## ## As fast as possible, with TUI progress, progress line rendering with auto-configuration, all transports available but less mature pure Rust HTTP implementation, all `ein` tools, CLI colors and local-time support, JSON output, regex support for rev-specs. -max-pure = [ - "max-control", - "gix-features/rustsha1", - "gix-features/zlib-rust-backend", - "http-client-reqwest", - "gitoxide-core-blocking-client", -] +max-pure = ["max-control", "gix-features/rustsha1", "gix-features/zlib-rust-backend", "http-client-reqwest", "gitoxide-core-blocking-client" ] ## Like `max`, but with more control for configuration. See the *Package Maintainers* headline for more information. -max-control = [ - "tracing", - "fast-safe", - "pretty-cli", - "gitoxide-core-tools-query", - "gitoxide-core-tools-corpus", - "gitoxide-core-tools", - "prodash-render-line", - "prodash-render-tui", - "prodash/render-line-autoconfigure", - "gix/revparse-regex", -] +max-control = ["tracing", "fast-safe", "pretty-cli", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-tools", "prodash-render-line", "prodash-render-tui", "prodash/render-line-autoconfigure", "gix/revparse-regex" ] ## All of the good stuff, with less fanciness for smaller binaries. ## ## As fast as possible, progress line rendering, all transports based on their most mature implementation (HTTP), all `ein` tools, CLI colors and local-time support, JSON output. -lean = [ - "fast", - "tracing", - "pretty-cli", - "http-client-curl", - "gitoxide-core-tools-query", - "gitoxide-core-tools-corpus", - "gitoxide-core-tools", - "gitoxide-core-blocking-client", - "prodash-render-line", -] +lean = ["fast", "tracing", "pretty-cli", "http-client-curl", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-tools", "gitoxide-core-blocking-client", "prodash-render-line" ] ## The smallest possible build, best suitable for small single-core machines. ## ## This build is essentially limited to local operations without any fanciness. ## ## Optimized for size, no parallelism thus much slower, progress line rendering. -small = [ - "pretty-cli", - "gix-features/rustsha1", - "gix-features/zlib-rust-backend", - "prodash-render-line", - "is-terminal", -] +small = ["pretty-cli", "gix-features/rustsha1", "gix-features/zlib-rust-backend", "prodash-render-line", "is-terminal" ] ## Like lean, but uses Rusts async implementations for networking. ## @@ -105,16 +67,7 @@ small = [ ## ## Due to async client-networking not being implemented for most transports, this one supports only the 'git+tcp' and HTTP transport. ## It uses, however, a fully asynchronous networking implementation which can serve a real-world example on how to implement custom async transports. -lean-async = [ - "fast", - "tracing", - "pretty-cli", - "gitoxide-core-tools", - "gitoxide-core-tools-query", - "gitoxide-core-tools-corpus", - "gitoxide-core-async-client", - "prodash-render-line", -] +lean-async = ["fast", "tracing", "pretty-cli", "gitoxide-core-tools", "gitoxide-core-tools-query", "gitoxide-core-tools-corpus", "gitoxide-core-async-client", "prodash-render-line"] #! ### Package Maintainers #! `*-control` features leave it to you to configure C libraries, involving choices for `zlib`, ! hashing and transport implementation. @@ -153,62 +106,29 @@ fast = ["gix/max-performance", "gix/comfort"] fast-safe = ["gix/max-performance-safe", "gix/comfort"] ## Enable tracing in `gitoxide-core`. -tracing = [ - "dep:tracing-forest", - "dep:tracing-subscriber", - "dep:tracing", - "gix-features/tracing", - "gix-features/tracing-detail", -] +tracing = ["dep:tracing-forest", "dep:tracing-subscriber", "dep:tracing", "gix-features/tracing", "gix-features/tracing-detail" ] ## Use `clap` 3.0 to build the prettiest, best documented and most user-friendly CLI at the expense of binary size. ## Provides a terminal user interface for detailed and exhaustive progress. ## Provides a line renderer for leaner progress display, without the need for a full-blown TUI. -pretty-cli = [ - "gitoxide-core/serde", - "prodash/progress-tree", - "prodash/progress-tree-log", - "prodash/local-time", - "env_logger/humantime", - "env_logger/color", - "env_logger/auto-color", -] +pretty-cli = [ "gitoxide-core/serde", "prodash/progress-tree", "prodash/progress-tree-log", "prodash/local-time", "env_logger/humantime", "env_logger/color", "env_logger/auto-color" ] ## The `--verbose` flag will be powered by an interactive progress mechanism that doubles as log as well as interactive progress ## that appears after a short duration. -prodash-render-line-crossterm = [ - "prodash-render-line", - "prodash/render-line-crossterm", - "prodash/signal-hook", - "is-terminal", - "crosstermion", -] +prodash-render-line-crossterm = ["prodash-render-line", "prodash/render-line-crossterm", "prodash/signal-hook", "is-terminal", "crosstermion"] ## Progress reporting with a TUI, can then be enabled with the `--progress` flag. -prodash-render-tui = [ - "prodash/render-tui", - "prodash/render-tui-crossterm", - "gix/progress-tree", - "futures-lite", -] +prodash-render-tui = ["prodash/render-tui", "prodash/render-tui-crossterm", "gix/progress-tree", "futures-lite"] ## Progress reporting by visually drawing lines into the terminal without switching to an alternate window. -prodash-render-line = [ - "prodash/render-line", - "prodash-render-line-crossterm", - "gix/progress-tree", -] +prodash-render-line = ["prodash/render-line", "prodash-render-line-crossterm", "gix/progress-tree"] ## Prints statistical information to inform about cache efficiency when those are dropped. ## Use this as a way to understand if bigger caches actually produce greater yiedls. cache-efficiency-debug = ["gix-features/cache-efficiency-debug"] ## A way to enable most `gitoxide-core` tools found in `ein tools`, namely `organize` and `estimate hours`. -gitoxide-core-tools = [ - "gitoxide-core/organize", - "gitoxide-core/estimate-hours", - "gitoxide-core-tools-archive", -] +gitoxide-core-tools = ["gitoxide-core/organize", "gitoxide-core/estimate-hours", "gitoxide-core-tools-archive"] ## A program to perform analytics on a `git` repository, using an auto-maintained sqlite database gitoxide-core-tools-query = ["gitoxide-core/query"] @@ -253,9 +173,7 @@ prodash = { workspace = true, optional = true } is-terminal = { version = "0.4.0", optional = true } env_logger = { version = "0.10.0", default-features = false } crosstermion = { version = "0.11.0", optional = true, default-features = false } -futures-lite = { version = "1.12.0", optional = true, default-features = false, features = [ - "std", -] } +futures-lite = { version = "1.12.0", optional = true, default-features = false, features = ["std"] } # for 'tracing' tracing-forest = { version = "0.1.5", features = ["serde"], optional = true } @@ -299,80 +217,80 @@ build-override = { opt-level = 0 } [workspace] members = [ - "gix-actor", - "gix-url", - "gix-hash", - "gix-validate", - "gix-ref", - "gix-command", - "gix-config", - "gix-config-value", - "gix-discover", - "gix-features", - "gix-trace", - "gix-commitgraph", - "gix-chunk", - "gix-quote", - "gix-object", - "gix-glob", - "gix-diff", - "gix-date", - "gix-traverse", - "gix-index", - "gix-bitmap", - "gix-worktree", - "gix-worktree-state", - "gix-status", - "gix-revision", - "gix-packetline", - "gix-packetline-blocking", - "gix-mailmap", - "gix-macros", - "gix-note", - "gix-negotiate", - "gix-fetchhead", - "gix-prompt", - "gix-filter", - "gix-sec", - "gix-lfs", - "gix-rebase", - "gix-sequencer", - "gix-submodule", - "gix-transport", - "gix-credentials", - "gix-protocol", - "gix-pack", - "gix-odb", - "gix-tempfile", - "gix-lock", - "gix-attributes", - "gix-ignore", - "gix-pathspec", - "gix-refspec", - "gix-path", - "gix-utils", - "gix-fs", - "gix", - "gitoxide-core", - "gix-hashtable", - "gix-tui", - "gix-tix", - "gix-archive", - "gix-worktree-stream", - "gix-revwalk", - - "tests/tools", - - "gix-diff/tests", - "gix-pack/tests", - "gix-odb/tests", - "gix-worktree-state/tests", - "gix-status/tests", - "gix-worktree/tests", - "gix-index/tests", - "gix-ref/tests", - "gix-config/tests", - "gix-traverse/tests", + "gix-actor", + "gix-url", + "gix-hash", + "gix-validate", + "gix-ref", + "gix-command", + "gix-config", + "gix-config-value", + "gix-discover", + "gix-features", + "gix-trace", + "gix-commitgraph", + "gix-chunk", + "gix-quote", + "gix-object", + "gix-glob", + "gix-diff", + "gix-date", + "gix-traverse", + "gix-index", + "gix-bitmap", + "gix-worktree", + "gix-worktree-state", + "gix-status", + "gix-revision", + "gix-packetline", + "gix-packetline-blocking", + "gix-mailmap", + "gix-macros", + "gix-note", + "gix-negotiate", + "gix-fetchhead", + "gix-prompt", + "gix-filter", + "gix-sec", + "gix-lfs", + "gix-rebase", + "gix-sequencer", + "gix-submodule", + "gix-transport", + "gix-credentials", + "gix-protocol", + "gix-pack", + "gix-odb", + "gix-tempfile", + "gix-lock", + "gix-attributes", + "gix-ignore", + "gix-pathspec", + "gix-refspec", + "gix-path", + "gix-utils", + "gix-fs", + "gix", + "gitoxide-core", + "gix-hashtable", + "gix-tui", + "gix-tix", + "gix-archive", + "gix-worktree-stream", + "gix-revwalk", + + "tests/tools", + + "gix-diff/tests", + "gix-pack/tests", + "gix-odb/tests", + "gix-worktree-state/tests", + "gix-status/tests", + "gix-worktree/tests", + "gix-index/tests", + "gix-ref/tests", + "gix-config/tests", + "gix-traverse/tests", ] [workspace.dependencies] From 215c3acfd25554b9c2259d069f3916a9d6d911f5 Mon Sep 17 00:00:00 2001 From: Shaun Hamilton Date: Mon, 9 Oct 2023 22:02:24 +0200 Subject: [PATCH 3/4] user decides completion output --- src/plumbing/main.rs | 36 +++++++----------------------------- src/plumbing/options/mod.rs | 13 ++++++++++--- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index fe842bfc4df..e42775950e0 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -9,7 +9,7 @@ use std::{ use anyhow::{Context, Result}; use clap::{CommandFactory, Parser}; -use clap_complete::{generate, shells::Bash}; +use clap_complete::{generate, generate_to}; use gitoxide_core as core; use gitoxide_core::{pack::verify, repository::PathsOrPatterns}; use gix::bstr::{io::BufReadExt, BString}; @@ -1220,36 +1220,14 @@ pub fn main() -> Result<()> { }, ), }, - Subcommands::GenerateCompletions => { + Subcommands::GenerateCompletions { shell, out_dir } => { let mut app = Args::command(); - let bin_name = "gix"; - - app.set_bin_name(bin_name); - - // TODO: For additonal shells, find preferred completion workflow - let outdir = std::path::Path::new("/etc/").join("bash_completion.d/"); - - match &mut std::fs::OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(&outdir.join(bin_name)) - { - Ok(write_buffer) => { - generate(Bash, &mut app, bin_name, write_buffer); - // generate(Fish, &mut app, bin_name, write_buffer); - // generate(Zsh, &mut app, bin_name, write_buffer); - // generate(PowerShell, &mut app, bin_name, write_buffer); - // generate(Elvish, &mut app, bin_name, write_buffer); - - println!("completion file generated in: {outdir:?}"); - } - Err(e) => { - eprintln!("failed to open path '{outdir:?}': {}", e); - std::process::exit(1); - } - }; + if let Some(out_dir) = out_dir { + generate_to(shell, &mut app, env!("CARGO_PKG_NAME"), &out_dir)?; + } else { + generate(shell, &mut app, env!("CARGO_PKG_NAME"), &mut std::io::stdout()); + } Ok(()) } diff --git a/src/plumbing/options/mod.rs b/src/plumbing/options/mod.rs index 5fa3613f92e..364b93adb4f 100644 --- a/src/plumbing/options/mod.rs +++ b/src/plumbing/options/mod.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +use clap_complete::Shell; use gitoxide_core as core; use gix::bstr::BString; @@ -134,9 +135,15 @@ pub enum Subcommands { /// Subcommands that need no git repository to run. #[clap(subcommand)] Free(free::Subcommands), - /// Generate shell completions in `/etc/bash_completion.d/gix.bash`. - /// NOTE: Requires `sudo` to write to `/etc/`. - GenerateCompletions, + /// Generate shell completions + GenerateCompletions { + /// Shell for generating completions. + #[clap(long, short)] + shell: Shell, + /// Output directory. If not provided, will write to stdout. + #[clap(long, short)] + out_dir: Option, + }, } #[cfg(feature = "gitoxide-core-tools-archive")] From fdd2df8e42f2a14a90e9a575e19811f25ab62237 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 10 Oct 2023 07:48:10 +0200 Subject: [PATCH 4/4] refactor --- src/plumbing/main.rs | 14 +++++++------- src/plumbing/options/mod.rs | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs index e42775950e0..9cbedce83fd 100644 --- a/src/plumbing/main.rs +++ b/src/plumbing/main.rs @@ -7,9 +7,8 @@ use std::{ }, }; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use clap::{CommandFactory, Parser}; -use clap_complete::{generate, generate_to}; use gitoxide_core as core; use gitoxide_core::{pack::verify, repository::PathsOrPatterns}; use gix::bstr::{io::BufReadExt, BString}; @@ -1220,15 +1219,16 @@ pub fn main() -> Result<()> { }, ), }, - Subcommands::GenerateCompletions { shell, out_dir } => { + Subcommands::Completions { shell, out_dir } => { let mut app = Args::command(); - + let shell = shell + .or_else(clap_complete::Shell::from_env) + .ok_or_else(|| anyhow!("The shell could not be derived from the environment"))?; if let Some(out_dir) = out_dir { - generate_to(shell, &mut app, env!("CARGO_PKG_NAME"), &out_dir)?; + clap_complete::generate_to(shell, &mut app, env!("CARGO_PKG_NAME"), &out_dir)?; } else { - generate(shell, &mut app, env!("CARGO_PKG_NAME"), &mut std::io::stdout()); + clap_complete::generate(shell, &mut app, env!("CARGO_PKG_NAME"), &mut std::io::stdout()); } - Ok(()) } }?; diff --git a/src/plumbing/options/mod.rs b/src/plumbing/options/mod.rs index 364b93adb4f..f7b484aaf6f 100644 --- a/src/plumbing/options/mod.rs +++ b/src/plumbing/options/mod.rs @@ -135,13 +135,13 @@ pub enum Subcommands { /// Subcommands that need no git repository to run. #[clap(subcommand)] Free(free::Subcommands), - /// Generate shell completions - GenerateCompletions { - /// Shell for generating completions. - #[clap(long, short)] - shell: Shell, - /// Output directory. If not provided, will write to stdout. + /// Generate shell completions to stdout or a directory. + #[clap(visible_alias = "generate-completions", visible_alias = "shell-completions")] + Completions { + /// The shell to generate completions for. Otherwise it's derived from the environment. #[clap(long, short)] + shell: Option, + /// The output directory in case multiple files are generated. If not provided, will write to stdout. out_dir: Option, }, }