Helix: модальный текстовый редактор

Зачем

Helix: post-vim редактор, написанный на Rust. Ключевые отличия от Vim/Neovim:

  • Всё работает из коробки: LSP, tree-sitter подсветка, автодополнение, файловый пикер, и всё это без плагинов
  • Модель selection → action вместо vim-овского action → motion (сначала выделяешь, потом действуешь)
  • Множественные курсоры как первоклассная фича
  • Встроенный file picker, buffer picker, symbol picker с fuzzy-поиском
  • Tree-sitter: структурная навигация и выделение по AST-узлам

Установка

# Arch
sudo pacman -S helix

# Ubuntu (PPA)
sudo add-apt-repository ppa:maveonair/helix-editor
sudo apt update && sudo apt install helix

# macOS
brew install helix

# Из исходников
git clone https://github.com/helix-editor/helix
cd helix
cargo install --path helix-term --locked

# Проверить, что языковые серверы и грамматики на месте
hx --health
hx --health go          # проверка для конкретного языка

Бинарник называется hx.

Модель: selection → action

Главное отличие от Vim. В Vim ты говоришь “удали слово” (dw), а в Helix: “выдели слово, затем удали” (wd).

Vim:    d  w       →  "delete word"     (action → motion)
Helix:  w  d       →  "word → delete"   (selection → action)

Преимущество: ты видишь, что выделено, прежде чем действовать. Меньше неожиданностей.

Режимы (modes)

РежимКак войтиКак выйти
NormalEsc(по умолчанию)
Inserti, a, o и др.Esc
Select (visual)vEsc
Command:Esc / Enter
Gotogавтовыход после команды
Matchmавтовыход после команды
WindowCtrl+wавтовыход после команды
Space (меню)Spaceавтовыход после команды

Space-меню: интерактивная подсказка. Нажми Space и увидишь все доступные действия.

Навигация

Базовое перемещение

КлавишаДействие
h j k lвлево / вниз / вверх / вправо
wследующее слово (начало)
bпредыдущее слово (начало)
eконец слова
W B Eто же, но WORD (разделитель: пробел)
0начало строки
$конец строки (в Helix: gl)
^первый непробельный символ (в Helix: gh)
ggначало файла
geконец файла
:<number>перейти к строке

Goto-режим (g)

КлавишаДействие
ggначало файла
geконец файла
ghначало строки (home)
glконец строки (end)
gsпервый непробельный символ
gtверх экрана
gcцентр экрана
gbниз экрана
gdgo to definition (LSP)
gygo to type definition
grgo to references
gigo to implementation
gago to last accessed file
gmgo to last modified file
gngo to next buffer
gpgo to previous buffer

Скролл

КлавишаДействие
Ctrl+dполстраницы вниз
Ctrl+uполстраницы вверх
Ctrl+fстраница вниз
Ctrl+bстраница вверх
zzтекущая строка в центр экрана
ztтекущая строка наверх
zbтекущая строка вниз

Поиск

КлавишаДействие
/поиск вперёд
?поиск назад
nследующее совпадение
Nпредыдущее совпадение
*поиск текущего выделения

Прыжки

КлавишаДействие
Ctrl+oназад по jumplist
Ctrl+iвперёд по jumplist
Ctrl+sсохранить позицию в jumplist

Выделение и редактирование

Выделение

КлавишаДействие
vtoggle select mode (расширяет выделение при навигации)
xвыделить текущую строку
Xвыделить строку вверх (расширяет)
%выделить весь файл
sselect (regex) внутри выделения, split
Ssplit выделения по regex
&выровнять выделения
;сбросить выделение (курсор остаётся)
,убрать все курсоры кроме основного
Alt+,убрать основной курсор

Действия над выделением

КлавишаДействие
dудалить
cудалить и перейти в insert
yкопировать (yank)
pвставить после
Pвставить перед
r<char>заменить выделение символом
~переключить регистр
`в нижний регистр
Alt+`в верхний регистр
>увеличить отступ
<уменьшить отступ
=отформатировать выделение (LSP)
Jобъединить строки

Вход в Insert mode

КлавишаДействие
iinsert перед курсором
ainsert после курсора
Iinsert в начало строки
Ainsert в конец строки
oновая строка снизу
Oновая строка сверху

