mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +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 typst_library::diag::{bail, SourceResult};
|
||||
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::layout::{
|
||||
Abs, AlignElem, Axes, BlockElem, BoxElem, Em, FixedAlignment, Fragment, Frame, HElem,
|
||||
@ -535,6 +537,12 @@ fn layout_realized(
|
||||
layout_h(elem, ctx, styles)?;
|
||||
} else if let Some(elem) = elem.to_packed::<TextElem>() {
|
||||
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>() {
|
||||
layout_box(elem, ctx, styles)?;
|
||||
} else if elem.is::<AlignPointElem>() {
|
||||
|
@ -6,7 +6,9 @@ use ecow::eco_format;
|
||||
use typst_utils::Numeric;
|
||||
|
||||
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::text::TextElem;
|
||||
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}")),
|
||||
(Bytes(a), Bytes(b)) => Bytes(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)),
|
||||
(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),
|
||||
(Dict(a), Dict(b)) => Dict(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}")),
|
||||
(Bytes(a), Bytes(b)) => Bytes(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)),
|
||||
(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),
|
||||
(Dict(a), Dict(b)) => Dict(a + b),
|
||||
|
@ -9,7 +9,10 @@ use typst_syntax::{is_ident, Span, Spanned};
|
||||
use typst_utils::hash128;
|
||||
|
||||
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.
|
||||
///
|
||||
@ -425,3 +428,31 @@ fn parts(modifiers: &str) -> impl Iterator<Item = &str> {
|
||||
fn contained(modifiers: &str, m: &str) -> bool {
|
||||
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,
|
||||
Decimal, Dict, Duration, Fold, FromValue, Func, IntoValue, Label, Module,
|
||||
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::text::{RawContent, RawElem, TextElem};
|
||||
@ -209,7 +209,7 @@ impl Value {
|
||||
Self::Decimal(v) => TextElem::packed(eco_format!("{v}")),
|
||||
Self::Str(v) => TextElem::packed(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::Module(module) => module.content(),
|
||||
_ => RawElem::new(RawContent::Text(self.repr()))
|
||||
@ -656,7 +656,7 @@ primitive! { Duration: "duration", Duration }
|
||||
primitive! { Content: "content",
|
||||
Content,
|
||||
None => Content::empty(),
|
||||
Symbol(v) => TextElem::packed(v.get()),
|
||||
Symbol(v) => SymbolElem::packed(v.get()),
|
||||
Str(v) => TextElem::packed(v)
|
||||
}
|
||||
primitive! { Styles: "styles", Styles }
|
||||
|
@ -1,8 +1,7 @@
|
||||
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::math::Mathy;
|
||||
use crate::text::TextElem;
|
||||
|
||||
/// Attaches an accent to a base.
|
||||
///
|
||||
@ -142,8 +141,8 @@ cast! {
|
||||
Accent,
|
||||
self => self.0.into_value(),
|
||||
v: char => Self::new(v),
|
||||
v: Content => match v.to_packed::<TextElem>() {
|
||||
Some(elem) => Value::Str(elem.text.clone().into()).cast()?,
|
||||
None => bail!("expected text"),
|
||||
v: Content => match v.to_packed::<SymbolElem>() {
|
||||
Some(elem) => Self::new(elem.text),
|
||||
None => bail!("expected a symbol"),
|
||||
},
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use typst_library::engine::Engine;
|
||||
use typst_library::foundations::{
|
||||
Content, Context, ContextElem, Element, NativeElement, Recipe, RecipeIndex, Selector,
|
||||
SequenceElem, Show, ShowSet, Style, StyleChain, StyleVec, StyledElem, Styles,
|
||||
Synthesize, Transformation,
|
||||
SymbolElem, Synthesize, Transformation,
|
||||
};
|
||||
use typst_library::html::{tag, HtmlElem};
|
||||
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.
|
||||
fn visit<'a>(
|
||||
s: &mut State<'a, '_, '_, '_>,
|
||||
content: &'a Content,
|
||||
mut content: &'a Content,
|
||||
styles: StyleChain<'a>,
|
||||
) -> SourceResult<()> {
|
||||
// Tags can always simply be pushed.
|
||||
@ -230,6 +230,12 @@ fn visit<'a>(
|
||||
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
|
||||
// to happen before show rules.
|
||||
if visit_math_rules(s, content, styles)? {
|
||||
|
@ -50,12 +50,14 @@
|
||||
`raw` <myraw>
|
||||
|
||||
--- 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 vars = vars.named()
|
||||
let f(elem) = {
|
||||
let func = elem.func()
|
||||
if func == text {
|
||||
if elem.has("text") {
|
||||
let text = elem.text
|
||||
if regex("^\d+$") in text {
|
||||
int(text)
|
||||
@ -74,7 +76,7 @@
|
||||
elem
|
||||
.children
|
||||
.filter(v => v != [ ])
|
||||
.split[+]
|
||||
.split($+$.body)
|
||||
.map(xs => xs.fold(1, (prod, v) => prod * f(v)))
|
||||
.fold(0, (sum, v) => sum + v)
|
||||
}
|
||||
@ -83,13 +85,15 @@
|
||||
[With ]
|
||||
vars
|
||||
.pairs()
|
||||
.map(p => $#p.first() = #p.last()$)
|
||||
.map(((name, value)) => $name = value$)
|
||||
.join(", ", last: " and ")
|
||||
[ we have:]
|
||||
$ equation = result $
|
||||
}
|
||||
|
||||
#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 ---
|
||||
// Test whether the label is accessible through the `has` method.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
--- math-symbol-basic ---
|
||||
#let sym = symbol("s", ("basic", "s"))
|
||||
#test($sym.basic$, $#"s"$)
|
||||
#test($sym.basic$, $s$)
|
||||
|
||||
--- math-symbol-underscore ---
|
||||
#let sym = symbol("s", ("test_underscore", "s"))
|
||||
@ -16,7 +16,7 @@ $sym.test-dash$
|
||||
|
||||
--- math-symbol-double ---
|
||||
#let sym = symbol("s", ("test.basic", "s"))
|
||||
#test($sym.test.basic$, $#"s"$)
|
||||
#test($sym.test.basic$, $s$)
|
||||
|
||||
--- math-symbol-double-underscore ---
|
||||
#let sym = symbol("s", ("one.test_underscore", "s"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user