From b86c058803dc2705cf912dc63e216c7f7a41b0c8 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Mon, 6 Nov 2017 19:29:04 +1300 Subject: Refactor toggle_option_flag.vim Got carried away and rewrote a lot of this all in one hit. * Show single-line error messages with an s:Error() function * Flag early errors on nonexistent options * Test for the flag both before and after trying to toggle it to use as the basis for error reporting and return value, in a new s:Has() function --- vim/plugin/toggle_option_flag.vim | 81 ++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 23 deletions(-) (limited to 'vim/plugin') diff --git a/vim/plugin/toggle_option_flag.vim b/vim/plugin/toggle_option_flag.vim index 1d4b11ce..dcc26cce 100644 --- a/vim/plugin/toggle_option_flag.vim +++ b/vim/plugin/toggle_option_flag.vim @@ -12,19 +12,16 @@ if exists('g:loaded_toggle_option_flag') endif let g:loaded_toggle_option_flag = 1 -" Internal function to do the toggling -function! s:Toggle(option, flag, local) - - " Check for weird options, we don't want to :execute anything funny - if a:option =~# '\m\L' - echoerr 'Illegal option name' - return - endif +" Show an error-highlighted message and beep, but without a real :echoerr +function! s:Error(message) + execute 'normal! \' + echohl ErrorMsg + echomsg a:message + echohl None +endfunction - " Choose which set command to use - let l:set = a:local - \ ? 'setlocal' - \ : 'set' +" Test whether an option currently has a flag as part of its value +function! s:Has(option, flag) " Horrible :execute to get the option's current setting into a variable " (I couldn't get {curly braces} indirection to work) @@ -33,29 +30,67 @@ function! s:Toggle(option, flag, local) " If the flag we're toggling is longer than one character, this must by " necessity be a delimited option. I think all of those in VimL are - " comma-separated. Extend the flag and current setting so that they'll still - " match at the start and end. Otherwise, use them as-is. + " comma-separated. Extend the flag and value so that they'll still match at + " the start and end. Otherwise, use them as-is. if strlen(a:flag) > 1 let l:search_flag = ',' . a:flag . ',' - let l:search_current = ',' . l:current . ',' + let l:search_value = ',' . l:current . ',' else let l:search_flag = a:flag - let l:search_current = l:current + let l:search_value = l:current endif + " Return whether + return stridx(l:search_value, l:search_flag) > -1 + +endfunction + +" Internal function to do the toggling +function! s:Toggle(option, flag, local) + + " Check for spurious option strings, we don't want to :execute anything funny + if a:option =~# '\m\L' + call s:Error('Illegal option name') + return 0 + endif + + " Check the option actually exists + if !exists('&' . a:option) + call s:Error('No such option: ' . a:option) + return 0 + endif + + " Choose which set command to use + let l:set = a:local + \ ? 'setlocal' + \ : 'set' + + " Find whether the flag is set before the change + let l:before = s:Has(a:option, a:flag) + " Assign -= or += as the operation to run based on whether the flag already " appears in the option value or not - let l:operation = stridx(l:search_current, l:search_flag) > -1 + let l:operation = l:before \ ? '-=' \ : '+=' - " Build the command strings to set and then show the value - let l:cmd_set = l:set . ' ' . a:option . l:operation . escape(a:flag, '\ ') - let l:cmd_show = l:set . ' ' . a:option . '?' + " Try to set the option; suppress errors, we'll check our work + silent! execute l:set + \ . ' ' + \ . a:option . l:operation . escape(a:flag, '\ ') + + " Find whether the flag is set after the change + let l:after = s:Has(a:option, a:flag) + + " If we made a difference, report the new value; if we didn't, admit it + if l:before != l:after + execute l:set . ' ' . a:option . '?' + else + call s:Error('Unable to toggle '.a:option.' flag '.a:flag) + endif - " Run the set and show command strings - execute l:cmd_set - execute l:cmd_show + " Return value is whether we made a change + return l:before != l:after endfunction -- cgit v1.2.3