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 vim_dev+unsubscr...@googlegroups.com.
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

Raspunde prin e-mail lui