Add Repr
trait (#2269)
This commit is contained in:
parent
57bc614cf4
commit
333e4037fc
@ -21,7 +21,7 @@ use serde::Deserialize;
|
||||
use serde_yaml as yaml;
|
||||
use typst::diag::{bail, StrResult};
|
||||
use typst::doc::Frame;
|
||||
use typst::eval::{CastInfo, Func, Library, Module, ParamInfo, Scope, Type, Value};
|
||||
use typst::eval::{CastInfo, Func, Library, Module, ParamInfo, Repr, Scope, Type, Value};
|
||||
use typst::font::{Font, FontBook};
|
||||
use typst::geom::{Abs, Smart};
|
||||
use typst_library::layout::{Margin, PageElem};
|
||||
|
@ -6,7 +6,7 @@ use if_chain::if_chain;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typst::doc::Frame;
|
||||
use typst::eval::{
|
||||
format_str, AutoValue, CastInfo, Func, Library, NoneValue, Scope, Type, Value,
|
||||
format_str, AutoValue, CastInfo, Func, Library, NoneValue, Repr, Scope, Type, Value,
|
||||
};
|
||||
use typst::geom::Color;
|
||||
use typst::syntax::{
|
||||
@ -1089,14 +1089,14 @@ impl<'a> CompletionContext<'a> {
|
||||
docs: Option<&str>,
|
||||
) {
|
||||
let at = label.as_deref().map_or(false, |field| !is_ident(field));
|
||||
let label = label.unwrap_or_else(|| value.repr().into());
|
||||
let label = label.unwrap_or_else(|| value.repr());
|
||||
|
||||
let detail = docs.map(Into::into).or_else(|| match value {
|
||||
Value::Symbol(_) => None,
|
||||
Value::Func(func) => func.docs().map(plain_docs_sentence),
|
||||
v => {
|
||||
let repr = v.repr();
|
||||
(repr.as_str() != label).then(|| repr.into())
|
||||
(repr.as_str() != label).then_some(repr)
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::fmt::Write;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use if_chain::if_chain;
|
||||
use typst::doc::Frame;
|
||||
use typst::eval::{CapturesVisitor, CastInfo, Tracer, Value};
|
||||
use typst::eval::{CapturesVisitor, CastInfo, Repr, Tracer, Value};
|
||||
use typst::geom::{round_2, Length, Numeric};
|
||||
use typst::syntax::ast::{self, AstNode};
|
||||
use typst::syntax::{LinkedNode, Source, SyntaxKind};
|
||||
@ -83,7 +83,7 @@ fn expr_tooltip(world: &dyn World, leaf: &LinkedNode) -> Option<Tooltip> {
|
||||
write!(pieces.last_mut().unwrap(), " (x{count})").unwrap();
|
||||
}
|
||||
}
|
||||
pieces.push(value.repr().into());
|
||||
pieces.push(value.repr());
|
||||
last = Some((value, 1));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use typst::eval::{
|
||||
Datetime, Duration, EvalMode, Module, Never, NoneValue, Plugin, Regex, Version,
|
||||
Datetime, Duration, EvalMode, Module, Never, NoneValue, Plugin, Regex, Repr, Version,
|
||||
};
|
||||
|
||||
use crate::prelude::*;
|
||||
@ -51,7 +51,7 @@ pub fn repr(
|
||||
/// The value whose string representation to produce.
|
||||
value: Value,
|
||||
) -> Str {
|
||||
value.repr()
|
||||
value.repr().into()
|
||||
}
|
||||
|
||||
/// Fails with an error.
|
||||
@ -135,7 +135,11 @@ impl assert {
|
||||
if let Some(message) = message {
|
||||
bail!("equality assertion failed: {message}");
|
||||
} else {
|
||||
bail!("equality assertion failed: value {left:?} was not equal to {right:?}");
|
||||
bail!(
|
||||
"equality assertion failed: value {} was not equal to {}",
|
||||
left.repr(),
|
||||
right.repr()
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(NoneValue)
|
||||
@ -165,7 +169,9 @@ impl assert {
|
||||
bail!("inequality assertion failed: {message}");
|
||||
} else {
|
||||
bail!(
|
||||
"inequality assertion failed: value {left:?} was equal to {right:?}"
|
||||
"inequality assertion failed: value {} was equal to {}",
|
||||
left.repr(),
|
||||
right.repr()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use std::fmt::{self, Debug, Formatter, Write};
|
||||
use std::str::FromStr;
|
||||
|
||||
use ecow::{eco_vec, EcoVec};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use typst::eval::Tracer;
|
||||
use typst::eval::{Repr, Tracer};
|
||||
use typst::model::DelayedErrors;
|
||||
|
||||
use super::{FigureElem, HeadingElem, Numbering, NumberingPattern};
|
||||
@ -199,7 +198,7 @@ use crate::prelude::*;
|
||||
/// documentation for more details on state management in Typst and why it
|
||||
/// doesn't just use normal variables for counters.
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub struct Counter(CounterKey);
|
||||
|
||||
impl Counter {
|
||||
@ -452,11 +451,9 @@ impl Counter {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Counter {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.write_str("counter(")?;
|
||||
self.0.fmt(f)?;
|
||||
f.write_char(')')
|
||||
impl Repr for Counter {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("counter({})", self.0.repr())
|
||||
}
|
||||
}
|
||||
|
||||
@ -465,7 +462,7 @@ cast! {
|
||||
}
|
||||
|
||||
/// Identifies a counter.
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum CounterKey {
|
||||
/// The page counter.
|
||||
Page,
|
||||
@ -495,19 +492,19 @@ cast! {
|
||||
v: LocatableSelector => Self::Selector(v.0),
|
||||
}
|
||||
|
||||
impl Debug for CounterKey {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for CounterKey {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Page => f.pad("page"),
|
||||
Self::Selector(selector) => selector.fmt(f),
|
||||
Self::Str(str) => str.fmt(f),
|
||||
Self::Page => "page".into(),
|
||||
Self::Selector(selector) => selector.repr(),
|
||||
Self::Str(str) => str.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An update to perform on a counter.
|
||||
#[ty]
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum CounterUpdate {
|
||||
/// Set the counter to the specified state.
|
||||
Set(CounterState),
|
||||
@ -517,9 +514,9 @@ pub enum CounterUpdate {
|
||||
Func(Func),
|
||||
}
|
||||
|
||||
impl Debug for CounterUpdate {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("..")
|
||||
impl Repr for CounterUpdate {
|
||||
fn repr(&self) -> EcoString {
|
||||
"..".into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::fmt::{self, Debug, Formatter, Write};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use ecow::{eco_vec, EcoVec};
|
||||
use typst::eval::Tracer;
|
||||
use typst::eval::{Repr, Tracer};
|
||||
use typst::model::DelayedErrors;
|
||||
|
||||
use crate::prelude::*;
|
||||
@ -181,7 +181,7 @@ use crate::prelude::*;
|
||||
/// function to `update` that determines the value of the state based on its
|
||||
/// previous value.
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub struct State {
|
||||
/// The key that identifies the state.
|
||||
key: Str,
|
||||
@ -335,13 +335,9 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for State {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.write_str("state(")?;
|
||||
self.key.fmt(f)?;
|
||||
f.write_str(", ")?;
|
||||
self.init.fmt(f)?;
|
||||
f.write_char(')')
|
||||
impl Repr for State {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("state({}, {})", self.key.repr(), self.init.repr())
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,7 +347,7 @@ cast! {
|
||||
|
||||
/// An update to perform on a state.
|
||||
#[ty]
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum StateUpdate {
|
||||
/// Set the state to the specified value.
|
||||
Set(Value),
|
||||
@ -359,9 +355,9 @@ pub enum StateUpdate {
|
||||
Func(Func),
|
||||
}
|
||||
|
||||
impl Debug for StateUpdate {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("..")
|
||||
impl Repr for StateUpdate {
|
||||
fn repr(&self) -> EcoString {
|
||||
"..".into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ pub use typst::doc::*;
|
||||
#[doc(no_inline)]
|
||||
pub use typst::eval::{
|
||||
array, cast, dict, format_str, func, scope, ty, Args, Array, Bytes, Cast, Dict,
|
||||
FromValue, Func, IntoValue, Scope, Str, Symbol, Type, Value, Vm,
|
||||
FromValue, Func, IntoValue, Repr, Scope, Str, Symbol, Type, Value, Vm,
|
||||
};
|
||||
#[doc(no_inline)]
|
||||
pub use typst::geom::*;
|
||||
|
@ -346,6 +346,12 @@ impl Fold for Decoration {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Decoration {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
type Decoration,
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ use std::ops::Range;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::EcoString;
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::eval::{cast, dict, ty, Dict, Value};
|
||||
use crate::eval::{cast, dict, ty, Dict, Repr, Value};
|
||||
use crate::export::PdfPageLabel;
|
||||
use crate::font::Font;
|
||||
use crate::geom::{
|
||||
@ -762,6 +762,12 @@ impl Debug for Meta {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Meta {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
/// A link destination.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Destination {
|
||||
@ -773,6 +779,12 @@ pub enum Destination {
|
||||
Location(Location),
|
||||
}
|
||||
|
||||
impl Repr for Destination {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
Destination,
|
||||
self => match self {
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use ecow::{eco_format, EcoVec};
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
|
||||
use super::{func, scope, ty, Array, Dict, FromValue, IntoValue, Str, Value};
|
||||
use super::{func, scope, ty, Array, Dict, FromValue, IntoValue, Repr, Str, Value};
|
||||
use crate::diag::{bail, At, SourceDiagnostic, SourceResult};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
use crate::util::pretty_array_like;
|
||||
@ -47,7 +47,7 @@ pub struct Args {
|
||||
}
|
||||
|
||||
/// An argument to a function call: `12` or `draw: false`.
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub struct Arg {
|
||||
/// The span of the whole argument.
|
||||
pub span: Span,
|
||||
@ -252,18 +252,23 @@ impl Args {
|
||||
|
||||
impl Debug for Args {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let pieces: Vec<_> =
|
||||
self.items.iter().map(|arg| eco_format!("{arg:?}")).collect();
|
||||
f.write_str(&pretty_array_like(&pieces, false))
|
||||
f.debug_list().entries(&self.items).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Arg {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
if let Some(name) = &self.name {
|
||||
f.write_str(name)?;
|
||||
f.write_str(": ")?;
|
||||
}
|
||||
Debug::fmt(&self.value.v, f)
|
||||
impl Repr for Args {
|
||||
fn repr(&self) -> EcoString {
|
||||
let pieces = self.items.iter().map(Arg::repr).collect::<Vec<_>>();
|
||||
pretty_array_like(&pieces, false).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Arg {
|
||||
fn repr(&self) -> EcoString {
|
||||
if let Some(name) = &self.name {
|
||||
eco_format!("{}: {}", name, self.value.v.repr())
|
||||
} else {
|
||||
self.value.v.repr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::num::NonZeroI64;
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
cast, func, ops, scope, ty, Args, Bytes, CastInfo, FromValue, Func, IntoValue,
|
||||
Reflect, Value, Version, Vm,
|
||||
Reflect, Repr, Value, Version, Vm,
|
||||
};
|
||||
use crate::diag::{At, SourceResult, StrResult};
|
||||
use crate::eval::ops::{add, mul};
|
||||
@ -808,14 +808,23 @@ cast! {
|
||||
}
|
||||
|
||||
impl Debug for Array {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
f.debug_list().entries(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Array {
|
||||
fn repr(&self) -> EcoString {
|
||||
let max = 40;
|
||||
let mut pieces: Vec<_> =
|
||||
self.iter().take(max).map(|value| eco_format!("{value:?}")).collect();
|
||||
let mut pieces: Vec<_> = self
|
||||
.iter()
|
||||
.take(max)
|
||||
.map(|value| eco_format!("{}", value.repr()))
|
||||
.collect();
|
||||
if self.len() > max {
|
||||
pieces.push(eco_format!(".. ({} items omitted)", self.len() - max));
|
||||
}
|
||||
f.write_str(&pretty_array_like(&pieces, self.len() == 1))
|
||||
pretty_array_like(&pieces, self.len() == 1).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use ecow::EcoString;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::{ty, CastInfo, FromValue, IntoValue, Reflect, Type, Value};
|
||||
use super::{ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value};
|
||||
use crate::diag::StrResult;
|
||||
|
||||
/// A value that indicates a smart default.
|
||||
@ -12,7 +13,7 @@ use crate::diag::StrResult;
|
||||
/// parameter. Setting it to `{auto}` lets Typst automatically determine the
|
||||
/// direction from the [text language]($text.lang).
|
||||
#[ty(name = "auto")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct AutoValue;
|
||||
|
||||
impl IntoValue for AutoValue {
|
||||
@ -44,8 +45,8 @@ impl Reflect for AutoValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for AutoValue {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("auto")
|
||||
impl Repr for AutoValue {
|
||||
fn repr(&self) -> EcoString {
|
||||
"auto".into()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
use super::ty;
|
||||
use ecow::EcoString;
|
||||
|
||||
use super::{ty, Repr};
|
||||
|
||||
/// A type with two states.
|
||||
///
|
||||
@ -13,3 +15,12 @@ use super::ty;
|
||||
/// ```
|
||||
#[ty(title = "Boolean")]
|
||||
type bool;
|
||||
|
||||
impl Repr for bool {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
true => "true".into(),
|
||||
false => "false".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::Debug;
|
||||
use std::ops::{Add, AddAssign, Deref};
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -7,7 +7,7 @@ use comemo::Prehashed;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use super::{cast, func, scope, ty, Array, Reflect, Str, Value};
|
||||
use super::{cast, func, scope, ty, Array, Reflect, Repr, Str, Value};
|
||||
use crate::diag::{bail, StrResult};
|
||||
|
||||
/// A sequence of bytes.
|
||||
@ -38,7 +38,7 @@ use crate::diag::{bail, StrResult};
|
||||
/// #str(data.slice(1, 4))
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct Bytes(Arc<Prehashed<Cow<'static, [u8]>>>);
|
||||
|
||||
impl Bytes {
|
||||
@ -179,9 +179,9 @@ impl AsRef<[u8]> for Bytes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Bytes {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "bytes({})", self.len())
|
||||
impl Repr for Bytes {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("bytes({})", self.len())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use std::ops::Add;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use super::{Type, Value};
|
||||
use super::{Repr, Type, Value};
|
||||
use crate::diag::{At, SourceResult, StrResult};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
use crate::util::separated_list;
|
||||
@ -239,7 +239,7 @@ impl CastInfo {
|
||||
self.walk(|info| match info {
|
||||
CastInfo::Any => parts.push("anything".into()),
|
||||
CastInfo::Value(value, _) => {
|
||||
parts.push(value.repr().into());
|
||||
parts.push(value.repr());
|
||||
if value.ty() == found.ty() {
|
||||
matching_type = true;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops::{Add, Sub};
|
||||
|
||||
@ -9,7 +9,7 @@ use time::error::{Format, InvalidFormatDescription};
|
||||
use time::macros::format_description;
|
||||
use time::{format_description, Month, PrimitiveDateTime};
|
||||
|
||||
use super::{cast, func, scope, ty, Dict, Duration, Str, Value, Vm};
|
||||
use super::{cast, func, scope, ty, Dict, Duration, Repr, Str, Value, Vm};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::geom::Smart;
|
||||
use crate::util::pretty_array_like;
|
||||
@ -113,7 +113,7 @@ use crate::World;
|
||||
/// components such as `hour` or `minute`, which would only work on datetimes
|
||||
/// that have a specified time.
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, Copy, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Hash)]
|
||||
pub enum Datetime {
|
||||
/// Representation as a date.
|
||||
Date(time::Date),
|
||||
@ -426,20 +426,20 @@ impl Datetime {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Datetime {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let year = self.year().map(|y| eco_format!("year: {y}"));
|
||||
let month = self.month().map(|m| eco_format!("month: {m}"));
|
||||
let day = self.day().map(|d| eco_format!("day: {d}"));
|
||||
let hour = self.hour().map(|h| eco_format!("hour: {h}"));
|
||||
let minute = self.minute().map(|m| eco_format!("minute: {m}"));
|
||||
let second = self.second().map(|s| eco_format!("second: {s}"));
|
||||
impl Repr for Datetime {
|
||||
fn repr(&self) -> EcoString {
|
||||
let year = self.year().map(|y| eco_format!("year: {}", (y as i64).repr()));
|
||||
let month = self.month().map(|m| eco_format!("month: {}", (m as i64).repr()));
|
||||
let day = self.day().map(|d| eco_format!("day: {}", (d as i64).repr()));
|
||||
let hour = self.hour().map(|h| eco_format!("hour: {}", (h as i64).repr()));
|
||||
let minute = self.minute().map(|m| eco_format!("minute: {}", (m as i64).repr()));
|
||||
let second = self.second().map(|s| eco_format!("second: {}", (s as i64).repr()));
|
||||
let filtered = [year, month, day, hour, minute, second]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<EcoVec<_>>();
|
||||
|
||||
write!(f, "datetime{}", &pretty_array_like(&filtered, false))
|
||||
eco_format!("datetime{}", &pretty_array_like(&filtered, false))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::{Add, AddAssign};
|
||||
use std::sync::Arc;
|
||||
@ -7,7 +7,7 @@ use ecow::{eco_format, EcoString};
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use super::{array, func, scope, ty, Array, Str, Value};
|
||||
use super::{array, func, scope, ty, Array, Repr, Str, Value};
|
||||
use crate::diag::StrResult;
|
||||
use crate::syntax::is_ident;
|
||||
use crate::util::{pretty_array_like, separated_list, ArcExt};
|
||||
@ -117,7 +117,7 @@ impl Dict {
|
||||
pub fn finish(&self, expected: &[&str]) -> StrResult<()> {
|
||||
if let Some((key, _)) = self.iter().next() {
|
||||
let parts: Vec<_> = expected.iter().map(|s| eco_format!("\"{s}\"")).collect();
|
||||
let mut msg = format!("unexpected key {key:?}, valid keys are ");
|
||||
let mut msg = format!("unexpected key {}, valid keys are ", key.repr());
|
||||
msg.push_str(&separated_list(&parts, "and"));
|
||||
return Err(msg.into());
|
||||
}
|
||||
@ -200,9 +200,15 @@ impl Dict {
|
||||
}
|
||||
|
||||
impl Debug for Dict {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_map().entries(self.0.iter()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for Dict {
|
||||
fn repr(&self) -> EcoString {
|
||||
if self.is_empty() {
|
||||
return f.write_str("(:)");
|
||||
return "(:)".into();
|
||||
}
|
||||
|
||||
let max = 40;
|
||||
@ -211,9 +217,9 @@ impl Debug for Dict {
|
||||
.take(max)
|
||||
.map(|(key, value)| {
|
||||
if is_ident(key) {
|
||||
eco_format!("{key}: {value:?}")
|
||||
eco_format!("{key}: {}", value.repr())
|
||||
} else {
|
||||
eco_format!("{key:?}: {value:?}")
|
||||
eco_format!("{}: {}", key.repr(), value.repr())
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@ -222,7 +228,7 @@ impl Debug for Dict {
|
||||
pieces.push(eco_format!(".. ({} pairs omitted)", self.len() - max));
|
||||
}
|
||||
|
||||
f.write_str(&pretty_array_like(&pieces, false))
|
||||
pretty_array_like(&pieces, false).into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,15 +316,15 @@ impl From<IndexMap<Str, Value>> for Dict {
|
||||
/// The missing key access error message.
|
||||
#[cold]
|
||||
fn missing_key(key: &str) -> EcoString {
|
||||
eco_format!("dictionary does not contain key {:?}", Str::from(key))
|
||||
eco_format!("dictionary does not contain key {}", key.repr())
|
||||
}
|
||||
|
||||
/// The missing key access error message when no default was fiven.
|
||||
#[cold]
|
||||
fn missing_key_no_default(key: &str) -> EcoString {
|
||||
eco_format!(
|
||||
"dictionary does not contain key {:?} \
|
||||
"dictionary does not contain key {} \
|
||||
and no default value was specified",
|
||||
Str::from(key)
|
||||
key.repr()
|
||||
)
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
use ecow::eco_format;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use time::ext::NumericalDuration;
|
||||
|
||||
use super::{func, scope, ty};
|
||||
use super::{func, scope, ty, Repr};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
/// Represents a positive or negative span of time.
|
||||
#[ty(scope)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Duration(time::Duration);
|
||||
|
||||
impl Duration {
|
||||
@ -111,41 +111,41 @@ impl Duration {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Duration {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Duration {
|
||||
fn repr(&self) -> EcoString {
|
||||
let mut tmp = self.0;
|
||||
let mut vec = Vec::with_capacity(5);
|
||||
|
||||
let weeks = tmp.whole_seconds() / 604_800.0 as i64;
|
||||
if weeks != 0 {
|
||||
vec.push(eco_format!("weeks: {weeks}"));
|
||||
vec.push(eco_format!("weeks: {}", weeks.repr()));
|
||||
}
|
||||
tmp -= weeks.weeks();
|
||||
|
||||
let days = tmp.whole_days();
|
||||
if days != 0 {
|
||||
vec.push(eco_format!("days: {days}"));
|
||||
vec.push(eco_format!("days: {}", days.repr()));
|
||||
}
|
||||
tmp -= days.days();
|
||||
|
||||
let hours = tmp.whole_hours();
|
||||
if hours != 0 {
|
||||
vec.push(eco_format!("hours: {hours}"));
|
||||
vec.push(eco_format!("hours: {}", hours.repr()));
|
||||
}
|
||||
tmp -= hours.hours();
|
||||
|
||||
let minutes = tmp.whole_minutes();
|
||||
if minutes != 0 {
|
||||
vec.push(eco_format!("minutes: {minutes}"));
|
||||
vec.push(eco_format!("minutes: {}", minutes.repr()));
|
||||
}
|
||||
tmp -= minutes.minutes();
|
||||
|
||||
let seconds = tmp.whole_seconds();
|
||||
if seconds != 0 {
|
||||
vec.push(eco_format!("seconds: {seconds}"));
|
||||
vec.push(eco_format!("seconds: {}", seconds.repr()));
|
||||
}
|
||||
|
||||
write!(f, "duration{}", &pretty_array_like(&vec, false))
|
||||
eco_format!("duration{}", &pretty_array_like(&vec, false))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use comemo::{Prehashed, Tracked, TrackedMut};
|
||||
use ecow::EcoString;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{
|
||||
@ -118,7 +119,7 @@ pub use typst_macros::func;
|
||||
/// [`array.push(value)`]($array.push). These can modify the values they are
|
||||
/// called on.
|
||||
#[ty(scope, name = "function")]
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Func {
|
||||
/// The internal representation.
|
||||
@ -128,7 +129,7 @@ pub struct Func {
|
||||
}
|
||||
|
||||
/// The different kinds of function representations.
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
enum Repr {
|
||||
/// A native Rust function.
|
||||
Native(Static<NativeFuncData>),
|
||||
@ -363,11 +364,11 @@ impl Func {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Func {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl super::Repr for Func {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self.name() {
|
||||
Some(name) => write!(f, "{name}"),
|
||||
None => f.write_str("(..) => .."),
|
||||
Some(name) => name.into(),
|
||||
None => "(..) => ..".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -412,6 +413,7 @@ pub trait NativeFunc {
|
||||
}
|
||||
|
||||
/// Defines a native function.
|
||||
#[derive(Debug)]
|
||||
pub struct NativeFuncData {
|
||||
pub function: fn(&mut Vm, &mut Args) -> SourceResult<Value>,
|
||||
pub name: &'static str,
|
||||
@ -461,7 +463,7 @@ pub struct ParamInfo {
|
||||
}
|
||||
|
||||
/// A user-defined closure.
|
||||
#[derive(Hash)]
|
||||
#[derive(Debug, Hash)]
|
||||
pub(super) struct Closure {
|
||||
/// The closure's syntax node. Must be castable to `ast::Closure`.
|
||||
pub node: SyntaxNode,
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::num::{NonZeroI64, NonZeroIsize, NonZeroU64, NonZeroUsize};
|
||||
|
||||
use ecow::eco_format;
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use super::{cast, func, scope, ty, Str, Value};
|
||||
use super::{cast, func, scope, ty, Repr, Str, Value};
|
||||
|
||||
/// A whole number.
|
||||
///
|
||||
@ -51,6 +51,18 @@ impl i64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for i64 {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for f64 {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("{self}")
|
||||
}
|
||||
}
|
||||
|
||||
/// A value that can be cast to an integer.
|
||||
pub struct ToInt(i64);
|
||||
|
||||
|
@ -65,7 +65,7 @@ pub use self::str::{format_str, Regex, Str};
|
||||
pub use self::symbol::{symbols, Symbol};
|
||||
pub use self::tracer::Tracer;
|
||||
pub use self::ty::{scope, ty, NativeType, NativeTypeData, Type};
|
||||
pub use self::value::{Dynamic, Value};
|
||||
pub use self::value::{Dynamic, Repr, Value};
|
||||
pub use self::version::Version;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
@ -24,7 +24,7 @@ use crate::diag::StrResult;
|
||||
/// >>> #(-3)
|
||||
/// ```
|
||||
#[ty]
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Module {
|
||||
/// The module's name.
|
||||
@ -34,7 +34,7 @@ pub struct Module {
|
||||
}
|
||||
|
||||
/// The internal representation.
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
struct Repr {
|
||||
/// The top-level definitions that were bound in this module.
|
||||
scope: Scope,
|
||||
@ -100,9 +100,9 @@ impl Module {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Module {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "<module {}>", self.name())
|
||||
impl super::Repr for Module {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("<module {}>", self.name())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use ecow::EcoString;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use super::{cast, ty, CastInfo, FromValue, IntoValue, Reflect, Type, Value};
|
||||
use super::{cast, ty, CastInfo, FromValue, IntoValue, Reflect, Repr, Type, Value};
|
||||
use crate::diag::StrResult;
|
||||
|
||||
/// A value that indicates the absence of any other value.
|
||||
@ -18,7 +19,7 @@ use crate::diag::StrResult;
|
||||
/// Not visible: #none
|
||||
/// ```
|
||||
#[ty(name = "none")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct NoneValue;
|
||||
|
||||
impl Reflect for NoneValue {
|
||||
@ -50,9 +51,9 @@ impl FromValue for NoneValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NoneValue {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("none")
|
||||
impl Repr for NoneValue {
|
||||
fn repr(&self) -> EcoString {
|
||||
"none".into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
//! Operations on values.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use ecow::eco_format;
|
||||
|
||||
use super::{format_str, IntoValue, Regex, Value};
|
||||
use super::{format_str, IntoValue, Regex, Repr, Value};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::geom::{Align, Length, Numeric, Rel, Smart, Stroke};
|
||||
use Value::*;
|
||||
@ -436,9 +435,9 @@ pub fn compare(lhs: &Value, rhs: &Value) -> StrResult<Ordering> {
|
||||
}
|
||||
|
||||
/// Try to compare two values.
|
||||
fn try_cmp_values<T: PartialOrd + Debug>(a: &T, b: &T) -> StrResult<Ordering> {
|
||||
fn try_cmp_values<T: PartialOrd + Repr>(a: &T, b: &T) -> StrResult<Ordering> {
|
||||
a.partial_cmp(b)
|
||||
.ok_or_else(|| eco_format!("cannot compare {:?} with {:?}", a, b))
|
||||
.ok_or_else(|| eco_format!("cannot compare {} with {}", a.repr(), b.repr()))
|
||||
}
|
||||
|
||||
/// Try to compare two datetimes.
|
||||
|
@ -288,7 +288,13 @@ impl Plugin {
|
||||
|
||||
impl Debug for Plugin {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("plugin(..)")
|
||||
f.pad("Plugin(..)")
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Repr for Plugin {
|
||||
fn repr(&self) -> EcoString {
|
||||
"plugin(..)".into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::{Add, AddAssign, Deref, Range};
|
||||
|
||||
@ -8,13 +8,14 @@ use serde::{Deserialize, Serialize};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use super::{
|
||||
cast, dict, func, scope, ty, Args, Array, Bytes, Dict, Func, IntoValue, Type, Value,
|
||||
Version, Vm,
|
||||
cast, dict, func, scope, ty, Args, Array, Bytes, Dict, Func, IntoValue, Repr, Type,
|
||||
Value, Version, Vm,
|
||||
};
|
||||
use crate::diag::{bail, At, SourceResult, StrResult};
|
||||
use crate::geom::Align;
|
||||
use crate::model::Label;
|
||||
use crate::syntax::{Span, Spanned};
|
||||
use crate::util::fmt::format_int_with_base;
|
||||
|
||||
/// Create a new [`Str`] from a format string.
|
||||
#[macro_export]
|
||||
@ -68,7 +69,8 @@ pub use ecow::eco_format;
|
||||
/// - `[\t]` for a tab
|
||||
/// - `[\u{1f600}]` for a hexadecimal Unicode escape sequence
|
||||
#[ty(scope, title = "String")]
|
||||
#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Str(EcoString);
|
||||
|
||||
@ -616,45 +618,6 @@ cast! {
|
||||
v: Str => Self::Str(v),
|
||||
}
|
||||
|
||||
/// Format an integer in a base.
|
||||
fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
||||
if n == 0 {
|
||||
return "0".into();
|
||||
}
|
||||
|
||||
// In Rust, `format!("{:x}", -14i64)` is not `-e` but `fffffffffffffff2`.
|
||||
// So we can only use the built-in for decimal, not bin/oct/hex.
|
||||
if base == 10 {
|
||||
return eco_format!("{n}");
|
||||
}
|
||||
|
||||
// The largest output is `to_base(i64::MIN, 2)`, which is 65 chars long.
|
||||
const SIZE: usize = 65;
|
||||
let mut digits = [b'\0'; SIZE];
|
||||
let mut i = SIZE;
|
||||
|
||||
// It's tempting to take the absolute value, but this will fail for i64::MIN.
|
||||
// Instead, we turn n negative, as -i64::MAX is perfectly representable.
|
||||
let negative = n < 0;
|
||||
if n > 0 {
|
||||
n = -n;
|
||||
}
|
||||
|
||||
while n != 0 {
|
||||
let digit = char::from_digit(-(n % base) as u32, base as u32);
|
||||
i -= 1;
|
||||
digits[i] = digit.unwrap_or('?') as u8;
|
||||
n /= base;
|
||||
}
|
||||
|
||||
if negative {
|
||||
i -= 1;
|
||||
digits[i] = b'-';
|
||||
}
|
||||
|
||||
std::str::from_utf8(&digits[i..]).unwrap_or_default().into()
|
||||
}
|
||||
|
||||
/// The out of bounds access error message.
|
||||
#[cold]
|
||||
fn out_of_bounds(index: i64, len: usize) -> EcoString {
|
||||
@ -717,18 +680,9 @@ impl Display for Str {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Str {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.write_char('"')?;
|
||||
for c in self.chars() {
|
||||
match c {
|
||||
'\0' => f.write_str("\\u{0}")?,
|
||||
'\'' => f.write_str("'")?,
|
||||
'"' => f.write_str(r#"\""#)?,
|
||||
_ => Display::fmt(&c.escape_debug(), f)?,
|
||||
}
|
||||
}
|
||||
f.write_char('"')
|
||||
impl Repr for Str {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.as_ref().repr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -836,6 +790,29 @@ cast! {
|
||||
v: Str => v.into(),
|
||||
}
|
||||
|
||||
impl Repr for &str {
|
||||
fn repr(&self) -> EcoString {
|
||||
let mut r = EcoString::with_capacity(self.len() + 2);
|
||||
r.push('"');
|
||||
for c in self.chars() {
|
||||
match c {
|
||||
'\0' => r.push_str(r"\u{0}"),
|
||||
'\'' => r.push('\''),
|
||||
'"' => r.push_str(r#"\""#),
|
||||
_ => c.escape_debug().for_each(|c| r.push(c)),
|
||||
}
|
||||
}
|
||||
r.push('"');
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr for EcoString {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.as_ref().repr()
|
||||
}
|
||||
}
|
||||
|
||||
/// A regular expression.
|
||||
///
|
||||
/// Can be used as a [show rule selector]($styling/#show-rules) and with
|
||||
@ -856,7 +833,7 @@ cast! {
|
||||
/// .split(regex("[,;]")))
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Regex(regex::Regex);
|
||||
|
||||
impl Regex {
|
||||
@ -895,9 +872,9 @@ impl Deref for Regex {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Regex {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "regex({:?})", self.0.as_str())
|
||||
impl Repr for Regex {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("regex({})", self.0.as_str().repr())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::collections::BTreeSet;
|
||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::EcoString;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
use super::{cast, func, scope, ty, Array};
|
||||
@ -43,11 +43,11 @@ pub use typst_macros::symbols;
|
||||
/// $arrow.t.quad$
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Symbol(Repr);
|
||||
|
||||
/// The internal representation.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
enum Repr {
|
||||
Single(char),
|
||||
Const(&'static [(&'static str, char)]),
|
||||
@ -55,7 +55,7 @@ enum Repr {
|
||||
}
|
||||
|
||||
/// A collection of symbols.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
enum List {
|
||||
Static(&'static [(&'static str, char)]),
|
||||
Runtime(Box<[(EcoString, char)]>),
|
||||
@ -208,15 +208,15 @@ impl Symbol {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Symbol {
|
||||
impl Display for Symbol {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.write_char(self.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Symbol {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.write_char(self.get())
|
||||
impl super::Repr for Symbol {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("\"{}\"", self.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
use ecow::eco_format;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{cast, func, Func, NativeFuncData, Scope, Value};
|
||||
use super::{cast, func, Func, NativeFuncData, Repr, Scope, Value};
|
||||
use crate::diag::StrResult;
|
||||
use crate::util::Static;
|
||||
|
||||
@ -53,7 +53,7 @@ pub use typst_macros::{scope, ty};
|
||||
/// - The `{in}` operator on a type and a dictionary will evaluate to `{true}`
|
||||
/// if the dictionary has a string key matching the type's name
|
||||
#[ty(scope)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Type(Static<NativeTypeData>);
|
||||
|
||||
impl Type {
|
||||
@ -139,9 +139,9 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Type {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(self.long_name())
|
||||
impl Repr for Type {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.long_name().into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,6 +180,7 @@ pub trait NativeType {
|
||||
}
|
||||
|
||||
/// Defines a native type.
|
||||
#[derive(Debug)]
|
||||
pub struct NativeTypeData {
|
||||
pub name: &'static str,
|
||||
pub long_name: &'static str,
|
||||
|
@ -1,10 +1,10 @@
|
||||
use std::any::Any;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::{self, Debug};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::eco_format;
|
||||
use ecow::{eco_format, EcoString};
|
||||
use serde::de::value::{MapAccessDeserializer, SeqAccessDeserializer};
|
||||
use serde::de::{Error, MapAccess, SeqAccess, Visitor};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
@ -12,9 +12,9 @@ use siphasher::sip128::{Hasher128, SipHasher13};
|
||||
use typst::eval::Duration;
|
||||
|
||||
use super::{
|
||||
fields, format_str, ops, Args, Array, AutoValue, Bytes, CastInfo, Content, Dict,
|
||||
FromValue, Func, IntoValue, Module, NativeType, NoneValue, Plugin, Reflect, Scope,
|
||||
Str, Symbol, Type, Version,
|
||||
fields, ops, Args, Array, AutoValue, Bytes, CastInfo, Content, Dict, FromValue, Func,
|
||||
IntoValue, Module, NativeType, NoneValue, Plugin, Reflect, Scope, Str, Symbol, Type,
|
||||
Version,
|
||||
};
|
||||
use crate::diag::StrResult;
|
||||
use crate::eval::Datetime;
|
||||
@ -23,7 +23,7 @@ use crate::model::{Label, Styles};
|
||||
use crate::syntax::{ast, Span};
|
||||
|
||||
/// A computational value.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub enum Value {
|
||||
/// The value that indicates the absence of a meaningful value.
|
||||
#[default]
|
||||
@ -90,7 +90,7 @@ impl Value {
|
||||
/// Create a new dynamic value.
|
||||
pub fn dynamic<T>(any: T) -> Self
|
||||
where
|
||||
T: Debug + NativeType + PartialEq + Hash + Sync + Send + 'static,
|
||||
T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
|
||||
{
|
||||
Self::Dyn(Dynamic::new(any))
|
||||
}
|
||||
@ -194,11 +194,6 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the debug representation of the value.
|
||||
pub fn repr(&self) -> Str {
|
||||
format_str!("{self:?}")
|
||||
}
|
||||
|
||||
/// Return the display representation of the value.
|
||||
pub fn display(self) -> Content {
|
||||
match self {
|
||||
@ -210,7 +205,7 @@ impl Value {
|
||||
Self::Symbol(v) => item!(text)(v.get().into()),
|
||||
Self::Content(v) => v,
|
||||
Self::Module(module) => module.content(),
|
||||
_ => item!(raw)(self.repr().into(), Some("typc".into()), false),
|
||||
_ => item!(raw)(self.repr(), Some("typc".into()), false),
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,38 +219,38 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Value {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Value {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::None => Debug::fmt(&NoneValue, f),
|
||||
Self::Auto => Debug::fmt(&AutoValue, f),
|
||||
Self::Bool(v) => Debug::fmt(v, f),
|
||||
Self::Int(v) => Debug::fmt(v, f),
|
||||
Self::Float(v) => Debug::fmt(v, f),
|
||||
Self::Length(v) => Debug::fmt(v, f),
|
||||
Self::Angle(v) => Debug::fmt(v, f),
|
||||
Self::Ratio(v) => Debug::fmt(v, f),
|
||||
Self::Relative(v) => Debug::fmt(v, f),
|
||||
Self::Fraction(v) => Debug::fmt(v, f),
|
||||
Self::Color(v) => Debug::fmt(v, f),
|
||||
Self::Gradient(v) => Debug::fmt(v, f),
|
||||
Self::Symbol(v) => Debug::fmt(v, f),
|
||||
Self::Version(v) => Debug::fmt(v, f),
|
||||
Self::Str(v) => Debug::fmt(v, f),
|
||||
Self::Bytes(v) => Debug::fmt(v, f),
|
||||
Self::Label(v) => Debug::fmt(v, f),
|
||||
Self::Datetime(v) => Debug::fmt(v, f),
|
||||
Self::Duration(v) => Debug::fmt(v, f),
|
||||
Self::Content(v) => Debug::fmt(v, f),
|
||||
Self::Styles(v) => Debug::fmt(v, f),
|
||||
Self::Array(v) => Debug::fmt(v, f),
|
||||
Self::Dict(v) => Debug::fmt(v, f),
|
||||
Self::Func(v) => Debug::fmt(v, f),
|
||||
Self::Args(v) => Debug::fmt(v, f),
|
||||
Self::Type(v) => Debug::fmt(v, f),
|
||||
Self::Module(v) => Debug::fmt(v, f),
|
||||
Self::Plugin(v) => Debug::fmt(v, f),
|
||||
Self::Dyn(v) => Debug::fmt(v, f),
|
||||
Self::None => NoneValue.repr(),
|
||||
Self::Auto => AutoValue.repr(),
|
||||
Self::Bool(v) => v.repr(),
|
||||
Self::Int(v) => v.repr(),
|
||||
Self::Float(v) => v.repr(),
|
||||
Self::Length(v) => v.repr(),
|
||||
Self::Angle(v) => v.repr(),
|
||||
Self::Ratio(v) => v.repr(),
|
||||
Self::Relative(v) => v.repr(),
|
||||
Self::Fraction(v) => v.repr(),
|
||||
Self::Color(v) => v.repr(),
|
||||
Self::Gradient(v) => v.repr(),
|
||||
Self::Symbol(v) => v.repr(),
|
||||
Self::Version(v) => v.repr(),
|
||||
Self::Str(v) => v.repr(),
|
||||
Self::Bytes(v) => v.repr(),
|
||||
Self::Label(v) => v.repr(),
|
||||
Self::Datetime(v) => v.repr(),
|
||||
Self::Duration(v) => v.repr(),
|
||||
Self::Content(v) => v.repr(),
|
||||
Self::Styles(v) => v.repr(),
|
||||
Self::Array(v) => v.repr(),
|
||||
Self::Dict(v) => v.repr(),
|
||||
Self::Func(v) => v.repr(),
|
||||
Self::Args(v) => v.repr(),
|
||||
Self::Type(v) => v.repr(),
|
||||
Self::Module(v) => v.repr(),
|
||||
Self::Plugin(v) => v.repr(),
|
||||
Self::Dyn(v) => v.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -452,7 +447,7 @@ impl<'de> Visitor<'de> for ValueVisitor {
|
||||
}
|
||||
|
||||
/// A value that is not part of the built-in enum.
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Dynamic(Arc<dyn Bounds>);
|
||||
|
||||
@ -460,7 +455,7 @@ impl Dynamic {
|
||||
/// Create a new instance from any value that satisfies the required bounds.
|
||||
pub fn new<T>(any: T) -> Self
|
||||
where
|
||||
T: Debug + NativeType + PartialEq + Hash + Sync + Send + 'static,
|
||||
T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
|
||||
{
|
||||
Self(Arc::new(any))
|
||||
}
|
||||
@ -481,9 +476,9 @@ impl Dynamic {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Dynamic {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.0, f)
|
||||
impl Repr for Dynamic {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.0.repr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,7 +488,13 @@ impl PartialEq for Dynamic {
|
||||
}
|
||||
}
|
||||
|
||||
trait Bounds: Debug + Sync + Send + 'static {
|
||||
/// A trait that defines the `repr` of a Typst value.
|
||||
pub trait Repr {
|
||||
/// Return the debug representation of the value.
|
||||
fn repr(&self) -> EcoString;
|
||||
}
|
||||
|
||||
trait Bounds: Debug + Repr + Sync + Send + 'static {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
||||
fn dyn_ty(&self) -> Type;
|
||||
@ -502,7 +503,7 @@ trait Bounds: Debug + Sync + Send + 'static {
|
||||
|
||||
impl<T> Bounds for T
|
||||
where
|
||||
T: Debug + NativeType + PartialEq + Hash + Sync + Send + 'static,
|
||||
T: Debug + Repr + NativeType + PartialEq + Hash + Sync + Send + 'static,
|
||||
{
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
@ -631,7 +632,7 @@ mod tests {
|
||||
|
||||
#[track_caller]
|
||||
fn test(value: impl IntoValue, exp: &str) {
|
||||
assert_eq!(format!("{:?}", value.into_value()), exp);
|
||||
assert_eq!(value.into_value().repr(), exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1,11 +1,11 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||
use std::fmt::{self, Display, Formatter, Write};
|
||||
use std::hash::Hash;
|
||||
use std::iter::repeat;
|
||||
|
||||
use ecow::{eco_format, EcoVec};
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
|
||||
use super::{cast, func, scope, ty};
|
||||
use super::{cast, func, scope, ty, Repr};
|
||||
use crate::diag::{bail, error, StrResult};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
@ -19,7 +19,7 @@ use crate::util::pretty_array_like;
|
||||
/// The first three components have names: `major`, `minor`, `patch`. All
|
||||
/// components after that do not have names.
|
||||
#[ty(scope)]
|
||||
#[derive(Default, Clone, Hash)]
|
||||
#[derive(Debug, Default, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Version(EcoVec<u32>);
|
||||
|
||||
@ -165,7 +165,7 @@ impl PartialEq for Version {
|
||||
}
|
||||
|
||||
impl Display for Version {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
let mut first = true;
|
||||
for &v in &self.0 {
|
||||
if !first {
|
||||
@ -178,11 +178,10 @@ impl Display for Version {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Version {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.write_str("version")?;
|
||||
impl Repr for Version {
|
||||
fn repr(&self) -> EcoString {
|
||||
let parts: Vec<_> = self.0.iter().map(|v| eco_format!("{v}")).collect();
|
||||
f.write_str(&pretty_array_like(&parts, false))
|
||||
eco_format!("version{}", &pretty_array_like(&parts, false))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ use super::color::PaintEncode;
|
||||
use super::extg::ExternalGraphicsState;
|
||||
use super::{deflate, AbsExt, EmExt, PdfContext, RefExt};
|
||||
use crate::doc::{Destination, Frame, FrameItem, GroupItem, Meta, TextItem};
|
||||
use crate::eval::Repr;
|
||||
use crate::font::Font;
|
||||
use crate::geom::{
|
||||
self, Abs, Em, FixedStroke, Geometry, LineCap, LineJoin, Numeric, Paint, Point,
|
||||
@ -710,6 +711,12 @@ pub struct PdfPageLabel {
|
||||
pub offset: Option<NonZeroUsize>,
|
||||
}
|
||||
|
||||
impl Repr for PdfPageLabel {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
/// A PDF page label number style.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum PdfPageLabelStyle {
|
||||
|
@ -133,7 +133,7 @@ impl Hash for Font {
|
||||
|
||||
impl Debug for Font {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "Font({},{:?})", self.info().family, self.info().variant)
|
||||
write!(f, "Font({}, {:?})", self.info().family, self.info().variant)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
use ecow::EcoString;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::eval::{cast, Cast, IntoValue};
|
||||
use crate::eval::{cast, Cast, IntoValue, Repr};
|
||||
use crate::geom::Ratio;
|
||||
|
||||
/// Properties that distinguish a font from other fonts in the same family.
|
||||
@ -176,7 +177,7 @@ cast! {
|
||||
}
|
||||
|
||||
/// The width of a font.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct FontStretch(u16);
|
||||
@ -247,10 +248,9 @@ impl Default for FontStretch {
|
||||
Self::NORMAL
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FontStretch {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
self.to_ratio().fmt(f)
|
||||
impl Repr for FontStretch {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.to_ratio().repr()
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,6 +291,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_font_stretch_debug() {
|
||||
assert_eq!(format!("{:?}", FontStretch::EXPANDED), "125%")
|
||||
assert_eq!(FontStretch::EXPANDED.repr(), "125%")
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
/// An absolute length.
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Abs(Scalar);
|
||||
|
||||
impl Abs {
|
||||
@ -133,9 +133,9 @@ impl Numeric for Abs {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Abs {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}pt", round_2(self.to_pt()))
|
||||
impl Repr for Abs {
|
||||
fn repr(&self) -> EcoString {
|
||||
format_float(self.to_pt(), Some(2), "pt")
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +220,7 @@ cast! {
|
||||
}
|
||||
|
||||
/// Different units of absolute measurement.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum AbsUnit {
|
||||
/// Points.
|
||||
Pt,
|
||||
@ -244,17 +244,6 @@ impl AbsUnit {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for AbsUnit {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(match self {
|
||||
AbsUnit::Mm => "mm",
|
||||
AbsUnit::Pt => "pt",
|
||||
AbsUnit::Cm => "cm",
|
||||
AbsUnit::In => "in",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -42,7 +42,7 @@ use super::*;
|
||||
/// #left.y (none)
|
||||
/// ```
|
||||
#[ty(scope, name = "alignment")]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Align {
|
||||
H(HAlign),
|
||||
V(VAlign),
|
||||
@ -149,12 +149,12 @@ impl Add for Align {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Align {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Align {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::H(x) => x.fmt(f),
|
||||
Self::V(y) => y.fmt(f),
|
||||
Self::Both(x, y) => write!(f, "{x:?} + {y:?}"),
|
||||
Self::H(x) => x.repr(),
|
||||
Self::V(y) => y.repr(),
|
||||
Self::Both(x, y) => eco_format!("{} + {}", x.repr(), y.repr()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -195,7 +195,7 @@ cast! {
|
||||
}
|
||||
|
||||
/// Where to align something horizontally.
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum HAlign {
|
||||
#[default]
|
||||
Start,
|
||||
@ -229,15 +229,15 @@ impl HAlign {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for HAlign {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(match self {
|
||||
Self::Start => "start",
|
||||
Self::Left => "left",
|
||||
Self::Center => "center",
|
||||
Self::Right => "right",
|
||||
Self::End => "end",
|
||||
})
|
||||
impl Repr for HAlign {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Start => "start".into(),
|
||||
Self::Left => "left".into(),
|
||||
Self::Center => "center".into(),
|
||||
Self::Right => "right".into(),
|
||||
Self::End => "end".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,12 +268,12 @@ cast! {
|
||||
self => Align::H(self).into_value(),
|
||||
align: Align => match align {
|
||||
Align::H(v) => v,
|
||||
v => bail!("expected `start`, `left`, `center`, `right`, or `end`, found {v:?}"),
|
||||
v => bail!("expected `start`, `left`, `center`, `right`, or `end`, found {}", v.repr()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Where to align something vertically.
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum VAlign {
|
||||
#[default]
|
||||
Top,
|
||||
@ -301,13 +301,13 @@ impl VAlign {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for VAlign {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(match self {
|
||||
Self::Top => "top",
|
||||
Self::Horizon => "horizon",
|
||||
Self::Bottom => "bottom",
|
||||
})
|
||||
impl Repr for VAlign {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Top => "top".into(),
|
||||
Self::Horizon => "horizon".into(),
|
||||
Self::Bottom => "bottom".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@ cast! {
|
||||
self => Align::V(self).into_value(),
|
||||
align: Align => match align {
|
||||
Align::V(v) => v,
|
||||
v => bail!("expected `top`, `horizon`, or `bottom`, found {v:?}"),
|
||||
v => bail!("expected `top`, `horizon`, or `bottom`, found {}", v.repr()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,7 +338,7 @@ cast! {
|
||||
///
|
||||
/// For horizontal alignment, start is globally left and for vertical alignment
|
||||
/// it is globally top.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum FixedAlign {
|
||||
Start,
|
||||
Center,
|
||||
@ -357,16 +357,6 @@ impl FixedAlign {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FixedAlign {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(match self {
|
||||
Self::Start => "start",
|
||||
Self::Center => "center",
|
||||
Self::End => "end",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Side> for FixedAlign {
|
||||
fn from(side: Side) -> Self {
|
||||
match side {
|
||||
|
@ -12,7 +12,7 @@ use super::*;
|
||||
/// #rotate(10deg)[Hello there!]
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Angle(Scalar);
|
||||
|
||||
impl Angle {
|
||||
@ -119,9 +119,9 @@ impl Numeric for Angle {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Angle {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}deg", round_2(self.to_deg()))
|
||||
impl Repr for Angle {
|
||||
fn repr(&self) -> EcoString {
|
||||
format_float(self.to_deg(), Some(2), "deg")
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ impl Sum for Angle {
|
||||
}
|
||||
|
||||
/// Different units of angular measurement.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum AngleUnit {
|
||||
/// Radians.
|
||||
Rad,
|
||||
@ -205,15 +205,6 @@ impl AngleUnit {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for AngleUnit {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(match self {
|
||||
Self::Rad => "rad",
|
||||
Self::Deg => "deg",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A quadrant of the Cartesian plane.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub enum Quadrant {
|
||||
|
@ -156,7 +156,7 @@ where
|
||||
}
|
||||
|
||||
/// The two layouting axes.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Axis {
|
||||
/// The horizontal axis.
|
||||
X,
|
||||
@ -182,27 +182,16 @@ impl Axis {
|
||||
Self::Y => Self::X,
|
||||
}
|
||||
}
|
||||
|
||||
/// A description of this axis' direction.
|
||||
pub fn description(self) -> &'static str {
|
||||
match self {
|
||||
Self::X => "horizontal",
|
||||
Self::Y => "vertical",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Axis {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(self.description())
|
||||
}
|
||||
}
|
||||
|
||||
cast! {
|
||||
Axis,
|
||||
self => self.description().into_value(),
|
||||
self => match self {
|
||||
Self::X => "horizontal".into_value(),
|
||||
Self::Y => "vertical".into_value(),
|
||||
},
|
||||
"horizontal" => Self::X,
|
||||
"vertical" => Self::X,
|
||||
"vertical" => Self::Y,
|
||||
}
|
||||
|
||||
impl<T> Axes<Option<T>> {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
use ecow::EcoVec;
|
||||
use once_cell::sync::Lazy;
|
||||
use palette::encoding::{self, Linear};
|
||||
use palette::{Darken, Desaturate, FromColor, Lighten, RgbHue, Saturate, ShiftHue};
|
||||
@ -185,7 +185,7 @@ const ANGLE_EPSILON: f32 = 1e-5;
|
||||
///
|
||||
/// Feel free to use or create a package with other presets useful to you!
|
||||
#[ty(scope)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum Color {
|
||||
/// A 32-bit luma color.
|
||||
Luma(Luma),
|
||||
@ -1223,106 +1223,101 @@ impl Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Color {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Color {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Luma(c) => write!(f, "luma({:?})", Ratio::new(c.luma as _)),
|
||||
Self::Rgba(_) => write!(f, "rgb({:?})", self.to_hex()),
|
||||
Self::Luma(c) => eco_format!("luma({})", Ratio::new(c.luma as _).repr()),
|
||||
Self::Rgba(_) => eco_format!("rgb({})", self.to_hex().repr()),
|
||||
Self::LinearRgb(c) => {
|
||||
if c.alpha == 1.0 {
|
||||
write!(
|
||||
f,
|
||||
"color.linear-rgb({:?}, {:?}, {:?})",
|
||||
Ratio::new(c.red as _),
|
||||
Ratio::new(c.green as _),
|
||||
Ratio::new(c.blue as _),
|
||||
eco_format!(
|
||||
"color.linear-rgb({}, {}, {})",
|
||||
Ratio::new(c.red as _).repr(),
|
||||
Ratio::new(c.green as _).repr(),
|
||||
Ratio::new(c.blue as _).repr(),
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"color.linear-rgb({:?}, {:?}, {:?}, {:?})",
|
||||
Ratio::new(c.red as _),
|
||||
Ratio::new(c.green as _),
|
||||
Ratio::new(c.blue as _),
|
||||
Ratio::new(c.alpha as _),
|
||||
eco_format!(
|
||||
"color.linear-rgb({}, {}, {}, {})",
|
||||
Ratio::new(c.red as _).repr(),
|
||||
Ratio::new(c.green as _).repr(),
|
||||
Ratio::new(c.blue as _).repr(),
|
||||
Ratio::new(c.alpha as _).repr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::Cmyk(c) => {
|
||||
write!(
|
||||
f,
|
||||
"rgb({:?}, {:?}, {:?}, {:?})",
|
||||
Ratio::new(c.c as _),
|
||||
Ratio::new(c.m as _),
|
||||
Ratio::new(c.y as _),
|
||||
Ratio::new(c.k as _),
|
||||
eco_format!(
|
||||
"rgb({}, {}, {}, {})",
|
||||
Ratio::new(c.c as _).repr(),
|
||||
Ratio::new(c.m as _).repr(),
|
||||
Ratio::new(c.y as _).repr(),
|
||||
Ratio::new(c.k as _).repr(),
|
||||
)
|
||||
}
|
||||
Self::Oklab(c) => {
|
||||
if c.alpha == 1.0 {
|
||||
write!(
|
||||
f,
|
||||
"oklab({:?}, {:.3}, {:.3})",
|
||||
Ratio::new(c.l as _),
|
||||
(c.a * 1000.0).round() / 1000.0,
|
||||
(c.b * 1000.0).round() / 1000.0,
|
||||
eco_format!(
|
||||
"oklab({}, {}, {})",
|
||||
Ratio::new(c.l as _).repr(),
|
||||
format_float(c.a as _, Some(3), ""),
|
||||
format_float(c.b as _, Some(3), ""),
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"oklab({:?}, {:?}, {:?}, {:?})",
|
||||
Ratio::new(c.l as _),
|
||||
(c.a * 1000.0).round() / 1000.0,
|
||||
(c.b * 1000.0).round() / 1000.0,
|
||||
Ratio::new(c.alpha as _),
|
||||
eco_format!(
|
||||
"oklab({}, {}, {}, {})",
|
||||
Ratio::new(c.l as _).repr(),
|
||||
format_float(c.a as _, Some(3), ""),
|
||||
format_float(c.b as _, Some(3), ""),
|
||||
Ratio::new(c.alpha as _).repr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::Hsl(c) => {
|
||||
if c.alpha == 1.0 {
|
||||
write!(
|
||||
f,
|
||||
"color.hsl({:?}, {:?}, {:?})",
|
||||
eco_format!(
|
||||
"color.hsl({}, {}, {})",
|
||||
Angle::deg(
|
||||
c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _
|
||||
),
|
||||
Ratio::new(c.saturation as _),
|
||||
Ratio::new(c.lightness as _),
|
||||
)
|
||||
.repr(),
|
||||
Ratio::new(c.saturation as _).repr(),
|
||||
Ratio::new(c.lightness as _).repr(),
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"color.hsl({:?}, {:?}, {:?}, {:?})",
|
||||
eco_format!(
|
||||
"color.hsl({}, {}, {}, {})",
|
||||
Angle::deg(
|
||||
c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _
|
||||
),
|
||||
Ratio::new(c.saturation as _),
|
||||
Ratio::new(c.lightness as _),
|
||||
Ratio::new(c.alpha as _),
|
||||
)
|
||||
.repr(),
|
||||
Ratio::new(c.saturation as _).repr(),
|
||||
Ratio::new(c.lightness as _).repr(),
|
||||
Ratio::new(c.alpha as _).repr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::Hsv(c) => {
|
||||
if c.alpha == 1.0 {
|
||||
write!(
|
||||
f,
|
||||
"color.hsv({:?}, {:?}, {:?})",
|
||||
eco_format!(
|
||||
"color.hsv({}, {}, {})",
|
||||
Angle::deg(
|
||||
c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _
|
||||
),
|
||||
Ratio::new(c.saturation as _),
|
||||
Ratio::new(c.value as _),
|
||||
)
|
||||
.repr(),
|
||||
Ratio::new(c.saturation as _).repr(),
|
||||
Ratio::new(c.value as _).repr(),
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"color.hsv({:?}, {:?}, {:?}, {:?})",
|
||||
eco_format!(
|
||||
"color.hsv({}, {}, {}, {})",
|
||||
Angle::deg(
|
||||
c.hue.into_degrees().rem_euclid(360.0 + ANGLE_EPSILON) as _
|
||||
),
|
||||
Ratio::new(c.saturation as _),
|
||||
Ratio::new(c.value as _),
|
||||
Ratio::new(c.alpha as _),
|
||||
)
|
||||
.repr(),
|
||||
Ratio::new(c.saturation as _).repr(),
|
||||
Ratio::new(c.value as _).repr(),
|
||||
Ratio::new(c.alpha as _).repr(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1404,7 +1399,7 @@ impl FromStr for Color {
|
||||
}
|
||||
|
||||
/// An 8-bit CMYK color.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Cmyk {
|
||||
/// The cyan component.
|
||||
pub c: f32,
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::eval::{CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
use super::*;
|
||||
use crate::eval::{CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
/// A container with components for the four corners of a rectangle.
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
|
@ -16,7 +16,7 @@ use super::*;
|
||||
/// #stack(dir: direction.rtl)[A][B][C]
|
||||
/// ```
|
||||
#[ty(scope, name = "direction")]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Dir {
|
||||
/// Left to right.
|
||||
LTR,
|
||||
@ -117,14 +117,14 @@ impl Dir {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Dir {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(match self {
|
||||
Self::LTR => "ltr",
|
||||
Self::RTL => "rtl",
|
||||
Self::TTB => "ttb",
|
||||
Self::BTT => "btt",
|
||||
})
|
||||
impl Repr for Dir {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::LTR => "ltr".into(),
|
||||
Self::RTL => "rtl".into(),
|
||||
Self::TTB => "ttb".into(),
|
||||
Self::BTT => "btt".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use super::*;
|
||||
/// A length that is relative to the font size.
|
||||
///
|
||||
/// `1em` is the same as the font size.
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Em(Scalar);
|
||||
|
||||
impl Em {
|
||||
@ -68,9 +68,9 @@ impl Numeric for Em {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Em {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}em", self.get())
|
||||
impl Repr for Em {
|
||||
fn repr(&self) -> EcoString {
|
||||
format_float(self.get(), None, "em")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ use super::*;
|
||||
/// Left #h(1fr) Left-ish #h(2fr) Right
|
||||
/// ```
|
||||
#[ty(name = "fraction")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Fr(Scalar);
|
||||
|
||||
impl Fr {
|
||||
@ -63,9 +63,9 @@ impl Numeric for Fr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Fr {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}fr", round_2(self.get()))
|
||||
impl Repr for Fr {
|
||||
fn repr(&self) -> EcoString {
|
||||
format_float(self.get(), Some(2), "fr")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,14 @@
|
||||
use std::f64::consts::{FRAC_PI_2, PI, TAU};
|
||||
use std::f64::{EPSILON, NEG_INFINITY};
|
||||
use std::fmt::{self, Debug, Write};
|
||||
use std::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
|
||||
use typst_macros::{cast, func, scope, ty, Cast};
|
||||
use typst_syntax::{Span, Spanned};
|
||||
|
||||
use super::color::{Hsl, Hsv};
|
||||
use super::*;
|
||||
use crate::diag::{bail, error, SourceResult};
|
||||
use crate::eval::{array, Args, Array, Func, IntoValue};
|
||||
use crate::eval::{array, cast, func, scope, ty, Args, Array, Cast, Func, IntoValue};
|
||||
use crate::geom::{ColorSpace, Smart};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
|
||||
/// A color gradient.
|
||||
///
|
||||
@ -169,7 +166,7 @@ use crate::geom::{ColorSpace, Smart};
|
||||
/// )
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Gradient {
|
||||
Linear(Arc<LinearGradient>),
|
||||
}
|
||||
@ -531,16 +528,16 @@ impl Gradient {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Gradient {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl Repr for Gradient {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Linear(linear) => linear.fmt(f),
|
||||
Self::Linear(linear) => linear.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A gradient that interpolates between two colors along an axis.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct LinearGradient {
|
||||
/// The color stops of this gradient.
|
||||
pub stops: Vec<(Color, Ratio)>,
|
||||
@ -554,40 +551,50 @@ pub struct LinearGradient {
|
||||
pub anti_alias: bool,
|
||||
}
|
||||
|
||||
impl Debug for LinearGradient {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("gradient.linear(")?;
|
||||
impl Repr for LinearGradient {
|
||||
fn repr(&self) -> EcoString {
|
||||
let mut r = EcoString::from("gradient.linear(");
|
||||
|
||||
let angle = self.angle.to_rad().rem_euclid(TAU);
|
||||
if angle.abs() < EPSILON {
|
||||
// Default value, do nothing
|
||||
} else if (angle - FRAC_PI_2).abs() < EPSILON {
|
||||
f.write_str("dir: rtl, ")?;
|
||||
r.push_str("dir: rtl, ");
|
||||
} else if (angle - PI).abs() < EPSILON {
|
||||
f.write_str("dir: ttb, ")?;
|
||||
r.push_str("dir: ttb, ");
|
||||
} else if (angle - 3.0 * FRAC_PI_2).abs() < EPSILON {
|
||||
f.write_str("dir: btt, ")?;
|
||||
r.push_str("dir: btt, ");
|
||||
} else {
|
||||
write!(f, "angle: {:?}, ", self.angle)?;
|
||||
r.push_str("angle: ");
|
||||
r.push_str(&self.angle.repr());
|
||||
r.push_str(", ");
|
||||
}
|
||||
|
||||
if self.space != ColorSpace::Oklab {
|
||||
write!(f, "space: {:?}, ", self.space.into_value())?;
|
||||
r.push_str("space: ");
|
||||
r.push_str(&self.space.into_value().repr());
|
||||
r.push_str(", ");
|
||||
}
|
||||
|
||||
if self.relative.is_custom() {
|
||||
write!(f, "relative: {:?}, ", self.relative.into_value())?;
|
||||
r.push_str("relative: ");
|
||||
r.push_str(&self.relative.into_value().repr());
|
||||
r.push_str(", ");
|
||||
}
|
||||
|
||||
for (i, (color, offset)) in self.stops.iter().enumerate() {
|
||||
write!(f, "({color:?}, {offset:?})")?;
|
||||
|
||||
r.push('(');
|
||||
r.push_str(&color.repr());
|
||||
r.push_str(", ");
|
||||
r.push_str(&offset.repr());
|
||||
r.push(')');
|
||||
if i != self.stops.len() - 1 {
|
||||
f.write_str(", ")?;
|
||||
r.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
f.write_char(')')
|
||||
r.push(')');
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
use ecow::eco_format;
|
||||
|
||||
use super::*;
|
||||
use crate::diag::{At, Hint, SourceResult};
|
||||
use crate::syntax::Span;
|
||||
@ -33,7 +31,7 @@ use crate::syntax::Span;
|
||||
/// (that is, excluding the `em` component).
|
||||
/// - `em`: The amount of `em` units in this length, as a [float]($float).
|
||||
#[ty(scope)]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Length {
|
||||
/// The absolute part.
|
||||
pub abs: Abs,
|
||||
@ -75,7 +73,8 @@ impl Length {
|
||||
return Ok(());
|
||||
}
|
||||
Err(eco_format!(
|
||||
"cannot convert a length with non-zero em units (`{self:?}`) to {unit}"
|
||||
"cannot convert a length with non-zero em units (`{}`) to {unit}",
|
||||
self.repr()
|
||||
))
|
||||
.hint(eco_format!("use `length.abs.{unit}()` instead to ignore its em component"))
|
||||
.at(span)
|
||||
@ -127,12 +126,12 @@ impl Length {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Length {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Length {
|
||||
fn repr(&self) -> EcoString {
|
||||
match (self.abs.is_zero(), self.em.is_zero()) {
|
||||
(false, false) => write!(f, "{:?} + {:?}", self.abs, self.em),
|
||||
(true, false) => self.em.fmt(f),
|
||||
(_, true) => self.abs.fmt(f),
|
||||
(false, false) => eco_format!("{} + {}", self.abs.repr(), self.em.repr()),
|
||||
(true, false) => self.em.repr(),
|
||||
(_, true) => self.abs.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,9 +61,12 @@ use std::hash::{Hash, Hasher};
|
||||
use std::iter::Sum;
|
||||
use std::ops::*;
|
||||
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::eval::{array, cast, func, scope, ty, Array, Dict, Value};
|
||||
use crate::eval::{array, cast, func, scope, ty, Array, Dict, Repr, Value};
|
||||
use crate::model::{Fold, Resolve, StyleChain};
|
||||
use crate::util::fmt::format_float;
|
||||
|
||||
/// Generic access to a structure's components.
|
||||
pub trait Get<Index> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
/// How a fill or stroke should be painted.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum Paint {
|
||||
/// A solid color.
|
||||
Solid(Color),
|
||||
@ -32,11 +32,11 @@ impl From<Gradient> for Paint {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Paint {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Paint {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Solid(color) => color.fmt(f),
|
||||
Self::Gradient(gradient) => gradient.fmt(f),
|
||||
Self::Solid(color) => color.repr(),
|
||||
Self::Gradient(gradient) => gradient.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use super::*;
|
||||
/// ]
|
||||
/// ```
|
||||
#[ty]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Ratio(Scalar);
|
||||
|
||||
impl Ratio {
|
||||
@ -62,9 +62,9 @@ impl Ratio {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Ratio {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}%", round_2(100.0 * self.get()))
|
||||
impl Repr for Ratio {
|
||||
fn repr(&self) -> EcoString {
|
||||
format_float(self.get() * 100.0, Some(2), "%")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ use super::*;
|
||||
/// - `length`: Its length component.
|
||||
/// - `ratio`: Its ratio component.
|
||||
#[ty(name = "relative", title = "Relative Length")]
|
||||
#[derive(Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Rel<T: Numeric = Length> {
|
||||
/// The relative part.
|
||||
pub rel: Ratio,
|
||||
@ -80,12 +80,12 @@ impl Rel<Length> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Numeric> Debug for Rel<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl<T: Numeric + Repr> Repr for Rel<T> {
|
||||
fn repr(&self) -> EcoString {
|
||||
match (self.rel.is_zero(), self.abs.is_zero()) {
|
||||
(false, false) => write!(f, "{:?} + {:?}", self.rel, self.abs),
|
||||
(false, true) => self.rel.fmt(f),
|
||||
(true, _) => self.abs.fmt(f),
|
||||
(false, false) => eco_format!("{} + {}", self.rel.repr(), self.abs.repr()),
|
||||
(false, true) => self.rel.repr(),
|
||||
(true, _) => self.abs.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use super::*;
|
||||
/// A 64-bit float that implements `Eq`, `Ord` and `Hash`.
|
||||
///
|
||||
/// Panics if it's `NaN` during any of those operations.
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct Scalar(f64);
|
||||
|
||||
// We have to detect NaNs this way since `f64::is_nan` isn’t const
|
||||
@ -61,9 +61,9 @@ impl From<Scalar> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Scalar {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Debug::fmt(&self.0, f)
|
||||
impl Repr for Scalar {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.0.repr()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::eval::{CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
use super::*;
|
||||
use crate::eval::{CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
/// A container with left, top, right and bottom components.
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::eval::{AutoValue, CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
use super::*;
|
||||
use crate::eval::{AutoValue, CastInfo, FromValue, IntoValue, Reflect};
|
||||
|
||||
/// A value that can be automatically determined.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::eval::{dict, Cast, FromValue, NoneValue};
|
||||
|
||||
use super::*;
|
||||
use crate::eval::{dict, Cast, FromValue, NoneValue};
|
||||
|
||||
/// Defines how to draw a line.
|
||||
///
|
||||
@ -67,7 +66,7 @@ use super::*;
|
||||
/// dictionary format above. For example, `{(2pt + blue).thickness}` is `{2pt}`.
|
||||
/// Meanwhile, `{(2pt + blue).cap}` is `{auto}` because it's unspecified.
|
||||
#[ty]
|
||||
#[derive(Default, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Stroke<T: Numeric = Length> {
|
||||
/// The stroke's paint.
|
||||
pub paint: Smart<Paint>,
|
||||
@ -146,8 +145,9 @@ impl Stroke<Abs> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Numeric + Debug> Debug for Stroke<T> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl<T: Numeric + Repr> Repr for Stroke<T> {
|
||||
fn repr(&self) -> EcoString {
|
||||
let mut r = EcoString::new();
|
||||
let Self {
|
||||
paint,
|
||||
thickness,
|
||||
@ -163,46 +163,59 @@ impl<T: Numeric + Debug> Debug for Stroke<T> {
|
||||
{
|
||||
match (&self.paint, &self.thickness) {
|
||||
(Smart::Custom(paint), Smart::Custom(thickness)) => {
|
||||
write!(f, "{thickness:?} + {paint:?}")
|
||||
r.push_str(&thickness.repr());
|
||||
r.push_str(" + ");
|
||||
r.push_str(&paint.repr());
|
||||
}
|
||||
(Smart::Custom(paint), Smart::Auto) => paint.fmt(f),
|
||||
(Smart::Auto, Smart::Custom(thickness)) => thickness.fmt(f),
|
||||
(Smart::Auto, Smart::Auto) => f.pad("1pt + black"),
|
||||
(Smart::Custom(paint), Smart::Auto) => r.push_str(&paint.repr()),
|
||||
(Smart::Auto, Smart::Custom(thickness)) => r.push_str(&thickness.repr()),
|
||||
(Smart::Auto, Smart::Auto) => r.push_str("1pt + black"),
|
||||
}
|
||||
} else {
|
||||
write!(f, "(")?;
|
||||
r.push('(');
|
||||
let mut sep = "";
|
||||
if let Smart::Custom(paint) = &paint {
|
||||
write!(f, "{}paint: {:?}", sep, paint)?;
|
||||
r.push_str(sep);
|
||||
r.push_str("paint: ");
|
||||
r.push_str(&paint.repr());
|
||||
sep = ", ";
|
||||
}
|
||||
if let Smart::Custom(thickness) = &thickness {
|
||||
write!(f, "{}thickness: {:?}", sep, thickness)?;
|
||||
r.push_str(sep);
|
||||
r.push_str("thickness: ");
|
||||
r.push_str(&thickness.repr());
|
||||
sep = ", ";
|
||||
}
|
||||
if let Smart::Custom(cap) = &line_cap {
|
||||
write!(f, "{}cap: {:?}", sep, cap)?;
|
||||
r.push_str(sep);
|
||||
r.push_str("cap: ");
|
||||
r.push_str(&cap.repr());
|
||||
sep = ", ";
|
||||
}
|
||||
if let Smart::Custom(join) = &line_join {
|
||||
write!(f, "{}join: {:?}", sep, join)?;
|
||||
r.push_str(sep);
|
||||
r.push_str("join: ");
|
||||
r.push_str(&join.repr());
|
||||
sep = ", ";
|
||||
}
|
||||
if let Smart::Custom(dash) = &dash_pattern {
|
||||
write!(f, "{}dash: ", sep)?;
|
||||
r.push_str(sep);
|
||||
r.push_str("cap: ");
|
||||
if let Some(dash) = dash {
|
||||
Debug::fmt(dash, f)?;
|
||||
r.push_str(&dash.repr());
|
||||
} else {
|
||||
Debug::fmt(&NoneValue, f)?;
|
||||
r.push_str(&NoneValue.repr());
|
||||
}
|
||||
sep = ", ";
|
||||
}
|
||||
if let Smart::Custom(miter_limit) = &miter_limit {
|
||||
write!(f, "{}miter-limit: {:?}", sep, miter_limit)?;
|
||||
r.push_str(sep);
|
||||
r.push_str("miter-limit: ");
|
||||
r.push_str(&miter_limit.repr());
|
||||
}
|
||||
write!(f, ")")?;
|
||||
Ok(())
|
||||
r.push(')');
|
||||
}
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,43 +290,43 @@ cast! {
|
||||
}
|
||||
|
||||
/// The line cap of a stroke
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||
pub enum LineCap {
|
||||
Butt,
|
||||
Round,
|
||||
Square,
|
||||
}
|
||||
|
||||
impl Debug for LineCap {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for LineCap {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
LineCap::Butt => write!(f, "\"butt\""),
|
||||
LineCap::Round => write!(f, "\"round\""),
|
||||
LineCap::Square => write!(f, "\"square\""),
|
||||
Self::Butt => "butt".repr(),
|
||||
Self::Round => "round".repr(),
|
||||
Self::Square => "square".repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The line join of a stroke
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
|
||||
pub enum LineJoin {
|
||||
Miter,
|
||||
Round,
|
||||
Bevel,
|
||||
}
|
||||
|
||||
impl Debug for LineJoin {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for LineJoin {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
LineJoin::Miter => write!(f, "\"miter\""),
|
||||
LineJoin::Round => write!(f, "\"round\""),
|
||||
LineJoin::Bevel => write!(f, "\"bevel\""),
|
||||
Self::Miter => "miter".repr(),
|
||||
Self::Round => "round".repr(),
|
||||
Self::Bevel => "bevel".repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A line dash pattern.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct DashPattern<T: Numeric = Length, DT = DashLength<T>> {
|
||||
/// The dash array.
|
||||
pub array: Vec<DT>,
|
||||
@ -321,18 +334,19 @@ pub struct DashPattern<T: Numeric = Length, DT = DashLength<T>> {
|
||||
pub phase: T,
|
||||
}
|
||||
|
||||
impl<T: Numeric + Debug, DT: Debug> Debug for DashPattern<T, DT> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "(array: (")?;
|
||||
impl<T: Numeric + Repr, DT: Repr> Repr for DashPattern<T, DT> {
|
||||
fn repr(&self) -> EcoString {
|
||||
let mut r = EcoString::from("(array: (");
|
||||
for (i, elem) in self.array.iter().enumerate() {
|
||||
if i == 0 {
|
||||
write!(f, "{:?}", elem)?;
|
||||
} else {
|
||||
write!(f, ", {:?}", elem)?;
|
||||
if i != 0 {
|
||||
r.push_str(", ")
|
||||
}
|
||||
r.push_str(&elem.repr())
|
||||
}
|
||||
write!(f, "), phase: {:?})", self.phase)?;
|
||||
Ok(())
|
||||
r.push_str("), phase: ");
|
||||
r.push_str(&self.phase.repr());
|
||||
r.push(')');
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,7 +398,7 @@ cast! {
|
||||
}
|
||||
|
||||
/// The length of a dash in a line dash pattern.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum DashLength<T: Numeric = Length> {
|
||||
LineWidth,
|
||||
Length(T),
|
||||
@ -399,11 +413,11 @@ impl<T: Numeric> DashLength<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Numeric + Debug> Debug for DashLength<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
impl<T: Numeric + Repr> Repr for DashLength<T> {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::LineWidth => write!(f, "\"dot\""),
|
||||
Self::Length(v) => Debug::fmt(v, f),
|
||||
Self::LineWidth => "dot".repr(),
|
||||
Self::Length(v) => v.repr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::any::TypeId;
|
||||
use std::fmt::{self, Debug, Formatter, Write};
|
||||
use std::fmt::Debug;
|
||||
use std::iter::{self, Sum};
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
@ -13,7 +13,7 @@ use super::{
|
||||
};
|
||||
use crate::diag::{SourceResult, StrResult};
|
||||
use crate::doc::Meta;
|
||||
use crate::eval::{func, scope, ty, Dict, FromValue, IntoValue, Str, Value, Vm};
|
||||
use crate::eval::{func, scope, ty, Dict, FromValue, IntoValue, Repr, Str, Value, Vm};
|
||||
use crate::syntax::Span;
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
@ -61,7 +61,7 @@ use crate::util::pretty_array_like;
|
||||
/// elements the content is composed of and what fields they have.
|
||||
/// Alternatively, you can inspect the output of the [`repr`]($repr) function.
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, Hash)]
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Content {
|
||||
elem: Element,
|
||||
@ -528,30 +528,26 @@ impl Content {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Content {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Content {
|
||||
fn repr(&self) -> EcoString {
|
||||
let name = self.elem.name();
|
||||
if let Some(text) = item!(text_str)(self) {
|
||||
f.write_char('[')?;
|
||||
f.write_str(&text)?;
|
||||
f.write_char(']')?;
|
||||
return Ok(());
|
||||
return eco_format!("[{}]", text);
|
||||
} else if name == "space" {
|
||||
return f.write_str("[ ]");
|
||||
return ("[ ]").into();
|
||||
}
|
||||
|
||||
let mut pieces: Vec<_> = self
|
||||
.fields()
|
||||
.into_iter()
|
||||
.map(|(name, value)| eco_format!("{name}: {value:?}"))
|
||||
.map(|(name, value)| eco_format!("{}: {}", name, value.repr()))
|
||||
.collect();
|
||||
|
||||
if self.is::<StyledElem>() {
|
||||
pieces.push(EcoString::from(".."));
|
||||
}
|
||||
|
||||
f.write_str(name)?;
|
||||
f.write_str(&pretty_array_like(&pieces, false))
|
||||
eco_format!("{}{}", name, pretty_array_like(&pieces, false))
|
||||
}
|
||||
}
|
||||
|
||||
@ -696,15 +692,15 @@ pub trait PlainText {
|
||||
/// The missing field access error message.
|
||||
#[cold]
|
||||
fn missing_field(field: &str) -> EcoString {
|
||||
eco_format!("content does not contain field {:?}", Str::from(field))
|
||||
eco_format!("content does not contain field {}", field.repr())
|
||||
}
|
||||
|
||||
/// The missing field access error message when no default value was given.
|
||||
#[cold]
|
||||
fn missing_field_no_default(field: &str) -> EcoString {
|
||||
eco_format!(
|
||||
"content does not contain field {:?} and \
|
||||
"content does not contain field {} and \
|
||||
no default value was specified",
|
||||
Str::from(field)
|
||||
field.repr()
|
||||
)
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
use ecow::EcoString;
|
||||
use std::any::TypeId;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{Content, Selector, Styles};
|
||||
use crate::diag::SourceResult;
|
||||
use crate::eval::{cast, Args, Dict, Func, ParamInfo, Scope, Value, Vm};
|
||||
use crate::eval::{cast, Args, Dict, Func, ParamInfo, Repr, Scope, Value, Vm};
|
||||
use crate::util::Static;
|
||||
|
||||
/// A document element.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Element(Static<NativeElementData>);
|
||||
|
||||
impl Element {
|
||||
@ -93,9 +94,9 @@ impl Element {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Element {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad(self.name())
|
||||
impl Repr for Element {
|
||||
fn repr(&self) -> EcoString {
|
||||
self.name().into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,6 +151,7 @@ pub trait Set {
|
||||
}
|
||||
|
||||
/// Defines a native element.
|
||||
#[derive(Debug)]
|
||||
pub struct NativeElementData {
|
||||
pub name: &'static str,
|
||||
pub title: &'static str,
|
||||
|
@ -1,17 +1,17 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use comemo::{Prehashed, Track, Tracked, Validate};
|
||||
use ecow::EcoVec;
|
||||
use ecow::{EcoString, EcoVec};
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use super::{Content, Selector};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::doc::{Frame, FrameItem, Meta, Position};
|
||||
use crate::eval::{cast, func, scope, ty, Dict, Value, Vm};
|
||||
use crate::eval::{cast, func, scope, ty, Dict, Repr, Value, Vm};
|
||||
use crate::geom::{Point, Transform};
|
||||
use crate::model::Label;
|
||||
use crate::util::NonZeroExt;
|
||||
@ -24,7 +24,7 @@ use crate::util::NonZeroExt;
|
||||
/// or shown element with the [`location()`]($content.location) method on
|
||||
/// content.
|
||||
#[ty(scope)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct Location {
|
||||
/// The hash of the element.
|
||||
hash: u128,
|
||||
@ -83,9 +83,9 @@ impl Location {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Location {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("..")
|
||||
impl Repr for Location {
|
||||
fn repr(&self) -> EcoString {
|
||||
"..".into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use std::fmt::{self, Debug, Formatter};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use ecow::EcoString;
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::eval::{func, scope, ty};
|
||||
use crate::eval::{func, scope, ty, Repr};
|
||||
|
||||
/// A label for an element.
|
||||
///
|
||||
@ -23,7 +23,7 @@ use crate::eval::{func, scope, ty};
|
||||
/// 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.
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct Label(pub EcoString);
|
||||
|
||||
#[scope]
|
||||
@ -38,9 +38,9 @@ impl Label {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Label {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "<{}>", self.0)
|
||||
impl Repr for Label {
|
||||
fn repr(&self) -> EcoString {
|
||||
eco_format!("<{}>", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::fmt::{self, Debug, Formatter, Write};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ecow::{eco_format, EcoString, EcoVec};
|
||||
@ -7,8 +7,8 @@ use ecow::{eco_format, EcoString, EcoVec};
|
||||
use super::{Content, Element, Label, Locatable, Location};
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::eval::{
|
||||
cast, func, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Str, Symbol,
|
||||
Type, Value,
|
||||
cast, func, scope, ty, CastInfo, Dict, FromValue, Func, Reflect, Regex, Repr, Str,
|
||||
Symbol, Type, Value,
|
||||
};
|
||||
use crate::util::pretty_array_like;
|
||||
|
||||
@ -49,7 +49,7 @@ use crate::util::pretty_array_like;
|
||||
/// === But this will not.
|
||||
/// ```
|
||||
#[ty(scope)]
|
||||
#[derive(Clone, PartialEq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||
pub enum Selector {
|
||||
/// Matches a specific type of element.
|
||||
///
|
||||
@ -209,42 +209,37 @@ impl From<Location> for Selector {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Selector {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
impl Repr for Selector {
|
||||
fn repr(&self) -> EcoString {
|
||||
match self {
|
||||
Self::Elem(elem, dict) => {
|
||||
f.write_str(elem.name())?;
|
||||
if let Some(dict) = dict {
|
||||
f.write_str(".where")?;
|
||||
dict.fmt(f)?;
|
||||
eco_format!("{}.where{}", elem.name(), dict.repr())
|
||||
} else {
|
||||
elem.name().into()
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Self::Label(label) => label.fmt(f),
|
||||
Self::Regex(regex) => regex.fmt(f),
|
||||
Self::Can(cap) => cap.fmt(f),
|
||||
Self::Label(label) => label.repr(),
|
||||
Self::Regex(regex) => regex.repr(),
|
||||
Self::Can(cap) => eco_format!("{cap:?}"),
|
||||
Self::Or(selectors) | Self::And(selectors) => {
|
||||
f.write_str(if matches!(self, Self::Or(_)) { "or" } else { "and" })?;
|
||||
let pieces: Vec<_> =
|
||||
selectors.iter().map(|sel| eco_format!("{sel:?}")).collect();
|
||||
f.write_str(&pretty_array_like(&pieces, false))
|
||||
let function = if matches!(self, Self::Or(_)) { "or" } else { "and" };
|
||||
let pieces: Vec<_> = selectors.iter().map(Selector::repr).collect();
|
||||
eco_format!("{}{}", function, pretty_array_like(&pieces, false))
|
||||
}
|
||||
Self::Location(loc) => loc.fmt(f),
|
||||
Self::Location(loc) => loc.repr(),
|
||||
Self::Before { selector, end: split, inclusive }
|
||||
| Self::After { selector, start: split, inclusive } => {
|
||||
selector.fmt(f)?;
|
||||
|
||||
if matches!(self, Self::Before { .. }) {
|
||||
f.write_str(".before(")?;
|
||||
} else {
|
||||
f.write_str(".after(")?;
|
||||
}
|
||||
|
||||
split.fmt(f)?;
|
||||
if !*inclusive {
|
||||
f.write_str(", inclusive: false")?;
|
||||
}
|
||||
f.write_char(')')
|
||||
let method =
|
||||
if matches!(self, Self::Before { .. }) { "before" } else { "after" };
|
||||
let inclusive_arg = if !*inclusive { ", inclusive: false" } else { "" };
|
||||
eco_format!(
|
||||
"{}.{}({}{})",
|
||||
selector.repr(),
|
||||
method,
|
||||
split.repr(),
|
||||
inclusive_arg
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ use ecow::{eco_vec, EcoString, EcoVec};
|
||||
|
||||
use super::{Content, Element, NativeElement, Selector, Vt};
|
||||
use crate::diag::{SourceResult, Trace, Tracepoint};
|
||||
use crate::eval::{cast, ty, Args, FromValue, Func, IntoValue, Value, Vm};
|
||||
use crate::eval::{cast, ty, Args, FromValue, Func, IntoValue, Repr, Value, Vm};
|
||||
use crate::syntax::Span;
|
||||
|
||||
/// A list of style properties.
|
||||
#[ty]
|
||||
#[derive(Default, PartialEq, Clone, Hash)]
|
||||
#[derive(Debug, Default, PartialEq, Clone, Hash)]
|
||||
pub struct Styles(EcoVec<Prehashed<Style>>);
|
||||
|
||||
impl Styles {
|
||||
@ -86,9 +86,9 @@ impl From<Style> for Styles {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Styles {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.pad("..")
|
||||
impl Repr for Styles {
|
||||
fn repr(&self) -> EcoString {
|
||||
"..".into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,54 @@
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
/// Format an integer in a base.
|
||||
pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
||||
if n == 0 {
|
||||
return "0".into();
|
||||
}
|
||||
|
||||
// In Rust, `format!("{:x}", -14i64)` is not `-e` but `fffffffffffffff2`.
|
||||
// So we can only use the built-in for decimal, not bin/oct/hex.
|
||||
if base == 10 {
|
||||
return eco_format!("{n}");
|
||||
}
|
||||
|
||||
// The largest output is `to_base(i64::MIN, 2)`, which is 65 chars long.
|
||||
const SIZE: usize = 65;
|
||||
let mut digits = [b'\0'; SIZE];
|
||||
let mut i = SIZE;
|
||||
|
||||
// It's tempting to take the absolute value, but this will fail for i64::MIN.
|
||||
// Instead, we turn n negative, as -i64::MAX is perfectly representable.
|
||||
let negative = n < 0;
|
||||
if n > 0 {
|
||||
n = -n;
|
||||
}
|
||||
|
||||
while n != 0 {
|
||||
let digit = char::from_digit(-(n % base) as u32, base as u32);
|
||||
i -= 1;
|
||||
digits[i] = digit.unwrap_or('?') as u8;
|
||||
n /= base;
|
||||
}
|
||||
|
||||
if negative {
|
||||
i -= 1;
|
||||
digits[i] = b'-';
|
||||
}
|
||||
|
||||
std::str::from_utf8(&digits[i..]).unwrap_or_default().into()
|
||||
}
|
||||
|
||||
/// Converts a float to a string representation with a specific precision and a
|
||||
/// suffix, all with a single allocation.
|
||||
pub fn format_float(mut value: f64, precision: Option<u8>, suffix: &str) -> EcoString {
|
||||
if let Some(p) = precision {
|
||||
let offset = 10_f64.powi(p as i32);
|
||||
value = (value * offset).round() / offset;
|
||||
}
|
||||
eco_format!("{}{}", value, suffix)
|
||||
}
|
||||
|
||||
/// Format pieces separated with commas and a final "and" or "or".
|
||||
pub fn separated_list(pieces: &[impl AsRef<str>], last: &str) -> String {
|
||||
let mut buf = String::new();
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Utilities.
|
||||
|
||||
pub mod fat;
|
||||
mod fmt;
|
||||
pub mod fmt;
|
||||
|
||||
pub use self::fmt::{pretty_array_like, pretty_comma_list, separated_list};
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 53 KiB |
@ -22,7 +22,9 @@ use walkdir::WalkDir;
|
||||
|
||||
use typst::diag::{bail, FileError, FileResult, Severity, StrResult};
|
||||
use typst::doc::{Document, Frame, FrameItem, Meta};
|
||||
use typst::eval::{eco_format, func, Bytes, Datetime, Library, NoneValue, Tracer, Value};
|
||||
use typst::eval::{
|
||||
eco_format, func, Bytes, Datetime, Library, NoneValue, Repr, Tracer, Value,
|
||||
};
|
||||
use typst::font::{Font, FontBook};
|
||||
use typst::geom::{Abs, Color, Smart};
|
||||
use typst::syntax::{FileId, PackageVersion, Source, SyntaxNode, VirtualPath};
|
||||
@ -154,7 +156,7 @@ fn library() -> Library {
|
||||
#[func]
|
||||
fn test(lhs: Value, rhs: Value) -> StrResult<NoneValue> {
|
||||
if lhs != rhs {
|
||||
bail!("Assertion failed: {lhs:?} != {rhs:?}");
|
||||
bail!("Assertion failed: {} != {}", lhs.repr(), rhs.repr());
|
||||
}
|
||||
Ok(NoneValue)
|
||||
}
|
||||
@ -162,7 +164,7 @@ fn library() -> Library {
|
||||
#[func]
|
||||
fn test_repr(lhs: Value, rhs: Value) -> StrResult<NoneValue> {
|
||||
if lhs.repr() != rhs.repr() {
|
||||
bail!("Assertion failed: {lhs:?} != {rhs:?}");
|
||||
bail!("Assertion failed: {} != {}", lhs.repr(), rhs.repr());
|
||||
}
|
||||
Ok(NoneValue)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user