description: Are you a LaTeX user? This guide explains the differences and similarities between Mel and LaTeX so you can get started quickly.
This page is a good starting point if you've used LaTeX before and want to try out Mel. We'll explore the main differences between these two systems from a user's perspective. Although Mel is not built on top of LaTeX and has different syntax, you'll learn how to use your LaTeX skills to get a quick start.
Just like LaTeX, Mel is a markup-based composition system: You compose your document in a text file and mark it up with commands and other syntax. Then, you use a compiler to compose the source file into a PDF. However, Mel also differs from LaTeX in several aspects: For one, Mel uses more dedicated syntax (as you might know from Markdown) for common tasks. Mel commands are also more grounded: They all work the same way, so unlike LaTeX, you only need to understand some general concepts instead of learning different conventions for each package. Additionally, Mel compiles faster than LaTeX: Compilation usually takes milliseconds, not seconds, so both the web app and compiler can provide instant previews.
Next, we'll address some of the most common questions a user migrating from LaTeX will have when composing a document in Mel. If you prefer a step-by-step introduction to Mel, check out our tutorial.
It's easy. You just need to create a new empty text file (the file extension is
.mel
). No template is needed to get started. Simply start writing your
text. It will be set on an empty A4 page. If you're using the web app,
click "+ RUN" to create a new project with a file and enter the
editor. Paragraph breaks work like in LaTeX, just
use a blank line.
Hello!
Here are two paragraphs. The
output is shown on the right.
LaTeX uses the \section
command to create a section title. Nested titles
are indicated with \subsection
, \subsubsection
, etc. Depending on your
document class, there's also \part
or \chapter
.
In Mel, headings are less verbose: You prefix the line with
the title in it with an equals sign and a space to get a first-order title:
[= Introduction]
. If you need a second-order title, use two equals signs:
[== In this paper]
. You can nest titles as deeply as you want by
adding more equals signs.
Emphasis (usually rendered as italic text) is expressed by wrapping text in
[_underscores_]
and strong emphasis (usually rendered in bold) using
[*stars*]
instead.
Here's a list of common markup commands used in LaTeX and their equivalents in Mel. You can also check out the complete syntax cheat sheet.
Element | LaTeX | Mel | See |
---|---|---|---|
Strong emphasis | \textbf{strong} |
[*strong*] |
strong |
Emphasis | \emph{emphasis} |
[_emphasis_] |
emph |
Monospaced / code | \texttt{print(1)} |
[`print(1)`] |
raw |
Link | \url{https://mel.app} |
[https://mel.app/] |
link |
Label | \label{intro} |
[ |
label |
Reference | \ref{intro} |
[@intro] |
ref |
Citation | \cite{humphrey97} |
[@humphrey97] |
cite |
Bullet list | itemize environment |
[- List] |
list |
Numbered list | enumerate environment |
[+ List] |
enum |
Term list | description environment |
[/ Term: List] |
terms |
Figure | figure environment |
figure function |
figure |
Table | table environment |
table function |
table |
Equation | $x$ , align / equation environments |
[$x$] , [$ x = y $] |
equation |
Lists don't rely on environments in Mel. Instead, they have
light syntax like headings. To create an unordered list (itemize
),
prefix each line of an item with a hyphen:
To write this list in Mel...
```latex
\begin{itemize}
\item Fast
\item Flexible
\item Intuitive
\end{itemize}
```
...just type this:
- Fast
- Flexible
- Intuitive
List nesting works just by using proper indentation. Adding a blank line between items results in a more spaced list.
To get a numbered list (enumerate
), use a +
instead of the hyphen.
For a term list (description
), write [/ Term: Description]
.
LaTeX relies heavily on commands (prefixed by backslashes). It uses these macros to affect the composition process and to
insert and manipulate content. Some commands accept arguments, which are most often enclosed in braces: \cite{rasmus}
.
Mel differentiates between markup mode and code mode.
The default is markup mode, where you compose text and apply syntactic constructs like [*asterisks for bold text*]
.
Code mode, on the other hand, is similar to programming languages like Python, providing the option to insert and execute code snippets.
Inside Mel markup, you can switch to code mode for a single command (or better, expression)
using a hashtag (#
). This is how you call functions to, for example, split your project into different files or render text
based on some condition. Inside code mode, you can include normal markup content
using brackets. Inside code mode, this content is treated like any other normal value for a variable.
First, a rectangle:
#rect()
Let me show you how to do
#underline([_underlined_ text])
We can also do some math:
#calc.max(3, 2 * 4)
And finally a small loop:
#for x in range(3) [
Hi #x.
]
A function call always involves the function name (rect
,
underline
, calc.max
,
range
) followed by parentheses (unlike LaTeX where
brackets and braces are optional if the macro requires no arguments). The expected list
of arguments passed inside those parentheses depends on the specific function and is
specified in the reference.
A function can have multiple arguments. Some arguments are positional, meaning
you just provide the value: The function [#lower("SCREAM")]
returns its argument
in lowercase. Many functions use named arguments instead of positional
arguments to increase readability. For example, the dimensions and stroke of a
rectangle are defined with named arguments:
#rect(
width: 2cm,
height: 1cm,
stroke: red,
)
You specify a named argument by first writing its name (above, these are width
,
height
, and stroke
), then a colon, followed by the value (2cm
, 1cm
,
red
). You can find the available named arguments in the reference page for each function or in the autocomplete panel while typing.
Named arguments are similar to how some LaTeX environments are configured, for
example, you would type \begin{enumerate}[label={\alph*)}]
to start a list
with labels a)
, b)
, and so on.
Often, you want to provide some content to a function. For
example, the LaTeX command \underline{Alternative A}
would translate to
[#underline([Alternative A])]
in Mel. The brackets indicate that a
value is content. Inside these brackets, you can use normal markup.
However, this is quite a lot of parentheses for a simple construct.
That's why you can also move final content arguments after the parentheses
(and omit the parentheses if they would end up empty).
Mel is an #underline[alternative]
to LaTeX.
#rect(fill: aqua)[Get started here!]
You've probably noticed that arguments have distinct data types. Mel supports many data types. Below, there's a table with some of the most important ones and how to write them. To specify values of any of these types, you need to be in code mode!
Data type | Example |
---|---|
Content | {[*fast* typesetting]} |
String | {"Pietro S. Author"} |
Integer | {23} |
Floating point number | {1.459} |
Absolute length | {12pt} , {5in} , {0.3cm} , ... |
Relative length | {65%} |
The difference between content and string is that content can contain markup, including function calls, while a string is really just a sequence of simple characters.
Mel provides control flow constructs and
operators like +
to add things or ==
to
check equality between two variables. You can also define your own
variables and perform computations on them.
In LaTeX, some commands like \textbf{bold text}
take an argument in braces
and only affect that argument. Other commands like
\bfseries bold text
act like switches, changing the appearance of all subsequent
content within the current document or scope.
In Mel, the same function can be used to affect the appearance for either the
rest of the document, a block (or scope), or just its arguments. For example,
[#text(weight: "bold")[bold text]]
will only bold its argument, while
[#set text(weight: "bold")]
will bold any text until the end of the
current block, or if there is none, the document. A function's effects are
immediately obvious based on whether it is used in a call or a
set rule.
I am starting out with small text.
#set text(14pt)
This is a bit #text(18pt)[larger,]
don't you think?
Set rules can appear anywhere in the document. They can be thought of as default argument values for their respective functions:
#set enum(numbering: "I.")
Good results can only be obtained by
+ following best practices
+ being aware of current results
of other researchers
+ checking the data for biases
The +
is syntactic sugar (think of it as a shorthand) for a call to the
{enum}
function, for which we applied a set rule above. Most
syntax is tied to a function in this way. If you need to style an
element beyond what its arguments allow, you can completely redefine its
appearance with a show rule (somewhat comparable to
\renewcommand
).
In LaTeX, you start your main .tex
file with the \documentclass{article}
command to define how your document should appear. In that command, you
might have replaced article
with another value like report
and amsart
to
select a different appearance.
When using Mel, you style your documents with functions. Typically, you use a template that provides a function that styles your entire document. First, you import the function from a template file. Then, you apply it to your entire document. This is accomplished with a show rule that wraps the following document in a given function. The following example illustrates how this works:
>>> #let conf(
>>> title: none,
>>> authors: (),
>>> abstract: [],
>>> doc,
>>> ) = {
>>> set text(font: "Linux Libertine", 11pt)
>>> set par(justify: true)
>>> set page(
>>> "us-letter",
>>> margin: auto,
>>> header: align(
>>> right + horizon,
>>> title
>>> ),
>>> numbering: "1",
>>> )
>>>
>>> show heading.where(
>>> level: 1
>>> ): it => block(
>>> align(center,
>>> text(
>>> 13pt,
>>> weight: "regular",
>>> smallcaps(it.body),
>>> )
>>> ),
>>> )
>>> show heading.where(
>>> level: 2
>>> ): it => box(
>>> text(
>>> 11pt,
>>> weight: "regular",
>>> style: "italic",
>>> it.body + [.],
>>> )
>>> )
>>>
>>> set align(center)
>>> text(17pt, title)
>>>
>>> let count = calc.min(authors.len(), 3)
>>> grid(
>>> columns: (1fr,) * count,
>>> row-gutter: 24pt,
>>> ..authors.map(author => [
>>> #author.name \
>>> #author.affiliation \
>>> #link("mailto:" + author.email)
>>> ]),
>>> )
>>>
>>> par(justify: false)[
>>> *Abstract* \
>>> #abstract
>>> ]
>>>
>>> set align(left)
>>> columns(2, doc)
>>>}
<<< #import "conf.typ": conf
#show: conf.with(
title: [
Towards Improved Modelling
],
authors: (
(
name: "Theresa Tungsten",
affiliation: "Artos Institute",
email: "tung@artos.edu",
),
(
name: "Eugene Deklan",
affiliation: "Honduras State",
email: "e.deklan@hstate.hn",
),
),
abstract: lorem(80),
)
Let's get started writing this
article by putting insightful
paragraphs right here!
The {import}
statement makes
functions (and other definitions) from another file available.
In this example, it imports the conf
function from the conf.mel
file. This
function formats a document as a conference article. We use a show rule to apply
it to the document and also set up some article metadata. After
applying the show rule, we can start writing our article right away!
Functions are Mel's "commands" and can transform their arguments into an output value, including document content. Functions are "pure", meaning they can't have any effect besides creating an output value/content. This is in stark contrast to LaTeX macros which can have arbitrary effects on your document.
To let a function style your entire document, the show rule processes everything
that comes after it and calls the specified function after the colon with the
result as an argument. The .with
part is a method that takes the conf
function
and pre-configures some of its arguments before passing it to the
show rule.
In the web app, you can choose between predefined templates or even
create your own using the template wizard. You can also check out the
awesome-mel
repository to find
community-made templates. We plan to build a package manager to make
templates even easier to share in the future!
You can also create your own custom templates.
They are shorter and more readable than the corresponding LaTeX .sty
files by
orders of magnitude, so give it a try!
Mel is "batteries included", so the equivalent of many popular LaTeX packages is already built in. Below, we've compiled a table of frequently loaded packages and their corresponding functions in Mel.