Repository: nat-418/boole.nvim Branch: main Commit: 7b4a3dae28e3 Files: 6 Total size: 18.3 KB Directory structure: gitextract_vei7v9zi/ ├── .github/ │ └── workflows/ │ └── release-please.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── doc/ │ └── boole.txt └── lua/ └── boole.lua ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/release-please.yml ================================================ on: push: branches: - main name: release-please jobs: release-please: runs-on: ubuntu-latest steps: - uses: google-github-actions/release-please-action@v3 with: release-type: simple package-name: release-please-action ================================================ FILE: CHANGELOG.md ================================================ # Changelog ## [3.0.1](https://github.com/nat-418/boole.nvim/compare/v3.0.0...v3.0.1) (2023-01-14) ### Bug Fixes * misc bugfixes ([16836c4](https://github.com/nat-418/boole.nvim/commit/16836c444252295cc984fe831fc6ef4ec186d89b)) ## [3.0.0](https://github.com/nat-418/boole.nvim/compare/v2.1.2...v3.0.0) (2022-11-14) ### ⚠ BREAKING CHANGES * jump to matches correctly ### Features * add enable/disable ([3bc80ec](https://github.com/nat-418/boole.nvim/commit/3bc80ece8ea74f85665e0184d5853ee583dec534)) * expose generate method ([0348b3e](https://github.com/nat-418/boole.nvim/commit/0348b3eaa5be364a3a8b4e896d81f35a66b5cd21)) * support case insensitive pairs ([93617c4](https://github.com/nat-418/boole.nvim/commit/93617c4bc1f1826c76b17fc952c22ef48fe6d276)) ### Bug Fixes * hard stop at EOL ([cbb9221](https://github.com/nat-418/boole.nvim/commit/cbb9221256db9a76a479760e331294dcf1681264)) * jump to matches correctly ([49a1354](https://github.com/nat-418/boole.nvim/commit/49a1354ef0fd3bc23350cbbf3f8d9e7d11cab077)) * misc. bugs ([a21bef2](https://github.com/nat-418/boole.nvim/commit/a21bef208cf557f512606ba3deaef7bd0fe8bc4b)) * misc. bugs ([9714f67](https://github.com/nat-418/boole.nvim/commit/9714f67c7ec3aea3ba2c9a483ef27153a6ba0e73)) * misc. bugs ([c46279f](https://github.com/nat-418/boole.nvim/commit/c46279fec4f43257fbf54596122927786711d921)) * off by one error / infinite loop ([5515ad9](https://github.com/nat-418/boole.nvim/commit/5515ad95bd751ca4bde10f54f9f01a5669122a54)) * off by one error / infinite loop ([353e9e1](https://github.com/nat-418/boole.nvim/commit/353e9e1dbfe3ed3d5dc4bf1f40cf632188965f53)) ================================================ FILE: LICENSE ================================================ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ================================================ FILE: README.md ================================================ boole.nvim 🔛 ============= Boole is a simple Neovim plugin that extends the default increment and decrement functionality of CTRL-A and CTRL-X to allow for toggling boolean values like `on`, `yes`, and `true` as well as cycling through: * Days of the week and their abbreviations (e.g., `Monday` → `Tuesday`) * Months of the year and their abbreviations (e.g., `Jan` → `Feb`) * X11 / Web color names (e.g., `Orange` → `OrangeRed`) * Canonical hours (e.g., `Compline` → `Vigil`) * Letter + number "words" (e.g., `F1` → `F2`) This plugin ships one command: * `:Boole {increment|decrement}` This command can be safely mapped to CTRL-A and CTRL-X. See the configuration section below for an example. Installation ------------ ```sh $ git clone --depth 1 https://github.com/nat-418/boole.nvim ~/.local/share/nvim/site/pack/boole/start/boole.nvim ``` Configuration ------------- Boole can be mapped to a key by passing a configuration table to the `setup` function. You can also add any cycle of words you would like. Feel free to submit an issue and pull request with additions you think would make good defaults. ```lua require('boole').setup({ mappings = { increment = '', decrement = '' }, -- User defined loops additions = { {'Foo', 'Bar'}, {'tic', 'tac', 'toe'} }, allow_caps_additions = { {'enable', 'disable'} -- enable → disable -- Enable → Disable -- ENABLE → DISABLE } }) ``` ================================================ FILE: doc/boole.txt ================================================ *boole.txt* A Neovim plugin for toggling booleans, etc. ============================================================================== CONTENTS *boole-contents* 1. Introduction ......................... |boole-introduction| 2. Install .............................. |boole-install| 3. Commands ............................. |boole-commands| 4. Configuration ........................ |boole-config| ============================================================================== 1. INTRODUCTION *boole-introduction* Boole is a simple Neovim plugin that extends the default increment and decrement functionality of CTRL-A and CTRL-X to allow for toggling boolean values like "on", "yes", and "true" as well as cycling through: * Days of the week and their abbreviations (e.g., `Monday` → `Tuesday`) * Months of the year and their abbreviations (e.g., `Jan` → `Feb`) * X11 / Web color names (e.g., `Orange` → `OrangeRed`) * Canonical hours (e.g., `Compline` → `Vigil`) ============================================================================== 2. INSTALL *boole-install* Using Packer: > use({ 'https://github.com/nat-418/boole.nvim', config = function() require('boole').setup() end }) ============================================================================== 3. COMMANDS *boole-commands* :Boole {increment|decrement} *Boole* Toggle or cycle up or down. ============================================================================== 4. CONFIGURATION *boole-config* Boole can be mapped to a key by passing a configuration table to the `setup` function. You can also add any cycle of words you would like. Feel free to submit an issue and pull request with additions you think would make good defaults. Here is an example: > *boole.setup()* require('boole').setup({ mappings = { increment = '', decrement = '' }, -- User defined loops additions = { {'Foo', 'Bar'} {'tic', 'tac', 'toe'} }, }) ============================================================================== vim:tw=78:ts=8:ft=help:norl:noet:fen:noet: ================================================ FILE: lua/boole.lua ================================================ local M = {} local ori_v_count = 0 local replace_map = { increment = {}, decrement = {}, } M.generate = function(loop_list, allow_caps) for i = 1, #loop_list do local current = loop_list[i] local next = loop_list[i + 1] or loop_list[1] replace_map.increment[current] = next replace_map.decrement[next] = current if allow_caps then local capitalized_current = string.gsub(current, "^%l", string.upper) local capitalized_next = string.gsub(next, "^%l", string.upper) local all_caps_current = string.upper(current) local all_caps_next = string.upper(next) replace_map.increment[capitalized_current] = capitalized_next replace_map.decrement[capitalized_next] = capitalized_current replace_map.increment[all_caps_current] = all_caps_next replace_map.decrement[all_caps_next] = all_caps_current end end end local letters = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' } for _, letter in ipairs(letters) do M.generate( { letter .. 0, letter .. 1, letter .. 2, letter .. 3, letter .. 4, letter .. 5, letter .. 6, letter .. 7, letter .. 8, letter .. 9 }, true ) end -- Booleans M.generate({'true', 'false'}, true) M.generate({'yes', 'no'}, true) M.generate({'on', 'off'}, true) M.generate({'enable', 'disable'}, true) M.generate({'enabled', 'disabled'}, true) -- Canonical hours M.generate( { 'Matins', 'Lauds', 'Prime', 'Terce', 'Sext', 'Nones', 'Vespers', 'Compline', 'Vigil' } ) -- Days of the week M.generate( { 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' }, true ) M.generate( { 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun' }, true ) -- Months of the year M.generate( { 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december' }, true ) -- Colors M.generate( { 'red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet' }) M.generate( { 'White', 'Snow', 'Ivory', 'Linen', 'AntiqueWhite', 'Beige', 'WhiteSmoke', 'LavenderBlush', 'OldLace', 'AliceBlue', 'SeaShell', 'GhostWhite', 'Honeydew', 'FloralWhite', 'Azure', 'MintCream' } ) M.generate( { 'Black', 'DarkSlateGray', 'DimGray', 'SlateGray', 'Gray', 'LightSlateGray', 'Silver', 'LightGray', 'Gainsboro' } ) M.generate( { 'Pink', 'LightPink', 'HotPink', 'PaleVioletRed', 'DeepPink', 'MediumVioletRed', } ) M.generate( { 'Indigo', 'Purple', 'DarkMagenta', 'DarkViolet', 'DarkSlateBlue', 'BlueViolet', 'DarkOrchid', 'Fuchsia', 'Magenta', 'SlateBlue', 'MediumSlateBlue', 'MediumOrchid', 'MediumPurple', 'Orchid', 'Violet', 'Plum', 'Thistle', 'Lavender' } ) M.generate( { 'DarkRed', 'Red', 'Firebrick', 'Crimson', 'IndianRed', 'LightCoral', 'Salmon', 'DarkSalmon', 'LightSalmon' } ) M.generate( { 'OrangeRed', 'Tomato', 'DarkOrange', 'Coral', 'Orange' } ) M.generate( { 'DarkKhaki', 'Gold', 'Khaki', 'PeachPuff', 'Yellow', 'PaleGoldenRod', 'Moccasin', 'PapayaWhip', 'LightGoldenRodYellow', 'LemonChiffon', 'LightYellow' } ) M.generate( { 'MidnightBlue', 'Navy', 'DarkBlue', 'MediumBlue', 'Blue', 'RoyalBlue', 'SteelBlue', 'DodgerBlue', 'DeepSkyBlue', 'CornflowerBlue', 'SkyBlue', 'LightSkyBlue', 'LightSteelBlue', 'LightBlue', 'PowderBlue', } ) M.generate( { 'Maroon', 'Brown', 'SaddleBrown', 'Sienna', 'Chocolate', 'DarkGoldenRod', 'Peru', 'RosyBrown', 'GoldenRod', 'SandyBrown', 'Tan', 'BurlyWood', 'Wheat', 'NavajoWhite', 'Bisque', 'BlanchedAlmond', 'Cornsilk', } ) M.generate( { 'Teal', 'DarkCyan', 'LightSeaGreen', 'CadetBlue', 'DarkTurquoise', 'MediumTurquoise', 'Turquoise', 'Aqua', 'Cyan', 'Aquamarine', 'PaleTurquoise', 'LightCyan', } ) M.generate( { 'DarkGreen', 'Green', 'DarkOliveGreen', 'ForestGreen', 'SeaGreen', 'Olive', 'OliveDrab', 'MediumSeaGreen', 'LimeGreen', 'Lime', 'SpringGreen', 'MediumSpringGreen', 'DarkSeaGreen', 'MediumAquamarine', 'YellowGreen', 'LawnGreen', 'Chartreuse', 'LightGreen', 'GreenYellow', 'PaleGreen', } ) --Check cursor word match the cword function check_postion_word(words,target_position,target_word) --In lua tab space is %s other is %S --In vim cword won't contains ", different behavior with lua --we have to know char in column[0] is word or %s i,j = string.find(words,"%S+"); local position = 0; if i==1 then position = j --Cursor in first word if position > target_position then return string.find(words:sub(i,j), target_word) end end -- split word with (space\tab)word for word in string.gmatch(words,"%s+%S+") do position = position + string.len(word) local s_word = word:gsub("%s","") -- means target_position is in %s location no need to compare if position - string.len(s_word) >= target_position then return false end if position > target_position then return string.find(s_word, target_word) end end return false end function number_exist_in_word(line,current_column) local space_after_cursor = string.find(line:sub(current_column + 1, string.len(line))," ") if space_after_cursor and space_after_cursor>1 then local word_after_cursor = line:sub(current_column+1,current_column + space_after_cursor) if string.match(word_after_cursor,"%d") then return true end -- no space check it contains number or not elseif space_after_cursor == nil then local last_string = line:sub(current_column+1,string.len(line)) if string.match(last_string,"%d") then return true end end return false end M.run = function(direction) local start_position = vim.api.nvim_win_get_cursor(0) -- Tail-recursive function to match and replace. local function tryMatch(last_position) local line = vim.api.nvim_get_current_line() local cword = vim.fn.expand('') local current_position = vim.api.nvim_win_get_cursor(0) local current_column = current_position[2] --Record the v.count vim.v.count will be reset after vim.cmd --if we have any good idea please modify it if(vim.v.count ~=0 ) then ori_v_count = vim.v.count end -- C-a and C-x already handle numbers, no need to try and -- match them to out added values. -- after current_column contains number if tonumber(cword) ~= nil or number_exist_in_word(line,current_column) then return false end -- we only need check char in alpha and number if string.find(line:sub(current_column+1, current_column+1),"[^][a-zA-Z0-9]") then if (current_column + 1) == vim.fn.strlen(line) then vim.api.nvim_win_set_cursor(0, start_position) return false end vim.cmd('normal! w') return tryMatch(current_position) end -- Limit matches to the original line. if last_position[1] < current_position[1] then -- After check number exist in word avoid number in front of cursor be increase or decrease -- if we use wb 123_te*st (* as cursor) and use -- will be 124*_test not as aspect vim.api.nvim_win_set_cursor(0, start_position) return false end -- Do we have a match? local match = direction == 'decrement' and replace_map.decrement[cword] or replace_map.increment[cword] if match then -- Are we on the first character of the word? If not, move there. -- If not first char compare current word is match or not if cword:sub(1, 1) ~= line:sub(current_column + 1, current_column + 1) then if check_postion_word(line,current_column, cword) then vim.cmd('normal! b') else vim.cmd('normal! w') end return tryMatch(current_position) -- Are we at the end of the line? If so, jump back. -- Even in last word we will check match or not so move this to back elseif (current_column + 1) == vim.fn.strlen(line) then vim.api.nvim_win_set_cursor(0, start_position) return false end --use ori_v_count to get correct match data for i =0, ori_v_count-1 do match = direction == 'decrement' and replace_map.decrement[cword] or replace_map.increment[cword] if match then cword = match else return false end end -- Replace the word and put the cursor on the beginning of replacement. ori_v_count = 0 vim.cmd('normal! "_ciw' .. match) vim.cmd('normal! b') return true else -- Are we at the end of the line? If so, give up. if (current_column + 1) == vim.fn.strlen(line) then vim.api.nvim_win_set_cursor(0, start_position) return false end -- Try the next word to see if it matches. vim.cmd('normal! w') return tryMatch(current_position) end end -- Fallback to original and functions for numbers. if not tryMatch(start_position) then local target_v_count = ori_v_count ori_v_count = 0 if target_v_count ~= nil and target_v_count > 0 then if direction == 'increment' then return vim.cmd('normal!' .. target_v_count .. '') end if direction == 'decrement' then return vim.cmd('normal!' .. target_v_count .. '') end else if direction == 'increment' then return vim.cmd('normal!' .. '') end if direction == 'decrement' then return vim.cmd('normal!' .. '') end end end end M.setup = function(options) vim.api.nvim_create_user_command( 'Boole', function(args) M.run(args.args) end, { nargs = 1, complete = function() return { 'increment', 'decrement' } end } ) if options == nil then return false end if options.allow_caps_additions ~= nil then for _, val in pairs(options.allow_caps_additions) do M.generate(val, true) end end if options.additions ~= nil then for _, val in pairs(options.additions) do M.generate(val) end end if options.mappings.increment ~= nil then vim.keymap.set( { 'n', 'v' }, options.mappings.increment, 'Boole increment' ) end if options.mappings.decrement ~= nil then vim.keymap.set( { 'n', 'v' }, options.mappings.decrement, 'Boole decrement' ) end return true end return M