use ropey::RopeSlice;
use crate::editor::document::Document;
#[must_use]
pub fn first_non_blank(doc: &Document, line: usize) -> usize {
let slice = doc.line(line);
slice
.chars()
.position(|ch| !ch.is_whitespace())
.unwrap_or_else(|| doc.line_len(line))
}
#[must_use]
pub fn indent_of(doc: &Document, line: usize) -> String {
doc.line(line)
.chars()
.take_while(|ch| *ch == ' ' || *ch == '\t')
.collect()
}
#[must_use]
pub fn indent_unit(tab_width: usize, use_spaces: bool) -> String {
if use_spaces {
" ".repeat(tab_width)
} else {
"\t".to_string()
}
}
#[must_use]
pub fn auto_indent_for_new_line(
doc: &Document,
line: usize,
col: usize,
tab_width: usize,
use_spaces: bool,
) -> String {
let mut indent: String = indent_of(doc, line).chars().take(col).collect();
if opens_block(doc.line(line), col) {
indent.push_str(&indent_unit(tab_width, use_spaces));
}
indent
}
fn opens_block(slice: RopeSlice<'_>, col: usize) -> bool {
slice
.chars()
.take(col)
.filter(|ch| !ch.is_whitespace())
.last()
.is_some_and(|ch| matches!(ch, '{' | '[' | '(' | ':'))
}
#[must_use]
pub fn should_dedent(doc: &Document, line: usize, col: usize, ch: char) -> bool {
matches!(ch, '}' | ']' | ')')
&& col > 0
&& first_non_blank(doc, line) >= col
}