├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── lua └── alternate-toggler.lua └── plugin └── alternate-toggler.vim /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [rmagatti] 4 | patreon: rmagatti 5 | ko_fi: rmagatti 6 | custom: ['buymeacoffee.com/rmagatti'] 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lua/.luarc.json 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ronnie Magatti 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alternate Toggler 2 | Alternate Toggler is a _very_ small plugin for toggling alternate "boolean" values. 3 | 4 | ![](https://github.com/rmagatti/readme-assets/blob/main/alternate-toggler.gif) 5 | 6 | # Usage 7 | `:ToggleAlternate` toggles the current word () based on a pre-defined map of alternates. 8 | 9 | # Installation 10 | Any plugin manager should do, I use [Packer](https://github.com/wbthomason/packer.nvim). 11 | 12 | ```lua 13 | use { 14 | 'rmagatti/alternate-toggler', 15 | config = function() 16 | require("alternate-toggler").setup { 17 | alternates = { 18 | ["=="] = "!=" 19 | } 20 | } 21 | 22 | vim.keymap.set( 23 | "n", 24 | "", -- 25 | "lua require('alternate-toggler').toggleAlternate()" 26 | ) 27 | end, 28 | event = { "BufReadPost" }, -- lazy load after reading a buffer 29 | } 30 | ``` 31 | 32 | # Configuration 33 | 34 | ### Defaults 35 | This plugin provides a few pre-defined alternate mappings. 36 | ```lua 37 | { 38 | ["true"] = "false", 39 | ["True"] = "False", 40 | ["TRUE"] = "FALSE", 41 | ["Yes"] = "No", 42 | ["YES"] = "NO", 43 | ["1"] = "0", 44 | ["<"] = ">", 45 | ["("] = ")", 46 | ["["] = "]", 47 | ["{"] = "}", 48 | ['"'] = "'", 49 | ['""'] = "''", 50 | ["+"] = "-", 51 | ["==="] = "!==" 52 | } 53 | ``` 54 | 55 | ### Custom 56 | You can add more alternates through a global config variable: 57 | ```viml 58 | let g:at_custom_alternates = {'===': '!=='} 59 | ``` 60 | 61 | Or through calling the `setup` method of the plugin passing in an `alternates` table in the config. 62 | ```lua 63 | require("alternate-toggler").setup { 64 | alternates = { 65 | ["==="] = "!==", 66 | ["=="] = "!=", 67 | } 68 | } 69 | ``` 70 | :warning: WARNING: anything added here will override existing values if the key of the dict/table is the same as any of the defaults. 71 | 72 | # Commands 73 | Alternate Toggler exposes a single `:ToggleAlternate` command. 74 | 75 | **Example mappings:** 76 | ```viml 77 | nnoremap ta :ToggleAlternate 78 | ``` 79 | **OR** 80 | ```viml 81 | augroup AlternateToggles 82 | au! 83 | au FileType typescript,viml,lua nnoremap :ToggleAlternate 84 | augroup end 85 | ``` 86 | This allows for merely hitting the enter key to toggle an alternate, the caveat is having to specify supported file types manually. 87 | 88 | # Compatibility 89 | Neovim > 0.5 90 | 91 | Tested with: 92 | ``` 93 | NVIM v0.5.0-dev+a1ec36f 94 | Build type: Release 95 | LuaJIT 2.1.0-beta3 96 | ``` 97 | -------------------------------------------------------------------------------- /lua/alternate-toggler.lua: -------------------------------------------------------------------------------- 1 | local AlternateToggler = {} 2 | 3 | local default_table = { 4 | ["true"] = "false", 5 | ["True"] = "False", 6 | ["TRUE"] = "FALSE", 7 | ["Yes"] = "No", 8 | ["YES"] = "NO", 9 | ["1"] = "0", 10 | ["<"] = ">", 11 | ["("] = ")", 12 | ["["] = "]", 13 | ["{"] = "}", 14 | ['"'] = "'", 15 | ['""'] = "''", 16 | ["+"] = "-", 17 | ["==="] = "!==", 18 | ["=="] = "!=" 19 | } 20 | 21 | local user_table = vim.g.at_custom_alternates or {} 22 | 23 | for k, v in pairs(default_table) do 24 | default_table[v] = k 25 | end 26 | 27 | for k, v in pairs(user_table) do 28 | user_table[v] = k 29 | end 30 | 31 | local merged_table = vim.tbl_extend("force", default_table, user_table) 32 | 33 | local function errorHandler(err) 34 | if not err == nil then 35 | vim.notify("Error toggling to alternate value. Err: " .. err, vim.log.levels.ERROR) 36 | end 37 | end 38 | 39 | function AlternateToggler.setup(conf) 40 | if type(conf.alternates) == "table" then 41 | for k, v in pairs(conf.alternates) do 42 | conf.alternates[v] = k 43 | end 44 | merged_table = vim.tbl_extend("force", merged_table, conf.alternates) 45 | end 46 | end 47 | 48 | local user_clipboard = nil 49 | local user_register = nil 50 | local user_register_mode = nil 51 | local curpos = nil 52 | 53 | local function snapshot_and_clean() 54 | user_clipboard = vim.o.clipboard 55 | user_register = vim.fn.getreg('"') 56 | user_register_mode = vim.fn.getregtype('"') 57 | curpos = vim.api.nvim_win_get_cursor(0) 58 | 59 | vim.o.clipboard = nil 60 | end 61 | 62 | local function restore_snapshot() 63 | vim.fn.setreg('"', user_register, user_register_mode) 64 | vim.o.clipboard = user_clipboard 65 | vim.api.nvim_win_set_cursor(0, curpos) 66 | end 67 | 68 | function AlternateToggler.toggleAlternate(str) 69 | if str ~= nil then 70 | vim.notify( 71 | "Deprecated: passing a string (usually ) into `toggleAlternate` is deprecated. It now automatically does a `iw` text object operation.", 72 | vim.log.levels.WARN 73 | ) 74 | end 75 | 76 | snapshot_and_clean() 77 | 78 | vim.cmd("normal! yiw") 79 | local yanked_word = vim.fn.getreg('"') 80 | local word = merged_table[yanked_word] 81 | 82 | if word == nil then 83 | vim.notify("Unsupported alternate value.", vim.log.levels.INFO) 84 | restore_snapshot() 85 | return 86 | end 87 | 88 | xpcall(function() 89 | vim.cmd("normal! ciw" .. word) 90 | end, errorHandler) 91 | 92 | restore_snapshot() 93 | end 94 | 95 | return AlternateToggler 96 | -------------------------------------------------------------------------------- /plugin/alternate-toggler.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_alternate_toggler') | finish | endif " prevent loading file twice 2 | 3 | let s:save_cpo = &cpo " save user coptions 4 | set cpo&vim " reset them to defaults 5 | 6 | let LuaToggleAlternate = luaeval('require("alternate-toggler").toggleAlternate') 7 | 8 | " Available commands 9 | command! -nargs=* ToggleAlternate call LuaToggleAlternate() 10 | 11 | let &cpo = s:save_cpo " and restore after 12 | unlet s:save_cpo 13 | 14 | let g:loaded_alternate_toggler = 1 15 | --------------------------------------------------------------------------------