1+ local ERROR = vim .log .levels .ERROR
12local Util = require (' boolean-toggle.util' )
23local Config = require (' boolean-toggle.config' )
34
4- local valid_chars = Util .dedup (vim .split (' aeflnrstuAEFLRSTU' , ' ' , { trimempty = false }))
55local delim = vim .split ([[ .,'"()[]{}$#?!:;%%^%*+=\\|/<>~` ]] , ' ' , { trimempty = false })
66
7- --- @enum BooleanToggle.ConvertToFalse
7+ --- @class BooleanToggle.ConvertToFalse
88local 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
1718local convert_lisp = {
1819 t = ' nil' ,
1920 [' nil' ] = ' t' ,
2021}
2122
22- --- @enum BooleanToggle.ConvertToTrue
23+ --- @class BooleanToggle.ConvertToTrue
2324local 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
3334local 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\n yes: `%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' })
113113end
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
151162end
152163
153164function 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
193202function 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
233243function 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
0 commit comments