forked from mirrors/jj
cli: use a positional argument for jj util completion
this has two main advantages: - it makes it clear that the shells are mutually exclusive - it allows us to extend the command with shell-specific options in the future if necessary as a happy accident, it also adds support for `elvish` and `powershell`. for backwards compatibility, this also keeps the existing options as hidden flags. i am not super happy with how the new help looks; the instructions for setting up the shell are squished together and IMO a little harder to read. i'm open to suggestions.
This commit is contained in:
parent
0773cefe32
commit
0f2715203f
4 changed files with 100 additions and 30 deletions
|
@ -39,8 +39,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
of `R` for "Removed". @joyously pointed out that `R` could also mean
|
||||
"Renamed".
|
||||
|
||||
* `jj util completion` now takes the shell as a positional argument, not a flag.
|
||||
the previous behavior is deprecated, but supported for now. it will be removed
|
||||
in the future.
|
||||
|
||||
### New features
|
||||
|
||||
* `jj util completion` now supports powershell and elvish.
|
||||
|
||||
* Official binaries for macOS running on Apple Silicon (`aarch64-apple-darwin`)
|
||||
are now available, alongside the existing macOS x86 binaries.
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ use std::slice;
|
|||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use clap::Subcommand;
|
||||
use clap_complete::Shell;
|
||||
use jj_lib::repo::Repo;
|
||||
use tracing::instrument;
|
||||
|
||||
|
@ -34,30 +35,26 @@ pub(crate) enum UtilCommand {
|
|||
}
|
||||
|
||||
/// Print a command-line-completion script
|
||||
///
|
||||
/// Apply it by running this:
|
||||
/// bash: source <(jj util completion)
|
||||
/// fish: jj util completion --fish | source
|
||||
/// zsh:
|
||||
/// autoload -U compinit
|
||||
/// compinit
|
||||
/// source <(jj util completion --zsh)
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
#[command(verbatim_doc_comment)]
|
||||
pub(crate) struct UtilCompletionArgs {
|
||||
/// Print a completion script for Bash (default)
|
||||
///
|
||||
/// Apply it by running this:
|
||||
///
|
||||
/// source <(jj util completion)
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
shell: Option<Shell>,
|
||||
/// Deprecated. Use the SHELL positional argument instead.
|
||||
#[arg(long, hide = true)]
|
||||
bash: bool,
|
||||
/// Print a completion script for Fish
|
||||
///
|
||||
/// Apply it by running this:
|
||||
///
|
||||
/// jj util completion --fish | source
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
/// Deprecated. Use the SHELL positional argument instead.
|
||||
#[arg(long, hide = true)]
|
||||
fish: bool,
|
||||
/// Print a completion script for Zsh
|
||||
///
|
||||
/// Apply it by running this:
|
||||
///
|
||||
/// autoload -U compinit
|
||||
/// compinit
|
||||
/// source <(jj util completion --zsh)
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
/// Deprecated. Use the SHELL positional argument instead.
|
||||
#[arg(long, hide = true)]
|
||||
zsh: bool,
|
||||
}
|
||||
|
||||
|
@ -109,13 +106,35 @@ fn cmd_util_completion(
|
|||
args: &UtilCompletionArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut app = command.app().clone();
|
||||
let warn = |shell| {
|
||||
writeln!(
|
||||
ui.warning(),
|
||||
"warning: `jj util completion --{shell}` will be removed in a future version, and \
|
||||
this will be a hard error"
|
||||
)
|
||||
};
|
||||
let mut buf = vec![];
|
||||
let shell = if args.zsh {
|
||||
clap_complete::Shell::Zsh
|
||||
} else if args.fish {
|
||||
clap_complete::Shell::Fish
|
||||
} else {
|
||||
clap_complete::Shell::Bash
|
||||
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
|
||||
}
|
||||
(None, false, true, false) => {
|
||||
warn("zsh")?;
|
||||
Shell::Zsh
|
||||
}
|
||||
// default to bash for back-compat. TODO: consider making `shell` a required argument
|
||||
(None, false, false, _) => {
|
||||
warn("bash")?;
|
||||
Shell::Bash
|
||||
}
|
||||
_ => {
|
||||
return Err(user_error(
|
||||
"cannot generate completion for multiple shells at once",
|
||||
))
|
||||
}
|
||||
};
|
||||
clap_complete::generate(shell, &mut app, "jj", &mut buf);
|
||||
ui.stdout_formatter().write_all(&buf)?;
|
||||
|
|
|
@ -1708,19 +1708,34 @@ Infrequently used commands such as for generating shell completions
|
|||
|
||||
Print a command-line-completion script
|
||||
|
||||
**Usage:** `jj util completion [OPTIONS]`
|
||||
Apply it by running this:
|
||||
bash: source <(jj util completion)
|
||||
fish: jj util completion --fish | source
|
||||
zsh:
|
||||
autoload -U compinit
|
||||
compinit
|
||||
source <(jj util completion --zsh)
|
||||
|
||||
**Usage:** `jj util completion [SHELL]`
|
||||
|
||||
###### **Arguments:**
|
||||
|
||||
* `<SHELL>`
|
||||
|
||||
Possible values: `bash`, `elvish`, `fish`, `powershell`, `zsh`
|
||||
|
||||
|
||||
###### **Options:**
|
||||
|
||||
* `--bash` — Print a completion script for Bash (default)
|
||||
* `--bash` — Deprecated. Use the SHELL positional argument instead
|
||||
|
||||
Possible values: `true`, `false`
|
||||
|
||||
* `--fish` — Print a completion script for Fish
|
||||
* `--fish` — Deprecated. Use the SHELL positional argument instead
|
||||
|
||||
Possible values: `true`, `false`
|
||||
|
||||
* `--zsh` — Print a completion script for Zsh
|
||||
* `--zsh` — Deprecated. Use the SHELL positional argument instead
|
||||
|
||||
Possible values: `true`, `false`
|
||||
|
||||
|
|
30
cli/tests/test_shell_completion.rs
Normal file
30
cli/tests/test_shell_completion.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024 The Jujutsu Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::common::TestEnvironment;
|
||||
|
||||
pub mod common;
|
||||
|
||||
#[test]
|
||||
fn test_deprecated_flags() {
|
||||
let test_env = TestEnvironment::default();
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["util", "completion", "--bash"]);
|
||||
assert_eq!(
|
||||
stderr,
|
||||
"warning: `jj util completion --bash` will be removed in a future version, and this will \
|
||||
be a hard error\n"
|
||||
);
|
||||
assert!(stdout.contains("COMPREPLY"));
|
||||
}
|
Loading…
Reference in a new issue