Skip to content

Commit

Permalink
completion: Add support for Nushell completions
Browse files Browse the repository at this point in the history
  • Loading branch information
poliorcetics committed Feb 16, 2024
1 parent 7cba089 commit febb8dc
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#2971](https://github.com/martinvonz/jj/issues/2971)). This may become the
default depending on feedback.

* Added completions for [Nushell](https://nushell.sh) to `jj util completion`

### Fixed bugs

* On Windows, symlinks in the repo are now materialized as regular files in the
Expand Down
11 changes: 11 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 @@ -32,6 +32,7 @@ clap = { version = "4.5.1", features = [
"string",
] }
clap_complete = "4.5.0"
clap_complete_nushell = "4.5.0"
clap-markdown = "0.1.3"
clap_mangen = "0.2.10"
chrono = { version = "0.4.34", default-features = false, features = [
Expand Down
1 change: 1 addition & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ chrono = { workspace = true }
clap = { workspace = true }
clap-markdown = { workspace = true }
clap_complete = { workspace = true }
clap_complete_nushell = { workspace = true }
clap_mangen = { workspace = true }
config = { workspace = true }
criterion = { workspace = true, optional = true }
Expand Down
53 changes: 45 additions & 8 deletions cli/src/commands/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ use std::io::Write;
use std::slice;
use std::time::{Duration, SystemTime};

use clap::Subcommand;
use clap_complete::Shell;
use clap::{Command, Subcommand};
use jj_lib::repo::Repo;
use tracing::instrument;

Expand All @@ -42,6 +41,11 @@ Apply it by running one of these:
- **bash**: `source <(jj util completion bash)`
- **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**:
```shell
autoload -U compinit
Expand All @@ -52,7 +56,7 @@ Apply it by running one of these:
#[derive(clap::Args, Clone, Debug)]
#[command(verbatim_doc_comment)]
pub(crate) struct UtilCompletionArgs {
shell: Option<Shell>,
shell: Option<ShellCompletion>,
/// Deprecated. Use the SHELL positional argument instead.
#[arg(long, hide = true)]
bash: bool,
Expand Down Expand Up @@ -91,6 +95,17 @@ pub(crate) struct UtilMarkdownHelp {}
#[derive(clap::Args, Clone, Debug)]
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)]
pub(crate) fn cmd_util(
ui: &mut Ui,
Expand Down Expand Up @@ -120,30 +135,30 @@ fn cmd_util_completion(
)?;
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) {
(Some(s), false, false, false) => s,
// allow `--fish` and `--zsh` for back-compat, but don't allow them to be combined
(None, true, false, false) => {
warn("fish")?;
Shell::Fish
ShellCompletion::Fish
}
(None, false, true, false) => {
warn("zsh")?;
Shell::Zsh
ShellCompletion::Zsh
}
// default to bash for back-compat. TODO: consider making `shell` a required argument
(None, false, false, _) => {
warn("bash")?;
Shell::Bash
ShellCompletion::Bash
}
_ => {
return Err(user_error(
"cannot generate completion for multiple shells at once",
))
}
};
clap_complete::generate(shell, &mut app, "jj", &mut buf);

let buf = shell.generate(&mut app);
ui.stdout_formatter().write_all(&buf)?;
Ok(())
}
Expand Down Expand Up @@ -206,3 +221,25 @@ fn cmd_util_config_schema(
ui.stdout_formatter().write_all(buf)?;
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
}
}
7 changes: 6 additions & 1 deletion cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,11 @@ Apply it by running one of these:
- **bash**: `source <(jj util completion bash)`
- **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**:
```shell
autoload -U compinit
Expand All @@ -1755,7 +1760,7 @@ Apply it by running one of these:
* `<SHELL>`
Possible values: `bash`, `elvish`, `fish`, `powershell`, `zsh`
Possible values: `bash`, `elvish`, `fish`, `nushell`, `power-shell`, `zsh`
###### **Options:**
Expand Down
18 changes: 18 additions & 0 deletions cli/tests/test_util_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,21 @@ fn test_gc_operation_log() {
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");
}
7 changes: 7 additions & 0 deletions docs/install-and-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ source <(jj util completion zsh)
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

```shell
Expand Down

0 comments on commit febb8dc

Please sign in to comment.