Изменения

КлавишаДействие
uundo
Uredo
.повторить последнее действие

Множественные курсоры

Одна из самых мощных фич Helix.

КлавишаДействие
Cдублировать курсор на строку ниже
Alt+Cдублировать курсор на строку выше
sregex select: создаёт курсор на каждом совпадении в выделении
,оставить только основной курсор
Alt+,убрать основной курсор
(циклить основной курсор назад
)циклить основной курсор вперёд
Alt+ssplit selection по переносам строк
&выровнять курсоры
_trim whitespace вокруг выделений

Практические паттерны

Переименовать переменную вручную (без LSP):

# 1. Выдели слово: wbe  или  miw (match inner word)
# 2. * — поиск этого слова
# 3. Выдели все нужные строки: x (несколько раз) или выделить функцию
# 4. s — ввести имя переменной → regex создаст курсоры на всех совпадениях
# 5. c — удалить и ввести новое имя
# 6. , — выйти из мультикурсора

Добавить текст в конец нескольких строк:

# 1. Выдели строки: x x x (или vG для до конца)
# 2. s ввести $ (конец строки) → Enter
# 3. a → ввести текст
# 4. Esc → ,

Обернуть каждую строку в кавычки:

# 1. Выдели строки: x x x
# 2. Alt+s — split по строкам (курсор на каждой)
# 3. I → ввести "
# 4. Esc → A → ввести "
# 5. Esc → ,

Match mode (m)

Работа с парными символами (скобки, кавычки, теги):

КлавишаДействие
mmперейти к парной скобке
ms<char>surround: обернуть выделение символом
md<char>удалить surrounding
mr<old><new>заменить surrounding
ma<char>выделить вокруг (around)
mi<char>выделить внутри (inner)

Примеры:

