|
|
@ -247,41 +247,18 @@ fn add_indent_level(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Computes for node and all ancestors whether they are the first node on their line.
|
|
|
|
/// Return true if only whitespace comes before the node on its line.
|
|
|
|
/// The first entry in the return value represents the root node, the last one the node itself
|
|
|
|
/// If given, new_line_byte_pos is treated the same way as any existing newline.
|
|
|
|
fn get_first_in_line(mut node: Node, new_line_byte_pos: Option<usize>) -> Vec<bool> {
|
|
|
|
fn is_first_in_line(node: Node, text: RopeSlice, new_line_byte_pos: Option<usize>) -> bool {
|
|
|
|
let mut first_in_line = Vec::new();
|
|
|
|
let mut line_start_byte_pos = text.line_to_byte(node.start_position().row);
|
|
|
|
loop {
|
|
|
|
if let Some(pos) = new_line_byte_pos {
|
|
|
|
if let Some(prev) = node.prev_sibling() {
|
|
|
|
if line_start_byte_pos < pos && pos <= node.start_byte() {
|
|
|
|
// If we insert a new line, the first node at/after the cursor is considered to be the first in its line
|
|
|
|
line_start_byte_pos = pos;
|
|
|
|
let first = prev.end_position().row != node.start_position().row
|
|
|
|
}
|
|
|
|
|| new_line_byte_pos.map_or(false, |byte_pos| {
|
|
|
|
}
|
|
|
|
node.start_byte() >= byte_pos && prev.start_byte() < byte_pos
|
|
|
|
text.byte_slice(line_start_byte_pos..node.start_byte())
|
|
|
|
});
|
|
|
|
.chars()
|
|
|
|
first_in_line.push(Some(first));
|
|
|
|
.all(|c| c.is_whitespace())
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// Nodes that have no previous siblings are first in their line if and only if their parent is
|
|
|
|
|
|
|
|
// (which we don't know yet)
|
|
|
|
|
|
|
|
first_in_line.push(None);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(parent) = node.parent() {
|
|
|
|
|
|
|
|
node = parent;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut result = Vec::with_capacity(first_in_line.len());
|
|
|
|
|
|
|
|
let mut parent_is_first = true; // The root node is by definition the first node in its line
|
|
|
|
|
|
|
|
for first in first_in_line.into_iter().rev() {
|
|
|
|
|
|
|
|
if let Some(first) = first {
|
|
|
|
|
|
|
|
result.push(first);
|
|
|
|
|
|
|
|
parent_is_first = first;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
result.push(parent_is_first);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
result
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// The total indent for some line of code.
|
|
|
|
/// The total indent for some line of code.
|
|
|
@ -852,7 +829,6 @@ pub fn treesitter_indent_for_pos<'a>(
|
|
|
|
byte_pos,
|
|
|
|
byte_pos,
|
|
|
|
new_line_byte_pos,
|
|
|
|
new_line_byte_pos,
|
|
|
|
)?;
|
|
|
|
)?;
|
|
|
|
let mut first_in_line = get_first_in_line(node, new_line.then_some(byte_pos));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut result = Indentation::default();
|
|
|
|
let mut result = Indentation::default();
|
|
|
|
// We always keep track of all the indent changes on one line, in order to only indent once
|
|
|
|
// We always keep track of all the indent changes on one line, in order to only indent once
|
|
|
@ -861,9 +837,7 @@ pub fn treesitter_indent_for_pos<'a>(
|
|
|
|
let mut indent_for_line_below = Indentation::default();
|
|
|
|
let mut indent_for_line_below = Indentation::default();
|
|
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
loop {
|
|
|
|
// This can safely be unwrapped because `first_in_line` contains
|
|
|
|
let is_first = is_first_in_line(node, text, new_line_byte_pos);
|
|
|
|
// one entry for each ancestor of the node (which is what we iterate over)
|
|
|
|
|
|
|
|
let is_first = *first_in_line.last().unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Apply all indent definitions for this node.
|
|
|
|
// Apply all indent definitions for this node.
|
|
|
|
// Since we only iterate over each node once, we can remove the
|
|
|
|
// Since we only iterate over each node once, we can remove the
|
|
|
@ -906,7 +880,6 @@ pub fn treesitter_indent_for_pos<'a>(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
node = parent;
|
|
|
|
node = parent;
|
|
|
|
first_in_line.pop();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Only add the indentation for the line below if that line
|
|
|
|
// Only add the indentation for the line below if that line
|
|
|
|
// is not after the line that the indentation is calculated for.
|
|
|
|
// is not after the line that the indentation is calculated for.
|
|
|
|