@@ -4,47 +4,42 @@ local Config = require('boolean-toggle.config')
44
55local delim = vim .split ([[ .,'"()[]{}$#?!:;%%^%*+=\\|/<>~` ]] , ' ' , { trimempty = false })
66
7- --- @class BooleanToggle.ConvertToFalse
87local 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
2417local 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
3427local 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
6560--- @class BooleanToggle
6661local 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
6997function M .setup (opts )
7098 Util .validate ({ opts = { opts , { ' table' , ' nil' }, true } })
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
120148function 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
162193end
@@ -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
0 commit comments