Skip to content

Commit

Permalink
Merge pull request #158 from schilkp/schilkp/autocomplete
Browse files Browse the repository at this point in the history
cmd: add 'completion' command
  • Loading branch information
micprog authored Mar 21, 2024
2 parents 755177c + 6540fe6 commit 69c82e9
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 7 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ tokio = { version = "1.27", features = ["full"] }
async-recursion = "1.0"

clap = { version = "4.0", features = ["derive"] }
clap_complete = "4.0"
semver = { version = "1.0", features = ["serde"] }
blake2 = "0.10"
typed-arena = "2"
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ Calling update with the `--fetch/-f` flag will force all git dependencies to be

### `clone` --- Clone dependency to make modifications

The `bender clone <PKG>` command checks out the package `PKG` into a directory (default `working_dir`, can be overridden with `-p / --path <DIR>`).
The `bender clone <PKG>` command checks out the package `PKG` into a directory (default `working_dir`, can be overridden with `-p / --path <DIR>`).
To ensure the package is correctly linked in bender, the `Bender.local` file is modified to include a `path` dependency override, linking to the corresponding package.

This can be used for development of dependent packages within the parent repository, allowing to test uncommitted and committed changes, without the worry that bender would update the dependency.
Expand Down Expand Up @@ -535,6 +535,23 @@ This branch can then be rebased and a pull request can be opened from it as usua
Note: when using mappings in your `vendor_package`, the patches will be relative to the mapped directory.
Hence, for upstreaming, you might need to use `git am --directory=<mapping.from>` instead of plain `git am`.

### `completion` --- Generate shell completion script

The `bender completion <SHELL>` command prints a completion script for the given shell.

