From 3be232000f1a6cf166de2b37db1e8f1f231e2799 Mon Sep 17 00:00:00 2001 From: Kevin K Date: Sun, 23 Oct 2016 19:51:11 -0400 Subject: [PATCH] Add command line completion support This commit adds two sections to the command line options to enable building of Shell Completion Scripts to `stdout`. This allows these scripts to be redirected to a file, effectively allowing the user to install these scripts at the location of their choosing. The arguments only accept the values `zsh`, `fish` and `bash`, which clap guards against. To use these scripts one must do one of the following *Note:* The commands `rustup completions ` and `rustup self --completions ` are synonyms for each other, and do the exact same thing. ``` $ rustup completions bash > /path/to/completions/dir/rustup.bash-completion ``` ``` $ rustup completions fish > ~/.config/fish/completions/rustup.fish ``` ``` $ mkdir ~/.zfunc $ rustup completions zsh > ~/.zfunc/_rustup $ echo "fpath+=~/.zfunc\ncominit" >> ~/.zshrc $ exec zsh ``` Relates to #278 --- src/rustup-cli/help.rs | 72 +++++++++++++++++++++++++++++++++++ src/rustup-cli/rustup_mode.rs | 29 ++++++++++++-- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/rustup-cli/help.rs b/src/rustup-cli/help.rs index dcb8be4818b..53b9b9baf1f 100644 --- a/src/rustup-cli/help.rs +++ b/src/rustup-cli/help.rs @@ -131,3 +131,75 @@ default browser. By default, it opens the documentation index. Use the various flags to open specific pieces of documentation."; + +pub static COMPLETIONS_HELP: &'static str = +r" +One can generate a completion script for `rustup` that is compatible with +a given shell. The script is output on `stdout` allowing one to re-direct +the output to the file of their choosing. Where you place the file will +depend on which shell, and which operating system you are using. Your +particular configuration may also determine where these scripts need +to be placed. + +Here are some common set ups for the three supported shells under +Unix and similar operating systems (such as GNU/Linux). + +*Note:* the commands `rustup compeltions ` and +`rustup self --completions ` are synonyms for each other and +interchangeable. + +BASH: + +Completion files are commonly stored in `/etc/bash_completion.d/` + +Run the command: + +`rustup completions bash > /etc/bash_completion.d/rustup.bash-completion` + +This installs the completion script. You may have to log out and log +back in to your shell session for the changes to take affect. + +FISH: + +Fish completion files are commonly stored in +`$HOME/.config/fish/completions` + +Run the command: +`rustup completions fish > ~/.config/fish/completions/rustup.fish` + +This installs the completion script. You may have to log out and log +back in to your shell session for the changes to take affect. + +ZSH: + +ZSH completions are commonly stored in any directory listed in your +`$fpath` variable. To use these completions, you must either add the +generated script to one of those directories, or add your own +to this list. + +Adding a custom directory is often the safest best if you're unsure +of which directory to use. First create the directory, for this +example we'll create a hidden directory inside our `$HOME` directory + +`mkdir ~/.zfunc` + +Then add the following lines to your `.zshrc` just before `compinit` + +`fpath+=~/.zfunc` + +Now you can install the completions script using the following command + +`rustup completions zsh > ~/.zfunc/_rustup` + +You must then either log out and log back in, or simply run + +`exec zsh` + +For the new completions to take affect. + +CUSTOM LOCATIONS: + +Alternatively, you could save these files to the place of your choosing, +such as a custom directory inside your $HOME. Doing so will require you +to add the proper directives, such as `source`ing inside your login +script. Consult your shells documentation for how to add such directives."; diff --git a/src/rustup-cli/rustup_mode.rs b/src/rustup-cli/rustup_mode.rs index 6ba71161aa5..7337d8bd374 100644 --- a/src/rustup-cli/rustup_mode.rs +++ b/src/rustup-cli/rustup_mode.rs @@ -1,4 +1,4 @@ -use clap::{App, Arg, ArgGroup, AppSettings, SubCommand, ArgMatches}; +use clap::{App, Arg, ArgGroup, AppSettings, SubCommand, ArgMatches, Shell}; use common; use rustup::{Cfg, Toolchain, command}; use rustup::settings::TelemetryMode; @@ -11,7 +11,7 @@ use std::path::Path; use std::process::Command; use std::iter; use term2; -use std::io::Write; +use std::io::{self, Write}; use help::*; pub fn main() -> Result<()> { @@ -80,6 +80,10 @@ pub fn main() -> Result<()> { ("doc", Some(m)) => try!(doc(cfg, m)), ("man", Some(m)) => try!(man(cfg,m)), ("self", Some(c)) => { + if let Some(shell) = c.value_of("completions") { + cli().gen_completions_to("rustup", shell.parse::().unwrap(), &mut io::stdout()); + return Ok(()); + } match c.subcommand() { ("update", Some(_)) => try!(self_update::update()), ("uninstall", Some(m)) => try!(self_uninstall(m)), @@ -100,6 +104,11 @@ pub fn main() -> Result<()> { (_, _) => unreachable!(), } } + ("completions", Some(c)) => { + if let Some(shell) = c.value_of("shell") { + cli().gen_completions_to("rustup", shell.parse::().unwrap(), &mut io::stdout()); + } + } (_, _) => unreachable!(), } @@ -313,9 +322,17 @@ pub fn cli() -> App<'static, 'static> { .takes_value(true))) .subcommand(SubCommand::with_name("self") .about("Modify the rustup installation") + .after_help(COMPLETIONS_HELP) .setting(AppSettings::VersionlessSubcommands) .setting(AppSettings::DeriveDisplayOrder) - .setting(AppSettings::SubcommandRequiredElseHelp) + .setting(AppSettings::ArgRequiredElseHelp) + .arg(Arg::with_name("completions") + .short("c") + .long("completions") + .takes_value(true) + .help("Generates a completion script for the specified SHELL") + .value_name("SHELL") + .possible_values(&["zsh", "bash", "fish"])) .subcommand(SubCommand::with_name("update") .about("Download and install updates to rustup")) .subcommand(SubCommand::with_name("uninstall") @@ -343,6 +360,12 @@ pub fn cli() -> App<'static, 'static> { .about("The triple used to identify toolchains when not specified") .arg(Arg::with_name("host_triple") .required(true)))) + .subcommand(SubCommand::with_name("completions") + .about("Generate completion scripts for your shell") + .after_help(COMPLETIONS_HELP) + .setting(AppSettings::ArgRequiredElseHelp) + .arg(Arg::with_name("shell") + .possible_values(&["bash", "fish", "zsh"]))) } fn maybe_upgrade_data(cfg: &Cfg, m: &ArgMatches) -> Result {