platformer / typst-algorithms

MIT License
141 stars 4 forks source link

Is it possible/desirable to have an algorithm2e-like syntax? #21

Open TimotheAlbouy opened 6 months ago

TimotheAlbouy commented 6 months ago

Thank you for this package. It surely is the most mature package for writing pseudocode in typst yet.

However, I find the syntax with indents/dedents not very ergonomic. I am used to LaTeX's algorithm2e syntax for writing pseudocode, where you define loops/if clauses/functions... using macros. I think that in typst, this would translate very naturally to function calls.

For example, the following LaTeX/algorithm2e code:

\documentclass{article}

\usepackage[vlined,boxed,linesnumbered]{algorithm2e}
\SetKwIF{If}{ElseIf}{Else}{if}{then}{else if}{else}{}
\SetKwProg{Function}{function}{ is}{}
\SetKwComment{Comment}{}{}

\begin{document}

\begin{algorithm}[ht]
\Function{Binary-Search$(A,n,v)$}{
    $l \gets 1$; $r \gets n$\Comment*{Initialize the search range}
    \While{$l \leq r$}{
      $m \gets floor((l+r)/2)$\;
      \If{$A[m] < v$}{
        $\ell \gets m+1$\;
      }
      \ElseIf{$A[m] > v$}{
        $r \gets m - 1$\;
      }
      \lElse{return $m$}
    }
    return null\;
}
\caption{Binary search.}
\end{algorithm}

\end{document}

would translate to the following typst/algo code:

#import "@preview/algo:1.0.0": algo, algo-block, algo-inline, algo-inline-comment

#let Line = algo-inline[]

#let Function = algo-block[*function*]
#let While = algo-block([*while*], preamble-end: [*do*])

#let lComment = algo-inline-comment()

// block versions of if/else-if/else
#let If = algo-block([*if*], preamble-end: [*then*])
#let ElseIf = algo-block([*else if*], preamble-end: [*then*])
#let Else = algo-block([*else*])

// inline versions of if/else-if/else
#let lIf = algo-inline([*if*], preamble-end: [*then*])
#let lElseIf = algo-inline([*else if*], preamble-end: [*then*])
#let lElse = algo-inline([*else*])

#algo({
  Function([_Binary-Search_$(A,n,v)$], {
    Line[$l <- 1$; $r <- n$; #lComment[Initialize the search range]]

    While($l <= r$, {
      Line[$m <- upright(bold("floor"))((l + r)/2)$;]
      If($A[m] < v$,
        [$l <- m+1$;]
      )
      ElseIf([$A[m] > v$],
        [$r <- m-1$;]
      )
      lElse[*return* $m$;]
    })
    Line[*return* null;]
  })
})

Here, the user would define their own function/if/else-if/else/while keywords, making the framework less opinionated. The algo-block() function would be used to define a new keyword for a block of code, whereas the algo-inline() function would be used to define an inline statement (e.g., a "if-then" statement on one line). The preamble-end option would specify the keyword at the end of the first part of the statement (e.g., the "then" part of a "if-then" statement).

The algorithmic typst package already uses this syntax, which is more elegant as the one currently used in the algo package IMHO, as it relieves the end-user of doing all the tedious (in/de)denting. However, algorithmic lacks all the nice features of the algo package.

What do you think? Would this syntax be feasible for the algo package? If so, would it be desirable?

platformer commented 6 months ago

I experimented with this when initially writing the package, but I found it to be more cumbersome to write and edit due to all the brackets. That's why I wanted to make algo's syntax as 1-to-1 as possible. However, I recognize that constantly typing newlines and indents can be annoying. For the next major version, I'm planning on leveraging Typst's list syntax for writing the algorithms, similar to one of the options lovelace provides. This moves the indentation information to Typst's built in lists rather than being a command typed by the user.

TimotheAlbouy commented 5 months ago

I think you are right, typst allows for much lighter syntax, we shouldn't limit ourselves to how a 20+-year-old Latex package did it.

Following your idea, I have created a small pseudocode package that leverages typst's list syntax and mimics algorithm2e's styling nearly perfectly. I've also added the capability to reference lines. I will use it for my personal use, but if you are interested I can send you my code.

platformer commented 5 months ago

If you feel comfortable sharing, sure! Would be very helpful

TimotheAlbouy commented 5 months ago

I have sent you an email to your gmail address ;)