A Zed editor extension that toggles boolean-like values in any language
| A side | B side | Variants (all automatically detected & preserved) |
|---|---|---|
true |
false |
true / True / TRUE |
yes |
no |
yes / Yes / YES |
on |
off |
on / On / ON |
1 |
0 |
(numeric — no case to preserve) |
The extension detects the case style of the token under your cursor and applies the same style to the replacement:
true → false (lowercase)
True → False (Title case)
TRUE → FALSE (UPPER CASE)
tRuE → false (Mixed → falls back to lowercase)
The same logic applies to YES/NO, ON/OFF, etc.
// TypeScript / JavaScript
const debug = true; // → false
if (enabled === FALSE) … // → TRUE
// Python / YAML config
verbose: yes // → no
mode: ON // → OFF
// Any config / markdown
enabled = 1 // → 0
active: Yes // → NoThe extension is active in 40+ languages out of the box:
To add more, append Zed's language name to the languages = [...] array in
extension.toml. The canonical names are listed in Zed's default settings
under "languages".
Zed editor
│ 1. Opens any supported file → spawns boolean-toggle-lsp via stdin/stdout
│ 2. User presses Code Actions (`ctrl-.`)
│ 3. Zed sends textDocument/codeAction with cursor line + column
│
LSP server
│ 4. Finds which keyword the cursor is on (case-insensitive scan)
│ 5. Detects case style: Lower / Title / Upper / Mixed
│ 6. Builds replacement with matching case style
│ 7. Returns CodeAction { WorkspaceEdit { newText: "<replacement>" } }
│
Zed editor
8. User selects the action → edit applied, undoable with Ctrl+Z
Line: "const DEBUG = TRUE && isOn"
Cols: 0 6 14 19 25
^^^^ (TRUE → cols 14–17)
^^^ (ON ← rejected: part of "isOn")
For each keyword in TOGGLE_PAIRS the function:
- Slides a case-insensitive window of
keyword.len()bytes across the line. - Verifies word boundaries: the byte before and after must not match
[A-Za-z0-9_$]— this rejectstrueValue,isFalse,$true,10, etc. - Checks
cursor_col ∈ [token_start, token_end](inclusive on both ends — a cursor right after the last character still counts).
All keywords are ASCII, so byte offsets equal UTF-16 code-unit offsets (what LSP uses for column positions).
detect_case_style("TRUE") → Upper (all alpha chars uppercase)
detect_case_style("True") → Title (first upper, rest lower)
detect_case_style("true") → Lower (all lowercase)
detect_case_style("tRuE") → Mixed (fallback → lowercase replacement)
detect_case_style("1") → Lower (no alpha chars → treat as lower)| Tool | Notes |
|---|---|
| Rust + Cargo | stable ≥ 1.78 |
wasm32-wasip1 target |
make dev installs it automatically |
| Zed | 0.140+ recommended |
# 1. Clone
git clone https://github.com/unlight/zed-boolean-toggle
cd zed-boolean-toggle
# 2. Build + install
make devmake dev does three things:
- builds the native lsp binary
- copies it to
~/.cargo/bin(on$PATH) - builds the WASM
Open the Extensions panel (⌘⇧X / Ctrl⇧X) → "Install Dev Extension" → select this directory.
- Place the cursor on any supported token (
true,YES,on,1, …) - Press Ctrl + Alt + X — the code-actions panel opens
- The panel shows exactly one action, e.g.
Toggle: TRUE → FALSE - Press Enter (or click) to apply
When the cursor is not on a toggle token, editor::ToggleCodeActions
falls through to other code actions from TypeScript, ESLint, etc. — no
interference.
Tip: the action is marked
"isPreferred": true. If a future Zed version adds an "apply preferred action" command, you'll be able to bind that to get a truly single-keystroke toggle.
make testThe suite covers:
| Category | Examples |
|---|---|
| All four pair types | true/false, yes/no, on/off, 1/0 |
| Three case styles | lower, Title, UPPER |
| Mixed case fallback | tRuE → false |
| Cursor positions | start, middle, end, one-past-end of token |
| Word boundaries | trueValue, isFalse, $true, 10, online, notable, yesterday |
| Multiple tokens per line | Cursor selects the right one |
| WorkspaceEdit ranges | Exact character positions verified |
| Action metadata | isPreferred, kind, title format |
| Server dispatch | initialize, didOpen, didChange, didClose |
| Transport | Content-Length framing round-trip |
# Native LSP binary
cargo build --release
# → target/release/boolean-toggle-lsp
# WASM extension
rustup target add wasm32-wasip1
cargo build --target wasm32-wasip1 --release
# → target/wasm32-wasip1/release/boolean_toggle.wasmFor the Zed extension marketplace, bundle pre-built binaries instead of relying on PATH:
// extension/lib.rs
fn language_server_command(
&mut self,
_id: &LanguageServerId,
_worktree: &zed::Worktree,
) -> Result<zed::Command> {
let (os, arch) = zed::current_platform();
let binary = self.download_if_needed(os, arch)?; // cache in extension dir
Ok(zed::Command { command: binary, args: vec![], env: vec![] })
}Upload platform binaries (linux-x86_64, linux-aarch64, macos-x86_64,
macos-aarch64, windows-x86_64) to a GitHub Release and download them
lazily on first use via Zed's zed::download_file API. See the
Zed extension docs
for the full API.
Edit TOGGLE_PAIRS in src/main.rs:
const TOGGLE_PAIRS: &[(&str, &str)] = &[
("true", "false"),
("yes", "no"),
("on", "off"),
("1", "0"),
// Add yours:
("enabled", "disabled"), // ← new
("allow", "deny"), // ← new
];Rules for new pairs:
- Always lowercase canonical form (case detection/application is automatic)
- Word-boundary checking is automatic — no extra configuration needed
- Rebuild with
make buildandcargo install --path .
- Fork → branch →
make testmust pass green - Every new toggle pair or behaviour needs a matching test in
main.rs - No new runtime dependencies without discussion —
serde_jsonis the only one
MIT License (c) 2026