This is a package for writing pseudocode in Typst. It is named after the computer science pioneer Ada Lovelace and inspired by the pseudo package for LaTeX.
Usage
Import the package using
#import "@preview/lovelace:0.1.0": *
You should then call the setup function in a show rule at the top of your document:
#show: setup-lovelace
You are then ready to go to typeset some pseudocode:
#pseudocode(
no-number,
[*input:* integers $a$ and $b$],
no-number,
[*output:* greatest common divisor of $a$ and $b$],
[*while* $a != b$ *do*], ind,
[*if* $a > b$ *then*], ind,
$a <- a - b$, ded,
[*else*], ind,
$b <- b - a$, ded,
[*end*], ded,
[*end*],
[*return* $a$]
)
resulting in:
As you can see, every line of your pseudocode is represented by a single content
argument.
Additionally, we use ind
and ded
to control the indentation level:
ind
(indent) to go one level deeper, ded
(dedent) to go one level back.
Don’t forget to put all the commas in between!
The content of your pseudocode is up to you.
This package does not assume any specific set of keywords or language constructs.
For example, you might want to write something like
#pseudocode(
$x <- a$,
[*repeat until convergence*], ind,
$x <- (x + a/x) / 2$, ded,
[*return* $x$]
)
for some more abstract, less implementation concerned pseudocode that follows your own convention, most suitable to you.
There are two other elements you can use as positional arguments to #pseudocode
:
no-number
makes the next line have no line number (and also not being counted).
This is useful for things like input and output (as seen above) or to introduce
an empty line (i.e, you add no-number, []
to the arguments).
Referencing lines
Finally, you can put labels there. They will be attached to the line number of the following line and can be used to reference that line later:
#pseudocode(
<line:eat>,
[Eat],
[Train],
<line:sleep>,
[Sleep],
[*goto* @line:eat]
)
@line:sleep is of particular importance.
Algorithm as figure
#pseudocode
is great if you just want to show some lines of code.
If you want to display a full algorithm with bells and whistles, you can use
#algorithm
:
#algorithm(
caption: [The Euclidean algorithm],
pseudocode(
no-number,
[*input:* integers $a$ and $b$],
no-number,
[*output:* greatest common divisor of $a$ and $b$],
[*while* $a != b$ *do*], ind,
[*if* $a > b$ *then*], ind,
$a <- a - b$, ded,
[*else*], ind,
$b <- b - a$, ded,
[*end*], ded,
[*end*],
[*return* $a$]
)
)
resulting in:
#algorithm
creates a figure with kind: "lovelace"
so it gets its own counter
and display.
You can use optional arguments such as placement
or caption
, see
figure in the Typst docs.
Note that such figures are only displayed correctly when you used the setup
function mentioned above!
Comments
Again, the content of your pseudocode is completely up to you, and that includes
comments.
However, Lovelace provides a sensible #comment
function you can use:
#pseudocode(
[A statement #comment[and a comment]],
[Another statement #comment[and another comment]],
)
Customisation
Lovelace provides a couple of customisation options.
First, the pseudocode
function accepts optional keyword arguments:
line-numbering
:true
orfalse
, whether to display line numbers, defaulttrue
line-number-transform
: a function that takes in the line number as an integer and returns an arbitrary value that will be displayed instead of the line number, defaultnum => num
(identity function)indentation-guide-stroke
: a stroke, defining how the indentation guides are displayed, defaultnone
(no lines)
For example, let’s use thin blue indentation guides and roman line numbering:
#pseudocode(
line-number-transform: num => numbering("i", num),
indentation-guide-stroke: .5pt + aqua,
no-number,
[*input:* integers $a$ and $b$],
no-number,
[*output:* greatest common divisor of $a$ and $b$],
[*while* $a != b$ *do*], ind,
[*if* $a > b$ *then*], ind,
$a <- a - b$, ded,
[*else*], ind,
$b <- b - a$, ded,
[*end*], ded,
[*end*],
[*return* $a$]
)
resulting in:
Also, there are some optional arguments to lovelace-setup
:
line-number-style
: a function that takes content and returns content, used to display the line numbers in the pseudocode, defaulttext.with(size: .7em)
, note that this is different from theline-number-transform
argument to#pseudocode
as the latter has an effect on line numbers in references as well.line-number-supplement
: some content that is placed before the line number when referencing it, default"Line"
If you want to avoid having to repeat all those configurations, here is what you can do. Suppose, we always want German supplements (Zeile and Algorithmus instead of Line and Algorithm) and thin indentation guides.
#show: setup-lovelace.with(line-number-supplement: "Zeile")
#let pseudocode = pseudocode.with(indentation-guide-stroke: .5pt)
#let algorithm = algorithm.with(supplement: "Algorithmus")
#algorithm(
caption: [Spurwechsel nach links auf der Autobahn],
pseudocode(
<line:blinken>,
[Links blinken],
[In den linken Außenspiegel schauen],
[*wenn* niemand nähert sich auf der linken Spur, *dann*], ind,
[Spur wechseln], ded,
[Blinker aus],
)
)
Der Schritt in @line:blinken stellt offenbar für viele Verkehrsteilnehmer eine
Herausforderung dar.