aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.markdown15
-rw-r--r--doc/toggle_option_flag.txt30
-rw-r--r--plugin/toggle_option_flag.vim104
3 files changed, 149 insertions, 0 deletions
diff --git a/README.markdown b/README.markdown
new file mode 100644
index 0000000..0203257
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,15 @@
+toggle\_option\_flag.vim
+========================
+
+This plugin provides `:ToggleOptionFlag` and `:ToggleOptionFlagLocal` commands
+to toggle the values of options like `'formatoptions'` or `'complete'` that
+have values comprised of single-character or comma-separated flags. The author
+originally designed it for toggling flags in `'formatoptions'` quickly.
+
+License
+-------
+
+Copyright (c) [Tom Ryder][1]. Distributed under the same terms as Vim itself.
+See `:help license`.
+
+[1]: https://sanctum.geek.nz/
diff --git a/doc/toggle_option_flag.txt b/doc/toggle_option_flag.txt
new file mode 100644
index 0000000..a421da3
--- /dev/null
+++ b/doc/toggle_option_flag.txt
@@ -0,0 +1,30 @@
+*toggle_option_flag.txt* For Vim version 7.0 Last change: 2018 May 30
+
+DESCRIPTION *toggle_option_flag*
+
+ *:ToggleOptionFlag* *:ToggleOptionFlagLocal*
+This plugin provides `:ToggleOptionFlag` and `:ToggleOptionFlagLocal` commands
+to toggle the values of options like |'formatoptions'| or |'complete'| that
+have values comprised of single-character or comma-separated flags. The author
+originally designed it for toggling flags in |'formatoptions'| quickly.
+
+EXAMPLES *toggle_option_flag-examples*
+>
+ :ToggleOptionFlag formatoptions a
+ :ToggleOptionFlag switchbuf useopen
+ :ToggleOptionFlagLocal shortmess I
+<
+REQUIREMENTS *toggle_option_flag-requirements*
+
+This plugin is only available if 'compatible' is not set. It also requires the
+|+user_commands| Vim feature.
+
+AUTHOR *toggle_option_flag-author*
+
+Written and maintained by Tom Ryder <tom@sanctum.geek.nz>.
+
+LICENSE *toggle_option_flag-license*
+
+Licensed for distribution under the same terms as Vim itself (see |license|).
+
+ vim:tw=78:ts=8:ft=help:norl:
diff --git a/plugin/toggle_option_flag.vim b/plugin/toggle_option_flag.vim
new file mode 100644
index 0000000..bc7ccd7
--- /dev/null
+++ b/plugin/toggle_option_flag.vim
@@ -0,0 +1,104 @@
+"
+" toggle_option_flag.vim: Provide commands to toggle flags in grouped options
+" like 'formatoptions', 'shortmess', 'complete', 'switchbuf', etc.
+"
+" Author: Tom Ryder <tom@sanctum.geek.nz>
+" License: Same as Vim itself
+"
+if exists('g:loaded_toggle_option_flag') || &compatible
+ finish
+endif
+if !has('user_commands')
+ finish
+endif
+let g:loaded_toggle_option_flag = 1
+
+" Show an error-highlighted message and beep, but without a real :echoerr
+function! s:Error(message)
+ execute 'normal! \<Esc>'
+ echohl ErrorMsg
+ echomsg a:message
+ echohl None
+endfunction
+
+" 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)
+ let l:current = ''
+ execute 'let l:current = &' . a:option
+
+ " 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 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_value = ',' . l:current . ','
+ else
+ let l:search_flag = a:flag
+ 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 = l:before
+ \ ? '-='
+ \ : '+='
+
+ " 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
+
+ " Return value is whether we made a change
+ return l:before != l:after
+
+endfunction
+
+" User commands wrapping around calls to the above function
+command -nargs=+ -complete=option
+ \ ToggleOptionFlag
+ \ call <SID>Toggle(<f-args>, 0)
+command -nargs=+ -complete=option
+ \ ToggleOptionFlagLocal
+ \ call <SID>Toggle(<f-args>, 1)