1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
use crate::prelude::*;
/// Find elements in the document.
///
/// Display: Query
/// Category: meta
/// Returns: content
#[func]
pub fn query(
/// The thing to search for.
target: Target,
/// A function to format the results with.
format: Func,
) -> Value {
QueryNode::new(target.0, format).pack().into()
}
/// A query target.
struct Target(Selector);
cast_from_value! {
Target,
label: Label => Self(Selector::Label(label)),
func: Func => {
let Some(id) = func.id() else {
return Err("this function is not selectable".into());
};
if !Content::new(id).can::<dyn Locatable>() {
Err(eco_format!("cannot query for {}s", id.name))?;
}
Self(Selector::Node(id, None))
}
}
/// Executes a query.
///
/// Display: Query
/// Category: special
#[node(Locatable, Show)]
pub struct QueryNode {
/// The thing to search for.
#[required]
pub target: Selector,
/// The function to format the results with.
#[required]
pub format: Func,
}
impl Show for QueryNode {
fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
if !vt.introspector.init() {
return Ok(Content::empty());
}
let id = self.0.stable_id().unwrap();
let target = self.target();
let (before, after) = vt.introspector.query_split(target, id);
let func = self.format();
let args = Args::new(func.span(), [encode(before), encode(after)]);
Ok(func.call_detached(vt.world, args)?.display())
}
}
fn encode(list: Vec<&Content>) -> Value {
Value::Array(list.into_iter().cloned().map(Value::Content).collect())
}
|