feat: Add support for cygwin/msys2/git-bash evironment (#2020)
* feat: Add support for cygwin/msys2/git-bash evironment * Update src/init/mod.rs Co-authored-by: David Knaack <davidkna@users.noreply.github.com> Co-authored-by: Thomas O'Donnell <andytom@users.noreply.github.com> Co-authored-by: David Knaack <davidkna@users.noreply.github.com>
This commit is contained in:
parent
f03c3f1de9
commit
851cf22caa
112
src/init/mod.rs
112
src/init/mod.rs
|
@ -1,5 +1,5 @@
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::{env, io};
|
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
|
||||||
|
@ -17,12 +17,62 @@ using whatever mechanism is available in the host shell--this two-phase solution
|
||||||
has been developed as a compatibility measure with `eval $(starship init X)`
|
has been developed as a compatibility measure with `eval $(starship init X)`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn path_to_starship() -> io::Result<String> {
|
struct StarshipPath {
|
||||||
let current_exe = env::current_exe()?
|
native_path: PathBuf,
|
||||||
.to_str()
|
}
|
||||||
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "can't convert to str"))?
|
impl StarshipPath {
|
||||||
.to_string();
|
fn init() -> io::Result<Self> {
|
||||||
Ok(current_exe)
|
Ok(Self {
|
||||||
|
native_path: env::current_exe()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn str_path(&self) -> io::Result<&str> {
|
||||||
|
let current_exe = self
|
||||||
|
.native_path
|
||||||
|
.to_str()
|
||||||
|
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "can't convert to str"))?;
|
||||||
|
Ok(current_exe)
|
||||||
|
}
|
||||||
|
fn sprint(&self) -> io::Result<String> {
|
||||||
|
self.str_path().map(|s| s.replace("\"", "\"'\"'\""))
|
||||||
|
}
|
||||||
|
fn sprint_posix(&self) -> io::Result<String> {
|
||||||
|
// On non-Windows platform, return directly.
|
||||||
|
if cfg!(not(target_os = "windows")) {
|
||||||
|
return self.sprint();
|
||||||
|
}
|
||||||
|
let str_path = self.str_path()?;
|
||||||
|
let res = std::process::Command::new("cygpath.exe")
|
||||||
|
.arg(str_path)
|
||||||
|
.output();
|
||||||
|
let output = match res {
|
||||||
|
Ok(output) => output,
|
||||||
|
Err(e) => {
|
||||||
|
if e.kind() != io::ErrorKind::NotFound {
|
||||||
|
log::warn!("Failed to convert \"{}\" to unix path:\n{:?}", str_path, e);
|
||||||
|
}
|
||||||
|
// Failed to execute cygpath.exe means there're not inside cygwin evironment,return directly.
|
||||||
|
return self.sprint();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let res = String::from_utf8(output.stdout);
|
||||||
|
let posix_path = match res {
|
||||||
|
Ok(ref cygpath_path) if output.status.success() => cygpath_path.trim(),
|
||||||
|
Ok(_) => {
|
||||||
|
log::warn!(
|
||||||
|
"Failed to convert \"{}\" to unix path:\n{}",
|
||||||
|
str_path,
|
||||||
|
String::from_utf8_lossy(&output.stderr),
|
||||||
|
);
|
||||||
|
str_path
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to convert \"{}\" to unix path:\n{}", str_path, e);
|
||||||
|
str_path
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(posix_path.replace("\"", "\"'\"'\""))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
|
@ -33,7 +83,7 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
|
||||||
|
|
||||||
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 starship = StarshipPath::init()?;
|
||||||
|
|
||||||
let setup_stub = match shell_basename {
|
let setup_stub = match shell_basename {
|
||||||
Some("bash") => {
|
Some("bash") => {
|
||||||
|
@ -72,25 +122,28 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
|
||||||
format!(
|
format!(
|
||||||
r#"if [ "${{BASH_VERSINFO[0]}}" -gt 4 ] || ([ "${{BASH_VERSINFO[0]}}" -eq 4 ] && [ "${{BASH_VERSINFO[1]}}" -ge 1 ])
|
r#"if [ "${{BASH_VERSINFO[0]}}" -gt 4 ] || ([ "${{BASH_VERSINFO[0]}}" -eq 4 ] && [ "${{BASH_VERSINFO[1]}}" -ge 1 ])
|
||||||
then
|
then
|
||||||
source <("{}" init bash --print-full-init)
|
source <("{0}" init bash --print-full-init)
|
||||||
else
|
else
|
||||||
source /dev/stdin <<<"$("{}" init bash --print-full-init)"
|
source /dev/stdin <<<"$("{0}" init bash --print-full-init)"
|
||||||
fi"#,
|
fi"#,
|
||||||
starship, starship
|
starship.sprint_posix()?
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(script)
|
Some(script)
|
||||||
}
|
}
|
||||||
Some("zsh") => {
|
Some("zsh") => {
|
||||||
let script = format!("source <(\"{}\" init zsh --print-full-init)", starship);
|
let script = format!(
|
||||||
|
"source <(\"{}\" init zsh --print-full-init)",
|
||||||
|
starship.sprint_posix()?
|
||||||
|
);
|
||||||
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 = format!(
|
let script = format!(
|
||||||
"source (\"{}\" init fish --print-full-init | psub)",
|
"source (\"{}\" init fish --print-full-init | psub)",
|
||||||
starship
|
starship.sprint_posix()?
|
||||||
);
|
);
|
||||||
Some(script)
|
Some(script)
|
||||||
}
|
}
|
||||||
|
@ -105,12 +158,12 @@ fi"#,
|
||||||
// Powershell escapes with ` instead of \ thus `n translates to a newline.
|
// Powershell escapes with ` instead of \ thus `n translates to a newline.
|
||||||
let script = format!(
|
let script = format!(
|
||||||
"Invoke-Expression (@(&\"{}\" init powershell --print-full-init) -join \"`n\")",
|
"Invoke-Expression (@(&\"{}\" init powershell --print-full-init) -join \"`n\")",
|
||||||
starship
|
starship.sprint()?
|
||||||
);
|
);
|
||||||
Some(script)
|
Some(script)
|
||||||
}
|
}
|
||||||
Some("ion") => {
|
Some("ion") => {
|
||||||
let script = format!("eval $({} init ion --print-full-init)", starship);
|
let script = format!("eval $({} init ion --print-full-init)", starship.sprint()?);
|
||||||
Some(script)
|
Some(script)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -143,32 +196,31 @@ fi"#,
|
||||||
/* 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) -> io::Result<()> {
|
pub fn init_main(shell_name: &str) -> io::Result<()> {
|
||||||
let starship_path = path_to_starship()?.replace("\"", "\"'\"'\"");
|
let starship_path = StarshipPath::init()?;
|
||||||
|
|
||||||
let setup_script = match shell_name {
|
match shell_name {
|
||||||
"bash" => Some(BASH_INIT),
|
"bash" => print_script(BASH_INIT, &starship_path.sprint_posix()?),
|
||||||
"zsh" => Some(ZSH_INIT),
|
"zsh" => print_script(ZSH_INIT, &starship_path.sprint_posix()?),
|
||||||
"fish" => Some(FISH_INIT),
|
"fish" => print_script(FISH_INIT, &starship_path.sprint_posix()?),
|
||||||
"powershell" => Some(PWSH_INIT),
|
"powershell" => print_script(PWSH_INIT, &starship_path.sprint()?),
|
||||||
"ion" => Some(ION_INIT),
|
"ion" => print_script(ION_INIT, &starship_path.sprint()?),
|
||||||
_ => {
|
_ => {
|
||||||
println!(
|
println!(
|
||||||
"printf \"Shell name detection failed on phase two init.\\n\
|
"printf \"Shell name detection failed on phase two init.\\n\
|
||||||
This probably indicates a bug within starship: please open\\n\
|
This probably indicates a bug within starship: please open\\n\
|
||||||
an issue at https://github.com/starship/starship/issues/new\\n\""
|
an issue at https://github.com/starship/starship/issues/new\\n\""
|
||||||
);
|
);
|
||||||
None
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
if let Some(script) = setup_script {
|
|
||||||
// Set up quoting for starship path in case it has spaces.
|
|
||||||
let starship_path_string = format!("\"{}\"", starship_path);
|
|
||||||
let script = script.replace("::STARSHIP::", &starship_path_string);
|
|
||||||
print!("{}", script);
|
|
||||||
};
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_script(script: &str, path: &str) {
|
||||||
|
let starship_path_string = format!("\"{}\"", path);
|
||||||
|
let script = script.replace("::STARSHIP::", &starship_path_string);
|
||||||
|
print!("{}", script);
|
||||||
|
}
|
||||||
|
|
||||||
/* GENERAL INIT SCRIPT NOTES
|
/* GENERAL INIT SCRIPT NOTES
|
||||||
|
|
||||||
Each init script will be passed as-is. Global notes for init scripts are in this
|
Each init script will be passed as-is. Global notes for init scripts are in this
|
||||||
|
|
Loading…
Reference in New Issue