Markdown mode
Lem’s markdown mode supports:
- syntax highlihgting
- live preview in a browser
- evaluation of code blocks and insertion of results
- multiple major modes into a single markdown buffer.
C-c C-l
:markdown-insert-link
.- you can select a text, and the command will add a link around it.
- with
C-u
, ask for a title / tooltip.
Use M-x markdown-preview
. This command renders the markdown of the
current buffer to a browser window. The preview is refreshed when the
file is saved.
The preview connection is stopped when the file is closed.
Note that this command currently processes Markdown, not CommonMark.
New as of May 28th, 2024

When you start a code block with three backticks and a programming language name, the code block will be highlighted for this language. You don’t have to activate anything.
When you write code in a code block, you can use the programming
language mode’s usual keybindings, such as C-c C-c
for Lisp. It will
work as if you were in a file for this language with its major mode
activated.

A known issue is that the execute
method is not called.
New as of August, 2025.
Lem got interactive features to markdown source code blocks. It works by default for:
- lisp
- bash
- python
The idea is that you can run the code blocks, and do something with them: display them in a pop-up windowd, print them on file below the code block, eval the code but ignore the results…
The API consists of these commands:
markdown-eval-block
(C-c c-e): evaluate the current markdown code block and display the results in a pop-up (just likelisp-macroexpand
).markdown-eval-block-and-insert
(C-c C-c): Evaluate the current markdown code block and insert its result below the block.markdown-eval-block-nop
(C-c C-r): evaluate the current markdown code block and do nothing with the result.markdown-kill-block-result
(C-c C-d): deletes the result block below the code block your cursor is in. This is run automatically beforemarkdown-eval-block-and-insert
.
For example:
```bash
echo "hello"
```
When the cursor is in the code block, press C-c C-c
to insert the results:
```bash
echo "hello"
```
```result
hello
```
If you try to evaluate a block and there is no registered evaluator, a message is displayed saying so. If you use any of these commands outside a code block, nothing happens. If you use these commands while not in markdown-mode, a warning is displayed.
Evaluation commands work asynchronously and you can do whatever you want while it is working.
Here is a demo:
Screencast from 2024-02-17 14-15-46.webm
The macro register-block-evaluator
is for users to add support for
other languages.
For example, this is how the bash support was added:
(register-block-evaluator "bash" (string callback)
"Register evaluator for Bash blocks."
(bt:make-thread
(lambda ()
(funcall callback (uiop:run-program string :output :string)))))
and the evaluator for lisp:
(register-block-evaluator "lisp" (string callback)
"Register evaluator for Lisp blocks."
(lem-lisp-mode:check-connection)
(lem-lisp-mode:lisp-eval-async
(read-from-string (format nil "(progn ~a)" string))
callback))