diff options
Diffstat (limited to 'library')
| -rw-r--r-- | library/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/src/meta/bibliography.rs | 6 | ||||
| -rw-r--r-- | library/src/meta/counter.rs | 17 | ||||
| -rw-r--r-- | library/src/meta/figure.rs | 12 | ||||
| -rw-r--r-- | library/src/meta/outline.rs | 5 | ||||
| -rw-r--r-- | library/src/meta/query.rs | 57 | ||||
| -rw-r--r-- | library/src/meta/state.rs | 7 |
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, |
