mirror of
https://github.com/Llewellynvdm/starship.git
synced 2024-12-04 19:03:38 +00:00
fix(status): fix pipestatus width calculation (#5036)
closes #3162 Co-authored-by: flw <flw@cpan.org>
This commit is contained in:
parent
938ea3c401
commit
ab840439e3
@ -57,15 +57,15 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let segment_format = config.pipestatus_segment_format.unwrap_or(config.format);
|
||||
let segment_format_with_separator = [segment_format, config.pipestatus_separator].join("");
|
||||
|
||||
// Create pipestatus string
|
||||
// Create pipestatus segments
|
||||
let pipestatus = match pipestatus_status {
|
||||
PipeStatusStatus::Pipe(pipestatus) => pipestatus
|
||||
PipeStatusStatus::Pipe(ps) => ps
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, ec)| {
|
||||
format_exit_code(
|
||||
let formatted = format_exit_code(
|
||||
ec.as_str(),
|
||||
if i == pipestatus.len() - 1 {
|
||||
if i == ps.len() - 1 {
|
||||
segment_format
|
||||
} else {
|
||||
&segment_format_with_separator
|
||||
@ -73,20 +73,25 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
None,
|
||||
&config,
|
||||
context,
|
||||
)
|
||||
.ok()
|
||||
.map(|segments| segments.into_iter().map(|s| s.to_string()))
|
||||
);
|
||||
match formatted {
|
||||
Ok(segments) => Some(segments),
|
||||
Err(e) => {
|
||||
log::warn!("Error parsing format string in `status.pipestatus_segment_format`: {e:?}");
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.collect::<String>(),
|
||||
_ => String::new(),
|
||||
.collect(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
let main_format = match pipestatus_status {
|
||||
PipeStatusStatus::Pipe(_) => config.pipestatus_format,
|
||||
_ => config.format,
|
||||
};
|
||||
let parsed = format_exit_code(exit_code, main_format, Some(&pipestatus), &config, context);
|
||||
let parsed = format_exit_code(exit_code, main_format, Some(pipestatus), &config, context);
|
||||
|
||||
module.set_segments(match parsed {
|
||||
Ok(segments) => segments,
|
||||
@ -101,7 +106,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
fn format_exit_code<'a>(
|
||||
exit_code: &'a str,
|
||||
format: &'a str,
|
||||
pipestatus: Option<&str>,
|
||||
pipestatus: Option<Vec<Segment>>,
|
||||
config: &'a StatusConfig,
|
||||
context: &'a Context,
|
||||
) -> Result<Vec<Segment>, StringFormatterError> {
|
||||
@ -164,16 +169,17 @@ fn format_exit_code<'a>(
|
||||
"common_meaning" => Ok(common_meaning).transpose(),
|
||||
"signal_number" => Ok(signal_number.as_deref()).transpose(),
|
||||
"signal_name" => Ok(signal_name).transpose(),
|
||||
"pipestatus" => {
|
||||
let pipestatus = pipestatus.unwrap_or_else(|| {
|
||||
// We might enter this case if pipestatus hasn't
|
||||
// been processed yet, which means that it has been
|
||||
// set in format
|
||||
log::warn!("pipestatus variable is only available in pipestatus_format");
|
||||
""
|
||||
});
|
||||
Some(Ok(pipestatus))
|
||||
_ => None,
|
||||
})
|
||||
.map_variables_to_segments(|variable| match variable {
|
||||
"pipestatus" if pipestatus.is_none() => {
|
||||
// We might enter this case if pipestatus hasn't
|
||||
// been processed yet, which means that it has been
|
||||
// set in format
|
||||
log::warn!("pipestatus variable is only available in pipestatus_format");
|
||||
None
|
||||
}
|
||||
"pipestatus" => pipestatus.clone().map(Ok),
|
||||
_ => None,
|
||||
})
|
||||
.parse(None, Some(context))
|
||||
@ -779,16 +785,15 @@ mod tests {
|
||||
let pipe_exit_code = &[0, 1, 2];
|
||||
let main_exit_code = 2;
|
||||
|
||||
let expected_style = Style::new().on(Color::Red).fg(Color::White).bold();
|
||||
let style = Style::new().on(Color::Red).fg(Color::White).bold();
|
||||
let sep_style = Style::new().on(Color::Green).fg(Color::White).italic();
|
||||
let expected = Some(format!(
|
||||
"{}{}{}{}{}{}{}",
|
||||
expected_style.paint("["),
|
||||
expected_style.paint("0"),
|
||||
expected_style.paint("|"),
|
||||
expected_style.paint("1"),
|
||||
expected_style.paint("|"),
|
||||
expected_style.paint("2"),
|
||||
expected_style.paint("] => <2>"),
|
||||
"{}{}{}{}{}",
|
||||
style.paint("[0"),
|
||||
sep_style.paint("|"),
|
||||
style.paint("1"),
|
||||
sep_style.paint("|"),
|
||||
style.paint("2] => <2>"),
|
||||
));
|
||||
let actual = ModuleRenderer::new("status")
|
||||
.config(toml::toml! {
|
||||
@ -796,7 +801,7 @@ mod tests {
|
||||
format = "\\($status\\)"
|
||||
style = "fg:white bg:red bold"
|
||||
pipestatus = true
|
||||
pipestatus_separator = "[|]($style)"
|
||||
pipestatus_separator = "[|](fg:white bg:green italic)"
|
||||
pipestatus_format = "[\\[]($style)$pipestatus[\\] => <$status>]($style)"
|
||||
pipestatus_segment_format = "[$status]($style)"
|
||||
disabled = false
|
||||
@ -806,4 +811,67 @@ mod tests {
|
||||
.collect();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pipestatus_width() {
|
||||
let pipe_exit_code = &[0, 1, 2];
|
||||
let main_exit_code = 2;
|
||||
|
||||
let renderer = ModuleRenderer::new("status")
|
||||
.config(toml::toml! {
|
||||
format = "$fill$status"
|
||||
[status]
|
||||
style = "fg:white bg:red bold"
|
||||
pipestatus = true
|
||||
pipestatus_segment_format = "[$status](bg:blue fg:yellow)"
|
||||
disabled = false
|
||||
})
|
||||
.status(main_exit_code)
|
||||
.pipestatus(pipe_exit_code)
|
||||
.width(100);
|
||||
let context = crate::modules::Context::from(renderer);
|
||||
let actual = crate::print::get_prompt(context);
|
||||
|
||||
let mut escaping = false;
|
||||
let mut width = 0;
|
||||
for c in actual.chars() {
|
||||
if c == '\x1B' {
|
||||
escaping = true;
|
||||
}
|
||||
if escaping {
|
||||
escaping = !c.is_ascii_alphabetic();
|
||||
continue;
|
||||
}
|
||||
width += 1;
|
||||
}
|
||||
assert_eq!(width, 100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pipestatus_segment_format_err() {
|
||||
let pipe_exit_code = &[0, 1, 2];
|
||||
let main_exit_code = 2;
|
||||
|
||||
let expected = Some(format!(
|
||||
"{}",
|
||||
Style::new()
|
||||
.on(Color::Red)
|
||||
.fg(Color::White)
|
||||
.bold()
|
||||
.paint("[] => <2>"),
|
||||
));
|
||||
let actual = ModuleRenderer::new("status")
|
||||
.config(toml::toml! {
|
||||
[status]
|
||||
style = "fg:white bg:red bold"
|
||||
pipestatus = true
|
||||
pipestatus_format = "[\\[]($style)$pipestatus[\\] => <$status>]($style)"
|
||||
pipestatus_segment_format = "${"
|
||||
disabled = false
|
||||
})
|
||||
.status(main_exit_code)
|
||||
.pipestatus(pipe_exit_code)
|
||||
.collect();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,11 @@ impl<'a> ModuleRenderer<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn width(mut self, width: usize) -> Self {
|
||||
self.context.width = width;
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "battery")]
|
||||
pub fn battery_info_provider(
|
||||
mut self,
|
||||
@ -164,6 +169,12 @@ impl<'a> ModuleRenderer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ModuleRenderer<'a>> for Context<'a> {
|
||||
fn from(renderer: ModuleRenderer<'a>) -> Self {
|
||||
renderer.context
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum FixtureProvider {
|
||||
Fossil,
|
||||
|
Loading…
Reference in New Issue
Block a user