From ae4f9aff0d4156ce2c3d5a30c35a7793efe3c3c0 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 10 May 2026 11:22:24 +0100 Subject: [PATCH] LitLinesCrlf rework Use the indentation of the first nonempty line, rather than trimming all whitespace from the front of every line. That will let us do indented lines if we want. Cons rather less. Signed-off-by: Ian Jackson --- client/client.rs | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/client/client.rs b/client/client.rs index 04686eb..8251d98 100644 --- a/client/client.rs +++ b/client/client.rs @@ -29,20 +29,35 @@ pub struct LitLinesCrlf<'s>(pub &'s str); impl Display for LitLinesCrlf<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let input = &self.0; - - // TODO don't collect - // TODO more principled indentation handling - let output = input.split_inclusive('\n') - .map(|s| s.trim_start_matches(&[' ','\t'][..])) - .map(|s| match s.strip_suffix("\n") { - None => [s, ""], - Some(l) => [l, "\r\n"], - }) - .flatten() - .collect::(); - - write!(f, "{output}") + let input = self.0.split_inclusive('\n'); + + // Use indentation from first nonempty line + let indent = input.clone() + .filter_map(|l| { + let trimmed = l.trim_start(); + if trimmed.is_empty() { + None + } else { + Some(l.len() - trimmed.len()) + } + }) + .next() + .unwrap_or(0); + + for l in input { + let (l, nl) = l.strip_suffix("\n") + .map(|l| (l, Some(()))) + .unwrap_or((l, None)); + + let (spc, content) = l.split_at_checked(indent).unwrap_or((l, "")); + assert!(spc.trim().is_empty(), "non-blank indent {:?} in {:?}", spc, l); + write!(f, "{content}")?; + if let Some(()) = nl { + write!(f, "\r\n")?; + } + } + + Ok(()) } } -- 2.30.2