mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Basic SymbolElem addition
This commit is contained in:
parent
0b8b7d0f23
commit
c47b71b435
@ -17,7 +17,9 @@ use rustybuzz::Feature;
|
|||||||
use ttf_parser::Tag;
|
use ttf_parser::Tag;
|
||||||
use typst_library::diag::{bail, SourceResult};
|
use typst_library::diag::{bail, SourceResult};
|
||||||
use typst_library::engine::Engine;
|
use typst_library::engine::Engine;
|
||||||
use typst_library::foundations::{Content, NativeElement, Packed, Resolve, StyleChain};
|
use typst_library::foundations::{
|
||||||
|
Content, NativeElement, Packed, Resolve, StyleChain, SymbolElem,
|
||||||
|
};
|
||||||
use typst_library::introspection::{Counter, Locator, SplitLocator, TagElem};
|
use typst_library::introspection::{Counter, Locator, SplitLocator, TagElem};
|
||||||
use typst_library::layout::{
|
use typst_library::layout::{
|
||||||
Abs, AlignElem, Axes, BlockElem, BoxElem, Em, FixedAlignment, Fragment, Frame, HElem,
|
Abs, AlignElem, Axes, BlockElem, BoxElem, Em, FixedAlignment, Fragment, Frame, HElem,
|
||||||
@ -535,6 +537,12 @@ fn layout_realized(
|
|||||||
layout_h(elem, ctx, styles)?;
|
layout_h(elem, ctx, styles)?;
|
||||||
} else if let Some(elem) = elem.to_packed::<TextElem>() {
|
} else if let Some(elem) = elem.to_packed::<TextElem>() {
|
||||||
self::text::layout_text(elem, ctx, styles)?;
|
self::text::layout_text(elem, ctx, styles)?;
|
||||||
|
} else if let Some(elem) = elem.to_packed::<SymbolElem>() {
|
||||||
|
// This is a hack to avoid affecting layout that will be replaced in a
|
||||||
|
// later commit.
|
||||||
|
let text_elem = TextElem::new(elem.text.to_string().into());
|
||||||
|
let packed = Packed::new(text_elem);
|
||||||
|
self::text::layout_text(&packed, ctx, styles)?;
|
||||||
} else if let Some(elem) = elem.to_packed::<BoxElem>() {
|
} else if let Some(elem) = elem.to_packed::<BoxElem>() {
|
||||||
layout_box(elem, ctx, styles)?;
|
layout_box(elem, ctx, styles)?;
|
||||||
} else if elem.is::<AlignPointElem>() {
|
} else if elem.is::<AlignPointElem>() {
|
||||||
|
@ -6,7 +6,9 @@ use ecow::eco_format;
|
|||||||
use typst_utils::Numeric;
|
use typst_utils::Numeric;
|
||||||
|
|
||||||
use crate::diag::{bail, HintedStrResult, StrResult};
|
use crate::diag::{bail, HintedStrResult, StrResult};
|
||||||
use crate::foundations::{format_str, Datetime, IntoValue, Regex, Repr, Value};
|
use crate::foundations::{
|
||||||
|
format_str, Datetime, IntoValue, Regex, Repr, SymbolElem, Value,
|
||||||
|
};
|
||||||
use crate::layout::{Alignment, Length, Rel};
|
use crate::layout::{Alignment, Length, Rel};
|
||||||
use crate::text::TextElem;
|
use crate::text::TextElem;
|
||||||
use crate::visualize::Stroke;
|
use crate::visualize::Stroke;
|
||||||
@ -30,10 +32,10 @@ pub fn join(lhs: Value, rhs: Value) -> StrResult<Value> {
|
|||||||
(Symbol(a), Str(b)) => Str(format_str!("{a}{b}")),
|
(Symbol(a), Str(b)) => Str(format_str!("{a}{b}")),
|
||||||
(Bytes(a), Bytes(b)) => Bytes(a + b),
|
(Bytes(a), Bytes(b)) => Bytes(a + b),
|
||||||
(Content(a), Content(b)) => Content(a + b),
|
(Content(a), Content(b)) => Content(a + b),
|
||||||
(Content(a), Symbol(b)) => Content(a + TextElem::packed(b.get())),
|
(Content(a), Symbol(b)) => Content(a + SymbolElem::packed(b.get())),
|
||||||
(Content(a), Str(b)) => Content(a + TextElem::packed(b)),
|
(Content(a), Str(b)) => Content(a + TextElem::packed(b)),
|
||||||
(Str(a), Content(b)) => Content(TextElem::packed(a) + b),
|
(Str(a), Content(b)) => Content(TextElem::packed(a) + b),
|
||||||
(Symbol(a), Content(b)) => Content(TextElem::packed(a.get()) + b),
|
(Symbol(a), Content(b)) => Content(SymbolElem::packed(a.get()) + b),
|
||||||
(Array(a), Array(b)) => Array(a + b),
|
(Array(a), Array(b)) => Array(a + b),
|
||||||
(Dict(a), Dict(b)) => Dict(a + b),
|
(Dict(a), Dict(b)) => Dict(a + b),
|
||||||
(Args(a), Args(b)) => Args(a + b),
|
(Args(a), Args(b)) => Args(a + b),
|
||||||
@ -130,10 +132,10 @@ pub fn add(lhs: Value, rhs: Value) -> HintedStrResult<Value> {
|
|||||||
(Symbol(a), Str(b)) => Str(format_str!("{a}{b}")),
|
(Symbol(a), Str(b)) => Str(format_str!("{a}{b}")),
|
||||||
(Bytes(a), Bytes(b)) => Bytes(a + b),
|
(Bytes(a), Bytes(b)) => Bytes(a + b),
|
||||||
(Content(a), Content(b)) => Content(a + b),
|
(Content(a), Content(b)) => Content(a + b),
|
||||||
(Content(a), Symbol(b)) => Content(a + TextElem::packed(b.get())),
|
(Content(a), Symbol(b)) => Content(a + SymbolElem::packed(b.get())),
|
||||||
(Content(a), Str(b)) => Content(a + TextElem::packed(b)),
|
(Content(a), Str(b)) => Content(a + TextElem::packed(b)),
|
||||||
(Str(a), Content(b)) => Content(TextElem::packed(a) + b),
|
(Str(a), Content(b)) => Content(TextElem::packed(a) + b),
|
||||||
(Symbol(a), Content(b)) => Content(TextElem::packed(a.get()) + b),
|
(Symbol(a), Content(b)) => Content(SymbolElem::packed(a.get()) + b),
|
||||||
|
|
||||||
(Array(a), Array(b)) => Array(a + b),
|
(Array(a), Array(b)) => Array(a + b),
|
||||||
(Dict(a), Dict(b)) => Dict(a + b),
|
(Dict(a), Dict(b)) => Dict(a + b),
|
||||||
|
@ -9,7 +9,10 @@ use typst_syntax::{is_ident, Span, Spanned};
|
|||||||
use typst_utils::hash128;
|
use typst_utils::hash128;
|
||||||
|
|
||||||
use crate::diag::{bail, SourceResult, StrResult};
|
use crate::diag::{bail, SourceResult, StrResult};
|
||||||
use crate::foundations::{cast, func, scope, ty, Array, Func, NativeFunc, Repr as _};
|
use crate::foundations::{
|
||||||
|
cast, elem, func, scope, ty, Array, Content, Func, NativeElement, NativeFunc, Packed,
|
||||||
|
PlainText, Repr as _,
|
||||||
|
};
|
||||||
|
|
||||||
/// A Unicode symbol.
|
/// A Unicode symbol.
|
||||||
///
|
///
|
||||||
@ -425,3 +428,31 @@ fn parts(modifiers: &str) -> impl Iterator<Item = &str> {
|
|||||||
fn contained(modifiers: &str, m: &str) -> bool {
|
fn contained(modifiers: &str, m: &str) -> bool {
|
||||||
parts(modifiers).any(|part| part == m)
|
parts(modifiers).any(|part| part == m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A single character.
|
||||||
|
#[elem(Repr, PlainText)]
|
||||||
|
pub struct SymbolElem {
|
||||||
|
/// The symbol's character.
|
||||||
|
#[required]
|
||||||
|
pub text: char, // This is called `text` for consistency with `TextElem`.
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SymbolElem {
|
||||||
|
/// Create a new packed symbol element.
|
||||||
|
pub fn packed(text: impl Into<char>) -> Content {
|
||||||
|
Self::new(text.into()).pack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlainText for Packed<SymbolElem> {
|
||||||
|
fn plain_text(&self, text: &mut EcoString) {
|
||||||
|
text.push(self.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::foundations::Repr for SymbolElem {
|
||||||
|
/// Use a custom repr that matches normal content.
|
||||||
|
fn repr(&self) -> EcoString {
|
||||||
|
eco_format!("[{}]", self.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,7 +16,7 @@ use crate::foundations::{
|
|||||||
fields, ops, repr, Args, Array, AutoValue, Bytes, CastInfo, Content, Datetime,
|
fields, ops, repr, Args, Array, AutoValue, Bytes, CastInfo, Content, Datetime,
|
||||||
Decimal, Dict, Duration, Fold, FromValue, Func, IntoValue, Label, Module,
|
Decimal, Dict, Duration, Fold, FromValue, Func, IntoValue, Label, Module,
|
||||||
NativeElement, NativeType, NoneValue, Plugin, Reflect, Repr, Resolve, Scope, Str,
|
NativeElement, NativeType, NoneValue, Plugin, Reflect, Repr, Resolve, Scope, Str,
|
||||||
Styles, Symbol, Type, Version,
|
Styles, Symbol, SymbolElem, Type, Version,
|
||||||
};
|
};
|
||||||
use crate::layout::{Abs, Angle, Em, Fr, Length, Ratio, Rel};
|
use crate::layout::{Abs, Angle, Em, Fr, Length, Ratio, Rel};
|
||||||
use crate::text::{RawContent, RawElem, TextElem};
|
use crate::text::{RawContent, RawElem, TextElem};
|
||||||
@ -209,7 +209,7 @@ impl Value {
|
|||||||
Self::Decimal(v) => TextElem::packed(eco_format!("{v}")),
|
Self::Decimal(v) => TextElem::packed(eco_format!("{v}")),
|
||||||
Self::Str(v) => TextElem::packed(v),
|
Self::Str(v) => TextElem::packed(v),
|
||||||
Self::Version(v) => TextElem::packed(eco_format!("{v}")),
|
Self::Version(v) => TextElem::packed(eco_format!("{v}")),
|
||||||
Self::Symbol(v) => TextElem::packed(v.get()),
|
Self::Symbol(v) => SymbolElem::packed(v.get()),
|
||||||
Self::Content(v) => v,
|
Self::Content(v) => v,
|
||||||
Self::Module(module) => module.content(),
|
Self::Module(module) => module.content(),
|
||||||
_ => RawElem::new(RawContent::Text(self.repr()))
|
_ => RawElem::new(RawContent::Text(self.repr()))
|
||||||
@ -656,7 +656,7 @@ primitive! { Duration: "duration", Duration }
|
|||||||
primitive! { Content: "content",
|
primitive! { Content: "content",
|
||||||
Content,
|
Content,
|
||||||
None => Content::empty(),
|
None => Content::empty(),
|
||||||
Symbol(v) => TextElem::packed(v.get()),
|
Symbol(v) => SymbolElem::packed(v.get()),
|
||||||
Str(v) => TextElem::packed(v)
|
Str(v) => TextElem::packed(v)
|
||||||
}
|
}
|
||||||
primitive! { Styles: "styles", Styles }
|
primitive! { Styles: "styles", Styles }
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use crate::diag::bail;
|
use crate::diag::bail;
|
||||||
use crate::foundations::{cast, elem, func, Content, NativeElement, Value};
|
use crate::foundations::{cast, elem, func, Content, NativeElement, SymbolElem};
|
||||||
use crate::layout::{Length, Rel};
|
use crate::layout::{Length, Rel};
|
||||||
use crate::math::Mathy;
|
use crate::math::Mathy;
|
||||||
use crate::text::TextElem;
|
|
||||||
|
|
||||||
/// Attaches an accent to a base.
|
/// Attaches an accent to a base.
|
||||||
///
|
///
|
||||||
@ -142,8 +141,8 @@ cast! {
|
|||||||
Accent,
|
Accent,
|
||||||
self => self.0.into_value(),
|
self => self.0.into_value(),
|
||||||
v: char => Self::new(v),
|
v: char => Self::new(v),
|
||||||
v: Content => match v.to_packed::<TextElem>() {
|
v: Content => match v.to_packed::<SymbolElem>() {
|
||||||
Some(elem) => Value::Str(elem.text.clone().into()).cast()?,
|
Some(elem) => Self::new(elem.text),
|
||||||
None => bail!("expected text"),
|
None => bail!("expected a symbol"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use typst_library::engine::Engine;
|
|||||||
use typst_library::foundations::{
|
use typst_library::foundations::{
|
||||||
Content, Context, ContextElem, Element, NativeElement, Recipe, RecipeIndex, Selector,
|
Content, Context, ContextElem, Element, NativeElement, Recipe, RecipeIndex, Selector,
|
||||||
SequenceElem, Show, ShowSet, Style, StyleChain, StyleVec, StyledElem, Styles,
|
SequenceElem, Show, ShowSet, Style, StyleChain, StyleVec, StyledElem, Styles,
|
||||||
Synthesize, Transformation,
|
SymbolElem, Synthesize, Transformation,
|
||||||
};
|
};
|
||||||
use typst_library::html::{tag, HtmlElem};
|
use typst_library::html::{tag, HtmlElem};
|
||||||
use typst_library::introspection::{Locatable, SplitLocator, Tag, TagElem};
|
use typst_library::introspection::{Locatable, SplitLocator, Tag, TagElem};
|
||||||
@ -221,7 +221,7 @@ impl<'a, 'x, 'y, 'z, 's> Grouped<'a, 'x, 'y, 'z, 's> {
|
|||||||
/// Handles an arbitrary piece of content during realization.
|
/// Handles an arbitrary piece of content during realization.
|
||||||
fn visit<'a>(
|
fn visit<'a>(
|
||||||
s: &mut State<'a, '_, '_, '_>,
|
s: &mut State<'a, '_, '_, '_>,
|
||||||
content: &'a Content,
|
mut content: &'a Content,
|
||||||
styles: StyleChain<'a>,
|
styles: StyleChain<'a>,
|
||||||
) -> SourceResult<()> {
|
) -> SourceResult<()> {
|
||||||
// Tags can always simply be pushed.
|
// Tags can always simply be pushed.
|
||||||
@ -230,6 +230,12 @@ fn visit<'a>(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(elem) = content.to_packed::<SymbolElem>() {
|
||||||
|
// This is a hack to avoid affecting layout that will be replaced in a
|
||||||
|
// later commit.
|
||||||
|
content = Box::leak(Box::new(TextElem::packed(elem.text.to_string())));
|
||||||
|
}
|
||||||
|
|
||||||
// Transformations for math content based on the realization kind. Needs
|
// Transformations for math content based on the realization kind. Needs
|
||||||
// to happen before show rules.
|
// to happen before show rules.
|
||||||
if visit_math_rules(s, content, styles)? {
|
if visit_math_rules(s, content, styles)? {
|
||||||
|
@ -50,12 +50,14 @@
|
|||||||
`raw` <myraw>
|
`raw` <myraw>
|
||||||
|
|
||||||
--- content-fields-complex ---
|
--- content-fields-complex ---
|
||||||
// Integrated test for content fields.
|
// Integrated test for content fields. The idea is to parse a normal looking
|
||||||
|
// equation and symbolically evaluate it with the given variable values.
|
||||||
|
|
||||||
#let compute(equation, ..vars) = {
|
#let compute(equation, ..vars) = {
|
||||||
let vars = vars.named()
|
let vars = vars.named()
|
||||||
let f(elem) = {
|
let f(elem) = {
|
||||||
let func = elem.func()
|
let func = elem.func()
|
||||||
if func == text {
|
if elem.has("text") {
|
||||||
let text = elem.text
|
let text = elem.text
|
||||||
if regex("^\d+$") in text {
|
if regex("^\d+$") in text {
|
||||||
int(text)
|
int(text)
|
||||||
@ -74,7 +76,7 @@
|
|||||||
elem
|
elem
|
||||||
.children
|
.children
|
||||||
.filter(v => v != [ ])
|
.filter(v => v != [ ])
|
||||||
.split[+]
|
.split($+$.body)
|
||||||
.map(xs => xs.fold(1, (prod, v) => prod * f(v)))
|
.map(xs => xs.fold(1, (prod, v) => prod * f(v)))
|
||||||
.fold(0, (sum, v) => sum + v)
|
.fold(0, (sum, v) => sum + v)
|
||||||
}
|
}
|
||||||
@ -83,13 +85,15 @@
|
|||||||
[With ]
|
[With ]
|
||||||
vars
|
vars
|
||||||
.pairs()
|
.pairs()
|
||||||
.map(p => $#p.first() = #p.last()$)
|
.map(((name, value)) => $name = value$)
|
||||||
.join(", ", last: " and ")
|
.join(", ", last: " and ")
|
||||||
[ we have:]
|
[ we have:]
|
||||||
$ equation = result $
|
$ equation = result $
|
||||||
}
|
}
|
||||||
|
|
||||||
#compute($x y + y^2$, x: 2, y: 3)
|
#compute($x y + y^2$, x: 2, y: 3)
|
||||||
|
// This should generate the same output as:
|
||||||
|
// With $x = 2$ and $y = 3$ we have: $ x y + y^2 = 15 $
|
||||||
|
|
||||||
--- content-label-has-method ---
|
--- content-label-has-method ---
|
||||||
// Test whether the label is accessible through the `has` method.
|
// Test whether the label is accessible through the `has` method.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
--- math-symbol-basic ---
|
--- math-symbol-basic ---
|
||||||
#let sym = symbol("s", ("basic", "s"))
|
#let sym = symbol("s", ("basic", "s"))
|
||||||
#test($sym.basic$, $#"s"$)
|
#test($sym.basic$, $s$)
|
||||||
|
|
||||||
--- math-symbol-underscore ---
|
--- math-symbol-underscore ---
|
||||||
#let sym = symbol("s", ("test_underscore", "s"))
|
#let sym = symbol("s", ("test_underscore", "s"))
|
||||||
@ -16,7 +16,7 @@ $sym.test-dash$
|
|||||||
|
|
||||||
--- math-symbol-double ---
|
--- math-symbol-double ---
|
||||||
#let sym = symbol("s", ("test.basic", "s"))
|
#let sym = symbol("s", ("test.basic", "s"))
|
||||||
#test($sym.test.basic$, $#"s"$)
|
#test($sym.test.basic$, $s$)
|
||||||
|
|
||||||
--- math-symbol-double-underscore ---
|
--- math-symbol-double-underscore ---
|
||||||
#let sym = symbol("s", ("one.test_underscore", "s"))
|
#let sym = symbol("s", ("one.test_underscore", "s"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user