summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <bram@vim.org>2013-05-06 03:52:55 +0200
committerBram Moolenaar <bram@vim.org>2013-05-06 03:52:55 +0200
commitab38f73b222cd77a27cb4b1baa5b3ff826082b77 (patch)
treeb7f5993e539d921ed4c649185cdca678c966c83d
parent3274af7301070abb8c262209c1900e413d6b77b7 (diff)
downloadvim-7-3-924.tar.gz
updated for version 7.3.924v7.3.924v7-3-924
Problem: Python interface can't easily access options. Solution: Add vim.options, vim.window.options and vim.buffer.options. (ZyX)
-rw-r--r--runtime/doc/if_pyth.txt33
-rw-r--r--src/eval.c57
-rw-r--r--src/if_py_both.h292
-rw-r--r--src/if_python.c4
-rw-r--r--src/if_python3.c3
-rw-r--r--src/option.c219
-rw-r--r--src/proto/eval.pro2
-rw-r--r--src/proto/option.pro2
-rw-r--r--src/testdir/test86.in119
-rw-r--r--src/testdir/test86.ok226
-rw-r--r--src/testdir/test87.in119
-rw-r--r--src/testdir/test87.ok226
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h13
14 files changed, 1299 insertions, 18 deletions
diff --git a/runtime/doc/if_pyth.txt b/runtime/doc/if_pyth.txt
index 96fd1247..044d92af 100644
--- a/runtime/doc/if_pyth.txt
+++ b/runtime/doc/if_pyth.txt
@@ -243,6 +243,18 @@ vim.vvars *python-vvars*
vim (|v:|) variables respectively. Identical to `vim.bindeval("g:")`,
but faster.
+vim.options *python-options*
+ Object partly supporting mapping protocol (supports setting and
+ getting items) providing a read-write access to global options.
+ Note: unlike |:set| this provides access only to global options. You
+ cannot use this object to obtain or set local options' values or
+ access local-only options in any fashion. Raises KeyError if no global
+ option with such name exists (i.e. does not raise KeyError for
+ |global-local| options and global only options, but does for window-
+ and buffer-local ones). Use |python-buffer| objects to access to
+ buffer-local options and |python-window| objects to access to
+ window-local options.
+
Output from Python *python-output*
Vim displays all Python code output in the Vim message area. Normal
output appears as information messages, and error output appears as
@@ -283,6 +295,17 @@ Buffer indexes start at zero, as is normal in Python. This differs from vim
line numbers, which start from 1. This is particularly relevant when dealing
with marks (see below) which use vim line numbers.
+The buffer object attributes are:
+ b.vars Dictionary-like object used to access
+ |buffer-variable|s.
+ b.options Mapping object (supports item getting, setting and
+ deleting) that provides access to buffer-local options
+ and buffer-local values of |global-local| options. Use
+ |python-window|.options if option is window-local,
+ this object will raise KeyError. If option is
+ |global-local| and local value is missing getting it
+ will return None.
+
The buffer object methods are:
b.append(str) Append a line to the buffer
b.append(str, nr) Idem, below line "nr"
@@ -313,6 +336,8 @@ Examples (assume b is the current buffer) >
:py (row,col) = b.mark('a') # named mark
:py r = b.range(1,5) # a sub-range of the buffer
:py b.vars["foo"] = "bar" # assign b:foo variable
+ :py b.options["ff"] = "dos" # set fileformat
+ :py del b.options["ar"] # same as :set autoread<
==============================================================================
4. Range objects *python-range*
@@ -363,6 +388,14 @@ Window attributes are:
vars (read-only) The window |w:| variables. Attribute is
unassignable, but you can change window
variables this way
+ options (read-only) The window-local options. Attribute is
+ unassignable, but you can change window
+ options this way. Provides access only to
+ window-local options, for buffer-local use
+ |python-buffer| and for global ones use
+ |python-options|. If option is |global-local|
+ and local value is missing getting it will
+ return None.
The height attribute is writable only if the screen is split horizontally.
The width attribute is writable only if the screen is split vertically.
diff --git a/src/eval.c b/src/eval.c
index 085eff88..e757f6bc 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -16643,9 +16643,48 @@ f_setwinvar(argvars, rettv)
setwinvar(argvars, rettv, 0);
}
+ int
+switch_win(save_curwin, save_curtab, win, tp)
+ win_T **save_curwin;
+ tabpage_T **save_curtab;
+ win_T *win;
+ tabpage_T *tp;
+{
+#ifdef FEAT_WINDOWS
+ /* set curwin to be our win, temporarily */
+ *save_curwin = curwin;
+ *save_curtab = curtab;
+ goto_tabpage_tp(tp, TRUE);
+ if (!win_valid(win))
+ return FAIL;
+ curwin = win;
+ curbuf = curwin->w_buffer;
+#endif
+ return OK;
+}
+
+ void
+restore_win(save_curwin, save_curtab)
+ win_T *save_curwin;
+ tabpage_T *save_curtab;
+{
+#ifdef FEAT_WINDOWS
+ /* Restore current tabpage and window, if still valid (autocomands can
+ * make them invalid). */
+ if (valid_tabpage(save_curtab))
+ goto_tabpage_tp(save_curtab, TRUE);
+ if (win_valid(save_curwin))
+ {
+ curwin = save_curwin;
+ curbuf = curwin->w_buffer;
+ }
+#endif
+}
+
/*
* "setwinvar()" and "settabwinvar()" functions
*/
+
static void
setwinvar(argvars, rettv, off)
typval_T *argvars;
@@ -16678,14 +16717,8 @@ setwinvar(argvars, rettv, off)
if (win != NULL && varname != NULL && varp != NULL)
{
#ifdef FEAT_WINDOWS
- /* set curwin to be our win, temporarily */
- save_curwin = curwin;
- save_curtab = curtab;
- goto_tabpage_tp(tp, TRUE);
- if (!win_valid(win))
+ if (switch_win(&save_curwin, &save_curtab, win, tp) == FAIL)
return;
- curwin = win;
- curbuf = curwin->w_buffer;
#endif
if (*varname == '&')
@@ -16713,15 +16746,7 @@ setwinvar(argvars, rettv, off)
}
#ifdef FEAT_WINDOWS
- /* Restore current tabpage and window, if still valid (autocomands can
- * make them invalid). */
- if (valid_tabpage(save_curtab))
- goto_tabpage_tp(save_curtab, TRUE);
- if (win_valid(save_curwin))
- {
- curwin = save_curwin;
- curbuf = curwin->w_buffer;
- }
+ restore_win(save_curwin, save_curtab);
#endif
}
}
diff --git a/src/if_py_both.h b/src/if_py_both.h
index 4362aee2..ff4ba0e5 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -1497,6 +1497,279 @@ static struct PyMethodDef FunctionMethods[] = {
{ NULL, NULL, 0, NULL }
};
+/*
+ * Options object
+ */
+
+static PyTypeObject OptionsType;
+
+typedef int (*checkfun)(void *);
+
+typedef struct
+{
+ PyObject_HEAD
+ int opt_type;
+ void *from;
+ checkfun Check;
+ PyObject *fromObj;
+} OptionsObject;
+
+ static PyObject *
+OptionsItem(OptionsObject *this, PyObject *keyObject)
+{
+ char_u *key;
+ int flags;
+ long numval;
+ char_u *stringval;
+
+ if (this->Check(this->from))
+ return NULL;
+
+ DICTKEY_DECL
+
+ DICTKEY_GET_NOTEMPTY(NULL)
+
+ flags = get_option_value_strict(key, &numval, &stringval,
+ this->opt_type, this->from);
+
+ DICTKEY_UNREF
+
+ if (flags == 0)
+ {
+ PyErr_SetString(PyExc_KeyError, "Option does not exist in given scope");
+ return NULL;
+ }
+
+ if (flags & SOPT_UNSET)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ else if (flags & SOPT_BOOL)
+ {
+ PyObject *r;
+ r = numval ? Py_True : Py_False;
+ Py_INCREF(r);
+ return r;
+ }
+ else if (flags & SOPT_NUM)
+ return PyInt_FromLong(numval);
+ else if (flags & SOPT_STRING)
+ {
+ if (stringval)
+ return PyBytes_FromString((char *) stringval);
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, "Unable to get option value");
+ return NULL;
+ }
+ }
+ else
+ {
+ PyErr_SetVim("Internal error: unknown option type. Should not happen");
+ return NULL;
+ }
+}
+
+ static int
+set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
+ char_u *key;
+ int numval;
+ char_u *stringval;
+ int opt_flags;
+ int opt_type;
+ void *from;
+{
+ win_T *save_curwin;
+ tabpage_T *save_curtab;
+ aco_save_T aco;
+ int r = 0;
+
+ switch (opt_type)
+ {
+ case SREQ_WIN:
+ if (switch_win(&save_curwin, &save_curtab, (win_T *) from, curtab)
+ == FAIL)
+ {
+ PyErr_SetVim("Problem while switching windows.");
+ return -1;
+ }
+ set_option_value(key, numval, stringval, opt_flags);
+ restore_win(save_curwin, save_curtab);
+ break;
+ case SREQ_BUF:
+ aucmd_prepbuf(&aco, (buf_T *) from);
+ set_option_value(key, numval, stringval, opt_flags);
+ aucmd_restbuf(&aco);
+ break;
+ case SREQ_GLOBAL:
+ set_option_value(key, numval, stringval, opt_flags);
+ break;
+ }
+ return r;
+}
+
+ static int
+OptionsAssItem(OptionsObject *this, PyObject *keyObject, PyObject *valObject)
+{
+ char_u *key;
+ int flags;
+ int opt_flags;
+ int r = 0;
+
+ if (this->Check(this->from))
+ return -1;
+
+ DICTKEY_DECL
+
+ DICTKEY_GET_NOTEMPTY(-1)
+
+ flags = get_option_value_strict(key, NULL, NULL,
+ this->opt_type, this->from);
+
+ DICTKEY_UNREF
+
+ if (flags == 0)
+ {
+ PyErr_SetString(PyExc_KeyError, "Option does not exist in given scope");
+ return -1;
+ }
+
+ if (valObject == NULL)
+ {
+ if (this->opt_type == SREQ_GLOBAL)
+ {
+ PyErr_SetString(PyExc_ValueError, "Unable to unset global option");
+ return -1;
+ }
+ else if (!(flags & SOPT_GLOBAL))
+ {
+ PyErr_SetString(PyExc_ValueError, "Unable to unset option without "
+ "global value");
+ return -1;
+ }
+ else
+ {
+ unset_global_local_option(key, this->from);
+ return 0;
+ }
+ }
+
+ opt_flags = (this->opt_type ? OPT_LOCAL : OPT_GLOBAL);
+
+ if (flags & SOPT_BOOL)
+ {
+ if (!PyBool_Check(valObject))
+ {
+ PyErr_SetString(PyExc_ValueError, "Object must be boolean");
+ return -1;
+ }
+
+ r = set_option_value_for(key, (valObject == Py_True), NULL, opt_flags,
+ this->opt_type, this->from);
+ }
+ else if (flags & SOPT_NUM)
+ {
+ int val;
+
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(valObject))
+ val = PyInt_AsLong(valObject);
+ else
+#endif
+ if (PyLong_Check(valObject))
+ val = PyLong_AsLong(valObject);
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, "Object must be integer");
+ return -1;
+ }
+
+ r = set_option_value_for(key, val, NULL, opt_flags,
+ this->opt_type, this->from);
+ }
+ else
+ {
+ char_u *val;
+ if (PyBytes_Check(valObject))
+ {
+
+ if (PyString_AsStringAndSize(valObject, (char **) &val, NULL) == -1)
+ return -1;
+ if (val == NULL)
+ return -1;
+
+ val = vim_strsave(val);
+ }
+ else if (PyUnicode_Check(valObject))
+ {
+ PyObject *bytes;
+
+ bytes = PyUnicode_AsEncodedString(valObject, (char *)ENC_OPT, NULL);
+ if (bytes == NULL)
+ return -1;
+
+ if(PyString_AsStringAndSize(bytes, (char **) &val, NULL) == -1)
+ return -1;
+ if (val == NULL)
+ return -1;
+
+ val = vim_strsave(val);
+ Py_XDECREF(bytes);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, "Object must be string");
+ return -1;
+ }
+
+ r = set_option_value_for(key, 0, val, opt_flags,
+ this->opt_type, this->from);
+ vim_free(val);
+ }
+
+ return r;
+}
+
+ static int
+dummy_check(void *arg UNUSED)
+{
+ return 0;
+}
+
+ static PyObject *
+OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
+{
+ OptionsObject *self;
+
+ self = PyObject_NEW(OptionsObject, &OptionsType);
+ if (self == NULL)
+ return NULL;
+
+ self->opt_type = opt_type;
+ self->from = from;
+ self->Check = Check;
+ self->fromObj = fromObj;
+ if (fromObj)
+ Py_INCREF(fromObj);
+
+ return (PyObject *)(self);
+}
+
+ static void
+OptionsDestructor(PyObject *self)
+{
+ if (((OptionsObject *)(self))->fromObj)
+ Py_DECREF(((OptionsObject *)(self))->fromObj);
+ DESTRUCTOR_FINISH(self);
+}
+
+static PyMappingMethods OptionsAsMapping = {
+ (lenfunc) NULL,
+ (binaryfunc) OptionsItem,
+ (objobjargproc) OptionsAssItem,
+};
+
#define INVALID_WINDOW_VALUE ((win_T *)(-1))
static int
@@ -1534,8 +1807,12 @@ WindowAttr(WindowObject *this, char *name)
#endif
else if (strcmp(name, "vars") == 0)
return DictionaryNew(this->win->w_vars);
+ else if (strcmp(name, "options") == 0)
+ return OptionsNew(SREQ_WIN, this->win, (checkfun) CheckWindow,
+ (PyObject *) this);
else if (strcmp(name,"__members__") == 0)
- return Py_BuildValue("[ssss]", "buffer", "cursor", "height", "vars");
+ return Py_BuildValue("[sssss]", "buffer", "cursor", "height", "vars",
+ "options");
else
return NULL;
}
@@ -2499,8 +2776,11 @@ BufferAttr(BufferObject *this, char *name)
return Py_BuildValue(Py_ssize_t_fmt, this->buf->b_fnum);
else if (strcmp(name, "vars") == 0)
return DictionaryNew(this->buf->b_vars);
+ else if (strcmp(name, "options") == 0)
+ return OptionsNew(SREQ_BUF, this->buf, (checkfun) CheckBuffer,
+ (PyObject *) this);
else if (strcmp(name,"__members__") == 0)
- return Py_BuildValue("[sss]", "name", "number", "vars");
+ return Py_BuildValue("[ssss]", "name", "number", "vars", "options");
else
return NULL;
}
@@ -3121,6 +3401,14 @@ init_structs(void)
FunctionType.tp_getattr = FunctionGetattr;
#endif
+ vim_memset(&OptionsType, 0, sizeof(OptionsType));
+ OptionsType.tp_name = "vim.options";
+ OptionsType.tp_basicsize = sizeof(OptionsObject);
+ OptionsType.tp_flags = Py_TPFLAGS_DEFAULT;
+ OptionsType.tp_doc = "object for manipulating options";
+ OptionsType.tp_as_mapping = &OptionsAsMapping;
+ OptionsType.tp_dealloc = OptionsDestructor;
+
#if PY_MAJOR_VERSION >= 3
vim_memset(&vimmodule, 0, sizeof(vimmodule));
vimmodule.m_name = "vim";
diff --git a/src/if_python.c b/src/if_python.c
index 6e1cb0c0..fb2d8986 100644
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -1341,6 +1341,7 @@ PythonMod_Init(void)
PyType_Ready(&BufListType);
PyType_Ready(&WinListType);
PyType_Ready(&CurrentType);
+ PyType_Ready(&OptionsType);
/* Set sys.argv[] to avoid a crash in warn(). */
PySys_SetArgv(1, argv);
@@ -1360,6 +1361,9 @@ PythonMod_Init(void)
tmp = DictionaryNew(&vimvardict);
PyDict_SetItemString(dict, "vvars", tmp);
Py_DECREF(tmp);
+ tmp = OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL);
+ PyDict_SetItemString(dict, "options", tmp);
+ Py_DECREF(tmp);
PyDict_SetItemString(dict, "VAR_LOCKED", PyInt_FromLong(VAR_LOCKED));
PyDict_SetItemString(dict, "VAR_FIXED", PyInt_FromLong(VAR_FIXED));
PyDict_SetItemString(dict, "VAR_SCOPE", PyInt_FromLong(VAR_SCOPE));
diff --git a/src/if_python3.c b/src/if_python3.c
index 659316b4..35fcffac 100644
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -1628,6 +1628,7 @@ Py3Init_vim(void)
PyType_Ready(&DictionaryType);
PyType_Ready(&ListType);
PyType_Ready(&FunctionType);
+ PyType_Ready(&OptionsType);
/* Set sys.argv[] to avoid a crash in warn(). */
PySys_SetArgv(1, argv);
@@ -1649,6 +1650,8 @@ Py3Init_vim(void)
PyModule_AddObject(mod, "vars", DictionaryNew(&globvardict));
PyModule_AddObject(mod, "vvars", DictionaryNew(&vimvardict));
+ PyModule_AddObject(mod, "options",
+ OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
#define ADD_INT_CONSTANT(name, value) \
tmp = PyLong_FromLong(value); \
diff --git a/src/option.c b/src/option.c
index 39b48dea..c9607632 100644
--- a/src/option.c
+++ b/src/option.c
@@ -8820,6 +8820,144 @@ get_option_value(name, numval, stringval, opt_flags)
}
#endif
+#if defined(FEAT_PYTHON) || defined(FEAT_PYTHON3)
+/*
+ * 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
+ * what was requested, but it will never return global value if it was
+ * requested to return local one and vice versa. Neither it will return
+ * buffer-local value if it was requested to return window-local one.
+ *
+ * Pretends that option is absent if it is not present in the requested scope
+ * (i.e. has no global, window-local or buffer-local value depending on
+ * opt_type). Uses
+ *
+ * Returned flags:
+ * 0 hidden or unknown option
+ * see SOPT_* in vim.h for other flags
+ *
+ * Possible opt_type values: see SREQ_* in vim.h
+ */
+ int
+get_option_value_strict(name, numval, stringval, opt_type, from)
+ char_u *name;
+ long *numval;
+ char_u **stringval; /* NULL when only obtaining attributes */
+ int opt_type;
+ void *from;
+{
+ int opt_idx;
+ char_u *varp;
+ struct vimoption *p;
+ int r = 0;
+
+ opt_idx = findoption(name);
+ if (opt_idx < 0)
+ return 0;
+
+ p = &(options[opt_idx]);
+
+ /* Hidden option */
+ if (p->var == NULL)
+ return 0;
+
+ if (p->flags & P_BOOL)
+ r |= SOPT_BOOL;
+ else if (p->flags & P_NUM)
+ r |= SOPT_NUM;
+ else if (p->flags & P_STRING)
+ r |= SOPT_STRING;
+
+ if (p->indir == PV_NONE)
+ {
+ if (opt_type == SREQ_GLOBAL)
+ r |= SOPT_GLOBAL;
+ else
+ return 0; /* Did not request global-only option */
+ }
+ else
+ {
+ if (p->indir & PV_BOTH)
+ r |= SOPT_GLOBAL;
+ else if (opt_type == SREQ_GLOBAL)
+ return 0; /* Requested global option */
+
+ if (p->indir & PV_WIN)
+ {
+ if (opt_type == SREQ_BUF)
+ return 0; /* Did not request window-local option */
+ else
+ r |= SOPT_WIN;
+ }
+ else if (p->indir & PV_BUF)
+ {
+ if (opt_type == SREQ_WIN)
+ return 0; /* Did not request buffer-local option */
+ else
+ r |= SOPT_BUF;
+ }
+ }
+
+ if (stringval == NULL)
+ return r;
+
+ if (opt_type == SREQ_GLOBAL)
+ varp = p->var;
+ else
+ {
+ if (opt_type == SREQ_BUF)
+ {
+ /* Special case: 'modified' is b_changed, but we also want to
+ * consider it set when 'ff' or 'fenc' changed. */
+ if (p->indir == PV_MOD)
+ {
+ *numval = bufIsChanged((buf_T *) from);
+ varp = NULL;
+ }
+#ifdef FEAT_CRYPT
+ else if (p->indir == PV_KEY)
+ {
+ /* never return the value of the crypt key */
+ *stringval = NULL;
+ varp = NULL;
+ }
+#endif
+ else
+ {
+ aco_save_T aco;
+ aucmd_prepbuf(&aco, (buf_T *) from);
+ varp = get_varp(p);
+ aucmd_restbuf(&aco);
+ }
+ }
+ else if (opt_type == SREQ_WIN)
+ {
+ win_T *save_curwin;
+ save_curwin = curwin;
+ curwin = (win_T *) from;
+ curbuf = curwin->w_buffer;
+ varp = get_varp(p);
+ curwin = save_curwin;
+ curbuf = curwin->w_buffer;
+ }
+ if (varp == p->var)
+ return (r | SOPT_UNSET);
+ }
+
+ if (varp != NULL)
+ {
+ if (p->flags & P_STRING)
+ *stringval = vim_strsave(*(char_u **)(varp));
+ else if (p->flags & P_NUM)
+ *numval = *(long *) varp;
+ else
+ *numval = *(int *)varp;
+ }
+
+ return r;
+}
+#endif
+
/*
* Set the value of option "name".
* Use "string" for string options, use "number" for other options.
@@ -9557,6 +9695,87 @@ comp_col()
}
/*
+ * Unset local option value, similar to ":set opt<".
+ */
+
+ void
+unset_global_local_option(name, from)
+ char_u *name;
+ void *from;
+{
+ struct vimoption *p;
+ int opt_idx;
+
+ buf_T *buf = (buf_T *) from;
+ win_T *win = (win_T *) from;
+
+ opt_idx = findoption(name);
+ p = &(options[opt_idx]);
+
+ switch ((int)p->indir)
+ {
+ /* global option with local value: use local value if it's been set */
+ case PV_EP:
+ *buf->b_p_ep = NUL;
+ break;
+ case PV_KP:
+ *buf->b_p_kp = NUL;
+ break;
+ case PV_PATH:
+ *buf->b_p_path = NUL;
+ break;
+ case PV_AR:
+ buf->b_p_ar = -1;
+ break;
+ case PV_TAGS:
+ *buf->b_p_tags = NUL;
+ break;
+#ifdef FEAT_FIND_ID
+ case PV_DEF:
+ *buf->b_p_def = NUL;
+ break;
+ case PV_INC:
+ *buf->b_p_inc = NUL;
+ break;
+#endif
+#ifdef FEAT_INS_EXPAND
+ case PV_DICT:
+ *buf->b_p_dict = NUL;
+ break;
+ case PV_TSR:
+ *buf->b_p_tsr = NUL;
+ break;
+#endif
+#ifdef FEAT_QUICKFIX
+ case PV_EFM:
+ *buf->b_p_efm = NUL;
+ break;
+ case PV_GP:
+ *buf->b_p_gp = NUL;
+ break;
+ case PV_MP:
+ *buf->b_p_mp = NUL;
+ break;
+#endif
+#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
+ case PV_BEXPR:
+ *buf->b_p_bexpr = NUL;
+ break;
+#endif
+#if defined(FEAT_CRYPT)
+ case PV_CM:
+ *buf->b_p_cm = NUL;
+ break;
+#endif
+#ifdef FEAT_STL_OPT
+ case PV_STL:
+ *win->w_p_stl = NUL;
+ break;
+#endif
+ }
+}
+
+/*
* Get pointer to option variable, depending on local or global scope.
*/
static char_u *
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index b23700d7..496fb75c 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -125,4 +125,6 @@ void last_set_msg __ARGS((scid_T scriptID));
void ex_oldfiles __ARGS((exarg_T *eap));
int modify_fname __ARGS((char_u *src, int *usedlen, char_u **fnamep, char_u **bufp, int *fnamelen));
char_u *do_string_sub __ARGS((char_u *str, char_u *pat, char_u *sub, char_u *flags));
+int switch_win __ARGS((win_T **, tabpage_T **, win_T *, tabpage_T *));
+void restore_win __ARGS((win_T *, tabpage_T *));
/* vim: set ft=c : */
diff --git a/src/proto/option.pro b/src/proto/option.pro
index ba0a4e16..681fa459 100644
--- a/src/proto/option.pro
+++ b/src/proto/option.pro
@@ -22,6 +22,7 @@ void set_string_option_direct __ARGS((char_u *name, int opt_idx, char_u *val, in
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));
void 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));
@@ -33,6 +34,7 @@ void free_termoptions __ARGS((void));
void free_one_termoption __ARGS((char_u *var));
void set_term_defaults __ARGS((void));
void comp_col __ARGS((void));
+void unset_global_local_option __ARGS((char_u *name, void *from));
char_u *get_equalprg __ARGS((void));
void win_copy_options __ARGS((win_T *wp_from, win_T *wp_to));
void copy_winopt __ARGS((winopt_T *from, winopt_T *to));
diff --git a/src/testdir/test86.in b/src/testdir/test86.in
index fc61848e..ca448075 100644
--- a/src/testdir/test86.in
+++ b/src/testdir/test86.in
@@ -359,6 +359,125 @@ EOF
:put =pyeval('vim.vars[''foo'']')
:put =pyeval('vim.current.window.vars[''abc'']')
:put =pyeval('vim.current.buffer.vars[''baz'']')
+:"
+:" Options
+:" paste: boolean, global
+:" previewheight number, global
+:" operatorfunc: string, global
+:" number: boolean, window-local
+:" numberwidth: number, window-local
+:" colorcolumn: string, window-local
+:" statusline: string, window-local/global
+:" autoindent: boolean, buffer-local
+:" iminsert: number, buffer-local
+:" omnifunc: string, buffer-local
+:" preserveindent: boolean, buffer-local/global
+:" path: string, buffer-local/global
+:let g:bufs=[bufnr('%')]
+:new
+:let g:bufs+=[bufnr('%')]
+:vnew
+:let g:bufs+=[bufnr('%')]
+:wincmd j
+:vnew
+:let g:bufs+=[bufnr('%')]
+:wincmd l
+:fun RecVars(opt)
+: let gval =string(eval('&g:'.a:opt))
+: let wvals=join(map(range(1, 4), 'v:val.":".string(getwinvar(v:val, "&".a:opt))'))
+: let bvals=join(map(copy(g:bufs), 'v:val.":".string(getbufvar(v:val, "&".a:opt))'))
+: put =' G: '.gval
+: put =' W: '.wvals
+: put =' B: '.wvals
+:endfun
+py << EOF
+def e(s, g=globals(), l=locals()):
+ try:
+ exec(s, g, l)
+ except Exception as e:
+ vim.command('throw ' + repr(e.__class__.__name__))
+
+def ev(s, g=globals(), l=locals()):
+ try:
+ return eval(s, g, l)
+ except Exception as e:
+ vim.command('throw ' + repr(e.__class__.__name__))
+ return 0
+EOF
+:function E(s)
+: python e(vim.eval('a:s'))
+:endfunction
+:function Ev(s)
+: return pyeval('ev(vim.eval("a:s"))')
+:endfunction
+:py gopts1=vim.options
+:py wopts1=vim.windows[2].options
+:py wopts2=vim.windows[0].options
+:py wopts3=vim.windows[1].options
+: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
+:let lst=[]
+:let lst+=[['paste', 1, 0, 1, 2, 1, 1, 0 ]]
+:let lst+=[['previewheight', 5, 1, 6, 'a', 0, 1, 0 ]]
+:let lst+=[['operatorfunc', 'A', 'B', 'C', 2, 0, 1, 0 ]]
+:let lst+=[['number', 0, 1, 1, 0, 1, 0, 1 ]]
+:let lst+=[['numberwidth', 2, 3, 5, -100, 0, 0, 1 ]]
+:let lst+=[['colorcolumn', '+1', '+2', '+3', 'abc', 0, 0, 1 ]]
+:let lst+=[['statusline', '1', '2', '4', 0, 0, 1, 1 ]]
+:let lst+=[['autoindent', 0, 1, 1, 2, 1, 0, 2 ]]
+:let lst+=[['iminsert', 0, 2, 1, 3, 0, 0, 2 ]]
+:let lst+=[['omnifunc', 'A', 'B', 'C', 1, 0, 0, 2 ]]
+:let lst+=[['preserveindent', 0, 1, 1, 2, 1, 1, 2 ]]
+:let lst+=[['path', '.,,', ',,', '.', 0, 0, 1, 2 ]]
+:for [oname, oval1, oval2, oval3, invval, bool, global, local] in lst
+: py oname=vim.eval('oname')
+: py oval1=vim.bindeval('oval1')
+: py oval2=vim.bindeval('oval2')
+: py oval3=vim.bindeval('oval3')
+: if invval is 0 || invval is 1
+: py invval=bool(vim.bindeval('invval'))
+: else
+: py invval=vim.bindeval('invval')
+: endif
+: if bool
+: py oval1=bool(oval1)
+: py oval2=bool(oval2)
+: py oval3=bool(oval3)
+: endif
+: put ='>>> '.oname
+: for v in ['gopts1', 'wopts1', 'bopts1']
+: try
+: put =' p/'.v.': '.Ev('repr('.v.'['''.oname.'''])')
+: catch
+: put =' p/'.v.'! '.v:exception
+: endtry
+: try
+: call E(v.'["'.oname.'"]=invval')
+: catch
+: put =' inv: '.string(invval).'! '.v:exception
+: endtry
+: for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
+: let val=substitute(vv, '^.opts', 'oval', '')
+: try
+: call E(vv.'["'.oname.'"]='.val)
+: catch
+: put =' '.vv.'! '.v:exception
+: endtry
+: endfor
+: endfor
+: call RecVars(oname)
+: for v in ['wopts3', 'bopts3']
+: try
+: call E('del '.v.'["'.oname.'"]')
+: catch
+: put =' del '.v.'! '.v:exception
+: endtry
+: endfor
+: call RecVars(oname)
+endtry
+:endfor
+:only
:endfun
:"
:call Test()
diff --git a/src/testdir/test86.ok b/src/testdir/test86.ok
index 3bd2dcf2..2acfb98a 100644
--- a/src/testdir/test86.ok
+++ b/src/testdir/test86.ok
@@ -80,3 +80,229 @@ Abc
bac
def
bar
+>>> paste
+ p/gopts1: False
+ inv: 2! ValueError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1! KeyError
+ inv: 2! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 1
+ W: 1:1 2:1 3:1 4:1
+ B: 1:1 2:1 3:1 4:1
+ del wopts3! KeyError
+ del bopts3! KeyError
+ G: 1
+ W: 1:1 2:1 3:1 4:1
+ B: 1:1 2:1 3:1 4:1
+>>> previewheight
+ p/gopts1: 12
+ inv: 'a'! ValueError
+ p/wopts1! KeyError
+ inv: 'a'! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1! KeyError
+ inv: 'a'! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 5
+ W: 1:5 2:5 3:5 4:5
+ B: 1:5 2:5 3:5 4:5
+ del wopts3! KeyError
+ del bopts3! KeyError
+ G: 5
+ W: 1:5 2:5 3:5 4:5
+ B: 1:5 2:5 3:5 4:5
+>>> operatorfunc
+ p/gopts1: ''
+ inv: 2! ValueError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1! KeyError
+ inv: 2! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 'A'
+ W: 1:'A' 2:'A' 3:'A' 4:'A'
+ B: 1:'A' 2:'A' 3:'A' 4:'A'
+ del wopts3! KeyError
+ del bopts3! KeyError
+ G: 'A'
+ W: 1:'A' 2:'A' 3:'A' 4:'A'
+ B: 1:'A' 2:'A' 3:'A' 4:'A'
+>>> number
+ p/gopts1! KeyError
+ inv: 0! KeyError
+ gopts1! KeyError
+ p/wopts1: False
+ p/bopts1! KeyError
+ inv: 0! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+ del wopts3! ValueError
+ del bopts3! KeyError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+>>> numberwidth
+ p/gopts1! KeyError
+ inv: -100! KeyError
+ gopts1! KeyError
+ p/wopts1: 8
+ p/bopts1! KeyError
+ inv: -100! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 8
+ W: 1:3 2:5 3:2 4:8
+ B: 1:3 2:5 3:2 4:8
+ del wopts3! ValueError
+ del bopts3! KeyError
+ G: 8
+ W: 1:3 2:5 3:2 4:8
+ B: 1:3 2:5 3:2 4:8
+>>> colorcolumn
+ p/gopts1! KeyError
+ inv: 'abc'! KeyError
+ gopts1! KeyError
+ p/wopts1: ''
+ p/bopts1! KeyError
+ inv: 'abc'! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: ''
+ W: 1:'+2' 2:'+3' 3:'+1' 4:''
+ B: 1:'+2' 2:'+3' 3:'+1' 4:''
+ del wopts3! ValueError
+ del bopts3! KeyError
+ G: ''
+ W: 1:'+2' 2:'+3' 3:'+1' 4:''
+ B: 1:'+2' 2:'+3' 3:'+1' 4:''
+>>> statusline
+ p/gopts1: ''
+ inv: 0! ValueError
+ p/wopts1: None
+ inv: 0! ValueError
+ p/bopts1! KeyError
+ inv: 0! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: '1'
+ W: 1:'2' 2:'4' 3:'1' 4:'1'
+ B: 1:'2' 2:'4' 3:'1' 4:'1'
+ del bopts3! KeyError
+ G: '1'
+ W: 1:'2' 2:'1' 3:'1' 4:'1'
+ B: 1:'2' 2:'1' 3:'1' 4:'1'
+>>> autoindent
+ p/gopts1! KeyError
+ inv: 2! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: False
+ inv: 2! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+>>> iminsert
+ p/gopts1! KeyError
+ inv: 3! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 3! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: 2
+ G: 1
+ W: 1:2 2:1 3:0 4:2
+ B: 1:2 2:1 3:0 4:2
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: 1
+ W: 1:2 2:1 3:0 4:2
+ B: 1:2 2:1 3:0 4:2
+>>> omnifunc
+ p/gopts1! KeyError
+ inv: 1! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 1! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: ''
+ inv: 1! ValueError
+ G: ''
+ W: 1:'B' 2:'C' 3:'A' 4:''
+ B: 1:'B' 2:'C' 3:'A' 4:''
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: ''
+ W: 1:'B' 2:'C' 3:'A' 4:''
+ B: 1:'B' 2:'C' 3:'A' 4:''
+>>> preserveindent
+ p/gopts1! KeyError
+ inv: 2! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: False
+ inv: 2! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+>>> path
+ p/gopts1: '.,/usr/include,,'
+ inv: 0! ValueError
+ p/wopts1! KeyError
+ inv: 0! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: None
+ inv: 0! ValueError
+ G: '.,,'
+ W: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+ B: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+ del wopts3! KeyError
+ G: '.,,'
+ W: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
+ B: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
diff --git a/src/testdir/test87.in b/src/testdir/test87.in
index bdde662f..c2bcb6a3 100644
--- a/src/testdir/test87.in
+++ b/src/testdir/test87.in
@@ -328,6 +328,125 @@ EOF
:put =py3eval('vim.vars[''foo'']')
:put =py3eval('vim.current.window.vars[''abc'']')
:put =py3eval('vim.current.buffer.vars[''baz'']')
+:"
+:" Options
+:" paste: boolean, global
+:" previewheight number, global
+:" operatorfunc: string, global
+:" number: boolean, window-local
+:" numberwidth: number, window-local
+:" colorcolumn: string, window-local
+:" statusline: string, window-local/global
+:" autoindent: boolean, buffer-local
+:" iminsert: number, buffer-local
+:" omnifunc: string, buffer-local
+:" preserveindent: boolean, buffer-local/global
+:" path: string, buffer-local/global
+:let g:bufs=[bufnr('%')]
+:new
+:let g:bufs+=[bufnr('%')]
+:vnew
+:let g:bufs+=[bufnr('%')]
+:wincmd j
+:vnew
+:let g:bufs+=[bufnr('%')]
+:wincmd l
+:fun RecVars(opt)
+: let gval =string(eval('&g:'.a:opt))
+: let wvals=join(map(range(1, 4), 'v:val.":".string(getwinvar(v:val, "&".a:opt))'))
+: let bvals=join(map(copy(g:bufs), 'v:val.":".string(getbufvar(v:val, "&".a:opt))'))
+: put =' G: '.gval
+: put =' W: '.wvals
+: put =' B: '.wvals
+:endfun
+py3 << EOF
+def e(s, g=globals(), l=locals()):
+ try:
+ exec(s, g, l)
+ except Exception as e:
+ vim.command('throw ' + repr(e.__class__.__name__))
+
+def ev(s, g=globals(), l=locals()):
+ try:
+ return eval(s, g, l)
+ except Exception as e:
+ vim.command('throw ' + repr(e.__class__.__name__))
+ return 0
+EOF
+:function E(s)
+: python3 e(vim.eval('a:s'))
+:endfunction
+:function Ev(s)
+: return py3eval('ev(vim.eval("a:s"))')
+:endfunction
+:py3 gopts1=vim.options
+:py3 wopts1=vim.windows[2].options
+:py3 wopts2=vim.windows[0].options
+:py3 wopts3=vim.windows[1].options
+: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
+:let lst=[]
+:let lst+=[['paste', 1, 0, 1, 2, 1, 1, 0 ]]
+:let lst+=[['previewheight', 5, 1, 6, 'a', 0, 1, 0 ]]
+:let lst+=[['operatorfunc', 'A', 'B', 'C', 2, 0, 1, 0 ]]
+:let lst+=[['number', 0, 1, 1, 0, 1, 0, 1 ]]
+:let lst+=[['numberwidth', 2, 3, 5, -100, 0, 0, 1 ]]
+:let lst+=[['colorcolumn', '+1', '+2', '+3', 'abc', 0, 0, 1 ]]
+:let lst+=[['statusline', '1', '2', '4', 0, 0, 1, 1 ]]
+:let lst+=[['autoindent', 0, 1, 1, 2, 1, 0, 2 ]]
+:let lst+=[['iminsert', 0, 2, 1, 3, 0, 0, 2 ]]
+:let lst+=[['omnifunc', 'A', 'B', 'C', 1, 0, 0, 2 ]]
+:let lst+=[['preserveindent', 0, 1, 1, 2, 1, 1, 2 ]]
+:let lst+=[['path', '.,,', ',,', '.', 0, 0, 1, 2 ]]
+:for [oname, oval1, oval2, oval3, invval, bool, global, local] in lst
+: py3 oname=vim.eval('oname')
+: py3 oval1=vim.bindeval('oval1')
+: py3 oval2=vim.bindeval('oval2')
+: py3 oval3=vim.bindeval('oval3')
+: if invval is 0 || invval is 1
+: py3 invval=bool(vim.bindeval('invval'))
+: else
+: py3 invval=vim.bindeval('invval')
+: endif
+: if bool
+: py3 oval1=bool(oval1)
+: py3 oval2=bool(oval2)
+: py3 oval3=bool(oval3)
+: endif
+: put ='>>> '.oname
+: for v in ['gopts1', 'wopts1', 'bopts1']
+: try
+: put =' p/'.v.': '.Ev('repr('.v.'['''.oname.'''])')
+: catch
+: put =' p/'.v.'! '.v:exception
+: endtry
+: try
+: call E(v.'["'.oname.'"]=invval')
+: catch
+: put =' inv: '.string(invval).'! '.v:exception
+: endtry
+: for vv in (v is# 'gopts1' ? [v] : [v, v[:-2].'2', v[:-2].'3'])
+: let val=substitute(vv, '^.opts', 'oval', '')
+: try
+: call E(vv.'["'.oname.'"]='.val)
+: catch
+: put =' '.vv.'! '.v:exception
+: endtry
+: endfor
+: endfor
+: call RecVars(oname)
+: for v in ['wopts3', 'bopts3']
+: try
+: call E('del '.v.'["'.oname.'"]')
+: catch
+: put =' del '.v.'! '.v:exception
+: endtry
+: endfor
+: call RecVars(oname)
+endtry
+:endfor
+:only
:endfun
:"
:call Test()
diff --git a/src/testdir/test87.ok b/src/testdir/test87.ok
index ca74c153..72e7b059 100644
--- a/src/testdir/test87.ok
+++ b/src/testdir/test87.ok
@@ -69,3 +69,229 @@ Abc
bac
def
bar
+>>> paste
+ p/gopts1: False
+ inv: 2! ValueError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1! KeyError
+ inv: 2! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 1
+ W: 1:1 2:1 3:1 4:1
+ B: 1:1 2:1 3:1 4:1
+ del wopts3! KeyError
+ del bopts3! KeyError
+ G: 1
+ W: 1:1 2:1 3:1 4:1
+ B: 1:1 2:1 3:1 4:1
+>>> previewheight
+ p/gopts1: 12
+ inv: 'a'! ValueError
+ p/wopts1! KeyError
+ inv: 'a'! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1! KeyError
+ inv: 'a'! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 5
+ W: 1:5 2:5 3:5 4:5
+ B: 1:5 2:5 3:5 4:5
+ del wopts3! KeyError
+ del bopts3! KeyError
+ G: 5
+ W: 1:5 2:5 3:5 4:5
+ B: 1:5 2:5 3:5 4:5
+>>> operatorfunc
+ p/gopts1: b''
+ inv: 2! ValueError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1! KeyError
+ inv: 2! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 'A'
+ W: 1:'A' 2:'A' 3:'A' 4:'A'
+ B: 1:'A' 2:'A' 3:'A' 4:'A'
+ del wopts3! KeyError
+ del bopts3! KeyError
+ G: 'A'
+ W: 1:'A' 2:'A' 3:'A' 4:'A'
+ B: 1:'A' 2:'A' 3:'A' 4:'A'
+>>> number
+ p/gopts1! KeyError
+ inv: 0! KeyError
+ gopts1! KeyError
+ p/wopts1: False
+ p/bopts1! KeyError
+ inv: 0! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+ del wopts3! ValueError
+ del bopts3! KeyError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+>>> numberwidth
+ p/gopts1! KeyError
+ inv: -100! KeyError
+ gopts1! KeyError
+ p/wopts1: 8
+ p/bopts1! KeyError
+ inv: -100! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: 8
+ W: 1:3 2:5 3:2 4:8
+ B: 1:3 2:5 3:2 4:8
+ del wopts3! ValueError
+ del bopts3! KeyError
+ G: 8
+ W: 1:3 2:5 3:2 4:8
+ B: 1:3 2:5 3:2 4:8
+>>> colorcolumn
+ p/gopts1! KeyError
+ inv: 'abc'! KeyError
+ gopts1! KeyError
+ p/wopts1: b''
+ p/bopts1! KeyError
+ inv: 'abc'! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: ''
+ W: 1:'+2' 2:'+3' 3:'+1' 4:''
+ B: 1:'+2' 2:'+3' 3:'+1' 4:''
+ del wopts3! ValueError
+ del bopts3! KeyError
+ G: ''
+ W: 1:'+2' 2:'+3' 3:'+1' 4:''
+ B: 1:'+2' 2:'+3' 3:'+1' 4:''
+>>> statusline
+ p/gopts1: b''
+ inv: 0! ValueError
+ p/wopts1: None
+ inv: 0! ValueError
+ p/bopts1! KeyError
+ inv: 0! KeyError
+ bopts1! KeyError
+ bopts2! KeyError
+ bopts3! KeyError
+ G: '1'
+ W: 1:'2' 2:'4' 3:'1' 4:'1'
+ B: 1:'2' 2:'4' 3:'1' 4:'1'
+ del bopts3! KeyError
+ G: '1'
+ W: 1:'2' 2:'1' 3:'1' 4:'1'
+ B: 1:'2' 2:'1' 3:'1' 4:'1'
+>>> autoindent
+ p/gopts1! KeyError
+ inv: 2! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: False
+ inv: 2! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+>>> iminsert
+ p/gopts1! KeyError
+ inv: 3! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 3! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: 2
+ G: 1
+ W: 1:2 2:1 3:0 4:2
+ B: 1:2 2:1 3:0 4:2
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: 1
+ W: 1:2 2:1 3:0 4:2
+ B: 1:2 2:1 3:0 4:2
+>>> omnifunc
+ p/gopts1! KeyError
+ inv: 1! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 1! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: b''
+ inv: 1! ValueError
+ G: ''
+ W: 1:'B' 2:'C' 3:'A' 4:''
+ B: 1:'B' 2:'C' 3:'A' 4:''
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: ''
+ W: 1:'B' 2:'C' 3:'A' 4:''
+ B: 1:'B' 2:'C' 3:'A' 4:''
+>>> preserveindent
+ p/gopts1! KeyError
+ inv: 2! KeyError
+ gopts1! KeyError
+ p/wopts1! KeyError
+ inv: 2! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: False
+ inv: 2! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+ del wopts3! KeyError
+ del bopts3! ValueError
+ G: 0
+ W: 1:1 2:1 3:0 4:0
+ B: 1:1 2:1 3:0 4:0
+>>> path
+ p/gopts1: b'.,/usr/include,,'
+ inv: 0! ValueError
+ p/wopts1! KeyError
+ inv: 0! KeyError
+ wopts1! KeyError
+ wopts2! KeyError
+ wopts3! KeyError
+ p/bopts1: None
+ inv: 0! ValueError
+ G: '.,,'
+ W: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+ B: 1:',,' 2:'.' 3:'.,,' 4:'.,,'
+ del wopts3! KeyError
+ G: '.,,'
+ W: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
+ B: 1:',,' 2:'.,,' 3:'.,,' 4:'.,,'
diff --git a/src/version.c b/src/version.c
index 4fb40d0c..fc44086b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 924,
+/**/
923,
/**/
922,
diff --git a/src/vim.h b/src/vim.h
index db2650ec..265720ae 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2230,4 +2230,17 @@ typedef int VimClipboard; /* This is required for the prototypes. */
#define FILEINFO_READ_FAIL 2 /* CreateFile() failed */
#define FILEINFO_INFO_FAIL 3 /* GetFileInformationByHandle() failed */
+/* Return value from get_option_value_strict */
+#define SOPT_BOOL 0x01 /* Boolean option */
+#define SOPT_NUM 0x02 /* Number option */
+#define SOPT_STRING 0x04 /* String option */
+#define SOPT_GLOBAL 0x08 /* Option has global value */
+#define SOPT_WIN 0x10 /* Option has window-local value */
+#define SOPT_BUF 0x20 /* Option has buffer-local value */
+#define SOPT_UNSET 0x40 /* Option does not have local value set */
+
+#define SREQ_GLOBAL 0 /* Request global option */
+#define SREQ_WIN 1 /* Request window-local option */
+#define SREQ_BUF 2 /* Request buffer-local option */
+
#endif /* VIM__H */