feat: add support for xonsh (#2807)

* feat: add support for xonsh

* xonsh: add STARSHIP_SESSION_KEY

* xonsh: implement STARSHIP_SESSION_KEY in xonsh

* docs: mention tcsh, elvish, and nu in more places

* xonsh: change STARSHIP_SESSION_KEY implementation

See https://github.com/starship/starship/pull/2807#discussion_r667064149

* xonsh: fix jobs implementation

* xonsh: do not silently discard stderr from starship
This commit is contained in:
Jeremy Schlatter
2021-07-16 12:25:01 -07:00
committed by GitHub
parent 1eaf996a36
commit b1dcd5aecd
13 changed files with 99 additions and 5 deletions
+1
View File
@@ -212,6 +212,7 @@ fn get_config_path(shell: &str) -> Option<PathBuf> {
"zsh" => Some(".zshrc"),
"elvish" => Some(".elvish/rc.elv"),
"tcsh" => Some(".tcshrc"),
"xonsh" => Some(".xonshrc"),
_ => None,
}
.map(|path| home_dir.join(path))
+2
View File
@@ -14,6 +14,7 @@ pub struct ShellConfig<'a> {
pub elvish_indicator: &'a str,
pub tcsh_indicator: &'a str,
pub nu_indicator: &'a str,
pub xonsh_indicator: &'a str,
pub unknown_indicator: &'a str,
pub disabled: bool,
}
@@ -30,6 +31,7 @@ impl<'a> Default for ShellConfig<'a> {
elvish_indicator: "esh",
tcsh_indicator: "tsh",
nu_indicator: "nu",
xonsh_indicator: "xsh",
unknown_indicator: "",
disabled: true,
}
+2
View File
@@ -257,6 +257,7 @@ impl<'a> Context<'a> {
"elvish" => Shell::Elvish,
"tcsh" => Shell::Tcsh,
"nu" => Shell::Nu,
"xonsh" => Shell::Xonsh,
_ => Shell::Unknown,
}
}
@@ -494,6 +495,7 @@ pub enum Shell {
Elvish,
Tcsh,
Nu,
Xonsh,
Unknown,
}
+8
View File
@@ -168,6 +168,10 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
starship.sprint_posix()?
),
"nu" => print_script(NU_INIT, &StarshipPath::init()?.sprint_posix()?),
"xonsh" => print!(
r#"execx($({} init xonsh --print-full-init))"#,
starship.sprint_posix()?
),
_ => {
let quoted_arg = shell_words::quote(shell_basename);
println!(
@@ -181,6 +185,7 @@ pub fn init_stub(shell_name: &str) -> io::Result<()> {
* tcsh\\n\
* zsh\\n\
* nu\\n\
* xonsh\\n\
\\n\
Please open an issue in the starship repo if you would like to \
see support for %s:\\nhttps://github.com/starship/starship/issues/new\\n\\n\" {0} {0}",
@@ -204,6 +209,7 @@ pub fn init_main(shell_name: &str) -> io::Result<()> {
"ion" => print_script(ION_INIT, &starship_path.sprint()?),
"elvish" => print_script(ELVISH_INIT, &starship_path.sprint_posix()?),
"tcsh" => print_script(TCSH_INIT, &starship_path.sprint_posix()?),
"xonsh" => print_script(XONSH_INIT, &starship_path.sprint_posix()?),
_ => {
println!(
"printf \"Shell name detection failed on phase two init.\\n\
@@ -251,6 +257,8 @@ const TCSH_INIT: &str = include_str!("starship.tcsh");
const NU_INIT: &str = include_str!("starship.nu");
const XONSH_INIT: &str = include_str!("starship.xsh");
#[cfg(test)]
mod tests {
use super::*;
+17
View File
@@ -0,0 +1,17 @@
import uuid
def starship_prompt():
last_cmd = __xonsh__.history[-1] if __xonsh__.history else None
status = last_cmd.rtn if last_cmd else 0
# I believe this is equivalent to xonsh.jobs.get_next_job_number() for our purposes,
# but we can't use that function because of https://gitter.im/xonsh/xonsh?at=60e8832d82dd9050f5e0c96a
jobs = sum(1 for job in __xonsh__.all_jobs.values() if job['obj'] and job['obj'].poll() is None)
duration = round((last_cmd.ts[1] - last_cmd.ts[0]) * 1000) if last_cmd else 0
# The `| cat` is a workaround for https://github.com/xonsh/xonsh/issues/3786. See https://github.com/starship/starship/pull/2807#discussion_r667316323.
return $(::STARSHIP:: prompt --status=@(status) --jobs=@(jobs) --cmd-duration=@(duration) | cat)
$PROMPT = starship_prompt
$STARSHIP_SHELL = "xonsh"
$STARSHIP_SESSION_KEY = uuid.uuid4().hex
+1 -1
View File
@@ -43,7 +43,7 @@ fn main() {
let shell_arg = Arg::with_name("shell")
.value_name("SHELL")
.help(
"The name of the currently running shell\nCurrently supported options: bash, zsh, fish, powershell, ion, elvish, tcsh, nu",
"The name of the currently running shell\nCurrently supported options: bash, zsh, fish, powershell, ion, elvish, tcsh, nu, xonsh",
)
.required(true);
+31
View File
@@ -25,6 +25,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
Shell::Elvish => Some(config.elvish_indicator),
Shell::Tcsh => Some(config.tcsh_indicator),
Shell::Nu => Some(config.nu_indicator),
Shell::Xonsh => Some(config.xonsh_indicator),
Shell::Unknown => Some(config.unknown_indicator),
},
_ => None,
@@ -37,6 +38,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
"ion_indicator" => Some(Ok(config.ion_indicator)),
"elvish_indicator" => Some(Ok(config.elvish_indicator)),
"tcsh_indicator" => Some(Ok(config.tcsh_indicator)),
"xonsh_indicator" => Some(Ok(config.xonsh_indicator)),
"unknown_indicator" => Some(Ok(config.unknown_indicator)),
_ => None,
})
@@ -279,6 +281,35 @@ mod tests {
assert_eq!(expected, actual);
}
#[test]
fn test_xonsh_default_format() {
let expected = Some(format!("{} ", "xsh"));
let actual = ModuleRenderer::new("shell")
.shell(Shell::Xonsh)
.config(toml::toml! {
[shell]
disabled = false
})
.collect();
assert_eq!(expected, actual);
}
#[test]
fn test_xonsh_custom_format() {
let expected = Some(format!("{} ", Color::Cyan.bold().paint("xonsh")));
let actual = ModuleRenderer::new("shell")
.shell(Shell::Xonsh)
.config(toml::toml! {
[shell]
xonsh_indicator = "[xonsh](bold cyan)"
disabled = false
})
.collect();
assert_eq!(expected, actual);
}
#[test]
fn test_custom_format_conditional_indicator_match() {
let expected = Some(format!("{} ", "B"));