1
0
mirror of https://github.com/Llewellynvdm/starship.git synced 2024-11-24 21:57:41 +00:00

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>
This commit is contained in:
Jan Katins 2020-09-26 00:04:51 +02:00 committed by GitHub
parent 17687be1cb
commit ffb1345052
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 192 additions and 0 deletions

View File

@ -217,6 +217,7 @@ $line_break\
$jobs\
$battery\
$time\
$status\
$character"""
```
@ -2084,6 +2085,51 @@ The module will be shown if any of the following conditions are met:
format = "via [🏎 $version](red bold)"
```
## Status
The `status` module displays the exit code of the previous command.
The module will be shown only if the exit code is not `0`.
::: tip
This module is disabled by default.
To enable it, set `disabled` to `false` in your configuration file.
:::
### Options
| Variable | Default | Description |
| ---------- | ----------------------------- | ------------------------------------------------------ |
| `format` | `[$symbol$status]($style) ` | The format of the module |
| `symbol` | `"✖"` | A format string representing the symbol for the status |
| `style` | `"bold red"` | The style for the module. |
| `disabled` | `true` | Disables the `status` module. |
### Variables
| Variable | Example | Description |
| -------- | -------- | ------------------------------------ |
| status | `127` | The exit code of the last command |
| symbol | | Mirrors the value of option `symbol` |
| style\* | | Mirrors the value of option `style` |
\*: This variable can only be used as a part of a style string
### Example
```toml
# ~/.config/starship.toml
[status]
style = "bg:blue"
symbol = "💣 "
format = "[\\[$symbol$status\\]]($style) "
disabled = false
```
## Terraform
The `terraform` module shows the currently selected terraform workspace and version.

View File

@ -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;

View File

@ -65,6 +65,7 @@ pub const PROMPT_ORDER: &[&str] = &[
#[cfg(feature = "battery")]
"battery",
"time",
"status",
"character",
];

22
src/configs/status.rs Normal file
View File

@ -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,
}
}
}

View File

@ -55,6 +55,7 @@ pub const ALL_MODULES: &[&str] = &[
"terraform",
"shlvl",
"singularity",
"status",
"time",
"username",
"zig",

View File

@ -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",

118
src/modules/status.rs Normal file
View File

@ -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(())
}
}