summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-ide/src/complete.rs45
-rw-r--r--crates/typst-ide/src/tooltip.rs2
-rw-r--r--crates/typst-ide/src/utils.rs11
-rw-r--r--crates/typst-library/src/text/font/book.rs3
4 files changed, 49 insertions, 12 deletions
diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs
index 91fa53f9..15b4296e 100644
--- a/crates/typst-ide/src/complete.rs
+++ b/crates/typst-ide/src/complete.rs
@@ -15,7 +15,7 @@ use typst::syntax::{
ast, is_id_continue, is_id_start, is_ident, FileId, LinkedNode, Side, Source,
SyntaxKind,
};
-use typst::text::RawElem;
+use typst::text::{FontFlags, RawElem};
use typst::visualize::Color;
use unscanny::Scanner;
@@ -1081,6 +1081,24 @@ fn code_completions(ctx: &mut CompletionContext, hash: bool) {
}
}
+/// See if the AST node is somewhere within a show rule applying to equations
+fn is_in_equation_show_rule(leaf: &LinkedNode<'_>) -> bool {
+ let mut node = leaf;
+ while let Some(parent) = node.parent() {
+ if_chain! {
+ if let Some(expr) = parent.get().cast::<ast::Expr>();
+ if let ast::Expr::ShowRule(show) = expr;
+ if let Some(ast::Expr::FieldAccess(field)) = show.selector();
+ if field.field().as_str() == "equation";
+ then {
+ return true;
+ }
+ }
+ node = parent;
+ }
+ false
+}
+
/// Context for autocompletion.
struct CompletionContext<'a> {
world: &'a (dyn IdeWorld + 'a),
@@ -1152,10 +1170,12 @@ impl<'a> CompletionContext<'a> {
/// Add completions for all font families.
fn font_completions(&mut self) {
- let equation = self.before_window(25).contains("equation");
+ let equation = is_in_equation_show_rule(self.leaf);
for (family, iter) in self.world.book().families() {
- let detail = summarize_font_family(iter);
- if !equation || family.contains("Math") {
+ let variants: Vec<_> = iter.collect();
+ let is_math = variants.iter().any(|f| f.flags.contains(FontFlags::MATH));
+ let detail = summarize_font_family(variants);
+ if !equation || is_math {
self.str_completion(
family,
Some(CompletionKind::Font),
@@ -1790,4 +1810,21 @@ mod tests {
.must_include(["r", "dashed"])
.must_exclude(["cases"]);
}
+
+ #[test]
+ fn test_autocomplete_fonts() {
+ test("#text(font:)", -1)
+ .must_include(["\"Libertinus Serif\"", "\"New Computer Modern Math\""]);
+
+ test("#show link: set text(font: )", -1)
+ .must_include(["\"Libertinus Serif\"", "\"New Computer Modern Math\""]);
+
+ test("#show math.equation: set text(font: )", -1)
+ .must_include(["\"New Computer Modern Math\""])
+ .must_exclude(["\"Libertinus Serif\""]);
+
+ test("#show math.equation: it => { set text(font: )\nit }", -6)
+ .must_include(["\"New Computer Modern Math\""])
+ .must_exclude(["\"Libertinus Serif\""]);
+ }
}
diff --git a/crates/typst-ide/src/tooltip.rs b/crates/typst-ide/src/tooltip.rs
index 2638ce51..e5e4cc19 100644
--- a/crates/typst-ide/src/tooltip.rs
+++ b/crates/typst-ide/src/tooltip.rs
@@ -269,7 +269,7 @@ fn font_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
.find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str());
then {
- let detail = summarize_font_family(iter);
+ let detail = summarize_font_family(iter.collect());
return Some(Tooltip::Text(detail));
}
};
diff --git a/crates/typst-ide/src/utils.rs b/crates/typst-ide/src/utils.rs
index d5d584e2..887e851f 100644
--- a/crates/typst-ide/src/utils.rs
+++ b/crates/typst-ide/src/utils.rs
@@ -77,23 +77,20 @@ pub fn plain_docs_sentence(docs: &str) -> EcoString {
}
/// Create a short description of a font family.
-pub fn summarize_font_family<'a>(
- variants: impl Iterator<Item = &'a FontInfo>,
-) -> EcoString {
- let mut infos: Vec<_> = variants.collect();
- infos.sort_by_key(|info| info.variant);
+pub fn summarize_font_family(mut variants: Vec<&FontInfo>) -> EcoString {
+ variants.sort_by_key(|info| info.variant);
let mut has_italic = false;
let mut min_weight = u16::MAX;
let mut max_weight = 0;
- for info in &infos {
+ for info in &variants {
let weight = info.variant.weight.to_number();
has_italic |= info.variant.style == FontStyle::Italic;
min_weight = min_weight.min(weight);
max_weight = min_weight.max(weight);
}
- let count = infos.len();
+ let count = variants.len();
let mut detail = eco_format!("{count} variant{}.", if count == 1 { "" } else { "s" });
if min_weight == max_weight {
diff --git a/crates/typst-library/src/text/font/book.rs b/crates/typst-library/src/text/font/book.rs
index 9f8acce8..cd90a08f 100644
--- a/crates/typst-library/src/text/font/book.rs
+++ b/crates/typst-library/src/text/font/book.rs
@@ -194,6 +194,8 @@ bitflags::bitflags! {
const MONOSPACE = 1 << 0;
/// Glyphs have short strokes at their stems.
const SERIF = 1 << 1;
+ /// Font face has a MATH table
+ const MATH = 1 << 2;
}
}
@@ -272,6 +274,7 @@ impl FontInfo {
let mut flags = FontFlags::empty();
flags.set(FontFlags::MONOSPACE, ttf.is_monospaced());
+ flags.set(FontFlags::MATH, ttf.tables().math.is_some());
// Determine whether this is a serif or sans-serif font.
if let Some(panose) = ttf