mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 01:42:14 +00:00
feat: lsp label descriptions for labels (#228)
This commit is contained in:
parent
0a76b4b18a
commit
97043b9789
3 changed files with 51 additions and 17 deletions
|
@ -78,36 +78,59 @@ pub fn analyze_import(world: &dyn World, source: &LinkedNode) -> Option<Value> {
|
||||||
.map(Value::Module)
|
.map(Value::Module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A label with a description and details.
|
||||||
|
pub struct DynLabel {
|
||||||
|
/// The label itself.
|
||||||
|
pub label: Label,
|
||||||
|
/// A description of the label.
|
||||||
|
pub label_desc: Option<EcoString>,
|
||||||
|
/// Additional details about the label.
|
||||||
|
pub detail: Option<EcoString>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Find all labels and details for them.
|
/// Find all labels and details for them.
|
||||||
///
|
///
|
||||||
/// Returns:
|
/// Returns:
|
||||||
/// - All labels and descriptions for them, if available
|
/// - All labels and descriptions for them, if available
|
||||||
/// - A split offset: All labels before this offset belong to nodes, all after
|
/// - A split offset: All labels before this offset belong to nodes, all after
|
||||||
/// belong to a bibliography.
|
/// belong to a bibliography.
|
||||||
pub fn analyze_labels(document: &Document) -> (Vec<(Label, Option<EcoString>)>, usize) {
|
pub fn analyze_labels(document: &Document) -> (Vec<DynLabel>, usize) {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
// Labels in the document.
|
// Labels in the document.
|
||||||
for elem in document.introspector.all() {
|
for elem in document.introspector.all() {
|
||||||
let Some(label) = elem.label() else { continue };
|
let Some(label) = elem.label() else { continue };
|
||||||
let details = elem
|
let (is_derived, details) = {
|
||||||
.get_by_name("caption")
|
let derived = elem
|
||||||
.or_else(|| elem.get_by_name("body"))
|
.get_by_name("caption")
|
||||||
.and_then(|field| match field {
|
.or_else(|| elem.get_by_name("body"));
|
||||||
Value::Content(content) => Some(content),
|
|
||||||
_ => None,
|
match derived {
|
||||||
})
|
Some(Value::Content(content)) => (true, content.plain_text()),
|
||||||
.as_ref()
|
Some(Value::Str(s)) => (true, s.into()),
|
||||||
.unwrap_or(elem)
|
_ => (false, elem.plain_text()),
|
||||||
.plain_text();
|
}
|
||||||
output.push((label, Some(details)));
|
};
|
||||||
|
output.push(DynLabel {
|
||||||
|
label,
|
||||||
|
label_desc: Some(if is_derived {
|
||||||
|
details.clone()
|
||||||
|
} else {
|
||||||
|
eco_format!("{}(..)", elem.func().name())
|
||||||
|
}),
|
||||||
|
detail: Some(details),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let split = output.len();
|
let split = output.len();
|
||||||
|
|
||||||
// Bibliography keys.
|
// Bibliography keys.
|
||||||
for (key, detail) in BibliographyElem::keys(document.introspector.track()) {
|
for (key, detail) in BibliographyElem::keys(document.introspector.track()) {
|
||||||
output.push((Label::new(&key), detail));
|
output.push(DynLabel {
|
||||||
|
label: Label::new(&key),
|
||||||
|
label_desc: detail.clone(),
|
||||||
|
detail,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
(output, split)
|
(output, split)
|
||||||
|
|
|
@ -17,7 +17,7 @@ use typst::visualize::Color;
|
||||||
use unscanny::Scanner;
|
use unscanny::Scanner;
|
||||||
|
|
||||||
use super::{plain_docs_sentence, summarize_font_family};
|
use super::{plain_docs_sentence, summarize_font_family};
|
||||||
use crate::analysis::{analyze_expr, analyze_import, analyze_labels};
|
use crate::analysis::{analyze_expr, analyze_import, analyze_labels, DynLabel};
|
||||||
use crate::AnalysisContext;
|
use crate::AnalysisContext;
|
||||||
|
|
||||||
mod ext;
|
mod ext;
|
||||||
|
@ -1144,7 +1144,12 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
|
||||||
(0, split)
|
(0, split)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (label, detail) in labels.into_iter().skip(skip).take(take) {
|
for DynLabel {
|
||||||
|
label,
|
||||||
|
label_desc,
|
||||||
|
detail,
|
||||||
|
} in labels.into_iter().skip(skip).take(take)
|
||||||
|
{
|
||||||
self.completions.push(Completion {
|
self.completions.push(Completion {
|
||||||
kind: CompletionKind::Constant,
|
kind: CompletionKind::Constant,
|
||||||
apply: (open || close).then(|| {
|
apply: (open || close).then(|| {
|
||||||
|
@ -1155,6 +1160,7 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
|
||||||
if close { ">" } else { "" }
|
if close { ">" } else { "" }
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
label_detail: label_desc,
|
||||||
label: label.as_str().into(),
|
label: label.as_str().into(),
|
||||||
detail,
|
detail,
|
||||||
..Completion::default()
|
..Completion::default()
|
||||||
|
|
|
@ -11,7 +11,7 @@ use typst::util::{round_2, Numeric};
|
||||||
use typst::World;
|
use typst::World;
|
||||||
|
|
||||||
use super::summarize_font_family;
|
use super::summarize_font_family;
|
||||||
use crate::analysis::{analyze_expr, analyze_labels};
|
use crate::analysis::{analyze_expr, analyze_labels, DynLabel};
|
||||||
|
|
||||||
/// Describe the item under the cursor.
|
/// Describe the item under the cursor.
|
||||||
///
|
///
|
||||||
|
@ -161,7 +161,12 @@ fn label_tooltip(document: &Document, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (label, detail) in analyze_labels(document).0 {
|
for DynLabel {
|
||||||
|
label,
|
||||||
|
label_desc: _,
|
||||||
|
detail,
|
||||||
|
} in analyze_labels(document).0
|
||||||
|
{
|
||||||
if label.as_str() == target {
|
if label.as_str() == target {
|
||||||
return Some(Tooltip::Text(detail?));
|
return Some(Tooltip::Text(detail?));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue