Compare commits
10 Commits
54024db83e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f63cd19d22 | ||
|
|
de332271d3 | ||
|
|
1d7f44983c | ||
|
|
cd92ad32ce | ||
|
|
ef4aa8a52a | ||
|
|
eac03a0592 | ||
|
|
c1548f9688 | ||
|
|
23ba85a5fc | ||
|
|
3b449c72a3 | ||
|
|
47c9f1eb74 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
tags
|
||||||
|
test.md
|
||||||
24
LICENSE
24
LICENSE
@@ -1,21 +1,11 @@
|
|||||||
MIT License
|
Copyright 2025 Stefan Rakel
|
||||||
|
|
||||||
Copyright (c) 2023 Stefan Rakel
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|||||||
58
README.md
Normal file
58
README.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# checkbox.nvim
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This plugin provides an easy way to toggle nested checkboxes of the form:
|
||||||
|
```markdown
|
||||||
|
[ ] item
|
||||||
|
* [ ] item
|
||||||
|
- [X] item
|
||||||
|
```
|
||||||
|
Parent and child items are updated automatically when a checkbox is changed. It
|
||||||
|
is easily configurable what may come before the checkbox. Configuring what is
|
||||||
|
skipped when searching for parents and child checkboxes alike is also possible.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Use your preferred plugin manager and add
|
||||||
|
```
|
||||||
|
"ibutra/checkbox.nvim"
|
||||||
|
```
|
||||||
|
as plugin.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Add a mapping to the provided function:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
vim.keymap.set("n", "<leader>x", require("checkbox").checkbox)
|
||||||
|
```
|
||||||
|
|
||||||
|
For further details and configuration options see the documentation:
|
||||||
|
[Vim Helpfile](doc/checkbox.nvim.txt)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
```
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Stefan Rakel
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
```
|
||||||
111
doc/checkbox.nvim.txt
Normal file
111
doc/checkbox.nvim.txt
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
*checkbox.nvim.txt* Easily toggle checklist items
|
||||||
|
|
||||||
|
1. Introduction ....................................... |checkbox-introduction|
|
||||||
|
2. Usage ..................................................... |checkbox-usage|
|
||||||
|
3. Configuration ..................................... |checkbox-configuration|
|
||||||
|
3.1 g:checkbox_prefixPatterns ..................... |checkbox-prefixPatterns|
|
||||||
|
3.2 g:checkbox_skipPatterns ......................... |checkbox-skipPatterns|
|
||||||
|
4. Changelog ............................................. |checkbox-changelog|
|
||||||
|
5. License ................................................. |checkbox-license|
|
||||||
|
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
1. Introduction *checkbox-introduction*
|
||||||
|
|
||||||
|
checkbox.nvim is a simple plugin that switches checkbox items of the form
|
||||||
|
>
|
||||||
|
[ ] item
|
||||||
|
[X] item
|
||||||
|
[X] item
|
||||||
|
* [ ] item
|
||||||
|
- [X] item
|
||||||
|
1. [ ] item
|
||||||
|
<
|
||||||
|
|
||||||
|
It also allows automatic adding of a checkbox to a line.
|
||||||
|
Furthermore it supports nested checkboxes and updates parents and children
|
||||||
|
alike.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
2. Usage *checkbox-usage*
|
||||||
|
|
||||||
|
To use the plugin bind a mapping to the returned function in the table:
|
||||||
|
>
|
||||||
|
vim.keymap.set("n", "<leader>x", require("checkbox").checkbox)
|
||||||
|
<
|
||||||
|
This will toggle the current line's checkbox or add one if not present.
|
||||||
|
This function will also update parent and child items to the following rules:
|
||||||
|
If a checkbox is checked, all its children are checked as well. If a chekcbox
|
||||||
|
is unchecked, all its children are unchecked as well.
|
||||||
|
The parent of the changed checkbox will get updated. It will be set to checked
|
||||||
|
if all its children are checked and to unchecked otherwise.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
3. Configuration *checkbox-configuration*
|
||||||
|
|
||||||
|
The following variables change the behaviour of this plugin:
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
3.1 g:checkbox_prefixPatterns *checkbox-prefixPatterns*
|
||||||
|
list
|
||||||
|
default: {"%-", "%*", "#+", "%->", "=>", "%d+%."}
|
||||||
|
|
||||||
|
Set this option to lua patterns which come before the checkbox `[ ]`. I.e. >
|
||||||
|
vim.g.checkbox_prefixPatterns = {"%-", "%*", "%d+%."}
|
||||||
|
Will create the checkbox after a `-`, `*` and `1.` item: >
|
||||||
|
- [ ] item
|
||||||
|
* [ ] item
|
||||||
|
12. [] item
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
3.1 g:checkbox_skipPatterns *checkbox-skipPatterns*
|
||||||
|
list
|
||||||
|
default:{"%-", "%*", "%->", "=>", "%d+%."}
|
||||||
|
|
||||||
|
Set this option to lua patterns which will be ignored when searching for
|
||||||
|
parents and children. I.e. >
|
||||||
|
vim.g.checkbox_skipPatterns = {"%-", "%*", "%->", "=>"}
|
||||||
|
Will make checkbox.nvim consider all checkboxes in the following example as
|
||||||
|
connected: >
|
||||||
|
[ ] Root-Parent
|
||||||
|
-> Some note
|
||||||
|
[ ] Child-Item to Root
|
||||||
|
- Another note
|
||||||
|
[ ] Another Child to Root
|
||||||
|
* Bullets under todo item
|
||||||
|
* another bullet
|
||||||
|
[ ] Child-Parent
|
||||||
|
=> More info
|
||||||
|
* [ ] Child
|
||||||
|
* [ ] Child
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
4. Changelog *checkbox-changelog*
|
||||||
|
|
||||||
|
2023.10.27
|
||||||
|
* First release
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
5. License *checkbox-license*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 Stefan Rakel
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
189
lua/checkbox.lua
Normal file
189
lua/checkbox.lua
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
-- MIT License
|
||||||
|
--
|
||||||
|
-- Copyright (c) 2023 Stefan Rakel
|
||||||
|
--
|
||||||
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
-- of this software and associated documentation files (the "Software"), to deal
|
||||||
|
-- in the Software without restriction, including without limitation the rights
|
||||||
|
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
-- copies of the Software, and to permit persons to whom the Software is
|
||||||
|
-- furnished to do so, subject to the following conditions:
|
||||||
|
--
|
||||||
|
-- The above copyright notice and this permission notice shall be included in all
|
||||||
|
-- copies or substantial portions of the Software.
|
||||||
|
--
|
||||||
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
-- SOFTWARE.
|
||||||
|
|
||||||
|
-- Initialize patterns
|
||||||
|
local prefixPatterns = {"%-", "%*", "#+", "%->", "=>", "%d+%."}
|
||||||
|
local skipPatterns = {"%-", "%*", "%->", "=>", "%d+%."}
|
||||||
|
local checkmarks = {"X", "x"} --UTF8 characters currently not supported
|
||||||
|
|
||||||
|
if vim.g.checkbox_prefixPatterns then
|
||||||
|
prefixPatterns = vim.g.checkbox_prefixPatterns
|
||||||
|
end
|
||||||
|
if vim.g.checkbox_skipPatterns then
|
||||||
|
prefixPatterns = vim.g.checkbox_skipPatterns
|
||||||
|
end
|
||||||
|
|
||||||
|
-- returns indentation level, checked status and text if the line has a checbox
|
||||||
|
-- nil otherwise
|
||||||
|
local function getCheckboxFromLine(lineNum)
|
||||||
|
local line = vim.fn.getline(lineNum)
|
||||||
|
for _, pat in ipairs(prefixPatterns) do
|
||||||
|
local pattern = "(%s*)(" .. pat .. "%s*)%[([ " .. vim.fn.join(checkmarks, "") .."]?)%](.*)"
|
||||||
|
local whitespace, before, checked, after = string.match(line, pattern)
|
||||||
|
if whitespace then
|
||||||
|
for _, c in ipairs(checkmarks) do
|
||||||
|
if checked == c then
|
||||||
|
checked = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if checked ~= true then
|
||||||
|
checked = false
|
||||||
|
end
|
||||||
|
whitespace = string.gsub(whitespace, "\t", " ")
|
||||||
|
local indentation = string.len(whitespace)
|
||||||
|
return {lineNum=lineNum, indentation=indentation, checked=checked, before=before, after=after}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function writeCheckbox(checkbox)
|
||||||
|
local checkedString = " "
|
||||||
|
if checkbox.checked then
|
||||||
|
checkedString = checkmarks[1]
|
||||||
|
end
|
||||||
|
local newLine = string.rep(" ", checkbox.indentation) .. checkbox.before .. "[" .. checkedString .. "]" .. checkbox.after
|
||||||
|
vim.fn.setline(checkbox.lineNum, newLine)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function setCheckbox(checkbox, checked)
|
||||||
|
checkbox.checked = checked
|
||||||
|
writeCheckbox(checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function switchOrAddCheckbox(lineNum)
|
||||||
|
local checkbox = getCheckboxFromLine(lineNum)
|
||||||
|
if checkbox then
|
||||||
|
checkbox.checked = not checkbox.checked
|
||||||
|
writeCheckbox(checkbox)
|
||||||
|
return checkbox
|
||||||
|
else
|
||||||
|
for _, pat in ipairs(prefixPatterns) do
|
||||||
|
local pattern = "(%s*" .. pat .. "%s*)(.*)"
|
||||||
|
local before, after = string.match(vim.fn.getline(lineNum), pattern)
|
||||||
|
if before then
|
||||||
|
local newLine = before .. "[ ] " .. after
|
||||||
|
vim.fn.setline(lineNum, newLine)
|
||||||
|
return getCheckboxFromLine(lineNum)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function findParent(startCheckbox)
|
||||||
|
if not startCheckbox then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local lineNum = startCheckbox.lineNum
|
||||||
|
while true do
|
||||||
|
lineNum = lineNum - 1
|
||||||
|
local checkbox = getCheckboxFromLine(lineNum)
|
||||||
|
if not checkbox then
|
||||||
|
--check skip patterns
|
||||||
|
local skipped = false
|
||||||
|
for _, pat in ipairs(skipPatterns) do
|
||||||
|
if string.match(vim.fn.getline(lineNum), "%s*" .. pat .. ".*") then
|
||||||
|
skipped = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not skipped then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if checkbox.indentation < startCheckbox.indentation then
|
||||||
|
return checkbox
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function findChildren(startCheckbox)
|
||||||
|
if not startCheckbox then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local children = {}
|
||||||
|
local lineNum = startCheckbox.lineNum
|
||||||
|
while true do
|
||||||
|
lineNum = lineNum + 1
|
||||||
|
local checkbox = getCheckboxFromLine(lineNum)
|
||||||
|
if not checkbox then
|
||||||
|
--check skip patterns
|
||||||
|
local skipped = false
|
||||||
|
for _, pat in ipairs(skipPatterns) do
|
||||||
|
if string.match(vim.fn.getline(lineNum), "%s*" .. pat .. ".*") then
|
||||||
|
skipped = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not skipped then
|
||||||
|
return children
|
||||||
|
end
|
||||||
|
elseif checkbox.indentation <= startCheckbox.indentation then
|
||||||
|
return children
|
||||||
|
elseif checkbox.indentation > startCheckbox.indentation then
|
||||||
|
table.insert(children, checkbox)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function updateFromChildren(checkbox)
|
||||||
|
local children = findChildren(checkbox)
|
||||||
|
if not children then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for _, child in ipairs(children) do
|
||||||
|
if not child.checked then
|
||||||
|
setCheckbox(checkbox, false)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setCheckbox(checkbox, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function updateChildren(checkbox)
|
||||||
|
local children = findChildren(checkbox)
|
||||||
|
if not children then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for _, child in ipairs(children) do
|
||||||
|
setCheckbox(child, checkbox.checked)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function switchAndUpdateCheckbox()
|
||||||
|
local lineNum = vim.fn.line(".")
|
||||||
|
local checkbox = switchOrAddCheckbox(lineNum)
|
||||||
|
if checkbox then
|
||||||
|
-- Update children
|
||||||
|
updateChildren(checkbox)
|
||||||
|
-- Traverse parents upwards and update them
|
||||||
|
local parent = findParent(checkbox)
|
||||||
|
while parent do
|
||||||
|
updateFromChildren(parent)
|
||||||
|
parent = findParent(parent)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
checkbox = switchAndUpdateCheckbox
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user