sulami/literate-calc-mode.el

🧮 Literate programming for M-x calc

Emacs Lisp

355

93 commits

updated Aug 9, 2025

See the code

README

#+TITLE: Literate Calc Mode

[[https://melpa.org/#/literate-calc-mode][file:https://melpa.org/packages/literate-calc-mode-badge.svg]]

Literate programming for =M-x calc=. There is an [[https://blog.sulami.xyz/posts/literate-calc-mode/][announcement blog
post]].

Displays inline results for calculations, supports variables and
updates as you type (if you want). Also works in your favourite markup
mode.

#+caption: Demo
[[file:./scrot.png]]

* Installing

Simply grab it from [[https://melpa.org/][MELPA]].

** [[https://github.com/jwiegley/use-package][use-package]]

#+begin_src emacs-lisp
(use-package literate-calc-mode
  :ensure t)
#+end_src

** [[https://github.com/raxod502/straight.el][straight.el]]

#+begin_src emacs-lisp
(straight-use-package 'literate-calc-mode)
#+end_src

** package.el

[[https://melpa.org/#/getting-started][Ensure you have MELPA available.]]

=M-x package-install=, select =literate-calc-mode=.

** Manual

Just fetch [[file:literate-calc-mode.el][literate-calc-mode.el]], save it somewhere and load it into
Emacs.

* Configuration

There is a =M-x customize= group named after the mode which contains
the following options:

| ~literate-calc-mode-idle-time~              | How long to wait after typing to recalculate results (buffer-local)                       |
| ~literate-calc-mode-inhibit-line-functions~ | Hook functions called for each line to test whether to inhibit calculation (buffer-local) |
| ~literate-calc-mode-radix~                  | Default radix/base for results (buffer-local)                                             |
| ~literate-calc-mode-max-buffer-size~        | Maximum buffer size to activate the minor mode                                            |
| ~literate-calc-usimplify-results~           | Apply =usimplify= to all results implicitly (buffer-local)                                  |
| ~literate-calc-equals~                      | The string used to indicate a result (default: " => ")                                    |
| ~literate-calc-mode-result-face~            | The face used when inserting results into the buffer                                      |
| ~literate-calc-mode-identifier-face~        | The face used to highlight variables during assignment                                    |
| ~literate-calc-mode-extra-options~          | Pass extra options to =calc-eval= (buffer-local) (default: ~'(calc-group-digits t)~)          |

The idle time prevents lag due to constant recalculation in the middle
of typing, defaulting to 1 second.

These are the available inhibitors, which are all enabled by default:

- ~literate-calc-mode-inhibit-in-src-blocks~ :: Prevents evaluation inside org-mode ~src~ blocks
- ~literate-calc-mode-inhibit-in-latex~ :: Prevents evaluation inside org-mode LaTeX fragments

Of course you can also just ~setq~ / ~setq-default~ the options directly.

** Calc Configuration

Because LCM uses Emacs =calc= under the hood, a lot of configuration
options for =calc= also affect LCM operation.

An interesting one is =calc-multiplication-has-precedence=, which when
non-nil means that multiplication will have higher precedence than
division, which can lead to surprising results.

You can also use ~literate-calc-mode-extra-options~ to pass extra
options to =calc-eval=. This can be used to for example change the digit
grouping (=calc-group-digits=) or the word size (=calc-word-size=).

* Use

There is both a major ~literate-calc-mode~ and a minor
~literate-calc-minor-mode~. The major mode does some basic syntax
highlighting, while the minor mode only evaluates all calc statements
while typing.

The minor mode works quite well with org-/markdown mode or other
markup language major modes.

There are also some functions which can be called without any mode
being active:

| =M-x literate-calc-eval-line=      | Evaluates a single line                                           |
| =M-x literate-calc-eval-region=    | Evaluates within the selected region                              |
| =M-x literate-calc-eval-buffer=    | Evaluates the whole buffer                                        |
| =M-x literate-calc-insert-results= | Evaluates the whole buffer and inserts results                    |
| =M-x literate-calc-remove-results= | Removes all results and clears variables                          |
| =M-x literate-calc-kill-result=    | Evaluates the current line and pushes the result to the kill ring |
| =M-x literate-calc-clear-overlays= | Removes all overlays and clears variables                         |
| =M-x literate-calc-set-radix=      | Sets the radix/base output for the current buffer                 |

** Using Units

You can simply append units to your values like so:

#+begin_src fundamental
Flour = 500g => Flour: 500 g
#+end_src

Unit conversion (and other complex functions) can be used by invoking
the matching [[https://www.gnu.org/software/emacs/manual/html_node/calc/Function-Index.html][Algebraic Function]].

#+begin_src fundamental
= usimplify(1m + 3mm) => 1.003 m
#+end_src

You can also use unknown mathematical symbols:

#+begin_src fundamental
= x*2 + x-3 => 3 x - 3
#+end_src

** Solving equations

Equations can be solved with calc's ~solve~ function. For example, this
is solving for =y=:

#+begin_src fundamental
y = solve(2y + 3 = 10, y) => y: 3.5
#+end_src

For now, solve expressions need to be the only expression within a
line to get evaluated correctly, so ~x = 5 + solve(..~ will not work as
intended.

** Evaluation in Org

Org-mode source blocks can be evaluated (~C-c C-c~ by default).

If ~:results~ is set to ~value~, which is the default, a block returns
its last result. If ~:results~ is set to ~output~, it will return the
entire block, annotated with results.

Local variables can be defined in header arguments as ~:var a=38 b=4~.

** Changing radix/base

You can change the ~literate-calc-mode-radix~ custom variable to set the default
base for number output globally for all literate-calc-mode buffers, but it's
also possible to change the output radix of the current buffer by calling the
interactive function ~literate-calc-set-radix~ in your desired buffer. For
example, =M-x literate-calc-set-radix 16= will display results with base 16
(hex).

Example output with radix set to 16:

#+begin_src fundamental
a0 = 2#11001100 => a0: 16#CC
a1 = 2#11110000 => a1: 16#F0
= and(a0, a1) => 16#C0
#+end_src


* Full Example

#+begin_src fundamental
This is a literate calc file.

Lines without "=" are ignored.

All results starting with "=>" are an overlay generated by
literate-calc-mode. That means they are displayed in Emacs, but not
actually in the buffer/file contents.

We can calculate a value like so:

= 2 + 2 => 4

If there is any string on the left hand side, it becomes a bound
variable.

Pi = 3.14159 => Pi: 3.14159

We can use this variable below the definiton.

Tau = Pi * 2 => Tau: 6.28318

Results are calculated using Emacs' own calc, so you can use formulas
as well.

= round(Pi, 2) => 3.14

Later bindings shadow earlier ones:

Pi = 3 => Pi: 3

= Pi => 3

Variable names can have spaces as well:

Monthly Expenses = 500 => Monthly Expenses: 500

Monthly Income = 1000 => Monthly Income: 1000

Annual Savings = 12 * (Monthly Income - Monthly Expenses) => Annual Savings: 6000

All values are recalculated on every update in a spreadsheet-like
fashion.

Calc also has a lot of advanced features, like arrays:

Numbers = [1 2 3] => Numbers: [1, 2, 3]

= 3 Numbers => [3, 6, 9]

#+end_src

* Roadmap

There are some additional features I'm currently thinking about.

** Semantic Highlighting

One of the original inspirations was [[http://tydligapp.com/][Tydlig]], which does similar
things, but also has semantic highlighting. That means, variables are
highlighted in different colours, but always the same one for a given
variable, so that you can see where it's used at a glance.

I might steal some code from [[https://github.com/Fanael/rainbow-identifiers][rainbow-identifiers]], which is one of the
[[https://github.com/ankurdave/color-identifiers-mode][shorter existing implementations]] around, and adapt that to our needs.

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

calc
calculator
emacs
hacktoberfest
literate-programming

Contributors

sulami

85 commits

dme

4 commits

chrisbarrett

2 commits

artenator

1 commits

sulami/literate-calc-mode.el

🧮 Literate programming for M-x calc

Emacs Lisp

355

93 commits

updated Aug 9, 2025

See the code

README

#+TITLE: Literate Calc Mode

[[https://melpa.org/#/literate-calc-mode][file:https://melpa.org/packages/literate-calc-mode-badge.svg]]

Literate programming for =M-x calc=. There is an [[https://blog.sulami.xyz/posts/literate-calc-mode/][announcement blog
post]].

Displays inline results for calculations, supports variables and
updates as you type (if you want). Also works in your favourite markup
mode.

#+caption: Demo
[[file:./scrot.png]]

* Installing

Simply grab it from [[https://melpa.org/][MELPA]].

** [[https://github.com/jwiegley/use-package][use-package]]

#+begin_src emacs-lisp
(use-package literate-calc-mode
  :ensure t)
#+end_src

** [[https://github.com/raxod502/straight.el][straight.el]]

#+begin_src emacs-lisp
(straight-use-package 'literate-calc-mode)
#+end_src

** package.el

[[https://melpa.org/#/getting-started][Ensure you have MELPA available.]]

=M-x package-install=, select =literate-calc-mode=.

** Manual

Just fetch [[file:literate-calc-mode.el][literate-calc-mode.el]], save it somewhere and load it into
Emacs.

* Configuration

There is a =M-x customize= group named after the mode which contains
the following options:

| ~literate-calc-mode-idle-time~              | How long to wait after typing to recalculate results (buffer-local)                       |
| ~literate-calc-mode-inhibit-line-functions~ | Hook functions called for each line to test whether to inhibit calculation (buffer-local) |
| ~literate-calc-mode-radix~                  | Default radix/base for results (buffer-local)                                             |
| ~literate-calc-mode-max-buffer-size~        | Maximum buffer size to activate the minor mode                                            |
| ~literate-calc-usimplify-results~           | Apply =usimplify= to all results implicitly (buffer-local)                                  |
| ~literate-calc-equals~                      | The string used to indicate a result (default: " => ")                                    |
| ~literate-calc-mode-result-face~            | The face used when inserting results into the buffer                                      |
| ~literate-calc-mode-identifier-face~        | The face used to highlight variables during assignment                                    |
| ~literate-calc-mode-extra-options~          | Pass extra options to =calc-eval= (buffer-local) (default: ~'(calc-group-digits t)~)          |

The idle time prevents lag due to constant recalculation in the middle
of typing, defaulting to 1 second.

These are the available inhibitors, which are all enabled by default:

- ~literate-calc-mode-inhibit-in-src-blocks~ :: Prevents evaluation inside org-mode ~src~ blocks
- ~literate-calc-mode-inhibit-in-latex~ :: Prevents evaluation inside org-mode LaTeX fragments

Of course you can also just ~setq~ / ~setq-default~ the options directly.

** Calc Configuration

Because LCM uses Emacs =calc= under the hood, a lot of configuration
options for =calc= also affect LCM operation.

An interesting one is =calc-multiplication-has-precedence=, which when
non-nil means that multiplication will have higher precedence than
division, which can lead to surprising results.

You can also use ~literate-calc-mode-extra-options~ to pass extra
options to =calc-eval=. This can be used to for example change the digit
grouping (=calc-group-digits=) or the word size (=calc-word-size=).

* Use

There is both a major ~literate-calc-mode~ and a minor
~literate-calc-minor-mode~. The major mode does some basic syntax
highlighting, while the minor mode only evaluates all calc statements
while typing.

The minor mode works quite well with org-/markdown mode or other
markup language major modes.

There are also some functions which can be called without any mode
being active:

| =M-x literate-calc-eval-line=      | Evaluates a single line                                           |
| =M-x literate-calc-eval-region=    | Evaluates within the selected region                              |
| =M-x literate-calc-eval-buffer=    | Evaluates the whole buffer                                        |
| =M-x literate-calc-insert-results= | Evaluates the whole buffer and inserts results                    |
| =M-x literate-calc-remove-results= | Removes all results and clears variables                          |
| =M-x literate-calc-kill-result=    | Evaluates the current line and pushes the result to the kill ring |
| =M-x literate-calc-clear-overlays= | Removes all overlays and clears variables                         |
| =M-x literate-calc-set-radix=      | Sets the radix/base output for the current buffer                 |

** Using Units

You can simply append units to your values like so:

#+begin_src fundamental
Flour = 500g => Flour: 500 g
#+end_src

Unit conversion (and other complex functions) can be used by invoking
the matching [[https://www.gnu.org/software/emacs/manual/html_node/calc/Function-Index.html][Algebraic Function]].

#+begin_src fundamental
= usimplify(1m + 3mm) => 1.003 m
#+end_src

You can also use unknown mathematical symbols:

#+begin_src fundamental
= x*2 + x-3 => 3 x - 3
#+end_src

** Solving equations

Equations can be solved with calc's ~solve~ function. For example, this
is solving for =y=:

#+begin_src fundamental
y = solve(2y + 3 = 10, y) => y: 3.5
#+end_src

For now, solve expressions need to be the only expression within a
line to get evaluated correctly, so ~x = 5 + solve(..~ will not work as
intended.

** Evaluation in Org

Org-mode source blocks can be evaluated (~C-c C-c~ by default).

If ~:results~ is set to ~value~, which is the default, a block returns
its last result. If ~:results~ is set to ~output~, it will return the
entire block, annotated with results.

Local variables can be defined in header arguments as ~:var a=38 b=4~.

** Changing radix/base

You can change the ~literate-calc-mode-radix~ custom variable to set the default
base for number output globally for all literate-calc-mode buffers, but it's
also possible to change the output radix of the current buffer by calling the
interactive function ~literate-calc-set-radix~ in your desired buffer. For
example, =M-x literate-calc-set-radix 16= will display results with base 16
(hex).

Example output with radix set to 16:

#+begin_src fundamental
a0 = 2#11001100 => a0: 16#CC
a1 = 2#11110000 => a1: 16#F0
= and(a0, a1) => 16#C0
#+end_src


* Full Example

#+begin_src fundamental
This is a literate calc file.

Lines without "=" are ignored.

All results starting with "=>" are an overlay generated by
literate-calc-mode. That means they are displayed in Emacs, but not
actually in the buffer/file contents.

We can calculate a value like so:

= 2 + 2 => 4

If there is any string on the left hand side, it becomes a bound
variable.

Pi = 3.14159 => Pi: 3.14159

We can use this variable below the definiton.

Tau = Pi * 2 => Tau: 6.28318

Results are calculated using Emacs' own calc, so you can use formulas
as well.

= round(Pi, 2) => 3.14

Later bindings shadow earlier ones:

Pi = 3 => Pi: 3

= Pi => 3

Variable names can have spaces as well:

Monthly Expenses = 500 => Monthly Expenses: 500

Monthly Income = 1000 => Monthly Income: 1000

Annual Savings = 12 * (Monthly Income - Monthly Expenses) => Annual Savings: 6000

All values are recalculated on every update in a spreadsheet-like
fashion.

Calc also has a lot of advanced features, like arrays:

Numbers = [1 2 3] => Numbers: [1, 2, 3]

= 3 Numbers => [3, 6, 9]

#+end_src

* Roadmap

There are some additional features I'm currently thinking about.

** Semantic Highlighting

One of the original inspirations was [[http://tydligapp.com/][Tydlig]], which does similar
things, but also has semantic highlighting. That means, variables are
highlighted in different colours, but always the same one for a given
variable, so that you can see where it's used at a glance.

I might steal some code from [[https://github.com/Fanael/rainbow-identifiers][rainbow-identifiers]], which is one of the
[[https://github.com/ankurdave/color-identifiers-mode][shorter existing implementations]] around, and adapt that to our needs.

Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.

calc
calculator
emacs
hacktoberfest
literate-programming

Contributors

sulami

85 commits

dme

4 commits

chrisbarrett

2 commits

artenator

1 commits

Languages

Emacs Lisp

100.0%