Skip to content

Commit 658e152

Browse files
committed
refactor!: now allow for custom yes/no spec and integrated in code
Signed-off-by: Guennadi Maximov C <g.maxc.fox@protonmail.com>
1 parent 8888a0d commit 658e152

2 files changed

Lines changed: 79 additions & 48 deletions

File tree

lua/boolean-toggle.lua

Lines changed: 78 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,42 @@ local Config = require('boolean-toggle.config')
44

55
local delim = vim.split([[.,'"()[]{}$#?!:;%%^%*+=\\|/<>~` ]], '', { trimempty = false })
66

7-
---@class BooleanToggle.ConvertToFalse
87
local convert_to_false = {
9-
['true'] = 'false',
10-
yes = 'no',
11-
True = 'False',
12-
Yes = 'No',
13-
TRUE = 'FALSE',
14-
YES = 'NO',
8+
['true'] = { 'false', ft = { '*' } },
9+
yes = { 'no', ft = { '*' } },
10+
True = { 'False', ft = { '*' } },
11+
Yes = { 'No', ft = { '*' } },
12+
TRUE = { 'FALSE', ft = { '*' } },
13+
YES = { 'NO', ft = { '*' } },
14+
['nil'] = { 't', ft = { 'lisp' } },
1515
}
1616

17-
---@class BooleanToggle.ConvertLisp
18-
local convert_lisp = {
19-
t = 'nil',
20-
['nil'] = 't',
21-
}
22-
23-
---@class BooleanToggle.ConvertToTrue
2417
local convert_to_true = {
25-
['false'] = 'true',
26-
no = 'yes',
27-
False = 'True',
28-
No = 'Yes',
29-
FALSE = 'TRUE',
30-
NO = 'NO',
18+
t = { 'nil', ft = { 'lisp' } },
19+
['false'] = { 'true', ft = { '*' } },
20+
no = { 'yes', ft = { '*' } },
21+
False = { 'True', ft = { '*' } },
22+
No = { 'Yes', ft = { '*' } },
23+
FALSE = { 'TRUE', ft = { '*' } },
24+
NO = { 'NO', ft = { '*' } },
3125
}
3226

33-
---@class BooleanToggle.Convert
3427
local convert = {
35-
FALSE = 'TRUE',
36-
False = 'True',
37-
NO = 'NO',
38-
No = 'Yes',
39-
TRUE = 'FALSE',
40-
True = 'False',
41-
YES = 'NO',
42-
Yes = 'No',
43-
['false'] = 'true',
44-
['not'] = '',
45-
['true'] = 'false',
46-
no = 'yes',
47-
yes = 'no',
28+
FALSE = { 'TRUE', ft = { '*' } },
29+
False = { 'True', ft = { '*' } },
30+
NO = { 'NO', ft = { '*' } },
31+
No = { 'Yes', ft = { '*' } },
32+
TRUE = { 'FALSE', ft = { '*' } },
33+
True = { 'False', ft = { '*' } },
34+
YES = { 'NO', ft = { '*' } },
35+
Yes = { 'No', ft = { '*' } },
36+
['false'] = { 'true', ft = { '*' } },
37+
['nil'] = { 't', ft = { 'lisp' } },
38+
['not'] = { '', ft = { '*' } },
39+
['true'] = { 'false', ft = { '*' } },
40+
no = { 'yes', ft = { '*' } },
41+
t = { 'nil', ft = { 'lisp' } },
42+
yes = { 'no', ft = { '*' } },
4843
}
4944

5045
---@param line string
@@ -65,6 +60,39 @@ end
6560
---@class BooleanToggle
6661
local M = {}
6762

63+
---@param ft? string
64+
---@param bool? 'true'|'false'
65+
---@return table<string, { [1]: string, ft: string[] }> values
66+
function M.get_spec_values(ft, bool)
67+
Util.validate({
68+
ft = { ft, { 'string', 'nil' }, true },
69+
bool = { bool, { 'string', 'nil' }, true },
70+
})
71+
ft = ft or Util.optget('filetype', 'buf', vim.api.nvim_get_current_buf())
72+
if bool and not vim.list_contains({ 'true', 'false' }, bool) then
73+
error(('Invalid value `%s`'):format(bool), ERROR)
74+
end
75+
76+
local conv = vim.deepcopy(not bool and convert or (bool == 'true' and convert_to_true or convert_to_false))
77+
if vim.tbl_isempty(Config.config.custom_spec) then
78+
return conv
79+
end
80+
81+
for _, spec in ipairs(Config.config.custom_spec) do
82+
local ft_spec = (not spec.ft or vim.tbl_isempty(spec.ft)) and { '*' } or spec.ft
83+
if not bool then
84+
conv[spec.no] = { spec.yes, ft = ft_spec }
85+
conv[spec.yes] = { spec.no, ft = ft_spec }
86+
elseif bool == 'true' then
87+
conv[spec.no] = { spec.yes, ft = ft_spec }
88+
elseif bool == 'false' then
89+
conv[spec.yes] = { spec.no, ft = ft_spec }
90+
end
91+
end
92+
93+
return conv
94+
end
95+
6896
---@param opts? BooleanToggleOpts
6997
function M.setup(opts)
7098
Util.validate({ opts = { opts, { 'table', 'nil' }, true } })
@@ -116,7 +144,7 @@ end
116144
---@return boolean is_boolean
117145
---@return integer|nil start_col
118146
---@return integer|nil end_col
119-
---@return table<string, string>|nil convert
147+
---@return table<string, { [1]: string, ft: string[] }>|nil convert
120148
function M.boolean_under_cursor(bool)
121149
Util.validate({ bool = { bool, { 'string', 'nil' }, true } })
122150

@@ -135,7 +163,7 @@ function M.boolean_under_cursor(bool)
135163
col = col - 1
136164
end
137165

138-
local word, start_col = '', col
166+
local word, start_col = '', col ---@type string, integer
139167
while true do
140168
if vim.list_contains(delim, line:sub(col, col)) or col > line:len() then
141169
col = col - 1
@@ -146,17 +174,20 @@ function M.boolean_under_cursor(bool)
146174
end
147175

148176
local bufnr = vim.api.nvim_get_current_buf()
149-
local is_lisp = Util.optget('filetype', 'buf', bufnr) == 'lisp'
177+
local ft = Util.optget('filetype', 'buf', bufnr) --[[@as string]]
150178
local conv
151179
if not bool then
152-
conv = vim.deepcopy(is_lisp and convert_lisp or convert)
180+
conv = M.get_spec_values('ft')
153181
elseif bool == 'true' then
154-
conv = vim.deepcopy(is_lisp and { ['nil'] = convert_lisp.t } or convert_to_true)
182+
conv = M.get_spec_values('ft', 'true')
155183
elseif bool == 'false' then
156-
conv = vim.deepcopy(is_lisp and { t = convert_lisp['nil'] } or convert_to_false)
184+
conv = M.get_spec_values('ft', 'false')
157185
end
158-
if vim.list_contains(vim.tbl_keys(conv), word) then
159-
return true, start_col, col, conv
186+
if conv[word] then
187+
local conv_ft = conv[word].ft or {}
188+
if vim.list_contains(conv_ft, ft) or vim.tbl_isempty(conv_ft) or vim.list_contains(conv_ft, '*') then
189+
return true, start_col, col, conv
190+
end
160191
end
161192
return false
162193
end
@@ -190,7 +221,7 @@ function M.cursor_toggle_boolean()
190221
local pos = vim.api.nvim_win_get_cursor(win)
191222
local before, after = get_boolean_surround(line, start_col, end_col)
192223

193-
vim.api.nvim_set_current_line(before .. conv[current_bool] .. after)
224+
vim.api.nvim_set_current_line(before .. conv[current_bool][1] .. after)
194225
pcall(vim.cmd.undojoin)
195226
vim.api.nvim_win_set_cursor(win, pos)
196227

@@ -228,10 +259,10 @@ function M.cursor_set_to_false()
228259
local pos = vim.api.nvim_win_get_cursor(win)
229260
local before, after = get_boolean_surround(line, start_col, end_col)
230261
if not vim.list_contains({ 't', 'T' }, line:sub(pos[2] + 1, pos[2] + 1)) then
231-
pos[2] = pos[2] + (line:len() > (before .. conv[current_bool] .. after):len() and -1 or 1)
262+
pos[2] = pos[2] + (line:len() > (before .. conv[current_bool][1] .. after):len() and -1 or 1)
232263
end
233264

234-
vim.api.nvim_set_current_line(before .. conv[line:sub(start_col, end_col)] .. after)
265+
vim.api.nvim_set_current_line(before .. conv[line:sub(start_col, end_col)][1] .. after)
235266
pcall(vim.cmd.undojoin)
236267
vim.api.nvim_win_set_cursor(win, pos)
237268

@@ -269,10 +300,10 @@ function M.cursor_set_to_true()
269300
local pos = vim.api.nvim_win_get_cursor(win)
270301
local before, after = get_boolean_surround(line, start_col, end_col)
271302
if not vim.list_contains({ 't', 'T', 'f', 'F', 'y', 'Y', 'n', 'N' }, line:sub(pos[2] + 1, pos[2] + 1)) then
272-
pos[2] = pos[2] + (line:len() > (before .. conv[current_bool] .. after):len() and -1 or 1)
303+
pos[2] = pos[2] + (line:len() > (before .. conv[current_bool][1] .. after):len() and -1 or 1)
273304
end
274305

275-
vim.api.nvim_set_current_line(before .. conv[line:sub(start_col, end_col)] .. after)
306+
vim.api.nvim_set_current_line(before .. conv[line:sub(start_col, end_col)][1] .. after)
276307
pcall(vim.cmd.undojoin)
277308
vim.api.nvim_win_set_cursor(win, pos)
278309

lua/boolean-toggle/config.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
---@field keymaps? BooleanToggleOpts.Keymaps|nil
1616

1717
---@class BooleanToggle.CustomSpec
18-
---@field ft? string[]|string|nil
18+
---@field ft? string[]|nil
1919
---@field no string
2020
---@field yes string
2121

0 commit comments

Comments
 (0)