mirror of
https://github.com/typst/typst
synced 2025-07-27 22:37:54 +08:00
Yeet if_chain
macro
This commit is contained in:
parent
c9c2315ad3
commit
e81a5a6ef2
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -1198,12 +1198,6 @@ dependencies = [
|
|||||||
"icu_properties",
|
"icu_properties",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "if_chain"
|
|
||||||
version = "1.0.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.25.5"
|
version = "0.25.5"
|
||||||
@ -2943,7 +2937,6 @@ version = "0.13.1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"comemo",
|
"comemo",
|
||||||
"ecow",
|
"ecow",
|
||||||
"if_chain",
|
|
||||||
"indexmap 2.7.1",
|
"indexmap 2.7.1",
|
||||||
"stacker",
|
"stacker",
|
||||||
"toml",
|
"toml",
|
||||||
@ -2991,7 +2984,6 @@ version = "0.13.1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"comemo",
|
"comemo",
|
||||||
"ecow",
|
"ecow",
|
||||||
"if_chain",
|
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pathdiff",
|
"pathdiff",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -68,7 +68,6 @@ icu_provider = { version = "1.4", features = ["sync"] }
|
|||||||
icu_provider_adapters = "1.4"
|
icu_provider_adapters = "1.4"
|
||||||
icu_provider_blob = "1.4"
|
icu_provider_blob = "1.4"
|
||||||
icu_segmenter = { version = "1.4", features = ["serde"] }
|
icu_segmenter = { version = "1.4", features = ["serde"] }
|
||||||
if_chain = "1"
|
|
||||||
image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif", "webp"] }
|
image = { version = "0.25.5", default-features = false, features = ["png", "jpeg", "gif", "webp"] }
|
||||||
indexmap = { version = "2", features = ["serde"] }
|
indexmap = { version = "2", features = ["serde"] }
|
||||||
infer = { version = "0.19.0", default-features = false }
|
infer = { version = "0.19.0", default-features = false }
|
||||||
|
@ -20,7 +20,6 @@ typst-timing = { workspace = true }
|
|||||||
typst-utils = { workspace = true }
|
typst-utils = { workspace = true }
|
||||||
comemo = { workspace = true }
|
comemo = { workspace = true }
|
||||||
ecow = { workspace = true }
|
ecow = { workspace = true }
|
||||||
if_chain = { workspace = true }
|
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
toml = { workspace = true }
|
toml = { workspace = true }
|
||||||
unicode-segmentation = { workspace = true }
|
unicode-segmentation = { workspace = true }
|
||||||
|
@ -324,22 +324,19 @@ impl Eval for ast::FieldAccess<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Check whether this is a get rule field access.
|
// Check whether this is a get rule field access.
|
||||||
if_chain::if_chain! {
|
if let Value::Func(func) = &value &&
|
||||||
if let Value::Func(func) = &value;
|
let Some(element) = func.element() &&
|
||||||
if let Some(element) = func.element();
|
let Some(id) = element.field_id(&field) &&
|
||||||
if let Some(id) = element.field_id(&field);
|
let styles = vm.context.styles().at(field.span()) &&
|
||||||
let styles = vm.context.styles().at(field.span());
|
let Ok(value) = element.field_from_styles(
|
||||||
if let Ok(value) = element.field_from_styles(
|
|
||||||
id,
|
id,
|
||||||
styles.as_ref().map(|&s| s).unwrap_or_default(),
|
styles.as_ref().map(|&s| s).unwrap_or_default(),
|
||||||
);
|
) {
|
||||||
then {
|
|
||||||
// Only validate the context once we know that this is indeed
|
// Only validate the context once we know that this is indeed
|
||||||
// a field from the style chain.
|
// a field from the style chain.
|
||||||
let _ = styles?;
|
let _ = styles?;
|
||||||
return Ok(value);
|
return Ok(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,11 @@ impl Eval for ast::ShowRule<'_> {
|
|||||||
|
|
||||||
/// Migration hint for `show par: set block(spacing: ..)`.
|
/// Migration hint for `show par: set block(spacing: ..)`.
|
||||||
fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) {
|
fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) {
|
||||||
if_chain::if_chain! {
|
if let Some(Selector::Elem(elem, _)) = recipe.selector() &&
|
||||||
if let Some(Selector::Elem(elem, _)) = recipe.selector();
|
*elem == Element::of::<ParElem>() &&
|
||||||
if *elem == Element::of::<ParElem>();
|
let Transformation::Style(styles) = recipe.transform() &&
|
||||||
if let Transformation::Style(styles) = recipe.transform();
|
(styles.has(BlockElem::above) || styles.has(BlockElem::below))
|
||||||
if styles.has(BlockElem::above) || styles.has(BlockElem::below);
|
{
|
||||||
then {
|
|
||||||
vm.engine.sink.warn(warning!(
|
vm.engine.sink.warn(warning!(
|
||||||
recipe.span(),
|
recipe.span(),
|
||||||
"`show par: set block(spacing: ..)` has no effect anymore";
|
"`show par: set block(spacing: ..)` has no effect anymore";
|
||||||
@ -71,4 +70,3 @@ fn check_show_par_set_block(vm: &mut Vm, recipe: &Recipe) {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -17,7 +17,6 @@ typst = { workspace = true }
|
|||||||
typst-eval = { workspace = true }
|
typst-eval = { workspace = true }
|
||||||
comemo = { workspace = true }
|
comemo = { workspace = true }
|
||||||
ecow = { workspace = true }
|
ecow = { workspace = true }
|
||||||
if_chain = { workspace = true }
|
|
||||||
pathdiff = { workspace = true }
|
pathdiff = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
unscanny = { workspace = true }
|
unscanny = { workspace = true }
|
||||||
|
@ -3,7 +3,6 @@ use std::collections::{BTreeMap, HashSet};
|
|||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
use if_chain::if_chain;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use typst::foundations::{
|
use typst::foundations::{
|
||||||
fields_on, repr, AutoValue, CastInfo, Func, Label, NoneValue, ParamInfo, Repr,
|
fields_on, repr, AutoValue, CastInfo, Func, Label, NoneValue, ParamInfo, Repr,
|
||||||
@ -145,27 +144,23 @@ fn complete_markup(ctx: &mut CompletionContext) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Behind a half-completed binding: "#let x = |".
|
// Behind a half-completed binding: "#let x = |".
|
||||||
if_chain! {
|
if let Some(prev) = ctx.leaf.prev_leaf()
|
||||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
&& prev.kind() == SyntaxKind::Eq
|
||||||
if prev.kind() == SyntaxKind::Eq;
|
&& prev.parent_kind() == Some(SyntaxKind::LetBinding)
|
||||||
if prev.parent_kind() == Some(SyntaxKind::LetBinding);
|
{
|
||||||
then {
|
|
||||||
ctx.from = ctx.cursor;
|
ctx.from = ctx.cursor;
|
||||||
code_completions(ctx, false);
|
code_completions(ctx, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Behind a half-completed context block: "#context |".
|
// Behind a half-completed context block: "#context |".
|
||||||
if_chain! {
|
if let Some(prev) = ctx.leaf.prev_leaf()
|
||||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
&& prev.kind() == SyntaxKind::Context
|
||||||
if prev.kind() == SyntaxKind::Context;
|
{
|
||||||
then {
|
|
||||||
ctx.from = ctx.cursor;
|
ctx.from = ctx.cursor;
|
||||||
code_completions(ctx, false);
|
code_completions(ctx, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Directly after a raw block.
|
// Directly after a raw block.
|
||||||
let mut s = Scanner::new(ctx.text);
|
let mut s = Scanner::new(ctx.text);
|
||||||
@ -373,38 +368,34 @@ fn complete_field_accesses(ctx: &mut CompletionContext) -> bool {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Behind an expression plus dot: "emoji.|".
|
// Behind an expression plus dot: "emoji.|".
|
||||||
if_chain! {
|
if (ctx.leaf.kind() == SyntaxKind::Dot
|
||||||
if ctx.leaf.kind() == SyntaxKind::Dot
|
|
||||||
|| (matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathText)
|
|| (matches!(ctx.leaf.kind(), SyntaxKind::Text | SyntaxKind::MathText)
|
||||||
&& ctx.leaf.text() == ".");
|
&& ctx.leaf.text() == "."))
|
||||||
if ctx.leaf.range().end == ctx.cursor;
|
&& ctx.leaf.range().end == ctx.cursor
|
||||||
if let Some(prev) = ctx.leaf.prev_sibling();
|
&& let Some(prev) = ctx.leaf.prev_sibling()
|
||||||
if !in_markup || prev.range().end == ctx.leaf.range().start;
|
&& (!in_markup || prev.range().end == ctx.leaf.range().start)
|
||||||
if prev.is::<ast::Expr>();
|
&& prev.is::<ast::Expr>()
|
||||||
if prev.parent_kind() != Some(SyntaxKind::Markup) ||
|
&& (prev.parent_kind() != Some(SyntaxKind::Markup) ||
|
||||||
prev.prev_sibling_kind() == Some(SyntaxKind::Hash);
|
prev.prev_sibling_kind() == Some(SyntaxKind::Hash))
|
||||||
if let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next();
|
&& let Some((value, styles)) = analyze_expr(ctx.world, &prev).into_iter().next()
|
||||||
then {
|
{
|
||||||
ctx.from = ctx.cursor;
|
ctx.from = ctx.cursor;
|
||||||
field_access_completions(ctx, &value, &styles);
|
field_access_completions(ctx, &value, &styles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Behind a started field access: "emoji.fa|".
|
// Behind a started field access: "emoji.fa|".
|
||||||
if_chain! {
|
if ctx.leaf.kind() == SyntaxKind::Ident
|
||||||
if ctx.leaf.kind() == SyntaxKind::Ident;
|
&& let Some(prev) = ctx.leaf.prev_sibling()
|
||||||
if let Some(prev) = ctx.leaf.prev_sibling();
|
&& prev.kind() == SyntaxKind::Dot
|
||||||
if prev.kind() == SyntaxKind::Dot;
|
&& let Some(prev_prev) = prev.prev_sibling()
|
||||||
if let Some(prev_prev) = prev.prev_sibling();
|
&& prev_prev.is::<ast::Expr>()
|
||||||
if prev_prev.is::<ast::Expr>();
|
&& let Some((value, styles)) = analyze_expr(ctx.world, &prev_prev).into_iter().next()
|
||||||
if let Some((value, styles)) = analyze_expr(ctx.world, &prev_prev).into_iter().next();
|
{
|
||||||
then {
|
|
||||||
ctx.from = ctx.leaf.offset();
|
ctx.from = ctx.leaf.offset();
|
||||||
field_access_completions(ctx, &value, &styles);
|
field_access_completions(ctx, &value, &styles);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -507,14 +498,10 @@ fn complete_open_labels(ctx: &mut CompletionContext) -> bool {
|
|||||||
fn complete_imports(ctx: &mut CompletionContext) -> bool {
|
fn complete_imports(ctx: &mut CompletionContext) -> bool {
|
||||||
// In an import path for a file or package:
|
// In an import path for a file or package:
|
||||||
// "#import "|",
|
// "#import "|",
|
||||||
if_chain! {
|
if let Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude) = ctx.leaf.parent_kind()
|
||||||
if matches!(
|
&& let Some(ast::Expr::Str(str)) = ctx.leaf.cast()
|
||||||
ctx.leaf.parent_kind(),
|
{
|
||||||
Some(SyntaxKind::ModuleImport | SyntaxKind::ModuleInclude)
|
|
||||||
);
|
|
||||||
if let Some(ast::Expr::Str(str)) = ctx.leaf.cast();
|
|
||||||
let value = str.get();
|
let value = str.get();
|
||||||
then {
|
|
||||||
ctx.from = ctx.leaf.offset();
|
ctx.from = ctx.leaf.offset();
|
||||||
if value.starts_with('@') {
|
if value.starts_with('@') {
|
||||||
let all_versions = value.contains(':');
|
let all_versions = value.contains(':');
|
||||||
@ -524,41 +511,36 @@ fn complete_imports(ctx: &mut CompletionContext) -> bool {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Behind an import list:
|
// Behind an import list:
|
||||||
// "#import "path.typ": |",
|
// "#import "path.typ": |",
|
||||||
// "#import "path.typ": a, b, |".
|
// "#import "path.typ": a, b, |".
|
||||||
if_chain! {
|
if let Some(prev) = ctx.leaf.prev_sibling()
|
||||||
if let Some(prev) = ctx.leaf.prev_sibling();
|
&& let Some(ast::Expr::ModuleImport(import)) = prev.get().cast()
|
||||||
if let Some(ast::Expr::ModuleImport(import)) = prev.get().cast();
|
&& let Some(ast::Imports::Items(items)) = import.imports()
|
||||||
if let Some(ast::Imports::Items(items)) = import.imports();
|
&& let Some(source) = prev.children().find(|child| child.is::<ast::Expr>())
|
||||||
if let Some(source) = prev.children().find(|child| child.is::<ast::Expr>());
|
{
|
||||||
then {
|
|
||||||
ctx.from = ctx.cursor;
|
ctx.from = ctx.cursor;
|
||||||
import_item_completions(ctx, items, &source);
|
import_item_completions(ctx, items, &source);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Behind a half-started identifier in an import list:
|
// Behind a half-started identifier in an import list:
|
||||||
// "#import "path.typ": thi|",
|
// "#import "path.typ": thi|",
|
||||||
if_chain! {
|
if ctx.leaf.kind() == SyntaxKind::Ident
|
||||||
if ctx.leaf.kind() == SyntaxKind::Ident;
|
&& let Some(parent) = ctx.leaf.parent()
|
||||||
if let Some(parent) = ctx.leaf.parent();
|
&& parent.kind() == SyntaxKind::ImportItemPath
|
||||||
if parent.kind() == SyntaxKind::ImportItemPath;
|
&& let Some(grand) = parent.parent()
|
||||||
if let Some(grand) = parent.parent();
|
&& grand.kind() == SyntaxKind::ImportItems
|
||||||
if grand.kind() == SyntaxKind::ImportItems;
|
&& let Some(great) = grand.parent()
|
||||||
if let Some(great) = grand.parent();
|
&& let Some(ast::Expr::ModuleImport(import)) = great.get().cast()
|
||||||
if let Some(ast::Expr::ModuleImport(import)) = great.get().cast();
|
&& let Some(ast::Imports::Items(items)) = import.imports()
|
||||||
if let Some(ast::Imports::Items(items)) = import.imports();
|
&& let Some(source) = great.children().find(|child| child.is::<ast::Expr>())
|
||||||
if let Some(source) = great.children().find(|child| child.is::<ast::Expr>());
|
{
|
||||||
then {
|
|
||||||
ctx.from = ctx.leaf.offset();
|
ctx.from = ctx.leaf.offset();
|
||||||
import_item_completions(ctx, items, &source);
|
import_item_completions(ctx, items, &source);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -607,16 +589,14 @@ fn complete_rules(ctx: &mut CompletionContext) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Behind a half-completed show rule: "show strong: |".
|
// Behind a half-completed show rule: "show strong: |".
|
||||||
if_chain! {
|
if let Some(prev) = ctx.leaf.prev_leaf()
|
||||||
if let Some(prev) = ctx.leaf.prev_leaf();
|
&& matches!(prev.kind(), SyntaxKind::Colon)
|
||||||
if matches!(prev.kind(), SyntaxKind::Colon);
|
&& matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule))
|
||||||
if matches!(prev.parent_kind(), Some(SyntaxKind::ShowRule));
|
{
|
||||||
then {
|
|
||||||
ctx.from = ctx.cursor;
|
ctx.from = ctx.cursor;
|
||||||
show_rule_recipe_completions(ctx);
|
show_rule_recipe_completions(ctx);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -682,26 +662,25 @@ fn show_rule_recipe_completions(ctx: &mut CompletionContext) {
|
|||||||
/// Complete call and set rule parameters.
|
/// Complete call and set rule parameters.
|
||||||
fn complete_params(ctx: &mut CompletionContext) -> bool {
|
fn complete_params(ctx: &mut CompletionContext) -> bool {
|
||||||
// Ensure that we are in a function call or set rule's argument list.
|
// Ensure that we are in a function call or set rule's argument list.
|
||||||
let (callee, set, args, args_linked) = if_chain! {
|
let (callee, set, args, args_linked) =
|
||||||
if let Some(parent) = ctx.leaf.parent();
|
if let Some(parent) = ctx.leaf.parent()
|
||||||
if let Some(parent) = match parent.kind() {
|
&& let Some(parent) = match parent.kind() {
|
||||||
SyntaxKind::Named => parent.parent(),
|
SyntaxKind::Named => parent.parent(),
|
||||||
_ => Some(parent),
|
_ => Some(parent),
|
||||||
};
|
}
|
||||||
if let Some(args) = parent.get().cast::<ast::Args>();
|
&& let Some(args) = parent.get().cast::<ast::Args>()
|
||||||
if let Some(grand) = parent.parent();
|
&& let Some(grand) = parent.parent()
|
||||||
if let Some(expr) = grand.get().cast::<ast::Expr>();
|
&& let Some(expr) = grand.get().cast::<ast::Expr>()
|
||||||
let set = matches!(expr, ast::Expr::SetRule(_));
|
&& let set = matches!(expr, ast::Expr::SetRule(_))
|
||||||
if let Some(callee) = match expr {
|
&& let Some(callee) = match expr {
|
||||||
ast::Expr::FuncCall(call) => Some(call.callee()),
|
ast::Expr::FuncCall(call) => Some(call.callee()),
|
||||||
ast::Expr::SetRule(set) => Some(set.target()),
|
ast::Expr::SetRule(set) => Some(set.target()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
}
|
||||||
then {
|
{
|
||||||
(callee, set, args, parent)
|
(callee, set, args, parent)
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find the piece of syntax that decides what we're completing.
|
// Find the piece of syntax that decides what we're completing.
|
||||||
@ -718,11 +697,10 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parameter values: "func(param:|)", "func(param: |)".
|
// Parameter values: "func(param:|)", "func(param: |)".
|
||||||
if_chain! {
|
if let SyntaxKind::Colon = deciding.kind()
|
||||||
if deciding.kind() == SyntaxKind::Colon;
|
&& let Some(prev) = deciding.prev_leaf()
|
||||||
if let Some(prev) = deciding.prev_leaf();
|
&& let Some(param) = prev.get().cast::<ast::Ident>()
|
||||||
if let Some(param) = prev.get().cast::<ast::Ident>();
|
{
|
||||||
then {
|
|
||||||
if let Some(next) = deciding.next_leaf() {
|
if let Some(next) = deciding.next_leaf() {
|
||||||
ctx.from = ctx.cursor.min(next.offset());
|
ctx.from = ctx.cursor.min(next.offset());
|
||||||
}
|
}
|
||||||
@ -730,13 +708,11 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
|
|||||||
named_param_value_completions(ctx, callee, ¶m);
|
named_param_value_completions(ctx, callee, ¶m);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Parameters: "func(|)", "func(hi|)", "func(12,|)".
|
// Parameters: "func(|)", "func(hi|)", "func(12,|)".
|
||||||
if_chain! {
|
if let SyntaxKind::LeftParen | SyntaxKind::Comma = deciding.kind()
|
||||||
if matches!(deciding.kind(), SyntaxKind::LeftParen | SyntaxKind::Comma);
|
&& (deciding.kind() != SyntaxKind::Comma || deciding.range().end < ctx.cursor)
|
||||||
if deciding.kind() != SyntaxKind::Comma || deciding.range().end < ctx.cursor;
|
{
|
||||||
then {
|
|
||||||
if let Some(next) = deciding.next_leaf() {
|
if let Some(next) = deciding.next_leaf() {
|
||||||
ctx.from = ctx.cursor.min(next.offset());
|
ctx.from = ctx.cursor.min(next.offset());
|
||||||
}
|
}
|
||||||
@ -744,7 +720,6 @@ fn complete_params(ctx: &mut CompletionContext) -> bool {
|
|||||||
param_completions(ctx, callee, set, args, args_linked);
|
param_completions(ctx, callee, set, args, args_linked);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -1104,15 +1079,13 @@ fn code_completions(ctx: &mut CompletionContext, hash: bool) {
|
|||||||
fn is_in_equation_show_rule(leaf: &LinkedNode<'_>) -> bool {
|
fn is_in_equation_show_rule(leaf: &LinkedNode<'_>) -> bool {
|
||||||
let mut node = leaf;
|
let mut node = leaf;
|
||||||
while let Some(parent) = node.parent() {
|
while let Some(parent) = node.parent() {
|
||||||
if_chain! {
|
if let Some(expr) = parent.get().cast::<ast::Expr>()
|
||||||
if let Some(expr) = parent.get().cast::<ast::Expr>();
|
&& let ast::Expr::ShowRule(show) = expr
|
||||||
if let ast::Expr::ShowRule(show) = expr;
|
&& let Some(ast::Expr::FieldAccess(field)) = show.selector()
|
||||||
if let Some(ast::Expr::FieldAccess(field)) = show.selector();
|
&& field.field().as_str() == "equation"
|
||||||
if field.field().as_str() == "equation";
|
{
|
||||||
then {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
node = parent;
|
node = parent;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
use ecow::{eco_format, EcoString};
|
use ecow::{eco_format, EcoString};
|
||||||
use if_chain::if_chain;
|
|
||||||
use typst::engine::Sink;
|
use typst::engine::Sink;
|
||||||
use typst::foundations::{repr, Binding, Capturer, CastInfo, Repr, Value};
|
use typst::foundations::{repr, Binding, Capturer, CastInfo, Repr, Value};
|
||||||
use typst::layout::{Length, PagedDocument};
|
use typst::layout::{Length, PagedDocument};
|
||||||
@ -107,20 +106,18 @@ fn expr_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
|||||||
|
|
||||||
/// Tooltips for imports.
|
/// Tooltips for imports.
|
||||||
fn import_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
fn import_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||||
if_chain! {
|
if leaf.kind() == SyntaxKind::Star
|
||||||
if leaf.kind() == SyntaxKind::Star;
|
&& let Some(parent) = leaf.parent()
|
||||||
if let Some(parent) = leaf.parent();
|
&& let Some(import) = parent.cast::<ast::ModuleImport>()
|
||||||
if let Some(import) = parent.cast::<ast::ModuleImport>();
|
&& let Some(node) = parent.find(import.source().span())
|
||||||
if let Some(node) = parent.find(import.source().span());
|
&& let Some(value) = analyze_import(world, &node)
|
||||||
if let Some(value) = analyze_import(world, &node);
|
&& let Some(scope) = value.scope()
|
||||||
if let Some(scope) = value.scope();
|
{
|
||||||
then {
|
|
||||||
let names: Vec<_> =
|
let names: Vec<_> =
|
||||||
scope.iter().map(|(name, ..)| eco_format!("`{name}`")).collect();
|
scope.iter().map(|(name, ..)| eco_format!("`{name}`")).collect();
|
||||||
let list = repr::separated_list(&names, "and");
|
let list = repr::separated_list(&names, "and");
|
||||||
return Some(Tooltip::Text(eco_format!("This star imports {list}")));
|
return Some(Tooltip::Text(eco_format!("This star imports {list}")));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -188,51 +185,46 @@ fn label_tooltip(document: &PagedDocument, leaf: &LinkedNode) -> Option<Tooltip>
|
|||||||
|
|
||||||
/// Tooltips for components of a named parameter.
|
/// Tooltips for components of a named parameter.
|
||||||
fn named_param_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
fn named_param_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||||
let (func, named) = if_chain! {
|
let (func, named) =
|
||||||
// Ensure that we are in a named pair in the arguments to a function
|
// Ensure that we are in a named pair in the arguments to a function
|
||||||
// call or set rule.
|
// call or set rule.
|
||||||
if let Some(parent) = leaf.parent();
|
if let Some(parent) = leaf.parent()
|
||||||
if let Some(named) = parent.cast::<ast::Named>();
|
&& let Some(named) = parent.cast::<ast::Named>()
|
||||||
if let Some(grand) = parent.parent();
|
&& let Some(grand) = parent.parent()
|
||||||
if matches!(grand.kind(), SyntaxKind::Args);
|
&& matches!(grand.kind(), SyntaxKind::Args)
|
||||||
if let Some(grand_grand) = grand.parent();
|
&& let Some(grand_grand) = grand.parent()
|
||||||
if let Some(expr) = grand_grand.cast::<ast::Expr>();
|
&& let Some(expr) = grand_grand.cast::<ast::Expr>()
|
||||||
if let Some(ast::Expr::Ident(callee)) = match expr {
|
&& let Some(ast::Expr::Ident(callee)) = match expr {
|
||||||
ast::Expr::FuncCall(call) => Some(call.callee()),
|
ast::Expr::FuncCall(call) => Some(call.callee()),
|
||||||
ast::Expr::SetRule(set) => Some(set.target()),
|
ast::Expr::SetRule(set) => Some(set.target()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
}
|
||||||
|
|
||||||
// Find metadata about the function.
|
// Find metadata about the function.
|
||||||
if let Some(Value::Func(func)) = world
|
&& let Some(Value::Func(func)) = world
|
||||||
.library()
|
.library()
|
||||||
.global
|
.global
|
||||||
.scope()
|
.scope()
|
||||||
.get(&callee)
|
.get(&callee)
|
||||||
.map(Binding::read);
|
.map(Binding::read)
|
||||||
then { (func, named) }
|
{ (func, named) }
|
||||||
else { return None; }
|
else { return None; };
|
||||||
};
|
|
||||||
|
|
||||||
// Hovering over the parameter name.
|
// Hovering over the parameter name.
|
||||||
if_chain! {
|
if leaf.index() == 0
|
||||||
if leaf.index() == 0;
|
&& let Some(ident) = leaf.cast::<ast::Ident>()
|
||||||
if let Some(ident) = leaf.cast::<ast::Ident>();
|
&& let Some(param) = func.param(&ident)
|
||||||
if let Some(param) = func.param(&ident);
|
{
|
||||||
then {
|
|
||||||
return Some(Tooltip::Text(plain_docs_sentence(param.docs)));
|
return Some(Tooltip::Text(plain_docs_sentence(param.docs)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Hovering over a string parameter value.
|
// Hovering over a string parameter value.
|
||||||
if_chain! {
|
if let Some(string) = leaf.cast::<ast::Str>()
|
||||||
if let Some(string) = leaf.cast::<ast::Str>();
|
&& let Some(param) = func.param(&named.name())
|
||||||
if let Some(param) = func.param(&named.name());
|
&& let Some(docs) = find_string_doc(¶m.input, &string.get())
|
||||||
if let Some(docs) = find_string_doc(¶m.input, &string.get());
|
{
|
||||||
then {
|
|
||||||
return Some(Tooltip::Text(docs.into()));
|
return Some(Tooltip::Text(docs.into()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -250,27 +242,25 @@ fn find_string_doc(info: &CastInfo, string: &str) -> Option<&'static str> {
|
|||||||
|
|
||||||
/// Tooltip for font.
|
/// Tooltip for font.
|
||||||
fn font_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
fn font_tooltip(world: &dyn IdeWorld, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||||
if_chain! {
|
|
||||||
// Ensure that we are on top of a string.
|
// Ensure that we are on top of a string.
|
||||||
if let Some(string) = leaf.cast::<ast::Str>();
|
if let Some(string) = leaf.cast::<ast::Str>()
|
||||||
let lower = string.get().to_lowercase();
|
&& let lower = string.get().to_lowercase()
|
||||||
|
|
||||||
// Ensure that we are in the arguments to the text function.
|
// Ensure that we are in the arguments to the text function.
|
||||||
if let Some(parent) = leaf.parent();
|
&& let Some(parent) = leaf.parent()
|
||||||
if let Some(named) = parent.cast::<ast::Named>();
|
&& let Some(named) = parent.cast::<ast::Named>()
|
||||||
if named.name().as_str() == "font";
|
&& named.name().as_str() == "font"
|
||||||
|
|
||||||
// Find the font family.
|
// Find the font family.
|
||||||
if let Some((_, iter)) = world
|
&& let Some((_, iter)) = world
|
||||||
.book()
|
.book()
|
||||||
.families()
|
.families()
|
||||||
.find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str());
|
.find(|&(family, _)| family.to_lowercase().as_str() == lower.as_str())
|
||||||
|
|
||||||
then {
|
{
|
||||||
let detail = summarize_font_family(iter.collect());
|
let detail = summarize_font_family(iter.collect());
|
||||||
return Some(Tooltip::Text(detail));
|
return Some(Tooltip::Text(detail));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user