Is a replacement for @Xavier de Gaye patch written in C. Main idea is the same.
# HG changeset patch # User ZyX <[email protected]> # Date 1370102113 -14400 # Branch python-extended-4 # Node ID 807b755f9898d68e4d93f18e7964783b207826b2 # Parent 0ee8bb6bd07f29fd51c7b753492ac727b69ac7ae Add vim.chdir and vim.fchdir functions, record them as attributes of os module diff -r 0ee8bb6bd07f -r 807b755f9898 runtime/doc/if_pyth.txt --- a/runtime/doc/if_pyth.txt Sat Jun 01 17:22:00 2013 +0400 +++ b/runtime/doc/if_pyth.txt Sat Jun 01 19:55:13 2013 +0400 @@ -180,6 +180,13 @@ Like |strwidth()|: returns number of display cells str occupies, tab is counted as one cell. +vim.chdir(*args, **kwargs) *python-chdir* +vim.fchdir(*args, **kwargs) *python-fchdir* + Run os.chdir or os.fchdir, then all appropriate vim stuff. + Note: you should not use these functions directly, use os.chdir and + os.fchdir instead. Behavior of vim.fchdir is undefined in case + os.fchdir does not exist. + Error object of the "vim" module vim.error *python-error* diff -r 0ee8bb6bd07f -r 807b755f9898 src/ex_docmd.c --- a/src/ex_docmd.c Sat Jun 01 17:22:00 2013 +0400 +++ b/src/ex_docmd.c Sat Jun 01 19:55:13 2013 +0400 @@ -8182,6 +8182,33 @@ } #endif + void +post_chdir(local) + int local; +{ + vim_free(curwin->w_localdir); + if (local) + { + /* If still in global directory, need to remember current + * directory as global directory. */ + if (globaldir == NULL && prev_dir != NULL) + globaldir = vim_strsave(prev_dir); + /* Remember this local directory for the window. */ + if (mch_dirname(NameBuff, MAXPATHL) == OK) + curwin->w_localdir = vim_strsave(NameBuff); + } + else + { + /* We are now in the global directory, no need to remember its + * name. */ + vim_free(globaldir); + globaldir = NULL; + curwin->w_localdir = NULL; + } + + shorten_fnames(TRUE); +} + /* * ":cd", ":lcd", ":chdir" and ":lchdir". @@ -8253,27 +8280,7 @@ EMSG(_(e_failed)); else { - vim_free(curwin->w_localdir); - if (eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir) - { - /* If still in global directory, need to remember current - * directory as global directory. */ - if (globaldir == NULL && prev_dir != NULL) - globaldir = vim_strsave(prev_dir); - /* Remember this local directory for the window. */ - if (mch_dirname(NameBuff, MAXPATHL) == OK) - curwin->w_localdir = vim_strsave(NameBuff); - } - else - { - /* We are now in the global directory, no need to remember its - * name. */ - vim_free(globaldir); - globaldir = NULL; - curwin->w_localdir = NULL; - } - - shorten_fnames(TRUE); + post_chdir(eap->cmdidx == CMD_lcd || eap->cmdidx == CMD_lchdir); /* Echo the new current directory if the command was typed. */ if (KeyTyped || p_verbose >= 5) diff -r 0ee8bb6bd07f -r 807b755f9898 src/if_py_both.h --- a/src/if_py_both.h Sat Jun 01 17:22:00 2013 +0400 +++ b/src/if_py_both.h Sat Jun 01 19:55:13 2013 +0400 @@ -52,6 +52,10 @@ static PyObject *globals; +static PyObject *py_chdir; +static PyObject *py_fchdir; +static PyObject *py_getcwd; + /* * obtain a lock on the Vim data structures */ @@ -706,17 +710,84 @@ ); } + static PyObject * +_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs) +{ + PyObject *r; + PyObject *newwd; + PyObject *todecref; + char_u *new_dir; + + if (!(r = PyObject_Call(_chdir, args, kwargs))) + return NULL; + + if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL))) + { + Py_DECREF(r); + return NULL; + } + + if (!(new_dir = StringToChars(newwd, &todecref))) + { + Py_DECREF(r); + Py_DECREF(newwd); + return NULL; + } + + VimTryStart(); + + if (vim_chdir(new_dir)) + { + Py_DECREF(r); + Py_DECREF(newwd); + Py_XDECREF(todecref); + + if (VimTryEnd()) + return NULL; + + PyErr_SetVim(_("failed to change directory")); + return NULL; + } + + Py_DECREF(newwd); + Py_XDECREF(todecref); + + post_chdir(FALSE); + + if (VimTryEnd()) + { + Py_DECREF(r); + return NULL; + } + + return r; +} + + static PyObject * +VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs) +{ + return _VimChdir(py_chdir, args, kwargs); +} + + static PyObject * +VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs) +{ + return _VimChdir(py_fchdir, args, kwargs); +} + /* * Vim module - Definitions */ static struct PyMethodDef VimMethods[] = { - /* name, function, calling, documentation */ - {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" }, - {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" }, - {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"}, - {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"}, - { NULL, NULL, 0, NULL } + /* name, function, calling, documentation */ + {"command", VimCommand, METH_VARARGS, "Execute a Vim ex-mode command" }, + {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" }, + {"bindeval", VimEvalPy, METH_VARARGS, "Like eval(), but returns objects attached to vim ones"}, + {"strwidth", VimStrwidth, METH_VARARGS, "Screen string width, counts <Tab> as having width 1"}, + {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"}, + {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"}, + { NULL, NULL, 0, NULL } }; /* @@ -5262,6 +5333,7 @@ }; typedef int (*object_adder)(PyObject *, const char *, PyObject *); +typedef PyObject *(*attr_getter)(PyObject *, const char *); #define ADD_OBJECT(m, name, obj) \ if (add_object(m, name, obj)) \ @@ -5276,9 +5348,10 @@ } static int -populate_module(PyObject *m, object_adder add_object) +populate_module(PyObject *m, object_adder add_object, attr_getter get_attr) { int i; + PyObject *os; for (i = 0; i < (int)(sizeof(numeric_constants) / sizeof(struct numeric_constant)); @@ -5305,5 +5378,27 @@ ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(&vimvardict)); ADD_CHECKED_OBJECT(m, "options", OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL)); + + if (!(os = PyImport_ImportModule("os"))) + return -1; + ADD_OBJECT(m, "os", os); + + if (!(py_getcwd = PyObject_GetAttrString(os, "getcwd"))) + return -1; + ADD_OBJECT(m, "_getcwd", py_getcwd) + + if (!(py_chdir = PyObject_GetAttrString(os, "chdir"))) + return -1; + ADD_OBJECT(m, "_chdir", py_chdir); + if (PyObject_SetAttrString(os, "chdir", get_attr(m, "chdir"))) + return -1; + + if ((py_fchdir = PyObject_GetAttrString(os, "fchdir"))) + { + ADD_OBJECT(m, "_fchdir", py_fchdir); + if (PyObject_SetAttrString(os, "fchdir", get_attr(m, "fchdir"))) + return -1; + } + return 0; } diff -r 0ee8bb6bd07f -r 807b755f9898 src/if_python.c --- a/src/if_python.c Sat Jun 01 17:22:00 2013 +0400 +++ b/src/if_python.c Sat Jun 01 19:55:13 2013 +0400 @@ -213,6 +213,7 @@ # define PyObject_HasAttrString dll_PyObject_HasAttrString # define PyObject_SetAttrString dll_PyObject_SetAttrString # define PyObject_CallFunctionObjArgs dll_PyObject_CallFunctionObjArgs +# define PyObject_Call dll_PyObject_Call # define PyString_AsString dll_PyString_AsString # define PyString_AsStringAndSize dll_PyString_AsStringAndSize # define PyString_FromString dll_PyString_FromString @@ -346,6 +347,7 @@ static int (*dll_PyObject_HasAttrString)(PyObject *, const char *); static PyObject* (*dll_PyObject_SetAttrString)(PyObject *, const char *, PyObject *); static PyObject* (*dll_PyObject_CallFunctionObjArgs)(PyObject *, ...); +static PyObject* (*dll_PyObject_Call)(PyObject *, PyObject *, PyObject *); static char*(*dll_PyString_AsString)(PyObject *); static int(*dll_PyString_AsStringAndSize)(PyObject *, char **, int *); static PyObject*(*dll_PyString_FromString)(const char *); @@ -510,6 +512,7 @@ {"PyObject_HasAttrString", (PYTHON_PROC*)&dll_PyObject_HasAttrString}, {"PyObject_SetAttrString", (PYTHON_PROC*)&dll_PyObject_SetAttrString}, {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&dll_PyObject_CallFunctionObjArgs}, + {"PyObject_Call", (PYTHON_PROC*)&dll_PyObject_Call}, {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString}, {"PyString_AsStringAndSize", (PYTHON_PROC*)&dll_PyString_AsStringAndSize}, {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString}, @@ -1364,6 +1367,7 @@ { PyObject *mod; PyObject *dict; + PyObject *os; /* The special value is removed from sys.path in Python_Init(). */ static char *(argv[2]) = {"/must>not&exist/foo", NULL}; @@ -1374,10 +1378,11 @@ /* Set sys.argv[] to avoid a crash in warn(). */ PySys_SetArgv(1, argv); - mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, PYTHON_API_VERSION); + mod = Py_InitModule4("vim", VimMethods, (char *)NULL, (PyObject *)NULL, + PYTHON_API_VERSION); dict = PyModule_GetDict(mod); - return populate_module(dict, add_object); + return populate_module(dict, add_object, PyDict_GetItemString); } /************************************************************************* diff -r 0ee8bb6bd07f -r 807b755f9898 src/if_python3.c --- a/src/if_python3.c Sat Jun 01 17:22:00 2013 +0400 +++ b/src/if_python3.c Sat Jun 01 19:55:13 2013 +0400 @@ -174,6 +174,7 @@ # define PyObject_HasAttrString py3_PyObject_HasAttrString # define PyObject_SetAttrString py3_PyObject_SetAttrString # define PyObject_CallFunctionObjArgs py3_PyObject_CallFunctionObjArgs +# define PyObject_Call py3_PyObject_Call # define PyEval_GetLocals py3_PyEval_GetLocals # define PyEval_GetGlobals py3_PyEval_GetGlobals # define PySys_SetObject py3_PySys_SetObject @@ -290,6 +291,7 @@ static int (*py3_PyObject_HasAttrString)(PyObject *, const char *); static PyObject* (*py3_PyObject_SetAttrString)(PyObject *, const char *, PyObject *); static PyObject* (*py3_PyObject_CallFunctionObjArgs)(PyObject *, ...); +static PyObject* (*py3_PyObject_Call)(PyObject *, PyObject *, PyObject *); static PyObject* (*py3_PyEval_GetGlobals)(); static PyObject* (*py3_PyEval_GetLocals)(); static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t); @@ -446,6 +448,7 @@ {"PyObject_HasAttrString", (PYTHON_PROC*)&py3_PyObject_HasAttrString}, {"PyObject_SetAttrString", (PYTHON_PROC*)&py3_PyObject_SetAttrString}, {"PyObject_CallFunctionObjArgs", (PYTHON_PROC*)&py3_PyObject_CallFunctionObjArgs}, + {"PyObject_Call", (PYTHON_PROC*)&py3_PyObject_Call}, {"PyEval_GetGlobals", (PYTHON_PROC*)&py3_PyEval_GetGlobals}, {"PyEval_GetLocals", (PYTHON_PROC*)&py3_PyEval_GetLocals}, {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem}, @@ -1586,6 +1589,7 @@ Py3Init_vim(void) { PyObject *mod; + PyObject *os; /* The special value is removed from sys.path in Python3_Init(). */ static wchar_t *(argv[2]) = {L"/must>not&exist/foo", NULL}; @@ -1600,7 +1604,7 @@ if (mod == NULL) return NULL; - if (populate_module(mod, PyModule_AddObject)) + if (populate_module(mod, PyModule_AddObject, PyObject_GetAttrString)) return NULL; return mod; diff -r 0ee8bb6bd07f -r 807b755f9898 src/proto/ex_docmd.pro --- a/src/proto/ex_docmd.pro Sat Jun 01 17:22:00 2013 +0400 +++ b/src/proto/ex_docmd.pro Sat Jun 01 19:55:13 2013 +0400 @@ -53,4 +53,5 @@ int put_line __ARGS((FILE *fd, char *s)); void dialog_msg __ARGS((char_u *buff, char *format, char_u *fname)); char_u *get_behave_arg __ARGS((expand_T *xp, int idx)); +void post_chdir __ARGS((int local)); /* vim: set ft=c : */ diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test86.in --- a/src/testdir/test86.in Sat Jun 01 17:22:00 2013 +0400 +++ b/src/testdir/test86.in Sat Jun 01 19:55:13 2013 +0400 @@ -788,6 +788,20 @@ :$put =string(pyeval('dl2')) :$put =string(pyeval('df(2)')) :" +:" Test chdir +py << EOF +import os +fnamemodify = vim.Function('fnamemodify') +cb.append(fnamemodify('.', ':p:h:t')) +cb.append(vim.eval('@%')) +os.chdir('..') +cb.append(fnamemodify('.', ':p:h:t')) +cb.append(vim.eval('@%').replace(os.path.sep, '/')) +os.chdir('testdir') +cb.append(fnamemodify('.', ':p:h:t')) +cb.append(vim.eval('@%')) +EOF +:" :" Test errors :fun F() dict :endfun diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test86.ok --- a/src/testdir/test86.ok Sat Jun 01 17:22:00 2013 +0400 +++ b/src/testdir/test86.ok Sat Jun 01 19:55:13 2013 +0400 @@ -429,6 +429,12 @@ ['a', 'b', 'c'] [2, 2] [2, 2] +testdir +test86.in +src +testdir/test86.in +testdir +test86.in > Output >> OutputSetattr del sys.stdout.softspace:(<type 'exceptions.AttributeError'>, AttributeError("can't delete OutputObject attributes",)) diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test87.in --- a/src/testdir/test87.in Sat Jun 01 17:22:00 2013 +0400 +++ b/src/testdir/test87.in Sat Jun 01 19:55:13 2013 +0400 @@ -748,6 +748,20 @@ :$put =string(py3eval('dl2')) :$put =string(py3eval('df(2)')) :" +:" Test chdir +py3 << EOF +import os +fnamemodify = vim.Function('fnamemodify') +cb.append(str(fnamemodify('.', ':p:h:t'))) +cb.append(vim.eval('@%')) +os.chdir('..') +cb.append(str(fnamemodify('.', ':p:h:t'))) +cb.append(vim.eval('@%').replace(os.path.sep, '/')) +os.chdir('testdir') +cb.append(str(fnamemodify('.', ':p:h:t'))) +cb.append(vim.eval('@%')) +EOF +:" :" Test errors :fun F() dict :endfun diff -r 0ee8bb6bd07f -r 807b755f9898 src/testdir/test87.ok --- a/src/testdir/test87.ok Sat Jun 01 17:22:00 2013 +0400 +++ b/src/testdir/test87.ok Sat Jun 01 19:55:13 2013 +0400 @@ -418,6 +418,12 @@ ['a', 'b', 'c'] [2, 2] [2, 2] +b'testdir' +test87.in +b'src' +testdir/test87.in +b'testdir' +test87.in > Output >> OutputSetattr del sys.stdout.softspace:(<class 'AttributeError'>, AttributeError("can't delete OutputObject attributes",)) -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/groups/opt_out.
