diff --git a/README.md b/README.md index 2d3fec9..dd618d8 100755 --- a/README.md +++ b/README.md @@ -43,13 +43,14 @@ This README is the tour. The field manual lives at ### 📊 Core Development -| Tool | Description | Features | -| -------------------------------------------------------------------- | -------------------- | --------------------------------------------------------------------------- | -| 📝 **[AstroNvim v5](https://astronvim.com/)** | Neovim configuration | • IDE-like features
• Avante.nvim AI assistant
• SilkCircuit theme | -| 👻 **[Ghostty](https://ghostty.org/)** | Terminal emulator | • GPU-accelerated
• SilkCircuit theme
• Native macOS/Linux | -| 🌌 **[Starship](https://starship.rs/)** | Cross-shell prompt | • SilkCircuit gradient theme
• Git status integration
• Context-aware | -| 🖥️ **[Tmux](https://github.com/tmux/tmux)** | Terminal multiplexer | • Custom key bindings
• SilkCircuit color scheme
• Session management | -| 🤖 **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** | AI pair programmer | • Custom status line
• Security hooks
• Project-aware assistance | +| Tool | Description | Features | +| -------------------------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------- | +| 📝 **[AstroNvim v5](https://astronvim.com/)** | Neovim configuration | • IDE-like features
• Avante.nvim AI assistant
• SilkCircuit theme | +| 🌙 **[Helix](https://helix-editor.com/)** | Modal editor, no plugins | • AstroNvim-shaped Space leader
• Shares Mason's language servers
• SilkCircuit theme | +| 👻 **[Ghostty](https://ghostty.org/)** | Terminal emulator | • GPU-accelerated
• SilkCircuit theme
• Native macOS/Linux | +| 🌌 **[Starship](https://starship.rs/)** | Cross-shell prompt | • SilkCircuit gradient theme
• Git status integration
• Context-aware | +| 🖥️ **[Tmux](https://github.com/tmux/tmux)** | Terminal multiplexer | • Custom key bindings
• SilkCircuit color scheme
• Session management | +| 🤖 **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** | AI pair programmer | • Custom status line
• Security hooks
• Project-aware assistance | ### 🎯 Modern CLI Tools @@ -78,6 +79,7 @@ This README is the tour. The field manual lives at dotfiles/ ├── nvim/ # AstroNvim v5 configuration (→ ~/.config/nvim) │ └── lua/plugins/ # Plugin configs (silkcircuit, avante, treesitter, …) +├── helix/ # Helix config + languages (→ ~/.config/helix/*.toml) ├── zsh/ # Zsh configuration (zshrc + completion) ├── bash/ # Bash configuration (profile + bashrc.local) ├── sh/ # 30 modular shell scripts (git, docker, k8s, macos, …) diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 2656a9a..d6d107b 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -21,6 +21,7 @@ export default defineConfig({ { text: 'Guide', link: '/getting-started/' }, { text: 'Shell', link: '/shell/' }, { text: 'Neovim', link: '/neovim/' }, + { text: 'Helix', link: '/helix/' }, { text: 'Tools', link: '/tools/' }, { text: 'Reference', @@ -88,6 +89,12 @@ export default defineConfig({ ], }, ], + '/helix/': [ + { + text: 'Helix', + items: [{ text: 'Overview', link: '/helix/' }], + }, + ], '/tools/': [ { text: 'CLI Tools', diff --git a/docs/helix/index.md b/docs/helix/index.md new file mode 100644 index 0000000..e54e31d --- /dev/null +++ b/docs/helix/index.md @@ -0,0 +1,230 @@ +# Helix + +Helix 25.07, painted in SilkCircuit glow, with the Space leader laid out the way AstroNvim taught your hands + +## Overview + +[Helix](https://helix-editor.com) is a modal editor with no plugin system: tree-sitter, LSP, pickers, multiple cursors +and a file explorer are built in, and the whole setup is two TOML files. It is Kakoune-shaped rather than Vim-shaped, so +you select first and act second. That model is the reason to try it, and the config here leaves it alone. What it does +carry over from the [Neovim setup](../neovim/) is the muscle memory that has nothing to do with motions: the Space +groups, `Ctrl-s`, `]b` and `[b`, and `Esc` clearing your selection. + +What you get: + +- The same language servers and formatters as Neovim: Rust, Python (ruff and ty), TypeScript (vtsls), HTML, CSS, + Tailwind, JSON, YAML, TOML, Markdown, Bash, Lua and Docker, with prettier, stylua and shfmt for formatting +- One master switch for format-on-save, off by default like the Neovim config, toggled with `Space u F` +- Inlay hints, inline diagnostics on the cursor line, a bufferline when more than one file is open, a statusline that + shows the git branch +- lazygit in a tmux popup, one-line git blame, and a `Space a y` that copies a `file:line` reference for pasting at an + agent + +## Structure + +``` +helix/ +├── config.toml # Editor options and keymap (→ ~/.config/helix/config.toml) +├── languages.toml # Language servers and formatters (→ ~/.config/helix/languages.toml) +└── README.md +sh/helix.sh # Puts Mason's binaries on PATH so Helix finds the servers +``` + +The SilkCircuit installer drops its five Helix themes into `~/.config/helix/themes/`, which is why the two files are +linked individually rather than the directory. Pick another variant any time with `:theme silkcircuit-neon` (also +`vibrant`, `soft` and `dawn`); the tracked default is `glow`. + +## Quick start + +``` +hx . # File explorer at the project root +hx file.py # Open a file + +Space f f # Find files +Space f w # Grep the project +Space f c # Grep the word under the cursor +Space e # File explorer +Space x x # Diagnostics for this buffer +Space l f # Format buffer +Space g g # lazygit (tmux popup) +Space ? # Command palette, searchable by description +:config-reload # After editing config.toml +hx --health python # What a language resolved to +``` + +## Coming from Neovim + +The unlearning is smaller than it looks. Everything that is not in this table works the way you expect. + +| Habit | Helix | +| ---------------------- | -------------------------------------------------------------------------------------------------- | +| `dw`, `ciw`, `yap` | Select first, then act: `wd`, `miwc`, `mapy`. `w`, `e`, `b` and friends leave a selection behind | +| `v` then move | You are always selecting. `v` toggles select mode, where motions extend instead of replace | +| `x` | Selects the whole line (repeat to grow). `d` deletes what is selected | +| `%` | Selects the whole file. `mm` jumps to the matching bracket | +| `Ctrl-r` | `U` redoes, and `Ctrl-r` is mapped to it too | +| `K` for hover | `Space k` (or `Space l h`). `K` keeps selections matching a regex, which you will want | +| `.` repeat | Repeats the last insert. Multiple cursors cover most of what `.` did: `s` splits a selection | +| | into one cursor per regex match, `C` copies the cursor down, `,` collapses back to one | +| `:%s/a/b/g` | `%` to select all, `s` to pick the matches, then `c` and type. Live, with every match visible | +| `f`, `t` | Not confined to the line | +| `:terminal`, lazygit | No terminal. `Space g g` opens lazygit in a tmux popup; anywhere else `Ctrl-z` drops you to the | +| | shell and `fg` brings Helix back | +| `:Mason`, `:Lazy` | Nothing to manage. `hx --health` reports what each language found on PATH | +| which-key | Press `Space` and wait; the infobox lists the group. Same for `g`, `m`, `z`, `Ctrl-w` | +| `q:`, `:help` | `Space ?` searches every command by description | +| `gd`, `gr`, `gi`, `gy` | Same keys. `gd` definition, `gr` references, `gi` implementation, `gy` type definition | +| `]d`, `[d`, `]g`, `[g` | Same keys: diagnostics and git hunks. Also `]f` function, `]t` type, `]a` argument, `]p` paragraph | + +## Keybindings + +Notation: `Space` is the leader, `C-x` is Ctrl. Mode is normal unless a table says otherwise. Mappings marked (ours) +come from `helix/config.toml`; the rest are Helix defaults kept because they already matched. + +### Files and windows + +| Key | Action | +| ----------------------- | --------------------------------------------------------------- | +| `Space w` | Save (ours) | +| `Space q` / `Space Q` | Close view / close all views (ours) | +| `Space n` | New scratch buffer (ours) | +| `Space c` / `Space C` | Close buffer / force close (ours) | +| `Space e` / `Space E` | File explorer at workspace root / at this file's directory | +| `Space \|` / `Space \\` | Vertical / horizontal split (ours) | +| `C-h` `C-j` `C-k` `C-l` | Move between splits (ours) | +| `C-w` | Window mode: `v` `s` split, `q` close, `o` only, `H J K L` swap | +| `C-s` | Save, in normal and insert mode (ours) | +| `C-q` | Quit everything, discarding changes (ours, same as AstroNvim) | +| `]b` / `[b` | Next / previous buffer (ours) | +| `Esc` | Collapse to one cursor, drop extra selections (ours) | + +### Find (`Space f`) + +| Key | Action | +| ----------- | --------------------------------- | +| `Space f f` | Files in the workspace | +| `Space f F` | Files under the current directory | +| `Space f w` | Grep the workspace, live | +| `Space f c` | Grep the word under the cursor | +| `Space f b` | Buffers | +| `Space f s` | Symbols in this file | +| `Space f S` | Symbols in the workspace | +| `Space f j` | Jumplist | +| `Space f g` | Files changed in git | +| `Space '` | Reopen the last picker | + +### Buffers (`Space b`) + +| Key | Action | +| ------------------------- | ------------------------ | +| `Space b b` | Buffer picker | +| `Space b n` / `Space b p` | Next / previous buffer | +| `Space b d` | Close this buffer | +| `Space b c` | Close every other buffer | +| `Space b C` | Close all buffers | + +### Language tools (`Space l`) + +| Key | Action | +| ------------------------- | -------------------------------------- | +| `Space l a` | Code action | +| `Space l r` / `Space r` | Rename symbol | +| `Space l h` / `Space k` | Hover documentation | +| `Space l f` | Format buffer | +| `Space l s` / `Space l G` | Document / workspace symbols | +| `Space l d` / `Space l D` | Document / workspace diagnostics | +| `Space l R` | References | +| `Space l i` / `Space l y` | Implementation / type definition | +| `Space l l` | Restart the language servers | +| `Space l L` | Open the Helix log | +| `Space x x` / `Space x X` | Diagnostics picker, buffer / workspace | + +### Git (`Space g`) + +| Key | Action | +| ----------- | ------------------------------------------------------- | +| `Space g g` | lazygit in a tmux popup | +| `Space g f` | lazygit filtered to this file's history | +| `Space g s` | Picker of files changed in the working tree | +| `Space g b` | Blame the current line: commit, author, age and subject | +| `]g` / `[g` | Next / previous hunk | + +Outside tmux, `Space g g` prints a reminder instead of failing quietly: `Ctrl-z`, run lazygit, `fg`. + +### Agents (`Space a`) + +| Key | Action | +| ----------- | -------------------------------------------------------------------------------------------------------- | +| `Space a y` | Copy `path:line` for the cursor, or `path:start-end` for a multi-line selection, to the system clipboard | + +Works in normal and select mode. It uses `pbcopy`, `wl-copy` or `xclip`, whichever the box has. + +### Toggles (`Space u`) + +| Key | Toggles | +| ----------- | ------------------------------------------ | +| `Space u n` | Relative / absolute line numbers | +| `Space u w` | Soft wrap | +| `Space u i` | Inlay hints | +| `Space u g` | Indent guides | +| `Space u h` | Visible whitespace | +| `Space u c` | Cursor line highlight | +| `Space u b` | Bufferline | +| `Space u m` | Mouse | +| `Space u d` | Inline and end-of-line diagnostics | +| `Space u F` | Format on save, for every language at once | + +### Kept from Helix + +`Space y`, `Space p`, `Space P` and `Space R` move text through the system clipboard. `Space j` is the jumplist, +`Space h` selects every reference to the symbol under the cursor, `Space G` is the debugger, `Space /` comments the +selection (matching AstroNvim, and replacing Helix's `Space c`). Two defaults moved: `Space a` is the agents group, so +code actions are `Space l a`, and `Space w` saves, so window mode is `Ctrl-w`. + +## Statusline and bufferline + +The bar follows the heirline layout from Neovim: a colored mode block on the left (NORMAL, INSERT and SELECT, each with +a Nerd Font glyph, the LSP spinner beside it), then the git branch, the file name and its modified or read-only state. +The right side carries diagnostics for the buffer and the workspace as colored dots, the selection count and length, the +active register, position and percentage, and the file type. Sections sit on the SilkCircuit highlight surface with cyan +separators; the mode block takes purple, pink or cyan for normal, insert or select, the same hues heirline uses. Those +colors live in the SilkCircuit Helix theme, generated from the helix extra in that repo, because Helix draws the bar +from `ui.statusline` scopes rather than from config. + +With more than one buffer open the bufferline appears on top, active buffer in bold purple on the editor background, the +rest muted on the section surface, matching the heirline tabline. + +Helix has no custom statusline components, so a few heirline pieces have no equivalent: git added, changed and removed +counts, attached server names and the scrollbar. The spinner covers server activity and `Space l L` opens the log. + +## Language servers + +Everything below resolves to the binaries Mason installed for Neovim under `~/.local/share/nvim/mason/bin`, which +`sh/helix.sh` appends to PATH. Nothing gets installed twice, and a box that has never run Neovim shows the gaps in +`hx --health`. + +| Language | Server(s) | Formatter | +| ---------------------- | ----------------------------------------------------------- | ------------------------------- | +| Rust | rust-analyzer, with clippy as the check command | LSP | +| Python | ty, ruff | LSP | +| TypeScript, JavaScript | vtsls (tsx and jsx also get tailwindcss-ls) | prettier | +| HTML, CSS, SCSS | vscode html and css servers, tailwindcss-ls | prettier | +| JSON, YAML, Markdown | vscode-json-language-server, yaml-language-server, marksman | prettier | +| TOML | taplo | LSP | +| Lua | lua-language-server | stylua | +| Bash | bash-language-server | shfmt, honoring `.editorconfig` | +| Dockerfile, Compose | docker-language-server (compose adds yaml-language-server) | none | + +Formatting is off on save until you flip `Space u F`, matching the Neovim config. `Space l f` formats on demand. Helix +has no separate linter hook, so the markdownlint and yamllint passes that nvim-lint runs in Neovim stay in `make lint`. + +## Gotchas + +- `hx --health` warns that `~/.config/helix/runtime` does not exist. That is where a source build keeps grammars; the + Homebrew install ships them elsewhere and the warning is noise. +- Helix expands the first word of a `:sh` command only when the whole word is an expansion, so `s=%{cursor_line}` stays + literal there. `Space a y` goes through `set --` for exactly that reason. +- `git blame -l` prefixes boundary commits with `^`; `Space g b` uses `--porcelain` to get a clean hash. +- `Space f c` deliberately does not press Enter: global search runs as you type, and Enter would jump to the first match + instead of leaving the picker open. +- Run `make install` after pulling: it links the two files and lets the SilkCircuit installer lay down the themes. diff --git a/dotbot.d/base.yaml b/dotbot.d/base.yaml index 39220e7..64753c1 100644 --- a/dotbot.d/base.yaml +++ b/dotbot.d/base.yaml @@ -80,6 +80,11 @@ ~/.config/nvim: path: nvim force: true + # Helix reads these two files from ~/.config/helix, and the SilkCircuit + # installer drops its themes into ~/.config/helix/themes, so the files + # are linked rather than the directory. + ~/.config/helix/config.toml: helix/config.toml + ~/.config/helix/languages.toml: helix/languages.toml ~/bin: bin ~/.tmux/plugins/tpm: tpm diff --git a/helix/README.md b/helix/README.md new file mode 100644 index 0000000..a6d25c4 --- /dev/null +++ b/helix/README.md @@ -0,0 +1,11 @@ +# Helix + +Helix 25.07 in the SilkCircuit glow theme, with the Space leader laid out like the AstroNvim config next door. +`~/.config/helix/config.toml` and `languages.toml` link here. + +- `config.toml` holds editor options and the keymap. Motions stay stock Helix; the Space groups mirror Neovim. +- `languages.toml` wires the language servers and formatters, the same binaries the Neovim config installs through + Mason. `sh/helix.sh` puts them on PATH. +- `~/.config/helix/themes/` is filled by the SilkCircuit installer and is not tracked here. + +The full tour lives in `docs/helix/`. diff --git a/helix/config.toml b/helix/config.toml new file mode 100644 index 0000000..3aac85a --- /dev/null +++ b/helix/config.toml @@ -0,0 +1,214 @@ +# Helix, tuned for hands that learned AstroNvim. +# +# Motions, selections and the g/m/z minor modes stay stock Helix: the +# select-then-act model is the reason to be here, so nothing below tries +# to turn it back into Vim. What does carry over is the Space leader +# layout from the Neovim config in this repo (f find, b buffers, l language +# tools, g git, u toggles, x diagnostics, a agents) plus a handful of +# reflexes (Ctrl-s, ]b/[b, Esc clearing the selection). Space e is already +# the file explorer and Space k is hover, so those needed no remap. +# +# The SilkCircuit installer owns ~/.config/helix/themes. `:config-reload` +# picks up edits here; `hx --health ` shows what each language +# resolved to. + +theme = "silkcircuit-glow" + +[editor] +line-number = "relative" +cursorline = true +scrolloff = 6 +bufferline = "multiple" +color-modes = true +true-color = true +undercurl = true +popup-border = "all" +text-width = 120 +completion-timeout = 50 +end-of-line-diagnostics = "hint" +# Master switch, like g.autoformat in the Neovim config. Every language in +# languages.toml with a formatter sets auto-format = true, so flipping this +# with Space u F turns format-on-save on for all of them at once. +auto-format = false + +[editor.inline-diagnostics] +cursor-line = "warning" + +[editor.lsp] +display-inlay-hints = true + +[editor.cursor-shape] +normal = "block" +insert = "bar" +select = "underline" + +[editor.file-picker] +# Neo-tree shows dotfiles; so does this picker. .gitignore still applies. +hidden = false + +[editor.indent-guides] +render = true +character = "│" +skip-levels = 1 + +# Statusline, laid out like heirline: mode block, branch, file and its +# state on the left; diagnostics, selection, position and filetype on the +# right. Helix paints the bar from the theme (ui.statusline.* in the +# SilkCircuit helix theme), so this side only picks elements, the +# separator glyph and the mode labels. Nerd Font glyphs: terminal for +# normal, pencil for insert, select-all for select. +[editor.statusline] +left = [ + "mode", + "spinner", + "version-control", + "separator", + "file-name", + "file-modification-indicator", + "read-only-indicator", +] +center = [] +right = [ + "diagnostics", + "workspace-diagnostics", + "separator", + "selections", + "primary-selection-length", + "register", + "separator", + "position", + "position-percentage", + "separator", + "file-type", +] +separator = "│" +mode.normal = " NORMAL" +mode.insert = " INSERT" +mode.select = "󰒅 SELECT" + +[editor.soft-wrap] +enable = false + +# ───────────────────────────────────────────────────────────────────── +# Reflexes +# ───────────────────────────────────────────────────────────────────── + +[keys.normal] +C-s = ":write" +C-q = ":quit-all!" +C-r = "redo" +C-h = "jump_view_left" +C-j = "jump_view_down" +C-k = "jump_view_up" +C-l = "jump_view_right" +# Vim's Esc clears the highlight; here it collapses to one cursor. +esc = ["collapse_selection", "keep_primary_selection"] + +[keys.normal."]"] +b = "goto_next_buffer" + +[keys.normal."["] +b = "goto_previous_buffer" + +[keys.insert] +C-s = ["normal_mode", ":write"] + +# ───────────────────────────────────────────────────────────────────── +# Space leader, AstroNvim layout +# +# Helix defaults kept as-is: Space e/E explorer, Space k hover, Space r +# rename, Space s/S symbols, Space d/D diagnostics, Space j jumplist, +# Space h references, Space ' last picker, Space ? palette, Space y/p/P/R +# clipboard, Space G debug. Space a becomes the agents group below, so code +# actions live at Space l a, as in AstroNvim. +# ───────────────────────────────────────────────────────────────────── + +[keys.normal.space] +w = ":write" +q = ":quit" +Q = ":quit-all" +n = ":new" +c = ":buffer-close" +C = ":buffer-close!" +"/" = "toggle_comments" +"|" = "vsplit" +"\\" = "hsplit" + +# Find +[keys.normal.space.f] +f = "file_picker" +F = "file_picker_in_current_directory" +w = "global_search" +b = "buffer_picker" +s = "symbol_picker" +S = "workspace_symbol_picker" +j = "jumplist_picker" +g = "changed_file_picker" +# Word under the cursor, searched across the project: select it, push it +# into the search register, open global search and paste it in. The picker +# searches as you type, so no Enter: that would jump to the first hit. +c = "@miw*fw/" + +# Buffers +[keys.normal.space.b] +b = "buffer_picker" +n = "goto_next_buffer" +p = "goto_previous_buffer" +d = ":buffer-close" +c = ":buffer-close-others" +C = ":buffer-close-all" + +# Language tools +[keys.normal.space.l] +a = "code_action" +r = "rename_symbol" +h = "hover" +f = ":format" +s = "symbol_picker" +G = "workspace_symbol_picker" +d = "diagnostics_picker" +D = "workspace_diagnostics_picker" +R = "goto_reference" +i = "goto_implementation" +y = "goto_type_definition" +l = ":lsp-restart" +L = ":log-open" + +# Git. lazygit rides a tmux popup because Helix has no terminal of its +# own; outside tmux the shell one-liner says so instead of failing quietly. +[keys.normal.space.g] +g = ':sh if [ -n "$TMUX" ]; then tmux display-popup -E -w 90%% -h 90%% -d "$PWD" lazygit; else echo "lazygit popup needs tmux: C-z, lazygit, fg"; fi' +f = ':sh if [ -n "$TMUX" ]; then tmux display-popup -E -w 90%% -h 90%% -d "$PWD" lazygit -f "%{buffer_name}"; else echo "lazygit popup needs tmux: C-z, lazygit, fg"; fi' +s = "changed_file_picker" +b = ':sh git log -1 --format="%%h %%an, %%ar%%n%%s" $(git blame --porcelain -L %{cursor_line},+1 -- %{buffer_name} | head -1 | cut -d" " -f1)' + +# Agents: copy a file:line reference the way Claude Code likes it, spanning +# the selection when it covers more than one line. The variables sit behind +# `set --` because Helix expands the first word of a :sh command only when +# the whole word is an expansion: `s=%{selection_line_start}` stays literal. +[keys.normal.space.a] +y = ':sh set -- %{selection_line_start} %{selection_line_end} %{buffer_name}; if [ "$1" = "$2" ]; then r="$1"; else r="$1-$2"; fi; if command -v pbcopy >/dev/null 2>&1; then printf "%%s" "$3:$r" | pbcopy; elif command -v wl-copy >/dev/null 2>&1; then printf "%%s" "$3:$r" | wl-copy; else printf "%%s" "$3:$r" | xclip -selection clipboard; fi; echo "copied $3:$r"' + +# UI toggles +[keys.normal.space.u] +n = ":toggle line-number relative absolute" +w = ":toggle soft-wrap.enable" +i = ":toggle lsp.display-inlay-hints" +g = ":toggle indent-guides.render" +h = ":toggle whitespace.render all none" +c = ":toggle cursorline" +b = ":toggle bufferline multiple never" +m = ":toggle mouse" +F = ":toggle auto-format" +d = [":toggle end-of-line-diagnostics hint disable", ":toggle inline-diagnostics.cursor-line warning disable"] + +# Diagnostics lists (Trouble's corner) +[keys.normal.space.x] +x = "diagnostics_picker" +X = "workspace_diagnostics_picker" + +[keys.select.space] +"/" = "toggle_comments" + +[keys.select.space.a] +y = ':sh set -- %{selection_line_start} %{selection_line_end} %{buffer_name}; if [ "$1" = "$2" ]; then r="$1"; else r="$1-$2"; fi; if command -v pbcopy >/dev/null 2>&1; then printf "%%s" "$3:$r" | pbcopy; elif command -v wl-copy >/dev/null 2>&1; then printf "%%s" "$3:$r" | wl-copy; else printf "%%s" "$3:$r" | xclip -selection clipboard; fi; echo "copied $3:$r"' diff --git a/helix/languages.toml b/helix/languages.toml new file mode 100644 index 0000000..231ba71 --- /dev/null +++ b/helix/languages.toml @@ -0,0 +1,143 @@ +# Language servers and formatters, mirroring the AstroNvim language packs. +# +# Helix ships sensible defaults for every language here; this file only +# swaps servers for the ones Mason already installs (see sh/helix.sh for +# how those reach PATH), trims servers that are not installed so the +# health report stays honest, and wires the same formatters conform uses +# in Neovim. Each formatted language sets auto-format = true so the global +# editor.auto-format switch in config.toml governs all of them at once. + +# ───────────────────────────────────────────────────────────────────── +# Servers Helix does not define out of the box +# ───────────────────────────────────────────────────────────────────── + +[language-server.vtsls] +command = "vtsls" +args = ["--stdio"] + +[language-server.vtsls.config] +# Match the Neovim setup: rename and imports from vtsls, formatting from +# prettier below. +typescript.format.enable = false +javascript.format.enable = false + +# Docker's own server, the one Mason installs; it covers Dockerfiles and +# compose files in a single process. +[language-server.docker-language-server] +command = "docker-language-server" +args = ["start", "--stdio"] + +# Helix merges languages.toml three levels deep, so a user [config] table +# replaces the default one wholesale. This is the 25.07.1 default block plus +# clippy as the check command. +[language-server.rust-analyzer.config] +check.command = "clippy" +files.watcher = "server" +inlayHints.bindingModeHints.enable = false +inlayHints.closingBraceHints.minLines = 10 +inlayHints.closureReturnTypeHints.enable = "with_block" +inlayHints.discriminantHints.enable = "fieldless" +inlayHints.lifetimeElisionHints.enable = "skip_trivial" +inlayHints.typeHints.hideClosureInitialization = false + +# ───────────────────────────────────────────────────────────────────── +# Languages +# ───────────────────────────────────────────────────────────────────── + +[[language]] +name = "python" +language-servers = ["ty", "ruff"] +auto-format = true + +[[language]] +name = "rust" +auto-format = true + +[[language]] +name = "typescript" +language-servers = ["vtsls"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "tsx" +language-servers = ["vtsls", "tailwindcss-ls"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "javascript" +language-servers = ["vtsls"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "jsx" +language-servers = ["vtsls", "tailwindcss-ls"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "json" +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "jsonc" +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "css" +language-servers = ["vscode-css-language-server", "tailwindcss-ls"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "scss" +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "html" +language-servers = ["vscode-html-language-server", "tailwindcss-ls"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "yaml" +language-servers = ["yaml-language-server"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "toml" +language-servers = ["taplo"] +auto-format = true + +[[language]] +name = "markdown" +language-servers = ["marksman"] +formatter = { command = "prettier", args = ["--stdin-filepath", "%{buffer_name}"] } +auto-format = true +text-width = 120 +soft-wrap = { enable = true, wrap-at-text-width = true } + +[[language]] +name = "lua" +formatter = { command = "stylua", args = ["--search-parent-directories", "--stdin-filepath", "%{buffer_name}", "-"] } +auto-format = true + +[[language]] +name = "bash" +# shfmt reads the repo .editorconfig once it knows the file name. +formatter = { command = "shfmt", args = ["--filename", "%{buffer_name}"] } +auto-format = true + +[[language]] +name = "dockerfile" +language-servers = ["docker-language-server"] + +[[language]] +name = "docker-compose" +language-servers = ["docker-language-server", "yaml-language-server"] diff --git a/herdr/plugins/moniker/moniker.py b/herdr/plugins/moniker/moniker.py index 3ca8c72..8a51a9e 100644 --- a/herdr/plugins/moniker/moniker.py +++ b/herdr/plugins/moniker/moniker.py @@ -221,9 +221,11 @@ def name_pane(pane_id: str, force: bool) -> None: def on_event() -> None: try: - event = json.loads(os.environ.get("HERDR_PLUGIN_EVENT_JSON") or "{}") + envelope = json.loads(os.environ.get("HERDR_PLUGIN_EVENT_JSON") or "{}") except ValueError: return + # Herdr wraps the payload: {"event": "...", "data": {"agent_status": ...}}. + event = envelope.get("data") if isinstance(envelope.get("data"), dict) else envelope if event.get("agent_status") != "working": return pane_id = event.get("pane_id") or os.environ.get("HERDR_PANE_ID") diff --git a/macos/Brewfile b/macos/Brewfile index c89f365..be32cac 100644 --- a/macos/Brewfile +++ b/macos/Brewfile @@ -18,6 +18,7 @@ brew "git-delta" # Syntax-highlighting pager for git brew "gnu-sed" # GNU implementation of the famous stream editor brew "go" # Open source programming language brew "grep" # GNU grep, egrep and fgrep +brew "helix" # Post-modern modal text editor brew "btop" # Resource monitor (C++ htop/top alternative) brew "htop" # Improved top (interactive process viewer) brew "jq" # Lightweight and flexible command-line JSON processor diff --git a/packages.conf b/packages.conf index ba349b1..4f0d969 100644 --- a/packages.conf +++ b/packages.conf @@ -46,6 +46,7 @@ golang-backports desktop ppa=ppa:longsleep/golang-backports git-core desktop,server ppa=ppa:git-core/ppa fastfetch desktop ppa=ppa:zhangsongcui3371/fastfetch +helix-editor desktop,server ppa=ppa:maintainers/helix-editor [Basic development tools] build-essential desktop,server apt pacman=base-devel @@ -56,6 +57,7 @@ git desktop,server apt=git-core pacman winget=Git.Git go desktop apt=golang-go pacman winget=GoLang.Go inetutils desktop pacman neovim desktop,server apt pacman winget=Neovim.Neovim +helix desktop,server apt pacman winget=Helix.Helix ninja desktop apt=ninja-build pacman winget=Ninja-build.Ninja pkg-config desktop,server apt pacman python desktop,server apt=python-is-python3 pacman winget=Python.Python.3.12 diff --git a/sh/helix.sh b/sh/helix.sh new file mode 100644 index 0000000..28f733b --- /dev/null +++ b/sh/helix.sh @@ -0,0 +1,21 @@ +# helix.sh +# Helix borrows Neovim's toolbox. +# https://helix-editor.com +# +# Mason installs every language server and formatter the Neovim config +# uses under ~/.local/share/nvim/mason/bin, and Helix resolves the same +# binaries by name on PATH. Appending that directory means ruff, ty, vtsls, +# marksman, taplo, prettier and friends light up in Helix with no second +# install, while brew, rustup and proto keep winning for anything they also +# ship. `hx --health ` shows what each language resolved to. +# +# No role guard: a box without Mason simply has nothing to append. + +_mason_bin="${HOME}/.local/share/nvim/mason/bin" +if [[ -d "${_mason_bin}" ]]; then + case ":${PATH}:" in + *":${_mason_bin}:"*) ;; + *) export PATH="${PATH}:${_mason_bin}" ;; + esac +fi +unset _mason_bin