Skip to content

Commit 8888a0d

Browse files
committed
feat!: new setup options and improved general logic to switch booleans
Signed-off-by: Guennadi Maximov C <g.maxc.fox@protonmail.com>
1 parent 4f0942c commit 8888a0d

2 files changed

Lines changed: 56 additions & 37 deletions

File tree

lua/boolean-toggle.lua

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
local ERROR = vim.log.levels.ERROR
12
local Util = require('boolean-toggle.util')
23
local Config = require('boolean-toggle.config')
34

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

7-
---@enum BooleanToggle.ConvertToFalse
7+
---@class BooleanToggle.ConvertToFalse
88
local convert_to_false = {
99
['true'] = 'false',
1010
yes = 'no',
@@ -14,12 +14,13 @@ local convert_to_false = {
1414
YES = 'NO',
1515
}
1616

17+
---@class BooleanToggle.ConvertLisp
1718
local convert_lisp = {
1819
t = 'nil',
1920
['nil'] = 't',
2021
}
2122

22-
---@enum BooleanToggle.ConvertToTrue
23+
---@class BooleanToggle.ConvertToTrue
2324
local convert_to_true = {
2425
['false'] = 'true',
2526
no = 'yes',
@@ -29,7 +30,7 @@ local convert_to_true = {
2930
NO = 'NO',
3031
}
3132

32-
---@enum BooleanToggle.Convert
33+
---@class BooleanToggle.Convert
3334
local convert = {
3435
FALSE = 'TRUE',
3536
False = 'True',
@@ -46,18 +47,6 @@ local convert = {
4647
yes = 'no',
4748
}
4849

49-
---@param line string
50-
---@param col integer
51-
---@return boolean valid
52-
local function is_valid_char(line, col)
53-
Util.validate({
54-
line = { line, { 'string' } },
55-
col = { col, { 'number' } },
56-
})
57-
58-
return vim.list_contains(valid_chars, line:sub(col, col))
59-
end
60-
6150
---@param line string
6251
---@param start_col integer
6352
---@param end_col integer
@@ -109,19 +98,35 @@ function M.setup(opts)
10998
end
11099
end
111100

101+
if Config.config.custom_spec and not vim.tbl_isempty(Config.config.custom_spec) then
102+
for _, spec in ipairs(Config.config.custom_spec) do
103+
if not (spec.yes and spec.no) then
104+
vim.notify(
105+
('Spec is missing either its `yes` and/or `no` values\nyes: `%s`'):format(spec.yes or '', spec.no or ''),
106+
ERROR
107+
)
108+
end
109+
end
110+
end
111+
112112
vim.api.nvim_create_user_command('Bool', M.cursor_toggle_boolean, { desc = 'Invert Boolean Value on Cursor' })
113113
end
114114

115+
---@param bool? 'true'|'false'
115116
---@return boolean is_boolean
116117
---@return integer|nil start_col
117118
---@return integer|nil end_col
118-
function M.boolean_under_cursor()
119+
---@return table<string, string>|nil convert
120+
function M.boolean_under_cursor(bool)
121+
Util.validate({ bool = { bool, { 'string', 'nil' }, true } })
122+
119123
local pos = vim.api.nvim_win_get_cursor(vim.api.nvim_get_current_win())
120124
local line = vim.api.nvim_get_current_line()
121125
local col = pos[2] + 1
122-
if not is_valid_char(line, col) then
126+
if vim.list_contains(delim, line:sub(col, col)) then
123127
return false
124128
end
129+
125130
while col > 0 do
126131
if vim.list_contains(delim, line:sub(col, col)) or col <= 0 then
127132
col = col + 1
@@ -141,23 +146,30 @@ function M.boolean_under_cursor()
141146
end
142147

143148
local bufnr = vim.api.nvim_get_current_buf()
144-
if vim.list_contains({ 't', 'nil' }, word) and Util.optget('filetype', 'buf', bufnr) == 'lisp' then
145-
return true, start_col, col
149+
local is_lisp = Util.optget('filetype', 'buf', bufnr) == 'lisp'
150+
local conv
151+
if not bool then
152+
conv = vim.deepcopy(is_lisp and convert_lisp or convert)
153+
elseif bool == 'true' then
154+
conv = vim.deepcopy(is_lisp and { ['nil'] = convert_lisp.t } or convert_to_true)
155+
elseif bool == 'false' then
156+
conv = vim.deepcopy(is_lisp and { t = convert_lisp['nil'] } or convert_to_false)
146157
end
147-
if vim.list_contains(vim.tbl_keys(convert), word) then
148-
return true, start_col, col
158+
if vim.list_contains(vim.tbl_keys(conv), word) then
159+
return true, start_col, col, conv
149160
end
150161
return false
151162
end
152163

153164
function M.cursor_toggle_boolean()
154165
local bufnr = vim.api.nvim_get_current_buf()
155-
local ok, start_col, end_col = M.boolean_under_cursor()
166+
local ok, start_col, end_col, conv = M.boolean_under_cursor()
156167
if
157168
not (
158169
ok
159170
and start_col
160171
and end_col
172+
and conv
161173
and vim.list_contains({ 'acwrite', '' }, vim.api.nvim_get_option_value('buftype', { buf = bufnr }))
162174
)
163175
then
@@ -170,18 +182,15 @@ function M.cursor_toggle_boolean()
170182

171183
local line = vim.api.nvim_get_current_line()
172184
local current_bool = line:sub(start_col, end_col)
173-
if not convert[current_bool] then
185+
if not conv[current_bool] then
174186
return
175187
end
176188

177189
local win = vim.api.nvim_get_current_win()
178190
local pos = vim.api.nvim_win_get_cursor(win)
179191
local before, after = get_boolean_surround(line, start_col, end_col)
180-
if not vim.list_contains({ 'f', 'F', 't', 'T', 'n' }, line:sub(pos[2] + 1, pos[2] + 1)) then
181-
pos[2] = pos[2] + (line:len() > (before .. convert[current_bool] .. after):len() and -1 or 1)
182-
end
183192

184-
vim.api.nvim_set_current_line(before .. convert[current_bool] .. after)
193+
vim.api.nvim_set_current_line(before .. conv[current_bool] .. after)
185194
pcall(vim.cmd.undojoin)
186195
vim.api.nvim_win_set_cursor(win, pos)
187196

@@ -192,12 +201,13 @@ end
192201

193202
function M.cursor_set_to_false()
194203
local bufnr = vim.api.nvim_get_current_buf()
195-
local ok, start_col, end_col = M.boolean_under_cursor()
204+
local ok, start_col, end_col, conv = M.boolean_under_cursor('false')
196205
if
197206
not (
198207
ok
199208
and start_col
200209
and end_col
210+
and conv
201211
and vim.list_contains({ 'acwrite', '' }, vim.api.nvim_get_option_value('buftype', { buf = bufnr }))
202212
)
203213
then
@@ -210,18 +220,18 @@ function M.cursor_set_to_false()
210220

211221
local line = vim.api.nvim_get_current_line()
212222
local current_bool = line:sub(start_col, end_col)
213-
if not convert_to_false[current_bool] then
223+
if not conv[current_bool] then
214224
return
215225
end
216226

217227
local win = vim.api.nvim_get_current_win()
218228
local pos = vim.api.nvim_win_get_cursor(win)
219229
local before, after = get_boolean_surround(line, start_col, end_col)
220230
if not vim.list_contains({ 't', 'T' }, line:sub(pos[2] + 1, pos[2] + 1)) then
221-
pos[2] = pos[2] + (line:len() > (before .. convert_to_false[current_bool] .. after):len() and -1 or 1)
231+
pos[2] = pos[2] + (line:len() > (before .. conv[current_bool] .. after):len() and -1 or 1)
222232
end
223233

224-
vim.api.nvim_set_current_line(before .. convert_to_false[line:sub(start_col, end_col)] .. after)
234+
vim.api.nvim_set_current_line(before .. conv[line:sub(start_col, end_col)] .. after)
225235
pcall(vim.cmd.undojoin)
226236
vim.api.nvim_win_set_cursor(win, pos)
227237

@@ -232,12 +242,13 @@ end
232242

233243
function M.cursor_set_to_true()
234244
local bufnr = vim.api.nvim_get_current_buf()
235-
local ok, start_col, end_col = M.boolean_under_cursor()
245+
local ok, start_col, end_col, conv = M.boolean_under_cursor('true')
236246
if
237247
not (
238248
ok
239249
and start_col
240250
and end_col
251+
and conv
241252
and vim.list_contains({ 'acwrite', '' }, vim.api.nvim_get_option_value('buftype', { buf = bufnr }))
242253
)
243254
then
@@ -250,18 +261,18 @@ function M.cursor_set_to_true()
250261

251262
local line = vim.api.nvim_get_current_line()
252263
local current_bool = line:sub(start_col, end_col)
253-
if not convert_to_true[current_bool] then
264+
if not conv[current_bool] then
254265
return
255266
end
256267

257268
local win = vim.api.nvim_get_current_win()
258269
local pos = vim.api.nvim_win_get_cursor(win)
259270
local before, after = get_boolean_surround(line, start_col, end_col)
260-
if not vim.list_contains({ 't', 'T', 'f', 'F', 'y', 'Y', 'n' }, line:sub(pos[2] + 1, pos[2] + 1)) then
261-
pos[2] = pos[2] + (line:len() > (before .. convert_to_true[current_bool] .. after):len() and -1 or 1)
271+
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)
262273
end
263274

264-
vim.api.nvim_set_current_line(before .. convert_to_true[line:sub(start_col, end_col)] .. after)
275+
vim.api.nvim_set_current_line(before .. conv[line:sub(start_col, end_col)] .. after)
265276
pcall(vim.cmd.undojoin)
266277
vim.api.nvim_win_set_cursor(win, pos)
267278

lua/boolean-toggle/config.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@
1010

1111
---@class BooleanToggleOpts
1212
---@field auto_write? boolean
13+
---@field custom_spec? BooleanToggle.CustomSpec[]
1314
---@field ignore_ft? string[]
1415
---@field keymaps? BooleanToggleOpts.Keymaps|nil
1516

17+
---@class BooleanToggle.CustomSpec
18+
---@field ft? string[]|string|nil
19+
---@field no string
20+
---@field yes string
21+
1622
---@class BooleanToggleDefaults: BooleanToggleOpts
1723
---@field auto_write boolean
24+
---@field custom_spec BooleanToggle.CustomSpec[]
1825
---@field ignore_ft string[]
1926
---@field keymaps BooleanToggleDefaults.Keymaps
2027

@@ -28,6 +35,7 @@ local M = {}
2835
function M.get_defaults()
2936
return { ---@type BooleanToggleDefaults
3037
auto_write = true,
38+
custom_spec = {},
3139
ignore_ft = {},
3240
keymaps = { toggle = nil, to_false = nil, to_true = nil },
3341
}

0 commit comments

Comments
 (0)