diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa7f35..9ff3686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ All notable changes to HYPERfix.nvim are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.3] - 2025-12-31 + +### ✨ Added + +- **Smart keyword skipping** — `` now skips language keywords (lua: `then`, `do`, `end`, `else`, `elseif`) in addition to closing punctuation; filetype-aware for easy extension to other languages +- **Insert mode exit** — `` (Shift+Backspace) to exit insert mode faster than Esc +- **CAPS LOCK detection** — Overrode `J` keymap to warn when likely CAPS LOCK is on instead of joining lines (use `:join` if you need the original behavior) + +### 📚 Documentation + +- **KEYMAPS.md update** — Added new keymaps to "Smart Skip", "Insert Mode Control", and "Normal Mode Utilities" sections + +--- + ## [1.0.2] - 2025-12-27 ### 🔧 Fixed diff --git a/KEYMAPS.md b/KEYMAPS.md index e4f1622..326276f 100644 --- a/KEYMAPS.md +++ b/KEYMAPS.md @@ -49,11 +49,23 @@ ## Text Editing -### Smart Closing Punctuation Skip (Insert Mode) +### Smart Skip (Insert Mode) -| Keymap | Mode | Action | -| ------- | ------ | ------------------------------------------------- | -| `` | Insert | Skip past closing punctuation `)` `}` `]` `'` `"` | +| Keymap | Mode | Action | +| ------- | ------ | ----------------------------------------------------------- | +| `` | Insert | Skip past closing punctuation `)` `}` `]` `'` `"` or keywords | + +### Insert Mode Control + +| Keymap | Mode | Action | +| -------- | ------ | ----------------------- | +| `` | Insert | Exit insert mode | + +### Normal Mode Utilities + +| Keymap | Mode | Action | +| ------ | ------ | ---------------------------------------- | +| `J` | Normal | CAPS LOCK detection (warns instead of join) | ### Visual Mode Indentation diff --git a/README.md b/README.md index 4f29e7b..40571df 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ HYPERfix is built around principles that help **ADHD, autism, dyslexia, and othe - **Clear visual hierarchy** — 4px line spacing + WCAG AAA contrast ratios - **Thoughtful pacing** — Longer timeouts (1250) for key sequences—time to think - **Mnemonic keymaps** — `f` = find, `g` = git. Patterns you can predict +- **Smart text insertion** — Skip closing punctuation and language keywords (`` for punctuation/keywords, `` to exit insert mode) +- **CAPS LOCK detection** — Overridden `J` warns you if CAPS LOCK is on (a common mistake after exiting insert mode) - **Explicit documentation** — Every code block explains WHAT/WHY/HOW - **Graceful degradation** — Missing optional tools won't break your editor diff --git a/lazy-lock.json b/lazy-lock.json index 95b0679..5ef1cd9 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -3,7 +3,7 @@ "amp.nvim": { "branch": "main", "commit": "3b9ad5ef0328de1b35cc9bfa723a37db5daf9434" }, "blink-ripgrep.nvim": { "branch": "main", "commit": "71027ced21dfc27d3466ebc569d9987f3b8d15c1" }, "blink.cmp": { "branch": "main", "commit": "b19413d214068f316c78978b08264ed1c41830ec" }, - "conform.nvim": { "branch": "master", "commit": "df83eeaab265dacd2eef139a78e502a3f8926618" }, + "conform.nvim": { "branch": "master", "commit": "4b713b9da0061a54750bfed457e190459be28c7b" }, "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, "grug-far.nvim": { "branch": "main", "commit": "74eef260e1142264ab994fb9c88e4f420e9486d7" }, @@ -18,9 +18,9 @@ "nvim-dap": { "branch": "master", "commit": "818cd8787a77a97703eb1d9090543a374f79a9ac" }, "nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" }, "nvim-lint": { "branch": "master", "commit": "1f19dacd945a7b1a57f29f32b2d7168384df3d36" }, - "nvim-lspconfig": { "branch": "master", "commit": "d696e36d5792daf828f8c8e8d4b9aa90c1a10c2a" }, + "nvim-lspconfig": { "branch": "master", "commit": "41ceb6bba3a40128b7841f5b7f5a9dae7201e823" }, "nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" }, - "nvim-treesitter": { "branch": "main", "commit": "7efc1b58a8061d29786860006c7257c90a5196dc" }, + "nvim-treesitter": { "branch": "main", "commit": "c6dd314086f7b471bf6c9110092a94ce1c06d220" }, "nvim-treesitter-context": { "branch": "master", "commit": "64dd4cf3f6fd0ab17622c5ce15c91fc539c3f24a" }, "nvim-treesitter-textobjects": { "branch": "main", "commit": "ecd03f5811eb5c66d2fa420b79121b866feecd82" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua index d5e8798..1602f07 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -130,26 +130,73 @@ map("i", ".", ".u") map("i", ";", ";u") -- ============================================================================= --- SMART CLOSING PUNCTUATION SKIP +-- SMART SKIP: Punctuation & Keywords -- ----------------------------------------------------------------------------- --- WHAT: Skip past closing punctuation in insert mode --- WHY: Streamlines workflow—jump over ) } ] ' " without arrow keys --- HOW: Checks if next character is closing punctuation, moves cursor forward +-- WHAT: Skip past closing punctuation or language keywords in insert mode +-- WHY: Streamlines workflow—jump over ) } ] ' " or then/do/end without arrows +-- HOW: Checks punctuation first, then keywords by filetype; moves cursor past match +-- NOTE: Keywords are organized by filetype for easy extension (see table below) -- ----------------------------------------------------------------------------- +local skip_keywords_by_filetype = { + lua = { "then", "do", "end", "else", "elseif" }, + -- TODO: add python, javascript, etc. +} + map("i", "", function() local line = vim.api.nvim_get_current_line() local row, col = unpack(vim.api.nvim_win_get_cursor(0)) - local next_char = line:sub(col + 1, col + 1) + local remaining = line:sub(col + 1) - if next_char:match("[%)%]%}%\"%']") then + -- Try punctuation first + if remaining:match("^[%)%]%}%\"%']") then vim.api.nvim_win_set_cursor(0, { row, col + 1 }) + return + end + + -- Try keywords for current filetype + local ft = vim.bo.filetype + local keywords = skip_keywords_by_filetype[ft] or {} + + for _, keyword in ipairs(keywords) do + -- Match keyword followed by a word boundary (non-alphanumeric or end of line) + local match_start, match_end = remaining:find("^" .. keyword .. "($|%W)") + if match_start then + -- We only want to advance past the keyword itself, not the boundary character + vim.api.nvim_win_set_cursor(0, { row, col + #keyword }) + return + end end -end, { noremap = true, silent = true, desc = "Skip past closing punctuation" }) +end, { noremap = true, silent = true, desc = "Skip past punctuation or keywords" }) + +-- ============================================================================= +-- EXIT INSERT MODE +-- ============================================================================= +-- WHAT: Exit insert mode with Shift+Backspace +-- WHY: Faster than Esc; easier to reach after typing +-- HOW: Maps Shift+Backspace to Esc in insert mode +-- NOTE: Works well alongside CAPS LOCK detection (see J keymap below) +-- ============================================================================= +map("i", "", "", { noremap = true, silent = true, desc = "Exit Insert Mode" }) +map("i", "", "", { noremap = true, silent = true, desc = "Exit Insert Mode" }) +map("i", "", "", { noremap = true, silent = true, desc = "Exit Insert Mode" }) + +-- ============================================================================= +-- CAPS LOCK DETECTION +-- ============================================================================= +-- WHAT: Warn when J is pressed (likely CAPS LOCK is on) +-- WHY: Prevents accidental line joins; CAPS LOCK is often forgotten after exiting insert mode +-- HOW: Overrides J with a notification function instead of joining lines +-- NOTE: Use :join or :j command if you actually need to join lines +-- ============================================================================= + +map("n", "J", function() + Snacks.notify.warn("CAPS LOCK may be on—press to exit insert mode properly!") +end, { noremap = true, silent = true, desc = "CAPS LOCK Detection" }) -- ============================================================================= -- FILE MANAGEMENT --- ----------------------------------------------------------------------------- +-- ============================================================================= map({ "i", "x", "n", "s" }, "", "w", { desc = "Save File" }) map("n", "fn", "enew", { desc = "[N]ew File" })