## 1. Project Overview & Quickstart (helix-editor/architecture)

# architecture

Open-source repository helix-editor/architecture

### Repository Details
- **Repository:** [helix-editor/architecture](https://github.com/helix-editor/architecture)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (helix-editor/website)

## File: content/news/_index.md

+++
title = "News"
sort_by = "date"
template = "news.html"
page_template = "news-page.html"
+++

---

## File: content/news/2022-03-28-release-22.03-highlights.md

+++
title = "Release 22.03 Highlights"
date = 2022-03-28T16:25:00Z
updated = 2022-04-04T13:25:00Z
type = "post"
description = "Highlights of the 22.03 release: the health-check flag, experimental DAP support, improved incremental injection parsing, and an overhauled tree-sitter grammar system."
in_search_index = true
+++

Ranging from small quality-of-life improvements and fixes to large features
and refactors, Helix 22.03 brings some exciting changes. Helix is a modal
text editor with built-in support for multiple selections, Language
Server Protocol (LSP), tree-sitter, and now Debug Adapter Protocol (DAP).

Before we look at the highlights, there are some administrative notes.
`master` branch changes are now published separately from the release
[documentation][docs]. Find the new `master` docs [here][master-docs].
Helix is switching versioning schemes. Expect to find new releases in
Calendar Version format: `YY.0M(.MICRO)`. We're aiming to cut regular
releases every two months or so. Check out the [changelog][changelog]
for all of the new features and fixes from this release.

With that out of the way, let's check out the highlights!

## Health-check

Helix 22.03 brings a new CLI flag: `hx --health`. Use the new health-check
flag to troubleshoot missing language servers and queries.

Check the health of all languages with `hx --health` or ask for details
about a specific language with `hx --health <lang>`.

{{ asciinema(id="health-check", width="92", height="24") }}

## Experimental DAP Support

Debug Adapter Protocol (DAP) is an abstract protocol for editors and debuggers
to communicate. It's very similar in spirit to the Language Server Protocol
(LSP), but built for debugging. Interact with the debug adapter with
`<space-d>`.

{{ asciinema(id="dap", width="154", height="46") }}

Note that the DAP adapter is experimental: it isn't yet documented, there may
be bugs, and the UX is a bit clunky. Contributions are very welcome!

## Incremental Injection Parsing Rewrite

One of the cooler features of syntax highlight driven by tree-sitter is the
ability to _inject_ a language into another language's document. For example,
if you're writing Markdown, you might use a code-fence like so:

    This is some rust:

    ```rust
    println!("Hello, world!")
    ```

Helix highlights the Rust block by injecting tree-sitter-rust. Injections
have been rewritten so that changes within are now parsed incrementally, which
is a big speed boost when editing documents with large injected blocks.

Along with this rewrite, Helix now supports _combined_ injections. For example,
when highlighting Interactive Elixir (IEx), we might have a block of code like
the following:

```elixir
iex> send(self(), :hello)
iex> receive do: (:hello -> :ok)
```

The IEx grammar injects tree-sitter-elixir into each line after the prompt
token. Combined injections cover the case where separate injected documents
must be parsed in one combined document, like so:

```elixir
iex> if true do
...>   :ok
...> end
```

Helix can now parse all three lines together. In the future this can be used
to add support for templating languages like EJS or ERB.

## Tree-Sitter Grammars Refactor

In the past, tree-sitter grammar repositories have been added to the Helix
repository as Git submodules. Submodules can be painful to work with though,
especially when there are more than 50 in a repository. Cloning, CI, and
packaging times have slowed down as language support has improved.

Helix 22.03 completely overhauls the system for tree-sitter grammars. The headline
is that **submodules are gone**! If you're working with the source, you can
now clone with a standard `git clone https://github.com/helix-editor/helix`.
So where did the tree-sitter submodules go? They've been replaced with two
new CLI flags: `hx --grammar fetch` to clone grammar repositories into the
runtime directory and `hx --grammar build` to compile them. Use `-g` for
short. Grammar repositories are shallow-cloned in parallel, so fetching all
60 grammars can now take as little as 6 seconds on a good connection.

If you're building from source or developing Helix, note that fetching and
building are included in the `helix-term` build step, so you should not
need to manually fetch or build grammars.

Additionally, if you would like to customize which tree-sitter grammars
you fetch and build, you may now add the `use-grammars` key to the **top** of
your `languages.toml`:

{{ asciinema(id="use-grammars", width="92", height="24") }}

If you're writing a tree-sitter grammar, you can try out integrating it
by pointing helix to your grammar's local path in `languages.toml` without
needing to publish changes to a Git remote:

```toml
[[language]]
name = "mylang"
# ..

[[grammar]]
name = "mylang"
source = { path = "/local/path/to/tree-sitter-mylang" }
```

Running `hx -g build` will build the grammar. Add some queries and you're
on your way to interactive grammar development.

## Up Next

The next release is sure to be exciting as well. Contribute and follow
along with development in the [GitHub repository][helix-git] and be sure to
join in on discussions in the [Matrix channel][matrix].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2203-2022-03-28
[docs]: https://docs.helix-editor.com/
[master-docs]: https://docs.helix-editor.com/master/
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org

---

## File: content/news/2022-05-28-release-22.05-highlights.md

+++
title = "Release 22.05 Highlights"
date = 2022-05-28T13:00:00Z
type = "post"
description = "Highlights of the 22.05 release."
in_search_index = true
+++

Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

Today marks the 22.05 release, a featureful release with over double the number
of contributors as last release (110!). A big thanks to all involved! 🙌

Also a big shout out to [`@amirrezaask`](https://github.com/amirrezaask) for
this great [Helix introduction video](https://www.youtube.com/watch?v=__U4A2Q9fNI)!

Let's check out the flashy features of 22.05.

## Indentation rework

The indentation system has been fully reworked. Indentation still works by
querying the parsed tree-sitter syntax tree for a document, but now query files
can use the full expressive power of tree-sitter queries rather than just
simple node names. Expect more robust indentation with fewer edge cases.

## Configurable gutters

Gutters can now be configured in your `config.toml` file. For example, you can
remove the line-number gutter while still showing LSP diagnostics.

```toml
[editor]
gutters = ["diagnostics"] # default is ["diagnostics", "line-numbers"]
```

## Local language configuration

Language configuration can now be specified local to a project. Create a
`.helix` directory and a `languages.toml` under it to override values from the
[default language configuration]. For example, override a C project's indents
to use tabs instead of spaces for indentation:

```toml
# my_c_project/.helix/languages.toml
[[language]]
name = "c"
indent = { tab-width = 8, unit = "\t" }
```

## Rulers

{{ asciinema(id="rulers", width="94", height="25") }}

Vertical rulers may now be configured through the `rulers` option. Use them
as a guide when adhering to a maximum line length.

## Show visible whitespace

{{ asciinema(id="visible-whitespace", width="94", height="25") }}

Whitespace characters like spaces, tabs, and newlines may now be rendered. Use
the `whitespace.render` option either at runtime with the `:set` command or in
your `config.toml` under the editor section. Visible whitespace indicators can
make Helix's selection model more intuitive, especially around line endings.
The characters used for tabs, spaces, non-breaking space, and newlines may also
be customized as well as whether any of the characters are rendered at all. In
fact, for the remaining asciicasts in this post, you'll be seeing my custom tab
and newline characters!

## Use registers in prompts

{{ asciinema(id="insert-registers-in-prompts", width="94", height="25") }}

Values stored in registers may now be used in prompts like search or global
search. In the above example, we yank a selection to the `"` register with
`y` and then open up the global search prompt with `Space` `/`. The available
registers are shown above the prompt and we hit `"` to insert the contents of
the `"` register.

## Reflow paragraphs

{{ asciinema(id="reflow", width="94", height="25") }}

The new `:reflow` command hard-wraps text to a given column width. Default
column widths may be configured on a per-language basis. Reflow recognizes
matching prefixes between lines, so you may reflow line-comments, markdown
quotes or lines with leading whitespace and the leading characters will be
placed appropriately.

## Swap windows

{{ asciinema(id="window-swapping", width="94", height="25") }}

Windows may now be swapped with neighbor windows and splits may be transposed.
With the window menu open (`C-w` or `space w`), use `H`, `J`, `K`, and `L`
to swap the current window with the left, down, up, and right neighbors,
respectively. Use `t` or `C-t` to switch between a vertical and horizontal
split or vice versa.

## Set a language at runtime

{{ asciinema(id="set-language", width="94", height="25") }}

The language for a buffer may now be set at runtime. Use
`:set-language language` (or `:lang language` for short) to set the language
and switch language servers.

## Wrapping up

These are just some highlights from the changes in 22.05. Check out the
[changelog] for the full set. Pick up the release binaries for 22.05 on the
[release page]. Starting with this release, an AppImage is included in the
release binaries for easier usage from Linux.

Expect plenty more features and improvements in Helix 22.07 coming in July.
Contribute and follow along with development in the
[GitHub repository][helix-git] and be sure to join in on discussions in the
[Matrix channel][matrix].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2205-2022-05-17
[default language configuration]: https://docs.helix-editor.com/guides/adding_languages.html#language-configuration
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org
[release page]: https://github.com/helix-editor/helix/releases/tag/22.05

---

## File: content/news/2022-08-31-release-22.08-highlights.md

+++
title = "Release 22.08 Highlights"
date = 2022-08-31T18:00:00Z
type = "post"
description = "Highlights of the 22.08 release."
in_search_index = true
+++

Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

Today marks the 22.08 release, a release with plenty of fixes and new features.
A big _thank you_ to our contributors! This release had 87 contributors. 🎉

Let's check out the highlighted features for 22.08.

## Indent guides

{{ asciinema(id="indent-guides", width="94", height="25") }}

Indent guides provide a visual representation for the current indentation
level. Enable indent guides with the `editor.indent-guides.render` key.
The character used as a guide is also customizable.

## Cursorline

{{ asciinema(id="cursorline", width="94", height="25") }}

The cursorline is a horizontal highlighted bar that follows your cursor.
Cursorlines may be themed for the primary and all secondary cursors and
can be enabled or disabled separate from theming with the `editor.cursorline`
option.

## Mode colors

{{ asciinema(id="color-modes", width="94", height="25") }}

The mode indicator in the statusline may now be styled based on the current
mode. This feature may be enabled with the `editor.color-modes` option and
colors may be configured using `ui.statusline.{insert,normal,select}` keys
in themes.

## Configurable statusline

{{ asciinema(id="configurable-statusline", width="94", height="25") }}

The statusline may now be configured in the `editor.statusline` section
of the config. Elements may be placed on the left, center or right of
the statusline with a configurable separator and spacers. Two new elements
may now also be added to your statusline: `file-line-ending` and
`position-percentage`.

## LSP signature help



Signature help provides documentation as you type the arguments to a function
call and tracks which function parameter is currently being entered. Signature
help is enabled by default.

## LSP document highlight

{{ asciinema(id="document-highlight", width="94", height="25") }}

The document highlight request (`Space-h`) creates a selection for all
instances of the symbol under the primary cursor. Helix has robust support for
multiple selections, so you may edit all selections simultaneously (for
example with `c`) or cycle between selections (`(`/`)`).

## LSP diagnostics pickers

{{ asciinema(id="diagnostic-picker", width="94", height="25") }}

The new buffer and workspace diagnostics pickers may be used to jump to
Language Server diagnostics like warnings and errors. Use `Space-g` to
open the picker with diagnostics for the current buffer and `Space-G`
to view all diagnostics in a workspace.

## Jumplist picker

{{ asciinema(id="jumplist-picker", width="94", height="25") }}

The jumplist saves a history of selections. Save selections with `C-s` and jump
forward with `C-i` and backward with `C-o`. The jumplist is a powerful tool,
especially when working with Language Server goto-definition or global search
which both save to the jumplist automatically.

22.08 adds a new picker that can be used to jump across entries in the jumplist.
The preview pane shows the line of the saved primary selection. Bring up the
jumplist picker with `Space-j`.

## External formatters

{{ asciinema(id="external-formatter", width="94", height="25") }}

Many Language Servers provide format-on-save capabilities. For languages
without Language Servers or for Language Servers that do not implement
formatting, an external formatter binary may now be configured. The document
is passed through the formatter's stdin and replaced with the formatted output
from stdout.

An external formatter may also be used when you prefer the formatting from an
external tool over formatting provided by a Language Server. For example if you
configure `black` for formatting Python, formatting will be accomplished with
`black` rather than `pylsp`.

## Bracketed paste

{{ asciinema(id="bracketed-paste", width="94", height="25") }}

Bracketed paste is terminal emulator feature that allows terminal programs to
recognize paste sequences and handle the pasted text. Without bracketed paste
support, text pasted with operating-system level paste (`C-v`) looked to Helix
like text that was entered very quickly which lead to some odd side-effects
like awkward indentation or mysteriously appearing auto-pair characters.

22.08 adds support for bracketed paste, so now all pastes into Helix from
terminal emulators that support bracketed paste work as if you had pressed
`Space-p` in normal mode. In the above cast, the entire text of _Moby-Dick_
is pasted with `C-v` in insert mode instantly.

## Wrapping up

These changes are just the highlights. Check out the full [changelog] to see
all that's changed since 22.05. Release binaries can be found on the [release
page].

Be ready for more exciting changes in Helix 22.10 expected in October!
Contribute and follow along with development in the
[Helix GitHub repository][helix-git] and be sure to join in on discussions in
the [Matrix channel][matrix].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2208-2022-08-31
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org
[release page]: https://github.com/helix-editor/helix/releases/tag/22.08

---

## File: content/news/2022-12-06-release-22.12-highlights.md

+++
title = "Release 22.12 Highlights"
date = 2022-12-06T22:00:00Z
type = "post"
description = "Highlights of the 22.12 release."
in_search_index = true
+++

Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

Today we cut the 22.12 release. This release is big and featureful and saw
contributions from 99 contributors. Thank you all! 🎊

Helix now has a logo! Thank you [`@jakehl`](https://github.com/jakehl) for your
contribution!



Looking for an introduction to Helix or to see Helix out in the wild? Check out
these new videos on Helix.

* [https://www.youtube.com/watch?v=xHebvTGOdH8](https://www.youtube.com/watch?v=xHebvTGOdH8)
* [https://www.youtube.com/watch?v=7mTi278jUS8](https://www.youtube.com/watch?v=7mTi278jUS8)

Now let's jump into the highlights.

## Git diff gutter

{{ asciinema(id="git-diff-gutter", width="94", height="25") }}

The new git diff gutter tracks the changes in the current buffer compared to
the the git index. The markers in the gutter indicate additions, modifications,
and removals compared to the file checked in to git. The git diff gutter is
enabled by default.

Also be sure to try out the new hunk textobject: `]g` jumps to the next changed
hunk and `[g` jumps to the previous.

## Underline styles and colors



Terminals with support for extended underlines can render underlines with
styles like curls or dots as well as colors. Extended underlines can be used to
improve the display of LSP diagnostics. These can be configured in themes with
the new `underline` key:

```toml
"diagnostic.error" = { underline = { style = "curl", color = "red" } }
```

The existing `underline` modifier is now an alias for the `"line"` style.

If you're looking to use this in a theme that hasn't configured it yet, you
can use the new [theme inheritance] feature to modify just the scopes you would
like to change:

```toml
# ~/.config/helix/themes/my-onedark.toml
inherits = "onedark"

"diagnostic.error" = { fg = "errorfg", bg = "errorbg", underline = { color = "red" } }
```

[theme inheritance]: https://docs.helix-editor.com/master/themes.html#inheritance

## Autosave when the terminal loses focus



Terminals with support for focus events can now automatically save the current
file when you focus on a new window. Enable this behavior by setting the
`editor.auto-save` configuration key to `true`.

## Multi-cursor completion

{{ asciinema(id="multi-cursor-completion", width="94", height="25") }}

Editing with multiple selections is a central feature within helix. LSP
auto-completion now applies to all cursors when editing with multiple
selections, making it easy to replace multiple instances of a symbol with
auto-complete's help.

## Bufferline

{{ asciinema(id="bufferline", width="94", height="25") }}

The bufferline is a listing of buffers displayed at the top of a window. It
provides an at-a-glance view of the buffers you're working with. Set
the `editor.bufferline` configuration key to `"always"` to always show the
bufferline, `"multiple"` to show the bufferline only when there are multiple
buffers open, and `"never"` to disable it.

## Behind-the-scenes improvements

22.12 brings also brings important changes to Helix's plumbing:

* The code-path for writing files has been overhauled. This fixes a number of
  edge cases around writing large files and failures to write.
* Performance has been improved for tree-sitter parsing, querying and the
  handling of injections. This is a noticeable speed boost for large markdown
  files in particular since markdown uses injections extensively.
* Failure handling in the LSP code-paths has been improved. Helix now
  gracefully handles cases like language servers not supporting capabilities
  and unexpected language server crashes.
* The speed and memory usage of the `:reload` command has been vastly improved.
  This comes from the creation of [`imara-diff`], a new diffing
  implementation which is faster than the one used internally by `git`!

## Wrapping up

There are many more changes arriving now in 22.12 than we can fit in this post.
Check out the 22.12 [changelog] for the full details on all of the performance
boosts, usability improvements and fixes in 22.12.

Contribute and follow along with development in the [Helix GitHub
repository][helix-git] and be sure to join in on discussions in the [Matrix
channel][matrix].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2212-2022-12-06
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org
[`imara-diff`]: https://github.com/pascalkuthe/imara-diff

---

## File: content/news/2023-03-31-release-23.03-highlights.md

+++
title = "Release 23.03 Highlights"
date = 2023-03-31T00:00:00Z
type = "post"
description = "Highlights of the 23.03 release."
in_search_index = true
+++

Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

Today marks the 23.03 release. First, a big _thank you_ to everyone involved!
This release includes changes from 102 contributors. Today's release brings
some especially useful and exciting features, so let's jump right in.

## Soft-wrap

{{ asciinema(id="softwrap", width="94", height="25") }}

Soft-wrap breaks up lines to fit in view without inserting actual line break
characters into the text (so called "hard-wrapping"). This can be useful for
reading and editing documentation or code with especially long lines. Enable
soft-wrap in your config with the `editor.soft-wrap.enable` key:

```toml
# ~/.config/helix/config.toml
[editor.soft-wrap]
enable = true
```

Heuristics for where to break lines and the wrap indicator may also be
[configured](https://docs.helix-editor.com/configuration.html#editorsoft-wrap-section).

Soft-wrap is the first feature implemented on top of a new "virtual text" API
within the Helix codebase. The virtual text API allows us to decorate and
manipulate the actual text in a document without disturbing positioning and
modifications. The virtual text API opens the door for many new exciting
features like the inlay hints we'll see next.

## Inlay hints

{{ asciinema(id="inlay-hints", width="94", height="25") }}

Inlay hints are a new feature in the latest LSP specification. Language servers
can provide editors with hints to show in a document. In the example above,
rust-analyzer provides type hints for variables and intermediary expressions
as well as parameter names in function calls.

Inlay hints can be enabled in your config with the `lsp.display-inlay-hints`
key.

## Initial support for snippets

{{ asciinema(id="snippets", width="94", height="25") }}

LSP snippets are a way for language servers to provide more complex completions
for an editor. Language servers can specify where to place cursors within a
completion (tabstops), placeholder values and more. Helix now has initial
support for LSP completions, leaving more advanced snippet features like
virtual placeholders, multiple tabstops, and variable substitutions for future
work.

## Dynamic workspace symbol picker

{{ asciinema(id="dynamic-workspace-symbol-picker", width="94", height="25") }}

The workspace symbol picker (`<space>S`) is an LSP-driven feature for looking
up a symbol in a project. Large projects might have many symbols, though, so
this symbol picker typically wouldn't load them all at once. The workspace
symbol picker has been reworked in this release though to dynamically
re-request symbols with a new query as you type in the picker. This lets the
language server narrow down the number of symbols and only tell Helix about the
ones relevant to the search. This rework fixes compatibility with some language
servers which returned empty symbols with no query (`gopls`, `pyright`,
`clangd`) or limited results (`rust-analyzer`).

The "dynamic picker" introduced in this refactor may benefit other pickers in
the future, for example allowing the global search picker (`<space>/`) to
update on-the-fly as you change the query.

## Version control HEAD statusline element

{{ asciinema(id="vcs-statusline-element", width="94", height="25") }}

A new statusline element has been added which displays the version control
HEAD. Add this to your statusline by introducing the `"version-control"`
element in the
[`editor.statusline`](https://docs.helix-editor.com/configuration.html#editorstatusline-section)
section of your config for the `left`, `center` or `right` sides.

## Enhanced keyboard protocol

Support for the [enhanced keyboard protocol] is now enabled. Terminals that
support the protocol (Kitty, WezTerm) can now send unambiguous keycodes to
Helix, enabling key combinations that weren't possible to bind before like
`C-/`, `C-h` or `S-backspace`. This functionality works out-of-the-box for
terminals that support the protocol.

[enhanced keyboard protocol]: https://sw.kovidgoyal.net/kitty/keyboard-protocol/

## Runtime directory refactor

Helix keeps files like tree-sitter parsers and queries, themes and the tutor
file in a special "runtime" directory. This directory is typically installed
by your package manager and shouldn't be modified by hand. Multiple runtime
directories are now supported, so you can keep the runtime files installed by
your package manager unchanged while adding new tree-sitter parsers and
queries to a local runtime directory. On Unix systems you can add files to the
`~/.config/helix/runtime` directory which take precedence over the runtime
directory installed by a package manager.

## Wrapping up

These flashy features are just the tip of the iceberg though. Check out the
23.03 [changelog] for the full details on all of the changes in this release.

Come chat about usage and development questions in the [Matrix space][matrix]
and follow along with Helix's development in the [GitHub repository][helix-git].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2303-2023-03-31
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org

---

## File: content/news/2023-10-25-release-23.10-highlights.md

+++
title = "Release 23.10 Highlights"
date = 2023-10-25T00:00:00Z
type = "post"
description = "Highlights of the 23.10 release."
in_search_index = true
+++

The Helix 23.10 release is finally here! 23.10 introduces some very large
internal changes that enable some powerful features. A very big _thank you_ to
everyone who made this release possible.

New to Helix?
Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

Let's check out this release's highlights.

## Multiple language servers

23.10 brings a big change to the way we handle language servers.
Previously each language could only support one language server at a time but
now you can configure multiple to work in tandem. For example you might use
the TypeScript language server for JavaScript/TypeScript development and also
configure [efm-langserver](https://github.com/mattn/efm-langserver) for
Prettier formatting and ESLint diagnostics. With the new support for multiple
language servers, you can specify which features to use from each language
server.

This brings a big change to the way language servers are configured in your
language configuration (`languages.toml`). All language servers are now
specified separately from languages and then each language selects which
language server(s) to use. From the example above, you might configure efm-
langserver and typescript-language-server like so:

```toml
[language-server.efm]
command = "efm-langserver"
config.documentFormatting = true

[language-server.typescript-language-server]
command = "typescript-language-server"
args = ["--stdio"]
config.hostInfo = "helix"

[[language]]
name = "typescript"
auto-format = true
language-servers = [
  { name = "efm", only-features = ["format", "diagnostics"] },
  { name = "typescript-language-server", except-features = ["format", "diagnostics"] },
]
```

See more details in the [language configuration docs](https://docs.helix-editor.com/languages.html).

## Fuzzy matching with Nucleo

{{ asciinema(id="nucleo-nix-store", width="94", height="25") }}

Helix uses "fuzzy" matching to filter as-you-type in components like the file
picker. Previously we used the popular `skim`/`fuzzy-matcher` crates but in the
23.10 release we've switched to the new
[`nucleo`](https://github.com/helix-editor/nucleo) crate. Nucleo is
significantly faster than skim and fzf, handles Unicode correctly, and uses a
bonus system that feels more intuitive.

Nucleo also enables us to lazily stream in new items, which is a big boost for
the user experience for pickers. In the asciicast above I'm scanning through
my computer's `/nix/store`, a huge directory containing more than twenty
million files. The file picker now works gradually as we scan through the
directory and matches files as we find them.

Nucleo also paves the way for future picker upgrades. Stay tuned to the
upcoming release notes to see where we'll take the picker.

## Smart tab

Smart tab is a new feature bound to the tab key in the default keymap. When
you press tab and the line to the left of the cursor isn't all whitespace,
the cursor will jump to the end of the syntax tree's parent node. For example:

```nix
{
  key = "value";
  nested = {
    key2 = "value2"; # When the cursor is at the end of the line here, <tab>
                     # jumps right after the closing brace on the next line.
  };
}
```

This is useful in languages like Nix for adding semicolons at the end of an
attribute set or jumping to the end of a block in a C-like language:

{{ asciinema(id="smart-tab", width="94", height="25") }}

## Expanded support for registers

{{ asciinema(id="special-registers", width="94", height="25") }}

Registers allow you to save and paste values. For example you might select
a paragraph, use `"ay` to yank it into the `a` register, and later use `"ap`
to paste that paragraph. Some registers have special effects when read or
written to though like the `_` "blackhole" register: any values written are
discarded and nothing can be read. Special registers have been expanded to
include some useful ones from Kakoune and clipboard registers:

* `%`: the current buffer name
* `#`: the number of each selection, 1-indexed
* `.`: the contents of each selection
* `*` and `+`: system and primary clipboards

Also check out the new register statusline element. It appears when you select
a register with `"`. Notice the `reg=#` in the bottom-right corner of the
statusline in the asciicast when we select the `#` register and how it goes
away when we paste that register (`p`) or increment the selections (`C-a`).

## Initial support for LSP DidChangeWatchedFiles

{{ asciinema(id="initial-lsp-didchangewatchedfiles", width="94", height="25") }}

Some language servers use the DidChangeWatchedFiles notification to discover
changes to related files in other languages. For example, `rust-analyzer` will
fetch and index new dependencies when you add them to your `Cargo.toml`.
Helix will now send file change notifications when the file is changed by
Helix itself. Full support for DidChangeWatchedFiles will require a file
watcher but for now we're able to support the most common use-case for
DidChangeWatchedFiles.

## Syntax highlight regex prompts



Regex prompts like those created with `s`, `S` or `|` are now syntax highlighted
via tree-sitter-regex. The highlighting makes special characters more obvious
and can catch syntax errors like trailing backslashes.

## Wrapping up

As always, this is just the tip of the iceberg for the 23.10 release. Check out
the [changelog] for the full details.

Come chat about usage and development questions in the [Matrix space][matrix]
and follow along with Helix's development in the [GitHub repository][helix-git].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2310-2023-10-24
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org

---

## File: content/news/2024-03-30-release-24.03-highlights.md

+++
title = "Release 24.03 Highlights"
date = 2024-03-30T00:00:00Z
type = "post"
description = "Highlights of the 24.03 release."
in_search_index = true
+++

The Helix 24.03 release has arrived! First, a very big _thank you_ to everyone
who made this release possible. This release saw changes from 125 contributors.

New to Helix?
Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

Let's check out this release's highlights.

## Amp-like jumping

{{ asciinema(id="amp-jump", width="94", height="25") }}

Jumping features are popular in the (Neo)Vim plugin space and there are even
plugins to add the same functionality to other tools like browsers. They allow
you to move your selection efficiently across even large parts of the view,
like you could by clicking with a mouse, but by entering "labels" instead.
24.03 introduces jumping commands inspired by the [Amp editor]'s [jump mode].
Press `gw` to add the jump labels and then enter one of the labels to jump to
the word under that label. Using `gw` in select mode (`v`) extends the
selection.

## Block comments

In the past, Helix has only been able to toggle line comments like `//` and `#`
and languages like OCaml have been left with workarounds like a "line" comment
token of `(*`. In 24.03 Helix can now toggle block comments as well. Use `C-c`
or `<space>c` to smartly add or remove line or block comments around the current
selection based on the language's comment token configuration, `<space>c` to
toggle block comments around the current selection, or `<space><A-c>` to toggle
only line comments on the current line.

## Improvements to tree-sitter injections

Helix uses [`tree-sitter`] incremental parsing for syntax highlighting,
textobjects, indentation and some motions and commands. 24.03 improves how we
handle _[injections]_ - a powerful tree-sitter feature for parsing documents
with multiple languages. For example you might have JavaScript, CSS or other
languages within a `<script>` or `<style>` tag in HTML. The HTML parser doesn't
need to know how to parse all of these languages. Instead it can _inject_
JavaScript or CSS parsers to handle the `<script>` or `<style>` tag contents.

{{ asciinema(id="ts-subtree-and-motions-injection", width="94", height="25") }}

One of these improvements is to the `:tree-sitter-subtree` command that
displays an S-expression of the syntax tree under the cursor. 24.03 shows the
injection layer under the selection instead of only the root layer. For example
in this asciicast we now show the syntax tree for the JavaScript parts of the
document while in the past we only showed the HTML part of the tree.

The other big improvement is to the tree-sitter motions. `A-o` (alt + o)
expands the selection to the parent node of the syntax tree node covered by the
current selection. `A-i` shrinks to the child node and `A-n` and `A-p` go to
the *n*ext and *p*revious nodes, respectively. Previously these
commands only worked on the root layer (for example HTML in the asciicast) but
they now find the injection layer that contains the selection and move along
that layer's syntax tree. Internally we organize injection layers into a
tree-like structure so that these motions can switch layers when needed.

Stay tuned for future changes that improve injections, like finding textobjects
within injected content.

## Internal improvements

24.03 also saw major internal improvements. The first comes from a new "event
system" - a system built around Tokio channels and tasks that allows different
parts of the Helix codebase to communicate with one another. The event system
also adds generic ways to debounce and run tasks in background threads so we
can prevent locking up the UI. Some parts of the code base have already been
migrated to the event system like LSP completion and signature-help. In
24.03 you'll notice that LSP completion doesn't automatically pop up after just
navigating around in insert mode, for example with arrow keys. It's now hooked
into document changes instead, so it can smartly pop up when you start changing
a document rather than every time the editor goes idle.

The other major improvement to be excited for is the general replacement of the
`regex` crate with [`regex-cursor`], a streaming regex implementation
compatible with [`ropey`], the rope crate we use to represent all documents.
`regex-cursor` is capable of running on _discontiguous strings_ - input that
may not be collocated in memory. In a rope, different parts of the document
might be stored separately internally. To use the `regex` API we needed to
convert slices of the document to a regular Rust `String`, duplicating the
memory footprint of that slice of the document. `regex-cursor` operates on the
chunks of the rope instead, which greatly improves efficiency.

## Wrapping up

As always, this is just the highlights from the 24.03 release. Check out the
full [changelog] for the details.

Come chat about usage and development questions in the [Matrix space][matrix]
and follow along with Helix's development in the [GitHub repository][helix-git].

[Amp editor]: https://github.com/jmacdonald/amp
[jump mode]: https://amp.rs/docs/usage/#jump-mode
[`tree-sitter`]: https://github.com/tree-sitter/tree-sitter
[injections]: https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection
[`regex-cursor`]: https://github.com/pascalkuthe/regex-cursor
[`ropey`]: https://github.com/cessen/ropey
[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2404-2024-03-30
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org

---

## File: content/news/release-25.01-highlights.md

+++
title = "Release 25.01 Highlights"
date = 2025-01-03T00:01:00Z
type = "post"
description = "Highlights of the 25.01 release."
in_search_index = true
+++

The new year brings in a new Helix release! Say hello to 25.01. This is an
especially large release comprising changes from a whopping 171 contributors.
_Thank you_ to everyone who made this release possible!

New to Helix?
Helix is a modal text editor with built-in support for multiple selections,
Language Server Protocol (LSP), tree-sitter, and experimental support for Debug
Adapter Protocol (DAP).

This large release has a bunch of big improvements so let's jump right in to
the highlights.

## Completions

Completions have seen two big updates in 25.01. First, completions now support
paths:

{{ asciinema(id="path-completion", width="94", height="25") }}

Helix now detects a possible path when inserting text and suggests either
absolute paths or relative paths based on the current working directory. This
is especially useful for some languages like Nix where paths are commonplace.

Path completion is especially exciting because it's the first completion
feature not driven by LSP. The change to add path completion refactored parts
of the codebase that assumed that completions could only ever come from a
language server and this should make it easier to add new completion sources
in the future.

The other big change comes to the behavior of snippet completions - currently
only sent by language servers - as 25.01 adds support for snippet tabstops.

{{ asciinema(id="snippet-tabstops", width="94", height="25") }}

In the recording above, rust-analyzer suggests a snippet completion for `add`
that includes some placeholders for the function arguments. In the past Helix
would clear these placeholders when accepting the completion with the Enter
key. Now the Enter key jumps the cursor to the first tabstop. The Tab key can
be used to switch to the next tabstop. Typing in any other character replaces
the placeholder text.

## Diagnostics

Historically, LSP diagnostics have appeared right-aligned in the top-right
corner of the editor. While this display is straightforward, it can become hard
to read on small terminal sizes or when a language server sends a long
diagnostic message. 25.01 adds a new way to render diagnostics _inline_.

{{ asciinema(id="inline-diagnostics", width="94", height="25") }}

Inline diagnostics leverage the internal virtual text system to render
diagnostics at the diagnostic's range in the document. Diagnostic messages
appear after the end of the line or in between lines of the appropriate code.

Inline diagnostics are currently disabled by default as we tune the display and
iron out bugs and can be enabled with a config like so:

```toml
# ~/.config/helix/config.toml
[editor]
# Minimum severity to show a diagnostic after the end of a line:
end-of-line-diagnostics = "hint"

[editor.inline-diagnostics]
# Minimum severity to show a diagnostic on the primary cursor's line.
# Note that `cursor-line` diagnostics are hidden in insert mode.
cursor-line = "error"
# Minimum severity to show a diagnostic on other lines:
# other-lines = "error"
```

Setting `end-of-line-diagnostics`, `cursor-line` or `other-lines` to anything
other than `"disable"` enables inline diagnostics.

## Tabular pickers

The picker UI component is central in Helix: it's an efficient and readable way
to jump between files and locations of interest like LSP diagnostics and
symbols. In 25.01 the picker component has been overhauled significantly so
that items are laid out as a table.

{{ asciinema(id="tabular-pickers", width="94", height="25") }}

Simple pickers such as the file picker (`<space>f`) which only need one column
are unchanged. Pickers with multiple fields of information though now show
column names at the top of the the results pane. Rows still correspond to
individual items to pick but there are now columns that horizontally align
the same kinds of content between items. The diagnostics picker for example now
has three columns - "severity", "code" and "message" - while the LSP symbol
picker has two - "kind" and "name".

Columns are individually filterable: one column is filtered by default and
others can be filtered with a query syntax: `%<column name> filter text`. For
example the diagnostics picker can now be filtered down to only errors by
searching for `%severity error`. Filter text is fuzzy matched and column names
may be specified by a prefix, so a search for `%s e` will behave the same in
the diagnostics picker as a search for `%severity error`.

{{ asciinema(id="interactive-global-search", width="94", height="25") }}

Alongside this change, the `global_search` command (`<space>/`) has been
refactored to update with the picker's query dynamically. This allows searching
a codebase for a regex interactively. Filenames can then be filtered separately
with a query like `%path filename`.

## Macro keybindings

Initial support for keybindings written as macros has landed in 25.01. Macro
keybindings can be written by prefixing a string of inputs with `@`.

```toml
# Change the `<space>y` keybinding to yank to the `a` register instead of the
# system clipboard:
[keys.normal]
space.y = "@\"ay"
```

Macro keybindings use the same infrastructure as macros recorded with `q` and
executed with `Q`, so the above behaves as if you typed

1. `"`: open the register select popup
2. `a`: select the 'a' register
3. `y`: copy the selection contents to the register

Macros cover a gap in keybindings: inputs into components like the register
select popup are not exposed as commands, so operations like selecting a
register would not otherwise be possible to bind.

The initial support for macro keybinding limits the bindings to be unusable
in a command sequence: you can't yet combine macros with regular commands. For
example you could swap out the `y` above for its command `yank` in a sequence
like `["@\"a", "yank"]`, but this is not yet supported.

## Commenting

25.01 includes improvements to commenting that make for a smoother experience
when writing line comments like inline documentation.

{{ asciinema(id="25.01-comment-improvements", width="94", height="25") }}

Line comments are now continued by default: pressing the Enter key while in
insert mode or `o`/`O` in normal mode while the cursor is on a line comment now
extends that comment, inserting the current comment token prefix and a trailing
space character. Trailing whitespace is now consistently stripped when pressing
Enter, so `<ret><ret>` can be used to insert a break between two paragraphs in
inline markdown documentation for example.

The `join_selections` and `join_selections_space` commands (`J` and `A-J`) have
also been improved to now strip the comment token when combining line comments.
This makes it easier to edit existing comments or fix spacing between
paragraphs.

## Wrapping up

As always, this is just the highlights from the 25.01 release. Check out the
full [changelog] for the details.

Come chat about usage and development questions in the [Matrix space][matrix]
and follow along with Helix's development in the [GitHub repository][helix-git].

[changelog]: https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2501-2025-01-03
[helix-git]: https://github.com/helix-editor/helix/
[matrix]: https://matrix.to/#/#helix-community:matrix.org