Skip to content

emacsmirror/evil-tex-ts

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

evil-tex-ts

evil-tex-ts is a modern, tree-sitter based toolkit for LaTeX editing in Evil mode. It is a re-imagining of the classic evil-tex package, utilizing Emacs 29+ built-in tree-sitter capabilities for superior performance and accuracy.

Why a new package? The original `evil-tex` has not seen updates in years and relies on regular expressions for text object detection. This approach can be brittle, inaccurate in complex cases, and inefficient on large files. evil-tex-ts leverages the structural understanding of the `tree-sitter-latex` parser to provide precise text objects, efficient toggles, and robust surround integration.

Warning: Initial Release This is an early version of the package. While functional, it may contain bugs. Please report issues on GitHub.

Table of Contents

Showcase

| marks point.

Visual reference

   \foobar{barbaz}     \foobar{barbaz}    \foobar     \foobar    \foobar{}     \foobar{}
   └─────────────┘             └────┘     └─────┘            ┆   └───────┘             ┆
          ac                     ic         ac      ic (empty)      ac            ic (empty)

  ┌\begin{foobar}     \begin{foobar}
  │                  ┌
ae│ baz            ie│ baz
  │                  └
  └\end{foobar}       \end{foobar}

  \(foobar\)    \(foobar\)    \[foobar\]    \[foobar\]
  └────────┘      └────┘      └────────┘      └────┘
      am            im            am            im

  (foobar)    (foobar)    \left(foobar\right)    \left(foobar\right)  \Bigl(foobar\Bigr)    \Bigl(foobar\Bigr)
  └──────┘     └────┘     └─────────────────┘          └────┘         └────────────────┘          └────┘
     ad          id               ad                     id                   ad                    id

   ┌\section{foo}          \section{foo}
   │                      ┌
 aS│ baz                iS│ baz
   │\subsection*{}        │\subsection*{}
   └ qux                  └ qux
    \chapter*{bar}         \chapter*{bar}

   a^{foo}    a^{foo}    a^b    a^b    a^\bar    a^\bar
    └────┘       └─┘      └╵      ╵     └───┘      └──┘
      a^          i^      a^     i^      a^         i^

   a_{foo}    a_{foo}    a_b    a_b    a_\bar    a_\bar
    └────┘       └─┘      └╵      ╵     └───┘      └──┘
      a_          i_      a_     i_      a_         i_

   & foobar &    & foobar &    & foobar \\    & foobar \\
   └───────┘      └──────┘     └───────┘       └──────┘
       aT            iT            aT             iT

    `foobar'      `foobar'     ``foobar''     ``foobar''
    └──────┘       └────┘      └────────┘       └────┘
       aq            iq            aQ             iQ

