Skip to content

Commit a70cc0e

Browse files
committed
More work on typst formatter.
1 parent b5105ed commit a70cc0e

File tree

4 files changed

+130
-115
lines changed

4 files changed

+130
-115
lines changed

skylighting-format-typst/src/Skylighting/Format/Typst.hs

+108-115
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ module Skylighting.Format.Typst (
88
) where
99

1010
import Control.Monad (mplus)
11-
import Data.Char (isSpace)
1211
import Data.List (sort)
1312
import qualified Data.Map as Map
1413
import Data.Text (Text)
@@ -19,134 +18,128 @@ import Text.Printf
1918
import Data.Semigroup
2019
#endif
2120

22-
formatTypst :: Bool -> [SourceLine] -> Text
23-
formatTypst inline = Text.intercalate (Text.singleton '\n')
24-
. map (sourceLineToTypst inline)
25-
2621
-- | Formats tokens as Typst using custom commands inside
2722
-- @|@ characters. Assumes that @|@ is defined as a short verbatim
2823
-- command by the macros produced by 'styleToTypst'.
2924
-- A @KeywordTok@ is rendered using @\\KeywordTok{..}@, and so on.
3025
formatTypstInline :: FormatOptions -> [SourceLine] -> Text
31-
formatTypstInline _opts ls = "\\VERB|" <> formatTypst True ls <> "|"
32-
33-
sourceLineToTypst :: Bool -> SourceLine -> Text
34-
sourceLineToTypst inline = mconcat . map (tokenToTypst inline)
35-
36-
tokenToTypst :: Bool -> Token -> Text
37-
tokenToTypst inline (NormalTok, txt)
38-
| Text.all isSpace txt = escapeTypst inline txt
39-
tokenToTypst inline (toktype, txt) = Text.cons '\\'
40-
(Text.pack (show toktype) <> "{" <> escapeTypst inline txt <> "}")
41-
42-
escapeTypst :: Bool -> Text -> Text
43-
escapeTypst inline = Text.concatMap escapeTypstChar
44-
where escapeTypstChar c =
45-
case c of
46-
'\\' -> "\\textbackslash{}"
47-
'{' -> "\\{"
48-
'}' -> "\\}"
49-
'|' | inline -> "\\VerbBar{}" -- used in inline verbatim
50-
'_' -> "\\_"
51-
'&' -> "\\&"
52-
'%' -> "\\%"
53-
'#' -> "\\#"
54-
'`' -> "\\textasciigrave{}"
55-
'\'' -> "\\textquotesingle{}"
56-
'-' -> "{-}" -- prevent ligatures
57-
'~' -> "\\textasciitilde{}"
58-
'^' -> "\\^{}"
59-
'>' -> "\\textgreater{}"
60-
'<' -> "\\textless{}"
61-
_ -> Text.singleton c
26+
formatTypstInline _opts = Text.intercalate newline . map sourceLineToTypst
27+
28+
newline :: Text
29+
newline = "#EndLine()\n"
30+
31+
sourceLineToTypst :: SourceLine -> Text
32+
sourceLineToTypst = mconcat . map tokenToTypst
33+
34+
tokenToTypst :: Token -> Text
35+
tokenToTypst (toktype, txt) =
36+
"#" <> Text.pack (show toktype) <> "(" <> doubleQuoted txt <> ");"
37+
38+
doubleQuoted :: Text -> Text
39+
doubleQuoted t = "\"" <> escape t <> "\""
40+
where
41+
escape = Text.concatMap escapeChar
42+
escapeChar '\\' = "\\\\"
43+
escapeChar '"' = "\\\""
44+
escapeChar c = Text.singleton c
6245

6346
-- Typst
6447

