helix-mirror/master/print.html

1960 lines
138 KiB
HTML
Raw Normal View History

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js colibri">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title></title>
<meta name="robots" content="noindex" />
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "colibri" : "colibri";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('colibri')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded affix "><a href="title-page.html">Helix</a></li><li class="chapter-item expanded "><a href="install.html"><strong aria-hidden="true">1.</strong> Installation</a></li><li class="chapter-item expanded "><a href="usage.html"><strong aria-hidden="true">2.</strong> Usage</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="keymap.html"><strong aria-hidden="true">2.1.</strong> Keymap</a></li><li class="chapter-item expanded "><a href="commands.html"><strong aria-hidden="true">2.2.</strong> Commands</a></li><li class="chapter-item expanded "><a href="lang-support.html"><strong aria-hidden="true">2.3.</strong> Language Support</a></li></ol></li><li class="chapter-item expanded "><a href="from-vim.html"><strong aria-hidden="true">3.</strong> Migrating from Vim</a></li><li class="chapter-item expanded "><a href="configuration.html"><strong aria-hidden="true">4.</strong> Configuration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="themes.html"><strong aria-hidden="true">4.1.</strong> Themes</a></li><li class="chapter-item expanded "><a href="remapping.html"><strong aria-hidden="true">4.2.</strong> Key Remapping</a></li><li class="chapter-item expanded "><a href="languages.html"><strong aria-hidden="true">4.3.</strong> Languages</a></li></ol></li><li class="chapter-item expanded "><a href="guides/index.html"><strong aria-hidden="true">5.</strong> Guides</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="guides/adding_languages.html"><strong aria-hidden="true">5.1.</strong> Adding Languages</a></li><li class="chapter-item expanded "><a href="guides/textobject.html"><strong aria-hidden="true">5.2.</strong> Adding Textobject Queries</a></li><li class="chapter-item expanded "><a href="guides/indent.html"><strong aria-hidden="true">5.3.</strong> Adding Indent Queries</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
<li role="none"><button role="menuitem" class="theme" id="colibri">Colibri (default)</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title"></h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h1 id="helix"><a class="header" href="#helix">Helix</a></h1>
<p>Docs for bleeding edge master can be found at
<a href="https://docs.helix-editor.com/master">https://docs.helix-editor.com/master</a>.</p>
<p>See the <a href="./usage.html">usage</a> section for a quick overview of the editor, <a href="./keymap.html">keymap</a>
section for all available keybindings and the <a href="./configuration.html">configuration</a> section
for defining custom keybindings, setting themes, etc.
For everything else (e.g., how to install supported language servers), see the <a href="https://github.com/helix-editor/helix/wiki">Helix Wiki</a>.</p>
<p>Refer the <a href="https://github.com/helix-editor/helix/wiki/FAQ">FAQ</a> for common questions.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="installation"><a class="header" href="#installation">Installation</a></h1>
<p>We provide pre-built binaries on the <a href="https://github.com/helix-editor/helix/releases">GitHub Releases page</a>.</p>
<p><a href="https://repology.org/project/helix/versions"><img src="https://repology.org/badge/vertical-allrepos/helix.svg" alt="Packaging status" /></a></p>
<h2 id="osx"><a class="header" href="#osx">OSX</a></h2>
<p>Helix is available in homebrew-core:</p>
<pre><code>brew install helix
</code></pre>
<h2 id="linux"><a class="header" href="#linux">Linux</a></h2>
<h3 id="nixos"><a class="header" href="#nixos">NixOS</a></h3>
<p>A <a href="https://nixos.wiki/wiki/Flakes">flake</a> containing the package is available in
the project root. The flake can also be used to spin up a reproducible development
shell for working on Helix with <code>nix develop</code>.</p>
<p>Flake outputs are cached for each push to master using
<a href="https://www.cachix.org/">Cachix</a>. The flake is configured to
automatically make use of this cache assuming the user accepts
the new settings on first use.</p>
<p>If you are using a version of Nix without flakes enabled you can
<a href="https://docs.cachix.org/installation">install Cachix cli</a>; <code>cachix use helix</code> will
configure Nix to use cached outputs when possible.</p>
<h3 id="arch-linux"><a class="header" href="#arch-linux">Arch Linux</a></h3>
<p>Releases are available in the <code>community</code> repository.</p>
<p>A <a href="https://aur.archlinux.org/packages/helix-git/">helix-git</a> package is also available on the AUR, which builds the master branch.</p>
<h3 id="fedora-linux"><a class="header" href="#fedora-linux">Fedora Linux</a></h3>
<p>You can install the COPR package for Helix via</p>
<pre><code>sudo dnf copr enable varlad/helix
sudo dnf install helix
</code></pre>
<h3 id="void-linux"><a class="header" href="#void-linux">Void Linux</a></h3>
<pre><code>sudo xbps-install helix
</code></pre>
<h2 id="windows"><a class="header" href="#windows">Windows</a></h2>
<p>Helix can be installed using <a href="https://scoop.sh/">Scoop</a>, <a href="https://chocolatey.org/">Chocolatey</a>
or <a href="https://msys2.org/">MSYS2</a>.</p>
<p><strong>Scoop:</strong></p>
<pre><code>scoop install helix
</code></pre>
<p><strong>Chocolatey:</strong></p>
<pre><code>choco install helix
</code></pre>
<p><strong>MSYS2:</strong></p>
<pre><code>pacman -S mingw-w64-i686-helix
</code></pre>
<p>or</p>
<pre><code>pacman -S mingw-w64-x86_64-helix
</code></pre>
<p>or</p>
<pre><code>pacman -S mingw-w64-ucrt-x86_64-helix
</code></pre>
<h2 id="build-from-source"><a class="header" href="#build-from-source">Build from source</a></h2>
<pre><code>git clone https://github.com/helix-editor/helix
cd helix
cargo install --path helix-term
</code></pre>
<p>This will install the <code>hx</code> binary to <code>$HOME/.cargo/bin</code> and build tree-sitter grammars in <code>./runtime/grammars</code>.</p>
<p>Helix also needs its runtime files so make sure to copy/symlink the <code>runtime/</code> directory into the
config directory (for example <code>~/.config/helix/runtime</code> on Linux/macOS). This location can be overridden
via the <code>HELIX_RUNTIME</code> environment variable.</p>
<div class="table-wrapper"><table><thead><tr><th>OS</th><th>Command</th></tr></thead><tbody>
<tr><td>Windows (Cmd)</td><td><code>xcopy /e /i runtime %AppData%\helix\runtime</code></td></tr>
<tr><td>Windows (PowerShell)</td><td><code>xcopy /e /i runtime $Env:AppData\helix\runtime</code></td></tr>
<tr><td>Linux / macOS</td><td><code>ln -s $PWD/runtime ~/.config/helix/runtime</code></td></tr>
</tbody></table>
</div>
<p>Starting with Windows Vista you can also create symbolic links on Windows. Note that this requires
elevated privileges - i.e. PowerShell or Cmd must be run as administrator.</p>
<p><strong>PowerShell:</strong></p>
<pre><code class="language-powershell">New-Item -ItemType SymbolicLink -Target &quot;runtime&quot; -Path &quot;$Env:AppData\helix\runtime&quot;
</code></pre>
<p><strong>Cmd:</strong></p>
<pre><code class="language-cmd">cd %appdata%\helix
mklink /D runtime &quot;&lt;helix-repo&gt;\runtime&quot;
</code></pre>
<p>The runtime location can be overridden via the <code>HELIX_RUNTIME</code> environment variable.</p>
<blockquote>
<p>NOTE: if <code>HELIX_RUNTIME</code> is set prior to calling <code>cargo install --path helix-term</code>,
tree-sitter grammars will be built in <code>$HELIX_RUNTIME/grammars</code>.</p>
</blockquote>
<p>If you plan on keeping the repo locally, an alternative to copying/symlinking
runtime files is to set <code>HELIX_RUNTIME=/path/to/helix/runtime</code>
(<code>HELIX_RUNTIME=$PWD/runtime</code> if you're in the helix repo directory).</p>
<p>To use Helix in desktop environments that supports <a href="https://specifications.freedesktop.org/menu-spec/menu-spec-latest.html">XDG desktop menu</a>, including Gnome and KDE, copy the provided <code>.desktop</code> file to the correct folder:</p>
<pre><code class="language-bash">cp contrib/Helix.desktop ~/.local/share/applications
</code></pre>
<p>To use another terminal than the default, you will need to modify the <code>.desktop</code> file. For example, to use <code>kitty</code>:</p>
<pre><code class="language-bash">sed -i &quot;s|Exec=hx %F|Exec=kitty hx %F|g&quot; ~/.local/share/applications/Helix.desktop
sed -i &quot;s|Terminal=true|Terminal=false|g&quot; ~/.local/share/applications/Helix.desktop
</code></pre>
<p>Please note: there is no icon for Helix yet, so the system default will be used.</p>
<h2 id="finishing-up-the-installation"><a class="header" href="#finishing-up-the-installation">Finishing up the installation</a></h2>
<p>To make sure everything is set up as expected you should finally run the helix healthcheck via</p>
<pre><code>hx --health
</code></pre>
<p>For more information on the information displayed in the health check results refer to <a href="https://github.com/helix-editor/helix/wiki/Healthcheck">Healthcheck</a>.</p>
<h3 id="building-tree-sitter-grammars"><a class="header" href="#building-tree-sitter-grammars">Building tree-sitter grammars</a></h3>
<p>Tree-sitter grammars must be fetched and compiled if not pre-packaged.
Fetch grammars with <code>hx --grammar fetch</code> (requires <code>git</code>) and compile them
with <code>hx --grammar build</code> (requires a C++ compiler).</p>
<h3 id="installing-language-servers"><a class="header" href="#installing-language-servers">Installing language servers</a></h3>
<p>Language servers can optionally be installed if you want their features (auto-complete, diagnostics etc.).
Follow the <a href="https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers">instructions on the wiki page</a> to add your language servers of choice.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="usage"><a class="header" href="#usage">Usage</a></h1>
<p>(Currently not fully documented, see the <a href="./keymap.html">keymappings</a> list for more.)</p>
<p>See <a href="https://github.com/helix-editor/helix/blob/master/runtime/tutor">tutor</a> (accessible via <code>hx --tutor</code> or <code>:tutor</code>) for a vimtutor-like introduction.</p>
<h2 id="registers"><a class="header" href="#registers">Registers</a></h2>
<p>Vim-like registers can be used to yank and store text to be pasted later. Usage is similar, with <code>&quot;</code> being used to select a register:</p>
<ul>
<li><code>&quot;ay</code> - Yank the current selection to register <code>a</code>.</li>
<li><code>&quot;op</code> - Paste the text in register <code>o</code> after the selection.</li>
</ul>
<p>If there is a selected register before invoking a change or delete command, the selection will be stored in the register and the action will be carried out:</p>
<ul>
<li><code>&quot;hc</code> - Store the selection in register <code>h</code> and then change it (delete and enter insert mode).</li>
<li><code>&quot;md</code> - Store the selection in register <code>m</code> and delete it.</li>
</ul>
<h3 id="special-registers"><a class="header" href="#special-registers">Special Registers</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Register character</th><th>Contains</th></tr></thead><tbody>
<tr><td><code>/</code></td><td>Last search</td></tr>
<tr><td><code>:</code></td><td>Last executed command</td></tr>
<tr><td><code>&quot;</code></td><td>Last yanked text</td></tr>
<tr><td><code>_</code></td><td>Black hole</td></tr>
</tbody></table>
</div>
<blockquote>
<p>There is no special register for copying to system clipboard, instead special commands and keybindings are provided. See the <a href="keymap.html#space-mode">keymap</a> for the specifics.
The black hole register works as a no-op register, meaning no data will be written to / read from it.</p>
</blockquote>
<h2 id="surround"><a class="header" href="#surround">Surround</a></h2>
<p>Functionality similar to <a href="https://github.com/tpope/vim-surround">vim-surround</a> is built into
helix. The keymappings have been inspired from <a href="https://github.com/machakann/vim-sandwich">vim-sandwich</a>:</p>
<p><img src="https://user-images.githubusercontent.com/23398472/122865801-97073180-d344-11eb-8142-8f43809982c6.gif" alt="surround demo" /></p>
<ul>
<li><code>ms</code> - Add surround characters</li>
<li><code>mr</code> - Replace surround characters</li>
<li><code>md</code> - Delete surround characters</li>
</ul>
<p><code>ms</code> acts on a selection, so select the text first and use <code>ms&lt;char&gt;</code>. <code>mr</code> and <code>md</code> work
on the closest pairs found and selections are not required; use counts to act in outer pairs.</p>
<p>It can also act on multiple selections (yay!). For example, to change every occurrence of <code>(use)</code> to <code>[use]</code>:</p>
<ul>
<li><code>%</code> to select the whole file</li>
<li><code>s</code> to split the selections on a search term</li>
<li>Input <code>use</code> and hit Enter</li>
<li><code>mr([</code> to replace the parens with square brackets</li>
</ul>
<p>Multiple characters are currently not supported, but planned.</p>
<h2 id="syntax-tree-motions"><a class="header" href="#syntax-tree-motions">Syntax-tree Motions</a></h2>
<p><code>Alt-p</code>, <code>Alt-o</code>, <code>Alt-i</code>, and <code>Alt-n</code> (or <code>Alt</code> and arrow keys) move the primary
selection according to the selection's place in the syntax tree. Let's walk
through an example to get familiar with them. Many languages have a syntax like
so for function calls:</p>
<pre><code>func(arg1, arg2, arg3)
</code></pre>
<p>A function call might be parsed by tree-sitter into a tree like the following.</p>
<pre><code class="language-tsq">(call
function: (identifier) ; func
arguments:
(arguments ; (arg1, arg2, arg3)
(identifier) ; arg1
(identifier) ; arg2
(identifier))) ; arg3
</code></pre>
<p>Use <code>:tree-sitter-subtree</code> to view the syntax tree of the primary selection. In
a more intuitive tree format:</p>
<pre><code> ┌────┐
│call│
┌─────┴────┴─────┐
│ │
┌─────▼────┐ ┌────▼────┐
│identifier│ │arguments│
&quot;func&quot; │ ┌────┴───┬─────┴───┐
└──────────┘ │ │ │
│ │ │
┌─────────▼┐ ┌────▼─────┐ ┌▼─────────┐
│identifier│ │identifier│ │identifier│
&quot;arg1&quot; │ │ &quot;arg2&quot; │ │ &quot;arg3&quot;
└──────────┘ └──────────┘ └──────────┘
</code></pre>
<p>Say we have a selection that wraps <code>arg1</code>. The selection is on the <code>arg1</code> leaf
in the tree above.</p>
<pre><code>func([arg1], arg2, arg3)
</code></pre>
<p>Using <code>Alt-n</code> would select the next sibling in the syntax tree: <code>arg2</code>.</p>
<pre><code>func(arg1, [arg2], arg3)
</code></pre>
<p>While <code>Alt-o</code> would expand the selection to the parent node. In the tree above we
can see that we would select the <code>arguments</code> node.</p>
<pre><code>func[(arg1, arg2, arg3)]
</code></pre>
<p>There is also some nuanced behavior that prevents you from getting stuck on a
node with no sibling. If we have a selection on <code>arg1</code>, <code>Alt-p</code> would bring us
to the previous child node. Since <code>arg1</code> doesn't have a sibling to its left,
though, we climb the syntax tree and then take the previous selection. So
<code>Alt-p</code> will move the selection over to the &quot;func&quot; <code>identifier</code>.</p>
<pre><code>[func](arg1, arg2, arg3)
</code></pre>
<h2 id="textobjects"><a class="header" href="#textobjects">Textobjects</a></h2>
<p><img src="https://user-images.githubusercontent.com/23398472/124231131-81a4bb00-db2d-11eb-9d10-8e577ca7b177.gif" alt="textobject-demo" />
<img src="https://user-images.githubusercontent.com/23398472/132537398-2a2e0a54-582b-44ab-a77f-eb818942203d.gif" alt="textobject-treesitter-demo" /></p>
<ul>
<li><code>ma</code> - Select around the object (<code>va</code> in Vim, <code>&lt;alt-a&gt;</code> in Kakoune)</li>
<li><code>mi</code> - Select inside the object (<code>vi</code> in Vim, <code>&lt;alt-i&gt;</code> in Kakoune)</li>
</ul>
<div class="table-wrapper"><table><thead><tr><th>Key after <code>mi</code> or <code>ma</code></th><th>Textobject selected</th></tr></thead><tbody>
<tr><td><code>w</code></td><td>Word</td></tr>
<tr><td><code>W</code></td><td>WORD</td></tr>
<tr><td><code>p</code></td><td>Paragraph</td></tr>
<tr><td><code>(</code>, <code>[</code>, <code>'</code>, etc</td><td>Specified surround pairs</td></tr>
<tr><td><code>m</code></td><td>Closest surround pair</td></tr>
<tr><td><code>f</code></td><td>Function</td></tr>
<tr><td><code>c</code></td><td>Class</td></tr>
<tr><td><code>a</code></td><td>Argument/parameter</td></tr>
<tr><td><code>o</code></td><td>Comment</td></tr>
<tr><td><code>t</code></td><td>Test</td></tr>
</tbody></table>
</div>
<blockquote>
<p>NOTE: <code>f</code>, <code>c</code>, etc need a tree-sitter grammar active for the current
document and a special tree-sitter query file to work properly. <a href="./lang-support.html">Only
some grammars</a> currently have the query file implemented.
Contributions are welcome!</p>
</blockquote>
<h2 id="tree-sitter-textobject-based-navigation"><a class="header" href="#tree-sitter-textobject-based-navigation">Tree-sitter Textobject Based Navigation</a></h2>
<p>Navigating between functions, classes, parameters, etc is made
possible by leveraging tree-sitter and textobjects queries. For
example to move to the next function use <code>]f</code>, to move to previous
class use <code>[c</code>, and so on.</p>
<p><img src="https://user-images.githubusercontent.com/23398472/152332550-7dfff043-36a2-4aec-b8f2-77c13eb56d6f.gif" alt="tree-sitter-nav-demo" /></p>
<p>See the <a href="./keymap.html#unimpaired">unimpaired</a> section of the keybind
documentation for the full reference.</p>
<blockquote>
<p>NOTE: This feature is dependent on tree-sitter based textobjects
and therefore requires the corresponding query file to work properly.</p>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="keymap"><a class="header" href="#keymap">Keymap</a></h1>
<ul>
<li><a href="keymap.html#normal-mode">Normal mode</a>
<ul>
<li><a href="keymap.html#movement">Movement</a></li>
<li><a href="keymap.html#changes">Changes</a>
<ul>
<li><a href="keymap.html#shell">Shell</a></li>
</ul>
</li>
<li><a href="keymap.html#selection-manipulation">Selection manipulation</a></li>
<li><a href="keymap.html#search">Search</a></li>
<li><a href="keymap.html#minor-modes">Minor modes</a>
<ul>
<li><a href="keymap.html#view-mode">View mode</a></li>
<li><a href="keymap.html#goto-mode">Goto mode</a></li>
<li><a href="keymap.html#match-mode">Match mode</a></li>
<li><a href="keymap.html#window-mode">Window mode</a></li>
<li><a href="keymap.html#space-mode">Space mode</a>
<ul>
<li><a href="keymap.html#popup">Popup</a></li>
</ul>
</li>
<li><a href="keymap.html#unimpaired">Unimpaired</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="keymap.html#insert-mode">Insert Mode</a></li>
<li><a href="keymap.html#select--extend-mode">Select / extend mode</a></li>
<li><a href="keymap.html#picker">Picker</a></li>
<li><a href="keymap.html#prompt">Prompt</a></li>
</ul>
<blockquote>
<p>💡 Mappings marked (<strong>LSP</strong>) require an active language server for the file.</p>
</blockquote>
<blockquote>
<p>💡 Mappings marked (<strong>TS</strong>) require a tree-sitter grammar for the filetype.</p>
</blockquote>
<h2 id="normal-mode"><a class="header" href="#normal-mode">Normal mode</a></h2>
<h3 id="movement"><a class="header" href="#movement">Movement</a></h3>
<blockquote>
<p>NOTE: Unlike Vim, <code>f</code>, <code>F</code>, <code>t</code> and <code>T</code> are not confined to the current line.</p>
</blockquote>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>h</code>, <code>Left</code></td><td>Move left</td><td><code>move_char_left</code></td></tr>
<tr><td><code>j</code>, <code>Down</code></td><td>Move down</td><td><code>move_line_down</code></td></tr>
<tr><td><code>k</code>, <code>Up</code></td><td>Move up</td><td><code>move_line_up</code></td></tr>
<tr><td><code>l</code>, <code>Right</code></td><td>Move right</td><td><code>move_char_right</code></td></tr>
<tr><td><code>w</code></td><td>Move next word start</td><td><code>move_next_word_start</code></td></tr>
<tr><td><code>b</code></td><td>Move previous word start</td><td><code>move_prev_word_start</code></td></tr>
<tr><td><code>e</code></td><td>Move next word end</td><td><code>move_next_word_end</code></td></tr>
<tr><td><code>W</code></td><td>Move next WORD start</td><td><code>move_next_long_word_start</code></td></tr>
<tr><td><code>B</code></td><td>Move previous WORD start</td><td><code>move_prev_long_word_start</code></td></tr>
<tr><td><code>E</code></td><td>Move next WORD end</td><td><code>move_next_long_word_end</code></td></tr>
<tr><td><code>t</code></td><td>Find 'till next char</td><td><code>find_till_char</code></td></tr>
<tr><td><code>f</code></td><td>Find next char</td><td><code>find_next_char</code></td></tr>
<tr><td><code>T</code></td><td>Find 'till previous char</td><td><code>till_prev_char</code></td></tr>
<tr><td><code>F</code></td><td>Find previous char</td><td><code>find_prev_char</code></td></tr>
<tr><td><code>G</code></td><td>Go to line number <code>&lt;n&gt;</code></td><td><code>goto_line</code></td></tr>
<tr><td><code>Alt-.</code></td><td>Repeat last motion (<code>f</code>, <code>t</code> or <code>m</code>)</td><td><code>repeat_last_motion</code></td></tr>
<tr><td><code>Home</code></td><td>Move to the start of the line</td><td><code>goto_line_start</code></td></tr>
<tr><td><code>End</code></td><td>Move to the end of the line</td><td><code>goto_line_end</code></td></tr>
<tr><td><code>Ctrl-b</code>, <code>PageUp</code></td><td>Move page up</td><td><code>page_up</code></td></tr>
<tr><td><code>Ctrl-f</code>, <code>PageDown</code></td><td>Move page down</td><td><code>page_down</code></td></tr>
<tr><td><code>Ctrl-u</code></td><td>Move half page up</td><td><code>half_page_up</code></td></tr>
<tr><td><code>Ctrl-d</code></td><td>Move half page down</td><td><code>half_page_down</code></td></tr>
<tr><td><code>Ctrl-i</code></td><td>Jump forward on the jumplist</td><td><code>jump_forward</code></td></tr>
<tr><td><code>Ctrl-o</code></td><td>Jump backward on the jumplist</td><td><code>jump_backward</code></td></tr>
<tr><td><code>Ctrl-s</code></td><td>Save the current selection to the jumplist</td><td><code>save_selection</code></td></tr>
</tbody></table>
</div>
<h3 id="changes"><a class="header" href="#changes">Changes</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>r</code></td><td>Replace with a character</td><td><code>replace</code></td></tr>
<tr><td><code>R</code></td><td>Replace with yanked text</td><td><code>replace_with_yanked</code></td></tr>
<tr><td><code>~</code></td><td>Switch case of the selected text</td><td><code>switch_case</code></td></tr>
<tr><td><code>`</code></td><td>Set the selected text to lower case</td><td><code>switch_to_lowercase</code></td></tr>
<tr><td><code>Alt-`</code></td><td>Set the selected text to upper case</td><td><code>switch_to_uppercase</code></td></tr>
<tr><td><code>i</code></td><td>Insert before selection</td><td><code>insert_mode</code></td></tr>
<tr><td><code>a</code></td><td>Insert after selection (append)</td><td><code>append_mode</code></td></tr>
<tr><td><code>I</code></td><td>Insert at the start of the line</td><td><code>insert_at_line_start</code></td></tr>
<tr><td><code>A</code></td><td>Insert at the end of the line</td><td><code>insert_at_line_end</code></td></tr>
<tr><td><code>o</code></td><td>Open new line below selection</td><td><code>open_below</code></td></tr>
<tr><td><code>O</code></td><td>Open new line above selection</td><td><code>open_above</code></td></tr>
<tr><td><code>.</code></td><td>Repeat last insert</td><td>N/A</td></tr>
<tr><td><code>u</code></td><td>Undo change</td><td><code>undo</code></td></tr>
<tr><td><code>U</code></td><td>Redo change</td><td><code>redo</code></td></tr>
<tr><td><code>Alt-u</code></td><td>Move backward in history</td><td><code>earlier</code></td></tr>
<tr><td><code>Alt-U</code></td><td>Move forward in history</td><td><code>later</code></td></tr>
<tr><td><code>y</code></td><td>Yank selection</td><td><code>yank</code></td></tr>
<tr><td><code>p</code></td><td>Paste after selection</td><td><code>paste_after</code></td></tr>
<tr><td><code>P</code></td><td>Paste before selection</td><td><code>paste_before</code></td></tr>
<tr><td><code>&quot;</code> <code>&lt;reg&gt;</code></td><td>Select a register to yank to or paste from</td><td><code>select_register</code></td></tr>
<tr><td><code>&gt;</code></td><td>Indent selection</td><td><code>indent</code></td></tr>
<tr><td><code>&lt;</code></td><td>Unindent selection</td><td><code>unindent</code></td></tr>
<tr><td><code>=</code></td><td>Format selection (currently nonfunctional/disabled) (<strong>LSP</strong>)</td><td><code>format_selections</code></td></tr>
<tr><td><code>d</code></td><td>Delete selection</td><td><code>delete_selection</code></td></tr>
<tr><td><code>Alt-d</code></td><td>Delete selection, without yanking</td><td><code>delete_selection_noyank</code></td></tr>
<tr><td><code>c</code></td><td>Change selection (delete and enter insert mode)</td><td><code>change_selection</code></td></tr>
<tr><td><code>Alt-c</code></td><td>Change selection (delete and enter insert mode, without yanking)</td><td><code>change_selection_noyank</code></td></tr>
<tr><td><code>Ctrl-a</code></td><td>Increment object (number) under cursor</td><td><code>increment</code></td></tr>
<tr><td><code>Ctrl-x</code></td><td>Decrement object (number) under cursor</td><td><code>decrement</code></td></tr>
<tr><td><code>Q</code></td><td>Start/stop macro recording to the selected register (experimental)</td><td><code>record_macro</code></td></tr>
<tr><td><code>q</code></td><td>Play back a recorded macro from the selected register (experimental)</td><td><code>replay_macro</code></td></tr>
</tbody></table>
</div>
<h4 id="shell"><a class="header" href="#shell">Shell</a></h4>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>|</code></td><td>Pipe each selection through shell command, replacing with output</td><td><code>shell_pipe</code></td></tr>
<tr><td><code>Alt-|</code></td><td>Pipe each selection into shell command, ignoring output</td><td><code>shell_pipe_to</code></td></tr>
<tr><td><code>!</code></td><td>Run shell command, inserting output before each selection</td><td><code>shell_insert_output</code></td></tr>
<tr><td><code>Alt-!</code></td><td>Run shell command, appending output after each selection</td><td><code>shell_append_output</code></td></tr>
<tr><td><code>$</code></td><td>Pipe each selection into shell command, keep selections where command returned 0</td><td><code>shell_keep_pipe</code></td></tr>
</tbody></table>
</div>
<h3 id="selection-manipulation"><a class="header" href="#selection-manipulation">Selection manipulation</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>s</code></td><td>Select all regex matches inside selections</td><td><code>select_regex</code></td></tr>
<tr><td><code>S</code></td><td>Split selection into subselections on regex matches</td><td><code>split_selection</code></td></tr>
<tr><td><code>Alt-s</code></td><td>Split selection on newlines</td><td><code>split_selection_on_newline</code></td></tr>
<tr><td><code>&amp;</code></td><td>Align selection in columns</td><td><code>align_selections</code></td></tr>
<tr><td><code>_</code></td><td>Trim whitespace from the selection</td><td><code>trim_selections</code></td></tr>
<tr><td><code>;</code></td><td>Collapse selection onto a single cursor</td><td><code>collapse_selection</code></td></tr>
<tr><td><code>Alt-;</code></td><td>Flip selection cursor and anchor</td><td><code>flip_selections</code></td></tr>
<tr><td><code>Alt-:</code></td><td>Ensures the selection is in forward direction</td><td><code>ensure_selections_forward</code></td></tr>
<tr><td><code>,</code></td><td>Keep only the primary selection</td><td><code>keep_primary_selection</code></td></tr>
<tr><td><code>Alt-,</code></td><td>Remove the primary selection</td><td><code>remove_primary_selection</code></td></tr>
<tr><td><code>C</code></td><td>Copy selection onto the next line (Add cursor below)</td><td><code>copy_selection_on_next_line</code></td></tr>
<tr><td><code>Alt-C</code></td><td>Copy selection onto the previous line (Add cursor above)</td><td><code>copy_selection_on_prev_line</code></td></tr>
<tr><td><code>(</code></td><td>Rotate main selection backward</td><td><code>rotate_selections_backward</code></td></tr>
<tr><td><code>)</code></td><td>Rotate main selection forward</td><td><code>rotate_selections_forward</code></td></tr>
<tr><td><code>Alt-(</code></td><td>Rotate selection contents backward</td><td><code>rotate_selection_contents_backward</code></td></tr>
<tr><td><code>Alt-)</code></td><td>Rotate selection contents forward</td><td><code>rotate_selection_contents_forward</code></td></tr>
<tr><td><code>%</code></td><td>Select entire file</td><td><code>select_all</code></td></tr>
<tr><td><code>x</code></td><td>Select current line, if already selected, extend to next line</td><td><code>extend_line_below</code></td></tr>
<tr><td><code>X</code></td><td>Extend selection to line bounds (line-wise selection)</td><td><code>extend_to_line_bounds</code></td></tr>
<tr><td><code>Alt-x</code></td><td>Shrink selection to line bounds (line-wise selection)</td><td><code>shrink_to_line_bounds</code></td></tr>
<tr><td><code>J</code></td><td>Join lines inside selection</td><td><code>join_selections</code></td></tr>
<tr><td><code>Alt-J</code></td><td>Join lines inside selection and select space</td><td><code>join_selections_space</code></td></tr>
<tr><td><code>K</code></td><td>Keep selections matching the regex</td><td><code>keep_selections</code></td></tr>
<tr><td><code>Alt-K</code></td><td>Remove selections matching the regex</td><td><code>remove_selections</code></td></tr>
<tr><td><code>Ctrl-c</code></td><td>Comment/uncomment the selections</td><td><code>toggle_comments</code></td></tr>
<tr><td><code>Alt-o</code>, <code>Alt-up</code></td><td>Expand selection to parent syntax node (<strong>TS</strong>)</td><td><code>expand_selection</code></td></tr>
<tr><td><code>Alt-i</code>, <code>Alt-down</code></td><td>Shrink syntax tree object selection (<strong>TS</strong>)</td><td><code>shrink_selection</code></td></tr>
<tr><td><code>Alt-p</code>, <code>Alt-left</code></td><td>Select previous sibling node in syntax tree (<strong>TS</strong>)</td><td><code>select_prev_sibling</code></td></tr>
<tr><td><code>Alt-n</code>, <code>Alt-right</code></td><td>Select next sibling node in syntax tree (<strong>TS</strong>)</td><td><code>select_next_sibling</code></td></tr>
</tbody></table>
</div>
<h3 id="search"><a class="header" href="#search">Search</a></h3>
<p>Search commands all operate on the <code>/</code> register by default. Use <code>&quot;&lt;char&gt;</code> to operate on a different one.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>/</code></td><td>Search for regex pattern</td><td><code>search</code></td></tr>
<tr><td><code>?</code></td><td>Search for previous pattern</td><td><code>rsearch</code></td></tr>
<tr><td><code>n</code></td><td>Select next search match</td><td><code>search_next</code></td></tr>
<tr><td><code>N</code></td><td>Select previous search match</td><td><code>search_prev</code></td></tr>
<tr><td><code>*</code></td><td>Use current selection as the search pattern</td><td><code>search_selection</code></td></tr>
</tbody></table>
</div>
<h3 id="minor-modes"><a class="header" href="#minor-modes">Minor modes</a></h3>
<p>These sub-modes are accessible from normal mode and typically switch back to normal mode after a command.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>v</code></td><td>Enter <a href="keymap.html#select--extend-mode">select (extend) mode</a></td><td><code>select_mode</code></td></tr>
<tr><td><code>g</code></td><td>Enter <a href="keymap.html#goto-mode">goto mode</a></td><td>N/A</td></tr>
<tr><td><code>m</code></td><td>Enter <a href="keymap.html#match-mode">match mode</a></td><td>N/A</td></tr>
<tr><td><code>:</code></td><td>Enter command mode</td><td><code>command_mode</code></td></tr>
<tr><td><code>z</code></td><td>Enter <a href="keymap.html#view-mode">view mode</a></td><td>N/A</td></tr>
<tr><td><code>Z</code></td><td>Enter sticky <a href="keymap.html#view-mode">view mode</a></td><td>N/A</td></tr>
<tr><td><code>Ctrl-w</code></td><td>Enter <a href="keymap.html#window-mode">window mode</a></td><td>N/A</td></tr>
<tr><td><code>Space</code></td><td>Enter <a href="keymap.html#space-mode">space mode</a></td><td>N/A</td></tr>
</tbody></table>
</div>
<h4 id="view-mode"><a class="header" href="#view-mode">View mode</a></h4>
<p>Accessed by typing <code>z</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>View mode is intended for scrolling and manipulating the view without changing
the selection. The &quot;sticky&quot; variant of this mode (accessed by typing <code>Z</code> in
normal mode) is persistent; use the Escape key to return to normal mode after
usage (useful when you're simply looking over text and not actively editing
it).</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>z</code>, <code>c</code></td><td>Vertically center the line</td><td><code>align_view_center</code></td></tr>
<tr><td><code>t</code></td><td>Align the line to the top of the screen</td><td><code>align_view_top</code></td></tr>
<tr><td><code>b</code></td><td>Align the line to the bottom of the screen</td><td><code>align_view_bottom</code></td></tr>
<tr><td><code>m</code></td><td>Align the line to the middle of the screen (horizontally)</td><td><code>align_view_middle</code></td></tr>
<tr><td><code>j</code>, <code>down</code></td><td>Scroll the view downwards</td><td><code>scroll_down</code></td></tr>
<tr><td><code>k</code>, <code>up</code></td><td>Scroll the view upwards</td><td><code>scroll_up</code></td></tr>
<tr><td><code>Ctrl-f</code>, <code>PageDown</code></td><td>Move page down</td><td><code>page_down</code></td></tr>
<tr><td><code>Ctrl-b</code>, <code>PageUp</code></td><td>Move page up</td><td><code>page_up</code></td></tr>
<tr><td><code>Ctrl-d</code></td><td>Move half page down</td><td><code>half_page_down</code></td></tr>
<tr><td><code>Ctrl-u</code></td><td>Move half page up</td><td><code>half_page_up</code></td></tr>
</tbody></table>
</div>
<h4 id="goto-mode"><a class="header" href="#goto-mode">Goto mode</a></h4>
<p>Accessed by typing <code>g</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>Jumps to various locations.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>g</code></td><td>Go to line number <code>&lt;n&gt;</code> else start of file</td><td><code>goto_file_start</code></td></tr>
<tr><td><code>e</code></td><td>Go to the end of the file</td><td><code>goto_last_line</code></td></tr>
<tr><td><code>f</code></td><td>Go to files in the selection</td><td><code>goto_file</code></td></tr>
<tr><td><code>h</code></td><td>Go to the start of the line</td><td><code>goto_line_start</code></td></tr>
<tr><td><code>l</code></td><td>Go to the end of the line</td><td><code>goto_line_end</code></td></tr>
<tr><td><code>s</code></td><td>Go to first non-whitespace character of the line</td><td><code>goto_first_nonwhitespace</code></td></tr>
<tr><td><code>t</code></td><td>Go to the top of the screen</td><td><code>goto_window_top</code></td></tr>
<tr><td><code>c</code></td><td>Go to the middle of the screen</td><td><code>goto_window_center</code></td></tr>
<tr><td><code>b</code></td><td>Go to the bottom of the screen</td><td><code>goto_window_bottom</code></td></tr>
<tr><td><code>d</code></td><td>Go to definition (<strong>LSP</strong>)</td><td><code>goto_definition</code></td></tr>
<tr><td><code>y</code></td><td>Go to type definition (<strong>LSP</strong>)</td><td><code>goto_type_definition</code></td></tr>
<tr><td><code>r</code></td><td>Go to references (<strong>LSP</strong>)</td><td><code>goto_reference</code></td></tr>
<tr><td><code>i</code></td><td>Go to implementation (<strong>LSP</strong>)</td><td><code>goto_implementation</code></td></tr>
<tr><td><code>a</code></td><td>Go to the last accessed/alternate file</td><td><code>goto_last_accessed_file</code></td></tr>
<tr><td><code>m</code></td><td>Go to the last modified/alternate file</td><td><code>goto_last_modified_file</code></td></tr>
<tr><td><code>n</code></td><td>Go to next buffer</td><td><code>goto_next_buffer</code></td></tr>
<tr><td><code>p</code></td><td>Go to previous buffer</td><td><code>goto_previous_buffer</code></td></tr>
<tr><td><code>.</code></td><td>Go to last modification in current file</td><td><code>goto_last_modification</code></td></tr>
</tbody></table>
</div>
<h4 id="match-mode"><a class="header" href="#match-mode">Match mode</a></h4>
<p>Accessed by typing <code>m</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>See the relevant section in <a href="./usage.html">Usage</a> for an explanation about
<a href="./usage.html#surround">surround</a> and <a href="./usage.html#textobjects">textobject</a> usage.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>m</code></td><td>Goto matching bracket (<strong>TS</strong>)</td><td><code>match_brackets</code></td></tr>
<tr><td><code>s</code> <code>&lt;char&gt;</code></td><td>Surround current selection with <code>&lt;char&gt;</code></td><td><code>surround_add</code></td></tr>
<tr><td><code>r</code> <code>&lt;from&gt;&lt;to&gt;</code></td><td>Replace surround character <code>&lt;from&gt;</code> with <code>&lt;to&gt;</code></td><td><code>surround_replace</code></td></tr>
<tr><td><code>d</code> <code>&lt;char&gt;</code></td><td>Delete surround character <code>&lt;char&gt;</code></td><td><code>surround_delete</code></td></tr>
<tr><td><code>a</code> <code>&lt;object&gt;</code></td><td>Select around textobject</td><td><code>select_textobject_around</code></td></tr>
<tr><td><code>i</code> <code>&lt;object&gt;</code></td><td>Select inside textobject</td><td><code>select_textobject_inner</code></td></tr>
</tbody></table>
</div>
<p>TODO: Mappings for selecting syntax nodes (a superset of <code>[</code>).</p>
<h4 id="window-mode"><a class="header" href="#window-mode">Window mode</a></h4>
<p>Accessed by typing <code>Ctrl-w</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>This layer is similar to Vim keybindings as Kakoune does not support window.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>w</code>, <code>Ctrl-w</code></td><td>Switch to next window</td><td><code>rotate_view</code></td></tr>
<tr><td><code>v</code>, <code>Ctrl-v</code></td><td>Vertical right split</td><td><code>vsplit</code></td></tr>
<tr><td><code>s</code>, <code>Ctrl-s</code></td><td>Horizontal bottom split</td><td><code>hsplit</code></td></tr>
<tr><td><code>f</code></td><td>Go to files in the selection in horizontal splits</td><td><code>goto_file</code></td></tr>
<tr><td><code>F</code></td><td>Go to files in the selection in vertical splits</td><td><code>goto_file</code></td></tr>
<tr><td><code>h</code>, <code>Ctrl-h</code>, <code>Left</code></td><td>Move to left split</td><td><code>jump_view_left</code></td></tr>
<tr><td><code>j</code>, <code>Ctrl-j</code>, <code>Down</code></td><td>Move to split below</td><td><code>jump_view_down</code></td></tr>
<tr><td><code>k</code>, <code>Ctrl-k</code>, <code>Up</code></td><td>Move to split above</td><td><code>jump_view_up</code></td></tr>
<tr><td><code>l</code>, <code>Ctrl-l</code>, <code>Right</code></td><td>Move to right split</td><td><code>jump_view_right</code></td></tr>
<tr><td><code>q</code>, <code>Ctrl-q</code></td><td>Close current window</td><td><code>wclose</code></td></tr>
<tr><td><code>o</code>, <code>Ctrl-o</code></td><td>Only keep the current window, closing all the others</td><td><code>wonly</code></td></tr>
<tr><td><code>H</code></td><td>Swap window to the left</td><td><code>swap_view_left</code></td></tr>
<tr><td><code>J</code></td><td>Swap window downwards</td><td><code>swap_view_down</code></td></tr>
<tr><td><code>K</code></td><td>Swap window upwards</td><td><code>swap_view_up</code></td></tr>
<tr><td><code>L</code></td><td>Swap window to the right</td><td><code>swap_view_right</code></td></tr>
</tbody></table>
</div>
<h4 id="space-mode"><a class="header" href="#space-mode">Space mode</a></h4>
<p>Accessed by typing <code>Space</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>This layer is a kludge of mappings, mostly pickers.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>f</code></td><td>Open file picker</td><td><code>file_picker</code></td></tr>
<tr><td><code>F</code></td><td>Open file picker at current working directory</td><td><code>file_picker_in_current_directory</code></td></tr>
<tr><td><code>b</code></td><td>Open buffer picker</td><td><code>buffer_picker</code></td></tr>
<tr><td><code>j</code></td><td>Open jumplist picker</td><td><code>jumplist_picker</code></td></tr>
<tr><td><code>k</code></td><td>Show documentation for item under cursor in a <a href="keymap.html#popup">popup</a> (<strong>LSP</strong>)</td><td><code>hover</code></td></tr>
<tr><td><code>s</code></td><td>Open document symbol picker (<strong>LSP</strong>)</td><td><code>symbol_picker</code></td></tr>
<tr><td><code>S</code></td><td>Open workspace symbol picker (<strong>LSP</strong>)</td><td><code>workspace_symbol_picker</code></td></tr>
<tr><td><code>d</code></td><td>Open document diagnostics picker (<strong>LSP</strong>)</td><td><code>diagnostics_picker</code></td></tr>
<tr><td><code>D</code></td><td>Open workspace diagnostics picker (<strong>LSP</strong>)</td><td><code>workspace_diagnostics_picker</code></td></tr>
<tr><td><code>r</code></td><td>Rename symbol (<strong>LSP</strong>)</td><td><code>rename_symbol</code></td></tr>
<tr><td><code>a</code></td><td>Apply code action (<strong>LSP</strong>)</td><td><code>code_action</code></td></tr>
<tr><td><code>'</code></td><td>Open last fuzzy picker</td><td><code>last_picker</code></td></tr>
<tr><td><code>w</code></td><td>Enter <a href="keymap.html#window-mode">window mode</a></td><td>N/A</td></tr>
<tr><td><code>p</code></td><td>Paste system clipboard after selections</td><td><code>paste_clipboard_after</code></td></tr>
<tr><td><code>P</code></td><td>Paste system clipboard before selections</td><td><code>paste_clipboard_before</code></td></tr>
<tr><td><code>y</code></td><td>Join and yank selections to clipboard</td><td><code>yank_joined_to_clipboard</code></td></tr>
<tr><td><code>Y</code></td><td>Yank main selection to clipboard</td><td><code>yank_main_selection_to_clipboard</code></td></tr>
<tr><td><code>R</code></td><td>Replace selections by clipboard contents</td><td><code>replace_selections_with_clipboard</code></td></tr>
<tr><td><code>/</code></td><td>Global search in workspace folder</td><td><code>global_search</code></td></tr>
<tr><td><code>?</code></td><td>Open command palette</td><td><code>command_palette</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p>TIP: Global search displays results in a fuzzy picker, use <code>Space + '</code> to bring it back up after opening a file.</p>
</blockquote>
<h5 id="popup"><a class="header" href="#popup">Popup</a></h5>
<p>Displays documentation for item under cursor.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>Ctrl-u</code></td><td>Scroll up</td></tr>
<tr><td><code>Ctrl-d</code></td><td>Scroll down</td></tr>
</tbody></table>
</div>
<h4 id="unimpaired"><a class="header" href="#unimpaired">Unimpaired</a></h4>
<p>Mappings in the style of <a href="https://github.com/tpope/vim-unimpaired">vim-unimpaired</a>.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>[d</code></td><td>Go to previous diagnostic (<strong>LSP</strong>)</td><td><code>goto_prev_diag</code></td></tr>
<tr><td><code>]d</code></td><td>Go to next diagnostic (<strong>LSP</strong>)</td><td><code>goto_next_diag</code></td></tr>
<tr><td><code>[D</code></td><td>Go to first diagnostic in document (<strong>LSP</strong>)</td><td><code>goto_first_diag</code></td></tr>
<tr><td><code>]D</code></td><td>Go to last diagnostic in document (<strong>LSP</strong>)</td><td><code>goto_last_diag</code></td></tr>
<tr><td><code>]f</code></td><td>Go to next function (<strong>TS</strong>)</td><td><code>goto_next_function</code></td></tr>
<tr><td><code>[f</code></td><td>Go to previous function (<strong>TS</strong>)</td><td><code>goto_prev_function</code></td></tr>
<tr><td><code>]c</code></td><td>Go to next class (<strong>TS</strong>)</td><td><code>goto_next_class</code></td></tr>
<tr><td><code>[c</code></td><td>Go to previous class (<strong>TS</strong>)</td><td><code>goto_prev_class</code></td></tr>
<tr><td><code>]a</code></td><td>Go to next argument/parameter (<strong>TS</strong>)</td><td><code>goto_next_parameter</code></td></tr>
<tr><td><code>[a</code></td><td>Go to previous argument/parameter (<strong>TS</strong>)</td><td><code>goto_prev_parameter</code></td></tr>
<tr><td><code>]o</code></td><td>Go to next comment (<strong>TS</strong>)</td><td><code>goto_next_comment</code></td></tr>
<tr><td><code>[o</code></td><td>Go to previous comment (<strong>TS</strong>)</td><td><code>goto_prev_comment</code></td></tr>
<tr><td><code>]t</code></td><td>Go to next test (<strong>TS</strong>)</td><td><code>goto_next_test</code></td></tr>
<tr><td><code>]t</code></td><td>Go to previous test (<strong>TS</strong>)</td><td><code>goto_prev_test</code></td></tr>
<tr><td><code>]p</code></td><td>Go to next paragraph</td><td><code>goto_next_paragraph</code></td></tr>
<tr><td><code>[p</code></td><td>Go to previous paragraph</td><td><code>goto_prev_paragraph</code></td></tr>
<tr><td><code>[Space</code></td><td>Add newline above</td><td><code>add_newline_above</code></td></tr>
<tr><td><code>]Space</code></td><td>Add newline below</td><td><code>add_newline_below</code></td></tr>
</tbody></table>
</div>
<h2 id="insert-mode"><a class="header" href="#insert-mode">Insert mode</a></h2>
<p>Insert mode bindings are somewhat minimal by default. Helix is designed to
be a modal editor, and this is reflected in the user experience and internal
mechanics. For example, changes to the text are only saved for undos when
escaping from insert mode to normal mode. For this reason, new users are
strongly encouraged to learn the modal editing paradigm to get the smoothest
experience.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>Escape</code></td><td>Switch to normal mode</td><td><code>normal_mode</code></td></tr>
<tr><td><code>Ctrl-s</code></td><td>Commit undo checkpoint</td><td><code>commit_undo_checkpoint</code></td></tr>
<tr><td><code>Ctrl-x</code></td><td>Autocomplete</td><td><code>completion</code></td></tr>
<tr><td><code>Ctrl-r</code></td><td>Insert a register content</td><td><code>insert_register</code></td></tr>
<tr><td><code>Ctrl-w</code>, <code>Alt-Backspace</code></td><td>Delete previous word</td><td><code>delete_word_backward</code></td></tr>
<tr><td><code>Alt-d</code>, <code>Alt-Delete</code></td><td>Delete next word</td><td><code>delete_word_forward</code></td></tr>
<tr><td><code>Ctrl-u</code></td><td>Delete to start of line</td><td><code>kill_to_line_start</code></td></tr>
<tr><td><code>Ctrl-k</code></td><td>Delete to end of line</td><td><code>kill_to_line_end</code></td></tr>
<tr><td><code>Ctrl-h</code>, <code>Backspace</code></td><td>Delete previous char</td><td><code>delete_char_backward</code></td></tr>
<tr><td><code>Ctrl-d</code>, <code>Delete</code></td><td>Delete next char</td><td><code>delete_char_forward</code></td></tr>
<tr><td><code>Ctrl-j</code>, <code>Enter</code></td><td>Insert new line</td><td><code>insert_newline</code></td></tr>
</tbody></table>
</div>
<p>These keys are not recommended, but are included for new users less familiar
with modal editors.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>Up</code></td><td>Move to previous line</td><td><code>move_line_up</code></td></tr>
<tr><td><code>Down</code></td><td>Move to next line</td><td><code>move_line_down</code></td></tr>
<tr><td><code>Left</code></td><td>Backward a char</td><td><code>move_char_left</code></td></tr>
<tr><td><code>Right</code></td><td>Forward a char</td><td><code>move_char_right</code></td></tr>
<tr><td><code>PageUp</code></td><td>Move one page up</td><td><code>page_up</code></td></tr>
<tr><td><code>PageDown</code></td><td>Move one page down</td><td><code>page_down</code></td></tr>
<tr><td><code>Home</code></td><td>Move to line start</td><td><code>goto_line_start</code></td></tr>
<tr><td><code>End</code></td><td>Move to line end</td><td><code>goto_line_end_newline</code></td></tr>
</tbody></table>
</div>
<p>If you want to disable them in insert mode as you become more comfortable with modal editing, you can use
the following in your <code>config.toml</code>:</p>
<pre><code class="language-toml">[keys.insert]
up = &quot;no_op&quot;
down = &quot;no_op&quot;
left = &quot;no_op&quot;
right = &quot;no_op&quot;
pageup = &quot;no_op&quot;
pagedown = &quot;no_op&quot;
home = &quot;no_op&quot;
end = &quot;no_op&quot;
</code></pre>
<h2 id="select--extend-mode"><a class="header" href="#select--extend-mode">Select / extend mode</a></h2>
<p>This mode echoes Normal mode, but changes any movements to extend
selections rather than replace them. Goto motions are also changed to
extend, so that <code>vgl</code> for example extends the selection to the end of
the line.</p>
<p>Search is also affected. By default, <code>n</code> and <code>N</code> will remove the current
selection and select the next instance of the search term. Toggling this
mode before pressing <code>n</code> or <code>N</code> makes it possible to keep the current
selection. Toggling it on and off during your iterative searching allows
you to selectively add search terms to your selections.</p>
<h2 id="picker"><a class="header" href="#picker">Picker</a></h2>
<p>Keys to use within picker. Remapping currently not supported.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>Shift-Tab</code>, <code>Up</code>, <code>Ctrl-p</code></td><td>Previous entry</td></tr>
<tr><td><code>Tab</code>, <code>Down</code>, <code>Ctrl-n</code></td><td>Next entry</td></tr>
<tr><td><code>PageUp</code>, <code>Ctrl-u</code></td><td>Page up</td></tr>
<tr><td><code>PageDown</code>, <code>Ctrl-d</code></td><td>Page down</td></tr>
<tr><td><code>Home</code></td><td>Go to first entry</td></tr>
<tr><td><code>End</code></td><td>Go to last entry</td></tr>
<tr><td><code>Enter</code></td><td>Open selected</td></tr>
<tr><td><code>Ctrl-s</code></td><td>Open horizontally</td></tr>
<tr><td><code>Ctrl-v</code></td><td>Open vertically</td></tr>
<tr><td><code>Ctrl-t</code></td><td>Toggle preview</td></tr>
<tr><td><code>Escape</code>, <code>Ctrl-c</code></td><td>Close picker</td></tr>
</tbody></table>
</div>
<h2 id="prompt"><a class="header" href="#prompt">Prompt</a></h2>
<p>Keys to use within prompt, Remapping currently not supported.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>Escape</code>, <code>Ctrl-c</code></td><td>Close prompt</td></tr>
<tr><td><code>Alt-b</code>, <code>Ctrl-Left</code></td><td>Backward a word</td></tr>
<tr><td><code>Ctrl-b</code>, <code>Left</code></td><td>Backward a char</td></tr>
<tr><td><code>Alt-f</code>, <code>Ctrl-Right</code></td><td>Forward a word</td></tr>
<tr><td><code>Ctrl-f</code>, <code>Right</code></td><td>Forward a char</td></tr>
<tr><td><code>Ctrl-e</code>, <code>End</code></td><td>Move prompt end</td></tr>
<tr><td><code>Ctrl-a</code>, <code>Home</code></td><td>Move prompt start</td></tr>
<tr><td><code>Ctrl-w</code>, <code>Alt-Backspace</code>, <code>Ctrl-Backspace</code></td><td>Delete previous word</td></tr>
<tr><td><code>Alt-d</code>, <code>Alt-Delete</code>, <code>Ctrl-Delete</code></td><td>Delete next word</td></tr>
<tr><td><code>Ctrl-u</code></td><td>Delete to start of line</td></tr>
<tr><td><code>Ctrl-k</code></td><td>Delete to end of line</td></tr>
<tr><td><code>Backspace</code>, <code>Ctrl-h</code></td><td>Delete previous char</td></tr>
<tr><td><code>Delete</code>, <code>Ctrl-d</code></td><td>Delete next char</td></tr>
<tr><td><code>Ctrl-s</code></td><td>Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later</td></tr>
<tr><td><code>Ctrl-p</code>, <code>Up</code></td><td>Select previous history</td></tr>
<tr><td><code>Ctrl-n</code>, <code>Down</code></td><td>Select next history</td></tr>
<tr><td><code>Ctrl-r</code></td><td>Insert the content of the register selected by following input char</td></tr>
<tr><td><code>Tab</code></td><td>Select next completion item</td></tr>
<tr><td><code>BackTab</code></td><td>Select previous completion item</td></tr>
<tr><td><code>Enter</code></td><td>Open selected</td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="commands"><a class="header" href="#commands">Commands</a></h1>
<p>Command mode can be activated by pressing <code>:</code>, similar to Vim. Built-in commands:</p>
<div class="table-wrapper"><table><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody>
<tr><td><code>:quit</code>, <code>:q</code></td><td>Close the current view.</td></tr>
<tr><td><code>:quit!</code>, <code>:q!</code></td><td>Force close the current view, ignoring unsaved changes.</td></tr>
<tr><td><code>:open</code>, <code>:o</code></td><td>Open a file from disk into the current view.</td></tr>
<tr><td><code>:buffer-close</code>, <code>:bc</code>, <code>:bclose</code></td><td>Close the current buffer.</td></tr>
<tr><td><code>:buffer-close!</code>, <code>:bc!</code>, <code>:bclose!</code></td><td>Close the current buffer forcefully, ignoring unsaved changes.</td></tr>
<tr><td><code>:buffer-close-others</code>, <code>:bco</code>, <code>:bcloseother</code></td><td>Close all buffers but the currently focused one.</td></tr>
<tr><td><code>:buffer-close-others!</code>, <code>:bco!</code>, <code>:bcloseother!</code></td><td>Force close all buffers but the currently focused one.</td></tr>
<tr><td><code>:buffer-close-all</code>, <code>:bca</code>, <code>:bcloseall</code></td><td>Close all buffers without quitting.</td></tr>
<tr><td><code>:buffer-close-all!</code>, <code>:bca!</code>, <code>:bcloseall!</code></td><td>Force close all buffers ignoring unsaved changes without quitting.</td></tr>
<tr><td><code>:buffer-next</code>, <code>:bn</code>, <code>:bnext</code></td><td>Goto next buffer.</td></tr>
<tr><td><code>:buffer-previous</code>, <code>:bp</code>, <code>:bprev</code></td><td>Goto previous buffer.</td></tr>
<tr><td><code>:write</code>, <code>:w</code></td><td>Write changes to disk. Accepts an optional path (:write some/path.txt)</td></tr>
<tr><td><code>:write!</code>, <code>:w!</code></td><td>Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write some/path.txt)</td></tr>
<tr><td><code>:new</code>, <code>:n</code></td><td>Create a new scratch buffer.</td></tr>
<tr><td><code>:format</code>, <code>:fmt</code></td><td>Format the file using the LSP formatter.</td></tr>
<tr><td><code>:indent-style</code></td><td>Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)</td></tr>
<tr><td><code>:line-ending</code></td><td>Set the document's default line ending. Options: crlf, lf.</td></tr>
<tr><td><code>:earlier</code>, <code>:ear</code></td><td>Jump back to an earlier point in edit history. Accepts a number of steps or a time span.</td></tr>
<tr><td><code>:later</code>, <code>:lat</code></td><td>Jump to a later point in edit history. Accepts a number of steps or a time span.</td></tr>
<tr><td><code>:write-quit</code>, <code>:wq</code>, <code>:x</code></td><td>Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt)</td></tr>
<tr><td><code>:write-quit!</code>, <code>:wq!</code>, <code>:x!</code></td><td>Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt)</td></tr>
<tr><td><code>:write-all</code>, <code>:wa</code></td><td>Write changes from all buffers to disk.</td></tr>
<tr><td><code>:write-quit-all</code>, <code>:wqa</code>, <code>:xa</code></td><td>Write changes from all buffers to disk and close all views.</td></tr>
<tr><td><code>:write-quit-all!</code>, <code>:wqa!</code>, <code>:xa!</code></td><td>Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes).</td></tr>
<tr><td><code>:quit-all</code>, <code>:qa</code></td><td>Close all views.</td></tr>
<tr><td><code>:quit-all!</code>, <code>:qa!</code></td><td>Force close all views ignoring unsaved changes.</td></tr>
<tr><td><code>:cquit</code>, <code>:cq</code></td><td>Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2).</td></tr>
<tr><td><code>:cquit!</code>, <code>:cq!</code></td><td>Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2).</td></tr>
<tr><td><code>:theme</code></td><td>Change the editor theme (show current theme if no name specified).</td></tr>
<tr><td><code>:clipboard-yank</code></td><td>Yank main selection into system clipboard.</td></tr>
<tr><td><code>:clipboard-yank-join</code></td><td>Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline.</td></tr>
<tr><td><code>:primary-clipboard-yank</code></td><td>Yank main selection into system primary clipboard.</td></tr>
<tr><td><code>:primary-clipboard-yank-join</code></td><td>Yank joined selections into system primary clipboard. A separator can be provided as first argument. Default value is newline.</td></tr>
<tr><td><code>:clipboard-paste-after</code></td><td>Paste system clipboard after selections.</td></tr>
<tr><td><code>:clipboard-paste-before</code></td><td>Paste system clipboard before selections.</td></tr>
<tr><td><code>:clipboard-paste-replace</code></td><td>Replace selections with content of system clipboard.</td></tr>
<tr><td><code>:primary-clipboard-paste-after</code></td><td>Paste primary clipboard after selections.</td></tr>
<tr><td><code>:primary-clipboard-paste-before</code></td><td>Paste primary clipboard before selections.</td></tr>
<tr><td><code>:primary-clipboard-paste-replace</code></td><td>Replace selections with content of system primary clipboard.</td></tr>
<tr><td><code>:show-clipboard-provider</code></td><td>Show clipboard provider name in status bar.</td></tr>
<tr><td><code>:change-current-directory</code>, <code>:cd</code></td><td>Change the current working directory.</td></tr>
<tr><td><code>:show-directory</code>, <code>:pwd</code></td><td>Show the current working directory.</td></tr>
<tr><td><code>:encoding</code></td><td>Set encoding. Based on <code>https://encoding.spec.whatwg.org</code>.</td></tr>
<tr><td><code>:reload</code></td><td>Discard changes and reload from the source file.</td></tr>
<tr><td><code>:reload-all</code></td><td>Discard changes and reload all documents from the source files.</td></tr>
<tr><td><code>:update</code></td><td>Write changes only if the file has been modified.</td></tr>
<tr><td><code>:lsp-workspace-command</code></td><td>Open workspace command picker</td></tr>
<tr><td><code>:lsp-restart</code></td><td>Restarts the Language Server that is in use by the current doc</td></tr>
<tr><td><code>:tree-sitter-scopes</code></td><td>Display tree sitter scopes, primarily for theming and development.</td></tr>
<tr><td><code>:debug-start</code>, <code>:dbg</code></td><td>Start a debug session from a given template with given parameters.</td></tr>
<tr><td><code>:debug-remote</code>, <code>:dbg-tcp</code></td><td>Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters.</td></tr>
<tr><td><code>:debug-eval</code></td><td>Evaluate expression in current debug context.</td></tr>
<tr><td><code>:vsplit</code>, <code>:vs</code></td><td>Open the file in a vertical split.</td></tr>
<tr><td><code>:vsplit-new</code>, <code>:vnew</code></td><td>Open a scratch buffer in a vertical split.</td></tr>
<tr><td><code>:hsplit</code>, <code>:hs</code>, <code>:sp</code></td><td>Open the file in a horizontal split.</td></tr>
<tr><td><code>:hsplit-new</code>, <code>:hnew</code></td><td>Open a scratch buffer in a horizontal split.</td></tr>
<tr><td><code>:tutor</code></td><td>Open the tutorial.</td></tr>
<tr><td><code>:goto</code>, <code>:g</code></td><td>Goto line number.</td></tr>
<tr><td><code>:set-language</code>, <code>:lang</code></td><td>Set the language of current buffer.</td></tr>
<tr><td><code>:set-option</code>, <code>:set</code></td><td>Set a config option at runtime.<br>For example to disable smart case search, use <code>:set search.smart-case false</code>.</td></tr>
<tr><td><code>:get-option</code>, <code>:get</code></td><td>Get the current value of a config option.</td></tr>
<tr><td><code>:sort</code></td><td>Sort ranges in selection.</td></tr>
<tr><td><code>:rsort</code></td><td>Sort ranges in selection in reverse order.</td></tr>
<tr><td><code>:reflow</code></td><td>Hard-wrap the current selection of lines to a given width.</td></tr>
<tr><td><code>:tree-sitter-subtree</code>, <code>:ts-subtree</code></td><td>Display tree sitter subtree under cursor, primarily for debugging queries.</td></tr>
<tr><td><code>:config-reload</code></td><td>Refresh user config.</td></tr>
<tr><td><code>:config-open</code></td><td>Open the user config.toml file.</td></tr>
<tr><td><code>:log-open</code></td><td>Open the helix log file.</td></tr>
<tr><td><code>:insert-output</code></td><td>Run shell command, inserting output before each selection.</td></tr>
<tr><td><code>:append-output</code></td><td>Run shell command, appending output after each selection.</td></tr>
<tr><td><code>:pipe</code></td><td>Pipe each selection to the shell command.</td></tr>
<tr><td><code>:run-shell-command</code>, <code>:sh</code></td><td>Run a shell command</td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="language-support"><a class="header" href="#language-support">Language Support</a></h1>
<p>The following languages and Language Servers are supported. In order to use
Language Server features, you must first <a href="https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers">install</a> the
appropriate Language Server.</p>
<p>Check the language support in your installed helix version with <code>hx --health</code>.</p>
<p>Also see the <a href="./languages.html">Language Configuration</a> docs and the <a href="./guides/adding_languages.html">Adding
Languages</a> guide for more language configuration information.</p>
<div class="table-wrapper"><table><thead><tr><th>Language</th><th>Syntax Highlighting</th><th>Treesitter Textobjects</th><th>Auto Indent</th><th>Default LSP</th></tr></thead><tbody>
<tr><td>astro</td><td></td><td></td><td></td><td></td></tr>
<tr><td>awk</td><td></td><td></td><td></td><td><code>awk-language-server</code></td></tr>
<tr><td>bash</td><td></td><td></td><td></td><td><code>bash-language-server</code></td></tr>
<tr><td>bass</td><td></td><td></td><td></td><td><code>bass</code></td></tr>
<tr><td>beancount</td><td></td><td></td><td></td><td></td></tr>
<tr><td>bicep</td><td></td><td></td><td></td><td><code>bicep-langserver</code></td></tr>
<tr><td>c</td><td></td><td></td><td></td><td><code>clangd</code></td></tr>
<tr><td>c-sharp</td><td></td><td></td><td></td><td><code>OmniSharp</code></td></tr>
<tr><td>cairo</td><td></td><td></td><td></td><td></td></tr>
<tr><td>clojure</td><td></td><td></td><td></td><td><code>clojure-lsp</code></td></tr>
<tr><td>cmake</td><td></td><td></td><td></td><td><code>cmake-language-server</code></td></tr>
<tr><td>comment</td><td></td><td></td><td></td><td></td></tr>
<tr><td>cpon</td><td></td><td></td><td></td><td></td></tr>
<tr><td>cpp</td><td></td><td></td><td></td><td><code>clangd</code></td></tr>
<tr><td>css</td><td></td><td></td><td></td><td><code>vscode-css-language-server</code></td></tr>
<tr><td>cue</td><td></td><td></td><td></td><td><code>cuelsp</code></td></tr>
<tr><td>d</td><td></td><td></td><td></td><td><code>serve-d</code></td></tr>
<tr><td>dart</td><td></td><td></td><td></td><td><code>dart</code></td></tr>
<tr><td>devicetree</td><td></td><td></td><td></td><td></td></tr>
<tr><td>diff</td><td></td><td></td><td></td><td></td></tr>
<tr><td>dockerfile</td><td></td><td></td><td></td><td><code>docker-langserver</code></td></tr>
<tr><td>dot</td><td></td><td></td><td></td><td><code>dot-language-server</code></td></tr>
<tr><td>edoc</td><td></td><td></td><td></td><td></td></tr>
<tr><td>eex</td><td></td><td></td><td></td><td></td></tr>
<tr><td>ejs</td><td></td><td></td><td></td><td></td></tr>
<tr><td>elixir</td><td></td><td></td><td></td><td><code>elixir-ls</code></td></tr>
<tr><td>elm</td><td></td><td></td><td></td><td><code>elm-language-server</code></td></tr>
<tr><td>elvish</td><td></td><td></td><td></td><td><code>elvish</code></td></tr>
<tr><td>env</td><td></td><td></td><td></td><td></td></tr>
<tr><td>erb</td><td></td><td></td><td></td><td></td></tr>
<tr><td>erlang</td><td></td><td></td><td></td><td><code>erlang_ls</code></td></tr>
<tr><td>esdl</td><td></td><td></td><td></td><td></td></tr>
<tr><td>fish</td><td></td><td></td><td></td><td></td></tr>
<tr><td>fortran</td><td></td><td></td><td></td><td><code>fortls</code></td></tr>
<tr><td>gdscript</td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-attributes</td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-commit</td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-config</td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-ignore</td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-rebase</td><td></td><td></td><td></td><td></td></tr>
<tr><td>gleam</td><td></td><td></td><td></td><td><code>gleam</code></td></tr>
<tr><td>glsl</td><td></td><td></td><td></td><td></td></tr>
<tr><td>go</td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>godot-resource</td><td></td><td></td><td></td><td></td></tr>
<tr><td>gomod</td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>gotmpl</td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>gowork</td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>graphql</td><td></td><td></td><td></td><td></td></tr>
<tr><td>hare</td><td></td><td></td><td></td><td></td></tr>
<tr><td>haskell</td><td></td><td></td><td></td><td><code>haskell-language-server-wrapper</code></td></tr>
<tr><td>hcl</td><td></td><td></td><td></td><td><code>terraform-ls</code></td></tr>
<tr><td>heex</td><td></td><td></td><td></td><td><code>elixir-ls</code></td></tr>
<tr><td>html</td><td></td><td></td><td></td><td><code>vscode-html-language-server</code></td></tr>
<tr><td>idris</td><td></td><td></td><td></td><td><code>idris2-lsp</code></td></tr>
<tr><td>iex</td><td></td><td></td><td></td><td></td></tr>
<tr><td>ini</td><td></td><td></td><td></td><td></td></tr>
<tr><td>java</td><td></td><td></td><td></td><td><code>jdtls</code></td></tr>
<tr><td>javascript</td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>jsdoc</td><td></td><td></td><td></td><td></td></tr>
<tr><td>json</td><td></td><td></td><td></td><td><code>vscode-json-language-server</code></td></tr>
<tr><td>jsonnet</td><td></td><td></td><td></td><td><code>jsonnet-language-server</code></td></tr>
<tr><td>jsx</td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>julia</td><td></td><td></td><td></td><td><code>julia</code></td></tr>
<tr><td>kdl</td><td></td><td></td><td></td><td></td></tr>
<tr><td>kotlin</td><td></td><td></td><td></td><td><code>kotlin-language-server</code></td></tr>
<tr><td>latex</td><td></td><td></td><td></td><td><code>texlab</code></td></tr>
<tr><td>lean</td><td></td><td></td><td></td><td><code>lean</code></td></tr>
<tr><td>ledger</td><td></td><td></td><td></td><td></td></tr>
<tr><td>llvm</td><td></td><td></td><td></td><td></td></tr>
<tr><td>llvm-mir</td><td></td><td></td><td></td><td></td></tr>
<tr><td>llvm-mir-yaml</td><td></td><td></td><td></td><td></td></tr>
<tr><td>lua</td><td></td><td></td><td></td><td><code>lua-language-server</code></td></tr>
<tr><td>make</td><td></td><td></td><td></td><td></td></tr>
<tr><td>markdown</td><td></td><td></td><td></td><td><code>marksman</code></td></tr>
<tr><td>markdown.inline</td><td></td><td></td><td></td><td></td></tr>
<tr><td>meson</td><td></td><td></td><td></td><td></td></tr>
<tr><td>mint</td><td></td><td></td><td></td><td><code>mint</code></td></tr>
<tr><td>nickel</td><td></td><td></td><td></td><td><code>nls</code></td></tr>
<tr><td>nix</td><td></td><td></td><td></td><td><code>nil</code></td></tr>
<tr><td>nu</td><td></td><td></td><td></td><td></td></tr>
<tr><td>ocaml</td><td></td><td></td><td></td><td><code>ocamllsp</code></td></tr>
<tr><td>ocaml-interface</td><td></td><td></td><td></td><td><code>ocamllsp</code></td></tr>
<tr><td>odin</td><td></td><td></td><td></td><td><code>ols</code></td></tr>
<tr><td>openscad</td><td></td><td></td><td></td><td><code>openscad-lsp</code></td></tr>
<tr><td>org</td><td></td><td></td><td></td><td></td></tr>
<tr><td>pascal</td><td></td><td></td><td></td><td><code>pasls</code></td></tr>
<tr><td>perl</td><td></td><td></td><td></td><td></td></tr>
<tr><td>php</td><td></td><td></td><td></td><td><code>intelephense</code></td></tr>
<tr><td>prisma</td><td></td><td></td><td></td><td><code>prisma-language-server</code></td></tr>
<tr><td>prolog</td><td></td><td></td><td></td><td><code>swipl</code></td></tr>
<tr><td>protobuf</td><td></td><td></td><td></td><td></td></tr>
<tr><td>purescript</td><td></td><td></td><td></td><td><code>purescript-language-server</code></td></tr>
<tr><td>python</td><td></td><td></td><td></td><td><code>pylsp</code></td></tr>
<tr><td>qml</td><td></td><td></td><td></td><td><code>qmlls</code></td></tr>
<tr><td>r</td><td></td><td></td><td></td><td><code>R</code></td></tr>
<tr><td>racket</td><td></td><td></td><td></td><td><code>racket</code></td></tr>
<tr><td>regex</td><td></td><td></td><td></td><td></td></tr>
<tr><td>rescript</td><td></td><td></td><td></td><td><code>rescript-language-server</code></td></tr>
<tr><td>rmarkdown</td><td></td><td></td><td></td><td><code>R</code></td></tr>
<tr><td>ron</td><td></td><td></td><td></td><td></td></tr>
<tr><td>ruby</td><td></td><td></td><td></td><td><code>solargraph</code></td></tr>
<tr><td>rust</td><td></td><td></td><td></td><td><code>rust-analyzer</code></td></tr>
<tr><td>scala</td><td></td><td></td><td></td><td><code>metals</code></td></tr>
<tr><td>scheme</td><td></td><td></td><td></td><td></td></tr>
<tr><td>scss</td><td></td><td></td><td></td><td><code>vscode-css-language-server</code></td></tr>
<tr><td>slint</td><td></td><td></td><td></td><td><code>slint-lsp</code></td></tr>
<tr><td>sml</td><td></td><td></td><td></td><td></td></tr>
<tr><td>solidity</td><td></td><td></td><td></td><td><code>solc</code></td></tr>
<tr><td>sql</td><td></td><td></td><td></td><td></td></tr>
<tr><td>sshclientconfig</td><td></td><td></td><td></td><td></td></tr>
<tr><td>starlark</td><td></td><td></td><td></td><td></td></tr>
<tr><td>svelte</td><td></td><td></td><td></td><td><code>svelteserver</code></td></tr>
<tr><td>swift</td><td></td><td></td><td></td><td><code>sourcekit-lsp</code></td></tr>
<tr><td>tablegen</td><td></td><td></td><td></td><td></td></tr>
<tr><td>task</td><td></td><td></td><td></td><td></td></tr>
<tr><td>tfvars</td><td></td><td></td><td></td><td><code>terraform-ls</code></td></tr>
<tr><td>toml</td><td></td><td></td><td></td><td><code>taplo</code></td></tr>
<tr><td>tsq</td><td></td><td></td><td></td><td></td></tr>
<tr><td>tsx</td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>twig</td><td></td><td></td><td></td><td></td></tr>
<tr><td>typescript</td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>ungrammar</td><td></td><td></td><td></td><td></td></tr>
<tr><td>v</td><td></td><td></td><td></td><td><code>vls</code></td></tr>
<tr><td>vala</td><td></td><td></td><td></td><td><code>vala-language-server</code></td></tr>
<tr><td>verilog</td><td></td><td></td><td></td><td><code>svlangserver</code></td></tr>
<tr><td>vhs</td><td></td><td></td><td></td><td></td></tr>
<tr><td>vue</td><td></td><td></td><td></td><td><code>vls</code></td></tr>
<tr><td>wast</td><td></td><td></td><td></td><td></td></tr>
<tr><td>wat</td><td></td><td></td><td></td><td></td></tr>
<tr><td>wgsl</td><td></td><td></td><td></td><td><code>wgsl_analyzer</code></td></tr>
<tr><td>wit</td><td></td><td></td><td></td><td></td></tr>
<tr><td>xit</td><td></td><td></td><td></td><td></td></tr>
<tr><td>xml</td><td></td><td></td><td></td><td></td></tr>
<tr><td>yaml</td><td></td><td></td><td></td><td><code>yaml-language-server</code></td></tr>
<tr><td>zig</td><td></td><td></td><td></td><td><code>zls</code></td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="migrating-from-vim"><a class="header" href="#migrating-from-vim">Migrating from Vim</a></h1>
<p>Helix's editing model is strongly inspired from Vim and Kakoune, and a notable
difference from Vim (and the most striking similarity to Kakoune) is that Helix
follows the <code>selection → action</code> model. This means that the whatever you are
going to act on (a word, a paragraph, a line, etc) is selected first and the
action itself (delete, change, yank, etc) comes second. A cursor is simply a
single width selection.</p>
<p>See also Kakoune's <a href="https://github.com/mawww/kakoune/wiki/Migrating-from-Vim">Migrating from Vim</a> and Helix's <a href="https://github.com/helix-editor/helix/wiki/Migrating-from-Vim">Migrating from Vim</a>.</p>
<blockquote>
<p>TODO: Mention textobjects, surround, registers</p>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="configuration"><a class="header" href="#configuration">Configuration</a></h1>
<p>To override global configuration parameters, create a <code>config.toml</code> file located in your config directory:</p>
<ul>
<li>Linux and Mac: <code>~/.config/helix/config.toml</code></li>
<li>Windows: <code>%AppData%\helix\config.toml</code></li>
</ul>
<blockquote>
<p>Hint: You can easily open the config file by typing <code>:config-open</code> within Helix normal mode.</p>
</blockquote>
<p>Example config:</p>
<pre><code class="language-toml">theme = &quot;onedark&quot;
[editor]
line-number = &quot;relative&quot;
mouse = false
[editor.cursor-shape]
insert = &quot;bar&quot;
normal = &quot;block&quot;
select = &quot;underline&quot;
[editor.file-picker]
hidden = false
</code></pre>
<p>You may also specify a file to use for configuration with the <code>-c</code> or
<code>--config</code> CLI argument: <code>hx -c path/to/custom-config.toml</code>.</p>
<p>It is also possible to trigger configuration file reloading by sending the <code>USR1</code>
signal to the helix process, e.g. via <code>pkill -USR1 hx</code>. This is only supported
on unix operating systems.</p>
<h2 id="editor"><a class="header" href="#editor">Editor</a></h2>
<h3 id="editor-section"><a class="header" href="#editor-section"><code>[editor]</code> Section</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>scrolloff</code></td><td>Number of lines of padding around the edge of the screen when scrolling.</td><td><code>5</code></td></tr>
<tr><td><code>mouse</code></td><td>Enable mouse mode.</td><td><code>true</code></td></tr>
<tr><td><code>middle-click-paste</code></td><td>Middle click paste support.</td><td><code>true</code></td></tr>
<tr><td><code>scroll-lines</code></td><td>Number of lines to scroll per scroll wheel step.</td><td><code>3</code></td></tr>
<tr><td><code>shell</code></td><td>Shell to use when running external commands.</td><td>Unix: <code>[&quot;sh&quot;, &quot;-c&quot;]</code><br/>Windows: <code>[&quot;cmd&quot;, &quot;/C&quot;]</code></td></tr>
<tr><td><code>line-number</code></td><td>Line number display: <code>absolute</code> simply shows each line's number, while <code>relative</code> shows the distance from the current line. When unfocused or in insert mode, <code>relative</code> will still show absolute line numbers.</td><td><code>absolute</code></td></tr>
<tr><td><code>cursorline</code></td><td>Highlight all lines with a cursor.</td><td><code>false</code></td></tr>
<tr><td><code>cursorcolumn</code></td><td>Highlight all columns with a cursor.</td><td><code>false</code></td></tr>
<tr><td><code>gutters</code></td><td>Gutters to display: Available are <code>diagnostics</code> and <code>line-numbers</code> and <code>spacer</code>, note that <code>diagnostics</code> also includes other features like breakpoints, 1-width padding will be inserted if gutters is non-empty</td><td><code>[&quot;diagnostics&quot;, &quot;spacer&quot;, &quot;line-numbers&quot;]</code></td></tr>
<tr><td><code>auto-completion</code></td><td>Enable automatic pop up of auto-completion.</td><td><code>true</code></td></tr>
<tr><td><code>auto-format</code></td><td>Enable automatic formatting on save.</td><td><code>true</code></td></tr>
<tr><td><code>auto-save</code></td><td>Enable automatic saving on focus moving away from Helix. Requires <a href="https://github.com/helix-editor/helix/wiki/Terminal-Support">focus event support</a> from your terminal.</td><td><code>false</code></td></tr>
<tr><td><code>idle-timeout</code></td><td>Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant.</td><td><code>400</code></td></tr>
<tr><td><code>completion-trigger-len</code></td><td>The min-length of word under cursor to trigger autocompletion</td><td><code>2</code></td></tr>
<tr><td><code>auto-info</code></td><td>Whether to display infoboxes</td><td><code>true</code></td></tr>
<tr><td><code>true-color</code></td><td>Set to <code>true</code> to override automatic detection of terminal truecolor support in the event of a false negative.</td><td><code>false</code></td></tr>
<tr><td><code>rulers</code></td><td>List of column positions at which to display the rulers. Can be overridden by language specific <code>rulers</code> in <code>languages.toml</code> file.</td><td><code>[]</code></td></tr>
<tr><td><code>bufferline</code></td><td>Renders a line at the top of the editor displaying open buffers. Can be <code>always</code>, <code>never</code> or <code>multiple</code> (only shown if more than one buffer is in use)</td><td><code>never</code></td></tr>
<tr><td><code>color-modes</code></td><td>Whether to color the mode indicator with different colors depending on the mode itself</td><td><code>false</code></td></tr>
</tbody></table>
</div>
<h3 id="editorstatusline-section"><a class="header" href="#editorstatusline-section"><code>[editor.statusline]</code> Section</a></h3>
<p>Allows configuring the statusline at the bottom of the editor.</p>
<p>The configuration distinguishes between three areas of the status line:</p>
<p><code>[ ... ... LEFT ... ... | ... ... ... ... CENTER ... ... ... ... | ... ... RIGHT ... ... ]</code></p>
<p>Statusline elements can be defined as follows:</p>
<pre><code class="language-toml">[editor.statusline]
left = [&quot;mode&quot;, &quot;spinner&quot;]
center = [&quot;file-name&quot;]
right = [&quot;diagnostics&quot;, &quot;selections&quot;, &quot;position&quot;, &quot;file-encoding&quot;, &quot;file-line-ending&quot;, &quot;file-type&quot;]
separator = &quot;&quot;
mode.normal = &quot;NORMAL&quot;
mode.insert = &quot;INSERT&quot;
mode.select = &quot;SELECT&quot;
</code></pre>
<p>The <code>[editor.statusline]</code> key takes the following sub-keys:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>left</code></td><td>A list of elements aligned to the left of the statusline</td><td><code>[&quot;mode&quot;, &quot;spinner&quot;, &quot;file-name&quot;]</code></td></tr>
<tr><td><code>center</code></td><td>A list of elements aligned to the middle of the statusline</td><td><code>[]</code></td></tr>
<tr><td><code>right</code></td><td>A list of elements aligned to the right of the statusline</td><td><code>[&quot;diagnostics&quot;, &quot;selections&quot;, &quot;position&quot;, &quot;file-encoding&quot;]</code></td></tr>
<tr><td><code>separator</code></td><td>The character used to separate elements in the statusline</td><td><code>&quot;&quot;</code></td></tr>
<tr><td><code>mode.normal</code></td><td>The text shown in the <code>mode</code> element for normal mode</td><td><code>&quot;NOR&quot;</code></td></tr>
<tr><td><code>mode.insert</code></td><td>The text shown in the <code>mode</code> element for insert mode</td><td><code>&quot;INS&quot;</code></td></tr>
<tr><td><code>mode.select</code></td><td>The text shown in the <code>mode</code> element for select mode</td><td><code>&quot;SEL&quot;</code></td></tr>
</tbody></table>
</div>
<p>The following statusline elements can be configured:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>mode</code></td><td>The current editor mode (<code>mode.normal</code>/<code>mode.insert</code>/<code>mode.select</code>)</td></tr>
<tr><td><code>spinner</code></td><td>A progress spinner indicating LSP activity</td></tr>
<tr><td><code>file-name</code></td><td>The path/name of the opened file</td></tr>
<tr><td><code>file-encoding</code></td><td>The encoding of the opened file if it differs from UTF-8</td></tr>
<tr><td><code>file-line-ending</code></td><td>The file line endings (CRLF or LF)</td></tr>
<tr><td><code>total-line-numbers</code></td><td>The total line numbers of the opened file</td></tr>
<tr><td><code>file-type</code></td><td>The type of the opened file</td></tr>
<tr><td><code>diagnostics</code></td><td>The number of warnings and/or errors</td></tr>
<tr><td><code>workspace-diagnostics</code></td><td>The number of warnings and/or errors on workspace</td></tr>
<tr><td><code>selections</code></td><td>The number of active selections</td></tr>
<tr><td><code>primary-selection-length</code></td><td>The number of characters currently in primary selection</td></tr>
<tr><td><code>position</code></td><td>The cursor position</td></tr>
<tr><td><code>position-percentage</code></td><td>The cursor position as a percentage of the total number of lines</td></tr>
<tr><td><code>separator</code></td><td>The string defined in <code>editor.statusline.separator</code> (defaults to <code>&quot;&quot;</code>)</td></tr>
<tr><td><code>spacer</code></td><td>Inserts a space between elements (multiple/contiguous spacers may be specified)</td></tr>
</tbody></table>
</div>
<h3 id="editorlsp-section"><a class="header" href="#editorlsp-section"><code>[editor.lsp]</code> Section</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>display-messages</code></td><td>Display LSP progress messages below statusline<sup class="footnote-reference"><a href="#1">1</a></sup></td><td><code>false</code></td></tr>
<tr><td><code>auto-signature-help</code></td><td>Enable automatic popup of signature help (parameter hints)</td><td><code>true</code></td></tr>
<tr><td><code>display-signature-help-docs</code></td><td>Display docs under signature help popup</td><td><code>true</code></td></tr>
</tbody></table>
</div>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>By default, a progress spinner is shown in the statusline beside the file path.</p>
</div>
<h3 id="editorcursor-shape-section"><a class="header" href="#editorcursor-shape-section"><code>[editor.cursor-shape]</code> Section</a></h3>
<p>Defines the shape of cursor in each mode. Note that due to limitations
of the terminal environment, only the primary cursor can change shape.
Valid values for these options are <code>block</code>, <code>bar</code>, <code>underline</code>, or <code>hidden</code>.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>normal</code></td><td>Cursor shape in <a href="./keymap.html#normal-mode">normal mode</a></td><td><code>block</code></td></tr>
<tr><td><code>insert</code></td><td>Cursor shape in <a href="./keymap.html#insert-mode">insert mode</a></td><td><code>block</code></td></tr>
<tr><td><code>select</code></td><td>Cursor shape in <a href="./keymap.html#select--extend-mode">select mode</a></td><td><code>block</code></td></tr>
</tbody></table>
</div>
<h3 id="editorfile-picker-section"><a class="header" href="#editorfile-picker-section"><code>[editor.file-picker]</code> Section</a></h3>
<p>Sets options for file picker and global search. All but the last key listed in
the default file-picker configuration below are IgnoreOptions: whether hidden
files and files listed within ignore files are ignored by (not visible in) the
helix file picker and global search. There is also one other key, <code>max-depth</code>
available, which is not defined by default.</p>
<p>All git related options are only enabled in a git repository.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>hidden</code></td><td>Enables ignoring hidden files.</td><td>true</td></tr>
<tr><td><code>parents</code></td><td>Enables reading ignore files from parent directories.</td><td>true</td></tr>
<tr><td><code>ignore</code></td><td>Enables reading <code>.ignore</code> files.</td><td>true</td></tr>
<tr><td><code>git-ignore</code></td><td>Enables reading <code>.gitignore</code> files.</td><td>true</td></tr>
<tr><td><code>git-global</code></td><td>Enables reading global .gitignore, whose path is specified in git's config: <code>core.excludefile</code> option.</td><td>true</td></tr>
<tr><td><code>git-exclude</code></td><td>Enables reading <code>.git/info/exclude</code> files.</td><td>true</td></tr>
<tr><td><code>max-depth</code></td><td>Set with an integer value for maximum depth to recurse.</td><td>Defaults to <code>None</code>.</td></tr>
</tbody></table>
</div>
<h3 id="editorauto-pairs-section"><a class="header" href="#editorauto-pairs-section"><code>[editor.auto-pairs]</code> Section</a></h3>
<p>Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a
simple boolean value, or a specific mapping of pairs of single characters.</p>
<p>To disable auto-pairs altogether, set <code>auto-pairs</code> to <code>false</code>:</p>
<pre><code class="language-toml">[editor]
auto-pairs = false # defaults to `true`
</code></pre>
<p>The default pairs are <code>(){}[]''&quot;&quot;``</code>, but these can be customized by
setting <code>auto-pairs</code> to a TOML table:</p>
<pre><code class="language-toml">[editor.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'&quot;' = '&quot;'
'`' = '`'
'&lt;' = '&gt;'
</code></pre>
<p>Additionally, this setting can be used in a language config. Unless
the editor setting is <code>false</code>, this will override the editor config in
documents with this language.</p>
<p>Example <code>languages.toml</code> that adds &lt;&gt; and removes ''</p>
<pre><code class="language-toml">[[language]]
name = &quot;rust&quot;
[language.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'&quot;' = '&quot;'
'`' = '`'
'&lt;' = '&gt;'
</code></pre>
<h3 id="editorsearch-section"><a class="header" href="#editorsearch-section"><code>[editor.search]</code> Section</a></h3>
<p>Search specific options.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>smart-case</code></td><td>Enable smart case regex searching (case insensitive unless pattern contains upper case characters)</td><td><code>true</code></td></tr>
<tr><td><code>wrap-around</code></td><td>Whether the search should wrap after depleting the matches</td><td><code>true</code></td></tr>
</tbody></table>
</div>
<h3 id="editorwhitespace-section"><a class="header" href="#editorwhitespace-section"><code>[editor.whitespace]</code> Section</a></h3>
<p>Options for rendering whitespace with visible characters. Use <code>:set whitespace.render all</code> to temporarily enable visible whitespace.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>render</code></td><td>Whether to render whitespace. May either be <code>&quot;all&quot;</code> or <code>&quot;none&quot;</code>, or a table with sub-keys <code>space</code>, <code>tab</code>, and <code>newline</code>.</td><td><code>&quot;none&quot;</code></td></tr>
<tr><td><code>characters</code></td><td>Literal characters to use when rendering whitespace. Sub-keys may be any of <code>tab</code>, <code>space</code>, <code>nbsp</code>, <code>newline</code> or <code>tabpad</code></td><td>See example below</td></tr>
</tbody></table>
</div>
<p>Example</p>
<pre><code class="language-toml">[editor.whitespace]
render = &quot;all&quot;
# or control each character
[editor.whitespace.render]
space = &quot;all&quot;
tab = &quot;all&quot;
newline = &quot;none&quot;
[editor.whitespace.characters]
space = &quot;·&quot;
nbsp = &quot;&quot;
tab = &quot;&quot;
newline = &quot;&quot;
tabpad = &quot;·&quot; # Tabs will look like &quot;→···&quot; (depending on tab width)
</code></pre>
<h3 id="editorindent-guides-section"><a class="header" href="#editorindent-guides-section"><code>[editor.indent-guides]</code> Section</a></h3>
<p>Options for rendering vertical indent guides.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>render</code></td><td>Whether to render indent guides.</td><td><code>false</code></td></tr>
<tr><td><code>character</code></td><td>Literal character to use for rendering the indent guide</td><td><code></code></td></tr>
<tr><td><code>skip-levels</code></td><td>Number of indent levels to skip</td><td><code>0</code></td></tr>
</tbody></table>
</div>
<p>Example:</p>
<pre><code class="language-toml">[editor.indent-guides]
render = true
character = &quot;&quot; # Some characters that work well: &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;
skip-levels = 1
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="themes"><a class="header" href="#themes">Themes</a></h1>
<p>To use a theme add <code>theme = &quot;&lt;name&gt;&quot;</code> to your <a href="./configuration.html"><code>config.toml</code></a> at the very top of the file before the first section or select it during runtime using <code>:theme &lt;name&gt;</code>.</p>
<h2 id="creating-a-theme"><a class="header" href="#creating-a-theme">Creating a theme</a></h2>
<p>Create a file with the name of your theme as file name (i.e <code>mytheme.toml</code>) and place it in your <code>themes</code> directory (i.e <code>~/.config/helix/themes</code>). The directory might have to be created beforehand.</p>
<p>The names &quot;default&quot; and &quot;base16_default&quot; are reserved for the builtin themes and cannot be overridden by user defined themes.</p>
<p>The default theme.toml can be found <a href="https://github.com/helix-editor/helix/blob/master/theme.toml">here</a>, and user submitted themes <a href="https://github.com/helix-editor/helix/blob/master/runtime/themes">here</a>. </p>
<p>Each line in the theme file is specified as below:</p>
<pre><code class="language-toml">key = { fg = &quot;#ffffff&quot;, bg = &quot;#000000&quot;, underline = { color = &quot;#ff0000&quot;, style = &quot;curl&quot;}, modifiers = [&quot;bold&quot;, &quot;italic&quot;] }
</code></pre>
<p>where <code>key</code> represents what you want to style, <code>fg</code> specifies the foreground color, <code>bg</code> the background color, <code>underline</code> the underline <code>style</code>/<code>color</code>, and <code>modifiers</code> is a list of style modifiers. <code>bg</code>, <code>underline</code> and <code>modifiers</code> can be omitted to defer to the defaults.</p>
<p>To specify only the foreground color:</p>
<pre><code class="language-toml">key = &quot;#ffffff&quot;
</code></pre>
<p>if the key contains a dot <code>'.'</code>, it must be quoted to prevent it being parsed as a <a href="https://toml.io/en/v1.0.0#keys">dotted key</a>.</p>
<pre><code class="language-toml">&quot;key.key&quot; = &quot;#ffffff&quot;
</code></pre>
<h3 id="color-palettes"><a class="header" href="#color-palettes">Color palettes</a></h3>
<p>It's recommended define a palette of named colors, and refer to them from the
configuration values in your theme. To do this, add a table called
<code>palette</code> to your theme file:</p>
<pre><code class="language-toml">&quot;ui.background&quot; = &quot;white&quot;
&quot;ui.text&quot; = &quot;black&quot;
[palette]
white = &quot;#ffffff&quot;
black = &quot;#000000&quot;
</code></pre>
<p>Remember that the <code>[palette]</code> table includes all keys after its header,
so you should define the palette after normal theme options.</p>
<p>The default palette uses the terminal's default 16 colors, and the colors names
are listed below. The <code>[palette]</code> section in the config file takes precedence
over it and is merged into the default palette.</p>
<div class="table-wrapper"><table><thead><tr><th>Color Name</th></tr></thead><tbody>
<tr><td><code>black</code></td></tr>
<tr><td><code>red</code></td></tr>
<tr><td><code>green</code></td></tr>
<tr><td><code>yellow</code></td></tr>
<tr><td><code>blue</code></td></tr>
<tr><td><code>magenta</code></td></tr>
<tr><td><code>cyan</code></td></tr>
<tr><td><code>gray</code></td></tr>
<tr><td><code>light-red</code></td></tr>
<tr><td><code>light-green</code></td></tr>
<tr><td><code>light-yellow</code></td></tr>
<tr><td><code>light-blue</code></td></tr>
<tr><td><code>light-magenta</code></td></tr>
<tr><td><code>light-cyan</code></td></tr>
<tr><td><code>light-gray</code></td></tr>
<tr><td><code>white</code></td></tr>
</tbody></table>
</div>
<h3 id="modifiers"><a class="header" href="#modifiers">Modifiers</a></h3>
<p>The following values may be used as modifiers. </p>
<p>Less common modifiers might not be supported by your terminal emulator.</p>
<div class="table-wrapper"><table><thead><tr><th>Modifier</th></tr></thead><tbody>
<tr><td><code>bold</code></td></tr>
<tr><td><code>dim</code></td></tr>
<tr><td><code>italic</code></td></tr>
<tr><td><code>underlined</code></td></tr>
<tr><td><code>slow_blink</code></td></tr>
<tr><td><code>rapid_blink</code></td></tr>
<tr><td><code>reversed</code></td></tr>
<tr><td><code>hidden</code></td></tr>
<tr><td><code>crossed_out</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p>Note: The <code>underlined</code> modifier is deprecated and only available for backwards compatibility.
Its behavior is equivalent to setting <code>underline.style=&quot;line&quot;</code>.</p>
</blockquote>
<h3 id="underline-style"><a class="header" href="#underline-style">Underline Style</a></h3>
<p>One of the following values may be used as a value for <code>underline.style</code>. </p>
<p>Some styles might not be supported by your terminal emulator.</p>
<div class="table-wrapper"><table><thead><tr><th>Modifier</th></tr></thead><tbody>
<tr><td><code>line</code></td></tr>
<tr><td><code>curl</code></td></tr>
<tr><td><code>dashed</code></td></tr>
<tr><td><code>dot</code></td></tr>
<tr><td><code>double_line</code></td></tr>
</tbody></table>
</div>
<h3 id="inheritance"><a class="header" href="#inheritance">Inheritance</a></h3>
<p>Extend upon other themes by setting the <code>inherits</code> property to an existing theme.</p>
<pre><code class="language-toml">inherits = &quot;boo_berry&quot;
# Override the theming for &quot;keyword&quot;s:
&quot;keyword&quot; = { fg = &quot;gold&quot; }
# Override colors in the palette:
[palette]
berry = &quot;#2A2A4D&quot;
</code></pre>
<h3 id="scopes"><a class="header" href="#scopes">Scopes</a></h3>
<p>The following is a list of scopes available to use for styling.</p>
<h4 id="syntax-highlighting"><a class="header" href="#syntax-highlighting">Syntax highlighting</a></h4>
<p>These keys match <a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#theme">tree-sitter scopes</a>.</p>
<p>For a given highlight produced, styling will be determined based on the longest matching theme key. For example, the highlight <code>function.builtin.static</code> would match the key <code>function.builtin</code> rather than <code>function</code>.</p>
<p>We use a similar set of scopes as
<a href="https://www.sublimetext.com/docs/scope_naming.html">SublimeText</a>. See also
<a href="https://macromates.com/manual/en/language_grammars">TextMate</a> scopes.</p>
<ul>
<li>
<p><code>attribute</code> - Class attributes, html tag attributes</p>
</li>
<li>
<p><code>type</code> - Types</p>
<ul>
<li><code>builtin</code> - Primitive types provided by the language (<code>int</code>, <code>usize</code>)</li>
</ul>
</li>
<li>
<p><code>constructor</code></p>
</li>
<li>
<p><code>constant</code> (TODO: constant.other.placeholder for %v)</p>
<ul>
<li><code>builtin</code> Special constants provided by the language (<code>true</code>, <code>false</code>, <code>nil</code> etc)
<ul>
<li><code>boolean</code></li>
</ul>
</li>
<li><code>character</code>
<ul>
<li><code>escape</code></li>
</ul>
</li>
<li><code>numeric</code> (numbers)
<ul>
<li><code>integer</code></li>
<li><code>float</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>string</code> (TODO: string.quoted.{single, double}, string.raw/.unquoted)?</p>
<ul>
<li><code>regexp</code> - Regular expressions</li>
<li><code>special</code>
<ul>
<li><code>path</code></li>
<li><code>url</code></li>
<li><code>symbol</code> - Erlang/Elixir atoms, Ruby symbols, Clojure keywords</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>comment</code> - Code comments</p>
<ul>
<li><code>line</code> - Single line comments (<code>//</code>)</li>
<li><code>block</code> - Block comments (e.g. (<code>/* */</code>)
<ul>
<li><code>documentation</code> - Documentation comments (e.g. <code>///</code> in Rust)</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>variable</code> - Variables</p>
<ul>
<li><code>builtin</code> - Reserved language variables (<code>self</code>, <code>this</code>, <code>super</code>, etc)</li>
<li><code>parameter</code> - Function parameters</li>
<li><code>other</code>
<ul>
<li><code>member</code> - Fields of composite data types (e.g. structs, unions)</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>label</code></p>
</li>
<li>
<p><code>punctuation</code></p>
<ul>
<li><code>delimiter</code> - Commas, colons</li>
<li><code>bracket</code> - Parentheses, angle brackets, etc.</li>
<li><code>special</code> - String interpolation brackets.</li>
</ul>
</li>
<li>
<p><code>keyword</code></p>
<ul>
<li><code>control</code>
<ul>
<li><code>conditional</code> - <code>if</code>, <code>else</code></li>
<li><code>repeat</code> - <code>for</code>, <code>while</code>, <code>loop</code></li>
<li><code>import</code> - <code>import</code>, <code>export</code></li>
<li><code>return</code></li>
<li><code>exception</code></li>
</ul>
</li>
<li><code>operator</code> - <code>or</code>, <code>in</code></li>
<li><code>directive</code> - Preprocessor directives (<code>#if</code> in C) </li>
<li><code>function</code> - <code>fn</code>, <code>func</code></li>
<li><code>storage</code> - Keywords describing how things are stored
<ul>
<li><code>type</code> - The type of something, <code>class</code>, <code>function</code>, <code>var</code>, <code>let</code>, etc. </li>
<li><code>modifier</code> - Storage modifiers like <code>static</code>, <code>mut</code>, <code>const</code>, <code>ref</code>, etc.</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>operator</code> - <code>||</code>, <code>+=</code>, <code>&gt;</code></p>
</li>
<li>
<p><code>function</code></p>
<ul>
<li><code>builtin</code></li>
<li><code>method</code></li>
<li><code>macro</code></li>
<li><code>special</code> (preprocessor in C)</li>
</ul>
</li>
<li>
<p><code>tag</code> - Tags (e.g. <code>&lt;body&gt;</code> in HTML)</p>
</li>
<li>
<p><code>namespace</code></p>
</li>
<li>
<p><code>markup</code></p>
<ul>
<li><code>heading</code>
<ul>
<li><code>marker</code></li>
<li><code>1</code>, <code>2</code>, <code>3</code>, <code>4</code>, <code>5</code>, <code>6</code> - heading text for h1 through h6</li>
</ul>
</li>
<li><code>list</code>
<ul>
<li><code>unnumbered</code></li>
<li><code>numbered</code></li>
</ul>
</li>
<li><code>bold</code></li>
<li><code>italic</code></li>
<li><code>link</code>
<ul>
<li><code>url</code> - urls pointed to by links</li>
<li><code>label</code> - non-url link references</li>
<li><code>text</code> - url and image descriptions in links</li>
</ul>
</li>
<li><code>quote</code></li>
<li><code>raw</code>
<ul>
<li><code>inline</code></li>
<li><code>block</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>diff</code> - version control changes</p>
<ul>
<li><code>plus</code> - additions</li>
<li><code>minus</code> - deletions</li>
<li><code>delta</code> - modifications
<ul>
<li><code>moved</code> - renamed or moved files/changes</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="interface"><a class="header" href="#interface">Interface</a></h4>
<p>These scopes are used for theming the editor interface.</p>
<ul>
<li><code>markup</code>
<ul>
<li><code>normal</code>
<ul>
<li><code>completion</code> - for completion doc popup ui</li>
<li><code>hover</code> - for hover popup ui</li>
</ul>
</li>
<li><code>heading</code>
<ul>
<li><code>completion</code> - for completion doc popup ui</li>
<li><code>hover</code> - for hover popup ui</li>
</ul>
</li>
<li><code>raw</code>
<ul>
<li><code>inline</code>
<ul>
<li><code>completion</code> - for completion doc popup ui</li>
<li><code>hover</code> - for hover popup ui</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Notes</th></tr></thead><tbody>
<tr><td><code>ui.background</code></td><td></td></tr>
<tr><td><code>ui.background.separator</code></td><td>Picker separator below input line</td></tr>
<tr><td><code>ui.cursor</code></td><td></td></tr>
<tr><td><code>ui.cursor.insert</code></td><td></td></tr>
<tr><td><code>ui.cursor.select</code></td><td></td></tr>
<tr><td><code>ui.cursor.match</code></td><td>Matching bracket etc.</td></tr>
<tr><td><code>ui.cursor.primary</code></td><td>Cursor with primary selection</td></tr>
<tr><td><code>ui.gutter</code></td><td>Gutter</td></tr>
<tr><td><code>ui.gutter.selected</code></td><td>Gutter for the line the cursor is on</td></tr>
<tr><td><code>ui.linenr</code></td><td>Line numbers</td></tr>
<tr><td><code>ui.linenr.selected</code></td><td>Line number for the line the cursor is on</td></tr>
<tr><td><code>ui.statusline</code></td><td>Statusline</td></tr>
<tr><td><code>ui.statusline.inactive</code></td><td>Statusline (unfocused document)</td></tr>
<tr><td><code>ui.statusline.normal</code></td><td>Statusline mode during normal mode (<a href="./configuration.html#editor-section">only if <code>editor.color-modes</code> is enabled</a>)</td></tr>
<tr><td><code>ui.statusline.insert</code></td><td>Statusline mode during insert mode (<a href="./configuration.html#editor-section">only if <code>editor.color-modes</code> is enabled</a>)</td></tr>
<tr><td><code>ui.statusline.select</code></td><td>Statusline mode during select mode (<a href="./configuration.html#editor-section">only if <code>editor.color-modes</code> is enabled</a>)</td></tr>
<tr><td><code>ui.statusline.separator</code></td><td>Separator character in statusline</td></tr>
<tr><td><code>ui.popup</code></td><td>Documentation popups (e.g Space + k)</td></tr>
<tr><td><code>ui.popup.info</code></td><td>Prompt for multiple key options</td></tr>
<tr><td><code>ui.window</code></td><td>Border lines separating splits</td></tr>
<tr><td><code>ui.help</code></td><td>Description box for commands</td></tr>
<tr><td><code>ui.text</code></td><td>Command prompts, popup text, etc.</td></tr>
<tr><td><code>ui.text.focus</code></td><td></td></tr>
<tr><td><code>ui.text.info</code></td><td>The key: command text in <code>ui.popup.info</code> boxes</td></tr>
<tr><td><code>ui.virtual.ruler</code></td><td>Ruler columns (see the <a href="./configuration.html#editor-section"><code>editor.rulers</code> config</a>)</td></tr>
<tr><td><code>ui.virtual.whitespace</code></td><td>Visible whitespace characters</td></tr>
<tr><td><code>ui.virtual.indent-guide</code></td><td>Vertical indent width guides</td></tr>
<tr><td><code>ui.menu</code></td><td>Code and command completion menus</td></tr>
<tr><td><code>ui.menu.selected</code></td><td>Selected autocomplete item</td></tr>
<tr><td><code>ui.menu.scroll</code></td><td><code>fg</code> sets thumb color, <code>bg</code> sets track color of scrollbar</td></tr>
<tr><td><code>ui.selection</code></td><td>For selections in the editing area</td></tr>
<tr><td><code>ui.selection.primary</code></td><td></td></tr>
<tr><td><code>ui.cursorline.primary</code></td><td>The line of the primary cursor (<a href="./configuration.html#editor-section">if cursorline is enabled</a>)</td></tr>
<tr><td><code>ui.cursorline.secondary</code></td><td>The lines of any other cursors (<a href="./configuration.html#editor-section">if cursorline is enabled</a>)</td></tr>
<tr><td><code>ui.cursorcolumn.primary</code></td><td>The column of the primary cursor (<a href="./configuration.html#editor-section">if cursorcolumn is enabled</a>)</td></tr>
<tr><td><code>ui.cursorcolumn.secondary</code></td><td>The columns of any other cursors (<a href="./configuration.html#editor-section">if cursorcolumn is enabled</a>)</td></tr>
<tr><td><code>warning</code></td><td>Diagnostics warning (gutter)</td></tr>
<tr><td><code>error</code></td><td>Diagnostics error (gutter)</td></tr>
<tr><td><code>info</code></td><td>Diagnostics info (gutter)</td></tr>
<tr><td><code>hint</code></td><td>Diagnostics hint (gutter)</td></tr>
<tr><td><code>diagnostic</code></td><td>Diagnostics fallback style (editing area)</td></tr>
<tr><td><code>diagnostic.hint</code></td><td>Diagnostics hint (editing area)</td></tr>
<tr><td><code>diagnostic.info</code></td><td>Diagnostics info (editing area)</td></tr>
<tr><td><code>diagnostic.warning</code></td><td>Diagnostics warning (editing area)</td></tr>
<tr><td><code>diagnostic.error</code></td><td>Diagnostics error (editing area)</td></tr>
</tbody></table>
</div>
<p>You can check compliance to spec with</p>
<pre><code class="language-shell">cargo xtask themelint onedark # replace onedark with &lt;name&gt;
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="key-remapping"><a class="header" href="#key-remapping">Key Remapping</a></h1>
<p>One-way key remapping is temporarily supported via a simple TOML configuration
file. (More powerful solutions such as rebinding via commands will be
available in the future).</p>
<p>To remap keys, write a <code>config.toml</code> file in your <code>helix</code> configuration
directory (default <code>~/.config/helix</code> in Linux systems) with a structure like
this:</p>
<pre><code class="language-toml"># At most one section each of 'keys.normal', 'keys.insert' and 'keys.select'
[keys.normal]
C-s = &quot;:w&quot; # Maps the Ctrl-s to the typable command :w which is an alias for :write (save file)
C-o = &quot;:open ~/.config/helix/config.toml&quot; # Maps the Ctrl-o to opening of the helix config file
a = &quot;move_char_left&quot; # Maps the 'a' key to the move_char_left command
w = &quot;move_line_up&quot; # Maps the 'w' key move_line_up
&quot;C-S-esc&quot; = &quot;extend_line&quot; # Maps Ctrl-Shift-Escape to extend_line
g = { a = &quot;code_action&quot; } # Maps `ga` to show possible code actions
&quot;ret&quot; = [&quot;open_below&quot;, &quot;normal_mode&quot;] # Maps the enter key to open_below then re-enter normal mode
[keys.insert]
&quot;A-x&quot; = &quot;normal_mode&quot; # Maps Alt-X to enter normal mode
j = { k = &quot;normal_mode&quot; } # Maps `jk` to exit insert mode
</code></pre>
<blockquote>
<p>NOTE: Typable commands can also be remapped, remember to keep the <code>:</code> prefix to indicate it's a typable command.</p>
</blockquote>
<p>Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes
<code>C-</code>, <code>S-</code> and <code>A-</code>. Special keys are encoded as follows:</p>
<div class="table-wrapper"><table><thead><tr><th>Key name</th><th>Representation</th></tr></thead><tbody>
<tr><td>Backspace</td><td><code>&quot;backspace&quot;</code></td></tr>
<tr><td>Space</td><td><code>&quot;space&quot;</code></td></tr>
<tr><td>Return/Enter</td><td><code>&quot;ret&quot;</code></td></tr>
<tr><td>-</td><td><code>&quot;minus&quot;</code></td></tr>
<tr><td>Left</td><td><code>&quot;left&quot;</code></td></tr>
<tr><td>Right</td><td><code>&quot;right&quot;</code></td></tr>
<tr><td>Up</td><td><code>&quot;up&quot;</code></td></tr>
<tr><td>Down</td><td><code>&quot;down&quot;</code></td></tr>
<tr><td>Home</td><td><code>&quot;home&quot;</code></td></tr>
<tr><td>End</td><td><code>&quot;end&quot;</code></td></tr>
<tr><td>Page Up</td><td><code>&quot;pageup&quot;</code></td></tr>
<tr><td>Page Down</td><td><code>&quot;pagedown&quot;</code></td></tr>
<tr><td>Tab</td><td><code>&quot;tab&quot;</code></td></tr>
<tr><td>Delete</td><td><code>&quot;del&quot;</code></td></tr>
<tr><td>Insert</td><td><code>&quot;ins&quot;</code></td></tr>
<tr><td>Null</td><td><code>&quot;null&quot;</code></td></tr>
<tr><td>Escape</td><td><code>&quot;esc&quot;</code></td></tr>
</tbody></table>
</div>
<p>Keys can be disabled by binding them to the <code>no_op</code> command.</p>
<p>Commands can be found at <a href="https://docs.helix-editor.com/keymap.html">Keymap</a> Commands.</p>
<blockquote>
<p>Commands can also be found in the source code at <a href="https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs"><code>helix-term/src/commands.rs</code></a> at the invocation of <code>static_commands!</code> macro and the <code>TypableCommandList</code>.</p>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="languages"><a class="header" href="#languages">Languages</a></h1>
<p>Language-specific settings and settings for language servers are configured
in <code>languages.toml</code> files.</p>
<h2 id="languagestoml-files"><a class="header" href="#languagestoml-files"><code>languages.toml</code> files</a></h2>
<p>There are three possible <code>languages.toml</code> files. The first is compiled into
Helix and lives in the <a href="https://github.com/helix-editor/helix/blob/master/languages.toml">Helix repository</a>.
This provides the default configurations for languages and language servers.</p>
<p>You may define a <code>languages.toml</code> in your <a href="./configuration.html">configuration directory</a>
which overrides values from the built-in language configuration. For example
to disable auto-LSP-formatting in Rust:</p>
<pre><code class="language-toml"># in &lt;config_dir&gt;/helix/languages.toml
[[language]]
name = &quot;rust&quot;
auto-format = false
</code></pre>
<p>Language configuration may also be overridden local to a project by creating
a <code>languages.toml</code> file under a <code>.helix</code> directory. Its settings will be merged
with the language configuration in the configuration directory and the built-in
configuration.</p>
<h2 id="language-configuration"><a class="header" href="#language-configuration">Language configuration</a></h2>
<p>Each language is configured by adding a <code>[[language]]</code> section to a
<code>languages.toml</code> file. For example:</p>
<pre><code class="language-toml">[[language]]
name = &quot;mylang&quot;
scope = &quot;source.mylang&quot;
injection-regex = &quot;^mylang$&quot;
file-types = [&quot;mylang&quot;, &quot;myl&quot;]
comment-token = &quot;#&quot;
indent = { tab-width = 2, unit = &quot; &quot; }
language-server = { command = &quot;mylang-lsp&quot;, args = [&quot;--stdio&quot;] }
formatter = { command = &quot;mylang-formatter&quot; , args = [&quot;--stdin&quot;] }
</code></pre>
<p>These configuration keys are available:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>name</code></td><td>The name of the language</td></tr>
<tr><td><code>scope</code></td><td>A string like <code>source.js</code> that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually <code>source.&lt;name&gt;</code> or <code>text.&lt;name&gt;</code> in case of markup languages</td></tr>
<tr><td><code>injection-regex</code></td><td>regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential <a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection">language injection</a> site.</td></tr>
<tr><td><code>file-types</code></td><td>The filetypes of the language, for example <code>[&quot;yml&quot;, &quot;yaml&quot;]</code>. See the file-type detection section below.</td></tr>
<tr><td><code>shebangs</code></td><td>The interpreters from the shebang line, for example <code>[&quot;sh&quot;, &quot;bash&quot;]</code></td></tr>
<tr><td><code>roots</code></td><td>A set of marker files to look for when trying to find the workspace root. For example <code>Cargo.lock</code>, <code>yarn.lock</code></td></tr>
<tr><td><code>auto-format</code></td><td>Whether to autoformat this language when saving</td></tr>
<tr><td><code>diagnostic-severity</code></td><td>Minimal severity of diagnostic for it to be displayed. (Allowed values: <code>Error</code>, <code>Warning</code>, <code>Info</code>, <code>Hint</code>)</td></tr>
<tr><td><code>comment-token</code></td><td>The token to use as a comment-token</td></tr>
<tr><td><code>indent</code></td><td>The indent to use. Has sub keys <code>tab-width</code> and <code>unit</code></td></tr>
<tr><td><code>language-server</code></td><td>The Language Server to run. See the Language Server configuration section below.</td></tr>
<tr><td><code>config</code></td><td>Language Server configuration</td></tr>
<tr><td><code>grammar</code></td><td>The tree-sitter grammar to use (defaults to the value of <code>name</code>)</td></tr>
<tr><td><code>formatter</code></td><td>The formatter for the language, it will take precedence over the lsp when defined. The formatter must be able to take the original file as input from stdin and write the formatted file to stdout</td></tr>
<tr><td><code>max-line-length</code></td><td>Maximum line length. Used for the <code>:reflow</code> command</td></tr>
</tbody></table>
</div>
<h3 id="file-type-detection-and-the-file-types-key"><a class="header" href="#file-type-detection-and-the-file-types-key">File-type detection and the <code>file-types</code> key</a></h3>
<p>Helix determines which language configuration to use with the <code>file-types</code> key
from the above section. <code>file-types</code> is a list of strings or tables, for
example:</p>
<pre><code class="language-toml">file-types = [&quot;Makefile&quot;, &quot;toml&quot;, { suffix = &quot;.git/config&quot; }]
</code></pre>
<p>When determining a language configuration to use, Helix searches the file-types
with the following priorities:</p>
<ol>
<li>Exact match: if the filename of a file is an exact match of a string in a
<code>file-types</code> list, that language wins. In the example above, <code>&quot;Makefile&quot;</code>
will match against <code>Makefile</code> files.</li>
<li>Extension: if there are no exact matches, any <code>file-types</code> string that
matches the file extension of a given file wins. In the example above, the
<code>&quot;toml&quot;</code> matches files like <code>Cargo.toml</code> or <code>languages.toml</code>.</li>
<li>Suffix: if there are still no matches, any values in <code>suffix</code> tables
are checked against the full path of the given file. In the example above,
the <code>{ suffix = &quot;.git/config&quot; }</code> would match against any <code>config</code> files
in <code>.git</code> directories. Note: <code>/</code> is used as the directory separator but is
replaced at runtime with the appropriate path separator for the operating
system, so this rule would match against <code>.git\config</code> files on Windows.</li>
</ol>
<h3 id="language-server-configuration"><a class="header" href="#language-server-configuration">Language Server configuration</a></h3>
<p>The <code>language-server</code> field takes the following keys:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>command</code></td><td>The name of the language server binary to execute. Binaries must be in <code>$PATH</code></td></tr>
<tr><td><code>args</code></td><td>A list of arguments to pass to the language server binary</td></tr>
<tr><td><code>timeout</code></td><td>The maximum time a request to the language server may take, in seconds. Defaults to <code>20</code></td></tr>
<tr><td><code>language-id</code></td><td>The language name to pass to the language server. Some language servers support multiple languages and use this field to determine which one is being served in a buffer</td></tr>
</tbody></table>
</div>
<p>The top-level <code>config</code> field is used to configure the LSP initialization options. A <code>format</code>
sub-table within <code>config</code> can be used to pass extra formatting options to
<a href="https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md#document-formatting-request--leftwards_arrow_with_hook">Document Formatting Requests</a>.
For example with typescript:</p>
<pre><code class="language-toml">[[language]]
name = &quot;typescript&quot;
auto-format = true
# pass format options according to https://github.com/typescript-language-server/typescript-language-server#workspacedidchangeconfiguration omitting the &quot;[language].format.&quot; prefix.
config = { format = { &quot;semicolons&quot; = &quot;insert&quot;, &quot;insertSpaceBeforeFunctionParenthesis&quot; = true } }
</code></pre>
<h2 id="tree-sitter-grammar-configuration"><a class="header" href="#tree-sitter-grammar-configuration">Tree-sitter grammar configuration</a></h2>
<p>The source for a language's tree-sitter grammar is specified in a <code>[[grammar]]</code>
section in <code>languages.toml</code>. For example:</p>
<pre><code class="language-toml">[[grammar]]
name = &quot;mylang&quot;
source = { git = &quot;https://github.com/example/mylang&quot;, rev = &quot;a250c4582510ff34767ec3b7dcdd3c24e8c8aa68&quot; }
</code></pre>
<p>Grammar configuration takes these keys:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>name</code></td><td>The name of the tree-sitter grammar</td></tr>
<tr><td><code>source</code></td><td>The method of fetching the grammar - a table with a schema defined below</td></tr>
</tbody></table>
</div>
<p>Where <code>source</code> is a table with either these keys when using a grammar from a
git repository:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>git</code></td><td>A git remote URL from which the grammar should be cloned</td></tr>
<tr><td><code>rev</code></td><td>The revision (commit hash or tag) which should be fetched</td></tr>
<tr><td><code>subpath</code></td><td>A path within the grammar directory which should be built. Some grammar repositories host multiple grammars (for example <code>tree-sitter-typescript</code> and <code>tree-sitter-ocaml</code>) in subdirectories. This key is used to point <code>hx --grammar build</code> to the correct path for compilation. When omitted, the root of repository is used</td></tr>
</tbody></table>
</div>
<h3 id="choosing-grammars"><a class="header" href="#choosing-grammars">Choosing grammars</a></h3>
<p>You may use a top-level <code>use-grammars</code> key to control which grammars are
fetched and built when using <code>hx --grammar fetch</code> and <code>hx --grammar build</code>.</p>
<pre><code class="language-toml"># Note: this key must come **before** the [[language]] and [[grammar]] sections
use-grammars = { only = [ &quot;rust&quot;, &quot;c&quot;, &quot;cpp&quot; ] }
# or
use-grammars = { except = [ &quot;yaml&quot;, &quot;json&quot; ] }
</code></pre>
<p>When omitted, all grammars are fetched and built.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="guides"><a class="header" href="#guides">Guides</a></h1>
<p>This section contains guides for adding new language server configurations,
tree-sitter grammars, textobject queries, etc.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-languages"><a class="header" href="#adding-languages">Adding languages</a></h1>
<h2 id="language-configuration-1"><a class="header" href="#language-configuration-1">Language configuration</a></h2>
<p>To add a new language, you need to add a <code>[[language]]</code> entry to the
<code>languages.toml</code> (see the <a href="guides/../languages.html">language configuration section</a>).</p>
<p>When adding a new language or Language Server configuration for an existing
language, run <code>cargo xtask docgen</code> to add the new configuration to the
<a href="guides/../lang-support.html">Language Support</a> docs before creating a pull request.
When adding a Language Server configuration, be sure to update the
<a href="https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers">Language Server Wiki</a> with installation notes.</p>
<h2 id="grammar-configuration"><a class="header" href="#grammar-configuration">Grammar configuration</a></h2>
<p>If a tree-sitter grammar is available for the language, add a new <code>[[grammar]]</code>
entry to <code>languages.toml</code>.</p>
<p>You may use the <code>source.path</code> key rather than <code>source.git</code> with an absolute path
to a locally available grammar for testing, but switch to <code>source.git</code> before
submitting a pull request.</p>
<h2 id="queries"><a class="header" href="#queries">Queries</a></h2>
<p>For a language to have syntax-highlighting and indentation among
other things, you have to add queries. Add a directory for your
language with the path <code>runtime/queries/&lt;name&gt;/</code>. The tree-sitter
<a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries">website</a>
gives more info on how to write queries.</p>
<blockquote>
<p>NOTE: When evaluating queries, the first matching query takes
precedence, which is different from other editors like Neovim where
the last matching query supersedes the ones before it. See
<a href="https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090">this issue</a> for an example.</p>
</blockquote>
<h2 id="common-issues"><a class="header" href="#common-issues">Common Issues</a></h2>
<ul>
<li>
<p>If you get errors when running after switching branches, you may have to update the tree-sitter grammars. Run <code>hx --grammar fetch</code> to fetch the grammars and <code>hx --grammar build</code> to build any out-of-date grammars.</p>
</li>
<li>
<p>If a parser is segfaulting or you want to remove the parser, make sure to remove the compiled parser in <code>runtime/grammar/&lt;name&gt;.so</code></p>
</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-textobject-queries"><a class="header" href="#adding-textobject-queries">Adding Textobject Queries</a></h1>
<p>Textobjects that are language specific (<a href="guides/../usage.html#textobjects">like functions, classes, etc</a>)
require an accompanying tree-sitter grammar and a <code>textobjects.scm</code> query file
to work properly. Tree-sitter allows us to query the source code syntax tree
and capture specific parts of it. The queries are written in a lisp dialect.
More information on how to write queries can be found in the <a href="https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax">official tree-sitter
documentation</a>.</p>
<p>Query files should be placed in <code>runtime/queries/{language}/textobjects.scm</code>
when contributing. Note that to test the query files locally you should put
them under your local runtime directory (<code>~/.config/helix/runtime</code> on Linux
for example).</p>
<p>The following <a href="https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes">captures</a> are recognized:</p>
<div class="table-wrapper"><table><thead><tr><th>Capture Name</th></tr></thead><tbody>
<tr><td><code>function.inside</code></td></tr>
<tr><td><code>function.around</code></td></tr>
<tr><td><code>class.inside</code></td></tr>
<tr><td><code>class.around</code></td></tr>
<tr><td><code>test.inside</code></td></tr>
<tr><td><code>test.around</code></td></tr>
<tr><td><code>parameter.inside</code></td></tr>
<tr><td><code>comment.inside</code></td></tr>
<tr><td><code>comment.around</code></td></tr>
</tbody></table>
</div>
<p><a href="https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&amp;type=Code&amp;ref=advsearch&amp;l=&amp;l=">Example query files</a> can be found in the helix GitHub repository.</p>
<h2 id="queries-for-textobject-based-navigation"><a class="header" href="#queries-for-textobject-based-navigation">Queries for Textobject Based Navigation</a></h2>
<p><a href="guides/../usage.html#tree-sitter-textobject-based-navigation">Tree-sitter based navigation</a> is done using captures in the
following order:</p>
<ul>
<li><code>object.movement</code></li>
<li><code>object.around</code></li>
<li><code>object.inside</code></li>
</ul>
<p>For example if a <code>function.around</code> capture has been already defined for a language
in it's <code>textobjects.scm</code> file, function navigation should also work automatically.
<code>function.movement</code> should be defined only if the node captured by <code>function.around</code>
doesn't make sense in a navigation context.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-indent-queries"><a class="header" href="#adding-indent-queries">Adding Indent Queries</a></h1>
<p>Helix uses tree-sitter to correctly indent new lines. This requires
a tree-sitter grammar and an <code>indent.scm</code> query file placed in
<code>runtime/queries/{language}/indents.scm</code>. The indentation for a line
is calculated by traversing the syntax tree from the lowest node at the
beginning of the new line. Each of these nodes contributes to the total
indent when it is captured by the query (in what way depends on the name
of the capture).</p>
<p>Note that it matters where these added indents begin. For example,
multiple indent level increases that start on the same line only increase
the total indent level by 1.</p>
<h2 id="scopes-1"><a class="header" href="#scopes-1">Scopes</a></h2>
<p>Added indents don't always apply to the whole node. For example, in most
cases when a node should be indented, we actually only want everything
except for its first line to be indented. For this, there are several
scopes (more scopes may be added in the future if required):</p>
<ul>
<li>
<p><code>all</code>:
This scope applies to the whole captured node. This is only different from
<code>tail</code> when the captured node is the first node on its line.</p>
</li>
<li>
<p><code>tail</code>:
This scope applies to everything except for the first line of the
captured node.</p>
</li>
</ul>
<p>Every capture type has a default scope which should do the right thing
in most situations. When a different scope is required, this can be
changed by using a <code>#set!</code> declaration anywhere in the pattern:</p>
<pre><code class="language-scm">(assignment_expression
right: (_) @indent
(#set! &quot;scope&quot; &quot;all&quot;))
</code></pre>
<h2 id="capture-types"><a class="header" href="#capture-types">Capture Types</a></h2>
<ul>
<li>
<p><code>@indent</code> (default scope <code>tail</code>):
Increase the indent level by 1. Multiple occurrences in the same line
don't stack. If there is at least one <code>@indent</code> and one <code>@outdent</code>
capture on the same line, the indent level isn't changed at all.</p>
</li>
<li>
<p><code>@outdent</code> (default scope <code>all</code>):
Decrease the indent level by 1. The same rules as for <code>@indent</code> apply.</p>
</li>
<li>
<p><code>@extend</code>:
Extend the range of this node to the end of the line and to lines that
are indented more than the line that this node starts on. This is useful
for languages like Python, where for the purpose of indentation some nodes
(like functions or classes) should also contain indented lines that follow them.</p>
</li>
<li>
<p><code>@extend.prevent-once</code>:
Prevents the first extension of an ancestor of this node. For example, in Python
a return expression always ends the block that it is in. Note that this only stops the
extension of the next <code>@extend</code> capture. If multiple ancestors are captured,
only the extension of the innermost one is prevented. All other ancestors are unaffected
(regardless of whether the innermost ancestor would actually have been extended).</p>
</li>
</ul>
<h2 id="predicates"><a class="header" href="#predicates">Predicates</a></h2>
<p>In some cases, an S-expression cannot express exactly what pattern should be matched.
For that, tree-sitter allows for predicates to appear anywhere within a pattern,
similar to how <code>#set!</code> declarations work:</p>
<pre><code class="language-scm">(some_kind
(child_kind) @indent
(#predicate? arg1 arg2 ...)
)
</code></pre>
<p>The number of arguments depends on the predicate that's used.
Each argument is either a capture (<code>@name</code>) or a string (<code>&quot;some string&quot;</code>).
The following predicates are supported by tree-sitter:</p>
<ul>
<li>
<p><code>#eq?</code>/<code>#not-eq?</code>:
The first argument (a capture) must/must not be equal to the second argument
(a capture or a string).</p>
</li>
<li>
<p><code>#match?</code>/<code>#not-match?</code>:
The first argument (a capture) must/must not match the regex given in the
second argument (a string).</p>
</li>
</ul>
<p>Additionally, we support some custom predicates for indent queries:</p>
<ul>
<li>
<p><code>#not-kind-eq?</code>:
The kind of the first argument (a capture) must not be equal to the second
argument (a string).</p>
</li>
<li>
<p><code>#same-line?</code>/<code>#not-same-line?</code>:
The captures given by the 2 arguments must/must not start on the same line.</p>
</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>