Skip to main content

Neovim plugin for efficient note taking in Typst

Project description

Typstar

Neovim plugin for efficient (mathematical) note taking in Typst

See changes in CHANGELOG.md

Weekly Integration PyPI version

Features

Usage

Snippets

Use :TypstarToggleSnippets to toggle all snippets at any time. To efficiently navigate insert nodes and avoid overlapping ones, use :TypstarSmartJump and :TypstarSmartJumpBack. Available snippets can mostly be intuitively derived from here, they include:

Universal snippets:

  • Alphanumeric characters: :<char>$<char>$ in markup (e.g. :X$X$ , :5$5$ )
  • Greek letters: ;<latin><greek> in math and $<greek>$ in markup (e.g. ;aalpha/$alpha$ )
  • Common indices (numbers and letters i-n): <letter><index> <letter>_<index> in math and $<letter>$ <index> $<letter>_<index>$ in markup (e.g A314 A_314 , $alpha$ n $alpha_n$ , $F$ n,$F_n$, , $F$ n.$F_n$.)
  • Primes: $<letter>$ ' $<letter>'$ and in combination with index and punctuation like above (e.g. $phi$ ' $phi'$ , $phi$ 5'$phi'_5$ , $f$ '5.$f'_5$., f'5,f'_5, )

You can find a complete map of latin to greek letters including reasons for the less intuitive ones here. Note that some greek letters have multiple latin ones mapped to them.

Markup snippets:

Math snippets:

  • Many shorthands for mathematical expressions
  • Series of numbered letters: <letter> <z/o>t<optional last index> <letter>_<0/1>, <letter>_<1/2>, ... (e.g. a ot a_1, a_2, ... , a zt4 a_0, a_1, a_2, a_3, a_4 , alpha otk alpha_1, alpha_2, ..., alpha_k , oti 1, 2, ..., i )
  • Wrapping of any mathematical expression (see operations, works nested, multiline and in visual mode via the selection key): <expression><operation><operation>(<expression>) (e.g. (a^2+b^2)rtsqrt(a^2+b^2), lambdatdtilde(lambda), (1+1)sQ[1+1], (1+1)sq[(1+1)])
  • Simple functions: fo<value> f(<value>) (e.g. fox f(x) , ao5 a(5) )
  • Matrices: <size>ma and <size>ma. (e.g. 23ma → 2x3 matrix and 32ma. → 3x2 matrix with dots)

Note that you can customize (enable, disable and modify) every snippet.

Excalidraw/Rnote

  • Use :TypstarInsertExcalidraw/:TypstarInsertRnote to create a new drawing using the configured template, insert a figure displaying it and open it in Obsidian/Rnote.
  • To open an inserted drawing in Obsidian/Rnote, simply run :TypstarOpenDrawing (or :TypstarOpenExcalidraw/:TypstarOpenRnote if you are using the same file extension for both) while your cursor is on a line referencing the drawing.

Anki

Use the flA snippet to create a new flashcard

#flashcard(0, "My first flashcard")[
  Typst is awesome $a^2+b^2=c^2$
]

or the fla snippet to add a more complex front

#flashcard(0)[I love Typst $pi$][
  This is the back of my second flashcard
]

To render the flashcard in your document as well add some code like this

#let flashcard(id, front, back) = {
  strong(front)
  [\ ]
  back
}
  • Add a comment like // ANKI: MY::DECK to your document to set a deck used for all flashcards after this comment (You can use multiple decks per file)
  • Add a file named .anki containing a deck name to define a default deck on a directory base
  • Add a file named .anki.typ to define a preamble on a directory base. You can find the default preamble here.
  • Tip: Despite the use of SVGs you can still search your flashcards in Anki as the typst source is added into an invisible html paragraph

Neovim

  • Use :TypstarAnkiScan to scan the current nvim working directory and compile all flashcards in its context, unchanged files will be ignored
  • Use :TypstarAnkiForce to force compilation of all flashcards in the current working directory even if the files haven't changed since the last scan (e.g. on preamble change)
  • Use :TypstarAnkiForceCurrent to force compilation of all flashcards in the file currently edited
  • Use :TypstarAnkiReimport to also add flashcards that have already been assigned an id but are not currently present in Anki
  • Use :TypstarAnkiForceReimport and :TypstarAnkiForceCurrentReimport to combine features accordingly