6548
-- | Format tokens as a Typst @Highlighting@ environment inside a
66-
-- @Shaded@ environment. @Highlighting@ and @Shaded@ are
67-
-- defined by the macros produced by 'styleToTypst'. @Highlighting@
68-
-- is a verbatim environment using @fancyvrb@; @\\@, @{@, and @}@
69-
-- have their normal meanings inside this environment, so that
70-
-- formatting commands work. @Shaded@ is either nothing
71-
-- (if the style's background color is default) or a @snugshade@
72-
-- environment from @framed@, providing a background color
73-
-- for the whole code block, even if it spans multiple pages.
49+
-- Skylighting block that can be styled. @Skylighting@ is
50+
-- defined by the macros produced by 'styleToTypst'.
7451
formatTypstBlock :: FormatOptions -> [SourceLine] -> Text
75-
formatTypstBlock opts ls = Text.unlines
76-
["\\begin{Shaded}"
77-
,"\\begin{Highlighting}[" <>
78-
(if numberLines opts
79-
then "numbers=left," <>
80-
(if startNumber opts == 1
81-
then ""
82-
else ",firstnumber=" <>
83-
Text.pack (show (startNumber opts))) <> ","
84-
else Text.empty) <> "]"
85-
,formatTypst False ls
86-
,"\\end{Highlighting}"
87-
,"\\end{Shaded}"]
52+
formatTypstBlock opts ls =
53+
"#Skylighting(" <>
54+
(if numberLines opts
55+
then "number: true, start: " <> Text.pack (show (startNumber opts)) <> ")"
56+
else ")") <>
57+
"[" <> formatTypstInline opts ls <> "];"
8858

8959
-- | Converts a 'Style' to a set of Typst macro definitions,
9060
-- which should be placed in the document's preamble.
91-
-- Note: default Typst setup doesn't allow boldface typewriter font.
92-
-- To make boldface work in styles, you need to use a different typewriter
93-
-- font. This will work for computer modern:
94-
--
95-
-- > \DeclareFontShape{OT1}{cmtt}{bx}{n}{<5><6><7><8><9><10><10.95><12><14.4><17.28><20.74><24.88>cmttb10}{}
96-
--
97-
-- Or, with xelatex:
98-
--
99-
-- > \usepackage{fontspec}
100-
-- > \setmainfont[SmallCapsFont={* Caps}]{Latin Modern Roman}
101-
-- > \setsansfont{Latin Modern Sans}
102-
-- > \setmonofont[SmallCapsFont={Latin Modern Mono Caps}]{Latin Modern Mono Light}
103-
--
10461
styleToTypst :: Style -> Text
105-
styleToTypst f = Text.unlines $
106-
[ "\\usepackage{color}"
107-
, "\\usepackage{fancyvrb}"
108-
, "\\newcommand{\\VerbBar}{|}"
109-
, "\\newcommand{\\VERB}{\\Verb[commandchars=\\\\\\{\\}]}"
110-
, "\\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\\\\{\\}}"
111-
, "% Add ',fontsize=\\small' for more characters per line"
112-
] ++
113-
(case backgroundColor f of
114-
Nothing -> ["\\newenvironment{Shaded}{}{}"]
115-
Just (RGB r g b) -> ["\\usepackage{framed}"
116-
,Text.pack
117-
(printf "\\definecolor{shadecolor}{RGB}{%d,%d,%d}" r g b)
118-
,"\\newenvironment{Shaded}{\\begin{snugshade}}{\\end{snugshade}}"])
119-
++ sort (map (macrodef (defaultColor f) (Map.toList (tokenStyles f)))
120-
(enumFromTo KeywordTok NormalTok))
62+
styleToTypst f = "TODO"
63+
64+
65+
-- #let Skylighting(body, number: false, start: 1) = body
66+
-- #let EndLine() = raw("\n")
67+
--
68+
-- #let KeywordTok(s) = raw(s)
69+
-- #let DataTypeTok(s) = raw(s)
70+
-- #let DecValTok(s) = raw(s)
71+
-- #let BaseNTok(s) = raw(s)
72+
-- #let FloatTok(s) = raw(s)
73+
-- #let ConstantTok(s) = raw(s)
74+
-- #let CharTok(s) = raw(s)
75+
-- #let SpecialCharTok(s) = raw(s)
76+
-- #let StringTok(s) = raw(s)
77+
-- #let VerbatimStringTok(s) = raw(s)
78+
-- #let SpecialStringTok(s) = raw(s)
79+
-- #let ImportTok(s) = raw(s)
80+
-- #let CommentTok(s) = raw(s)
81+
-- #let DocumentationTok(s) = raw(s)
82+
-- #let AnnotationTok(s) = raw(s)
83+
-- #let CommentVarTok(s) = raw(s)
84+
-- #let OtherTok(s) = raw(s)
85+
-- #let FunctionTok(s) = raw(s)
86+
-- #let VariableTok(s) = raw(s)
87+
-- #let ControlFlowTok(s) = raw(s)
88+
-- #let OperatorTok(s) = raw(s)
89+
-- #let BuiltInTok(s) = raw(s)
90+
-- #let ExtensionTok(s) = raw(s)
91+
-- #let PreprocessorTok(s) = raw(s)
92+
-- #let AttributeTok(s) = raw(s)
93+
-- #let RegionMarkerTok(s) = raw(s)
94+
-- #let InformationTok(s) = raw(s)
95+
-- #let WarningTok(s) = raw(s)
96+
-- #let AlertTok(s) = raw(s)
97+
-- #let ErrorTok(s) = raw(s)
98+
-- #let NormalTok(s) = raw(s)
99+
100+
101+
-- define Skylighting + all the token functions
102+
-- (case backgroundColor f of
103+
-- Nothing -> ["\\newenvironment{Shaded}{}{}"]
104+
-- Just (RGB r g b) -> ["\\usepackage{framed}"
105+
-- ,Text.pack
106+
-- (printf "\\definecolor{shadecolor}{RGB}{%d,%d,%d}" r g b)
107+
-- ,"\\newenvironment{Shaded}{\\begin{snugshade}}{\\end{snugshade}}"])
108+
-- ++ sort (map (macrodef (defaultColor f) (Map.toList (tokenStyles f)))
109+
-- (enumFromTo KeywordTok NormalTok))
110+
111+
-- also define EndLine
112+
-- #raw(\"\\n\")"
121113

122114
macrodef :: Maybe Color -> [(TokenType, TokenStyle)] -> TokenType -> Text
123-
macrodef defaultcol tokstyles tokt = "\\newcommand{\\"
124-
<> Text.pack (show tokt)
125-
<> "}[1]{"
126-
<> Text.pack (co . ul . bf . it . bg $ "#1")
127-
<> "}"
128-
where tokf = case lookup tokt tokstyles of
129-
Nothing -> defStyle
130-
Just x -> x
131-
ul x = if tokenUnderline tokf
132-
then "\\underline{" <> x <> "}"
133-
else x
134-
it x = if tokenItalic tokf
135-
then "\\textit{" <> x <> "}"
136-
else x
137-
bf x = if tokenBold tokf
138-
then "\\textbf{" <> x <> "}"
139-
else x
140-
bcol = fromColor `fmap` tokenBackground tokf
141-
:: Maybe (Double, Double, Double)
142-
bg x = case bcol of
143-
Nothing -> x
144-
Just (r, g, b) ->
145-
printf "\\colorbox[rgb]{%0.2f,%0.2f,%0.2f}{%s}" r g b x
146-
col = fromColor `fmap` (tokenColor tokf `mplus` defaultcol)
147-
:: Maybe (Double, Double, Double)
148-
co x = case col of
149-
Nothing -> x
150-
Just (r, g, b) ->
151-
printf "\\textcolor[rgb]{%0.2f,%0.2f,%0.2f}{%s}" r g b x
115+
macrodef defaultcol tokstyles tokt = "TODO"
116+
-- "\\newcommand{\\"
117+
-- <> Text.pack (show tokt)
118+
-- <> "}[1]{"
119+
-- <> Text.pack (co . ul . bf . it . bg $ "#1")
120+
-- <> "}"
121+
-- where tokf = case lookup tokt tokstyles of
122+
-- Nothing -> defStyle
123+
-- Just x -> x
124+
-- ul x = if tokenUnderline tokf
125+
-- then "\\underline{" <> x <> "}"
126+
-- else x
127+
-- it x = if tokenItalic tokf
128+
-- then "\\textit{" <> x <> "}"
129+
-- else x
130+
-- bf x = if tokenBold tokf
131+
-- then "\\textbf{" <> x <> "}"
132+
-- else x
133+
-- bcol = fromColor `fmap` tokenBackground tokf
134+
-- :: Maybe (Double, Double, Double)
135+
-- bg x = case bcol of
136+
-- Nothing -> x
137+
-- Just (r, g, b) ->
138+
-- printf "\\colorbox[rgb]{%0.2f,%0.2f,%0.2f}{%s}" r g b x
139+
-- col = fromColor `fmap` (tokenColor tokf `mplus` defaultcol)
140+
-- :: Maybe (Double, Double, Double)
141+
-- co x = case col of
142+
-- Nothing -> x
143+
-- Just (r, g, b) ->
144+
-- printf "\\textcolor[rgb]{%0.2f,%0.2f,%0.2f}{%s}" r g b x
152145

skylighting/bin/main.hs

+18
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ data HighlightFormat = FormatANSI
4545
| FormatConTeXt
4646
| FormatHtml
4747
| FormatLaTeX
48+
| FormatTypst
4849
| FormatNative
4950
deriving (Eq, Show)
5051

@@ -147,6 +148,7 @@ formatOf (Format s : _) = case map toLower s of
147148
"context"-> return FormatConTeXt
148149
"html" -> return FormatHtml
149150
"latex" -> return FormatLaTeX
151+
"typst" -> return FormatTypst
150152
"native" -> return FormatNative
151153
_ -> err $ "Unknown format: " ++ s
152154
formatOf (_ : xs) = formatOf xs
@@ -249,6 +251,7 @@ main = do
249251
FormatConTeXt-> hlConTeXt fragment fname highlightOpts style sourceLines
250252
FormatHtml -> hlHtml fragment fname highlightOpts style sourceLines
251253
FormatLaTeX -> hlLaTeX fragment fname highlightOpts style sourceLines
254+
FormatTypst -> hlTypst fragment fname highlightOpts style sourceLines
252255
FormatNative -> putStrLn $ ppShow sourceLines
253256

254257
hlANSI :: FormatOptions
@@ -298,6 +301,21 @@ hlLaTeX frag fname opts sty sourceLines =
298301
macros = styleToLaTeX sty
299302
pageTitle = "\\title{" <> Text.pack fname <> "}\n"
300303

304+
hlTypst :: Bool -- ^ Fragment
305+
-> FilePath -- ^ Filename
306+
-> FormatOptions
307+
-> Style
308+
-> [SourceLine]
309+
-> IO ()
310+
hlTypst frag fname opts sty sourceLines =
311+
if frag
312+
then Text.putStrLn fragment
313+
else Text.putStrLn $ macros <> pageTitle <> fragment
314+
where fragment = formatTypstBlock opts sourceLines
315+
macros = styleToTypst sty
316+
pageTitle = "== " <> Text.pack fname <> "\n"
317+
318+
301319
hlConTeXt :: Bool -- ^ Fragment
302320
-> FilePath -- ^ Filename
303321
-> FormatOptions

skylighting/skylighting.cabal

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ library
4646
, skylighting-format-blaze-html:Skylighting.Format.HTML
4747
, skylighting-format-context:Skylighting.Format.ConTeXt
4848
, skylighting-format-latex:Skylighting.Format.LaTeX
49+
, skylighting-format-typst:Skylighting.Format.Typst
4950
other-modules:
5051
Skylighting.Syntax.Abc
5152
Skylighting.Syntax.Actionscript
@@ -217,6 +218,7 @@ library
217218
skylighting-format-context >= 0.1 && < 0.2,
218219
skylighting-format-latex >= 0.1 && < 0.2,
219220
skylighting-format-blaze-html >= 0.1 && < 0.2,
221+
skylighting-format-typst >= 0.1 && < 0.2,
220222
containers,
221223
binary
222224
hs-source-dirs: src

skylighting/src/Skylighting.hs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module Skylighting
1717
, module Skylighting.Format.ConTeXt
1818
, module Skylighting.Format.HTML
1919
, module Skylighting.Format.LaTeX
20+
, module Skylighting.Format.Typst
2021
, module Skylighting.Loader
2122

2223
)
@@ -27,6 +28,7 @@ import Skylighting.Format.ANSI
2728
import Skylighting.Format.ConTeXt
2829
import Skylighting.Format.HTML
2930
import Skylighting.Format.LaTeX
31+
import Skylighting.Format.Typst
3032
import Skylighting.Parser
3133
import Skylighting.Regex
3234
import Skylighting.Styles

0 commit comments

Comments
 (0)