{"id":13412928,"url":"https://github.com/chrisgrieser/nvim-alt-substitute","last_synced_at":"2025-03-14T18:32:42.087Z","repository":{"id":152069123,"uuid":"624297023","full_name":"chrisgrieser/nvim-alt-substitute","owner":"chrisgrieser","description":"A substitute of vim's :substitute that uses lua patterns instead of vim regex. Supports incremental preview.","archived":true,"fork":false,"pushed_at":"2024-06-04T20:38:44.000Z","size":131,"stargazers_count":43,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-07-31T20:51:41.167Z","etag":null,"topics":["editing-support","lua-pattern-matching","nvim-plugin","search-and-replace","substitute"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrisgrieser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"custom":"https://www.paypal.me/ChrisGrieser","ko_fi":"pseudometa"}},"created_at":"2023-04-06T06:53:47.000Z","updated_at":"2024-07-04T12:11:35.000Z","dependencies_parsed_at":"2024-01-03T03:32:58.785Z","dependency_job_id":"a130e09d-3332-486f-90ac-1373d9b287f8","html_url":"https://github.com/chrisgrieser/nvim-alt-substitute","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":"chrisgrieser/nvim-pseudometa-plugin-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-alt-substitute","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-alt-substitute/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-alt-substitute/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgrieser%2Fnvim-alt-substitute/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisgrieser","download_url":"https://codeload.github.com/chrisgrieser/nvim-alt-substitute/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221495316,"owners_count":16832458,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["editing-support","lua-pattern-matching","nvim-plugin","search-and-replace","substitute"],"created_at":"2024-07-30T20:01:31.225Z","updated_at":"2024-10-26T04:31:25.910Z","avatar_url":"https://github.com/chrisgrieser.png","language":"Lua","funding_links":["https://www.paypal.me/ChrisGrieser","https://ko-fi.com/pseudometa","https://ko-fi.com/Y8Y86SQ91'"],"categories":["Editing Support","Lua"],"sub_categories":["Scrollbar"],"readme":"# nvim-alt-substitute\n\u003ca href=\"https://dotfyle.com/plugins/chrisgrieser/nvim-alt-substitute\"\u003e\u003cimg src=\"https://dotfyle.com/plugins/chrisgrieser/nvim-alt-substitute/shield\" /\u003e\u003c/a\u003e\n\n\nA substitute of vim's `:substitute` that uses lua patterns instead of vim regex. Since you really don't want to learn a whole new flavor of regex just to be able to make search-and-replace operations in your editor.\n\n\n\u003e [!NOTE]\n\u003e The plugin is not maintained anymore. Please use its far more powerful\n\u003e successor,\n\u003e [nvim-rip-substitute](https://github.com/chrisgrieser/nvim-rip-substitute).\n\n---\n\n\nhttps://user-images.githubusercontent.com/73286100/231134276-e33b4ee8-611c-4b27-9c57-031ae13fc268.mp4\n\n*Colorscheme: dawnfox variant of nightfox.nvim*\n\n\u003c!--toc:start--\u003e\n- [Motivation](#motivation)\n- [Features](#features)\n- [Installation](#installation)\n- [Configuration](#configuration)\n- [Usage](#usage)\n  - [Flags](#flags)\n  - [Ranges](#ranges)\n  - [Escaping](#escaping)\n- [Advanced Usage](#advanced-usage)\n  - [Lua Pattern Tricks](#lua-pattern-tricks)\n  - [Appearance](#appearance)\n  - [Command Line Completion](#command-line-completion)\n- [Current Limitations](#current-limitations)\n- [Add Support for more Regex Flavors](#add-support-for-more-regex-flavors)\n- [Other Search-and-Replace Plugins](#other-search-and-replace-plugins)\n- [Credits](#credits)\n\u003c!--toc:end--\u003e\n\n## Motivation\n\u003c!-- vale Google.FirstPerson = NO --\u003e\nMany people like me have only started using nvim after the introduction of lua as configuration language. While almost everything about neovim can be done with lua by now, search-and-replace via `:substitute` is one of few areas remaining where you still have to use vimscript. Regardless whether you like vimscript or not, learning vim's flavor of regex *just* for search-and-replace-operations feels somewhat unproductive. \n\nVim's `:smagic` does help a bit, but still requires additional backslashes where common regex syntax does not require them. Using `verymagic` gets you closest to common regex, [but requires rather convoluted syntax](https://stackoverflow.com/questions/3760444/in-vim-is-there-a-way-to-set-very-magic-permanently-and-globally/23021259#23021259) that can make the command line hard to read in my view. And even if using `magic` or `verymagic`, vim's regex still differs from common regex syntax in various ways, [like the the the way non-greedy quantifiers are written](https://vi.stackexchange.com/questions/196/how-to-make-regex-matchers-non-greedy).\n\nSo for those of us who have never used neovim with anything other than lua, why not work with lua patterns for search-and-replace as well to drop the need to learn yet another regex flavor? For people already well-versed in vim regex, this plugin is indeed of little use, but for newcomers it may lower the barrier by removing the need to learn yet another regex flavor.\n\n## Features\n- Use `:AltSubstitute` (short form `:S`) to perform search-and-replace\n  operations using lua patterns.\n- Incremental preview of the substitution.\n- Supports ranges, with `%` as default.\n- The `g` flag is supported and works like with `:substitute`. \n- New flags: `i` for case-insensitive search and `f` for fixed strings (literal strings).\n\n```text\n:%s /\\(\\a\\+\\)\\d\\+/\\1/g          -- :substitute\n:S /(%a+)%d+/%1/g               -- :AltSubstitute\ndeviceModel2020 -\u003e deviceModel  -- effect\n```\n\n## Installation\n\n```lua\n-- lazy.nvim\n{\n\t\"chrisgrieser/nvim-alt-substitute\",\n  \topts = true,\n  \t-- lazy-loading with `cmd =` does not work well with incremental preview\n  \tevent = \"CmdlineEnter\",\n},\n\n-- packer\nuse {\n\t\"chrisgrieser/nvim-alt-substitute\",\n\tconfig = function() require(\"alt-substitute\").setup({}) end,\n}\n```\n\n\u003e __Note__  \n\u003e This plugin requires at least __nvim 0.8__, which introduced the incremental\n\u003e command preview feature.\n\n## Configuration\n\n```lua\n-- default values\nopts = {\n\tshowNotification = true, -- whether to show the \"x replacements made\" notification\n}\n```\n\nThe plugin uses ex-commands and comes without keymaps. You can set some of your own though. (Remember *not* to add `\u003cCR\u003e` at the end.)\n\n```lua\n-- prefill commandline with Substitution Syntax\nvim.keymap.set({ \"n\", \"x\" }, \"\u003cleader\u003es\", [[:S ///g\u003cLeft\u003e\u003cLeft\u003e\u003cLeft\u003e]], { desc = \"󱗘 :AltSubstitute\" })\n\n-- prefill commandline with Substitution Syntax and word under cursor\nvim.keymap.set(\n\t{ \"n\", \"x\" },\n\t\"\u003cleader\u003eS\",\n\tfunction() return \":S /\" .. vim.fn.expand(\"\u003ccword\u003e\") .. \"//g\u003cLeft\u003e\u003cLeft\u003e\" end,\n\t{ desc = \"󱗘 :AltSubstitute (word under cursor)\", expr = true }\n)\n```\n\n## Usage\nThe plugin registers the Ex-commands `:AltSubstitue` and `:S` as short form.\n\n### Flags\n- `g`: works the same as the `g` flag from `:substitute`: Without the `g` flag, only the first match in a line is replaced. With it, every occurrence in a line is replaced.\n- `f`: the search query and replace value are treated as __fixed strings__,\n  meaning lua magic characters are treated as literal strings.\n- `i`: the search query is __case insensitive__. The `i` flag is ignored when the `f` flag is also used. (Also note that as opposed to `:substitute`, this plugin ignores the `ignorecase` and `smartcase` setting – case sensitivity is solely determined by whether this flag is present.)\n\n### Ranges\n- Ranges are line-based and work [like all other vim command](https://neovim.io/doc/user/cmdline.html#cmdline-ranges). \n- However, as opposed to `:substitute`, `:AltSubstitute` works on the whole buffer when no range is given. (In other words, `%` is the default range.)\n\n### Escaping\n- Like with `:substitute`, slashes (`/`) delimit search query, replace\n  value, and flags. Therefore, to search for or replace a `/` you need to escape it with a backslash: `\\/`. \n\n## Advanced Usage\n\n### Lua Pattern Tricks\n- The frontier pattern`%f[set]`[^1] can be used as a replacement for `\\b`:\n  `%f[%w]`\n- The balanced match `%bxy` can be used to deal conveniently with nested brackets.\n- [Read more about lua patterns in the lua reference manual](https://www.lua.org/manual/5.4/manual.html#6.4.1).\n\n### Appearance\nThe incremental preview uses the same highlight group as `:substitute`, namely `Substitition`.\n\n### Command Line Completion\nYou can use [cmp-cmdline-history](https://github.com/dmitmel/cmp-cmdline-history) to get suggestions of previous substitutions you made. If you find them not helpful, and do not want the suggestions to obfuscate your view of the buffer, then you can disable command suggestions for this plugin:\n\n```lua\ncmp.setup.cmdline(\":\", {\n\tsources = { --[[ your sources ]]\n\t},\n\tenabled = function()\n\t\t-- Set of commands where cmp will be disabled\n\t\tlocal disabled = {\n\t\t\tAltSubstitute = true,\n\t\t\tS = true,\n\t\t}\n\t\t-- Get first word of cmdline\n\t\tlocal cmd = vim.fn.getcmdline():match(\"%S+\")\n\t\t-- Return true if cmd isn't disabled\n\t\t-- else call/return cmp.close(), which returns false\n\t\treturn not disabled[cmd] or cmp.close()\n\tend,\n})\n```\n\n### Interactive Lua Pattern Evaluation\nWhile unintended,  I found this plugin's incremental preview to also be very useful for interactive testing of lua patterns. Without a replacement value, the plugin evaluates `string.find()` and with a replacement value, it evaluates `string.gsub()`.\n\n## Current Limitations\n- `:substitution` flags other than `g` are not supported.\n- The `ignorecase` and the `smartcase` option are ignored. Instead, case sensitivity is termined by the presence or absense of the `i` flag.\n- `inccommand=split` is not supported, please use `inccommand=unsplit` instead.\n- Line breaks in the search or the replacement value are not supported.\n- Delimiters other than `/` are not supported yet. (You can make a PR to add\n  them, the relevant functions are in the [process-parameters module](./lua/alt-substitute/process-parameters.lua))\n\n## Add Support for more Regex Flavors\nPRs adding support for more regex flavors, like for example javascript regex, are welcome. The plugin has been specifically built with extensibility in mind, so other regex flavors can be added by writing just one search function and one replace function. However, the bridging to other languages necessitates some tricky escaping. Also performance was an issue in my brief attempts, since the incremental preview basically runs the substitution on every keystroke.\n\nHave a look this plugin's [regex module](./lua/alt-substitute/regex.lua) to see want needs to be implemented, if you wanna give it a try.\n\n## Other Search-and-Replace Plugins\n- [nvim-spectre](https://github.com/windwp/nvim-spectre)\n- [serch-replace.nvim](https://github.com/roobert/search-replace.nvim)\n- [replacer.nvim](https://github.com/gabrielpoca/replacer.nvim)\n- [nvim-search-and-replace](https://github.com/s1n7ax/nvim-search-and-replace)\n\n## Credits\n\u003c!-- vale Google.FirstPerson = NO --\u003e\n__About Me__  \nIn 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.\n\n__Profiles__  \n- [reddit](https://www.reddit.com/user/pseudometapseudo)\n- [Discord](https://discordapp.com/users/462774483044794368/)\n- [Academic Website](https://chris-grieser.de/)\n- [Twitter](https://twitter.com/pseudo_meta)\n- [ResearchGate](https://www.researchgate.net/profile/Christopher-Grieser)\n- [LinkedIn](https://www.linkedin.com/in/christopher-grieser-ba693b17a/)\n\n__Buy Me a Coffee__  \n\u003cbr\u003e\n\u003ca href='https://ko-fi.com/Y8Y86SQ91' target='_blank'\u003e\u003cimg height='36' style='border:0px;height:36px;' src='https://cdn.ko-fi.com/cdn/kofi1.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /\u003e\u003c/a\u003e\n\n[^1]: Frontier patterns are not mentioned in [neovim's respective section for lua patterns](https://neovim.io/doc/user/luaref.html#luaref-patterns). This is likely due to neovim using LuaJit, which itself is based on Lua 5.1, where [frontier patterns were still an undocumented feature](http://lua-users.org/lists/lua-l/2006-12/msg00536.html). But since frontier patterns are [officially documented in the most recent lua version](https://www.lua.org/manual/5.4/manual.html#6.4.1), it should be safe to assume that they are here to stay, so using them should not be an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisgrieser%2Fnvim-alt-substitute","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisgrieser%2Fnvim-alt-substitute","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisgrieser%2Fnvim-alt-substitute/lists"}