Use full path to starship in all phases of init (#224)

This commit is contained in:
Bruno Bigras 2019-08-22 15:57:32 -04:00 committed by Kevin Song
parent 70d53ee7a9
commit 68cbcb91b7
2 changed files with 37 additions and 16 deletions

View File

@ -1,5 +1,6 @@
use std::ffi::OsStr; use std::ffi::OsStr;
use std::path::Path; use std::path::Path;
use std::{env, io};
/* We use a two-phase init here: the first phase gives a simple command to the /* We use a two-phase init here: the first phase gives a simple command to the
shell. This command evaluates a more complicated script using `source` and shell. This command evaluates a more complicated script using `source` and
@ -11,29 +12,45 @@ rest of the script, and you have to spam semicolons everywhere. By using
source and process substitutions, we make it possible to comment and debug source and process substitutions, we make it possible to comment and debug
the init scripts. */ the init scripts. */
fn path_to_starship() -> io::Result<String> {
let current_exe = env::current_exe()?
.to_str()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "can't convert to str"))?
.to_string();
Ok(current_exe)
}
/* This prints the setup stub, the short piece of code which sets up the main /* This prints the setup stub, the short piece of code which sets up the main
init code. The stub produces the main init script, then evaluates it with init code. The stub produces the main init script, then evaluates it with
`source` and process substitution */ `source` and process substitution */
pub fn init_stub(shell_name: &str) { pub fn init_stub(shell_name: &str) -> io::Result<()> {
log::debug!("Shell name: {}", shell_name); log::debug!("Shell name: {}", shell_name);
let shell_basename = Path::new(shell_name).file_stem().and_then(OsStr::to_str); let shell_basename = Path::new(shell_name).file_stem().and_then(OsStr::to_str);
let starship = path_to_starship()?.replace("\"", "\"'\"'\"");
let setup_stub = match shell_basename { let setup_stub = match shell_basename {
Some("bash") => { Some("bash") => {
/* This *should* look like the zsh function, but bash 3.2 (MacOS default shell) /* This *should* look like the zsh function, but bash 3.2 (MacOS default shell)
does not support using source with process substitution, so we use this does not support using source with process substitution, so we use this
workaround from https://stackoverflow.com/a/32596626 */ workaround from https://stackoverflow.com/a/32596626 */
let script = "source /dev/stdin <<<\"$(starship init bash --print-full-init)\""; let script = format!(
"source /dev/stdin <<<\"$(\"{}\" init bash --print-full-init)\"",
starship
);
Some(script) Some(script)
} }
Some("zsh") => { Some("zsh") => {
let script = "source <(starship init zsh --print-full-init)"; let script = format!("source <(\"{}\" init zsh --print-full-init)", starship);
Some(script) Some(script)
} }
Some("fish") => { Some("fish") => {
// Fish does process substitution with pipes and psub instead of bash syntax // Fish does process substitution with pipes and psub instead of bash syntax
let script = "source (starship init fish --print-full-init | psub)"; let script = format!(
"source (\"{}\" init fish --print-full-init | psub)",
starship
);
Some(script) Some(script)
} }
None => { None => {
@ -62,15 +79,18 @@ pub fn init_stub(shell_name: &str) {
if let Some(script) = setup_stub { if let Some(script) = setup_stub {
print!("{}", script); print!("{}", script);
}; };
Ok(())
} }
/* This function (called when `--print-full-init` is passed to `starship init`) /* This function (called when `--print-full-init` is passed to `starship init`)
prints out the main initialization script */ prints out the main initialization script */
pub fn init_main(shell_name: &str) { pub fn init_main(shell_name: &str) -> io::Result<()> {
let starship_path = path_to_starship()?.replace("\"", "\"'\"'\"");
let setup_script = match shell_name { let setup_script = match shell_name {
"bash" => Some(BASH_INIT), "bash" => Some(BASH_INIT.replace("## STARSHIP ##", &format!("\"{}\"", starship_path))),
"zsh" => Some(ZSH_INIT), "zsh" => Some(ZSH_INIT.replace("## STARSHIP ##", &format!("\"{}\"", starship_path))),
"fish" => Some(FISH_INIT), "fish" => Some(FISH_INIT.replace("## STARSHIP ##", &format!("\"{}\"", starship_path))),
_ => { _ => {
println!( println!(
"printf \"Shell name detection failed on phase two init.\\n\ "printf \"Shell name detection failed on phase two init.\\n\
@ -83,6 +103,7 @@ pub fn init_main(shell_name: &str) {
if let Some(script) = setup_script { if let Some(script) = setup_script {
print!("{}", script); print!("{}", script);
}; };
Ok(())
} }
/* GENERAL INIT SCRIPT NOTES /* GENERAL INIT SCRIPT NOTES
@ -132,10 +153,10 @@ starship_precmd() {
if [[ $STARSHIP_START_TIME ]]; then if [[ $STARSHIP_START_TIME ]]; then
STARSHIP_END_TIME=$(date +%s) STARSHIP_END_TIME=$(date +%s)
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME)) STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME))
PS1="$(starship prompt --status=$STATUS --jobs="$(jobs -p | wc -l)" --cmd-duration=$STARSHIP_DURATION)" PS1="$(## STARSHIP ## prompt --status=$STATUS --jobs="$(jobs -p | wc -l)" --cmd-duration=$STARSHIP_DURATION)"
unset STARSHIP_START_TIME unset STARSHIP_START_TIME
else else
PS1="$(starship prompt --status=$STATUS --jobs="$(jobs -p | wc -l)")" PS1="$(## STARSHIP ## prompt --status=$STATUS --jobs="$(jobs -p | wc -l)")"
fi fi
PREEXEC_READY=true; # Signal that we can safely restart the timer PREEXEC_READY=true; # Signal that we can safely restart the timer
} }
@ -190,10 +211,10 @@ starship_precmd() {
if [[ ! -z "${STARSHIP_START_TIME+1}" ]]; then if [[ ! -z "${STARSHIP_START_TIME+1}" ]]; then
STARSHIP_END_TIME="$(date +%s)" STARSHIP_END_TIME="$(date +%s)"
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME)) STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME))
PROMPT="$(starship prompt --status=$STATUS --cmd-duration=$STARSHIP_DURATION --jobs="$(jobs | wc -l)")" PROMPT="$(## STARSHIP ## prompt --status=$STATUS --cmd-duration=$STARSHIP_DURATION --jobs="$(jobs | wc -l)")"
unset STARSHIP_START_TIME unset STARSHIP_START_TIME
else else
PROMPT="$(starship prompt --status=$STATUS --jobs="$(jobs | wc -l)")" PROMPT="$(## STARSHIP ## prompt --status=$STATUS --jobs="$(jobs | wc -l)")"
fi fi
} }
starship_preexec(){ starship_preexec(){
@ -217,7 +238,7 @@ fi
# Set up a function to redraw the prompt if the user switches vi modes # Set up a function to redraw the prompt if the user switches vi modes
function zle-keymap-select function zle-keymap-select
{ {
PROMPT=$(starship prompt --keymap=$KEYMAP --jobs="$(jobs | wc -l)") PROMPT=$(## STARSHIP ## prompt --keymap=$KEYMAP --jobs="$(jobs | wc -l)")
zle reset-prompt zle reset-prompt
} }
@ -232,6 +253,6 @@ function fish_prompt
# Account for changes in variable name between v2.7 and v3.0 # Account for changes in variable name between v2.7 and v3.0
set -l CMD_DURATION "$CMD_DURATION$cmd_duration" set -l CMD_DURATION "$CMD_DURATION$cmd_duration"
set -l starship_duration (math --scale=0 "$CMD_DURATION / 1000") set -l starship_duration (math --scale=0 "$CMD_DURATION / 1000")
starship prompt --status=$exit_code --cmd-duration=$starship_duration --jobs=(count (jobs -p)) ## STARSHIP ## prompt --status=$exit_code --cmd-duration=$starship_duration --jobs=(count (jobs -p))
end end
"##; "##;

View File

@ -113,9 +113,9 @@ fn main() {
("init", Some(sub_m)) => { ("init", Some(sub_m)) => {
let shell_name = sub_m.value_of("shell").expect("Shell name missing."); let shell_name = sub_m.value_of("shell").expect("Shell name missing.");
if sub_m.is_present("print_full_init") { if sub_m.is_present("print_full_init") {
init::init_main(shell_name); init::init_main(shell_name).expect("can't init_main");
} else { } else {
init::init_stub(shell_name); init::init_stub(shell_name).expect("can't init_stub");
} }
} }
("prompt", Some(sub_m)) => print::prompt(sub_m.clone()), ("prompt", Some(sub_m)) => print::prompt(sub_m.clone()),