summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Katins <jasc@gmx.net>2020-09-26 00:04:51 +0200
committerGitHub <noreply@github.com>2020-09-26 00:04:51 +0200
commitffb13450529f319ac54e2dacccb897fb22632e3d (patch)
tree53ee7225eb437ce2fa8f981030eff467c87b9396 /src
parent17687be1cb331cf5910912b87ca6f912b5975c7f (diff)
feat(status): add the status module (#1651)
* add the exit code module this allows to display more precisely the last command exit code and to configure starship to not change the last charcter of the prompt even in case of failure. It is disabled by default, because it seems a bit redundant with the character module in its default configuration. * rename exit_code module to status * Enforce a default disabled=true In the outer places, we only check for the disabled flag in the config toml file, only when this is loaded into the real config struct, we see the default. And if the default is true, we have to abort at that place. For status and hg_branch that wasn't so. I also commented the rest * fix spaces in markdown table for status module * Add a tip that status module is disabled by default Co-authored-by: Thomas O'Donnell <andytom@users.noreply.github.com> * Remove unrelated changes for default disabled=true Co-authored-by: Gaëtan Lehmann <gaetan.lehmann@gmail.com> Co-authored-by: Thomas O'Donnell <andytom@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/configs/mod.rs1
-rw-r--r--src/configs/starship_root.rs1
-rw-r--r--src/configs/status.rs22
-rw-r--r--src/module.rs1
-rw-r--r--src/modules/mod.rs3
-rw-r--r--src/modules/status.rs118
6 files changed, 146 insertions, 0 deletions
diff --git a/src/configs/mod.rs b/src/configs/mod.rs
index 1d961b3af..2643fe513 100644
--- a/src/configs/mod.rs
+++ b/src/configs/mod.rs
@@ -42,6 +42,7 @@ pub mod rust;
pub mod shlvl;
pub mod singularity;
mod starship_root;
+pub mod status;
pub mod swift;
pub mod terraform;
pub mod time;
diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs
index b3f7a5b27..99ad5b295 100644
--- a/src/configs/starship_root.rs
+++ b/src/configs/starship_root.rs
@@ -65,6 +65,7 @@ pub const PROMPT_ORDER: &[&str] = &[
#[cfg(feature = "battery")]
"battery",
"time",
+ "status",
"character",
];
diff --git a/src/configs/status.rs b/src/configs/status.rs
new file mode 100644
index 000000000..dde8766cf
--- /dev/null
+++ b/src/configs/status.rs
@@ -0,0 +1,22 @@
+use crate::config::{ModuleConfig, RootModuleConfig};
+
+use starship_module_config_derive::ModuleConfig;
+
+#[derive(Clone, ModuleConfig)]
+pub struct StatusConfig<'a> {
+ pub format: &'a str,
+ pub symbol: &'a str,
+ pub style: &'a str,
+ pub disabled: bool,
+}
+
+impl<'a> RootModuleConfig<'a> for StatusConfig<'a> {
+ fn new() -> Self {
+ StatusConfig {
+ format: "[$symbol$status]($style) ",
+ symbol: "✖",
+ style: "bold red",
+ disabled: true,
+ }
+ }
+}
diff --git a/src/module.rs b/src/module.rs
index 768071c9c..fc20cf1f7 100644
--- a/src/module.rs
+++ b/src/module.rs
@@ -55,6 +55,7 @@ pub const ALL_MODULES: &[&str] = &[
"terraform",
"shlvl",
"singularity",
+ "status",
"time",
"username",
"zig",
diff --git a/src/modules/mod.rs b/src/modules/mod.rs
index 9098a746a..aedebced7 100644
--- a/src/modules/mod.rs
+++ b/src/modules/mod.rs
@@ -42,6 +42,7 @@ mod ruby;
mod rust;
mod shlvl;
mod singularity;
+mod status;
mod swift;
mod terraform;
mod time;
@@ -108,6 +109,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"shlvl" => shlvl::module(context),
"singularity" => singularity::module(context),
"swift" => swift::module(context),
+ "status" => status::module(context),
"terraform" => terraform::module(context),
"time" => time::module(context),
"crystal" => crystal::module(context),
@@ -179,6 +181,7 @@ pub fn description(module: &str) -> &'static str {
"rust" => "The currently installed version of Rust",
"swift" => "The currently installed version of Swift",
"shlvl" => "The current value of SHLVL",
+ "status" => "The status of the last command",
"terraform" => "The currently selected terraform workspace and version",
"time" => "The current local time",
"username" => "The active user's username",
diff --git a/src/modules/status.rs b/src/modules/status.rs
new file mode 100644
index 000000000..d985864a8
--- /dev/null
+++ b/src/modules/status.rs
@@ -0,0 +1,118 @@
+use super::{Context, Module, RootModuleConfig};
+
+use crate::configs::status::StatusConfig;
+use crate::formatter::StringFormatter;
+
+/// Creates a module with the status of the last command
+///
+/// Will display the status only if it is not 0
+pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
+ let exit_code = context
+ .properties
+ .get("status_code")
+ .map_or("0", String::as_str);
+
+ if exit_code == "0" {
+ None
+ } else {
+ let mut module = context.new_module("status");
+ let config = StatusConfig::try_load(module.config);
+
+ // As we default to disabled=true, we have to check here after loading our config module,
+ // before it was only checking against whatever is in the config starship.toml
+ if config.disabled {
+ return None;
+ };
+
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_meta(|var, _| match var {
+ "symbol" => Some(config.symbol),
+ _ => None,
+ })
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ "status" => Some(Ok(exit_code)),
+ _ => None,
+ })
+ .parse(None)
+ });
+
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(_error) => {
+ log::warn!("Error parsing format string in `status.format`");
+ return None;
+ }
+ });
+ Some(module)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use ansi_term::Color;
+ use std::io;
+
+ use crate::test::ModuleRenderer;
+
+ #[test]
+ fn success_status() -> io::Result<()> {
+ let expected = None;
+
+ // Status code 0
+ let actual = ModuleRenderer::new("status")
+ .config(toml::toml! {
+ [status]
+ disabled = false
+ })
+ .status(0)
+ .collect();
+ assert_eq!(expected, actual);
+
+ // No status code
+ let actual = ModuleRenderer::new("status")
+ .config(toml::toml! {
+ [status]
+ disabled = false
+ })
+ .collect();
+ assert_eq!(expected, actual);
+
+ Ok(())
+ }
+
+ #[test]
+ fn not_enabled() -> io::Result<()> {
+ let expected = None;
+
+ let actual = ModuleRenderer::new("status").status(1).collect();
+ assert_eq!(expected, actual);
+ Ok(())
+ }
+
+ #[test]
+ fn failure_status() -> io::Result<()> {
+ let exit_values = [1, 2, 130];
+
+ for status in exit_values.iter() {
+ let expected = Some(format!(
+ "{} ",
+ Color::Red.bold().paint(format!("✖{}", status))
+ ));
+ let actual = ModuleRenderer::new("status")
+ .config(toml::toml! {
+ [status]
+ disabled = false
+ })
+ .status(*status)
+ .collect();
+ assert_eq!(expected, actual);
+ }
+
+ Ok(())
+ }
+}