Skip to content

Commit

Permalink
cli: Rework completion error handling
Browse files Browse the repository at this point in the history
Moves the error reporting from the completion function to the standard
error handling mechanism.

CompletionCommand had to be made fully public, not that this matters for
a binary target. That said, this could have been prevented by
transforming the CompletionCommand into its String form at the error
site rather than at the reporting site. It was chosen to go with this
method as stringly-typed interfaces are generally bad.
  • Loading branch information
yodaldevoid committed Mar 30, 2019
1 parent 02d63fc commit 8a189fa
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 19 deletions.
7 changes: 7 additions & 0 deletions src/cli/errors.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#![allow(dead_code)]

use crate::rustup_mode::CompletionCommand;

use std::io;
use std::path::PathBuf;

use clap::Shell;
use error_chain::error_chain;
use error_chain::error_chain_processing;
use error_chain::{impl_error_chain_kind, impl_error_chain_processed, impl_extract_backtrace};
Expand Down Expand Up @@ -46,5 +49,9 @@ error_chain! {
WindowsUninstallMadness {
description("failure during windows uninstall")
}
UnsupportedCompletionShell(shell: Shell, cmd: CompletionCommand) {
description("completion script for shell not yet supported for tool")
display("{} does not currently support completions for {}", cmd, shell)
}
}
}
49 changes: 30 additions & 19 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rustup::dist::manifest::Component;
use rustup::utils::utils::{self, ExitCode};
use rustup::{command, Cfg, Toolchain};
use std::error::Error;
use std::fmt;
use std::io::Write;
use std::iter;
use std::path::Path;
Expand Down Expand Up @@ -1111,8 +1112,8 @@ fn set_default_host_triple(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> {
Ok(())
}

#[derive(Copy, Clone, Debug)]
enum CompletionCommand {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CompletionCommand {
Rustup,
Cargo,
}
Expand All @@ -1138,7 +1139,25 @@ impl FromStr for CompletionCommand {
.next()
{
Some(&(_, cmd)) => Ok(cmd),
None => Err(String::from("[valid values: rustup, cargo]")),
None => {
let completion_options = COMPLETIONS
.iter()
.map(|&(v, _)| v)
.fold("".to_owned(), |s, v| format!("{}{}, ", s, v));
Err(format!(
"[valid values: {}]",
completion_options.trim_end_matches(", ")
))
}
}
}
}

impl fmt::Display for CompletionCommand {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match COMPLETIONS.iter().filter(|&(_, cmd)| cmd == self).next() {
Some(&(val, _)) => write!(f, "{}", val),
None => unreachable!(),
}
}
}
Expand All @@ -1150,24 +1169,16 @@ fn output_completion_script(shell: Shell, command: CompletionCommand) -> Result<
}
CompletionCommand::Cargo => {
let script = match shell {
Shell::Bash => Some("/etc/bash_completion.d/cargo"),
Shell::Zsh => Some("/share/zsh/site-functions/_cargo"),
_ => None,
Shell::Bash => "/etc/bash_completion.d/cargo",
Shell::Zsh => "/share/zsh/site-functions/_cargo",
_ => return Err(ErrorKind::UnsupportedCompletionShell(shell, command).into()),
};

if let Some(script) = script {
writeln!(
&mut term2::stdout(),
"source $(rustc --print sysroot){}",
script,
)?;
} else {
writeln!(
&mut term2::stderr(),
"Cargo does not currently support completions for {}.",
shell,
)?;
}
writeln!(
&mut term2::stdout(),
"source $(rustc --print sysroot){}",
script,
)?;
}
}

Expand Down

0 comments on commit 8a189fa

Please sign in to comment.