Text object examples

  • die (delete inner environment)

    Before:

    \begin{equation}
      x^2 + y^2 = z^2|
    \end{equation}
        

    Press die

    After:

    \begin{equation}
    \end{equation}
        
  • cic (change inner command)

    Point can be anywhere inside the command:

    Before: \textbf{hel|lo}

    Press cic

    After: \textbf{|}

    Before: \tex|tbf{hello}

    Press cic

    After: \textbf{|}

    If point is outside a command, seeks the nearest command to the right on the same line:

    Before: s|ome text \textbf{hello}

    Press cic

    After: some text \textbf{|}

  • dam (delete around math)

    Before: \(x + y| = z\)

    Press dam

    After: (empty)

    If point is outside math, seeks the nearest math to the right on the same line:

    Before: some te|xt \(x + y\)

    Press dam

    After: some text|

  • viS (select inner section)

    Select the content of a section until the next section (excluding the \section{...} header).

    Before:

    \section{Introduction}
    This is the intro.|
    More text here.
    
    \section{Methods}
        

    Press viS

    After (selected region marked with ##):

    \section{Introduction}
    ##This is the intro.
    ##More text here.
    ##
    \section{Methods}
        

    The empty line before \section{Methods} is included. Use vaS to also include the \section{...} header.

Toggle examples

All toggle commands use the mt prefix by default (mnemonic: “magnificent toggle”).

Note: The mt prefix overrides the m (set-marker) command for the t character. You have 25 other marks available. To change this behavior, see User Options.

  • mte (toggle environment *)

    Toggle the asterisk on environments. Useful for switching between numbered and unnumbered equations.

    \begin{equation}|  →  \begin{equation*}
        

    Works with any environment:

    \begin{align}    ↔  \begin{align*}
    \begin{figure}   ↔  \begin{figure*}
    \begin{table}    ↔  \begin{table*}
        
  • mtm (toggle math mode)

    Toggle between inline and display math modes.

    \(x + y|\)  →  \[x + y\]  →  \(x + y\)
    $x + y|$    →  \[x + y\]  →  $x + y$
        

    The inline math format is controlled by evil-tex-ts-preferred-inline-math: dollar ($...$, default) or paren (\(...\)).

  • mtM (toggle math align)

    Toggle between display math and align* environment.

    Before:

    \[
      x + y|
    \]
        

    Press mtM

    After:

    \begin{align*}
      x + y
    \end{align*}
        

    Press mtM again

    \[
      x + y
    \]
        

    Also works starting from inline math (one-way to align*):

    Before: $x + |y$

    Press mtM

    After:

    \begin{align*}
      x + y
    \end{align*}
        

    Then toggles between align* and \[...\].

  • mtd (toggle delimiter sizing)

    Toggle automatic delimiter sizing with \left=/\right=.

    (x + y|)      ↔  \left(x + y\right)
    [a, b|]       ↔  \left[a, b\right]
    \{1, 2|\}     ↔  \left\{1, 2\right\}
        

    Also removes \bigl=/\bigr= and similar sizing commands (one-way):

    \bigl(x + y\bigr)   →  (x + y)
    \Bigl[a, b\Bigr]    →  [a, b]
        
  • mtc (toggle command *)

    Toggle the asterisk on commands. Useful for switching between numbered and unnumbered sections.

    \section{Title|}  →  \section*{Title}
        

    Works with various sectioning commands:

    \chapter{Title}      ↔  \chapter*{Title}
    \subsection{Title}   ↔  \subsection*{Title}
    \paragraph{Title}    ↔  \paragraph*{Title}
        
  • mtS (change section type)

    Change the type of the current section. A prompt appears with available section types.

    Before:

    \section{My Title|}
    Some content here.
        

    Press mtS, select subsection from prompt

    After:

    \subsection{My Title}
    Some content here.
        

    Available types: part, chapter, section, subsection, subsubsection, paragraph, subparagraph

Surround examples

Surround commands follow the evil-surround patterns:

  • ys<text-object><surround-type> — add surround (e.g., ysiwe wraps inner word with environment)
  • cs<old><new> — change surround (e.g., csee changes environment to environment)
  • ds<type> — delete surround (e.g., dsd deletes delimiter)

When <new> or <type> opens a keymap (like e for environment or d for delimiter), press the corresponding key to select (see Keymaps).

  • ysiwe (surround word with environment)

    Before: |word

    Press ysiwe, then type equation

    After:

    \begin{equation}
      word
    \end{equation}
        
  • Se (visual surround with environment)

    Before: |1 + 2

    Select the expression with v$ (or any visual selection), press S, then e for environment, then a for align (see Environment Keymap)

    After:

    \begin{align}
      1 + 2
    \end{align}
        

    Content is automatically indented inside the environment.

  • VjSeA (linewise surround multiple lines with environment)

    Before:

    |1 + 2
    3 + 4
        

    Vj selects both lines, S starts surround, e for environment, A for align*

    After:

    \begin{align*}
      1 + 2
      3 + 4
    \end{align*}
        
  • cseea (change environment to align)

    Before:

    \begin{equation}
      x^2 + y^2| = z^2
    \end{equation}
        

    Press cs (change surround), e (old: environment), e (new: environment keymap), a (align)

    After:

    \begin{align}
      x^2 + y^2 = z^2
    \end{align}
        
  • dsd (delete surrounding delimiter)

    Before: \left(x + y|\right)

    Press dsd

    After: |x + y

    Also works with simple delimiters:

    Before: (a + b|)

    Press dsd

    After: |a + b

Installation

Requirements

  • Emacs 29.1 or later (with tree-sitter support enabled)
  • evil
  • evil-surround (optional, but highly recommended)
  • A generic `tree-sitter-latex` grammar (usually installed via `M-x treesit-install-language-grammar`)

Setup

Since this package is not yet on MELPA, clone the repository and add it to your load-path.

Basic setup

(add-to-list 'load-path "/path/to/evil-tex-ts")
(require 'evil-tex-ts)

;; Hook into LaTeX modes
(add-hook 'latex-ts-mode-hook #'evil-tex-ts-mode)
(add-hook 'LaTeX-mode-hook #'evil-tex-ts-mode) ;; If using AUCTeX

With use-package

(use-package evil-tex-ts
  :load-path "/path/to/evil-tex-ts"  ; or use :straight, :elpaca, etc.
  :after (evil)
  :hook ((LaTeX-mode . evil-tex-ts-mode)
         (latex-mode . evil-tex-ts-mode))
  :init
  ;; Register tree-sitter grammar source
  (add-to-list 'treesit-language-source-alist
               '(latex "https://github.com/latex-lsp/tree-sitter-latex"))
  :config
  ;; Auto-install grammar if not available
  (unless (treesit-language-available-p 'latex)
    (treesit-install-language-grammar 'latex))

  ;; IMPORTANT: Set preferred inline math format
  ;; 'dollar for $...$ (default), 'paren for \(...\)
  (setq evil-tex-ts-preferred-inline-math 'dollar))

Important: The variable evil-tex-ts-preferred-inline-math controls which format is used when toggling math modes (mtm) and surrounding with inline math (m). Default value is 'dollar ($...$). Set to 'paren for \(...\).

Overview

Text Objects

This package defines precise text objects based on the AST:

KeyText Object TargetNotes
cLaTeX commands: \foo{...}Handles optional args [...] and nested braces
eEnvironments: \begin{...} ... \end{...}Selects proper range including newlines
mMath: \(...\), \[...\], $...$, environmentsDetects inline vs display math automatically
dDelimiters: (), [], \{\}, \left(\right)Handles balanced pairs
SSections: \section{...} to end of sectionHierarchical selection
^Superscripts: x^2, x^{...}
_Subscripts: x_i, x_{...}

Toggles

Default prefix is mt (“magnificent toggle”).

KeyBehaviourExample
mteToggle environment asterisk\begin{eq}\begin{eq*}
mtcToggle command asterisk\section\section*
mtmToggle math mode (inline ↔ display)\(...\)\[...\]
mtMToggle math align (display ↔ align*)\[...\]\begin{align*}...
mtdToggle delimiter sizing(x)\left(x\right)

Surround

If `evil-surround` is installed, `evil-tex-ts` adds specific surround pairs.

KeySurrounds withExample InputResult
cCommand (prompts)text\cmd{text}
eEnvironment (keymap)text\begin{env} text \end{env}
mInline mathtext\(text\) or $text$
MDisplay mathtext\[text\]
dDelimiter (keymap)text\left(text\right)
^Superscriptx^{x}
_Subscriptx_{x}
;CDLaTeX accents (keymap)x\bar{x}

See Keymaps for full keymaps.

Navigation

KeyCommandDescription
]]evil-tex-ts-go-forward-sectionJump to next section heading
[[evil-tex-ts-go-back-sectionJump to previous section heading

Works in both normal and visual modes. Recognizes chapter, section, subsection, etc.

Configuration

User Options

Customize these variables via M-x customize-group RET evil-tex-ts.

  • evil-tex-ts-select-newlines-with-envs (default: t)
    Include newlines when selecting/deleting environments. Makes dae remove the whole block cleanly.
  • evil-tex-ts-toggle-override-m (default: t)
    Bind toggles to mt. Set to nil to preserve the m marker key.
  • evil-tex-ts-toggle-override-t (default: nil)
    Bind toggles to ts (vimtex style). Can be used alongside or instead of mt.
  • evil-tex-ts-preferred-inline-math (default: 'dollar)
    Preferred format for inline math toggles: dollar ($...$) or paren (\(...\)).

Custom Surround Insertions

Add your own environments, accents, and delimiters using these functions:

;; Add "quote" environment on "q"
(evil-tex-ts-bind-to-env-map '(("q" . "quote")))

;; Add figure with default [!ht] position
(evil-tex-ts-bind-to-env-map '(("F" "\\begin{figure}[!ht]" . "\\end{figure}")))

;; Add custom accent
(evil-tex-ts-bind-to-cdlatex-accents-map '(("B" . "fbox")))

;; Add custom delimiter
(evil-tex-ts-bind-to-delim-map '(("h" "\\huge(" . "\\huge)")))

See docstrings of evil-tex-ts-bind-to-env-map for the complete format.

Custom Toggles

Bind your function to evil-tex-ts-toggle-map, it’s a normal keymap:

(define-key evil-tex-ts-toggle-map "x" #'my-custom-toggle-function)

Differences from evil-tex

Featureevil-tex (Original)evil-tex-ts (This package)
ParsingRegular ExpressionsTree-sitter (AST)
PerformanceSlower on large filesFast & Incremental
AccuracyCan be tricked by commentsRobust structural parsing
DependenciesEmacs 25+, AUCTeXEmacs 29+, tree-sitter grammar
MaintainabilityHarder (complex regex)Easier (standard grammar)

Acknowledgements

Appendix

Keymaps

Environment Keymap (e)

KeyEnvKeyEnv
xpromptmmultline
eequationMmultline*
Eequation*ccases
aalignztikzpicture
Aalign*ffigure
nalignatiitemize
Nalignat*Ienumerate
ggatherbframe
Ggather*yarray
lflalignreqnarray
Lflalign*

Theorem prefix (t)

Press t then the second key to select theorem-like environment.

Example: ysiwetd wraps word in \begin{definition}...\end{definition}

KeyEnvKeyEnv
taaxiomtllemma
tccorollarytpproof
tCclaimtqquestion
tddefinitiontrremark
teexamplestttheorem
tsexercise

Delimiter Keymap (d)

Uppercase = simple, lowercase = sized (\left~/\right~).

KeySimpleKeySized
P()p\left(\right)
S[]s\left[\right]
C\{\}c\left\{\right\}
R\langle\rangler\left\langle\right\rangle
V\lvert\rvertv\left\lvert\right\rvert
N\lVert\rVertn\left\lVert\right\rVert

CDLaTeX Accent Keymap (;)

Context sensitive: uses \mathbf in math, \textbf in text.

Math accents

KeyAccentKeyAccent
.dot:ddot
^hatHwidehat
~~~~tildeNwidetilde
-barToverline
vcheckubreve
>vec/grave
"acute_underline
{overbrace}underbrace
qsqrt

Text styles

KeyStyleKeyStyle
bbold (bf)rroman (rm)
iitalic (it)eemph
ytypewriter (tt)fsans-serif (sf)
lslanted (textsl)ccalligraphic
mmbox

Math size styles

Useful for controlling formula size, e.g. in fractions.

Example: ysiw;1 wraps word in {\displaystyle ...}

KeyStyle
0{\textstyle }
1{\displaystyle }
2{\scriptstyle }
3{\scriptscriptstyle }

About

Tree-sitter based LaTeX text objects for Evil

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •  

Packages

No packages published

Languages

  • Emacs Lisp 99.8%
  • Makefile 0.2%