Installation and usage of these scripts is shell-dependent. Please refer to your shell's documentation
for information on how to install and use the generated script
([bash](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html),
[zsh](https://zsh.sourceforge.io/Doc/Release/Completion-System.html),
[fish](https://fishshell.com/docs/current/completions.html)).

Supported shells:
- `bash`
- `elvish`
- `fish`
- `powershell`
- `zsh`

[aur-bender]: https://aur.archlinux.org/packages/bender
[releases]: https://github.com/pulp-platform/bender/releases
[rust-installation]: https://doc.rust-lang.org/book/ch01-01-installation.html
11 changes: 10 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ pub fn main() -> Result<()> {
.version(env!("CARGO_PKG_VERSION"))
.author(env!("CARGO_PKG_AUTHORS"))
.about("A dependency management tool for hardware projects.")
.after_help(
"Type 'bender <SUBCOMMAND> --help' for more information about a bender subcommand.",
)
.arg(
Arg::new("dir")
.short('d')
Expand Down Expand Up @@ -77,6 +80,7 @@ pub fn main() -> Result<()> {
.subcommand(cmd::clone::new())
.subcommand(cmd::packages::new())
.subcommand(cmd::sources::new())
.subcommand(cmd::completion::new())
.subcommand(cmd::config::new())
.subcommand(cmd::script::new())
.subcommand(cmd::checkout::new())
Expand All @@ -99,7 +103,7 @@ pub fn main() -> Result<()> {
};

// Parse the arguments.
let matches = app.get_matches();
let matches = app.clone().get_matches();

// Enable debug outputs if needed.
if matches.contains_id("debug") && matches.get_flag("debug") {
Expand All @@ -110,6 +114,11 @@ pub fn main() -> Result<()> {
return cmd::init::run(matches);
}

if let Some(("completion", matches)) = matches.subcommand() {
let mut app = app;
return cmd::completion::run(matches, &mut app);
}

let mut force_fetch = false;
if let Some(("update", intern_matches)) = matches.subcommand() {
force_fetch = intern_matches.get_flag("fetch");
Expand Down
44 changes: 44 additions & 0 deletions src/cmd/completion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) 2017-2024 ETH Zurich
// Philipp Schilk <[email protected]>

//! The `completion` subcommand.
use std::io;

use crate::error::*;
use clap::{builder::PossibleValue, Arg, ArgMatches, Command};

/// Assemble the `completion` subcommand.
pub fn new() -> Command {
Command::new("completion")
.about("Emit shell completion script")
.arg(
Arg::new("completion_shell")
.help("Shell completion script style")
.required(true)
.num_args(1)
.value_name("SHELL")
.value_parser([
PossibleValue::new("bash"),
PossibleValue::new("elvish"),
PossibleValue::new("fish"),
PossibleValue::new("powershell"),
PossibleValue::new("zsh"),
]),
)
}

/// Execute the `completion` subcommand.
pub fn run(matches: &ArgMatches, app: &mut Command) -> Result<()> {
let shell = matches.get_one::<String>("completion_shell").unwrap();
let shell = match shell.as_str() {
"bash" => clap_complete::Shell::Bash,
"elvish" => clap_complete::Shell::Elvish,
"fish" => clap_complete::Shell::Fish,
"powershell" => clap_complete::Shell::PowerShell,
"zsh" => clap_complete::Shell::Zsh,
_ => unreachable!(),
};
clap_complete::generate(shell, app, "bender", &mut io::stdout());
Ok(())
}
2 changes: 1 addition & 1 deletion src/cmd/fusesoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::target::TargetSpec;
/// Assemble the `fusesoc` subcommand.
pub fn new() -> Command {
Command::new("fusesoc")
.about("Creates a FuseSoC `.core` file for all dependencies where none is present.")
.about("Creates a FuseSoC `.core` file for all dependencies where none is present")
.arg(
Arg::new("single")
.long("single")
Expand Down
1 change: 1 addition & 0 deletions src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

pub mod checkout;
pub mod clone;
pub mod completion;
pub mod config;
pub mod fusesoc;
pub mod init;
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/packages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ pub fn new() -> Command {
.long("flat")
.num_args(0)
.action(ArgAction::SetTrue)
.help("Do not group packages by topological rank. If the `--graph` option is specified, print multiple lines per package, one for each dependency.")
.help("Do not group packages by topological rank")
.long_help("Do not group packages by topological rank. If the `--graph` option is specified, print multiple lines per package, one for each dependency.")
)
}

Expand Down
10 changes: 7 additions & 3 deletions src/cmd/vendor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ pub struct PatchLink {
pub fn new() -> Command {
Command::new("vendor")
.subcommand_required(true).arg_required_else_help(true)
.about("Copy source code from upstream external repositories into this repository. Functions similar to the lowrisc vendor.py script. Type bender vendor <SUBCOMMAND> --help for more information about the subcommands.")
.about("Copy source code from upstream external repositories into this repository")
.long_about("Copy source code from upstream external repositories into this repository. Functions similar to the lowrisc vendor.py script.")
.after_help("Type 'bender vendor <SUBCOMMAND> --help' for more information about a vendor subcommand.")
.subcommand(Command::new("diff")
.about("Display a diff of the local tree and the upstream tree with patches applied.")
.arg(
Expand All @@ -46,7 +48,8 @@ pub fn new() -> Command {
)
)
.subcommand(Command::new("init")
.about("(Re-)initialize the external dependencies. Copies the upstream files into the target directories and applies existing patches.")
.about("(Re-)initialize the external dependencies.")
.long_about("(Re-)initialize the external dependencies. Copies the upstream files into the target directories and applies existing patches.")
.arg(
Arg::new("no_patch")
.short('n')
Expand All @@ -61,7 +64,8 @@ pub fn new() -> Command {
Arg::new("plain")
.action(ArgAction::SetTrue)
.long("plain")
.help("Generate a plain diff instead of a format-patch. Includes all local changes (not only the staged ones)."),
.help("Generate a plain diff instead of a format-patch.")
.long_help("Generate a plain diff instead of a format-patch. Includes all local changes (not only the staged ones)."),
)
.arg(
Arg::new("message")
Expand Down

0 comments on commit 69c82e9

Please sign in to comment.