summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-11-11 10:49:23 -0500
committerDan Davison <dandavison7@gmail.com>2021-11-14 14:32:03 -0500
commit91d7d794a51a565da4068f1eb9b7c49a19b7d80e (patch)
treecb3080bf75e7be046805a199d66ef85c294b9c05
parentf570da972fa79debdb9c5516debfdd76d21be6de (diff)
Support precision specifier in run-time format strings
-rw-r--r--src/features/line_numbers.rs31
-rw-r--r--src/format.rs51
2 files changed, 73 insertions, 9 deletions
diff --git a/src/features/line_numbers.rs b/src/features/line_numbers.rs
index 0cc4ebfb..7082d05d 100644
--- a/src/features/line_numbers.rs
+++ b/src/features/line_numbers.rs
@@ -266,14 +266,22 @@ fn format_and_paint_line_number_field<'a>(
.as_ref()
.unwrap_or(&Align::Center);
match placeholder.placeholder {
- Some(Placeholder::NumberMinus) => ansi_strings.push(styles[Minus].paint(
- format_line_number(line_numbers[Minus], alignment_spec, width, None, config),
- )),
+ Some(Placeholder::NumberMinus) => {
+ ansi_strings.push(styles[Minus].paint(format_line_number(
+ line_numbers[Minus],
+ alignment_spec,
+ width,
+ placeholder.precision,
+ None,
+ config,
+ )))
+ }
Some(Placeholder::NumberPlus) => {
ansi_strings.push(styles[Plus].paint(format_line_number(
line_numbers[Plus],
alignment_spec,
width,
+ placeholder.precision,
Some(plus_file),
config,
)))
@@ -292,10 +300,11 @@ fn format_line_number(
line_number: Option<usize>,
alignment: &Align,
width: usize,
+ precision: Option<usize>,
plus_file: Option<&str>,
config: &config::Config,
) -> String {
- let pad = |n| format::pad(n, width, alignment);
+ let pad = |n| format::pad(n, width, alignment, precision);
match (line_number, config.hyperlinks, plus_file) {
(None, _, _) => pad(""),
(Some(n), true, Some(file)) => {
@@ -332,6 +341,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberMinus),
alignment_spec: None,
width: None,
+ precision: None,
suffix: "".into(),
prefix_len: 0,
suffix_len: 0,
@@ -348,6 +358,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberPlus),
alignment_spec: None,
width: Some(4),
+ precision: None,
suffix: "".into(),
prefix_len: 0,
suffix_len: 0,
@@ -364,6 +375,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberPlus),
alignment_spec: Some(Align::Right),
width: Some(4),
+ precision: None,
suffix: "".into(),
prefix_len: 0,
suffix_len: 0,
@@ -380,6 +392,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberPlus),
alignment_spec: Some(Align::Right),
width: Some(4),
+ precision: None,
suffix: "".into(),
prefix_len: 0,
suffix_len: 0,
@@ -396,6 +409,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberPlus),
alignment_spec: Some(Align::Right),
width: Some(4),
+ precision: None,
suffix: "@@".into(),
prefix_len: 2,
suffix_len: 2,
@@ -413,6 +427,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberMinus),
alignment_spec: Some(Align::Left),
width: Some(3),
+ precision: None,
suffix: "@@---{np:_>4}**".into(),
prefix_len: 2,
suffix_len: 15,
@@ -422,6 +437,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberPlus),
alignment_spec: Some(Align::Right),
width: Some(4),
+ precision: None,
suffix: "**".into(),
prefix_len: 5,
suffix_len: 2,
@@ -439,6 +455,7 @@ pub mod tests {
placeholder: None,
alignment_spec: None,
width: None,
+ precision: None,
suffix: "__@@---**".into(),
prefix_len: 0,
suffix_len: 9,
@@ -455,12 +472,14 @@ pub mod tests {
placeholder: Some(Placeholder::NumberMinus),
alignment_spec: Some(Align::Left),
width: Some(4),
+ precision: None,
suffix: "|".into(),
prefix_len: 2,
suffix_len: 1,
}]
);
}
+
#[test]
fn test_line_number_format_odd_width_two() {
assert_eq!(
@@ -475,6 +494,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberMinus),
alignment_spec: Some(Align::Left),
width: Some(4),
+ precision: None,
suffix: "+{np:<4}|".into(),
prefix_len: 2,
suffix_len: 9,
@@ -484,6 +504,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberPlus),
alignment_spec: Some(Align::Left),
width: Some(4),
+ precision: None,
suffix: "|".into(),
prefix_len: 1,
suffix_len: 1,
@@ -500,6 +521,7 @@ pub mod tests {
placeholder: None,
alignment_spec: None,
width: None,
+ precision: None,
suffix: "|++|".into(),
prefix_len: 1,
suffix_len: 4,
@@ -522,6 +544,7 @@ pub mod tests {
placeholder: Some(Placeholder::NumberMinus),
alignment_spec: None,
width: None,
+ precision: None,
suffix: long.into(),
suffix_len: long.len(),
},]
diff --git a/src/format.rs b/src/format.rs
index bbc6e9f5..ab0e856f 100644
--- a/src/format.rs
+++ b/src/format.rs
@@ -55,6 +55,7 @@ pub struct FormatStringPlaceholderData<'a> {
pub placeholder: Option<Placeholder<'a>>,
pub alignment_spec: Option<Align>,
pub width: Option<usize>,
+ pub precision: Option<usize>,
pub suffix: SmolStr,
pub suffix_len: usize,
}
@@ -90,6 +91,9 @@ pub fn make_placeholder_regex(labels: &[&str]) -> Regex {
([<^>]) # 3: Alignment spec
)? #
(\d+) # 4: Width
+ (?: # Start optional precision (non-capturing)
+ \.(\d+) # 5: Precision
+ )? #
)? #
\}}
",
@@ -134,6 +138,11 @@ pub fn parse_line_number_format<'a>(
.parse()
.unwrap_or_else(|_| panic!("Invalid width in format string: {}", format_string))
}),
+ precision: captures.get(5).map(|m| {
+ m.as_str().parse().unwrap_or_else(|_| {
+ panic!("Invalid precision in format string: {}", format_string)
+ })
+ }),
suffix,
suffix_len,
});
@@ -156,10 +165,42 @@ pub fn parse_line_number_format<'a>(
format_data
}
-pub fn pad(s: &str, width: usize, alignment: &Align) -> String {
- match alignment {
- Align::Left => format!("{0:<1$}", s, width),
- Align::Center => format!("{0:^1$}", s, width),
- Align::Right => format!("{0:>1$}", s, width),
+// Note that in this case of a string `s`, `precision` means "max width".
+// See https://doc.rust-lang.org/std/fmt/index.html
+pub fn pad(s: &str, width: usize, alignment: &Align, precision: Option<usize>) -> String {
+ match precision {
+ None => match alignment {
+ Align::Left => format!("{0:<1$}", s, width),
+ Align::Center => format!("{0:^1$}", s, width),
+ Align::Right => format!("{0:>1$}", s, width),
+ },
+ Some(precision) => match alignment {
+ Align::Left => format!("{0:<1$.2$}", s, width, precision),
+ Align::Center => format!("{0:^1$.2$}", s, width, precision),
+ Align::Right => format!("{0:>1$.2$}", s, width, precision),
+ },
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_placeholder_regex() {
+ let regex = make_placeholder_regex(&["placeholder"]);
+ assert_eq!(
+ parse_line_number_format("prefix {placeholder:<15.14} suffix", &regex, false),
+ vec![FormatStringPlaceholderData {
+ prefix: "prefix ".into(),
+ placeholder: Some(Placeholder::Str("placeholder")),
+ alignment_spec: Some(Align::Left),
+ width: Some(15),
+ precision: Some(14),
+ suffix: " suffix".into(),
+ prefix_len: 7,
+ suffix_len: 7,
+ }]
+ );
}
}