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
commit84e0f6ca9adcbdca254060713878ebc29faaaa65 (patch)
tree3025211efa4e5c1d9f48e9f369ecd786713b6c69
parentd1864597a0d87fa9b3fbd09fc022b3405be7f274 (diff)
downloadvim-git-84e0f6ca9adcbdca254060713878ebc29faaaa65.tar.gz
updated for version 7.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 96fd1247d..044d92af9 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 085eff88c..e757f6bc7 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 4362aee29..ff4ba0e54 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 6e1cb0c0f..fb2d8986b 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 659316b41..35fcffac2 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 39b48dea8..c9607632c 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 b23700d70..496fb75c1 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 ba0a4e169..681fa4592 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 fc61848e0..ca4480754 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 3bd2dcf25..2acfb98ae 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 bdde662f3..c2bcb6a33 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 ca74c1532..72e7b059f 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 4fb40d0c0..fc44086b5 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 db2650ecd..265720aeb 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 */