]> granicus.if.org Git - vim/commitdiff
updated for version 7.4.152 v7.4.152
authorBram Moolenaar <Bram@vim.org>
Tue, 14 Jan 2014 15:55:00 +0000 (16:55 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 14 Jan 2014 15:55:00 +0000 (16:55 +0100)
Problem:    Python: Cannot iterate over options.
Solution:   Add options iterator. (ZyX)

src/if_py_both.h
src/option.c
src/proto/option.pro
src/testdir/test86.in
src/testdir/test86.ok
src/testdir/test87.in
src/testdir/test87.ok
src/version.c
src/vim.h

index 6e3939abe569f4b634d990a7d1e6a1df5939fa73..01cbe418c8e1e64b09073d73323fab47dedbf6db 100644 (file)
@@ -2949,10 +2949,10 @@ typedef int (*checkfun)(void *);
 typedef struct
 {
     PyObject_HEAD
-    int opt_type;
-    void *from;
-    checkfun Check;
-    PyObject *fromObj;
+    int                opt_type;
+    void       *from;
+    checkfun   Check;
+    PyObject   *fromObj;
 } OptionsObject;
 
     static int
@@ -3071,6 +3071,69 @@ OptionsItem(OptionsObject *self, PyObject *keyObject)
     }
 }
 
+    static int
+OptionsContains(OptionsObject *self, PyObject *keyObject)
+{
+    char_u     *key;
+    PyObject   *todecref;
+
+    if (!(key = StringToChars(keyObject, &todecref)))
+       return -1;
+
+    if (*key == NUL)
+    {
+       Py_XDECREF(todecref);
+       return 0;
+    }
+
+    if (get_option_value_strict(key, NULL, NULL, self->opt_type, NULL))
+    {
+       Py_XDECREF(todecref);
+       return 1;
+    }
+    else
+    {
+       Py_XDECREF(todecref);
+       return 0;
+    }
+}
+
+typedef struct
+{
+    void       *lastoption;
+    int                opt_type;
+} optiterinfo_T;
+
+    static PyObject *
+OptionsIterNext(optiterinfo_T **oii)
+{
+    char_u     *name;
+
+    if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type)))
+       return PyString_FromString((char *)name);
+
+    return NULL;
+}
+
+    static PyObject *
+OptionsIter(OptionsObject *self)
+{
+    optiterinfo_T      *oii;
+
+    if (!(oii = PyMem_New(optiterinfo_T, 1)))
+    {
+       PyErr_NoMemory();
+       return NULL;
+    }
+
+    oii->opt_type = self->opt_type;
+    oii->lastoption = NULL;
+
+    return IterNew(oii,
+           (destructorfun) PyMem_Free, (nextfun) OptionsIterNext,
+           NULL, NULL);
+}
+
     static int
 set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
 {
@@ -3231,6 +3294,19 @@ OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
     return ret;
 }
 
+static PySequenceMethods OptionsAsSeq = {
+    0,                                 /* sq_length */
+    0,                                 /* sq_concat */
+    0,                                 /* sq_repeat */
+    0,                                 /* sq_item */
+    0,                                 /* sq_slice */
+    0,                                 /* sq_ass_item */
+    0,                                 /* sq_ass_slice */
+    (objobjproc) OptionsContains,      /* sq_contains */
+    0,                                 /* sq_inplace_concat */
+    0,                                 /* sq_inplace_repeat */
+};
+
 static PyMappingMethods OptionsAsMapping = {
     (lenfunc)       NULL,
     (binaryfunc)    OptionsItem,
@@ -6121,8 +6197,10 @@ init_structs(void)
     vim_memset(&OptionsType, 0, sizeof(OptionsType));
     OptionsType.tp_name = "vim.options";
     OptionsType.tp_basicsize = sizeof(OptionsObject);
+    OptionsType.tp_as_sequence = &OptionsAsSeq;
     OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
     OptionsType.tp_doc = "object for manipulating options";
+    OptionsType.tp_iter = (getiterfunc)OptionsIter;
     OptionsType.tp_as_mapping = &OptionsAsMapping;
     OptionsType.tp_dealloc = (destructor)OptionsDestructor;
     OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
index 4e087a58bfb2a0ee858c1c4b77c27560950de75a..8c72da6391debb5a8c2ea3ad3edd77fd638fd2a0 100644 (file)
@@ -8861,7 +8861,7 @@ get_option_value(name, numval, stringval, opt_flags)
 }
 #endif
 
