summaryrefslogtreecommitdiff
path: root/library/src/compute/construct.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-03-10 12:55:21 +0100
committerLaurenz <laurmaedje@gmail.com>2023-03-10 12:55:21 +0100
commit62f35602a87574dcc607f1637aeae1be574981ff (patch)
tree363a1918006e06d7d79dc2ace5f8e59cd3b6bb19 /library/src/compute/construct.rs
parentc38d72383d2068361d635d6c1c78ba97aa917801 (diff)
New #[func] macro
Diffstat (limited to 'library/src/compute/construct.rs')
-rw-r--r--library/src/compute/construct.rs264
1 files changed, 121 insertions, 143 deletions
diff --git a/library/src/compute/construct.rs b/library/src/compute/construct.rs
index db442327..4d6068a1 100644
--- a/library/src/compute/construct.rs
+++ b/library/src/compute/construct.rs
@@ -1,3 +1,4 @@
+use std::num::NonZeroI64;
use std::str::FromStr;
use ecow::EcoVec;
@@ -19,17 +20,15 @@ use crate::prelude::*;
/// #{ int("27") + int("4") }
/// ```
///
-/// ## Parameters
-/// - value: `ToInt` (positional, required)
-/// The value that should be converted to an integer.
-///
-/// - returns: integer
-///
/// Display: Integer
/// Category: construct
+/// Returns: integer
#[func]
-pub fn int(args: &mut Args) -> SourceResult<Value> {
- Ok(Value::Int(args.expect::<ToInt>("value")?.0))
+pub fn int(
+ /// The value that should be converted to an integer.
+ value: ToInt,
+) -> Value {
+ Value::Int(value.0)
}
/// A value that can be cast to an integer.
@@ -59,17 +58,15 @@ cast_from_value! {
/// #float("1e5")
/// ```
///
-/// ## Parameters
-/// - value: `ToFloat` (positional, required)
-/// The value that should be converted to a float.
-///
-/// - returns: float
-///
/// Display: Float
/// Category: construct
+/// Returns: float
#[func]
-pub fn float(args: &mut Args) -> SourceResult<Value> {
- Ok(Value::Float(args.expect::<ToFloat>("value")?.0))
+pub fn float(
+ /// The value that should be converted to a float.
+ value: ToFloat,
+) -> Value {
+ Value::Float(value.0)
}
/// A value that can be cast to a float.
@@ -92,18 +89,15 @@ cast_from_value! {
/// }
/// ```
///
-/// ## Parameters
-/// - gray: `Component` (positional, required)
-/// The gray component.
-///
-/// - returns: color
-///
/// Display: Luma
/// Category: construct
+/// Returns: color
#[func]
-pub fn luma(args: &mut Args) -> SourceResult<Value> {
- let Component(luma) = args.expect("gray component")?;
- Ok(Value::Color(LumaColor::new(luma).into()))
+pub fn luma(
+ /// The gray component.
+ gray: Component,
+) -> Value {
+ Value::Color(LumaColor::new(gray.0).into())
}
/// Create an RGB(A) color.
@@ -121,40 +115,44 @@ pub fn luma(args: &mut Args) -> SourceResult<Value> {
/// #square(fill: rgb(25%, 13%, 65%))
/// ```
///
-/// ## Parameters
-/// - hex: `EcoString` (positional)
-/// The color in hexadecimal notation.
-///
-/// Accepts three, four, six or eight hexadecimal digits and optionally
-/// a leading hashtag.
-///
-/// If this string is given, the individual components should not be given.
-///
-/// ```example
-/// #text(16pt, rgb("#239dad"))[
-/// *Typst*
-/// ]
-/// ```
-///
-/// - red: `Component` (positional)
-/// The red component.
-///
-/// - green: `Component` (positional)
-/// The green component.
-///
-/// - blue: `Component` (positional)
-/// The blue component.
-///
-/// - alpha: `Component` (positional)
-/// The alpha component.
-///
-/// - returns: color
-///
-/// Display: RGBA
+/// Display: RGB
/// Category: construct
+/// Returns: color
#[func]
-pub fn rgb(args: &mut Args) -> SourceResult<Value> {
- Ok(Value::Color(if let Some(string) = args.find::<Spanned<EcoString>>()? {
+pub fn rgb(
+ /// The color in hexadecimal notation.
+ ///
+ /// Accepts three, four, six or eight hexadecimal digits and optionally
+ /// a leading hashtag.
+ ///
+ /// If this string is given, the individual components should not be given.
+ ///
+ /// ```example
+ /// #text(16pt, rgb("#239dad"))[
+ /// *Typst*
+ /// ]
+ /// ```
+ #[external]
+ #[default]
+ hex: EcoString,
+ /// The red component.
+ #[external]
+ #[default]
+ red: Component,
+ /// The green component.
+ #[external]
+ #[default]
+ green: Component,
+ /// The blue component.
+ #[external]
+ #[default]
+ blue: Component,
+ /// The alpha component.
+ #[external]
+ #[default]
+ alpha: Component,
+) -> Value {
+ Value::Color(if let Some(string) = args.find::<Spanned<EcoString>>()? {
match RgbaColor::from_str(&string.v) {
Ok(color) => color.into(),
Err(msg) => bail!(string.span, msg),
@@ -165,7 +163,7 @@ pub fn rgb(args: &mut Args) -> SourceResult<Value> {
let Component(b) = args.expect("blue component")?;
let Component(a) = args.eat()?.unwrap_or(Component(255));
RgbaColor::new(r, g, b, a).into()
- }))
+ })
}
/// An integer or ratio component.
@@ -197,30 +195,21 @@ cast_from_value! {
/// )
/// ````
///
-/// ## Parameters
-/// - cyan: `RatioComponent` (positional, required)
-/// The cyan component.
-///
-/// - magenta: `RatioComponent` (positional, required)
-/// The magenta component.
-///
-/// - yellow: `RatioComponent` (positional, required)
-/// The yellow component.
-///
-/// - key: `RatioComponent` (positional, required)
-/// The key component.
-///
-/// - returns: color
-///
/// Display: CMYK
/// Category: construct
+/// Returns: color
#[func]
-pub fn cmyk(args: &mut Args) -> SourceResult<Value> {
- let RatioComponent(c) = args.expect("cyan component")?;
- let RatioComponent(m) = args.expect("magenta component")?;
- let RatioComponent(y) = args.expect("yellow component")?;
- let RatioComponent(k) = args.expect("key component")?;
- Ok(Value::Color(CmykColor::new(c, m, y, k).into()))
+pub fn cmyk(
+ /// The cyan component.
+ cyan: RatioComponent,
+ /// The magenta component.
+ magenta: RatioComponent,
+ /// The yellow component.
+ yellow: RatioComponent,
+ /// The key component.
+ key: RatioComponent,
+) -> Value {
+ Value::Color(CmykColor::new(cyan.0, magenta.0, yellow.0, key.0).into())
}
/// A component that must be a ratio.
@@ -254,30 +243,29 @@ cast_from_value! {
/// #envelope.fly
/// ```
///
-/// ## Parameters
-/// - variants: `Variant` (positional, variadic)
-/// The variants of the symbol.
-///
-/// Can be a just a string consisting of a single character for the
-/// modifierless variant or an array with two strings specifying the modifiers
-/// and the symbol. Individual modifiers should be separated by dots. When
-/// displaying a symbol, Typst selects the first from the variants that have
-/// all attached modifiers and the minimum number of other modifiers.
-///
-/// - returns: symbol
-///
/// Display: Symbol
/// Category: construct
+/// Returns: symbol
#[func]
-pub fn symbol(args: &mut Args) -> SourceResult<Value> {
+pub fn symbol(
+ /// The variants of the symbol.
+ ///
+ /// Can be a just a string consisting of a single character for the
+ /// modifierless variant or an array with two strings specifying the modifiers
+ /// and the symbol. Individual modifiers should be separated by dots. When
+ /// displaying a symbol, Typst selects the first from the variants that have
+ /// all attached modifiers and the minimum number of other modifiers.
+ #[variadic]
+ variants: Vec<Spanned<Variant>>,
+) -> Value {
let mut list = EcoVec::new();
- for Spanned { v, span } in args.all::<Spanned<Variant>>()? {
+ for Spanned { v, span } in variants {
if list.iter().any(|(prev, _)| &v.0 == prev) {
bail!(span, "duplicate variant");
}
list.push((v.0, v.1));
}
- Ok(Value::Symbol(Symbol::runtime(list)))
+ Value::Symbol(Symbol::runtime(list))
}
/// A value that can be cast to a symbol.
@@ -309,17 +297,15 @@ cast_from_value! {
/// #str(<intro>)
/// ```
///
-/// ## Parameters
-/// - value: `ToStr` (positional, required)
-/// The value that should be converted to a string.
-///
-/// - returns: string
-///
/// Display: String
/// Category: construct
+/// Returns: string
#[func]
-pub fn str(args: &mut Args) -> SourceResult<Value> {
- Ok(Value::Str(args.expect::<ToStr>("value")?.0))
+pub fn str(
+ /// The value that should be converted to a string.
+ value: ToStr,
+) -> Value {
+ Value::Str(value.0)
}
/// A value that can be cast to a string.
@@ -352,17 +338,15 @@ cast_from_value! {
/// This function also has dedicated syntax: You can create a label by enclosing
/// its name in angle brackets. This works both in markup and code.
///
-/// ## Parameters
-/// - name: `EcoString` (positional, required)
-/// The name of the label.
-///
-/// - returns: label
-///
/// Display: Label
/// Category: construct
+/// Returns: label
#[func]
-pub fn label(args: &mut Args) -> SourceResult<Value> {
- Ok(Value::Label(Label(args.expect("string")?)))
+pub fn label(
+ /// The name of the label.
+ name: EcoString,
+) -> Value {
+ Value::Label(Label(name))
}
/// Create a regular expression from a string.
@@ -386,23 +370,20 @@ pub fn label(args: &mut Args) -> SourceResult<Value> {
/// .split(regex("[,;]")))
/// ```
///
-/// ## Parameters
-/// - regex: `EcoString` (positional, required)
-/// The regular expression as a string.
-///
-/// Most regex escape sequences just work because they are not valid Typst
-/// escape sequences. To produce regex escape sequences that are also valid in
-/// Typst (e.g. `[\\]`), you need to escape twice. Thus, to match a verbatim
-/// backslash, you would need to write `{regex("\\\\")}`.
-///
-/// - returns: regex
-///
/// Display: Regex
/// Category: construct
+/// Returns: regex
#[func]
-pub fn regex(args: &mut Args) -> SourceResult<Value> {
- let Spanned { v, span } = args.expect::<Spanned<EcoString>>("regular expression")?;
- Ok(Regex::new(&v).at(span)?.into())
+pub fn regex(
+ /// The regular expression as a string.
+ ///
+ /// Most regex escape sequences just work because they are not valid Typst
+ /// escape sequences. To produce regex escape sequences that are also valid in
+ /// Typst (e.g. `[\\]`), you need to escape twice. Thus, to match a verbatim
+ /// backslash, you would need to write `{regex("\\\\")}`.
+ regex: Spanned<EcoString>,
+) -> Value {
+ Regex::new(&regex.v).at(regex.span)?.into()
}
/// Create an array consisting of a sequence of numbers.
@@ -420,33 +401,30 @@ pub fn regex(args: &mut Args) -> SourceResult<Value> {
/// #range(5, 2, step: -1)
/// ```
///
-/// ## Parameters
-/// - start: `i64` (positional)
-/// The start of the range (inclusive).
-///
-/// - end: `i64` (positional, required)
-/// The end of the range (exclusive).
-///
-/// - step: `i64` (named)
-/// The distance between the generated numbers.
-///
-/// - returns: array
-///
/// Display: Range
/// Category: construct
+/// Returns: array
#[func]
-pub fn range(args: &mut Args) -> SourceResult<Value> {
+pub fn range(
+ /// The start of the range (inclusive).
+ #[external]
+ #[default]
+ start: i64,
+ /// The end of the range (exclusive).
+ #[external]
+ end: i64,
+ /// The distance between the generated numbers.
+ #[named]
+ #[default(NonZeroI64::new(1).unwrap())]
+ step: NonZeroI64,
+) -> Value {
let first = args.expect::<i64>("end")?;
let (start, end) = match args.eat::<i64>()? {
Some(second) => (first, second),
None => (0, first),
};
- let step: i64 = match args.named("step")? {
- Some(Spanned { v: 0, span }) => bail!(span, "step must not be zero"),
- Some(Spanned { v, .. }) => v,
- None => 1,
- };
+ let step = step.get();
let mut x = start;
let mut array = Array::new();
@@ -456,5 +434,5 @@ pub fn range(args: &mut Args) -> SourceResult<Value> {
x += step;
}
- Ok(Value::Array(array))
+ Value::Array(array)
}