Hi,
This patch adds a function with the declaration optiontype({option})
which returns the type of the given option. I'm currently using it to
achieve the following option toggle mapping:
" :NMapChangeOption[!] {letter} {option} [enable]
"
" Create a normal mode option toggle mapping for {option}. The mapping key
" sequence will be prefixed with 'co' followed by {letter}.
"
" By default the option will only be changed in the current buffer. Using [!]
" will change the option globally.
"
" Boolean option example:
"
" :NMapChangeOption s spell
"
" Pressing 'cos' will toggle the spell option on and off.
"
" Non boolean option example:
"
" :NMapChangeOption y syntax ON
"
" The optional [enable] argument can be used for string and comma separated
" list options. Pressing 'coy' will add/remove 'ON' from the syntax option.
"
" This functionality is borrowed from Tim Pope's unimpaired.vim plugin.
command! -bang -complete=option -nargs=+ NMapChangeOption
\ call s:NMapChangeOption(<bang>0, <f-args>)
func! s:NMapChangeOption(global, letter, option, ...) abort
let set = a:global ? 'set' : 'setlocal'
let type = optiontype(a:option)
if type == 0 " boolean
let rhs = printf(':%s <C-R>=&%s ? "no" : ""<CR>%s<CR>',
\ set, a:option, a:option)
elseif type == 2 " comma separated list
let rhs = printf(':%s %s<C-R>=&%s !~# "%s" ? "+=" : "-="<CR>%s<CR>',
\ set, a:option, a:option, a:1, a:1)
elseif type == 4 " string
let rhs = printf(':%s %s<C-R>=&%s == "%s" ? "&" : "=%s"<CR><CR>',
\ set, a:option, a:option, a:1, a:1)
endif
exe 'nnoremap co' . a:letter rhs
endfunc
NMapChangeOption c colorcolumn +1
NMapChangeOption! h hlsearch
NMapChangeOption l list
NMapChangeOption! p paste
NMapChangeOption s spell
NMapChangeOption w wrap
NMapChangeOption y syntax ON
The patch includes tests and docs.
--
:wq
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 642f0ad..f411beb 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2023,6 +2023,7 @@ mode( [expr]) String current editing
mode
mzeval( {expr}) any evaluate |MzScheme| expression
nextnonblank( {lnum}) Number line nr of non-blank line >= {lnum}
nr2char( {expr}[, {utf8}]) String single char with ASCII/UTF8 value {expr}
+optiontype( {option}) Number type of option {option}
or( {expr}, {expr}) Number bitwise OR
pathshorten( {expr}) String shorten directory names in a path
perleval( {expr}) any evaluate |Perl| expression
@@ -5316,6 +5317,15 @@ nr2char({expr}[, {utf8}])
*nr2char()*
characters. nr2char(0) is a real NUL and terminates the
string, thus results in an empty string.
+optiontype({option}) *optiontype()* *E518*
+ Return the type of {option} as a Number:
+ Boolean: 0
+ Number: 1
+ Comma separated list: 2
+ Char flag list: 3
+ String: 4
+ If {option} does not exist, -1 is returned.
+
or({expr}, {expr}) *or()*
Bitwise OR on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error.
diff --git a/src/eval.c b/src/eval.c
index b233833..38533d8 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -682,6 +682,7 @@ static void f_mzeval(typval_T *argvars, typval_T *rettv);
static void f_nextnonblank(typval_T *argvars, typval_T *rettv);
static void f_nr2char(typval_T *argvars, typval_T *rettv);
static void f_or(typval_T *argvars, typval_T *rettv);
+static void f_optiontype(typval_T *argvars, typval_T *rettv);
static void f_pathshorten(typval_T *argvars, typval_T *rettv);
#ifdef FEAT_PERL
static void f_perleval(typval_T *argvars, typval_T *rettv);
@@ -8327,6 +8328,7 @@ static struct fst
{"nextnonblank", 1, 1, f_nextnonblank},
{"nr2char", 1, 2, f_nr2char},
{"or", 2, 2, f_or},
+ {"optiontype", 1, 1, f_optiontype},
{"pathshorten", 1, 1, f_pathshorten},
#ifdef FEAT_PERL
{"perleval", 1, 1, f_perleval},
@@ -15901,6 +15903,22 @@ f_or(typval_T *argvars, typval_T *rettv)
}
/*
+ * "optiontype(option)" function
+ */
+ static void
+f_optiontype(typval_T *argvars, typval_T *rettv)
+{
+ char_u *p;
+ int type;
+
+ p = get_tv_string_chk(&argvars[0]);
+ type = get_option_type(p);
+ if (type == -1)
+ EMSG(_("E518: Unknown option"));
+ rettv->vval.v_number = type;
+}
+
+/*
* "pathshorten()" function
*/
static void
diff --git a/src/option.c b/src/option.c
index 8a706af..8b163ca 100644
--- a/src/option.c
+++ b/src/option.c
@@ -12244,3 +12244,28 @@ get_bkc_value(buf_T *buf)
{
return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags;
}
+
+/*
+ * Get the type of an option.
+ * Returns -1 when the option is unknown.
+ */
+ int
+get_option_type(char_u *name)
+{
+ int opt_idx;
+
+ opt_idx = findoption(name);
+ if (opt_idx == -1)
+ return -1;
+ if (options[opt_idx].flags & P_BOOL)
+ return 0;
+ if (options[opt_idx].flags & P_NUM)
+ return 1;
+ if (options[opt_idx].flags & P_COMMA || options[opt_idx].flags &
P_ONECOMMA)
+ return 2;
+ if (options[opt_idx].flags & P_FLAGLIST)
+ return 3;
+ if (options[opt_idx].flags & P_STRING)
+ return 4;
+ return 4; /* type unknown, assume string */
+}
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 455ca7b..ed589bf 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -176,6 +176,7 @@ NEW_TESTS = test_arglist.res \
test_increment.res \
test_json.res \
test_langmap.res \
+ test_optiontype.res \
test_packadd.res \
test_perl.res \
test_quickfix.res \
diff --git a/src/testdir/test_optiontype.vim b/src/testdir/test_optiontype.vim
new file mode 100644
index 0000000..7f48a52
--- /dev/null
+++ b/src/testdir/test_optiontype.vim
@@ -0,0 +1,14 @@
+" Test for the optiontype function.
+function Test_optiontype()
+ call assert_equal(0, optiontype('antialias'))
+ call assert_equal(1, optiontype('aleph'))
+ call assert_equal(2, optiontype('backspace'))
+ call assert_equal(2, optiontype('belloff'))
+ call assert_equal(3, optiontype('breakat'))
+ call assert_equal(4, optiontype('ambiwidth'))
+ try
+ call optiontype('unknown')
+ catch
+ call assert_exception('E518:')
+ endtry
+endfunction