Math operator functions
This commit is contained in:
parent
c5ef350cce
commit
a0146b5b9b
@ -7,9 +7,11 @@ mod align;
|
||||
mod atom;
|
||||
mod braced;
|
||||
mod frac;
|
||||
mod group;
|
||||
mod fragment;
|
||||
mod matrix;
|
||||
mod op;
|
||||
mod root;
|
||||
mod row;
|
||||
mod script;
|
||||
mod spacing;
|
||||
mod stretch;
|
||||
@ -54,6 +56,8 @@ pub fn define(scope: &mut Scope) {
|
||||
scope.def_func::<ScriptNode>("script");
|
||||
scope.def_func::<SqrtNode>("sqrt");
|
||||
scope.def_func::<RootNode>("root");
|
||||
scope.def_func::<FloorNode>("floor");
|
||||
scope.def_func::<CeilNode>("ceil");
|
||||
scope.def_func::<VecNode>("vec");
|
||||
scope.def_func::<CasesNode>("cases");
|
||||
scope.def_func::<UnderbraceNode>("underbrace");
|
||||
@ -70,6 +74,7 @@ pub fn define(scope: &mut Scope) {
|
||||
scope.define("med", HNode::strong(MEDIUM).pack());
|
||||
scope.define("thick", HNode::strong(THICK).pack());
|
||||
scope.define("quad", HNode::strong(QUAD).pack());
|
||||
define_operators(scope);
|
||||
}
|
||||
|
||||
/// # Math
|
||||
|
150
library/src/math/op.rs
Normal file
150
library/src/math/op.rs
Normal file
@ -0,0 +1,150 @@
|
||||
use typst::model::Scope;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// # Text Operator
|
||||
/// A text operator in a math formula.
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - text: EcoString (positional, required)
|
||||
/// The operator's text.
|
||||
/// - limits: bool (named)
|
||||
/// Whether the operator should display sub- and superscripts as limits.
|
||||
///
|
||||
/// Defaults to `true`.
|
||||
///
|
||||
/// ## Category
|
||||
/// math
|
||||
#[func]
|
||||
#[capable(LayoutMath)]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct OpNode {
|
||||
/// The operator's text.
|
||||
pub text: EcoString,
|
||||
/// Whether the operator should display sub- and superscripts as limits.
|
||||
pub limits: bool,
|
||||
}
|
||||
|
||||
impl OpNode {
|
||||
fn new(text: impl Into<EcoString>, limits: bool) -> Self {
|
||||
Self { text: text.into(), limits }
|
||||
}
|
||||
}
|
||||
|
||||
#[node]
|
||||
impl OpNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self {
|
||||
text: args.expect("text")?,
|
||||
limits: args.named("limits")?.unwrap_or(true),
|
||||
}
|
||||
.pack())
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutMath for OpNode {
|
||||
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
|
||||
let frame = ctx.layout_non_math(&TextNode(self.text.clone()).pack())?;
|
||||
ctx.push(FrameFragment {
|
||||
frame,
|
||||
class: MathClass::Large,
|
||||
limits: self.limits,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Hook up all operators.
|
||||
pub fn define_operators(scope: &mut Scope) {
|
||||
let mut define = |name: &str, limits| {
|
||||
scope.define(name, OpNode { text: name.into(), limits }.pack());
|
||||
};
|
||||
|
||||
// These have the same name in code and display.
|
||||
define("arccos", false);
|
||||
define("arcsin", false);
|
||||
define("arctan", false);
|
||||
define("arg", false);
|
||||
define("cos", false);
|
||||
define("cosh", false);
|
||||
define("cot", false);
|
||||
define("coth", false);
|
||||
define("csc", false);
|
||||
define("deg", false);
|
||||
define("det", true);
|
||||
define("dim", false);
|
||||
define("exp", false);
|
||||
define("gcd", true);
|
||||
define("hom", false);
|
||||
define("inf", true);
|
||||
define("ker", false);
|
||||
define("lg", false);
|
||||
define("lim", true);
|
||||
define("ln", false);
|
||||
define("log", false);
|
||||
define("max", true);
|
||||
define("min", true);
|
||||
define("Pr", true);
|
||||
define("sec", false);
|
||||
define("sin", false);
|
||||
define("sinh", false);
|
||||
define("sup", true);
|
||||
define("tan", false);
|
||||
define("tanh", false);
|
||||
|
||||
// These have an extra thin space.
|
||||
scope.define("liminf", OpNode::new("lim inf", true).pack());
|
||||
scope.define("limsup", OpNode::new("lim sup", true).pack());
|
||||
}
|
||||
|
||||
/// # Floor
|
||||
/// A floored expression.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// $ floor(x/2) $
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - body: Content (positional, required)
|
||||
/// The expression to floor.
|
||||
///
|
||||
/// ## Category
|
||||
/// math
|
||||
#[func]
|
||||
#[capable]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct FloorNode(pub Content);
|
||||
|
||||
#[node]
|
||||
impl FloorNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self(args.expect("body")?).pack())
|
||||
}
|
||||
}
|
||||
|
||||
/// # Ceil
|
||||
/// A ceiled expression.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// $ ceil(x/2) $
|
||||
/// ```
|
||||
///
|
||||
/// ## Parameters
|
||||
/// - body: Content (positional, required)
|
||||
/// The expression to ceil.
|
||||
///
|
||||
/// ## Category
|
||||
/// math
|
||||
#[func]
|
||||
#[capable]
|
||||
#[derive(Debug, Hash)]
|
||||
pub struct CeilNode(pub Content);
|
||||
|
||||
#[node]
|
||||
impl CeilNode {
|
||||
fn construct(_: &Vm, args: &mut Args) -> SourceResult<Content> {
|
||||
Ok(Self(args.expect("body")?).pack())
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user