mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 01:16:18 +04:00
wip
This commit is contained in:
parent
15714ac32e
commit
6db03fa41d
@ -240,7 +240,7 @@ fn get_first_in_line(mut node: Node, new_line_byte_pos: Option<usize>) -> Vec<bo
|
|||||||
/// This is usually constructed in one of 2 ways:
|
/// This is usually constructed in one of 2 ways:
|
||||||
/// - Successively add indent captures to get the (added) indent from a single line
|
/// - Successively add indent captures to get the (added) indent from a single line
|
||||||
/// - Successively add the indent results for each line
|
/// - Successively add the indent results for each line
|
||||||
#[derive(Default)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Indentation {
|
pub struct Indentation {
|
||||||
/// The total indent (the number of indent levels) is defined as max(0, indent-outdent).
|
/// The total indent (the number of indent levels) is defined as max(0, indent-outdent).
|
||||||
/// The string that this results in depends on the indent style (spaces or tabs, etc.)
|
/// The string that this results in depends on the indent style (spaces or tabs, etc.)
|
||||||
@ -281,11 +281,12 @@ fn as_string(&self, indent_style: &IndentStyle) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An indent definition which corresponds to a capture from the indent query
|
/// An indent definition which corresponds to a capture from the indent query
|
||||||
|
#[derive(Debug)]
|
||||||
struct IndentCapture {
|
struct IndentCapture {
|
||||||
capture_type: IndentCaptureType,
|
capture_type: IndentCaptureType,
|
||||||
scope: IndentScope,
|
scope: IndentScope,
|
||||||
}
|
}
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum IndentCaptureType {
|
enum IndentCaptureType {
|
||||||
Indent,
|
Indent,
|
||||||
Outdent,
|
Outdent,
|
||||||
@ -301,7 +302,7 @@ fn default_scope(&self) -> IndentScope {
|
|||||||
/// This defines which part of a node an [IndentCapture] applies to.
|
/// This defines which part of a node an [IndentCapture] applies to.
|
||||||
/// Each [IndentCaptureType] has a default scope, but the scope can be changed
|
/// Each [IndentCaptureType] has a default scope, but the scope can be changed
|
||||||
/// with `#set!` property declarations.
|
/// with `#set!` property declarations.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum IndentScope {
|
enum IndentScope {
|
||||||
/// The indent applies to the whole node
|
/// The indent applies to the whole node
|
||||||
All,
|
All,
|
||||||
@ -311,6 +312,7 @@ enum IndentScope {
|
|||||||
|
|
||||||
/// A capture from the indent query which does not define an indent but extends
|
/// A capture from the indent query which does not define an indent but extends
|
||||||
/// the range of a node. This is used before the indent is calculated.
|
/// the range of a node. This is used before the indent is calculated.
|
||||||
|
#[derive(Debug)]
|
||||||
enum ExtendCapture {
|
enum ExtendCapture {
|
||||||
Extend,
|
Extend,
|
||||||
PreventOnce,
|
PreventOnce,
|
||||||
@ -319,6 +321,7 @@ enum ExtendCapture {
|
|||||||
/// The result of running a tree-sitter indent query. This stores for
|
/// The result of running a tree-sitter indent query. This stores for
|
||||||
/// each node (identified by its ID) the relevant captures (already filtered
|
/// each node (identified by its ID) the relevant captures (already filtered
|
||||||
/// by predicates).
|
/// by predicates).
|
||||||
|
#[derive(Debug)]
|
||||||
struct IndentQueryResult {
|
struct IndentQueryResult {
|
||||||
indent_captures: HashMap<usize, Vec<IndentCapture>>,
|
indent_captures: HashMap<usize, Vec<IndentCapture>>,
|
||||||
extend_captures: HashMap<usize, Vec<ExtendCapture>>,
|
extend_captures: HashMap<usize, Vec<ExtendCapture>>,
|
||||||
@ -337,8 +340,39 @@ fn query_indents(
|
|||||||
let mut indent_captures: HashMap<usize, Vec<IndentCapture>> = HashMap::new();
|
let mut indent_captures: HashMap<usize, Vec<IndentCapture>> = HashMap::new();
|
||||||
let mut extend_captures: HashMap<usize, Vec<ExtendCapture>> = HashMap::new();
|
let mut extend_captures: HashMap<usize, Vec<ExtendCapture>> = HashMap::new();
|
||||||
cursor.set_byte_range(range);
|
cursor.set_byte_range(range);
|
||||||
|
|
||||||
|
enum End {
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
let get_line_num = |node: Node, end: End| {
|
||||||
|
let get_position = match end {
|
||||||
|
End::Start => Node::start_position,
|
||||||
|
End::End => Node::end_position,
|
||||||
|
};
|
||||||
|
|
||||||
|
let get_byte = match end {
|
||||||
|
End::Start => Node::start_byte,
|
||||||
|
End::End => Node::end_byte,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut node_line = get_position(&node).row;
|
||||||
|
|
||||||
|
// Adjust for the new line that will be inserted
|
||||||
|
if let Some((line, byte)) = new_line_break {
|
||||||
|
if node_line == line && get_byte(&node) >= byte {
|
||||||
|
node_line += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node_line
|
||||||
|
};
|
||||||
|
|
||||||
// Iterate over all captures from the query
|
// Iterate over all captures from the query
|
||||||
for m in cursor.matches(query, syntax.tree().root_node(), RopeProvider(text)) {
|
for m in cursor.matches(query, syntax.tree().root_node(), RopeProvider(text)) {
|
||||||
|
log::debug!("{:?}", m);
|
||||||
|
|
||||||
// Skip matches where not all custom predicates are fulfilled
|
// Skip matches where not all custom predicates are fulfilled
|
||||||
if !query.general_predicates(m.pattern_index).iter().all(|pred| {
|
if !query.general_predicates(m.pattern_index).iter().all(|pred| {
|
||||||
match pred.operator.as_ref() {
|
match pred.operator.as_ref() {
|
||||||
@ -363,21 +397,14 @@ fn query_indents(
|
|||||||
Some(QueryPredicateArg::Capture(capt1)),
|
Some(QueryPredicateArg::Capture(capt1)),
|
||||||
Some(QueryPredicateArg::Capture(capt2))
|
Some(QueryPredicateArg::Capture(capt2))
|
||||||
) => {
|
) => {
|
||||||
let get_line_num = |node: Node| {
|
|
||||||
let mut node_line = node.start_position().row;
|
|
||||||
// Adjust for the new line that will be inserted
|
|
||||||
if let Some((line, byte)) = new_line_break {
|
|
||||||
if node_line==line && node.start_byte()>=byte {
|
|
||||||
node_line += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node_line
|
|
||||||
};
|
|
||||||
let n1 = m.nodes_for_capture_index(*capt1).next();
|
let n1 = m.nodes_for_capture_index(*capt1).next();
|
||||||
let n2 = m.nodes_for_capture_index(*capt2).next();
|
let n2 = m.nodes_for_capture_index(*capt2).next();
|
||||||
match (n1, n2) {
|
match (n1, n2) {
|
||||||
(Some(n1), Some(n2)) => {
|
(Some(n1), Some(n2)) => {
|
||||||
let same_line = get_line_num(n1)==get_line_num(n2);
|
let n1_line = get_line_num(n1, End::Start);
|
||||||
|
let n2_line = get_line_num(n2, End::Start);
|
||||||
|
log::debug!("n1 line: {}, n2 line: {}", n1_line, n2_line);
|
||||||
|
let same_line = n1_line == n2_line;
|
||||||
same_line==(pred.operator.as_ref()=="same-line?")
|
same_line==(pred.operator.as_ref()=="same-line?")
|
||||||
}
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
@ -388,6 +415,46 @@ fn query_indents(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"same-lines?" | "not-same-lines?" => {
|
||||||
|
match (pred.args.get(0), pred.args.get(1)) {
|
||||||
|
(
|
||||||
|
Some(QueryPredicateArg::Capture(capt1)),
|
||||||
|
Some(QueryPredicateArg::Capture(capt2))
|
||||||
|
) => {
|
||||||
|
let n1 = m.nodes_for_capture_index(*capt1).next();
|
||||||
|
let n2 = m.nodes_for_capture_index(*capt2).next();
|
||||||
|
match (n1, n2) {
|
||||||
|
(Some(n1), Some(n2)) => {
|
||||||
|
let n1_line_span = (get_line_num(n1, End::Start), get_line_num(n1, End::End));
|
||||||
|
let n2_line_span = (get_line_num(n2, End::Start), get_line_num(n2, End::End));
|
||||||
|
let same_lines = n1_line_span == n2_line_span;
|
||||||
|
same_lines == (pred.operator.as_ref() == "same-lines?")
|
||||||
|
}
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Invalid indent query: Arguments to \"{}\" must be 2 captures", pred.operator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"one-line?" | "not-one-line?" => match pred.args.get(0) {
|
||||||
|
Some(QueryPredicateArg::Capture(capture_idx)) => {
|
||||||
|
let node = m.nodes_for_capture_index(*capture_idx).next();
|
||||||
|
|
||||||
|
match node {
|
||||||
|
Some(node) => {
|
||||||
|
let (start_line, end_line) = (get_line_num(node, End::Start), get_line_num(node, End::End));
|
||||||
|
let one_line = end_line - start_line == 1;
|
||||||
|
one_line == (pred.operator.as_ref() == "one-line?")
|
||||||
|
},
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("Invalid indent query: Arguments to \"not-kind-eq?\" must be a capture and a string");
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!(
|
panic!(
|
||||||
"Invalid indent query: Unknown predicate (\"{}\")",
|
"Invalid indent query: Unknown predicate (\"{}\")",
|
||||||
@ -398,6 +465,9 @@ fn query_indents(
|
|||||||
}) {
|
}) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::debug!("passed predicates");
|
||||||
|
|
||||||
for capture in m.captures {
|
for capture in m.captures {
|
||||||
let capture_name = query.capture_names()[capture.index as usize].as_str();
|
let capture_name = query.capture_names()[capture.index as usize].as_str();
|
||||||
let capture_type = match capture_name {
|
let capture_type = match capture_name {
|
||||||
@ -459,10 +529,15 @@ fn query_indents(
|
|||||||
.push(indent_capture);
|
.push(indent_capture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IndentQueryResult {
|
|
||||||
|
let result = IndentQueryResult {
|
||||||
indent_captures,
|
indent_captures,
|
||||||
extend_captures,
|
extend_captures,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
log::debug!("{:?}", result);
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle extend queries. deepest_preceding is the deepest descendant of node that directly precedes the cursor position.
|
/// Handle extend queries. deepest_preceding is the deepest descendant of node that directly precedes the cursor position.
|
||||||
@ -651,6 +726,7 @@ pub fn treesitter_indent_for_pos(
|
|||||||
let is_first = *first_in_line.last().unwrap();
|
let is_first = *first_in_line.last().unwrap();
|
||||||
// Apply all indent definitions for this node
|
// Apply all indent definitions for this node
|
||||||
if let Some(definitions) = indent_captures.get(&node.id()) {
|
if let Some(definitions) = indent_captures.get(&node.id()) {
|
||||||
|
log::debug!("found def: {:?}", definitions);
|
||||||
for definition in definitions {
|
for definition in definitions {
|
||||||
match definition.scope {
|
match definition.scope {
|
||||||
IndentScope::All => {
|
IndentScope::All => {
|
||||||
@ -667,9 +743,13 @@ pub fn treesitter_indent_for_pos(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::debug!("indent for line: {:?}", indent_for_line);
|
||||||
|
log::debug!("indent for line below: {:?}", indent_for_line_below);
|
||||||
|
|
||||||
if let Some(parent) = node.parent() {
|
if let Some(parent) = node.parent() {
|
||||||
let mut node_line = node.start_position().row;
|
let mut node_line = node.start_position().row;
|
||||||
let mut parent_line = parent.start_position().row;
|
let mut parent_line = parent.start_position().row;
|
||||||
|
|
||||||
if node_line == line && new_line {
|
if node_line == line && new_line {
|
||||||
// Also consider the line that will be inserted
|
// Also consider the line that will be inserted
|
||||||
if node.start_byte() >= byte_pos {
|
if node.start_byte() >= byte_pos {
|
||||||
@ -679,17 +759,26 @@ pub fn treesitter_indent_for_pos(
|
|||||||
parent_line += 1;
|
parent_line += 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::debug!("node line: {:?}", node_line);
|
||||||
|
log::debug!("found parent line: {:?}", parent_line);
|
||||||
|
|
||||||
if node_line != parent_line {
|
if node_line != parent_line {
|
||||||
if node_line < line + (new_line as usize) {
|
if node_line < line + (new_line as usize) {
|
||||||
// Don't add indent for the line below the line of the query
|
// Don't add indent for the line below the line of the query
|
||||||
result.add_line(&indent_for_line_below);
|
result.add_line(&indent_for_line_below);
|
||||||
|
log::debug!("added indent for line below: {:?}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if node_line == parent_line + 1 {
|
if node_line == parent_line + 1 {
|
||||||
indent_for_line_below = indent_for_line;
|
indent_for_line_below = indent_for_line;
|
||||||
|
log::debug!("moved up a line");
|
||||||
} else {
|
} else {
|
||||||
result.add_line(&indent_for_line);
|
result.add_line(&indent_for_line);
|
||||||
indent_for_line_below = Indentation::default();
|
indent_for_line_below = Indentation::default();
|
||||||
|
log::debug!("added indent for current line: {:?}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
indent_for_line = Indentation::default();
|
indent_for_line = Indentation::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,6 +796,9 @@ pub fn treesitter_indent_for_pos(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::debug!("{:?}", result);
|
||||||
|
|
||||||
Some(result.as_string(indent_style))
|
Some(result.as_string(indent_style))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user