From 2ae4839ce0596ddc618c8bee85c3b6a19bc8f382 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Thu, 21 Dec 2023 12:27:34 -0500 Subject: [PATCH] Remove common whitespace prefix from src block lines. --- src/intermediate/src_block.rs | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/intermediate/src_block.rs b/src/intermediate/src_block.rs index 5ec4520..145f2ed 100644 --- a/src/intermediate/src_block.rs +++ b/src/intermediate/src_block.rs @@ -14,12 +14,60 @@ intermediate!( original, _registry, { - let lines = original - .get_value() + let source_code = original.get_value(); + let prefix_content_pairs: Vec<_> = source_code .split_inclusive('\n') - .map(|s| s.to_owned()) + .map(|line| { + line.find(|c: char| !c.is_ascii_whitespace() && c != '\n') + .map(|content_start| line.split_at(content_start)) + .map(|(leading_whitespace, content)| { + ( + leading_whitespace + .chars() + .map(ascii_whitespace_value) + .sum::(), + content, + ) + }) + .unwrap_or((0, line)) + }) + .collect(); + let common_whitespace_prefix = prefix_content_pairs + .iter() + .filter_map(|(leading_whitespace, _content)| { + if *leading_whitespace > 0 { + Some(*leading_whitespace) + } else { + None + } + }) + .min() + .unwrap_or(0); + let lines: Vec<_> = prefix_content_pairs + .into_iter() + .map(|(leading_whitespace, content)| { + let mut line = String::with_capacity(common_whitespace_prefix + content.len()); + if leading_whitespace > common_whitespace_prefix { + // Empty lines can have a leading_whitespace less than common_whitespace_prefix. + for _ in 0..(leading_whitespace - common_whitespace_prefix) { + line.push(' '); + } + } + line.push_str(content); + line + }) .collect(); let language = original.language.map(str::to_owned); Ok(ISrcBlock { lines, language }) } ); + +fn ascii_whitespace_value(c: char) -> usize { + match c { + ' ' => 1, + '\t' => 8, + '\r' | '\n' => 0, + c if c as u32 == 12 => 0, // form feed + _ => unreachable!("Only ascii whitespace can reach this code."), + } +}