On Sat, Mar 26, 2016 at 04:52:47PM +0100, Bram Moolenaar wrote:
>
> Anton Lindqvist wrote:
>
> > > > 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.
> > >
> > > I can see how this would be useful. But returning just a number is
> > > limited. There are many more properties of an option, such as whether
> > > it is window-local, was set or not, can be set from a modeline, etc.
> > > Not that we need to add all those properties now, but I'm sure someone
> > > will want to add them later. Perhaps using "optionproperties()" and
> > > returning a Dictionary?
> >
> > Great feedback. Attached is a revised patch with you ideas applied.
> > For now the 'optionproperties()' function returns a Dictionary with only
> > one entry called 'type'.
>
> Thanks. I wonder if "type" would just return bool/number/string. Then
> for a string type there would be a subtype for comma/flaglist.
> I suppose it depends on what you want to do if you want to know what
> kind of string option it is. Also, if we later add another kind (colon
> separate?) that is also a string, it would still be possible to
> recognize the string if you don't care about the subtype.
It guess it makes sense to assume that in the general use-case one is
only interested of the primitive type of a option, therefore
bool/number/string is sufficient. The attached patch adds two new
entries to the returned dictionary: 'comma' and 'flaglist'.
--
: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..a6df0cf 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}
+optionproperties( {option}) Dict properties 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,21 @@ nr2char({expr}[, {utf8}])
*nr2char()*
characters. nr2char(0) is a real NUL and terminates the
string, thus results in an empty string.
+ *E518*
+optionproperties({option}) *optionproperties()*
+ Return the properties of {option} as a dictionary with the
+ following entries:
+
+ comma 1 if {option} is a comma separated list, 0
+ otherwise
+ flaglist 1 if {option} is a list of single-char flags,
+ 0 otherwise
+ type Boolean: 0
+ Number: 1
+ String: 2
+
+ If {option} does not exist, a empty dictionary 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 2256589..0fecf0a 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -683,6 +683,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_optionproperties(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);
@@ -8367,6 +8368,7 @@ static struct fst
{"nextnonblank", 1, 1, f_nextnonblank},
{"nr2char", 1, 2, f_nr2char},
{"or", 2, 2, f_or},
+ {"optionproperties",1, 1, f_optionproperties},
{"pathshorten", 1, 1, f_pathshorten},
#ifdef FEAT_PERL
{"perleval", 1, 1, f_perleval},
@@ -15917,6 +15919,46 @@ f_or(typval_T *argvars, typval_T *rettv)
}
/*
+ * "optionproperties(option)" function
+ */
+ static void
+f_optionproperties(typval_T *argvars, typval_T *rettv)
+{
+ char_u *p;
+ int flags;
+ int type;
+
+ if (rettv_dict_alloc(rettv) == FAIL)
+ return;
+
+ p = get_tv_string_chk(&argvars[0]);
+ flags = get_option_flags(p);
+ if (flags == -1) {
+ EMSG(_("E518: Unknown option"));
+ return;
+ }
+
+ if (flags & P_BOOL)
+ type = 0;
+ else if (flags & P_NUM)
+ type = 1;
+ else if (flags & P_STRING)
+ type = 2;
+ else
+ type = 2; /* type unknown, assume string */
+ if (dict_add_nr_str(rettv->vval.v_dict, "type", type, NULL) == FAIL)
+ return;
+
+ if (dict_add_nr_str(rettv->vval.v_dict, "comma",
+ flags & P_COMMA || flags & P_ONECOMMA, NULL) == FAIL)
+ return;
+
+ if (dict_add_nr_str(rettv->vval.v_dict, "flaglist",
+ (flags & P_FLAGLIST) == P_FLAGLIST, NULL) == FAIL)
+ return;
+}
+
+/*
* "pathshorten()" function
*/
static void
diff --git a/src/option.c b/src/option.c
index 8a706af..58727a2 100644
--- a/src/option.c
+++ b/src/option.c
@@ -410,50 +410,6 @@ struct vimoption
#define VI_DEFAULT 0 /* def_val[VI_DEFAULT] is Vi default value */
#define VIM_DEFAULT 1 /* def_val[VIM_DEFAULT] is Vim default value */
-/*
- * Flags
- */
-#define P_BOOL 0x01 /* the option is boolean */
-#define P_NUM 0x02 /* the option is numeric */
-#define P_STRING 0x04 /* the option is a string */
-#define P_ALLOCED 0x08 /* the string option is in allocated memory,
- must use free_string_option() when
- assigning new value. Not set if default is
- the same. */
-#define P_EXPAND 0x10 /* environment expansion. NOTE: P_EXPAND can
- never be used for local or hidden options! */
-#define P_NODEFAULT 0x40 /* don't set to default value */
-#define P_DEF_ALLOCED 0x80 /* default value is in allocated memory, must
- use vim_free() when assigning new value */
-#define P_WAS_SET 0x100 /* option has been set/reset */
-#define P_NO_MKRC 0x200 /* don't include in :mkvimrc output */
-#define P_VI_DEF 0x400 /* Use Vi default for Vim */
-#define P_VIM 0x800 /* Vim option, reset when 'cp' set */
-
- /* when option changed, what to display: */
-#define P_RSTAT 0x1000 /* redraw status lines */
-#define P_RWIN 0x2000 /* redraw current window */
-#define P_RBUF 0x4000 /* redraw current buffer */
-#define P_RALL 0x6000 /* redraw all windows */
-#define P_RCLR 0x7000 /* clear and redraw all */
-
-#define P_COMMA 0x8000 /* comma separated list */
-#define P_ONECOMMA 0x18000L /* P_COMMA and cannot have two consecutive
- * commas */
-#define P_NODUP 0x20000L /* don't allow duplicate strings */
-#define P_FLAGLIST 0x40000L /* list of single-char flags */
-
-#define P_SECURE 0x80000L /* cannot change in modeline or secure mode */
-#define P_GETTEXT 0x100000L /* expand default value with _() */
-#define P_NOGLOB 0x200000L /* do not use local value for global vimrc */
-#define P_NFNAME 0x400000L /* only normal file name chars allowed */
-#define P_INSECURE 0x800000L /* option was set from a modeline */
-#define P_PRI_MKRC 0x1000000L /* priority for :mkvimrc (setting option has
- side effects) */
-#define P_NO_ML 0x2000000L /* not allowed in modeline */
-#define P_CURSWANT 0x4000000L /* update curswant required; not needed when
- * there is a redraw flag */
-
#define ISK_LATIN1 (char_u *)"@,48-57,_,192-255"
/* 'isprint' for latin1 is also used for MS-Windows cp1252, where 0x80 is used
@@ -12244,3 +12200,19 @@ get_bkc_value(buf_T *buf)
{
return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags;
}
+
+/*
+ * Get the flags of an option.
+ * Returns -1 when the option is unknown.
+ */
+ int
+get_option_flags(char_u *name)
+{
+ int opt_idx;
+
+ opt_idx = findoption(name);
+ if (opt_idx == -1)
+ return -1;
+ else
+ return options[opt_idx].flags;
+}
diff --git a/src/option.h b/src/option.h
index cf7ba04..518f20b 100644
--- a/src/option.h
+++ b/src/option.h
@@ -11,6 +11,50 @@
*/
/*
+ * Flags
+ */
+#define P_BOOL 0x01 /* the option is boolean */
+#define P_NUM 0x02 /* the option is numeric */
+#define P_STRING 0x04 /* the option is a string */
+#define P_ALLOCED 0x08 /* the string option is in allocated memory,
+ must use free_string_option() when
+ assigning new value. Not set if default is
+ the same. */
+#define P_EXPAND 0x10 /* environment expansion. NOTE: P_EXPAND can
+ never be used for local or hidden options! */
+#define P_NODEFAULT 0x40 /* don't set to default value */
+#define P_DEF_ALLOCED 0x80 /* default value is in allocated memory, must
+ use vim_free() when assigning new value */
+#define P_WAS_SET 0x100 /* option has been set/reset */
+#define P_NO_MKRC 0x200 /* don't include in :mkvimrc output */
+#define P_VI_DEF 0x400 /* Use Vi default for Vim */
+#define P_VIM 0x800 /* Vim option, reset when 'cp' set */
+
+ /* when option changed, what to display: */
+#define P_RSTAT 0x1000 /* redraw status lines */
+#define P_RWIN 0x2000 /* redraw current window */
+#define P_RBUF 0x4000 /* redraw current buffer */
+#define P_RALL 0x6000 /* redraw all windows */
+#define P_RCLR 0x7000 /* clear and redraw all */
+
+#define P_COMMA 0x8000 /* comma separated list */
+#define P_ONECOMMA 0x18000L /* P_COMMA and cannot have two consecutive
+ * commas */
+#define P_NODUP 0x20000L /* don't allow duplicate strings */
+#define P_FLAGLIST 0x40000L /* list of single-char flags */
+
+#define P_SECURE 0x80000L /* cannot change in modeline or secure mode */
+#define P_GETTEXT 0x100000L /* expand default value with _() */
+#define P_NOGLOB 0x200000L /* do not use local value for global vimrc */
+#define P_NFNAME 0x400000L /* only normal file name chars allowed */
+#define P_INSECURE 0x800000L /* option was set from a modeline */
+#define P_PRI_MKRC 0x1000000L /* priority for :mkvimrc (setting option has
+ side effects) */
+#define P_NO_ML 0x2000000L /* not allowed in modeline */
+#define P_CURSWANT 0x4000000L /* update curswant required; not needed when
+ * there is a redraw flag */
+
+/*
* Default values for 'errorformat'.
* The "%f|%l| %m" one is used for when the contents of the quickfix window is
* written to a file.
diff --git a/src/proto/option.pro b/src/proto/option.pro
index d0ba4ec..f7044da 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -63,4 +63,5 @@ long get_sw_value(buf_T *buf);
long get_sts_value(void);
void find_mps_values(int *initc, int *findc, int *backwards, int switchit);
unsigned int get_bkc_value(buf_T *buf);
+int get_option_flags(char_u *name);
/* vim: set ft=c : */
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
index 98cf985..bce23b8 100644
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -175,6 +175,7 @@ NEW_TESTS = test_arglist.res \
test_increment.res \
test_json.res \
test_langmap.res \
+ test_optionproperties.res \
test_packadd.res \
test_perl.res \
test_quickfix.res \
diff --git a/src/testdir/test_optionproperties.vim
b/src/testdir/test_optionproperties.vim
new file mode 100644
index 0000000..3f68f2f
--- /dev/null
+++ b/src/testdir/test_optionproperties.vim
@@ -0,0 +1,20 @@
+" Test for the optionproperties function.
+function Test_optionproperties()
+ call assert_equal({'type': 0, 'comma': 0, 'flaglist': 0},
+ \ optionproperties('antialias'))
+ call assert_equal({'type': 1, 'comma': 0, 'flaglist': 0},
+ \ optionproperties('cmdheight'))
+ call assert_equal({'type': 2, 'comma': 1, 'flaglist': 0},
+ \ optionproperties('backspace'))
+ call assert_equal({'type': 2, 'comma': 1, 'flaglist': 0},
+ \ optionproperties('belloff'))
+ call assert_equal({'type': 2, 'comma': 0, 'flaglist': 1},
+ \ optionproperties('breakat'))
+ call assert_equal({'type': 2, 'comma': 0, 'flaglist': 0},
+ \ optionproperties('ambiwidth'))
+ try
+ call optionproperties('unknown')
+ catch
+ call assert_exception('E518:')
+ endtry
+endfunction