use crate::editor::IndentSettings;
use crate::syntax::Highlighter;
pub(super) fn strip_one_indent_level(indent: &str, settings: IndentSettings) -> String {
if indent.is_empty() {
return String::new();
}
if indent.ends_with('\t') {
let mut out = indent.to_string();
out.pop();
return out;
}
let trailing_spaces = indent.chars().rev().take_while(|c| *c == ' ').count();
if trailing_spaces == 0 {
return indent.to_string();
}
let w = settings.width.max(1);
let target = (trailing_spaces.saturating_sub(1) / w) * w;
let remove = trailing_spaces - target;
indent[..indent.len() - remove].to_string()
}
pub(super) fn copy_leading_indent(line: &str, _settings: IndentSettings) -> String {
line.chars()
.take_while(|c| c.is_whitespace() && *c != '\n')
.collect()
}
pub(super) fn compute_new_line_indent(
reference_line: &str,
ref_row: usize,
highlighter: &Option<Highlighter>,
settings: IndentSettings,
) -> String {
let base = copy_leading_indent(reference_line, settings);
let ts_begin = highlighter
.as_ref()
.is_some_and(|h| h.indent_begins_at(ref_row));
let trailing_opener = reference_line
.trim_end()
.chars()
.last()
.is_some_and(|c| matches!(c, '{' | '(' | '['));
if ts_begin || trailing_opener {
add_one_indent_level(&base, settings)
} else {
base
}
}
pub(super) fn add_one_indent_level(base: &str, settings: IndentSettings) -> String {
let use_tabs = if base.is_empty() {
settings.use_tabs
} else {
base.contains('\t')
};
let mut out = base.to_string();
if use_tabs {
out.push('\t');
} else {
for _ in 0..settings.width.max(1) {
out.push(' ');
}
}
out
}