use alloc::string::String;
use crate::detect::detect;
use crate::IndentStyle;
pub(crate) fn reindent(text: &str, to: IndentStyle) -> String {
let from = detect(text);
let from_unit = match from {
IndentStyle::Tabs => 1, IndentStyle::Spaces(n) if n > 0 => n,
_ => return String::from(text), };
let target = match to {
IndentStyle::Unknown | IndentStyle::Spaces(0) => return String::from(text),
other => other.unit(),
};
let mut out = String::new();
let mut lines = text.split('\n').peekable();
while let Some(line) = lines.next() {
if line.is_empty() || line.trim().is_empty() {
} else {
let (level, rest) = split_indent(line, from, from_unit);
for _ in 0..level {
out.push_str(&target);
}
out.push_str(rest);
}
if lines.peek().is_some() {
out.push('\n');
}
}
out
}
fn split_indent(line: &str, from: IndentStyle, from_unit: usize) -> (usize, &str) {
match from {
IndentStyle::Tabs => {
let tabs = line.bytes().take_while(|&b| b == b'\t').count();
(tabs, &line[tabs..])
}
IndentStyle::Spaces(_) => {
let spaces = line.bytes().take_while(|&b| b == b' ').count();
let level = spaces / from_unit;
(level, &line[level * from_unit..])
}
IndentStyle::Unknown => (0, line),
}
}