From: Ian Jackson Date: Sun, 10 May 2026 10:22:24 +0000 (+0100) Subject: LitLinesCrlf rework X-Git-Tag: debian/1.3.3~5^2~4 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=ae4f9aff0d4156ce2c3d5a30c35a7793efe3c3c0;p=hippotat.git 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 --- 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(()) } }