diff --git a/README.md b/README.md index 8a90990..4266e83 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ + # nvim-spider 🕷️🕸️ + badge @@ -14,26 +16,28 @@ mode. Supports counts and dot-repeat. -- [Features](#features) - * [Subword Motion](#subword-motion) - * [Skipping Insignificant Punctuation](#skipping-insignificant-punctuation) -- [Installation](#installation) -- [Configuration](#configuration) - * [Advanced: Custom Movement Patterns](#advanced-custom-movement-patterns) -- [Special Cases](#special-cases) - * [UTF-8 support](#utf-8-support) - * [Subword Text Object](#subword-text-object) - * [Operator-pending Mode: The case of `cw`](#operator-pending-mode-the-case-of-cw) - * [Motions in Insert Mode](#motions-in-insert-mode) -- [Credits](#credits) +- [Features](#features) + - [Subword Motion](#subword-motion) + - [Skipping Insignificant Punctuation](#skipping-insignificant-punctuation) +- [Installation](#installation) +- [Configuration](#configuration) + - [Advanced: Custom Movement Patterns](#advanced-custom-movement-patterns) +- [Special Cases](#special-cases) + - [UTF-8 support](#utf-8-support) + - [Subword Text Object](#subword-text-object) + - [Operator-pending Mode: The case of `cw`](#operator-pending-mode-the-case-of-cw) + - [Motions in Insert Mode](#motions-in-insert-mode) +- [Credits](#credits) ## Features + The `w`, `e`, `b` (and `ge`) motions work the same as the default ones by vim, except for two differences: ### Subword Motion + The movements happen by subwords, meaning it stops at the sub-parts of a camelCase, SCREAMING_SNAKE_CASE, or kebab-case variable. @@ -48,6 +52,7 @@ local myVariableName = FOO_BAR_BAZ ``` ### Skipping Insignificant Punctuation + A sequence of one or more punctuation characters is considered significant if it is surrounded by whitespace and does not include any non-punctuation characters. @@ -91,6 +96,18 @@ call. "lua require('spider').motion('e')", mode = { "n", "o", "x" }, }, + { -- example using an explicit function + "w", + function() + require('spider').motion('w', { + customPatterns = { + patterns = { ('%x'):rep(6) .. '+' }, + overrideDefault = true, + }, + }) + end, + mode = { 'n', 'o', 'x' }, + }, }, }, @@ -124,13 +141,16 @@ vim.keymap.set( { desc = "Spider-b" } ) ``` + + > [!NOTE] > For dot-repeat to work, you have to call the motions as Ex-commands. When > using `function() require("spider").motion("w") end` as third argument of > the keymap, dot-repeatability will not work. ## Configuration + The `.setup()` call is optional. ```lua @@ -138,7 +158,7 @@ The `.setup()` call is optional. require("spider").setup { skipInsignificantPunctuation = true, subwordMovement = true, - customPatterns = {}, -- overrides other settings if not-empty. See README. + customPatterns = {}, -- check Custom Movement Patterns for details } ``` @@ -152,6 +172,7 @@ Any options passed here will be used, and override the options set in the `setup()` call. ### Advanced: Custom Movement Patterns + You can use the `customPatterns` table to define custom movement patterns. These must be [lua patterns](https://www.lua.org/manual/5.4/manual.html#6.4.1), and they must be symmetrical (work the same backwards and forwards) to work @@ -179,8 +200,14 @@ require("spider").motion("w", { -- The motion stops only at hashes like `ef82a2`, avoiding repetition by using -- `string.rep()`. +-- Extend default patterns by passing a `patterns` table and +-- setting `overrideDefault` to false. require("spider").motion("w", { - customPatterns = { ("%x"):rep(6) .. "+" }, + customPatterns = { + patterns = { + ("%x"):rep(6) .. "+" }, + }, + overrideDefault = false, }) -- The motion stops at the next declaration of a variable in -- javascript. @@ -192,14 +219,17 @@ require("spider").motion("e", { ``` > [!NOTE] -> Setting the option overrides `nvim-spider`'s default behavior, meaning subword +> The customPatterns option overrides `nvim-spider`'s default behavior, meaning subword > movement and skipping of punctuation are disabled. You can add -> `customPatterns` as an option to the `.motion` call to create extra motions, +> `customPatterns` as an option to the `.motion` call to create new motions, > while still having access `nvim-spider`'s default behavior. +> Pass a patterns table and set overrideDefault to false to extend +> `nvim-spider`'s default behavior with a new pattern. ## Special Cases ### UTF-8 support + For adding UTF-8 support for matching non-ASCII text, add `luautf8` as rocks. You can do so directly in `packer.nvim` or via dependency on `nvim_rocks` in `lazy.nvim`. @@ -221,15 +251,18 @@ You can do so directly in `packer.nvim` or via dependency on `nvim_rocks` in ``` ### Subword Text Object + This plugin supports `w`, `e`, and `b` in operator-pending mode, but does not include a subword variant of `iw`. For a version of `iw` that considers camelCase, check out the `subword` text object of [nvim-various-textobjs](https://github.com/chrisgrieser/nvim-various-textobjs). + ### Operator-pending Mode: The case of `cw` + In operator pending mode, vim's `web` motions are actually a bit inconsistent. -For instance, `cw` will change to the *end* of a word instead of the start of +For instance, `cw` will change to the _end_ of a word instead of the start of the next word, like `dw` does. This is probably done for convenience in vi's early days before there were text objects. In my view, this is quite problematic since it makes people habitualize inconsistent motion behavior. @@ -258,26 +291,28 @@ vim.keymap.set("i", "", "lua require('spider').motion('b')i") ``` ## Credits -__Thanks__ + +**Thanks** To `@vypxl` and `@ii14` [for figuring out dot-repeatability](https://github.com/chrisgrieser/nvim-spider/pull/4). -__About Me__ +**About Me** In my day job, I am a sociologist studying the social mechanisms underlying the digital economy. For my PhD project, I investigate the governance of the app economy and how software ecosystems manage the tension between innovation and compatibility. If you are interested in this subject, feel free to get in touch. -__Blog__ +**Blog** I also occasionally blog about vim: [Nano Tips for Vim](https://nanotipsforvim.prose.sh) -__Profiles__ -- [reddit](https://www.reddit.com/user/pseudometapseudo) -- [Discord](https://discordapp.com/users/462774483044794368/) -- [Academic Website](https://chris-grieser.de/) -- [Twitter](https://twitter.com/pseudo_meta) -- [Mastodon](https://pkm.social/@pseudometa) -- [ResearchGate](https://www.researchgate.net/profile/Christopher-Grieser) -- [LinkedIn](https://www.linkedin.com/in/christopher-grieser-ba693b17a/) +**Profiles** + +- [reddit](https://www.reddit.com/user/pseudometapseudo) +- [Discord](https://discordapp.com/users/462774483044794368/) +- [Academic Website](https://chris-grieser.de/) +- [Twitter](https://twitter.com/pseudo_meta) +- [Mastodon](https://pkm.social/@pseudometa) +- [ResearchGate](https://www.researchgate.net/profile/Christopher-Grieser) +- [LinkedIn](https://www.linkedin.com/in/christopher-grieser-ba693b17a/) 0 then return opts.customPatterns end + + -- need to check if opts.customPatterns is a string array to avoid breaking changes. + if opts.customPatterns and isStringArray(opts.customPatterns) then + if #opts.customPatterns > 0 then return opts.customPatterns end + end + + -- this checks if a user set a custom pattern in the patterns table + -- then it checks if overrideDefault was set + if opts.customPatterns.patterns and #opts.customPatterns.patterns > 0 then + if opts.customPatterns.overrideDefault then return opts.customPatterns.patterns end + end local punctuationPatterns = opts.skipInsignificantPunctuation and skipPunctuationPatterns or allPunctuationPatterns @@ -54,7 +80,10 @@ function M.get(opts, backwards) if backwards then wordPatterns.camelCaseWordForward = nil end if not backwards then wordPatterns.camelCaseWordBackward = nil end - local patternsToUse = vim.tbl_extend("force", wordPatterns, punctuationPatterns) + -- user patterns default to {} + -- user patterns table only changes patterntsToUse if patterns has a pattern and overrideDefaults was set to false. + local patternsToUse = + vim.tbl_extend("force", wordPatterns, punctuationPatterns, opts.customPatterns.patterns) return patternsToUse end