Skip to content

Commit

Permalink
completion: resolve aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
senekor committed Nov 11, 2024
1 parent bfbd04b commit 325402d
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 10 deletions.
42 changes: 32 additions & 10 deletions cli/src/cli_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3060,6 +3060,34 @@ fn handle_early_args(
Ok(())
}

fn handle_shell_completion(
ui: &Ui,
app: &Command,
config: &config::Config,
cwd: &Path,
) -> Result<(), CommandError> {
let mut args = vec![];
// Take the first two arguments as is, they must be passed to clap_complete
// without any changes. They are usually "jj --".
args.extend(env::args_os().take(2));

if env::args_os().nth(2).is_some() {
// Make sure aliases are expanded before passing them to
// clap_complete. We skip the first two args ("jj" and "--") for
// alias resolution, then we stitch the args back together, like
// clap_complete expects them.
let resolved_aliases = expand_args(ui, app, env::args_os().skip(2), config)?;
args.extend(resolved_aliases.into_iter().map(OsString::from));
}
let ran_completion = clap_complete::CompleteEnv::with_factory(|| app.clone())
.try_complete(args.iter(), Some(cwd))?;
assert!(
ran_completion,
"This function should not be called without the COMPLETE variable set."
);
Ok(())
}

pub fn expand_args(
ui: &Ui,
app: &Command,
Expand Down Expand Up @@ -3316,6 +3344,10 @@ impl CliRunner {
e.hinted(format!("Check the following config files:\n{paths}"))
})?;

if env::var_os("COMPLETE").is_some() {
return handle_shell_completion(ui, &self.app, &config, &cwd);
}

let string_args = expand_args(ui, &self.app, env::args_os(), &config)?;
let (matches, args) = parse_args(
ui,
Expand Down Expand Up @@ -3385,16 +3417,6 @@ impl CliRunner {
#[must_use]
#[instrument(skip(self))]
pub fn run(mut self) -> ExitCode {
match clap_complete::CompleteEnv::with_factory(|| self.app.clone())
.try_complete(env::args_os(), None)
{
Ok(true) => return ExitCode::SUCCESS,
Err(e) => {
eprintln!("failed to generate completions: {e}");
return ExitCode::FAILURE;
}
Ok(false) => {}
};
let builder = config::Config::builder().add_source(crate::config::default_config());
let config = self
.extra_configs
Expand Down
39 changes: 39 additions & 0 deletions cli/tests/test_completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,42 @@ fn test_global_arg_repository_is_respected() {
);
insta::assert_snapshot!(stdout, @"aaa");
}

#[test]
fn test_aliases_are_resolved() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");

test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "aaa"]);

// user config alias
test_env.add_config(r#"aliases.b = ["bookmark"]"#);
// repo config alias
test_env.jj_cmd_ok(
&repo_path,
&["config", "set", "--repo", "aliases.b2", "['bookmark']"],
);

let mut test_env = test_env;
test_env.add_env_var("COMPLETE", "fish");
let test_env = test_env;

let stdout = test_env.jj_cmd_success(&repo_path, &["--", "jj", "b", "rename", "a"]);
insta::assert_snapshot!(stdout, @"aaa");

let stdout = test_env.jj_cmd_success(&repo_path, &["--", "jj", "b2", "rename", "a"]);
insta::assert_snapshot!(stdout, @"aaa");
}

#[test]
fn test_completions_are_generated() {
let mut test_env = TestEnvironment::default();
test_env.add_env_var("COMPLETE", "fish");
let stdout = test_env.jj_cmd_success(test_env.env_root(), &[]);
// cannot use assert_snapshot!, output contains path to binary that depends
// on environment
assert!(stdout.starts_with("complete --keep-order --exclusive --command jj --arguments"));
let stdout = test_env.jj_cmd_success(test_env.env_root(), &["--"]);
assert!(stdout.starts_with("complete --keep-order --exclusive --command jj --arguments"));
}

0 comments on commit 325402d

Please sign in to comment.