summaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/src/lib.rs1
-rw-r--r--library/src/meta/bibliography.rs6
-rw-r--r--library/src/meta/counter.rs17
-rw-r--r--library/src/meta/figure.rs12
-rw-r--r--library/src/meta/outline.rs5
-rw-r--r--library/src/meta/query.rs57
-rw-r--r--library/src/meta/state.rs7
7 files changed, 50 insertions, 55 deletions
diff --git a/library/src/lib.rs b/library/src/lib.rs
index ac99425f..9b4e9644 100644
--- a/library/src/lib.rs
+++ b/library/src/lib.rs
@@ -102,6 +102,7 @@ fn global(math: Module, calc: Module) -> Module {
global.define("numbering", meta::numbering);
global.define("state", meta::state);
global.define("query", meta::query);
+ global.define("selector", meta::selector);
// Symbols.
global.define("sym", symbols::sym());
diff --git a/library/src/meta/bibliography.rs b/library/src/meta/bibliography.rs
index cd167049..8fa2ee34 100644
--- a/library/src/meta/bibliography.rs
+++ b/library/src/meta/bibliography.rs
@@ -91,7 +91,7 @@ cast_to_value! {
impl BibliographyElem {
/// Find the document's bibliography.
pub fn find(introspector: Tracked<Introspector>) -> StrResult<Self> {
- let mut iter = introspector.query(Self::func().select()).into_iter();
+ let mut iter = introspector.query(&Self::func().select()).into_iter();
let Some(elem) = iter.next() else {
return Err("the document does not contain a bibliography".into());
};
@@ -106,7 +106,7 @@ impl BibliographyElem {
/// Whether the bibliography contains the given key.
pub fn has(vt: &Vt, key: &str) -> bool {
vt.introspector
- .query(Self::func().select())
+ .query(&Self::func().select())
.into_iter()
.flat_map(|elem| load(vt.world, &elem.to::<Self>().unwrap().path()))
.flatten()
@@ -395,7 +395,7 @@ impl Works {
let bibliography = BibliographyElem::find(vt.introspector)?;
let citations = vt
.introspector
- .query(Selector::Any(eco_vec![
+ .query(&Selector::Or(eco_vec![
RefElem::func().select(),
CiteElem::func().select(),
]))
diff --git a/library/src/meta/counter.rs b/library/src/meta/counter.rs
index d771168d..b1d2e3bd 100644
--- a/library/src/meta/counter.rs
+++ b/library/src/meta/counter.rs
@@ -335,7 +335,10 @@ impl Counter {
/// Get the value of the state at the given location.
pub fn at(&self, vt: &mut Vt, location: Location) -> SourceResult<CounterState> {
let sequence = self.sequence(vt)?;
- let offset = vt.introspector.query_before(self.selector(), location).len();
+ let offset = vt
+ .introspector
+ .query(&Selector::before(self.selector(), location, true))
+ .len();
let (mut state, page) = sequence[offset].clone();
if self.is_page() {
let delta = vt.introspector.page(location).get().saturating_sub(page.get());
@@ -359,7 +362,10 @@ impl Counter {
/// Get the current and final value of the state combined in one state.
pub fn both(&self, vt: &mut Vt, location: Location) -> SourceResult<CounterState> {
let sequence = self.sequence(vt)?;
- let offset = vt.introspector.query_before(self.selector(), location).len();
+ let offset = vt
+ .introspector
+ .query(&Selector::before(self.selector(), location, true))
+ .len();
let (mut at_state, at_page) = sequence[offset].clone();
let (mut final_state, final_page) = sequence.last().unwrap().clone();
if self.is_page() {
@@ -412,11 +418,10 @@ impl Counter {
let mut page = NonZeroUsize::ONE;
let mut stops = eco_vec![(state.clone(), page)];
- for elem in introspector.query(self.selector()) {
+ for elem in introspector.query(&self.selector()) {
if self.is_page() {
- let location = elem.location().unwrap();
let prev = page;
- page = introspector.page(location);
+ page = introspector.page(elem.location().unwrap());
let delta = page.get() - prev.get();
if delta > 0 {
@@ -446,7 +451,7 @@ impl Counter {
Selector::Elem(UpdateElem::func(), Some(dict! { "counter" => self.clone() }));
if let CounterKey::Selector(key) = &self.0 {
- selector = Selector::Any(eco_vec![selector, key.clone()]);
+ selector = Selector::Or(eco_vec![selector, key.clone()]);
}
selector
diff --git a/library/src/meta/figure.rs b/library/src/meta/figure.rs
index 964bb4ec..a838b9a5 100644
--- a/library/src/meta/figure.rs
+++ b/library/src/meta/figure.rs
@@ -173,14 +173,14 @@ impl Synthesize for FigureElem {
// Determine the figure's kind.
let kind = match self.kind(styles) {
Smart::Auto => self
- .find_figurable(styles)
+ .find_figurable(vt, styles)
.map(|elem| FigureKind::Elem(elem.func()))
.unwrap_or_else(|| FigureKind::Elem(ImageElem::func())),
Smart::Custom(kind) => kind,
};
let content = match &kind {
- FigureKind::Elem(func) => self.find_of_elem(*func),
+ FigureKind::Elem(func) => self.find_of_elem(vt, *func),
FigureKind::Name(_) => None,
}
.unwrap_or_else(|| self.body());
@@ -303,9 +303,9 @@ impl Refable for FigureElem {
impl FigureElem {
/// Determines the type of the figure by looking at the content, finding all
/// [`Figurable`] elements and sorting them by priority then returning the highest.
- pub fn find_figurable(&self, styles: StyleChain) -> Option<Content> {
+ pub fn find_figurable(&self, vt: &Vt, styles: StyleChain) -> Option<Content> {
self.body()
- .query(Selector::can::<dyn Figurable>())
+ .query(vt.introspector, Selector::can::<dyn Figurable>())
.into_iter()
.max_by_key(|elem| elem.with::<dyn Figurable>().unwrap().priority(styles))
.cloned()
@@ -313,9 +313,9 @@ impl FigureElem {
/// Finds the element with the given function in the figure's content.
/// Returns `None` if no element with the given function is found.
- pub fn find_of_elem(&self, func: ElemFunc) -> Option<Content> {
+ pub fn find_of_elem(&self, vt: &Vt, func: ElemFunc) -> Option<Content> {
self.body()
- .query(Selector::Elem(func, None))
+ .query(vt.introspector, Selector::Elem(func, None))
.into_iter()
.next()
.cloned()
diff --git a/library/src/meta/outline.rs b/library/src/meta/outline.rs
index 4c12da75..099c3bdf 100644
--- a/library/src/meta/outline.rs
+++ b/library/src/meta/outline.rs
@@ -154,14 +154,13 @@ impl Show for OutlineElem {
let lang = TextElem::lang_in(styles);
let mut ancestors: Vec<&Content> = vec![];
- let elems = vt.introspector.query(self.target(styles));
+ let elems = vt.introspector.query(&self.target(styles));
for elem in &elems {
let Some(refable) = elem.with::<dyn Refable>() else {
bail!(elem.span(), "outlined elements must be referenceable");
};
- let location = elem.location().expect("missing location");
if depth < refable.level() {
continue;
}
@@ -170,6 +169,8 @@ impl Show for OutlineElem {
continue;
};
+ let location = elem.location().unwrap();
+
// Deals with the ancestors of the current element.
// This is only applicable for elements with a hierarchy/level.
while ancestors
diff --git a/library/src/meta/query.rs b/library/src/meta/query.rs
index 4241c19d..f256af23 100644
--- a/library/src/meta/query.rs
+++ b/library/src/meta/query.rs
@@ -38,8 +38,8 @@ use crate::prelude::*;
/// >>> )
/// #set page(header: locate(loc => {
/// let elems = query(
-/// heading,
-/// before: loc,
+/// selector(heading).before(loc),
+/// loc,
/// )
/// let academy = smallcaps[
/// Typst Academy
@@ -102,8 +102,7 @@ pub fn query(
/// elements with an explicit label. As a result, you _can_ query for e.g.
/// [`strong`]($func/strong) elements, but you will find only those that
/// have an explicit label attached to them. This limitation will be
- /// resolved
- /// in the future.
+ /// resolved in the future.
target: LocatableSelector,
/// Can be any location. Why is it required then? As noted before, Typst has
@@ -115,39 +114,25 @@ pub fn query(
/// could depend on the query's result.
///
/// Only one of this, `before`, and `after` shall be given.
- #[external]
- #[default]
location: Location,
+) -> Value {
+ let _ = location;
+ vm.vt.introspector.query(&target.0).into()
+}
- /// If given, returns only those elements that are before the given
- /// location. A suitable location can be retrieved from
- /// [`locate`]($func/locate), but also through the
- /// [`location()`]($type/content.location) method on content returned by
- /// another query. Only one of `location`, this, and `after` shall be given.
- #[named]
- #[external]
- #[default]
- before: Location,
-
- /// If given, returns only those elements that are after the given location.
- /// A suitable location can be retrieved from [`locate`]($func/locate), but
- /// also through the [`location()`]($type/content.location) method on
- /// content returned by another query. Only one of `location`, `before`, and
- /// this shall be given.
- #[named]
- #[external]
- #[default]
- after: Location,
+/// Turns a value into a selector. The following values are accepted:
+/// - An element function like a `heading` or `figure`.
+/// - A `{<label>}`.
+/// - A more complex selector like `{heading.where(level: 1)}`.
+///
+/// Display: Selector
+/// Category: meta
+/// Returns: content
+#[func]
+pub fn selector(
+ /// Can be an element function like a `heading` or `figure`, a `{<label>}`
+ /// or a more complex selector like `{heading.where(level: 1)}`.
+ target: Selector,
) -> Value {
- let selector = target.0;
- let introspector = vm.vt.introspector;
- let elements = if let Some(location) = args.named("before")? {
- introspector.query_before(selector, location)
- } else if let Some(location) = args.named("after")? {
- introspector.query_after(selector, location)
- } else {
- let _: Location = args.expect("location")?;
- introspector.query(selector)
- };
- elements.into()
+ target.into()
}
diff --git a/library/src/meta/state.rs b/library/src/meta/state.rs
index 3e6d65b2..781d4294 100644
--- a/library/src/meta/state.rs
+++ b/library/src/meta/state.rs
@@ -282,7 +282,10 @@ impl State {
/// Get the value of the state at the given location.
pub fn at(self, vt: &mut Vt, location: Location) -> SourceResult<Value> {
let sequence = self.sequence(vt)?;
- let offset = vt.introspector.query_before(self.selector(), location).len();
+ let offset = vt
+ .introspector
+ .query(&Selector::before(self.selector(), location, true))
+ .len();
Ok(sequence[offset].clone())
}
@@ -323,7 +326,7 @@ impl State {
let mut state = self.init.clone();
let mut stops = eco_vec![state.clone()];
- for elem in introspector.query(self.selector()) {
+ for elem in introspector.query(&self.selector()) {
let elem = elem.to::<UpdateElem>().unwrap();
match elem.update() {
StateUpdate::Set(value) => state = value,