Split shorthands into math and markup, add tilde shorthand (#4706)

This commit is contained in:
Max 2024-08-09 07:41:01 +00:00 committed by GitHub
parent a6a8cdaa28
commit b07607d35e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 127 additions and 86 deletions

View File

@ -125,6 +125,8 @@ pub enum Expr<'a> {
Math(Math<'a>),
/// An identifier in math: `pi`.
MathIdent(MathIdent<'a>),
/// A shorthand for a unicode codepoint in math: `a <= b`.
MathShorthand(MathShorthand<'a>),
/// An alignment point in math: `&`.
MathAlignPoint(MathAlignPoint<'a>),
/// Matched delimiters in math: `[x + y]`.
@ -232,6 +234,7 @@ impl<'a> AstNode<'a> for Expr<'a> {
SyntaxKind::Equation => node.cast().map(Self::Equation),
SyntaxKind::Math => node.cast().map(Self::Math),
SyntaxKind::MathIdent => node.cast().map(Self::MathIdent),
SyntaxKind::MathShorthand => node.cast().map(Self::MathShorthand),
SyntaxKind::MathAlignPoint => node.cast().map(Self::MathAlignPoint),
SyntaxKind::MathDelimited => node.cast().map(Self::MathDelimited),
SyntaxKind::MathAttach => node.cast().map(Self::MathAttach),
@ -295,6 +298,7 @@ impl<'a> AstNode<'a> for Expr<'a> {
Self::Equation(v) => v.to_untyped(),
Self::Math(v) => v.to_untyped(),
Self::MathIdent(v) => v.to_untyped(),
Self::MathShorthand(v) => v.to_untyped(),
Self::MathAlignPoint(v) => v.to_untyped(),
Self::MathDelimited(v) => v.to_untyped(),
Self::MathAttach(v) => v.to_untyped(),
@ -450,7 +454,7 @@ node! {
impl Shorthand<'_> {
/// A list of all shorthands in markup mode.
pub const MARKUP_LIST: &'static [(&'static str, char)] = &[
pub const LIST: &'static [(&'static str, char)] = &[
("...", '…'),
("~", '\u{00A0}'),
("-", '\u{2212}'), // Only before a digit
@ -459,52 +463,11 @@ impl Shorthand<'_> {
("-?", '\u{00AD}'),
];
/// A list of all shorthands in math mode.
pub const MATH_LIST: &'static [(&'static str, char)] = &[
("...", '…'),
("-", '\u{2212}'),
("'", ''),
("*", ''),
("!=", '≠'),
(":=", '≔'),
("::=", '⩴'),
("=:", '≕'),
("<<", '≪'),
("<<<", '⋘'),
(">>", '≫'),
(">>>", '⋙'),
("<=", '≤'),
(">=", '≥'),
("->", '→'),
("-->", '⟶'),
("|->", '↦'),
(">->", '↣'),
("->>", '↠'),
("<-", '←'),
("<--", '⟵'),
("<-<", '↢'),
("<<-", '↞'),
("<->", '↔'),
("<-->", '⟷'),
("~>", '⇝'),
("~~>", '⟿'),
("<~", '⇜'),
("<~~", '⬳'),
("=>", '⇒'),
("|=>", '⤇'),
("==>", '⟹'),
("<==", '⟸'),
("<=>", '⇔'),
("<==>", '⟺'),
("[|", '⟦'),
("|]", '⟧'),
("||", '‖'),
];
/// Get the shorthanded character.
pub fn get(self) -> char {
let text = self.0.text();
(Self::MARKUP_LIST.iter().chain(Self::MATH_LIST))
Self::LIST
.iter()
.find(|&&(s, _)| s == text)
.map_or_else(char::default, |&(_, c)| c)
}
@ -770,6 +733,65 @@ impl Deref for MathIdent<'_> {
}
}
node! {
/// A shorthand for a unicode codepoint in math: `a <= b`.
MathShorthand
}
impl MathShorthand<'_> {
/// A list of all shorthands in math mode.
pub const LIST: &'static [(&'static str, char)] = &[
("...", '…'),
("-", ''),
("'", ''),
("*", ''),
("~", ''),
("!=", '≠'),
(":=", '≔'),
("::=", '⩴'),
("=:", '≕'),
("<<", '≪'),
("<<<", '⋘'),
(">>", '≫'),
(">>>", '⋙'),
("<=", '≤'),
(">=", '≥'),
("->", '→'),
("-->", '⟶'),
("|->", '↦'),
(">->", '↣'),
("->>", '↠'),
("<-", '←'),
("<--", '⟵'),
("<-<", '↢'),
("<<-", '↞'),
("<->", '↔'),
("<-->", '⟷'),
("~>", '⇝'),
("~~>", '⟿'),
("<~", '⇜'),
("<~~", '⬳'),
("=>", '⇒'),
("|=>", '⤇'),
("==>", '⟹'),
("<==", '⟸'),
("<=>", '⇔'),
("<==>", '⟺'),
("[|", '⟦'),
("|]", '⟧'),
("||", '‖'),
];
/// Get the shorthanded character.
pub fn get(self) -> char {
let text = self.0.text();
Self::LIST
.iter()
.find(|&&(s, _)| s == text)
.map_or_else(char::default, |&(_, c)| c)
}
}
node! {
/// An alignment point in math: `&`.
MathAlignPoint

View File

@ -172,6 +172,7 @@ pub fn highlight(node: &LinkedNode) -> Option<Tag> {
SyntaxKind::Math => None,
SyntaxKind::MathIdent => highlight_ident(node),
SyntaxKind::MathShorthand => Some(Tag::Escape),
SyntaxKind::MathAlignPoint => Some(Tag::MathOperator),
SyntaxKind::MathDelimited => None,
SyntaxKind::MathAttach => None,

View File

@ -75,6 +75,8 @@ pub enum SyntaxKind {
Math,
/// An identifier in math: `pi`.
MathIdent,
/// A shorthand for a unicode codepoint in math: `a <= b`.
MathShorthand,
/// An alignment point in math: `&`.
MathAlignPoint,
/// Matched delimiters in math: `[x + y]`.
@ -400,6 +402,7 @@ impl SyntaxKind {
Self::Equation => "equation",
Self::Math => "math",
Self::MathIdent => "math identifier",
Self::MathShorthand => "math shorthand",
Self::MathAlignPoint => "math alignment point",
Self::MathDelimited => "delimited math",
Self::MathAttach => "math attachments",

View File

@ -514,42 +514,42 @@ impl Lexer<'_> {
'\\' => self.backslash(),
'"' => self.string(),
'-' if self.s.eat_if(">>") => SyntaxKind::Shorthand,
'-' if self.s.eat_if('>') => SyntaxKind::Shorthand,
'-' if self.s.eat_if("->") => SyntaxKind::Shorthand,
':' if self.s.eat_if('=') => SyntaxKind::Shorthand,
':' if self.s.eat_if(":=") => SyntaxKind::Shorthand,
'!' if self.s.eat_if('=') => SyntaxKind::Shorthand,
'.' if self.s.eat_if("..") => SyntaxKind::Shorthand,
'[' if self.s.eat_if('|') => SyntaxKind::Shorthand,
'<' if self.s.eat_if("==>") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("-->") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("--") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("-<") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("->") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("<-") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("<<") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("=>") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("==") => SyntaxKind::Shorthand,
'<' if self.s.eat_if("~~") => SyntaxKind::Shorthand,
'<' if self.s.eat_if('=') => SyntaxKind::Shorthand,
'<' if self.s.eat_if('<') => SyntaxKind::Shorthand,
'<' if self.s.eat_if('-') => SyntaxKind::Shorthand,
'<' if self.s.eat_if('~') => SyntaxKind::Shorthand,
'>' if self.s.eat_if("->") => SyntaxKind::Shorthand,
'>' if self.s.eat_if(">>") => SyntaxKind::Shorthand,
'=' if self.s.eat_if("=>") => SyntaxKind::Shorthand,
'=' if self.s.eat_if('>') => SyntaxKind::Shorthand,
'=' if self.s.eat_if(':') => SyntaxKind::Shorthand,
'>' if self.s.eat_if('=') => SyntaxKind::Shorthand,
'>' if self.s.eat_if('>') => SyntaxKind::Shorthand,
'|' if self.s.eat_if("->") => SyntaxKind::Shorthand,
'|' if self.s.eat_if("=>") => SyntaxKind::Shorthand,
'|' if self.s.eat_if(']') => SyntaxKind::Shorthand,
'|' if self.s.eat_if('|') => SyntaxKind::Shorthand,
'~' if self.s.eat_if("~>") => SyntaxKind::Shorthand,
'~' if self.s.eat_if('>') => SyntaxKind::Shorthand,
'*' | '-' => SyntaxKind::Shorthand,
'-' if self.s.eat_if(">>") => SyntaxKind::MathShorthand,
'-' if self.s.eat_if('>') => SyntaxKind::MathShorthand,
'-' if self.s.eat_if("->") => SyntaxKind::MathShorthand,
':' if self.s.eat_if('=') => SyntaxKind::MathShorthand,
':' if self.s.eat_if(":=") => SyntaxKind::MathShorthand,
'!' if self.s.eat_if('=') => SyntaxKind::MathShorthand,
'.' if self.s.eat_if("..") => SyntaxKind::MathShorthand,
'[' if self.s.eat_if('|') => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("==>") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("-->") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("--") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("-<") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("->") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("<-") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("<<") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("=>") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("==") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if("~~") => SyntaxKind::MathShorthand,
'<' if self.s.eat_if('=') => SyntaxKind::MathShorthand,
'<' if self.s.eat_if('<') => SyntaxKind::MathShorthand,
'<' if self.s.eat_if('-') => SyntaxKind::MathShorthand,
'<' if self.s.eat_if('~') => SyntaxKind::MathShorthand,
'>' if self.s.eat_if("->") => SyntaxKind::MathShorthand,
'>' if self.s.eat_if(">>") => SyntaxKind::MathShorthand,
'=' if self.s.eat_if("=>") => SyntaxKind::MathShorthand,
'=' if self.s.eat_if('>') => SyntaxKind::MathShorthand,
'=' if self.s.eat_if(':') => SyntaxKind::MathShorthand,
'>' if self.s.eat_if('=') => SyntaxKind::MathShorthand,
'>' if self.s.eat_if('>') => SyntaxKind::MathShorthand,
'|' if self.s.eat_if("->") => SyntaxKind::MathShorthand,
'|' if self.s.eat_if("=>") => SyntaxKind::MathShorthand,
'|' if self.s.eat_if(']') => SyntaxKind::MathShorthand,
'|' if self.s.eat_if('|') => SyntaxKind::MathShorthand,
'~' if self.s.eat_if("~>") => SyntaxKind::MathShorthand,
'~' if self.s.eat_if('>') => SyntaxKind::MathShorthand,
'*' | '-' | '~' => SyntaxKind::MathShorthand,
'#' => SyntaxKind::Hash,
'_' => SyntaxKind::Underscore,

View File

@ -319,7 +319,7 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
}
}
SyntaxKind::Text | SyntaxKind::Shorthand => {
SyntaxKind::Text | SyntaxKind::MathShorthand => {
continuable = matches!(
math_class(p.current_text()),
None | Some(MathClass::Alphabetic)

View File

@ -80,7 +80,7 @@ pub const MATH_EXPR: SyntaxSet = SyntaxSet::new()
.add(SyntaxKind::Hash)
.add(SyntaxKind::MathIdent)
.add(SyntaxKind::Text)
.add(SyntaxKind::Shorthand)
.add(SyntaxKind::MathShorthand)
.add(SyntaxKind::Linebreak)
.add(SyntaxKind::MathAlignPoint)
.add(SyntaxKind::Escape)

View File

@ -95,6 +95,7 @@ impl Eval for ast::Expr<'_> {
Self::Equation(v) => v.eval(vm).map(Value::Content),
Self::Math(v) => v.eval(vm).map(Value::Content),
Self::MathIdent(v) => v.eval(vm),
Self::MathShorthand(v) => v.eval(vm),
Self::MathAlignPoint(v) => v.eval(vm).map(Value::Content),
Self::MathDelimited(v) => v.eval(vm).map(Value::Content),
Self::MathAttach(v) => v.eval(vm).map(Value::Content),

View File

@ -4,6 +4,7 @@ use crate::diag::{At, SourceResult};
use crate::eval::{Eval, Vm};
use crate::foundations::{Content, NativeElement, Value};
use crate::math::{AlignPointElem, AttachElem, FracElem, LrElem, PrimesElem, RootElem};
use crate::symbols::Symbol;
use crate::syntax::ast::{self, AstNode};
use crate::text::TextElem;
@ -26,6 +27,14 @@ impl Eval for ast::MathIdent<'_> {
}
}
impl Eval for ast::MathShorthand<'_> {
type Output = Value;
fn eval(self, _: &mut Vm) -> SourceResult<Self::Output> {
Ok(Value::Symbol(Symbol::single(self.get().into())))
}
}
impl Eval for ast::MathAlignPoint<'_> {
type Output = Content;

View File

@ -664,8 +664,8 @@ fn symbols_model(resolver: &dyn Resolver, group: &GroupData) -> SymbolsModel {
list.push(SymbolModel {
name: complete(variant),
markup_shorthand: shorthand(typst::syntax::ast::Shorthand::MARKUP_LIST),
math_shorthand: shorthand(typst::syntax::ast::Shorthand::MATH_LIST),
markup_shorthand: shorthand(typst::syntax::ast::Shorthand::LIST),
math_shorthand: shorthand(typst::syntax::ast::MathShorthand::LIST),
codepoint: c.char() as _,
accent: typst::math::Accent::combine(c.char()).is_some(),
alternates: symbol

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -8,7 +8,7 @@ $ a class("normal", +) b \
{ x class("fence", \;) x > 0} \
a class("large", \/) b \
a class("punctuation", :) b \
a class("relation", ~) b \
a class("relation", !) b \
a + class("unary", times) b \
class("vary", :) a class("vary", :) b $

View File

@ -19,12 +19,17 @@ a~b
#set text(font: "Roboto")
A... vs #"A..."
--- shorthand-minus ---
// Make sure shorthand is applied only before a digit.
-a -1
--- shorthands-math ---
// Check all math shorthands
// Check all math shorthands.
$...$\
$-$\
$'$\
$*$\
$~$\
$!=$\
$:=$\
$::=$\