mi(    → выделить содержимое внутри скобок
ma"    → выделить строку в кавычках вместе с кавычками
ms(    → обернуть выделение в скобки
md'    → удалить окружающие кавычки
mr([   → заменить () на []

Space-меню (лидер)

Нажми Space, и появится меню с подсказками.

КлавишаДействие
Space ffile picker (fuzzy)
Space Ffile picker в текущей директории
Space bbuffer picker
Space ssymbol picker (текущий файл, LSP)
Space Sworkspace symbol picker (весь проект, LSP)
Space ddiagnostics picker (текущий файл)
Space Ddiagnostics picker (весь проект)
Space gdebug menu
Space acode action (LSP)
Space rrename symbol (LSP)
Space hselect symbol references (LSP)
Space 'last picker (повторить)
Space wwindow mode
Space ppaste from system clipboard
Space yyank to system clipboard
Space Yyank main selection to clipboard
Space Rreplace from clipboard
Space /global search (grep в проекте)
Space kshow docs popup (hover, LSP)
Space ?command palette

Окна и буферы

Window mode (Ctrl+w или Space w)

КлавишаДействие
Ctrl+w s или Ctrl+w vвертикальный сплит
Ctrl+w sгоризонтальный сплит
Ctrl+w h/j/k/lпереключение между окнами
Ctrl+w qзакрыть окно
Ctrl+w oоставить только текущее окно

Буферы

:buffer-close        или :bc      — закрыть текущий буфер
:buffer-close!       или :bc!     — закрыть без сохранения
:buffer-close-others или :bco     — закрыть все кроме текущего
:buffer-next         или :bn      — следующий буфер
:buffer-previous     или :bp      — предыдущий буфер

Быстрое переключение: Space b (fuzzy picker буферов).

LSP: языковые серверы

Helix автоматически запускает LSP для распознанного языка. Проверить:

hx --health python               # покажет LSP, formatter, debugger

Установка языковых серверов

# TypeScript / JavaScript
npm i -g typescript-language-server typescript

# Python
pip install python-lsp-server

# Go
go install golang.org/x/tools/gopls@latest

# Rust — rust-analyzer ставится через rustup
rustup component add rust-analyzer

# C/C++
sudo pacman -S clang              # clangd встроен

# YAML
npm i -g yaml-language-server

# Bash
npm i -g bash-language-server

# Docker
npm i -g dockerfile-language-server-nodejs

# Tailwind CSS
npm i -g @tailwindcss/language-server

LSP-команды в Normal mode

КлавишаДействие
gdgo to definition
gygo to type definition
grgo to references
gigo to implementation
Space acode action
Space rrename symbol
Space khover docs
Space sdocument symbols
Space Sworkspace symbols
Space ddiagnostics (файл)
Space Ddiagnostics (проект)
]dследующая диагностика
[dпредыдущая диагностика

Автодополнение

Появляется автоматически при вводе. Управление:

  • Ctrl+x: trigger вручную
  • Tab / Ctrl+n: следующий вариант
  • Shift+Tab / Ctrl+p: предыдущий
  • Enter: подтвердить
  • Ctrl+e: отменить

Конфигурация

Конфиги лежат в ~/.config/helix/:

~/.config/helix/
├── config.toml      # основные настройки
└── languages.toml   # настройки языков и LSP

config.toml

theme = "catppuccin_mocha"

[editor]
line-number = "relative"
cursorline = true
bufferline = "multiple"          # показывать вкладки если открыто >1 буфера
auto-format = true
auto-save = { focus-lost = true, after-delay.enable = true, after-delay.timeout = 1000 }
color-modes = true               # цвет курсора зависит от режима
completion-trigger-len = 1
idle-timeout = 200
rulers = [80, 120]
shell = ["bash", "-c"]
true-color = true
undercurl = true
text-width = 100

[editor.cursor-shape]
insert = "bar"
normal = "block"
select = "underline"

[editor.statusline]
left = ["mode", "spinner", "file-name", "file-modification-indicator"]
center = ["diagnostics"]
right = ["selections", "position", "file-encoding", "file-line-ending", "file-type", "version-control"]
separator = "│"

[editor.lsp]
display-messages = true
display-inlay-hints = true

[editor.indent-guides]
render = true
character = "│"
skip-levels = 1

[editor.file-picker]
hidden = false                   # показывать скрытые файлы

[editor.soft-wrap]
enable = true

[editor.whitespace.render]
tab = "all"
newline = "none"

[editor.search]
smart-case = true
wrap-around = true

# Кастомные клавиши
[keys.normal]
C-s = ":write"                   # Ctrl+s — сохранить
C-q = ":quit"                    # Ctrl+q — выйти
A-x = "extend_to_line_bounds"    # Alt+x — выделить полные строки
X = "extend_line_above"          # X — выделить строку вверх

# Space shortcuts
[keys.normal.space]
e = ":toggle-option lsp.display-inlay-hints"
q = ":reflow"                    # переформатировать текст по text-width

# Быстрая навигация по диагностикам
[keys.normal."]"]
d = "goto_next_diag"
D = "goto_last_diag"

[keys.normal."["]
d = "goto_prev_diag"
D = "goto_first_diag"

[keys.insert]
C-s = ":write"                   # сохранить из insert mode

languages.toml

# Prettier для JS/TS/JSON
[[language]]
name = "javascript"
formatter = { command = "prettier", args = ["--parser", "typescript"] }
auto-format = true

[[language]]
name = "typescript"
formatter = { command = "prettier", args = ["--parser", "typescript"] }
auto-format = true

[[language]]
name = "json"
formatter = { command = "prettier", args = ["--parser", "json"] }
auto-format = true

# Go
[[language]]
name = "go"
auto-format = true
formatter = { command = "goimports" }

# Python — ruff как LSP + formatter
[[language]]
name = "python"
language-servers = ["ruff", "pylsp"]
auto-format = true
formatter = { command = "ruff", args = ["format", "-"] }

[language-server.ruff]
command = "ruff"
args = ["server"]

[language-server.pylsp]
command = "pylsp"

# Rust — rust-analyzer настройки
[language-server.rust-analyzer.config]
check.command = "clippy"

# TOML
[[language]]
name = "toml"
formatter = { command = "taplo", args = ["format", "-"] }
auto-format = true

# Markdown
[[language]]
name = "markdown"
soft-wrap.enable = true
text-width = 80

Темы

# Список встроенных тем:
:theme <Tab>                     # в командном режиме — автодополнение

# Популярные:
:theme catppuccin_mocha
:theme gruvbox_dark_hard
:theme onedark
:theme tokyonight
:theme rose_pine
:theme kanagawa

Превью темы: в командном режиме :theme и перебирай Tab, тема применяется мгновенно.

Tree-sitter: структурная навигация

Helix использует tree-sitter для парсинга кода в AST. Это даёт навигацию по структуре, а не по тексту.

КлавишаДействие
Alt+pвыделить родительский узел AST
Alt+o / Alt+iрасширить / сузить выделение по AST
Alt+nвыделить соседний узел
Alt+eпереместиться к концу узла
]fследующая функция
[fпредыдущая функция
]cследующий класс
[cпредыдущий класс
]aследующий аргумент/параметр
[aпредыдущий аргумент/параметр
]tследующий тест
[tпредыдущий тест

Dev-флоу

Ежедневная работа

hx .                              # открыть файловый пикер в текущей директории
# или
hx src/main.rs                    # открыть конкретный файл

Типичная сессия:

Space f    → открыть файл (fuzzy picker по имени)
Space /    → найти текст во всём проекте (grep)
Space s    → навигация по символам текущего файла (функции, классы)
Space S    → навигация по символам проекта
gd         → перейти к определению
gr         → найти все использования
Space a    → code action (импорт, quick fix)
Space r    → переименовать символ
Space d    → посмотреть ошибки
:w         → сохранить

Паттерн: рефакторинг

# Переименовать через LSP (надёжно, все файлы):
# Курсор на символе → Space r → ввести новое имя

# Массовая замена (regex):
# 1. % — выделить весь файл
# 2. s — ввести regex для поиска
# 3. Enter — курсоры на каждом совпадении
# 4. c — ввести замену

Паттерн: работа с ошибками

Space d    → список диагностик (ошибки, warnings)
]d         → следующая ошибка
[d         → предыдущая ошибка
Space a    → code action на ошибке (auto-import, fix)
Space k    → развернуть описание ошибки

Паттерн: grep по проекту + массовое редактирование

Space /    → ввести паттерн поиска → Enter
            результаты в пикере — Enter чтобы перейти к файлу

Паттерн: быстрое переключение

Space b    → buffer picker (открытые файлы)
Space f    → file picker (все файлы)
ga         → последний посещённый файл (toggle)
Ctrl+o     → назад по истории прыжков
Ctrl+i     → вперёд по истории прыжков

Команды (:)

:write   :w                      — сохранить
:quit    :q                      — выйти
:wq                              — сохранить и выйти
:quit!   :q!                     — выйти без сохранения
:write-quit-all :wqa             — сохранить все буферы и выйти
:open <path>                     — открыть файл
:buffer-close :bc                — закрыть буфер
:reload                          — перезагрузить файл
:config-reload                   — перезагрузить config.toml
:config-open                     — открыть config.toml
:log-open                        — открыть лог (для отладки LSP)
:theme <name>                    — сменить тему
:set <option> <value>            — изменить настройку на лету
:toggle-option <option>          — toggle bool-настройки
:sh <command>                    — выполнить shell-команду
:pipe <command>                  — пропустить выделение через shell-команду
:run-shell-command               — запустить команду и показать результат
:sort                            — отсортировать выделенные строки
:reflow                          — переформатировать текст по text-width

Pipe: мощный приём

Пропустить выделенный текст через внешнюю команду:

# Отсортировать строки
:pipe sort

# Отсортировать и убрать дубли
:pipe sort -u

# Отформатировать JSON
:pipe jq .

# Отформатировать SQL
:pipe pg_format

# Посчитать строки
:pipe wc -l

Частые проблемы

LSP не запускается:

hx --health <language>           # проверить, что LSP-сервер установлен и в PATH
:log-open                        # посмотреть логи внутри helix

Нет tree-sitter грамматик:

hx --grammar fetch               # скачать грамматики
hx --grammar build               # собрать

Копирование не работает с системным буфером:

Использовать Space y (yank to system clipboard) и Space p (paste from system clipboard). Требуется xclip (X11) или wl-copy (Wayland).

# Wayland
sudo pacman -S wl-clipboard
# X11
sudo pacman -S xclip

Привычка из Vim, dd удаляет строку:

В Helix: xd (выделить строку → удалить). Для нескольких строк: 3xd или xxd.

Автоформат раздражает:

:set auto-format false           # отключить на лету
# или в config.toml:
# auto-format = false