Standalone

  • Run typstar-anki --help to show the available options

Installation

Install the plugin in Neovim and run the plugin setup. To run a demo installation, see Demo. To use Nix for installation, see Nix.

require('typstar').setup({ -- depending on your neovim plugin system
   -- your typstar config goes here
})
Example lazy.nvim config
{
    "arne314/typstar",
    dependencies = {
        "L3MON4D3/LuaSnip",
    },
    ft = { "typst" },
    keys = {
        {
            "<M-t>",
            "<Cmd>TypstarToggleSnippets<CR>",
            mode = { "n", "i" },
        },
        {
            "<M-j>",
            "<Cmd>TypstarSmartJump<CR>",
            mode = { "s", "i" },
        },
        {
            "<M-k>",
            "<Cmd>TypstarSmartJumpBack<CR>",
            mode = { "s", "i" },
        },
    },
    config = function()
        local typstar = require("typstar")
        typstar.setup({
            -- your typstar configuration
            add_undo_breakpoints = true,
        })
    end,
},
{
    "L3MON4D3/LuaSnip",
    version = "v2.*",
    build = "make install_jsregexp",
    config = function()
        local luasnip = require("luasnip")
        luasnip.config.setup({
            enable_autosnippets = true,
            cut_selection_keys = "<Tab>",
        })
    end,
},
{
    "nvim-treesitter/nvim-treesitter",
    build = ":TSUpdate",
    branch = "main",
    lazy = false,
    config = function()
        require('nvim-treesitter').install { "typst" }
    end
},

