diff --git a/cli/src/complete.rs b/cli/src/complete.rs index 56d7e87231..944b6080fb 100644 --- a/cli/src/complete.rs +++ b/cli/src/complete.rs @@ -55,8 +55,9 @@ fn split_help_text(line: &str) -> (&str, Option) { } pub fn local_bookmarks() -> Vec { - with_jj(|mut jj, _| { + with_jj(|jj, _| { let output = jj + .build() .arg("bookmark") .arg("list") .arg("--config-toml") @@ -75,8 +76,9 @@ pub fn local_bookmarks() -> Vec { } pub fn tracked_bookmarks() -> Vec { - with_jj(|mut jj, _| { + with_jj(|jj, _| { let output = jj + .build() .arg("bookmark") .arg("list") .arg("--tracked") @@ -96,8 +98,9 @@ pub fn tracked_bookmarks() -> Vec { } pub fn untracked_bookmarks() -> Vec { - with_jj(|mut jj, config| { + with_jj(|jj, config| { let output = jj + .build() .arg("bookmark") .arg("list") .arg("--all-remotes") @@ -133,8 +136,9 @@ pub fn untracked_bookmarks() -> Vec { } pub fn bookmarks() -> Vec { - with_jj(|mut jj, config| { + with_jj(|jj, config| { let output = jj + .build() .arg("bookmark") .arg("list") .arg("--all-remotes") @@ -177,8 +181,9 @@ pub fn bookmarks() -> Vec { } pub fn git_remotes() -> Vec { - with_jj(|mut jj, _| { + with_jj(|jj, _| { let output = jj + .build() .arg("git") .arg("remote") .arg("list") @@ -211,8 +216,9 @@ pub fn aliases() -> Vec { } fn revisions(revisions: &str) -> Vec { - with_jj(|mut jj, _| { + with_jj(|jj, _| { let output = jj + .build() .arg("log") .arg("--no-graph") .arg("--limit") @@ -244,8 +250,9 @@ pub fn all_revisions() -> Vec { } pub fn operations() -> Vec { - with_jj(|mut jj, _| { + with_jj(|jj, _| { let output = jj + .build() .arg("operation") .arg("log") .arg("--no-graph") @@ -274,8 +281,9 @@ pub fn operations() -> Vec { } pub fn workspaces() -> Vec { - with_jj(|mut jj, _| { + with_jj(|jj, _| { let output = jj + .build() .arg("--config-toml") .arg(r#"templates.commit_summary = 'if(description, description.first_line(), "(no description set)")'"#) .arg("workspace") @@ -359,7 +367,7 @@ pub fn leaf_config_keys() -> Vec { /// In case of errors, print them and early return an empty vector. fn with_jj(completion_fn: F) -> Vec where - F: FnOnce(std::process::Command, &Config) -> Result, CommandError>, + F: FnOnce(JjBuilder, &Config) -> Result, CommandError>, { get_jj_command() .and_then(|(jj, config)| completion_fn(jj, &config)) @@ -378,7 +386,7 @@ where /// give completion code access to custom backends. Shelling out was chosen as /// the preferred method, because it's more maintainable and the performance /// requirements of completions aren't very high. -fn get_jj_command() -> Result<(std::process::Command, Config), CommandError> { +fn get_jj_command() -> Result<(JjBuilder, Config), CommandError> { let current_exe = std::env::current_exe().map_err(user_error)?; let mut cmd_args = Vec::::new(); @@ -459,10 +467,27 @@ fn get_jj_command() -> Result<(std::process::Command, Config), CommandError> { cmd_args.push(config_toml); } - let mut cmd = std::process::Command::new(current_exe); - cmd.args(&cmd_args); + let builder = JjBuilder { + cmd: current_exe, + args: cmd_args, + }; - Ok((cmd, config)) + Ok((builder, config)) +} + +/// A helper struct to allow completion functions to call jj multiple times with +/// different arguments. +struct JjBuilder { + cmd: std::path::PathBuf, + args: Vec, +} + +impl JjBuilder { + fn build(&self) -> std::process::Command { + let mut cmd = std::process::Command::new(&self.cmd); + cmd.args(&self.args); + cmd + } } #[cfg(test)]