ok/jj
1
0
Fork 0
forked from mirrors/jj

completion: Add support for Nushell completions

This commit is contained in:
Alexis (Poliorcetics) Bourget 2024-02-16 21:23:41 +01:00 committed by Poliorcetics
parent b533cdc538
commit c75230747a
8 changed files with 94 additions and 12 deletions

View file

@ -57,6 +57,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `jj move --from/--to` can now be abbreviated to `jj move -f/-t` * `jj move --from/--to` can now be abbreviated to `jj move -f/-t`
* Added completions for [Nushell](https://nushell.sh) to `jj util completion`
### Fixed bugs ### Fixed bugs
* On Windows, symlinks in the repo are now materialized as regular files in the * On Windows, symlinks in the repo are now materialized as regular files in the

15
Cargo.lock generated
View file

@ -391,13 +391,23 @@ dependencies = [
[[package]] [[package]]
name = "clap_complete" name = "clap_complete"
version = "4.5.0" version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "299353be8209bd133b049bf1c63582d184a8b39fd9c04f15fe65f50f88bdfe6c" checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c"
dependencies = [ dependencies = [
"clap", "clap",
] ]
[[package]]
name = "clap_complete_nushell"
version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d0e48e026ce7df2040239117d25e4e79714907420c70294a5ce4b6bbe6a7b6"
dependencies = [
"clap",
"clap_complete",
]
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.0" version = "4.5.0"
@ -1603,6 +1613,7 @@ dependencies = [
"clap", "clap",
"clap-markdown", "clap-markdown",
"clap_complete", "clap_complete",
"clap_complete_nushell",
"clap_mangen", "clap_mangen",
"config", "config",
"criterion", "criterion",

View file

@ -31,7 +31,8 @@ clap = { version = "4.5.1", features = [
"wrap_help", "wrap_help",
"string", "string",
] } ] }
clap_complete = "4.5.0" clap_complete = "4.5.1"
clap_complete_nushell = "4.5.1"
clap-markdown = "0.1.3" clap-markdown = "0.1.3"
clap_mangen = "0.2.10" clap_mangen = "0.2.10"
chrono = { version = "0.4.34", default-features = false, features = [ chrono = { version = "0.4.34", default-features = false, features = [

View file

@ -38,6 +38,7 @@ chrono = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
clap-markdown = { workspace = true } clap-markdown = { workspace = true }
clap_complete = { workspace = true } clap_complete = { workspace = true }
clap_complete_nushell = { workspace = true }
clap_mangen = { workspace = true } clap_mangen = { workspace = true }
config = { workspace = true } config = { workspace = true }
criterion = { workspace = true, optional = true } criterion = { workspace = true, optional = true }

View file

@ -16,8 +16,7 @@ use std::io::Write;
use std::slice; use std::slice;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use clap::Subcommand; use clap::{Command, Subcommand};
use clap_complete::Shell;
use jj_lib::repo::Repo; use jj_lib::repo::Repo;
use tracing::instrument; use tracing::instrument;
@ -42,6 +41,11 @@ Apply it by running one of these:
- **bash**: `source <(jj util completion bash)` - **bash**: `source <(jj util completion bash)`
- **fish**: `jj util completion fish | source` - **fish**: `jj util completion fish | source`
- **nushell**:
```nu
jj util completion nushell | save "completions-jj.nu"
use "completions-jj.nu" * # Or `source "completions-jj.nu"`
```
- **zsh**: - **zsh**:
```shell ```shell
autoload -U compinit autoload -U compinit
@ -52,7 +56,7 @@ Apply it by running one of these:
#[derive(clap::Args, Clone, Debug)] #[derive(clap::Args, Clone, Debug)]
#[command(verbatim_doc_comment)] #[command(verbatim_doc_comment)]
pub(crate) struct UtilCompletionArgs { pub(crate) struct UtilCompletionArgs {
shell: Option<Shell>, shell: Option<ShellCompletion>,
/// Deprecated. Use the SHELL positional argument instead. /// Deprecated. Use the SHELL positional argument instead.
#[arg(long, hide = true)] #[arg(long, hide = true)]
bash: bool, bash: bool,
@ -91,6 +95,17 @@ pub(crate) struct UtilMarkdownHelp {}
#[derive(clap::Args, Clone, Debug)] #[derive(clap::Args, Clone, Debug)]
pub(crate) struct UtilConfigSchemaArgs {} pub(crate) struct UtilConfigSchemaArgs {}
/// Available shell completions
#[derive(clap::ValueEnum, Clone, Copy, Debug, Eq, Hash, PartialEq)]
enum ShellCompletion {
Bash,
Elvish,
Fish,
Nushell,
PowerShell,
Zsh,
}
#[instrument(skip_all)] #[instrument(skip_all)]
pub(crate) fn cmd_util( pub(crate) fn cmd_util(
ui: &mut Ui, ui: &mut Ui,
@ -120,22 +135,21 @@ fn cmd_util_completion(
)?; )?;
writeln!(ui.hint(), "Hint: Use `jj util completion {shell}` instead") writeln!(ui.hint(), "Hint: Use `jj util completion {shell}` instead")
}; };
let mut buf = vec![];
let shell = match (args.shell, args.fish, args.zsh, args.bash) { let shell = match (args.shell, args.fish, args.zsh, args.bash) {
(Some(s), false, false, false) => s, (Some(s), false, false, false) => s,
// allow `--fish` and `--zsh` for back-compat, but don't allow them to be combined // allow `--fish` and `--zsh` for back-compat, but don't allow them to be combined
(None, true, false, false) => { (None, true, false, false) => {
warn("fish")?; warn("fish")?;
Shell::Fish ShellCompletion::Fish
} }
(None, false, true, false) => { (None, false, true, false) => {
warn("zsh")?; warn("zsh")?;
Shell::Zsh ShellCompletion::Zsh
} }
// default to bash for back-compat. TODO: consider making `shell` a required argument // default to bash for back-compat. TODO: consider making `shell` a required argument
(None, false, false, _) => { (None, false, false, _) => {
warn("bash")?; warn("bash")?;
Shell::Bash ShellCompletion::Bash
} }
_ => { _ => {
return Err(user_error( return Err(user_error(
@ -143,7 +157,8 @@ fn cmd_util_completion(
)) ))
} }
}; };
clap_complete::generate(shell, &mut app, "jj", &mut buf);
let buf = shell.generate(&mut app);
ui.stdout_formatter().write_all(&buf)?; ui.stdout_formatter().write_all(&buf)?;
Ok(()) Ok(())
} }
@ -206,3 +221,25 @@ fn cmd_util_config_schema(
ui.stdout_formatter().write_all(buf)?; ui.stdout_formatter().write_all(buf)?;
Ok(()) Ok(())
} }
impl ShellCompletion {
fn generate(&self, cmd: &mut Command) -> Vec<u8> {
use clap_complete::{generate, Shell};
use clap_complete_nushell::Nushell;
let mut buf = Vec::new();
let bin_name = "jj";
match self {
Self::Bash => generate(Shell::Bash, cmd, bin_name, &mut buf),
Self::Elvish => generate(Shell::Elvish, cmd, bin_name, &mut buf),
Self::Fish => generate(Shell::Fish, cmd, bin_name, &mut buf),
Self::Nushell => generate(Nushell, cmd, bin_name, &mut buf),
Self::PowerShell => generate(Shell::PowerShell, cmd, bin_name, &mut buf),
Self::Zsh => generate(Shell::Zsh, cmd, bin_name, &mut buf),
}
buf
}
}

View file

@ -1742,6 +1742,11 @@ Apply it by running one of these:
- **bash**: `source <(jj util completion bash)` - **bash**: `source <(jj util completion bash)`
- **fish**: `jj util completion fish | source` - **fish**: `jj util completion fish | source`
- **nushell**:
```nu
jj util completion nushell | save "completions-jj.nu"
use "completions-jj.nu" * # Or `source "completions-jj.nu"`
```
- **zsh**: - **zsh**:
```shell ```shell
autoload -U compinit autoload -U compinit
@ -1755,7 +1760,7 @@ Apply it by running one of these:
* `<SHELL>` * `<SHELL>`
Possible values: `bash`, `elvish`, `fish`, `powershell`, `zsh` Possible values: `bash`, `elvish`, `fish`, `nushell`, `power-shell`, `zsh`
###### **Options:** ###### **Options:**

View file

@ -92,3 +92,21 @@ fn test_gc_operation_log() {
Error: No operation ID matching "f9400b5274c6f1cfa23afbc1956349897a6975116135a59ab19d941119cc9fad93d9668b8c7d913fbd68c543dcba40a8d44135a53996a9e8ea92d4b78ef52cb6" Error: No operation ID matching "f9400b5274c6f1cfa23afbc1956349897a6975116135a59ab19d941119cc9fad93d9668b8c7d913fbd68c543dcba40a8d44135a53996a9e8ea92d4b78ef52cb6"
"###); "###);
} }
#[test]
fn test_shell_completions() {
#[track_caller]
fn test(shell: &str) {
let test_env = TestEnvironment::default();
// Use the local backend because GitBackend::gc() depends on the git CLI.
let (out, err) = test_env.jj_cmd_ok(test_env.env_root(), &["util", "completion", shell]);
// Ensures only stdout contains text
assert!(!out.is_empty());
assert!(err.is_empty());
}
test("bash");
test("fish");
test("nushell");
test("zsh");
}

View file

@ -179,6 +179,13 @@ source <(jj util completion zsh)
jj util completion fish | source jj util completion fish | source
``` ```
### Nushell
```nu
jj util completion nushell | save completions-jj.nu
use completions-jj.nu * # Or `source completions-jj.nu`
```
### Xonsh ### Xonsh
```shell ```shell