Bram,

On Thu, Mar 24, 2016 at 06:44:39PM +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'.

-- 
: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..3087938 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,20 @@ 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:
+
+               type
+                                    Boolean: 0
+                                     Number: 1
+                       Comma separated list: 2
+                             Char flag list: 3
+                                     String: 4
+
+               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 9091f79..8a27ca3 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -684,6 +684,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);
@@ -8371,6 +8372,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},
@@ -15921,6 +15923,42 @@ 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_COMMA || flags & P_ONECOMMA)
+       type = 2;
+    else if (flags & P_FLAGLIST)
+       type = 3;
+    else if (flags & P_STRING)
+       type = 4;
+    else
+       type = 4; /* type unknown, assume string */
+    if (dict_add_nr_str(rettv->vval.v_dict, "type", type, 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 455ca7b..1db3e58 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_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..ae13e89
--- /dev/null
+++ b/src/testdir/test_optionproperties.vim
@@ -0,0 +1,14 @@
+" Test for the optionproperties function.
+function Test_optionproperties()
+  call assert_equal(0, optionproperties('antialias').type)
+  call assert_equal(1, optionproperties('cmdheight').type)
+  call assert_equal(2, optionproperties('backspace').type)
+  call assert_equal(2, optionproperties('belloff').type)
+  call assert_equal(3, optionproperties('breakat').type)
+  call assert_equal(4, optionproperties('ambiwidth').type)
+  try
+    call optionproperties('unknown')
+  catch
+    call assert_exception('E518:')
+  endtry
+endfunction

Raspunde prin e-mail lui