Snippets

  1. The snippets are designed to work with Typst 0.14. For older versions check out the legacy typst-0.13 branch.
  2. Install LuaSnip, set enable_autosnippets = true and set a visual mode selection key (e.g. cut_selection_keys = '<Tab>') in the configuration
  3. Install jsregexp as described here (You will see a warning on startup if jsregexp isn't installed properly)
  4. Install nvim-treesitter and run :TSInstall typst
  5. Make sure you haven't remapped <C-g>. Otherwise set add_undo_breakpoints = false in the config
  6. Optional: Setup ctheorems with names like here

Excalidraw

  1. Install Obsidian and create a vault in your typst note taking directory
  2. Install the obsidian-excalidraw-plugin and enable Auto-export SVG (in plugin settings at Embedding Excalidraw into your Notes and Exporting > Export Settings > Auto-export Settings)
  3. Have the xdg-open command working or set a different command at uriOpenCommand in the config
  4. If you encounter issues with the file creation of drawings, try cloning the repo into ~/typstar or setting the typstarRoot config accordingly; feel free to open an issue

Rnote

  1. Install Rnote; I recommend not using flatpak as that might cause issues with file permissions.
  2. Make sure rnote-cli is available in your PATH or set a different command at exportCommand in the config
  3. Have the xdg-open command working with Rnote files or set a different command at uriOpenCommand in the config
  4. See comment 4 above at Excalidraw

Anki

  1. Install Anki
  2. Install Anki-Connect and make sure http://localhost is added to webCorsOriginList in the Add-on config (should be added by default)
  3. Install the typstar python package (I recommend using uv via uv tool install typstar, using pipx should also work)
  4. Make sure the typstar-anki command is available in your PATH or modify the typstarAnkiCmd option in the config

Demo

A basic demo setup using either Nix or Lazy is provided. The keybindings are defined here.

For Nix: Run nix run github:arne314/typstar#nvim -- test.typ (~200MB download).

For Lazy: Clone the repo with git clone https://github.com/arne314/typstar.git and run just lazy if you have just installed or run ./res/lazy/lazy.sh test.typ if you don't. You will need to have nvim and tree-sitter available in your PATH.

In a Nix Flake (optional)

You can add typstar to your nix flake like so

# `flake.nix`
inputs = {
  # ... other inputs
  typstar = {
    url = "github:arne314/typstar";
    flake = false;
  };
}

Now you can use typstar in any package-set

with pkgs; [
  # ... other packages
  (pkgs.vimUtils.buildVimPlugin {
     name = "typstar";
     src = inputs.typstar; 
     buildInputs = with pkgs.vimPlugins; [
        luasnip
        nvim-treesitter-parsers.typst
     ];
  })
]

Configuration

Configuration options can be intuitively derived from the table here.

Excalidraw/Rnote templates

The templatePath option expects a table that maps file patterns to template locations. To for example have a specific template for lectures, you could configure it like this

templatePath = {
    { 'lectures/.*%.excalidraw%.md$', '~/Templates/lecture_excalidraw.excalidraw.md' }, -- path contains "lectures"
    { '%.excalidraw%.md$', '~/Templates/default_excalidraw.excalidraw.md' }, -- fallback
},

Custom snippets

The config allows you to

  • disable all snippets via snippets.enable = false
  • only include specific modules from the snippets folder via e.g. snippets.modules = { 'letters' }
  • exclude specific triggers via e.g. snippets.exclude = { 'dx', 'ddx' }
  • disable different behaviors of snippets from the visual module
    • visual selection via e.g. snippets.visual_disable = { 'br' }
    • normal snippets (absabs(1+1)) via e.g. snippets.visual_disable_normal = { 'abs' }
    • postfix snippets (xabsabs(x)) via e.g. snippets.visual_disable_postfix = { 'abs' }

For further customization you can make use of the provided wrappers from within your LuaSnip config. Let's say you prefer the short => arrow over the long ==> one and would like to change the ip trigger to imp. Your typstar config could look like

require('typstar').setup({
    snippets = {
        exclude = { 'ip' },
    },
})

while your LuaSnip typst.lua could look like this (< and > require escaping as <> introduces a new node)

local tp = require('typstar.autosnippets')
local snip = tp.snip
local math = tp.in_math
local markup = tp.in_markup

return {
    -- add a new snippet (the old one is excluded via the config)
    snip('imp', '=>> ', {}, math),

    -- override existing triggers by setting a high priority
    snip('ib', '<<= ', {}, math, 2000),
    snip('iff', '<<=>> ', {}, math, 2000),

    -- setup markup snippets accordingly
    snip('IMP', '$=>>$ ', {}, markup, 2000),
    snip('IFF', '$<<=>>$ ', {}, markup, 2000),
}

Contribution

Feel free to open an issue or a PR.

For development with Nix, a shell is provided, which you can enter via nix develop. Running nvim from within the shell will launch a minimal installation of the plugin, sourced at startup, so no additional nix build is needed. Tests can be executed using just test from within the shell or via nix flake check. The code can be linted using just lint.

For development without Nix, run just lazy for a local lazy installation which sources the plugin on startup. To run tests in lazy, run just test-lazy.

Run just --list for more details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typstar-1.6.0.tar.gz (12.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typstar-1.6.0-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file typstar-1.6.0.tar.gz.

File metadata

  • Download URL: typstar-1.6.0.tar.gz
  • Upload date:
  • Size: 12.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for typstar-1.6.0.tar.gz
Algorithm Hash digest
SHA256 6dbc64cd057445073db1f8360ba9cc6e270e5bc16d8f8d3a3f0923241164ed1b
MD5 0aedea4530952da77b46b7b11cd863e6
BLAKE2b-256 88f5bcb39f4ed1ed45038eb9300bb0184a30ae937c39561ea207ebd71a0ef6f7

See more details on using hashes here.

File details

Details for the file typstar-1.6.0-py3-none-any.whl.

File metadata

  • Download URL: typstar-1.6.0-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for typstar-1.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bfd58e805411a9196696957873935b566104512820f8b977834f69f73eadb5de
MD5 36cbc08fb745014da48885a5647d8d5b
BLAKE2b-256 032a18fa55d080ff7340711669ecaa5e2cb4409fa121c2b064141a152900be57

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page