feat: automatically add indent on entering in the empty block math (#646)

This commit is contained in:
Myriad-Dreamin 2024-10-09 14:22:36 +08:00 committed by GitHub
parent 5ae003efcd
commit 2334593ec4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 9 deletions

View file

@ -1,6 +1,6 @@
use typst_shim::syntax::LinkedNodeExt;
use crate::{prelude::*, SemanticRequest};
use crate::{prelude::*, syntax::node_ancestors, SemanticRequest};
/// The [`textDocument/documentHighlight`] request
///
@ -120,7 +120,7 @@ impl<'a, 'w> DocumentHighlightWorker<'a, 'w> {
let _ = self.ctx;
// find the nearest loop node
let loop_node = ancestors(node)
let loop_node = node_ancestors(node)
.find(|node| matches!(node.kind(), SyntaxKind::ForLoop | SyntaxKind::WhileLoop))?;
// find the first key word of the loop node
@ -146,10 +146,6 @@ fn highlight_func_returns(
None
}
fn ancestors<'a>(node: &'a LinkedNode<'a>) -> impl Iterator<Item = &'a LinkedNode<'a>> {
std::iter::successors(Some(node), |node| node.parent())
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -2,7 +2,7 @@
use typst_shim::syntax::LinkedNodeExt;
use crate::{prelude::*, SyntaxRequest};
use crate::{prelude::*, syntax::node_ancestors, SyntaxRequest};
/// The [`experimental/onEnter`] request is sent from client to server to handle
/// the <kbd>Enter</kbd> key press.
@ -45,6 +45,12 @@ impl SyntaxRequest for OnEnterRequest {
return worker.enter_line_doc_comment(&leaf, cursor);
}
let math_node =
node_ancestors(&leaf).find(|node| matches!(node.kind(), SyntaxKind::Equation));
if let Some(mn) = math_node {
return worker.enter_block_math(mn, cursor);
}
None
}
}
@ -55,6 +61,13 @@ struct OnEnterWorker<'a> {
}
impl OnEnterWorker<'_> {
fn indent_of(&self, of: usize) -> String {
let all_text = self.source.text();
let start = all_text[..of].rfind('\n').map(|e| e + 1);
let indent_size = all_text[start.unwrap_or_default()..of].chars().count();
" ".repeat(indent_size)
}
fn enter_line_doc_comment(&self, leaf: &LinkedNode, cursor: usize) -> Option<Vec<TextEdit>> {
let skipper = |n: &LinkedNode| {
matches!(
@ -84,8 +97,7 @@ impl OnEnterWorker<'_> {
return None;
}
// todo: indent
let indent = "";
let indent = self.indent_of(leaf.offset());
// todo: remove_trailing_whitespace
let rng = cursor..cursor;
@ -97,4 +109,32 @@ impl OnEnterWorker<'_> {
Some(vec![edit])
}
fn enter_block_math(&self, math_node: &LinkedNode<'_>, cursor: usize) -> Option<Vec<TextEdit>> {
let o = math_node.range();
if !o.contains(&cursor) {
return None;
}
let all_text = self.source.text();
let math_text = &all_text[o.clone()];
let content = math_text.trim_start_matches('$').trim_end_matches('$');
if !content.trim().is_empty() {
return None;
}
let indent = self.indent_of(o.start);
let rng = cursor..cursor;
let edit = TextEdit {
range: typst_to_lsp::range(rng, self.source, self.position_encoding),
// todo: read indent configuration
new_text: if !content.contains('\n') {
format!("\n{indent} $0\n{indent}")
} else {
format!("\n{indent} $0")
},
};
Some(vec![edit])
}
}

View file

@ -44,6 +44,10 @@ pub(crate) fn find_expr_in_import(mut node: LinkedNode) -> Option<LinkedNode> {
None
}
pub fn node_ancestors<'a>(node: &'a LinkedNode<'a>) -> impl Iterator<Item = &'a LinkedNode<'a>> {
std::iter::successors(Some(node), |node| node.parent())
}
fn is_mark(sk: SyntaxKind) -> bool {
use SyntaxKind::*;
matches!(