-#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
+#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3) || defined(PROTO)
 /*
  * Returns the option attributes and its value. Unlike the above function it
  * will return either global value or local value of the option depending on
@@ -8874,7 +8874,8 @@ get_option_value(name, numval, stringval, opt_flags)
  * opt_type). Uses
  *
  * Returned flags:
- *       0 hidden or unknown option
+ *       0 hidden or unknown option, also option that does not have requested 
+ *         type (see SREQ_* in vim.h)
  *  see SOPT_* in vim.h for other flags
  *
  * Possible opt_type values: see SREQ_* in vim.h
@@ -8997,6 +8998,68 @@ get_option_value_strict(name, numval, stringval, opt_type, from)
 
     return r;
 }
+
+/*
+ * Iterate over options. First argument is a pointer to a pointer to a structure 
+ * inside options[] array, second is option type like in the above function.
+ *
+ * If first argument points to NULL it is assumed that iteration just started 
+ * and caller needs the very first value.
+ * If first argument points to the end marker function returns NULL and sets 
+ * first argument to NULL.
+ *
+ * Returns full option name for current option on each call.
+ */
+    char_u *
+option_iter_next(option, opt_type)
+    void       **option;
+    int                opt_type;
+{
+    struct vimoption   *ret = NULL;
+    do
+    {
+       if (*option == NULL)
+           *option = (void *) options;
+       else if (((struct vimoption *) (*option))->fullname == NULL)
+       {
+           *option = NULL;
+           return NULL;
+       }
+       else
+           *option = (void *) (((struct vimoption *) (*option)) + 1);
+
+       ret = ((struct vimoption *) (*option));
+
+       /* Hidden option */
+       if (ret->var == NULL)
+       {
+           ret = NULL;
+           continue;
+       }
+
+       switch (opt_type)
+       {
+           case SREQ_GLOBAL:
+               if (!(ret->indir == PV_NONE || ret->indir & PV_BOTH))
+                   ret = NULL;
+               break;
+           case SREQ_BUF:
+               if (!(ret->indir & PV_BUF))
+                   ret = NULL;
+               break;
+           case SREQ_WIN:
+               if (!(ret->indir & PV_WIN))
+                   ret = NULL;
+               break;
+           default:
+               EMSG2(_(e_intern2), "option_iter_next()");
+               return NULL;
+       }
+    }
+    while (ret == NULL);
+
+    return (char_u *)ret->fullname;
+}
 #endif
 
 /*
index cd3afbf79b523576638987c5a3edb6e3a9c676e1..4347d65919b5ae2d3ae5584fffecec060894e46a 100644 (file)
@@ -23,6 +23,7 @@ char_u *check_colorcolumn __ARGS((win_T *wp));
 char_u *check_stl_option __ARGS((char_u *s));
 int get_option_value __ARGS((char_u *name, long *numval, char_u **stringval, int opt_flags));
 int get_option_value_strict __ARGS((char_u *name, long *numval, char_u **stringval, int opt_type, void *from));
+char_u *option_iter_next __ARGS((void **option, int opt_type));
 char_u *set_option_value __ARGS((char_u *name, long number, char_u *string, int opt_flags));
 char_u *get_term_code __ARGS((char_u *tname));
 char_u *get_highlight_default __ARGS((void));
index 1ccf7bd3ded3151f3572a552147ced6652cea95e..240e07e477d6ef9a48d7b10a286963ab22fb2a28 100644 (file)
@@ -506,6 +506,11 @@ EOF
 :py bopts1=vim.buffers[vim.bindeval("g:bufs")[2]].options
 :py bopts2=vim.buffers[vim.bindeval("g:bufs")[1]].options
 :py bopts3=vim.buffers[vim.bindeval("g:bufs")[0]].options
+:$put ='wopts iters equal: '.pyeval('list(wopts1) == list(wopts2)')
+:$put ='bopts iters equal: '.pyeval('list(bopts1) == list(bopts2)')
+:py gset=set(iter(gopts1))
+:py wset=set(iter(wopts1))
+:py bset=set(iter(bopts1))
 :set path=.,..,,
 :let lst=[]
 :let lst+=[['paste',          1,     0,     1,     2,      1,    1,      0    ]]
@@ -536,6 +541,8 @@ EOF
 :       py oval3=bool(oval3)
 :   endif
 :   put ='>>> '.oname
+:   $put ='  g/w/b:'.pyeval('oname in gset').'/'.pyeval('oname in wset').'/'.pyeval('oname in bset')
+:   $put ='  g/w/b (in):'.pyeval('oname in gopts1').'/'.pyeval('oname in wopts1').'/'.pyeval('oname in bopts1')
 :   for v in ['gopts1', 'wopts1', 'bopts1']
 :       try
 :           put ='  p/'.v.': '.Ev('repr('.v.'['''.oname.'''])')
@@ -1122,6 +1129,13 @@ ee('import failing_import')
 ee('import failing')
 vim.options['rtp'] = old_rtp
 del old_rtp
+cb.append("> Options")
+cb.append(">> OptionsItem")
+ee('vim.options["abcQ"]')
+ee('vim.options[""]')
+stringtochars_test('vim.options[%s]')
+cb.append(">> OptionsContains")
+stringtochars_test('%s in vim.options')
 cb.append("> Dictionary")
 cb.append(">> DictionaryConstructor")
 ee('vim.Dictionary("abcI")')
index 42cb0259c8b047bc7c5c0ed464dba1ecdb3bc064..257a5ee4cd052670e5c51d7c9c942d16d5345d6d 100644 (file)
@@ -112,7 +112,11 @@ bac
 def
 bar
 jkl
+wopts iters equal: 1
+bopts iters equal: 1
 >>> paste
+  g/w/b:1/0/0
+  g/w/b (in):1/0/0
   p/gopts1: False
   p/wopts1! KeyError
   inv: 2! KeyError
@@ -133,6 +137,8 @@ jkl
   W: 1:1 2:1 3:1 4:1
   B: 1:1 2:1 3:1 4:1
 >>> previewheight
+  g/w/b:1/0/0
+  g/w/b (in):1/0/0
   p/gopts1: 12
   inv: 'a'! TypeError
   p/wopts1! KeyError
@@ -154,6 +160,8 @@ jkl
   W: 1:5 2:5 3:5 4:5
   B: 1:5 2:5 3:5 4:5
 >>> operatorfunc
+  g/w/b:1/0/0
+  g/w/b (in):1/0/0
   p/gopts1: ''
   inv: 2! TypeError
   p/wopts1! KeyError
@@ -175,6 +183,8 @@ jkl
   W: 1:'A' 2:'A' 3:'A' 4:'A'
   B: 1:'A' 2:'A' 3:'A' 4:'A'
 >>> number
+  g/w/b:0/1/0
+  g/w/b (in):0/1/0
   p/gopts1! KeyError
   inv: 0! KeyError
   gopts1! KeyError
@@ -193,6 +203,8 @@ jkl
   W: 1:1 2:1 3:0 4:0
   B: 1:1 2:1 3:0 4:0
 >>> numberwidth
+  g/w/b:0/1/0
+  g/w/b (in):0/1/0
   p/gopts1! KeyError
   inv: -100! KeyError
   gopts1! KeyError
@@ -212,6 +224,8 @@ jkl
   W: 1:3 2:5 3:2 4:8
   B: 1:3 2:5 3:2 4:8
 >>> colorcolumn
+  g/w/b:0/1/0
+  g/w/b (in):0/1/0
   p/gopts1! KeyError
   inv: 'abc4'! KeyError
   gopts1! KeyError
@@ -231,6 +245,8 @@ jkl
   W: 1:'+2' 2:'+3' 3:'+1' 4:''
   B: 1:'+2' 2:'+3' 3:'+1' 4:''
 >>> statusline
+  g/w/b:1/1/0
+  g/w/b (in):1/1/0
   p/gopts1: ''
   inv: 0! TypeError
   p/wopts1: None
@@ -248,6 +264,8 @@ jkl
   W: 1:'2' 2:'1' 3:'1' 4:'1'
   B: 1:'2' 2:'1' 3:'1' 4:'1'
 >>> autoindent
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 2! KeyError
   gopts1! KeyError
@@ -266,6 +284,8 @@ jkl
   W: 1:0 2:1 3:0 4:1
   B: 1:0 2:1 3:0 4:1
 >>> shiftwidth
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 3! KeyError
   gopts1! KeyError
@@ -284,6 +304,8 @@ jkl
   W: 1:0 2:2 3:8 4:1
   B: 1:0 2:2 3:8 4:1
 >>> omnifunc
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 1! KeyError
   gopts1! KeyError
@@ -303,6 +325,8 @@ jkl
   W: 1:'A' 2:'B' 3:'' 4:'C'
   B: 1:'A' 2:'B' 3:'' 4:'C'
 >>> preserveindent
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 2! KeyError
   gopts1! KeyError
@@ -321,6 +345,8 @@ jkl
   W: 1:0 2:1 3:0 4:1
   B: 1:0 2:1 3:0 4:1
 >>> path
+  g/w/b:1/0/1
+  g/w/b (in):1/0/1
   p/gopts1: '.,..,,'
   inv: 0! TypeError
   p/wopts1! KeyError
@@ -509,6 +535,21 @@ vim.foreach_rtp(int, 2):TypeError:('foreach_rtp() takes exactly one argument (2
 import xxx_no_such_module_xxx:ImportError:('No module named xxx_no_such_module_xxx',)
 import failing_import:ImportError:('No module named failing_import',)
 import failing:NotImplementedError:()
+> Options
+>> OptionsItem
+vim.options["abcQ"]:KeyError:('abcQ',)
+vim.options[""]:ValueError:('empty keys are not allowed',)
+>>> Testing StringToChars using vim.options[%s]
+vim.options[1]:TypeError:('expected str() or unicode() instance, but got int',)
+vim.options[u"\0"]:TypeError:('expected string without null bytes',)
+vim.options["\0"]:TypeError:('expected string without null bytes',)
+<<< Finished
+>> OptionsContains
+>>> Testing StringToChars using %s in vim.options
+1 in vim.options:TypeError:('expected str() or unicode() instance, but got int',)
+u"\0" in vim.options:TypeError:('expected string without null bytes',)
+"\0" in vim.options:TypeError:('expected string without null bytes',)
+<<< Finished
 > Dictionary
 >> DictionaryConstructor
 vim.Dictionary("abcI"):ValueError:('expected sequence element of size 2, but got sequence of size 1',)
index 79b24b00dedaae056362bc4bd391aae7b6f10364..e45883b59d9cb72771d347b748d7fcecfbc5c737 100644 (file)
@@ -503,6 +503,11 @@ EOF
 :py3 bopts1=vim.buffers[vim.bindeval("g:bufs")[2]].options
 :py3 bopts2=vim.buffers[vim.bindeval("g:bufs")[1]].options
 :py3 bopts3=vim.buffers[vim.bindeval("g:bufs")[0]].options
+:$put ='wopts iters equal: '.py3eval('list(wopts1) == list(wopts2)')
+:$put ='bopts iters equal: '.py3eval('list(bopts1) == list(bopts2)')
+:py3 gset=set(iter(gopts1))
+:py3 wset=set(iter(wopts1))
+:py3 bset=set(iter(bopts1))
 :set path=.,..,,
 :let lst=[]
 :let lst+=[['paste',          1,     0,     1,     2,      1,    1,      0    ]]
@@ -533,6 +538,8 @@ EOF
 :       py3 oval3=bool(oval3)
 :   endif
 :   put ='>>> '.oname
+:   $put ='  g/w/b:'.py3eval('oname in gset').'/'.py3eval('oname in wset').'/'.py3eval('oname in bset')
+:   $put ='  g/w/b (in):'.py3eval('oname in gopts1').'/'.py3eval('oname in wopts1').'/'.py3eval('oname in bopts1')
 :   for v in ['gopts1', 'wopts1', 'bopts1']
 :       try
 :           put ='  p/'.v.': '.Ev('repr('.v.'['''.oname.'''])')
@@ -1099,6 +1106,13 @@ ee('import failing_import')
 ee('import failing')
 vim.options['rtp'] = old_rtp
 del old_rtp
+cb.append("> Options")
+cb.append(">> OptionsItem")
+ee('vim.options["abcQ"]')
+ee('vim.options[""]')
+stringtochars_test('vim.options[%s]')
+cb.append(">> OptionsContains")
+stringtochars_test('%s in vim.options')
 cb.append("> Dictionary")
 cb.append(">> DictionaryConstructor")
 ee('vim.Dictionary("abcI")')
index 57ac1a63a9341d7e2af181fe51a951092bdbc7ba..d1ec84c6b83b0cf9eb5d41fd9e792faef541caa3 100644 (file)
@@ -112,7 +112,11 @@ bac
 def
 bar
 jkl
+wopts iters equal: 1
+bopts iters equal: 1
 >>> paste
+  g/w/b:1/0/0
+  g/w/b (in):1/0/0
   p/gopts1: False
   p/wopts1! KeyError
   inv: 2! KeyError
@@ -133,6 +137,8 @@ jkl
   W: 1:1 2:1 3:1 4:1
   B: 1:1 2:1 3:1 4:1
 >>> previewheight
+  g/w/b:1/0/0
+  g/w/b (in):1/0/0
   p/gopts1: 12
   inv: 'a'! TypeError
   p/wopts1! KeyError
@@ -154,6 +160,8 @@ jkl
   W: 1:5 2:5 3:5 4:5
   B: 1:5 2:5 3:5 4:5
 >>> operatorfunc
+  g/w/b:1/0/0
+  g/w/b (in):1/0/0
   p/gopts1: b''
   inv: 2! TypeError
   p/wopts1! KeyError
@@ -175,6 +183,8 @@ jkl
   W: 1:'A' 2:'A' 3:'A' 4:'A'
   B: 1:'A' 2:'A' 3:'A' 4:'A'
 >>> number
+  g/w/b:0/1/0
+  g/w/b (in):0/1/0
   p/gopts1! KeyError
   inv: 0! KeyError
   gopts1! KeyError
@@ -193,6 +203,8 @@ jkl
   W: 1:1 2:1 3:0 4:0
   B: 1:1 2:1 3:0 4:0
 >>> numberwidth
+  g/w/b:0/1/0
+  g/w/b (in):0/1/0
   p/gopts1! KeyError
   inv: -100! KeyError
   gopts1! KeyError
@@ -212,6 +224,8 @@ jkl
   W: 1:3 2:5 3:2 4:8
   B: 1:3 2:5 3:2 4:8
 >>> colorcolumn
+  g/w/b:0/1/0
+  g/w/b (in):0/1/0
   p/gopts1! KeyError
   inv: 'abc4'! KeyError
   gopts1! KeyError
@@ -231,6 +245,8 @@ jkl
   W: 1:'+2' 2:'+3' 3:'+1' 4:''
   B: 1:'+2' 2:'+3' 3:'+1' 4:''
 >>> statusline
+  g/w/b:1/1/0
+  g/w/b (in):1/1/0
   p/gopts1: b''
   inv: 0! TypeError
   p/wopts1: None
@@ -248,6 +264,8 @@ jkl
   W: 1:'2' 2:'1' 3:'1' 4:'1'
   B: 1:'2' 2:'1' 3:'1' 4:'1'
 >>> autoindent
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 2! KeyError
   gopts1! KeyError
@@ -266,6 +284,8 @@ jkl
   W: 1:0 2:1 3:0 4:1
   B: 1:0 2:1 3:0 4:1
 >>> shiftwidth
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 3! KeyError
   gopts1! KeyError
@@ -284,6 +304,8 @@ jkl
   W: 1:0 2:2 3:8 4:1
   B: 1:0 2:2 3:8 4:1
 >>> omnifunc
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 1! KeyError
   gopts1! KeyError
@@ -303,6 +325,8 @@ jkl
   W: 1:'A' 2:'B' 3:'' 4:'C'
   B: 1:'A' 2:'B' 3:'' 4:'C'
 >>> preserveindent
+  g/w/b:0/0/1
+  g/w/b (in):0/0/1
   p/gopts1! KeyError
   inv: 2! KeyError
   gopts1! KeyError
@@ -321,6 +345,8 @@ jkl
   W: 1:0 2:1 3:0 4:1
   B: 1:0 2:1 3:0 4:1
 >>> path
+  g/w/b:1/0/1
+  g/w/b (in):1/0/1
   p/gopts1: b'.,..,,'
   inv: 0! TypeError
   p/wopts1! KeyError
@@ -509,6 +535,21 @@ vim.foreach_rtp(int, 2):(<class 'TypeError'>, TypeError('foreach_rtp() takes exa
 import xxx_no_such_module_xxx:(<class 'ImportError'>, ImportError('No module named xxx_no_such_module_xxx',))
 import failing_import:(<class 'ImportError'>, ImportError('No module named failing_import',))
 import failing:(<class 'NotImplementedError'>, NotImplementedError())
+> Options
+>> OptionsItem
+vim.options["abcQ"]:(<class 'KeyError'>, KeyError('abcQ',))
+vim.options[""]:(<class 'ValueError'>, ValueError('empty keys are not allowed',))
+>>> Testing StringToChars using vim.options[%s]
+vim.options[1]:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
+vim.options[b"\0"]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
+vim.options["\0"]:(<class 'TypeError'>, TypeError('expected bytes with no null',))
+<<< Finished
+>> OptionsContains
+>>> Testing StringToChars using %s in vim.options
+1 in vim.options:(<class 'TypeError'>, TypeError('expected bytes() or str() instance, but got int',))
+b"\0" in vim.options:(<class 'TypeError'>, TypeError('expected bytes with no null',))
+"\0" in vim.options:(<class 'TypeError'>, TypeError('expected bytes with no null',))
+<<< Finished
 > Dictionary
 >> DictionaryConstructor
 vim.Dictionary("abcI"):(<class 'ValueError'>, ValueError('expected sequence element of size 2, but got sequence of size 1',))
index c0fe21f3f978b1bd9db9a254c5f16860a0c8d792..8a472146db30c7750279475ec48cca1475f7624d 100644 (file)
@@ -738,6 +738,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    152,
 /**/
     151,
 /**/
index 88f3dc29b4af45df4c8bae5f5bf7c17d16121cba..3969842c7bef8eec07e542529f9b805650419039 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2249,6 +2249,7 @@ typedef int VimClipboard; /* This is required for the prototypes. */
 #define SOPT_BUF       0x20    /* Option has buffer-local value */
 #define SOPT_UNSET     0x40    /* Option does not have local value set */
 
+/* Option types for various functions in option.c */
 #define SREQ_GLOBAL    0       /* Request global option */
 #define SREQ_WIN       1       /* Request window-local option */
 #define SREQ_BUF       2       /* Request buffer-local option */