summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/if_py_both.h111
-rw-r--r--src/testdir/test86.in56
-rw-r--r--src/testdir/test86.ok8
-rw-r--r--src/testdir/test87.in56
-rw-r--r--src/testdir/test87.ok8
-rw-r--r--src/version.c2
6 files changed, 173 insertions, 68 deletions
diff --git a/src/if_py_both.h b/src/if_py_both.h
index 957d6d5cd..b9ffcbb70 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -272,20 +272,42 @@ static PyObject *VimError;
/* Check to see whether a Vim error has been reported, or a keyboard
* interrupt has been detected.
*/
+
+ static void
+VimTryStart(void)
+{
+ ++trylevel;
+}
+
static int
-VimErrorCheck(void)
+VimTryEnd(void)
{
+ --trylevel;
if (got_int)
{
PyErr_SetNone(PyExc_KeyboardInterrupt);
return 1;
}
- else if (did_emsg && !PyErr_Occurred())
+ else if (!did_throw)
+ return 0;
+ else if (PyErr_Occurred())
+ return 1;
+ else
{
- PyErr_SetNone(VimError);
+ PyErr_SetVim((char *) current_exception->value);
+ discard_current_exception();
return 1;
}
+}
+ static int
+VimCheckInterrupt(void)
+{
+ if (got_int)
+ {
+ PyErr_SetNone(PyExc_KeyboardInterrupt);
+ return 1;
+ }
return 0;
}
@@ -306,17 +328,19 @@ VimCommand(PyObject *self UNUSED, PyObject *args)
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
+ VimTryStart();
do_cmdline_cmd((char_u *)cmd);
update_screen(VALID);
Python_Release_Vim();
Py_END_ALLOW_THREADS
- if (VimErrorCheck())
+ if (VimTryEnd())
result = NULL;
else
result = Py_None;
+
Py_XINCREF(result);
return result;
}
@@ -449,11 +473,14 @@ VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
+ VimTryStart();
our_tv = eval_expr((char_u *)expr, NULL);
-
Python_Release_Vim();
Py_END_ALLOW_THREADS
+ if (VimTryEnd())
+ return NULL;
+
if (our_tv == NULL)
{
PyErr_SetVim(_("invalid expression"));
@@ -490,11 +517,14 @@ VimEvalPy(PyObject *self UNUSED, PyObject *args)
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
+ VimTryStart();
our_tv = eval_expr((char_u *)expr, NULL);
-
Python_Release_Vim();
Py_END_ALLOW_THREADS
+ if (VimTryEnd())
+ return NULL;
+
if (our_tv == NULL)
{
PyErr_SetVim(_("invalid expression"));
@@ -1324,12 +1354,15 @@ FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
+ VimTryStart();
error = func_call(name, &args, selfdict, &rettv);
Python_Release_Vim();
Py_END_ALLOW_THREADS
- if (error != OK)
+ if (VimTryEnd())
+ result = NULL;
+ else if (error != OK)
{
result = NULL;
PyErr_SetVim(_("failed to run function"));
@@ -1486,14 +1519,16 @@ set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
win_T *save_curwin;
tabpage_T *save_curtab;
buf_T *save_curbuf;
- int r = 0;
+ VimTryStart();
switch (opt_type)
{
case SREQ_WIN:
if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
win_find_tabpage((win_T *)from)) == FAIL)
{
+ if (VimTryEnd())
+ return -1;
PyErr_SetVim("Problem while switching windows.");
return -1;
}
@@ -1509,7 +1544,7 @@ set_option_value_for(key, numval, stringval, opt_flags, opt_type, from)
set_option_value(key, numval, stringval, opt_flags);
break;
}
- return r;
+ return VimTryEnd();
}
static int
@@ -1961,7 +1996,7 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
}
/* Check for keyboard interrupts */
- if (VimErrorCheck())
+ if (VimCheckInterrupt())
return -1;
self->win->w_cursor.lnum = lnum;
@@ -1988,11 +2023,11 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
#endif
savewin = curwin;
curwin = self->win;
+
+ VimTryStart();
win_setheight(height);
curwin = savewin;
-
- /* Check for keyboard interrupts */
- if (VimErrorCheck())
+ if (VimTryEnd())
return -1;
return 0;
@@ -2011,11 +2046,11 @@ WindowSetattr(WindowObject *self, char *name, PyObject *val)
#endif
savewin = curwin;
curwin = self->win;
+
+ VimTryStart();
win_setwidth(width);
curwin = savewin;
-
- /* Check for keyboard interrupts */
- if (VimErrorCheck())
+ if (VimTryEnd())
return -1;
return 0;
@@ -2304,6 +2339,8 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
PyErr_Clear();
switch_buffer(&savebuf, buf);
+ VimTryStart();
+
if (u_savedel((linenr_T)n, 1L) == FAIL)
PyErr_SetVim(_("cannot save undo information"));
else if (ml_delete((linenr_T)n, FALSE) == FAIL)
@@ -2317,7 +2354,7 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
restore_buffer(savebuf);
- if (PyErr_Occurred() || VimErrorCheck())
+ if (VimTryEnd())
return FAIL;
if (len_change)
@@ -2333,6 +2370,8 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
if (save == NULL)
return FAIL;
+ VimTryStart();
+
/* We do not need to free "save" if ml_replace() consumes it. */
PyErr_Clear();
switch_buffer(&savebuf, buf);
@@ -2356,7 +2395,7 @@ SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
if (buf == savebuf)
check_cursor_col();
- if (PyErr_Occurred() || VimErrorCheck())
+ if (VimTryEnd())
return FAIL;
if (len_change)
@@ -2395,6 +2434,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
buf_T *savebuf;
PyErr_Clear();
+ VimTryStart();
switch_buffer(&savebuf, buf);
if (u_savedel((linenr_T)lo, (long)n) == FAIL)
@@ -2416,7 +2456,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
restore_buffer(savebuf);
- if (PyErr_Occurred() || VimErrorCheck())
+ if (VimTryEnd())
return FAIL;
if (len_change)
@@ -2459,6 +2499,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
}
}
+ VimTryStart();
PyErr_Clear();
// START of region without "return". Must call restore_buffer()!
@@ -2545,7 +2586,7 @@ SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_cha
// END of region without "return".
restore_buffer(savebuf);
- if (PyErr_Occurred() || VimErrorCheck())
+ if (VimTryEnd())
return FAIL;
if (len_change)
@@ -2583,6 +2624,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
return FAIL;
PyErr_Clear();
+ VimTryStart();
switch_buffer(&savebuf, buf);
if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
@@ -2596,7 +2638,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
restore_buffer(savebuf);
update_screen(VALID);
- if (PyErr_Occurred() || VimErrorCheck())
+ if (VimTryEnd())
return FAIL;
if (len_change)
@@ -2633,6 +2675,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
}
PyErr_Clear();
+ VimTryStart();
switch_buffer(&savebuf, buf);
if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
@@ -2666,7 +2709,7 @@ InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
restore_buffer(savebuf);
update_screen(VALID);
- if (PyErr_Occurred() || VimErrorCheck())
+ if (VimTryEnd())
return FAIL;
if (len_change)
@@ -2896,7 +2939,7 @@ RangeNew(buf_T *buf, PyInt start, PyInt end)
static void
RangeDestructor(RangeObject *self)
{
- Py_DECREF(self->buf);
+ Py_XDECREF(self->buf);
DESTRUCTOR_FINISH(self);
}
@@ -3078,9 +3121,12 @@ BufferMark(BufferObject *self, PyObject *args)
return NULL;
mark = *pmark;
+ VimTryStart();
switch_buffer(&savebuf, self->buf);
posp = getmark(mark, FALSE);
restore_buffer(savebuf);
+ if (VimTryEnd())
+ return NULL;
if (posp == NULL)
{
@@ -3088,10 +3134,6 @@ BufferMark(BufferObject *self, PyObject *args)
return NULL;
}
- /* Check for keyboard interrupt */
- if (VimErrorCheck())
- return NULL;
-
if (posp->lnum <= 0)
{
/* Or raise an error? */
@@ -3330,13 +3372,16 @@ CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
return -1;
count = ((BufferObject *)(value))->buf->b_fnum;
+ VimTryStart();
if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
{
+ if (VimTryEnd())
+ return -1;
PyErr_SetVim(_("failed to switch to given buffer"));
return -1;
}
- return 0;
+ return VimTryEnd();
}
else if (strcmp(name, "window") == 0)
{
@@ -3359,15 +3404,18 @@ CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
return -1;
}
+ VimTryStart();
win_goto(((WindowObject *)(value))->win);
if (((WindowObject *)(value))->win != curwin)
{
+ if (VimTryEnd())
+ return -1;
PyErr_SetString(PyExc_RuntimeError,
_("did not switch to the specified window"));
return -1;
}
- return 0;
+ return VimTryEnd();
}
else if (strcmp(name, "tabpage") == 0)
{
@@ -3380,15 +3428,18 @@ CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *value)
if (CheckTabPage((TabPageObject *)(value)))
return -1;
+ VimTryStart();
goto_tabpage_tp(((TabPageObject *)(value))->tab, TRUE, TRUE);
if (((TabPageObject *)(value))->tab != curtab)
{
+ if (VimTryEnd())
+ return -1;
PyErr_SetString(PyExc_RuntimeError,
_("did not switch to the specified tab page"));
return -1;
}
- return 0;
+ return VimTryEnd();
}
else
{
diff --git a/src/testdir/test86.in b/src/testdir/test86.in
index c49eb3bad..fac315e2d 100644
--- a/src/testdir/test86.in
+++ b/src/testdir/test86.in
@@ -380,20 +380,24 @@ def e(s, g=globals(), l=locals()):
try:
exec(s, g, l)
except:
- vim.command('throw ' + repr(sys.exc_type.__name__))
+ vim.command('return ' + repr(sys.exc_type.__name__))
def ev(s, g=globals(), l=locals()):
try:
return eval(s, g, l)
except:
- vim.command('throw ' + repr(sys.exc_type.__name__))
+ vim.command('let exc=' + repr(sys.exc_type.__name__))
return 0
EOF
:function E(s)
: python e(vim.eval('a:s'))
:endfunction
:function Ev(s)
-: return pyeval('ev(vim.eval("a:s"))')
+: let r=pyeval('ev(vim.eval("a:s"))')
+: if exists('exc')
+: throw exc
+: endif
+: return r
:endfunction
:py gopts1=vim.options
:py wopts1=vim.windows[2].options
@@ -437,27 +441,24 @@ EOF
: catch
: put =' p/'.v.'! '.v:exception
: endtry
-: try
-: call E(v.'["'.oname.'"]=invval')
-: catch
-: put =' inv: '.string(invval).'! '.v:exception
-: endtry
+: let r=E(v.'['''.oname.''']=invval')
+: if r isnot 0
+: put =' inv: '.string(invval).'! '.r
+: endif
: 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
+: let r=E(vv.'['''.oname.''']='.val)
+: if r isnot 0
+: put =' '.vv.'! '.r
+: endif
: endfor
: endfor
: call RecVars(oname)
: for v in ['wopts3', 'bopts3']
-: try
-: call E('del '.v.'["'.oname.'"]')
-: catch
-: put =' del '.v.'! '.v:exception
-: endtry
+: let r=E('del '.v.'["'.oname.'"]')
+: if r isnot 0
+: put =' del '.v.'! '.r
+: endif
: endfor
: call RecVars(oname)
:endfor
@@ -651,6 +652,25 @@ for expr, attr in (
):
cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
EOF
+:"
+:" Test exceptions
+:fun Exe(e)
+: execute a:e
+:endfun
+py << EOF
+def ee(expr, g=globals(), l=locals()):
+ try:
+ exec(expr, g, l)
+ except:
+ cb.append(repr(sys.exc_info()[:2]))
+Exe = vim.bindeval('function("Exe")')
+ee('vim.command("throw \'abc\'")')
+ee('Exe("throw \'def\'")')
+ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
+ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
+ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
+EOF
:endfun
:"
:call Test()
diff --git a/src/testdir/test86.ok b/src/testdir/test86.ok
index c91f741a0..5602b2f10 100644
--- a/src/testdir/test86.ok
+++ b/src/testdir/test86.ok
@@ -333,7 +333,7 @@ Number of tabs: 4
Current tab pages:
<tabpage 0>(1): 1 windows, current is <window object (unknown)>
Windows:
- <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor is at (970, 0)
+ <window object (unknown)>(1): displays buffer <buffer test86.in>; cursor is at (990, 0)
<tabpage 1>(2): 1 windows, current is <window object (unknown)>
Windows:
<window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
@@ -368,3 +368,9 @@ vim.current.buffer:Buffer:True
vim.current.range:Range:True
vim.current.window:Window:True
vim.current.tabpage:TabPage:True
+(<class 'vim.error'>, error('abc',))
+(<class 'vim.error'>, error('def',))
+(<class 'vim.error'>, error('ghi',))
+(<class 'vim.error'>, error('Vim(echoerr):jkl',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
diff --git a/src/testdir/test87.in b/src/testdir/test87.in
index 94c1ab535..69af02eec 100644
--- a/src/testdir/test87.in
+++ b/src/testdir/test87.in
@@ -367,20 +367,24 @@ def e(s, g=globals(), l=locals()):
try:
exec(s, g, l)
except Exception as e:
- vim.command('throw ' + repr(e.__class__.__name__))
+ vim.command('return ' + 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__))
+ vim.command('let exc=' + 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"))')
+: let r=py3eval('ev(vim.eval("a:s"))')
+: if exists('exc')
+: throw exc
+: endif
+: return r
:endfunction
:py3 gopts1=vim.options
:py3 wopts1=vim.windows[2].options
@@ -424,27 +428,24 @@ EOF
: catch
: put =' p/'.v.'! '.v:exception
: endtry
-: try
-: call E(v.'["'.oname.'"]=invval')
-: catch
-: put =' inv: '.string(invval).'! '.v:exception
-: endtry
+: let r=E(v.'['''.oname.''']=invval')
+: if r isnot 0
+: put =' inv: '.string(invval).'! '.r
+: endif
: 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
+: let r=E(vv.'['''.oname.''']='.val)
+: if r isnot 0
+: put =' '.vv.'! '.r
+: endif
: endfor
: endfor
: call RecVars(oname)
: for v in ['wopts3', 'bopts3']
-: try
-: call E('del '.v.'["'.oname.'"]')
-: catch
-: put =' del '.v.'! '.v:exception
-: endtry
+: let r=E('del '.v.'["'.oname.'"]')
+: if r isnot 0
+: put =' del '.v.'! '.r
+: endif
: endfor
: call RecVars(oname)
:endfor
@@ -638,6 +639,25 @@ for expr, attr in (
):
cb.append(expr + ':' + attr + ':' + repr(type(eval(expr)) is getattr(vim, attr)))
EOF
+:"
+:" Test exceptions
+:fun Exe(e)
+: execute a:e
+:endfun
+py3 << EOF
+def ee(expr, g=globals(), l=locals()):
+ try:
+ exec(expr, g, l)
+ except Exception as e:
+ cb.append(repr((e.__class__, e)))
+Exe = vim.bindeval('function("Exe")')
+ee('vim.command("throw \'abc\'")')
+ee('Exe("throw \'def\'")')
+ee('vim.eval("Exe(\'throw \'\'ghi\'\'\')")')
+ee('vim.eval("Exe(\'echoerr \'\'jkl\'\'\')")')
+ee('vim.eval("Exe(\'xxx_non_existent_command_xxx\')")')
+ee('vim.bindeval("Exe(\'xxx_non_existent_command_xxx\')")')
+EOF
:endfun
:"
:call Test()
diff --git a/src/testdir/test87.ok b/src/testdir/test87.ok
index 08cd590e2..64ef57d5c 100644
--- a/src/testdir/test87.ok
+++ b/src/testdir/test87.ok
@@ -322,7 +322,7 @@ Number of tabs: 4
Current tab pages:
<tabpage 0>(1): 1 windows, current is <window object (unknown)>
Windows:
- <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor is at (946, 0)
+ <window object (unknown)>(1): displays buffer <buffer test87.in>; cursor is at (966, 0)
<tabpage 1>(2): 1 windows, current is <window object (unknown)>
Windows:
<window object (unknown)>(1): displays buffer <buffer 0>; cursor is at (1, 0)
@@ -357,3 +357,9 @@ vim.current.buffer:Buffer:True
vim.current.range:Range:True
vim.current.window:Window:True
vim.current.tabpage:TabPage:True
+(<class 'vim.error'>, error('abc',))
+(<class 'vim.error'>, error('def',))
+(<class 'vim.error'>, error('ghi',))
+(<class 'vim.error'>, error('Vim(echoerr):jkl',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
+(<class 'vim.error'>, error('Vim:E492: Not an editor command: xxx_non_existent_command_xxx',))
diff --git a/src/version.c b/src/version.c
index 817112427..411687e67 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 */
/**/
+ 997,
+/**/
996,
/**/
995,