summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-05-26 11:59:53 +0200
committerLaurenz <laurmaedje@gmail.com>2022-05-26 11:59:53 +0200
commit66d8f4569a9f13270c5f477e0730f127a22333e2 (patch)
treeebb60254e69d7f65ec2245aeae3543f6efff0cbb /src/library
parent99cb655832161d4ebec73273a15453a8f6acc1b7 (diff)
Locate me!
Diffstat (limited to 'src/library')
-rw-r--r--src/library/mod.rs1
-rw-r--r--src/library/text/par.rs43
-rw-r--r--src/library/utility/locate.rs8
-rw-r--r--src/library/utility/mod.rs2
4 files changed, 42 insertions, 12 deletions
diff --git a/src/library/mod.rs b/src/library/mod.rs
index ac0cbb92..3321a36b 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -92,6 +92,7 @@ pub fn new() -> Scope {
std.def_fn("roman", utility::roman);
std.def_fn("symbol", utility::symbol);
std.def_fn("lorem", utility::lorem);
+ std.def_fn("locate", utility::locate);
// Predefined colors.
std.def_const("black", Color::BLACK);
diff --git a/src/library/text/par.rs b/src/library/text/par.rs
index 1269ffed..65098b61 100644
--- a/src/library/text/par.rs
+++ b/src/library/text/par.rs
@@ -26,6 +26,8 @@ pub enum ParChild {
Spacing(Spacing),
/// An arbitrary inline-level node.
Node(LayoutNode),
+ /// A pin identified by index.
+ Pin(usize),
}
#[node]
@@ -100,6 +102,7 @@ impl Debug for ParChild {
Self::Quote { double } => write!(f, "Quote({double})"),
Self::Spacing(kind) => write!(f, "{:?}", kind),
Self::Node(node) => node.fmt(f),
+ Self::Pin(idx) => write!(f, "Pin({idx})"),
}
}
}
@@ -275,6 +278,8 @@ enum Segment<'a> {
Spacing(Spacing),
/// An arbitrary inline-level layout node.
Node(&'a LayoutNode),
+ /// A pin identified by index.
+ Pin(usize),
}
impl Segment<'_> {
@@ -282,7 +287,7 @@ impl Segment<'_> {
fn len(&self) -> usize {
match *self {
Self::Text(len) => len,
- Self::Spacing(_) => SPACING_REPLACE.len_utf8(),
+ Self::Spacing(_) | Self::Pin(_) => SPACING_REPLACE.len_utf8(),
Self::Node(_) => NODE_REPLACE.len_utf8(),
}
}
@@ -301,6 +306,8 @@ enum Item<'a> {
Frame(Arc<Frame>),
/// A repeating node.
Repeat(&'a RepeatNode, StyleChain<'a>),
+ /// A pin identified by index.
+ Pin(usize),
}
impl<'a> Item<'a> {
@@ -316,7 +323,9 @@ impl<'a> Item<'a> {
fn len(&self) -> usize {
match self {
Self::Text(shaped) => shaped.text.len(),
- Self::Absolute(_) | Self::Fractional(_) => SPACING_REPLACE.len_utf8(),
+ Self::Absolute(_) | Self::Fractional(_) | Self::Pin(_) => {
+ SPACING_REPLACE.len_utf8()
+ }
Self::Frame(_) | Self::Repeat(_, _) => NODE_REPLACE.len_utf8(),
}
}
@@ -324,10 +333,10 @@ impl<'a> Item<'a> {
/// The natural width of the item.
fn width(&self) -> Length {
match self {
- Item::Text(shaped) => shaped.width,
- Item::Absolute(v) => *v,
- Item::Fractional(_) | Self::Repeat(_, _) => Length::zero(),
- Item::Frame(frame) => frame.size.x,
+ Self::Text(shaped) => shaped.width,
+ Self::Absolute(v) => *v,
+ Self::Frame(frame) => frame.size.x,
+ Self::Fractional(_) | Self::Repeat(_, _) | Self::Pin(_) => Length::zero(),
}
}
}
@@ -447,7 +456,7 @@ fn collect<'a>(
}
Segment::Text(full.len() - prev)
}
- ParChild::Quote { double } => {
+ &ParChild::Quote { double } => {
let prev = full.len();
if styles.get(TextNode::SMART_QUOTES) {
let lang = styles.get(TextNode::LANG);
@@ -456,24 +465,28 @@ fn collect<'a>(
let peeked = iter.peek().and_then(|(child, _)| match child {
ParChild::Text(text) => text.chars().next(),
ParChild::Quote { .. } => Some('"'),
- ParChild::Spacing(_) => Some(SPACING_REPLACE),
+ ParChild::Spacing(_) | ParChild::Pin(_) => Some(SPACING_REPLACE),
ParChild::Node(_) => Some(NODE_REPLACE),
});
- full.push_str(quoter.quote(&quotes, *double, peeked));
+ full.push_str(quoter.quote(&quotes, double, peeked));
} else {
- full.push(if *double { '"' } else { '\'' });
+ full.push(if double { '"' } else { '\'' });
}
Segment::Text(full.len() - prev)
}
- ParChild::Spacing(spacing) => {
+ &ParChild::Spacing(spacing) => {
full.push(SPACING_REPLACE);
- Segment::Spacing(*spacing)
+ Segment::Spacing(spacing)
}
ParChild::Node(node) => {
full.push(NODE_REPLACE);
Segment::Node(node)
}
+ &ParChild::Pin(idx) => {
+ full.push(SPACING_REPLACE);
+ Segment::Pin(idx)
+ }
};
if let Some(last) = full.chars().last() {
@@ -540,6 +553,7 @@ fn prepare<'a>(
items.push(Item::Frame(frame));
}
}
+ Segment::Pin(idx) => items.push(Item::Pin(idx)),
}
cursor = end;
@@ -1171,6 +1185,11 @@ fn commit(
}
offset = before + width;
}
+ Item::Pin(idx) => {
+ let mut frame = Frame::new(Size::zero());
+ frame.push(Point::zero(), Element::Pin(*idx));
+ push(&mut offset, MaybeShared::Owned(frame));
+ }
}
}
diff --git a/src/library/utility/locate.rs b/src/library/utility/locate.rs
new file mode 100644
index 00000000..0352199f
--- /dev/null
+++ b/src/library/utility/locate.rs
@@ -0,0 +1,8 @@
+use crate::library::prelude::*;
+use crate::model::LocateNode;
+
+/// Format content with access to its location on the page.
+pub fn locate(_: &mut Machine, args: &mut Args) -> TypResult<Value> {
+ let node = LocateNode::new(args.expect("recipe")?);
+ Ok(Value::Content(Content::Locate(node)))
+}
diff --git a/src/library/utility/mod.rs b/src/library/utility/mod.rs
index 10aa7c7a..32815607 100644
--- a/src/library/utility/mod.rs
+++ b/src/library/utility/mod.rs
@@ -1,10 +1,12 @@
//! Computational utility functions.
mod color;
+mod locate;
mod math;
mod string;
pub use color::*;
+pub use locate::*;
pub use math::*;
pub use string::*;