Skip to content

Commit 7100091

Browse files
authored
Merge pull request #5765 from epage/complete
refactor(complete): Better separate concerns
2 parents f40b37f + e90b2da commit 7100091

File tree

1 file changed

+57
-39
lines changed

1 file changed

+57
-39
lines changed

clap_complete/src/env/mod.rs

+57-39
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub struct CompleteEnv<'s, F> {
9696
shells: Shells<'s>,
9797
}
9898

99-
impl<'s, F: FnOnce() -> clap::Command> CompleteEnv<'s, F> {
99+
impl<'s, F: Fn() -> clap::Command> CompleteEnv<'s, F> {
100100
/// Complete a [`clap::Command`]
101101
///
102102
/// # Example
@@ -174,7 +174,7 @@ impl<'s, F: FnOnce() -> clap::Command> CompleteEnv<'s, F> {
174174
}
175175
}
176176

177-
impl<'s, F: FnOnce() -> clap::Command> CompleteEnv<'s, F> {
177+
impl<'s, F: Fn() -> clap::Command> CompleteEnv<'s, F> {
178178
/// Process the completion request and exit
179179
///
180180
/// **Warning:** `stdout` should not be written to before this has had a
@@ -217,8 +217,34 @@ impl<'s, F: FnOnce() -> clap::Command> CompleteEnv<'s, F> {
217217
// completion logic.
218218
std::env::remove_var(self.var);
219219

220+
let shell = self.shell(std::path::Path::new(&name))?;
221+
222+
let mut cmd = (self.factory)();
223+
cmd.build();
224+
225+
let completer = args.remove(0);
226+
let escape_index = args
227+
.iter()
228+
.position(|a| *a == "--")
229+
.map(|i| i + 1)
230+
.unwrap_or(args.len());
231+
args.drain(0..escape_index);
232+
if args.is_empty() {
233+
let mut buf = Vec::new();
234+
self.write_registration(&cmd, current_dir, shell, completer, &mut buf)?;
235+
std::io::stdout().write_all(&buf)?;
236+
} else {
237+
let mut buf = Vec::new();
238+
shell.write_complete(&mut cmd, args, current_dir, &mut buf)?;
239+
std::io::stdout().write_all(&buf)?;
240+
}
241+
242+
Ok(true)
243+
}
244+
245+
fn shell(&self, name: &std::path::Path) -> Result<&dyn EnvCompleter, std::io::Error> {
220246
// Strip off the parent dir in case `$SHELL` was used
221-
let name = std::path::Path::new(&name).file_stem().unwrap_or(&name);
247+
let name = name.file_stem().unwrap_or(name.as_os_str());
222248
// lossy won't match but this will delegate to unknown
223249
// error
224250
let name = name.to_string_lossy();
@@ -238,46 +264,38 @@ impl<'s, F: FnOnce() -> clap::Command> CompleteEnv<'s, F> {
238264
format!("unknown shell `{name}`, expected one of {shells}"),
239265
)
240266
})?;
267+
Ok(shell)
268+
}
241269

242-
let mut cmd = (self.factory)();
243-
cmd.build();
244-
245-
let completer = args.remove(0);
246-
let escape_index = args
247-
.iter()
248-
.position(|a| *a == "--")
249-
.map(|i| i + 1)
250-
.unwrap_or(args.len());
251-
args.drain(0..escape_index);
252-
if args.is_empty() {
253-
let name = cmd.get_name();
254-
let bin = self
255-
.bin
256-
.as_deref()
257-
.or_else(|| cmd.get_bin_name())
258-
.unwrap_or_else(|| cmd.get_name());
259-
let completer = if let Some(completer) = self.completer.as_deref() {
260-
completer.to_owned()
261-
} else {
262-
let mut completer = std::path::PathBuf::from(completer);
263-
if let Some(current_dir) = current_dir {
264-
if 1 < completer.components().count() {
265-
completer = current_dir.join(completer);
266-
}
270+
fn write_registration(
271+
&self,
272+
cmd: &clap::Command,
273+
current_dir: Option<&std::path::Path>,
274+
shell: &dyn EnvCompleter,
275+
completer: OsString,
276+
buf: &mut dyn std::io::Write,
277+
) -> Result<(), std::io::Error> {
278+
let name = cmd.get_name();
279+
let bin = self
280+
.bin
281+
.as_deref()
282+
.or_else(|| cmd.get_bin_name())
283+
.unwrap_or_else(|| cmd.get_name());
284+
let completer = if let Some(completer) = self.completer.as_deref() {
285+
completer.to_owned()
286+
} else {
287+
let mut completer = std::path::PathBuf::from(completer);
288+
if let Some(current_dir) = current_dir {
289+
if 1 < completer.components().count() {
290+
completer = current_dir.join(completer);
267291
}
268-
completer.to_string_lossy().into_owned()
269-
};
292+
}
293+
completer.to_string_lossy().into_owned()
294+
};
270295

271-
let mut buf = Vec::new();
272-
shell.write_registration(self.var, name, bin, &completer, &mut buf)?;
273-
std::io::stdout().write_all(&buf)?;
274-
} else {
275-
let mut buf = Vec::new();
276-
shell.write_complete(&mut cmd, args, current_dir, &mut buf)?;
277-
std::io::stdout().write_all(&buf)?;
278-
}
296+
shell.write_registration(self.var, name, bin, &completer, buf)?;
279297

280-
Ok(true)
298+
Ok(())
281299
}
282300
}
283301

0 commit comments

Comments
 (0)