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 = config.pipestatus_segment_format.unwrap_or(config.format);
|
||||||
let segment_format_with_separator = [segment_format, config.pipestatus_separator].join("");
|
let segment_format_with_separator = [segment_format, config.pipestatus_separator].join("");
|
||||||
|
|
||||||
// Create pipestatus string
|
// Create pipestatus segments
|
||||||
let pipestatus = match pipestatus_status {
|
let pipestatus = match pipestatus_status {
|
||||||
PipeStatusStatus::Pipe(pipestatus) => pipestatus
|
PipeStatusStatus::Pipe(ps) => ps
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter_map(|(i, ec)| {
|
.filter_map(|(i, ec)| {
|
||||||
format_exit_code(
|
let formatted = format_exit_code(
|
||||||
ec.as_str(),
|
ec.as_str(),
|
||||||
if i == pipestatus.len() - 1 {
|
if i == ps.len() - 1 {
|
||||||
segment_format
|
segment_format
|
||||||
} else {
|
} else {
|
||||||
&segment_format_with_separator
|
&segment_format_with_separator
|
||||||
|
@ -73,20 +73,25 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
None,
|
None,
|
||||||
&config,
|
&config,
|
||||||
context,
|
context,
|
||||||
)
|
);
|
||||||
.ok()
|
match formatted {
|
||||||
.map(|segments| segments.into_iter().map(|s| s.to_string()))
|
Ok(segments) => Some(segments),
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Error parsing format string in `status.pipestatus_segment_format`: {e:?}");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect::<String>(),
|
.collect(),
|
||||||
_ => String::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let main_format = match pipestatus_status {
|
let main_format = match pipestatus_status {
|
||||||
PipeStatusStatus::Pipe(_) => config.pipestatus_format,
|
PipeStatusStatus::Pipe(_) => config.pipestatus_format,
|
||||||
_ => config.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 {
|
module.set_segments(match parsed {
|
||||||
Ok(segments) => segments,
|
Ok(segments) => segments,
|
||||||
|
@ -101,7 +106,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
fn format_exit_code<'a>(
|
fn format_exit_code<'a>(
|
||||||
exit_code: &'a str,
|
exit_code: &'a str,
|
||||||
format: &'a str,
|
format: &'a str,
|
||||||
pipestatus: Option<&str>,
|
pipestatus: Option<Vec<Segment>>,
|
||||||
config: &'a StatusConfig,
|
config: &'a StatusConfig,
|
||||||
context: &'a Context,
|
context: &'a Context,
|
||||||
) -> Result<Vec<Segment>, StringFormatterError> {
|
) -> Result<Vec<Segment>, StringFormatterError> {
|
||||||
|
@ -164,16 +169,17 @@ fn format_exit_code<'a>(
|
||||||
"common_meaning" => Ok(common_meaning).transpose(),
|
"common_meaning" => Ok(common_meaning).transpose(),
|
||||||
"signal_number" => Ok(signal_number.as_deref()).transpose(),
|
"signal_number" => Ok(signal_number.as_deref()).transpose(),
|
||||||
"signal_name" => Ok(signal_name).transpose(),
|
"signal_name" => Ok(signal_name).transpose(),
|
||||||
"pipestatus" => {
|
_ => None,
|
||||||
let pipestatus = pipestatus.unwrap_or_else(|| {
|
})
|
||||||
// We might enter this case if pipestatus hasn't
|
.map_variables_to_segments(|variable| match variable {
|
||||||
// been processed yet, which means that it has been
|
"pipestatus" if pipestatus.is_none() => {
|
||||||
// set in format
|
// We might enter this case if pipestatus hasn't
|
||||||
log::warn!("pipestatus variable is only available in pipestatus_format");
|
// 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
|
||||||
}
|
}
|
||||||
|
"pipestatus" => pipestatus.clone().map(Ok),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.parse(None, Some(context))
|
.parse(None, Some(context))
|
||||||
|
@ -779,16 +785,15 @@ mod tests {
|
||||||
let pipe_exit_code = &[0, 1, 2];
|
let pipe_exit_code = &[0, 1, 2];
|
||||||
let main_exit_code = 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!(
|
let expected = Some(format!(
|
||||||
"{}{}{}{}{}{}{}",
|
"{}{}{}{}{}",
|
||||||
expected_style.paint("["),
|
style.paint("[0"),
|
||||||
expected_style.paint("0"),
|
sep_style.paint("|"),
|
||||||
expected_style.paint("|"),
|
style.paint("1"),
|
||||||
expected_style.paint("1"),
|
sep_style.paint("|"),
|
||||||
expected_style.paint("|"),
|
style.paint("2] => <2>"),
|
||||||
expected_style.paint("2"),
|
|
||||||
expected_style.paint("] => <2>"),
|
|
||||||
));
|
));
|
||||||
let actual = ModuleRenderer::new("status")
|
let actual = ModuleRenderer::new("status")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
|
@ -796,7 +801,7 @@ mod tests {
|
||||||
format = "\\($status\\)"
|
format = "\\($status\\)"
|
||||||
style = "fg:white bg:red bold"
|
style = "fg:white bg:red bold"
|
||||||
pipestatus = true
|
pipestatus = true
|
||||||
pipestatus_separator = "[|]($style)"
|
pipestatus_separator = "[|](fg:white bg:green italic)"
|
||||||
pipestatus_format = "[\\[]($style)$pipestatus[\\] => <$status>]($style)"
|
pipestatus_format = "[\\[]($style)$pipestatus[\\] => <$status>]($style)"
|
||||||
pipestatus_segment_format = "[$status]($style)"
|
pipestatus_segment_format = "[$status]($style)"
|
||||||
disabled = false
|
disabled = false
|
||||||
|
@ -806,4 +811,67 @@ mod tests {
|
||||||
.collect();
|
.collect();
|
||||||
assert_eq!(expected, actual);
|
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
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn width(mut self, width: usize) -> Self {
|
||||||
|
self.context.width = width;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "battery")]
|
#[cfg(feature = "battery")]
|
||||||
pub fn battery_info_provider(
|
pub fn battery_info_provider(
|
||||||
mut self,
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum FixtureProvider {
|
pub enum FixtureProvider {
|
||||||
Fossil,
|
Fossil,
|
||||||
|
|
Loading…
Reference in New Issue