= Typst Prism
- Repository: https://github.com/Mc-Zen/prism-typst
- Prism: https://prismjs.com/
== Distinguishing markup and code mode
Distinguishing between *markup* and *code* mode (not
to forget _math_) is not as easy as one would think.
#[
Especially since they can be
#{
"nested"
[
_and nested_
#{
"and even more"
[
*nested*.
]
}
]
}
]
Basically, Typst code consists of three languages. And
you can go from each language to each other language
by using all kinds of
#let parentheses = ("()", "[]", "{}")
In order to parse the code properly, we need to do
_balanced matching_ for these #parentheses. The problem
is that #regex() is not good at doing recursive things.
This is why the recursion depth is _*limited*_.
== Code mode
After we enter code mode, which is quite tricky as we
saw in section @section1, syntax highlighting looks
quite different.
There are
#{
let lengths = (1pt, 1fr, -2, 1em, 3deg, 0in, 9cm, 0rad, 100%, 1mm)
[and]
let numbers = (1.2, 2e9, -3.0003e99, 0xFF, 0b100201, 0o337, )
}
When in markup mode, certain keywords change the
context to code mode for the entire line
#import "@preview/conchord:0.2.0" as con
#import emoji: face
#let x = range(0, 10)
Test some important cases
We have #emoji.wave and #data.rev()
#if true == true [
*yes*
] else [ // this is a bug but it's tough to fix
noe
]
#let my-func(a: 1pt, b, c) = {
if true {
return false
}
return $ a + b $
}
#show heading: it => {
it * 2
}
#show math.equation.where(block: true): it => {}
#show math.equation: it => {}
#show: template
#show : template
#set text(..) if a == b
if k==l // obviously no code
== Markup mode
All escaped symbols, like \@, \{, \} etc. are noticed!
The same holds for line/equation breaks \
#set text(2em, red)
#show math.equation(numbering: "(1)")
#hide[_hidden_]
#table(
columns: (auto, auto, 1fr),
$A$, $B$, $C$,
// note: here lurks a recursion limit for () pairs
..range(20).map(i => str(2*(i+1)))
)
An example from the Typst documentation
$ A = pi r^2 $
$ "area" = pi dot "radius"^2 $
$ cal(A) :=
{ x in RR | x "is natural" } $
#let x = 5
$ #x < 17 qt.eq gt.e $ // single-character symbols are not recognized
- a
- b ~ a --- as \u{1f600} \$1.50! \u{1f600}
`asd`
```typ
raw text // asd ) #{asd + 3}
```
// hard to detect then end of a context expression with regex:
#context locate().position()
#dictionary(sys).at("version")
$
[| |] || := ::= ... =: != >> >= >>> << <= <<<
-> |-> => |=> ==> --> ~~> ~> >-> ->> <- <==
<-- <~~ <~ <-< <<- <-> <=> <==> <-->/
$
#"text"
#while n < 10 {
n = (n * 2) - 1
(n,)
}
#{
#k[]
}
#let func() ={
v(2cm)
pad(x: 8%)[
#abstract
]
pagebreak[2pt]
}
#(23+
23)
#let p = ("a", "k")
#(21)
#let p = ("a", "k")
21
#let pd = "a"
12
== Equations
$
c^2 &= a^2 + b^2 \
c &= plus.minus sqrt(a^2 + b^2)
$
#[
$ a + x + b $
$ a + #place([]) x + #b $
]
Switching to content mode within equations is currently
not supported: $#box[*2*]$
== Modes and comments
Due to matching rules, it is tricky to get comments and
switched language modes to work. Let's check some cases
#{
// We have entered code mode
let verification = "Is this parsed as code?"
table(
columns: 2, // we're still in code mode, the "2" is an int
)
let /*really bad practice*/ x = 2pt
[
// Back in markup mode
#hide()
let // <- not a keyword
]
[/**/ #hide[]]
}
#table(
columns: 2, // we're now in code mode, the "2" is an int
)
#let url = "https://another.edge/case" // sometimes "tricky"
This is not simplified
\#show heading:
#asd()