blob: bdac3fc3e467fc21460e2191ccbea58b088edbcd [file] [log] [blame]
Bram Moolenaardb913952012-06-29 12:54:53 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar170bf1a2010-07-24 23:51:45 +02002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020010 * Python extensions by Paul Moore, David Leonard, Roland Puntaier, Nikolay
11 * Pavlov.
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020012 *
13 * Common code for if_python.c and if_python3.c.
14 */
15
Bram Moolenaar41009372013-07-01 22:03:04 +020016static char_u e_py_systemexit[] = "E880: Can't handle SystemExit of %s exception in vim";
17
Bram Moolenaarc1a995d2012-08-08 16:05:07 +020018#if PY_VERSION_HEX < 0x02050000
Bram Moolenaar9bf703d2019-11-30 19:44:38 +010019typedef int Py_ssize_t; // Python 2.4 and earlier don't have this type.
Bram Moolenaarc1a995d2012-08-08 16:05:07 +020020#endif
21
Bram Moolenaar556684f2019-12-31 21:59:01 +010022#define ENC_OPT (enc_utf8 ? "utf-8" : (char *)p_enc)
Bram Moolenaard620aa92013-05-17 16:40:06 +020023#define DOPY_FUNC "_vim_pydo"
Bram Moolenaar91805fc2011-06-26 04:01:44 +020024
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020025static const char *vim_special_path = "_vim_path_";
26
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020027#define PyErr_SET_STRING(exc, str) PyErr_SetString(exc, _(str))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020028#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020029#define PyErr_SET_VIM(str) PyErr_SET_STRING(VimError, str)
Bram Moolenaar063a46b2014-01-14 16:36:51 +010030#define PyErr_FORMAT(exc, str, arg) PyErr_Format(exc, _(str), arg)
31#define PyErr_FORMAT2(exc, str, arg1, arg2) PyErr_Format(exc, _(str), arg1,arg2)
32#define PyErr_VIM_FORMAT(str, arg) PyErr_FORMAT(VimError, str, arg)
Bram Moolenaarc476e522013-06-23 13:46:40 +020033
34#define Py_TYPE_NAME(obj) (obj->ob_type->tp_name == NULL \
35 ? "(NULL)" \
36 : obj->ob_type->tp_name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020037
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +020038#define RAISE_NO_EMPTY_KEYS PyErr_SET_STRING(PyExc_ValueError, \
Bram Moolenaar6f1404f2013-06-23 16:04:08 +020039 N_("empty keys are not allowed"))
40#define RAISE_LOCKED_DICTIONARY PyErr_SET_VIM(N_("dictionary is locked"))
41#define RAISE_LOCKED_LIST PyErr_SET_VIM(N_("list is locked"))
42#define RAISE_UNDO_FAIL PyErr_SET_VIM(N_("cannot save undo information"))
43#define RAISE_DELETE_LINE_FAIL PyErr_SET_VIM(N_("cannot delete line"))
44#define RAISE_INSERT_LINE_FAIL PyErr_SET_VIM(N_("cannot insert line"))
45#define RAISE_REPLACE_LINE_FAIL PyErr_SET_VIM(N_("cannot replace line"))
Bram Moolenaarc476e522013-06-23 13:46:40 +020046#define RAISE_KEY_ADD_FAIL(key) \
Bram Moolenaar6f1404f2013-06-23 16:04:08 +020047 PyErr_VIM_FORMAT(N_("failed to add key '%s' to dictionary"), key)
Bram Moolenaarc476e522013-06-23 13:46:40 +020048#define RAISE_INVALID_INDEX_TYPE(idx) \
Bram Moolenaar6f1404f2013-06-23 16:04:08 +020049 PyErr_FORMAT(PyExc_TypeError, N_("index must be int or slice, not %s"), \
Bram Moolenaarc476e522013-06-23 13:46:40 +020050 Py_TYPE_NAME(idx));
Bram Moolenaar35eacd72013-05-30 22:06:33 +020051
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020052#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
53#define INVALID_WINDOW_VALUE ((win_T *)(-1))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +020054#define INVALID_TABPAGE_VALUE ((tabpage_T *)(-1))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020055
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020056typedef void (*rangeinitializer)(void *);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +020057typedef void (*runner)(const char *, void *
58#ifdef PY_CAN_RECURSE
59 , PyGILState_STATE *
60#endif
61 );
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020062
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020063static int ConvertFromPyObject(PyObject *, typval_T *);
64static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
Bram Moolenaara9922d62013-05-30 13:01:18 +020065static int ConvertFromPyMapping(PyObject *, typval_T *);
Bram Moolenaar8110a092016-04-14 15:56:09 +020066static int ConvertFromPySequence(PyObject *, typval_T *);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +020067static PyObject *WindowNew(win_T *, tabpage_T *);
68static PyObject *BufferNew (buf_T *);
69static PyObject *LineToString(const char *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +020070
71static PyInt RangeStart;
72static PyInt RangeEnd;
73
Bram Moolenaarb52f4c02013-05-21 18:19:38 +020074static PyObject *globals;
75
Bram Moolenaarf4258302013-06-02 18:20:17 +020076static PyObject *py_chdir;
77static PyObject *py_fchdir;
78static PyObject *py_getcwd;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +020079static PyObject *vim_module;
80static PyObject *vim_special_path_object;
Bram Moolenaarf4258302013-06-02 18:20:17 +020081
Bram Moolenaar79a494d2018-07-22 04:30:21 +020082#if PY_VERSION_HEX >= 0x030700f0
83static PyObject *py_find_spec;
84#else
Bram Moolenaar81c40c52013-06-12 14:41:04 +020085static PyObject *py_load_module;
Bram Moolenaar79a494d2018-07-22 04:30:21 +020086#endif
Bram Moolenaarb999ba22019-02-14 13:28:45 +010087static PyObject *py_find_module;
Bram Moolenaar81c40c52013-06-12 14:41:04 +020088
89static PyObject *VimError;
90
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020091/*
92 * obtain a lock on the Vim data structures
93 */
94 static void
95Python_Lock_Vim(void)
96{
97}
98
99/*
100 * release a lock on the Vim data structures
101 */
102 static void
103Python_Release_Vim(void)
104{
105}
106
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200107/*
108 * The "todecref" argument holds a pointer to PyObject * that must be
109 * DECREF'ed after returned char_u * is no longer needed or NULL if all what
110 * was needed to generate returned value is object.
111 *
112 * Use Py_XDECREF to decrement reference count.
113 */
114 static char_u *
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200115StringToChars(PyObject *obj, PyObject **todecref)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200116{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200117 char_u *str;
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200118
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200119 if (PyBytes_Check(obj))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200120 {
121
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200122 if (PyBytes_AsStringAndSize(obj, (char **) &str, NULL) == -1
123 || str == NULL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200124 return NULL;
125
126 *todecref = NULL;
127 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200128 else if (PyUnicode_Check(obj))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200129 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200130 PyObject *bytes;
131
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200132 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL)))
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200133 return NULL;
134
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200135 if(PyBytes_AsStringAndSize(bytes, (char **) &str, NULL) == -1
136 || str == NULL)
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200137 {
138 Py_DECREF(bytes);
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200139 return NULL;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200140 }
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200141
142 *todecref = bytes;
143 }
144 else
145 {
Bram Moolenaarc476e522013-06-23 13:46:40 +0200146#if PY_MAJOR_VERSION < 3
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200147 PyErr_FORMAT(PyExc_TypeError,
148 N_("expected str() or unicode() instance, but got %s"),
149 Py_TYPE_NAME(obj));
Bram Moolenaarc476e522013-06-23 13:46:40 +0200150#else
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200151 PyErr_FORMAT(PyExc_TypeError,
152 N_("expected bytes() or str() instance, but got %s"),
153 Py_TYPE_NAME(obj));
Bram Moolenaarc476e522013-06-23 13:46:40 +0200154#endif
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200155 return NULL;
156 }
157
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200158 return (char_u *) str;
Bram Moolenaare9ba5162013-05-29 22:02:22 +0200159}
160
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200161#define NUMBER_LONG 1
162#define NUMBER_INT 2
163#define NUMBER_NATURAL 4
164#define NUMBER_UNSIGNED 8
165
166 static int
167NumberToLong(PyObject *obj, long *result, int flags)
168{
169#if PY_MAJOR_VERSION < 3
170 if (PyInt_Check(obj))
171 {
172 *result = PyInt_AsLong(obj);
173 if (PyErr_Occurred())
174 return -1;
175 }
176 else
177#endif
178 if (PyLong_Check(obj))
179 {
180 *result = PyLong_AsLong(obj);
181 if (PyErr_Occurred())
182 return -1;
183 }
184 else if (PyNumber_Check(obj))
185 {
186 PyObject *num;
187
188 if (!(num = PyNumber_Long(obj)))
189 return -1;
190
191 *result = PyLong_AsLong(num);
192
193 Py_DECREF(num);
194
195 if (PyErr_Occurred())
196 return -1;
197 }
198 else
199 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200200#if PY_MAJOR_VERSION < 3
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200201 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200202 N_("expected int(), long() or something supporting "
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200203 "coercing to long(), but got %s"),
204 Py_TYPE_NAME(obj));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200205#else
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200206 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200207 N_("expected int() or something supporting coercing to int(), "
Bram Moolenaarc1c3d682013-06-24 21:21:58 +0200208 "but got %s"),
209 Py_TYPE_NAME(obj));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200210#endif
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200211 return -1;
212 }
213
214 if (flags & NUMBER_INT)
215 {
216 if (*result > INT_MAX)
217 {
218 PyErr_SET_STRING(PyExc_OverflowError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200219 N_("value is too large to fit into C int type"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200220 return -1;
221 }
222 else if (*result < INT_MIN)
223 {
224 PyErr_SET_STRING(PyExc_OverflowError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200225 N_("value is too small to fit into C int type"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200226 return -1;
227 }
228 }
229
230 if (flags & NUMBER_NATURAL)
231 {
232 if (*result <= 0)
233 {
234 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar4de6a212014-03-08 16:13:44 +0100235 N_("number must be greater than zero"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200236 return -1;
237 }
238 }
239 else if (flags & NUMBER_UNSIGNED)
240 {
241 if (*result < 0)
242 {
243 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200244 N_("number must be greater or equal to zero"));
Bram Moolenaar141be8a2013-06-23 14:16:57 +0200245 return -1;
246 }
247 }
248
249 return 0;
250}
251
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200252 static int
253add_string(PyObject *list, char *s)
254{
255 PyObject *string;
256
257 if (!(string = PyString_FromString(s)))
258 return -1;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +0200259
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200260 if (PyList_Append(list, string))
261 {
262 Py_DECREF(string);
263 return -1;
264 }
265
266 Py_DECREF(string);
267 return 0;
268}
269
270 static PyObject *
271ObjectDir(PyObject *self, char **attributes)
272{
273 PyMethodDef *method;
274 char **attr;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200275 PyObject *ret;
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200276
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200277 if (!(ret = PyList_New(0)))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200278 return NULL;
279
280 if (self)
281 for (method = self->ob_type->tp_methods ; method->ml_name != NULL ; ++method)
Bram Moolenaar41009372013-07-01 22:03:04 +0200282 if (add_string(ret, (char *)method->ml_name))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200283 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200284 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200285 return NULL;
286 }
287
288 for (attr = attributes ; *attr ; ++attr)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200289 if (add_string(ret, *attr))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200290 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200291 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200292 return NULL;
293 }
294
295#if PY_MAJOR_VERSION < 3
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200296 if (add_string(ret, "__members__"))
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200297 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200298 Py_DECREF(ret);
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200299 return NULL;
300 }
301#endif
302
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200303 return ret;
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200304}
305
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100306// Output buffer management
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200307
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100308// Function to write a line, points to either msg() or emsg().
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200309typedef void (*writefn)(char_u *);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200310
311static PyTypeObject OutputType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200312
313typedef struct
314{
315 PyObject_HEAD
316 long softspace;
317 long error;
318} OutputObject;
319
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200320static char *OutputAttrs[] = {
321 "softspace",
322 NULL
323};
324
325 static PyObject *
326OutputDir(PyObject *self)
327{
328 return ObjectDir(self, OutputAttrs);
329}
330
Bram Moolenaar77045652012-09-21 13:46:06 +0200331 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200332OutputSetattr(OutputObject *self, char *name, PyObject *valObject)
Bram Moolenaar77045652012-09-21 13:46:06 +0200333{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200334 if (valObject == NULL)
Bram Moolenaar77045652012-09-21 13:46:06 +0200335 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +0200336 PyErr_SET_STRING(PyExc_AttributeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200337 N_("can't delete OutputObject attributes"));
Bram Moolenaar77045652012-09-21 13:46:06 +0200338 return -1;
339 }
340
341 if (strcmp(name, "softspace") == 0)
342 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200343 if (NumberToLong(valObject, &(self->softspace), NUMBER_UNSIGNED))
Bram Moolenaar77045652012-09-21 13:46:06 +0200344 return -1;
Bram Moolenaar77045652012-09-21 13:46:06 +0200345 return 0;
346 }
347
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200348 PyErr_FORMAT(PyExc_AttributeError, N_("invalid attribute: %s"), name);
Bram Moolenaar77045652012-09-21 13:46:06 +0200349 return -1;
350}
351
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100352// Buffer IO, we write one whole line at a time.
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200353static garray_T io_ga = {0, 0, 1, 80, NULL};
354static writefn old_fn = NULL;
355
356 static void
357PythonIO_Flush(void)
358{
359 if (old_fn != NULL && io_ga.ga_len > 0)
360 {
361 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
362 old_fn((char_u *)io_ga.ga_data);
363 }
364 io_ga.ga_len = 0;
365}
366
367 static void
368writer(writefn fn, char_u *str, PyInt n)
369{
370 char_u *ptr;
371
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100372 // Flush when switching output function.
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200373 if (fn != old_fn)
374 PythonIO_Flush();
375 old_fn = fn;
376
Bram Moolenaarb98678a2019-10-19 15:18:44 +0200377 // Write each NL separated line. Text after the last NL is kept for
378 // writing later.
379 // For normal messages: Do not output when "got_int" was set. This avoids
380 // a loop gone crazy flooding the terminal with messages. Also for when
381 // "q" is pressed at the more-prompt.
382 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL
383 && (fn == (writefn)emsg || !got_int))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200384 {
385 PyInt len = ptr - str;
386
387 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
388 break;
389
390 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
391 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
392 fn((char_u *)io_ga.ga_data);
393 str = ptr + 1;
394 n -= len + 1;
395 io_ga.ga_len = 0;
396 }
397
Bram Moolenaarb98678a2019-10-19 15:18:44 +0200398 // Put the remaining text into io_ga for later printing.
399 if (n > 0 && (fn == (writefn)emsg || !got_int)
400 && ga_grow(&io_ga, (int)(n + 1)) == OK)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200401 {
402 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
403 io_ga.ga_len += (int)n;
404 }
405}
406
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200407 static int
408write_output(OutputObject *self, PyObject *string)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200409{
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200410 Py_ssize_t len = 0;
411 char *str = NULL;
412 int error = self->error;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200413
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200414 if (!PyArg_Parse(string, "et#", ENC_OPT, &str, &len))
415 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200416
417 Py_BEGIN_ALLOW_THREADS
418 Python_Lock_Vim();
Bram Moolenaar7f3a2842019-05-18 15:02:25 +0200419 if (error)
420 emsg_severe = TRUE;
Bram Moolenaar32526b32019-01-19 17:43:09 +0100421 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200422 Python_Release_Vim();
423 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200424 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200425
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200426 return 0;
427}
428
429 static PyObject *
430OutputWrite(OutputObject *self, PyObject *string)
431{
432 if (write_output(self, string))
433 return NULL;
434
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200435 Py_INCREF(Py_None);
436 return Py_None;
437}
438
439 static PyObject *
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200440OutputWritelines(OutputObject *self, PyObject *seq)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200441{
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200442 PyObject *iterator;
443 PyObject *item;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200444
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200445 if (!(iterator = PyObject_GetIter(seq)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200446 return NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200447
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200448 while ((item = PyIter_Next(iterator)))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200449 {
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200450 if (write_output(self, item))
Bram Moolenaardb913952012-06-29 12:54:53 +0200451 {
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200452 Py_DECREF(iterator);
453 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200454 return NULL;
455 }
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200456 Py_DECREF(item);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200457 }
458
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200459 Py_DECREF(iterator);
460
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100461 // Iterator may have finished due to an exception
Bram Moolenaar01a7a722013-05-30 12:26:58 +0200462 if (PyErr_Occurred())
463 return NULL;
464
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200465 Py_INCREF(Py_None);
466 return Py_None;
467}
468
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100469 static PyObject *
Bram Moolenaard4247472015-11-02 13:28:59 +0100470AlwaysNone(PyObject *self UNUSED)
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100471{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100472 // do nothing
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100473 Py_INCREF(Py_None);
474 return Py_None;
475}
476
Bram Moolenaard4247472015-11-02 13:28:59 +0100477 static PyObject *
478AlwaysFalse(PyObject *self UNUSED)
479{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100480 // do nothing
Bram Moolenaare7427f42015-11-10 13:24:20 +0100481 PyObject *ret = Py_False;
482 Py_INCREF(ret);
483 return ret;
Bram Moolenaard4247472015-11-02 13:28:59 +0100484}
485
486 static PyObject *
487AlwaysTrue(PyObject *self UNUSED)
488{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100489 // do nothing
Bram Moolenaare7427f42015-11-10 13:24:20 +0100490 PyObject *ret = Py_True;
491 Py_INCREF(ret);
492 return ret;
Bram Moolenaard4247472015-11-02 13:28:59 +0100493}
494
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200495/***************/
496
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200497static struct PyMethodDef OutputMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100498 // name, function, calling, doc
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +0200499 {"write", (PyCFunction)OutputWrite, METH_O, ""},
500 {"writelines", (PyCFunction)OutputWritelines, METH_O, ""},
Bram Moolenaard4247472015-11-02 13:28:59 +0100501 {"flush", (PyCFunction)AlwaysNone, METH_NOARGS, ""},
502 {"close", (PyCFunction)AlwaysNone, METH_NOARGS, ""},
503 {"isatty", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
504 {"readable", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
505 {"seekable", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
506 {"writable", (PyCFunction)AlwaysTrue, METH_NOARGS, ""},
Bram Moolenaar6d4431e2016-04-21 20:00:56 +0200507 {"closed", (PyCFunction)AlwaysFalse, METH_NOARGS, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +0200508 {"__dir__", (PyCFunction)OutputDir, METH_NOARGS, ""},
Bram Moolenaar182dc4f2013-05-21 19:01:55 +0200509 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200510};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200511
512static OutputObject Output =
513{
514 PyObject_HEAD_INIT(&OutputType)
515 0,
516 0
517};
518
519static OutputObject Error =
520{
521 PyObject_HEAD_INIT(&OutputType)
522 0,
523 1
524};
525
526 static int
527PythonIO_Init_io(void)
528{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +0200529 if (PySys_SetObject("stdout", (PyObject *)(void *)&Output))
530 return -1;
531 if (PySys_SetObject("stderr", (PyObject *)(void *)&Error))
532 return -1;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200533
534 if (PyErr_Occurred())
535 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +0100536 emsg(_("E264: Python: Error initialising I/O objects"));
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200537 return -1;
538 }
539
540 return 0;
541}
542
Bram Moolenaar79a494d2018-07-22 04:30:21 +0200543#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200544static PyObject *call_load_module(char *name, int len, PyObject *find_module_result);
545
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200546typedef struct
547{
548 PyObject_HEAD
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200549 char *fullname;
550 PyObject *result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200551} LoaderObject;
552static PyTypeObject LoaderType;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200553
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200554 static void
555LoaderDestructor(LoaderObject *self)
556{
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200557 vim_free(self->fullname);
558 Py_XDECREF(self->result);
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200559 DESTRUCTOR_FINISH(self);
560}
561
562 static PyObject *
563LoaderLoadModule(LoaderObject *self, PyObject *args UNUSED)
564{
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200565 char *fullname = self->fullname;
566 PyObject *result = self->result;
567 PyObject *module;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200568
Bram Moolenaar447bd5a2018-08-07 19:45:27 +0200569 if (!fullname)
570 {
571 module = result ? result : Py_None;
572 Py_INCREF(module);
573 return module;
574 }
575
576 module = call_load_module(fullname, (int)STRLEN(fullname), result);
577
578 self->fullname = NULL;
579 self->result = module;
580
581 vim_free(fullname);
582 Py_DECREF(result);
583
584 if (!module)
585 {
586 if (PyErr_Occurred())
587 return NULL;
588
589 Py_INCREF(Py_None);
590 return Py_None;
591 }
592
593 Py_INCREF(module);
594 return module;
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200595}
596
597static struct PyMethodDef LoaderMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100598 // name, function, calling, doc
Bram Moolenaar81c40c52013-06-12 14:41:04 +0200599 {"load_module", (PyCFunction)LoaderLoadModule, METH_VARARGS, ""},
600 { NULL, NULL, 0, NULL}
601};
Bram Moolenaar79a494d2018-07-22 04:30:21 +0200602#endif
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200603
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100604/*
605 * Check to see whether a Vim error has been reported, or a keyboard
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200606 * interrupt has been detected.
607 */
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200608 static void
609VimTryStart(void)
610{
611 ++trylevel;
612}
613
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200614 static int
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200615VimTryEnd(void)
616{
617 --trylevel;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100618 // Without this it stops processing all subsequent Vim script commands and
619 // generates strange error messages if I e.g. try calling Test() in a cycle
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200620 did_emsg = FALSE;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100621 // Keyboard interrupt should be preferred over anything else
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200622 if (got_int)
623 {
Bram Moolenaar4315f262014-01-31 14:54:04 +0100624 if (did_throw)
Bram Moolenaard6b8a522013-11-11 01:05:48 +0100625 discard_current_exception();
Bram Moolenaard6b8a522013-11-11 01:05:48 +0100626 got_int = FALSE;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200627 PyErr_SetNone(PyExc_KeyboardInterrupt);
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200628 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200629 }
Bram Moolenaar9fee7d42013-11-28 17:04:43 +0100630 else if (msg_list != NULL && *msg_list != NULL)
631 {
632 int should_free;
Bram Moolenaarb1443b42019-01-13 23:51:14 +0100633 char *msg;
Bram Moolenaar9fee7d42013-11-28 17:04:43 +0100634
635 msg = get_exception_string(*msg_list, ET_ERROR, NULL, &should_free);
636
637 if (msg == NULL)
638 {
639 PyErr_NoMemory();
640 return -1;
641 }
642
Bram Moolenaarb1443b42019-01-13 23:51:14 +0100643 PyErr_SetVim(msg);
Bram Moolenaar9fee7d42013-11-28 17:04:43 +0100644
645 free_global_msglist();
646
647 if (should_free)
648 vim_free(msg);
649
650 return -1;
651 }
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200652 else if (!did_throw)
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200653 return (PyErr_Occurred() ? -1 : 0);
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100654 // Python exception is preferred over vim one; unlikely to occur though
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200655 else if (PyErr_Occurred())
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200656 {
Bram Moolenaar4315f262014-01-31 14:54:04 +0100657 discard_current_exception();
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200658 return -1;
659 }
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100660 // Finally transform Vim script exception to python one
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200661 else
662 {
Bram Moolenaar41009372013-07-01 22:03:04 +0200663 PyErr_SetVim((char *)current_exception->value);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200664 discard_current_exception();
Bram Moolenaar841fbd22013-06-23 14:37:07 +0200665 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200666 }
667}
668
669 static int
670VimCheckInterrupt(void)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200671{
672 if (got_int)
673 {
674 PyErr_SetNone(PyExc_KeyboardInterrupt);
675 return 1;
676 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200677 return 0;
678}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200679
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100680// Vim module - Implementation
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +0200681
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200682 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200683VimCommand(PyObject *self UNUSED, PyObject *string)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200684{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200685 char_u *cmd;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200686 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200687 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200688
Bram Moolenaar389a1792013-06-23 13:00:44 +0200689 if (!(cmd = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200690 return NULL;
691
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200692 Py_BEGIN_ALLOW_THREADS
693 Python_Lock_Vim();
694
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200695 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200696 do_cmdline_cmd(cmd);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200697 update_screen(VALID);
698
699 Python_Release_Vim();
700 Py_END_ALLOW_THREADS
701
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200702 if (VimTryEnd())
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200703 ret = NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200704 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200705 ret = Py_None;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200706
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200707 Py_XINCREF(ret);
Bram Moolenaar389a1792013-06-23 13:00:44 +0200708 Py_XDECREF(todecref);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200709 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200710}
711
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200712/*
713 * Function to translate a typval_T into a PyObject; this will recursively
714 * translate lists/dictionaries into their Python equivalents.
715 *
716 * The depth parameter is to avoid infinite recursion, set it to 1 when
717 * you call VimToPython.
718 */
719 static PyObject *
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200720VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200721{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200722 PyObject *ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200723 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +0200724 char ptrBuf[sizeof(void *) * 2 + 3];
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200725
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100726 // Avoid infinite recursion
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200727 if (depth > 100)
728 {
729 Py_INCREF(Py_None);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200730 ret = Py_None;
731 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200732 }
733
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100734 // Check if we run into a recursive loop. The item must be in lookup_dict
735 // then and we can use it again.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200736 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
737 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
738 {
Bram Moolenaardb913952012-06-29 12:54:53 +0200739 sprintf(ptrBuf, "%p",
740 our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
741 : (void *)our_tv->vval.v_dict);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200742
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200743 if ((ret = PyDict_GetItemString(lookup_dict, ptrBuf)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200744 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200745 Py_INCREF(ret);
746 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200747 }
748 }
749
750 if (our_tv->v_type == VAR_STRING)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200751 ret = PyString_FromString(our_tv->vval.v_string == NULL
Bram Moolenaard1f13fd2012-10-05 21:30:07 +0200752 ? "" : (char *)our_tv->vval.v_string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200753 else if (our_tv->v_type == VAR_NUMBER)
754 {
755 char buf[NUMBUFLEN];
756
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100757 // For backwards compatibility numbers are stored as strings.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200758 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
Bram Moolenaar41009372013-07-01 22:03:04 +0200759 ret = PyString_FromString((char *)buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200760 }
Bram Moolenaarb999ba22019-02-14 13:28:45 +0100761#ifdef FEAT_FLOAT
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200762 else if (our_tv->v_type == VAR_FLOAT)
763 {
764 char buf[NUMBUFLEN];
765
766 sprintf(buf, "%f", our_tv->vval.v_float);
Bram Moolenaar41009372013-07-01 22:03:04 +0200767 ret = PyString_FromString((char *)buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200768 }
Bram Moolenaarb999ba22019-02-14 13:28:45 +0100769#endif
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200770 else if (our_tv->v_type == VAR_LIST)
771 {
772 list_T *list = our_tv->vval.v_list;
773 listitem_T *curr;
774
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200775 if (list == NULL)
776 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200777
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200778 if (!(ret = PyList_New(0)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200779 return NULL;
780
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200781 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200782 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200783 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200784 return NULL;
785 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200786
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200787 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
788 {
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200789 if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200790 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200791 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200792 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200793 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200794 if (PyList_Append(ret, newObj))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200795 {
796 Py_DECREF(newObj);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200797 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200798 return NULL;
799 }
800 Py_DECREF(newObj);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200801 }
802 }
803 else if (our_tv->v_type == VAR_DICT)
804 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200805
Bram Moolenaar24a6ff82015-02-10 18:41:58 +0100806 hashtab_T *ht;
807 long_u todo;
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200808 hashitem_T *hi;
809 dictitem_T *di;
Bram Moolenaar24a6ff82015-02-10 18:41:58 +0100810
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200811 if (our_tv->vval.v_dict == NULL)
812 return NULL;
Bram Moolenaar24a6ff82015-02-10 18:41:58 +0100813 ht = &our_tv->vval.v_dict->dv_hashtab;
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200814
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200815 if (!(ret = PyDict_New()))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200816 return NULL;
817
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200818 if (PyDict_SetItemString(lookup_dict, ptrBuf, ret))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200819 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200820 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200821 return NULL;
822 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200823
Bram Moolenaar24a6ff82015-02-10 18:41:58 +0100824 todo = ht->ht_used;
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200825 for (hi = ht->ht_array; todo > 0; ++hi)
826 {
827 if (!HASHITEM_EMPTY(hi))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200828 {
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200829 --todo;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200830
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200831 di = dict_lookup(hi);
Bram Moolenaarb38caae2013-05-29 22:39:52 +0200832 if (!(newObj = VimToPython(&di->di_tv, depth + 1, lookup_dict)))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200833 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200834 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200835 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200836 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200837 if (PyDict_SetItemString(ret, (char *)hi->hi_key, newObj))
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200838 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200839 Py_DECREF(ret);
Bram Moolenaar21642ed2013-05-29 22:20:01 +0200840 Py_DECREF(newObj);
841 return NULL;
842 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200843 }
844 }
845 }
Bram Moolenaar520e1e42016-01-23 19:46:28 +0100846 else if (our_tv->v_type == VAR_SPECIAL)
847 {
848 if (our_tv->vval.v_number == VVAL_FALSE)
849 {
850 ret = Py_False;
851 Py_INCREF(ret);
852 }
853 else if (our_tv->vval.v_number == VVAL_TRUE)
854 {
855 ret = Py_True;
856 Py_INCREF(ret);
857 }
858 else
859 {
860 Py_INCREF(Py_None);
861 ret = Py_None;
862 }
863 return ret;
864 }
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +0100865 else if (our_tv->v_type == VAR_BLOB)
866 ret = PyBytes_FromStringAndSize(
867 (char*) our_tv->vval.v_blob->bv_ga.ga_data,
868 (Py_ssize_t) our_tv->vval.v_blob->bv_ga.ga_len);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200869 else
870 {
871 Py_INCREF(Py_None);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200872 ret = Py_None;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200873 }
874
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200875 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200876}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200877
878 static PyObject *
Bram Moolenaar774267b2013-05-21 20:51:59 +0200879VimEval(PyObject *self UNUSED, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200880{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200881 char_u *expr;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200882 typval_T *our_tv;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200883 PyObject *string;
884 PyObject *todecref;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200885 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200886 PyObject *lookup_dict;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200887
Bram Moolenaar389a1792013-06-23 13:00:44 +0200888 if (!PyArg_ParseTuple(args, "O", &string))
889 return NULL;
890
891 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200892 return NULL;
893
894 Py_BEGIN_ALLOW_THREADS
895 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200896 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200897 our_tv = eval_expr(expr, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200898 Python_Release_Vim();
899 Py_END_ALLOW_THREADS
900
Bram Moolenaar389a1792013-06-23 13:00:44 +0200901 Py_XDECREF(todecref);
902
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200903 if (VimTryEnd())
904 return NULL;
905
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200906 if (our_tv == NULL)
907 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200908 PyErr_SET_VIM(N_("invalid expression"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200909 return NULL;
910 }
911
Bram Moolenaar9bf703d2019-11-30 19:44:38 +0100912 // Convert the Vim type into a Python type. Create a dictionary that's
913 // used to check for recursive loops.
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200914 if (!(lookup_dict = PyDict_New()))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200915 ret = NULL;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200916 else
917 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200918 ret = VimToPython(our_tv, 1, lookup_dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +0200919 Py_DECREF(lookup_dict);
920 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200921
922
923 Py_BEGIN_ALLOW_THREADS
924 Python_Lock_Vim();
925 free_tv(our_tv);
926 Python_Release_Vim();
927 Py_END_ALLOW_THREADS
928
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200929 return ret;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200930}
931
Bram Moolenaardb913952012-06-29 12:54:53 +0200932static PyObject *ConvertToPyObject(typval_T *);
933
934 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200935VimEvalPy(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +0200936{
Bram Moolenaardb913952012-06-29 12:54:53 +0200937 typval_T *our_tv;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200938 PyObject *ret;
Bram Moolenaar389a1792013-06-23 13:00:44 +0200939 char_u *expr;
940 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +0200941
Bram Moolenaar389a1792013-06-23 13:00:44 +0200942 if (!(expr = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +0200943 return NULL;
944
945 Py_BEGIN_ALLOW_THREADS
946 Python_Lock_Vim();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200947 VimTryStart();
Bram Moolenaar389a1792013-06-23 13:00:44 +0200948 our_tv = eval_expr(expr, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +0200949 Python_Release_Vim();
950 Py_END_ALLOW_THREADS
951
Bram Moolenaar389a1792013-06-23 13:00:44 +0200952 Py_XDECREF(todecref);
953
Bram Moolenaara7b64ce2013-05-21 20:40:40 +0200954 if (VimTryEnd())
955 return NULL;
956
Bram Moolenaardb913952012-06-29 12:54:53 +0200957 if (our_tv == NULL)
958 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +0200959 PyErr_SET_VIM(N_("invalid expression"));
Bram Moolenaardb913952012-06-29 12:54:53 +0200960 return NULL;
961 }
962
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200963 ret = ConvertToPyObject(our_tv);
Bram Moolenaardb913952012-06-29 12:54:53 +0200964 Py_BEGIN_ALLOW_THREADS
965 Python_Lock_Vim();
966 free_tv(our_tv);
967 Python_Release_Vim();
968 Py_END_ALLOW_THREADS
969
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200970 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +0200971}
972
973 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +0200974VimStrwidth(PyObject *self UNUSED, PyObject *string)
Bram Moolenaardb913952012-06-29 12:54:53 +0200975{
Bram Moolenaar389a1792013-06-23 13:00:44 +0200976 char_u *str;
977 PyObject *todecref;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200978 int len;
Bram Moolenaardb913952012-06-29 12:54:53 +0200979
Bram Moolenaar389a1792013-06-23 13:00:44 +0200980 if (!(str = StringToChars(string, &todecref)))
Bram Moolenaardb913952012-06-29 12:54:53 +0200981 return NULL;
982
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200983 len = mb_string2cells(str, (int)STRLEN(str));
Bram Moolenaar389a1792013-06-23 13:00:44 +0200984
985 Py_XDECREF(todecref);
986
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200987 return PyLong_FromLong(len);
Bram Moolenaardb913952012-06-29 12:54:53 +0200988}
989
Bram Moolenaarf4258302013-06-02 18:20:17 +0200990 static PyObject *
991_VimChdir(PyObject *_chdir, PyObject *args, PyObject *kwargs)
992{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +0200993 PyObject *ret;
Bram Moolenaarf4258302013-06-02 18:20:17 +0200994 PyObject *newwd;
995 PyObject *todecref;
996 char_u *new_dir;
997
Bram Moolenaard4209d22013-06-05 20:34:15 +0200998 if (_chdir == NULL)
999 return NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001000 if (!(ret = PyObject_Call(_chdir, args, kwargs)))
Bram Moolenaarf4258302013-06-02 18:20:17 +02001001 return NULL;
1002
1003 if (!(newwd = PyObject_CallFunctionObjArgs(py_getcwd, NULL)))
1004 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001005 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001006 return NULL;
1007 }
1008
1009 if (!(new_dir = StringToChars(newwd, &todecref)))
1010 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001011 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001012 Py_DECREF(newwd);
1013 return NULL;
1014 }
1015
1016 VimTryStart();
1017
1018 if (vim_chdir(new_dir))
1019 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001020 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001021 Py_DECREF(newwd);
1022 Py_XDECREF(todecref);
1023
1024 if (VimTryEnd())
1025 return NULL;
1026
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001027 PyErr_SET_VIM(N_("failed to change directory"));
Bram Moolenaarf4258302013-06-02 18:20:17 +02001028 return NULL;
1029 }
1030
1031 Py_DECREF(newwd);
1032 Py_XDECREF(todecref);
1033
Bram Moolenaar1063f3d2019-05-07 22:06:52 +02001034 post_chdir(CDSCOPE_GLOBAL);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001035
1036 if (VimTryEnd())
1037 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001038 Py_DECREF(ret);
Bram Moolenaarf4258302013-06-02 18:20:17 +02001039 return NULL;
1040 }
1041
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001042 return ret;
Bram Moolenaarf4258302013-06-02 18:20:17 +02001043}
1044
1045 static PyObject *
1046VimChdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
1047{
1048 return _VimChdir(py_chdir, args, kwargs);
1049}
1050
1051 static PyObject *
1052VimFchdir(PyObject *self UNUSED, PyObject *args, PyObject *kwargs)
1053{
1054 return _VimChdir(py_fchdir, args, kwargs);
1055}
1056
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001057typedef struct {
1058 PyObject *callable;
1059 PyObject *result;
1060} map_rtp_data;
1061
1062 static void
1063map_rtp_callback(char_u *path, void *_data)
1064{
1065 void **data = (void **) _data;
1066 PyObject *pathObject;
1067 map_rtp_data *mr_data = *((map_rtp_data **) data);
1068
Bram Moolenaar41009372013-07-01 22:03:04 +02001069 if (!(pathObject = PyString_FromString((char *)path)))
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001070 {
1071 *data = NULL;
1072 return;
1073 }
1074
1075 mr_data->result = PyObject_CallFunctionObjArgs(mr_data->callable,
1076 pathObject, NULL);
1077
1078 Py_DECREF(pathObject);
1079
1080 if (!mr_data->result || mr_data->result != Py_None)
1081 *data = NULL;
1082 else
1083 {
1084 Py_DECREF(mr_data->result);
1085 mr_data->result = NULL;
1086 }
1087}
1088
1089 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02001090VimForeachRTP(PyObject *self UNUSED, PyObject *callable)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001091{
1092 map_rtp_data data;
1093
Bram Moolenaar389a1792013-06-23 13:00:44 +02001094 data.callable = callable;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001095 data.result = NULL;
1096
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01001097 do_in_runtimepath(NULL, 0, &map_rtp_callback, &data);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001098
1099 if (data.result == NULL)
1100 {
1101 if (PyErr_Occurred())
1102 return NULL;
1103 else
1104 {
1105 Py_INCREF(Py_None);
1106 return Py_None;
1107 }
1108 }
1109 return data.result;
1110}
1111
1112/*
1113 * _vim_runtimepath_ special path implementation.
1114 */
1115
1116 static void
1117map_finder_callback(char_u *path, void *_data)
1118{
1119 void **data = (void **) _data;
1120 PyObject *list = *((PyObject **) data);
1121 PyObject *pathObject1, *pathObject2;
1122 char *pathbuf;
1123 size_t pathlen;
1124
1125 pathlen = STRLEN(path);
1126
1127#if PY_MAJOR_VERSION < 3
1128# define PY_MAIN_DIR_STRING "python2"
1129#else
1130# define PY_MAIN_DIR_STRING "python3"
1131#endif
1132#define PY_ALTERNATE_DIR_STRING "pythonx"
1133
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001134#define PYTHONX_STRING_LENGTH 7 // STRLEN("pythonx")
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001135 if (!(pathbuf = PyMem_New(char,
1136 pathlen + STRLEN(PATHSEPSTR) + PYTHONX_STRING_LENGTH + 1)))
1137 {
1138 PyErr_NoMemory();
1139 *data = NULL;
1140 return;
1141 }
1142
1143 mch_memmove(pathbuf, path, pathlen + 1);
1144 add_pathsep((char_u *) pathbuf);
1145
1146 pathlen = STRLEN(pathbuf);
1147 mch_memmove(pathbuf + pathlen, PY_MAIN_DIR_STRING,
1148 PYTHONX_STRING_LENGTH + 1);
1149
1150 if (!(pathObject1 = PyString_FromString(pathbuf)))
1151 {
1152 *data = NULL;
1153 PyMem_Free(pathbuf);
1154 return;
1155 }
1156
1157 mch_memmove(pathbuf + pathlen, PY_ALTERNATE_DIR_STRING,
1158 PYTHONX_STRING_LENGTH + 1);
1159
1160 if (!(pathObject2 = PyString_FromString(pathbuf)))
1161 {
1162 Py_DECREF(pathObject1);
1163 PyMem_Free(pathbuf);
1164 *data = NULL;
1165 return;
1166 }
1167
1168 PyMem_Free(pathbuf);
1169
1170 if (PyList_Append(list, pathObject1)
1171 || PyList_Append(list, pathObject2))
1172 *data = NULL;
1173
1174 Py_DECREF(pathObject1);
1175 Py_DECREF(pathObject2);
1176}
1177
1178 static PyObject *
1179Vim_GetPaths(PyObject *self UNUSED)
1180{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001181 PyObject *ret;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001182
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001183 if (!(ret = PyList_New(0)))
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001184 return NULL;
1185
Bram Moolenaar7f8989d2016-03-12 22:11:39 +01001186 do_in_runtimepath(NULL, 0, &map_finder_callback, ret);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001187
1188 if (PyErr_Occurred())
1189 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001190 Py_DECREF(ret);
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001191 return NULL;
1192 }
1193
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001194 return ret;
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001195}
1196
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001197#if PY_VERSION_HEX >= 0x030700f0
1198 static PyObject *
1199FinderFindSpec(PyObject *self, PyObject *args)
1200{
1201 char *fullname;
1202 PyObject *paths;
1203 PyObject *target = Py_None;
1204 PyObject *spec;
1205
1206 if (!PyArg_ParseTuple(args, "s|O", &fullname, &target))
1207 return NULL;
1208
1209 if (!(paths = Vim_GetPaths(self)))
1210 return NULL;
1211
Bram Moolenaarde5b3802019-03-30 12:51:22 +01001212 spec = PyObject_CallFunction(py_find_spec, "sOO", fullname, paths, target);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001213
1214 Py_DECREF(paths);
1215
1216 if (!spec)
1217 {
1218 if (PyErr_Occurred())
1219 return NULL;
1220
1221 Py_INCREF(Py_None);
1222 return Py_None;
1223 }
1224
1225 return spec;
1226}
Bram Moolenaar0b0ad352019-05-20 21:52:45 +02001227
1228 static PyObject *
1229FinderFindModule(PyObject* self UNUSED, PyObject* args UNUSED)
1230{
1231 // Apparently returning None works.
1232 Py_INCREF(Py_None);
1233 return Py_None;
1234}
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001235#else
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001236 static PyObject *
1237call_load_module(char *name, int len, PyObject *find_module_result)
1238{
1239 PyObject *fd, *pathname, *description;
1240
Bram Moolenaarc476e522013-06-23 13:46:40 +02001241 if (!PyTuple_Check(find_module_result))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001242 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001243 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001244 N_("expected 3-tuple as imp.find_module() result, but got %s"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02001245 Py_TYPE_NAME(find_module_result));
1246 return NULL;
1247 }
1248 if (PyTuple_GET_SIZE(find_module_result) != 3)
1249 {
1250 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001251 N_("expected 3-tuple as imp.find_module() result, but got "
1252 "tuple of size %d"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02001253 (int) PyTuple_GET_SIZE(find_module_result));
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001254 return NULL;
1255 }
1256
1257 if (!(fd = PyTuple_GET_ITEM(find_module_result, 0))
1258 || !(pathname = PyTuple_GET_ITEM(find_module_result, 1))
1259 || !(description = PyTuple_GET_ITEM(find_module_result, 2)))
1260 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001261 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001262 N_("internal error: imp.find_module returned tuple with NULL"));
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001263 return NULL;
1264 }
1265
1266 return PyObject_CallFunction(py_load_module,
1267 "s#OOO", name, len, fd, pathname, description);
1268}
1269
1270 static PyObject *
1271find_module(char *fullname, char *tail, PyObject *new_path)
1272{
1273 PyObject *find_module_result;
1274 PyObject *module;
1275 char *dot;
1276
Bram Moolenaar41009372013-07-01 22:03:04 +02001277 if ((dot = (char *)vim_strchr((char_u *) tail, '.')))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001278 {
1279 /*
Bram Moolenaaredb07a22013-06-12 18:13:38 +02001280 * There is a dot in the name: call find_module recursively without the
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001281 * first component
1282 */
1283 PyObject *newest_path;
1284 int partlen = (int) (dot - 1 - tail);
1285
1286 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1287 "s#O", tail, partlen, new_path)))
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001288 {
1289 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_ImportError))
1290 PyErr_Clear();
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001291 return NULL;
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001292 }
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001293
1294 if (!(module = call_load_module(
1295 fullname,
1296 ((int) (tail - fullname)) + partlen,
1297 find_module_result)))
1298 {
1299 Py_DECREF(find_module_result);
1300 return NULL;
1301 }
1302
1303 Py_DECREF(find_module_result);
1304
1305 if (!(newest_path = PyObject_GetAttrString(module, "__path__")))
1306 {
1307 Py_DECREF(module);
1308 return NULL;
1309 }
1310
1311 Py_DECREF(module);
1312
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001313 find_module_result = find_module(fullname, dot + 1, newest_path);
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001314
1315 Py_DECREF(newest_path);
1316
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001317 return find_module_result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001318 }
1319 else
1320 {
1321 if (!(find_module_result = PyObject_CallFunction(py_find_module,
1322 "sO", tail, new_path)))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001323 {
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001324 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_ImportError))
1325 PyErr_Clear();
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001326 return NULL;
1327 }
1328
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001329 return find_module_result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001330 }
1331}
1332
1333 static PyObject *
1334FinderFindModule(PyObject *self, PyObject *args)
1335{
1336 char *fullname;
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001337 PyObject *result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001338 PyObject *new_path;
1339 LoaderObject *loader;
1340
1341 if (!PyArg_ParseTuple(args, "s", &fullname))
1342 return NULL;
1343
1344 if (!(new_path = Vim_GetPaths(self)))
1345 return NULL;
1346
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001347 result = find_module(fullname, fullname, new_path);
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001348
1349 Py_DECREF(new_path);
1350
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001351 if (!result)
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001352 {
Bram Moolenaar7e85d3d2013-06-23 16:40:39 +02001353 if (PyErr_Occurred())
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001354 return NULL;
Bram Moolenaar7e85d3d2013-06-23 16:40:39 +02001355
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001356 Py_INCREF(Py_None);
1357 return Py_None;
1358 }
1359
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001360 if (!(fullname = (char *)vim_strsave((char_u *)fullname)))
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001361 {
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001362 Py_DECREF(result);
1363 PyErr_NoMemory();
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001364 return NULL;
1365 }
1366
Bram Moolenaar447bd5a2018-08-07 19:45:27 +02001367 if (!(loader = PyObject_NEW(LoaderObject, &LoaderType)))
1368 {
1369 vim_free(fullname);
1370 Py_DECREF(result);
1371 return NULL;
1372 }
1373
1374 loader->fullname = fullname;
1375 loader->result = result;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001376
1377 return (PyObject *) loader;
1378}
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001379#endif
Bram Moolenaar81c40c52013-06-12 14:41:04 +02001380
1381 static PyObject *
1382VimPathHook(PyObject *self UNUSED, PyObject *args)
1383{
1384 char *path;
1385
1386 if (PyArg_ParseTuple(args, "s", &path)
1387 && STRCMP(path, vim_special_path) == 0)
1388 {
1389 Py_INCREF(vim_module);
1390 return vim_module;
1391 }
1392
1393 PyErr_Clear();
1394 PyErr_SetNone(PyExc_ImportError);
1395 return NULL;
1396}
1397
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001398/*
1399 * Vim module - Definitions
1400 */
1401
1402static struct PyMethodDef VimMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001403 // name, function, calling, documentation
Bram Moolenaar389a1792013-06-23 13:00:44 +02001404 {"command", VimCommand, METH_O, "Execute a Vim ex-mode command" },
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001405 {"eval", VimEval, METH_VARARGS, "Evaluate an expression using Vim evaluator" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02001406 {"bindeval", VimEvalPy, METH_O, "Like eval(), but returns objects attached to vim ones"},
1407 {"strwidth", VimStrwidth, METH_O, "Screen string width, counts <Tab> as having width 1"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001408 {"chdir", (PyCFunction)VimChdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
1409 {"fchdir", (PyCFunction)VimFchdir, METH_VARARGS|METH_KEYWORDS, "Change directory"},
Bram Moolenaar389a1792013-06-23 13:00:44 +02001410 {"foreach_rtp", VimForeachRTP, METH_O, "Call given callable for each path in &rtp"},
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001411#if PY_VERSION_HEX >= 0x030700f0
1412 {"find_spec", FinderFindSpec, METH_VARARGS, "Internal use only, returns spec object for any input it receives"},
Bram Moolenaar79a494d2018-07-22 04:30:21 +02001413#endif
Bram Moolenaar0b0ad352019-05-20 21:52:45 +02001414 {"find_module", FinderFindModule, METH_VARARGS, "Internal use only, returns loader object for any input it receives"},
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02001415 {"path_hook", VimPathHook, METH_VARARGS, "Hook function to install in sys.path_hooks"},
1416 {"_get_paths", (PyCFunction)Vim_GetPaths, METH_NOARGS, "Get &rtp-based additions to sys.path"},
1417 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001418};
1419
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001420/*
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001421 * Generic iterator object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001422 */
1423
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001424static PyTypeObject IterType;
1425
1426typedef PyObject *(*nextfun)(void **);
1427typedef void (*destructorfun)(void *);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001428typedef int (*traversefun)(void *, visitproc, void *);
1429typedef int (*clearfun)(void **);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001430
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001431// Main purpose of this object is removing the need for do python
1432// initialization (i.e. PyType_Ready and setting type attributes) for a big
1433// bunch of objects.
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001434typedef struct
1435{
1436 PyObject_HEAD
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001437 void *cur;
1438 nextfun next;
1439 destructorfun destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001440 traversefun traverse;
1441 clearfun clear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001442} IterObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001443
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001444 static PyObject *
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001445IterNew(void *start, destructorfun destruct, nextfun next, traversefun traverse,
1446 clearfun clear)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001447{
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001448 IterObject *self;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001449
Bram Moolenaar774267b2013-05-21 20:51:59 +02001450 self = PyObject_GC_New(IterObject, &IterType);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001451 self->cur = start;
1452 self->next = next;
1453 self->destruct = destruct;
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001454 self->traverse = traverse;
1455 self->clear = clear;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001456
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001457 return (PyObject *)(self);
1458}
1459
1460 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001461IterDestructor(IterObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001462{
Bram Moolenaar774267b2013-05-21 20:51:59 +02001463 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02001464 self->destruct(self->cur);
Bram Moolenaar774267b2013-05-21 20:51:59 +02001465 PyObject_GC_Del((void *)(self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001466}
1467
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001468 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001469IterTraverse(IterObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001470{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001471 if (self->traverse != NULL)
1472 return self->traverse(self->cur, visit, arg);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001473 else
1474 return 0;
1475}
1476
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001477// Mac OSX defines clear() somewhere.
Bram Moolenaar9e74e302013-05-17 21:20:17 +02001478#ifdef clear
1479# undef clear
1480#endif
1481
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001482 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02001483IterClear(IterObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001484{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001485 if (self->clear != NULL)
1486 return self->clear(&self->cur);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02001487 else
1488 return 0;
1489}
1490
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001491 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02001492IterNext(IterObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001493{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001494 return self->next(&self->cur);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001495}
1496
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001497 static PyObject *
1498IterIter(PyObject *self)
1499{
Bram Moolenaar1bcabe12013-05-29 22:52:32 +02001500 Py_INCREF(self);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02001501 return self;
1502}
Bram Moolenaardfa38d42013-05-15 13:38:47 +02001503
Bram Moolenaardb913952012-06-29 12:54:53 +02001504typedef struct pylinkedlist_S {
1505 struct pylinkedlist_S *pll_next;
1506 struct pylinkedlist_S *pll_prev;
1507 PyObject *pll_obj;
1508} pylinkedlist_T;
1509
1510static pylinkedlist_T *lastdict = NULL;
1511static pylinkedlist_T *lastlist = NULL;
Bram Moolenaar8110a092016-04-14 15:56:09 +02001512static pylinkedlist_T *lastfunc = NULL;
Bram Moolenaardb913952012-06-29 12:54:53 +02001513
1514 static void
1515pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
1516{
1517 if (ref->pll_prev == NULL)
1518 {
1519 if (ref->pll_next == NULL)
1520 {
1521 *last = NULL;
1522 return;
1523 }
1524 }
1525 else
1526 ref->pll_prev->pll_next = ref->pll_next;
1527
1528 if (ref->pll_next == NULL)
1529 *last = ref->pll_prev;
1530 else
1531 ref->pll_next->pll_prev = ref->pll_prev;
1532}
1533
1534 static void
1535pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
1536{
1537 if (*last == NULL)
1538 ref->pll_prev = NULL;
1539 else
1540 {
1541 (*last)->pll_next = ref;
1542 ref->pll_prev = *last;
1543 }
1544 ref->pll_next = NULL;
1545 ref->pll_obj = self;
1546 *last = ref;
1547}
1548
1549static PyTypeObject DictionaryType;
1550
1551typedef struct
1552{
1553 PyObject_HEAD
1554 dict_T *dict;
1555 pylinkedlist_T ref;
1556} DictionaryObject;
1557
Bram Moolenaara9922d62013-05-30 13:01:18 +02001558static PyObject *DictionaryUpdate(DictionaryObject *, PyObject *, PyObject *);
1559
1560#define NEW_DICTIONARY(dict) DictionaryNew(&DictionaryType, dict)
1561
Bram Moolenaardb913952012-06-29 12:54:53 +02001562 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001563DictionaryNew(PyTypeObject *subtype, dict_T *dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02001564{
1565 DictionaryObject *self;
1566
Bram Moolenaara9922d62013-05-30 13:01:18 +02001567 self = (DictionaryObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02001568 if (self == NULL)
1569 return NULL;
1570 self->dict = dict;
1571 ++dict->dv_refcount;
1572
1573 pyll_add((PyObject *)(self), &self->ref, &lastdict);
1574
1575 return (PyObject *)(self);
1576}
1577
Bram Moolenaara9922d62013-05-30 13:01:18 +02001578 static dict_T *
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001579py_dict_alloc(void)
Bram Moolenaara9922d62013-05-30 13:01:18 +02001580{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001581 dict_T *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001582
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001583 if (!(ret = dict_alloc()))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001584 {
1585 PyErr_NoMemory();
1586 return NULL;
1587 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001588 ++ret->dv_refcount;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001589
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001590 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001591}
1592
1593 static PyObject *
1594DictionaryConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
1595{
1596 DictionaryObject *self;
1597 dict_T *dict;
1598
1599 if (!(dict = py_dict_alloc()))
1600 return NULL;
1601
1602 self = (DictionaryObject *) DictionaryNew(subtype, dict);
1603
1604 --dict->dv_refcount;
1605
1606 if (kwargs || PyTuple_Size(args))
1607 {
1608 PyObject *tmp;
1609 if (!(tmp = DictionaryUpdate(self, args, kwargs)))
1610 {
1611 Py_DECREF(self);
1612 return NULL;
1613 }
1614
1615 Py_DECREF(tmp);
1616 }
1617
1618 return (PyObject *)(self);
1619}
1620
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001621 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02001622DictionaryDestructor(DictionaryObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001623{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001624 pyll_remove(&self->ref, &lastdict);
1625 dict_unref(self->dict);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02001626
1627 DESTRUCTOR_FINISH(self);
1628}
1629
Bram Moolenaardd8aca62013-05-29 22:36:10 +02001630static char *DictionaryAttrs[] = {
1631 "locked", "scope",
1632 NULL
1633};
1634
1635 static PyObject *
1636DictionaryDir(PyObject *self)
1637{
1638 return ObjectDir(self, DictionaryAttrs);
1639}
1640
Bram Moolenaardb913952012-06-29 12:54:53 +02001641 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001642DictionarySetattr(DictionaryObject *self, char *name, PyObject *valObject)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001643{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001644 if (valObject == NULL)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001645 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001646 PyErr_SET_STRING(PyExc_AttributeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001647 N_("cannot delete vim.Dictionary attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001648 return -1;
1649 }
1650
1651 if (strcmp(name, "locked") == 0)
1652 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02001653 if (self->dict->dv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02001654 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001655 PyErr_SET_STRING(PyExc_TypeError,
1656 N_("cannot modify fixed dictionary"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02001657 return -1;
1658 }
1659 else
1660 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001661 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarb983f752013-05-15 16:11:50 +02001662 if (istrue == -1)
1663 return -1;
1664 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02001665 self->dict->dv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001666 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02001667 self->dict->dv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02001668 }
1669 return 0;
1670 }
1671 else
1672 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001673 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name);
Bram Moolenaar66b79852012-09-21 14:00:35 +02001674 return -1;
1675 }
1676}
1677
1678 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02001679DictionaryLength(DictionaryObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02001680{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001681 return ((PyInt) (self->dict->dv_hashtab.ht_used));
Bram Moolenaardb913952012-06-29 12:54:53 +02001682}
1683
Bram Moolenaara9922d62013-05-30 13:01:18 +02001684#define DICT_FLAG_HAS_DEFAULT 0x01
1685#define DICT_FLAG_POP 0x02
1686#define DICT_FLAG_NONE_DEFAULT 0x04
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01001687#define DICT_FLAG_RETURN_BOOL 0x08 // Incompatible with DICT_FLAG_POP
Bram Moolenaara9922d62013-05-30 13:01:18 +02001688#define DICT_FLAG_RETURN_PAIR 0x10
1689
Bram Moolenaardb913952012-06-29 12:54:53 +02001690 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001691_DictionaryItem(DictionaryObject *self, PyObject *args, int flags)
Bram Moolenaardb913952012-06-29 12:54:53 +02001692{
Bram Moolenaara9922d62013-05-30 13:01:18 +02001693 PyObject *keyObject;
1694 PyObject *defObject = ((flags & DICT_FLAG_NONE_DEFAULT)? Py_None : NULL);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001695 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001696 char_u *key;
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001697 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001698 dict_T *dict = self->dict;
1699 hashitem_T *hi;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001700 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001701
Bram Moolenaara9922d62013-05-30 13:01:18 +02001702 if (flags & DICT_FLAG_HAS_DEFAULT)
1703 {
1704 if (!PyArg_ParseTuple(args, "O|O", &keyObject, &defObject))
1705 return NULL;
1706 }
1707 else
1708 keyObject = args;
1709
1710 if (flags & DICT_FLAG_RETURN_BOOL)
1711 defObject = Py_False;
1712
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001713 if (!(key = StringToChars(keyObject, &todecref)))
1714 return NULL;
1715
1716 if (*key == NUL)
1717 {
1718 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001719 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001720 return NULL;
1721 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001722
Bram Moolenaara9922d62013-05-30 13:01:18 +02001723 hi = hash_find(&dict->dv_hashtab, key);
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001724
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001725 Py_XDECREF(todecref);
Bram Moolenaar696c2112012-09-21 13:43:14 +02001726
Bram Moolenaara9922d62013-05-30 13:01:18 +02001727 if (HASHITEM_EMPTY(hi))
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001728 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001729 if (defObject)
1730 {
1731 Py_INCREF(defObject);
1732 return defObject;
1733 }
1734 else
1735 {
1736 PyErr_SetObject(PyExc_KeyError, keyObject);
1737 return NULL;
1738 }
1739 }
1740 else if (flags & DICT_FLAG_RETURN_BOOL)
1741 {
Bram Moolenaar0e4eebd2014-02-12 22:08:49 +01001742 ret = Py_True;
1743 Py_INCREF(ret);
1744 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001745 }
1746
1747 di = dict_lookup(hi);
1748
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001749 if (!(ret = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001750 return NULL;
1751
1752 if (flags & DICT_FLAG_POP)
1753 {
1754 if (dict->dv_lock)
1755 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001756 RAISE_LOCKED_DICTIONARY;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001757 Py_DECREF(ret);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001758 return NULL;
1759 }
1760
1761 hash_remove(&dict->dv_hashtab, hi);
1762 dictitem_free(di);
1763 }
1764
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001765 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001766}
1767
1768 static PyObject *
1769DictionaryItem(DictionaryObject *self, PyObject *keyObject)
1770{
1771 return _DictionaryItem(self, keyObject, 0);
1772}
1773
1774 static int
1775DictionaryContains(DictionaryObject *self, PyObject *keyObject)
1776{
1777 PyObject *rObj = _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001778 int ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001779
Bram Moolenaarba2d7ff2013-11-04 00:34:53 +01001780 if (rObj == NULL)
1781 return -1;
1782
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001783 ret = (rObj == Py_True);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001784
Bram Moolenaardee2e312013-06-23 16:35:47 +02001785 Py_DECREF(rObj);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001786
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001787 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001788}
1789
1790typedef struct
1791{
1792 hashitem_T *ht_array;
1793 long_u ht_used;
1794 hashtab_T *ht;
1795 hashitem_T *hi;
Bram Moolenaar99dc19d2013-05-31 20:49:31 +02001796 long_u todo;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001797} dictiterinfo_T;
1798
1799 static PyObject *
1800DictionaryIterNext(dictiterinfo_T **dii)
1801{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001802 PyObject *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001803
1804 if (!(*dii)->todo)
1805 return NULL;
1806
1807 if ((*dii)->ht->ht_array != (*dii)->ht_array ||
1808 (*dii)->ht->ht_used != (*dii)->ht_used)
1809 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02001810 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02001811 N_("hashtab changed during iteration"));
Bram Moolenaar231e1a12012-09-05 18:45:28 +02001812 return NULL;
1813 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001814
Bram Moolenaara9922d62013-05-30 13:01:18 +02001815 while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
1816 ++((*dii)->hi);
1817
1818 --((*dii)->todo);
1819
Bram Moolenaar41009372013-07-01 22:03:04 +02001820 if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02001821 return NULL;
1822
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001823 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001824}
1825
1826 static PyObject *
1827DictionaryIter(DictionaryObject *self)
1828{
1829 dictiterinfo_T *dii;
1830 hashtab_T *ht;
1831
1832 if (!(dii = PyMem_New(dictiterinfo_T, 1)))
1833 {
1834 PyErr_NoMemory();
1835 return NULL;
1836 }
1837
1838 ht = &self->dict->dv_hashtab;
1839 dii->ht_array = ht->ht_array;
1840 dii->ht_used = ht->ht_used;
1841 dii->ht = ht;
1842 dii->hi = dii->ht_array;
1843 dii->todo = dii->ht_used;
1844
1845 return IterNew(dii,
1846 (destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
1847 NULL, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02001848}
1849
1850 static PyInt
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02001851DictionaryAssItem(
1852 DictionaryObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaardb913952012-06-29 12:54:53 +02001853{
1854 char_u *key;
1855 typval_T tv;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001856 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001857 dictitem_T *di;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001858 PyObject *todecref;
Bram Moolenaardb913952012-06-29 12:54:53 +02001859
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001860 if (dict->dv_lock)
Bram Moolenaardb913952012-06-29 12:54:53 +02001861 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02001862 RAISE_LOCKED_DICTIONARY;
Bram Moolenaardb913952012-06-29 12:54:53 +02001863 return -1;
1864 }
1865
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001866 if (!(key = StringToChars(keyObject, &todecref)))
1867 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02001868
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001869 if (*key == NUL)
1870 {
1871 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001872 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001873 return -1;
1874 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001875
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001876 di = dict_find(dict, key, -1);
Bram Moolenaardb913952012-06-29 12:54:53 +02001877
1878 if (valObject == NULL)
1879 {
Bram Moolenaarf27839c2012-06-29 16:19:50 +02001880 hashitem_T *hi;
1881
Bram Moolenaardb913952012-06-29 12:54:53 +02001882 if (di == NULL)
1883 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001884 Py_XDECREF(todecref);
Bram Moolenaar4d188da2013-05-15 15:35:09 +02001885 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaardb913952012-06-29 12:54:53 +02001886 return -1;
1887 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001888 hi = hash_find(&dict->dv_hashtab, di->di_key);
1889 hash_remove(&dict->dv_hashtab, hi);
Bram Moolenaardb913952012-06-29 12:54:53 +02001890 dictitem_free(di);
Bram Moolenaar78b59572013-06-02 18:54:21 +02001891 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001892 return 0;
1893 }
1894
1895 if (ConvertFromPyObject(valObject, &tv) == -1)
Bram Moolenaar78b59572013-06-02 18:54:21 +02001896 {
1897 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001898 return -1;
Bram Moolenaar78b59572013-06-02 18:54:21 +02001899 }
Bram Moolenaardb913952012-06-29 12:54:53 +02001900
1901 if (di == NULL)
1902 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001903 if (!(di = dictitem_alloc(key)))
Bram Moolenaardb913952012-06-29 12:54:53 +02001904 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001905 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001906 PyErr_NoMemory();
1907 return -1;
1908 }
Bram Moolenaara9922d62013-05-30 13:01:18 +02001909 di->di_tv.v_type = VAR_UNKNOWN;
Bram Moolenaardb913952012-06-29 12:54:53 +02001910
Bram Moolenaarb38caae2013-05-29 22:39:52 +02001911 if (dict_add(dict, di) == FAIL)
Bram Moolenaardb913952012-06-29 12:54:53 +02001912 {
1913 vim_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001914 dictitem_free(di);
Bram Moolenaarc476e522013-06-23 13:46:40 +02001915 RAISE_KEY_ADD_FAIL(key);
1916 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001917 return -1;
1918 }
1919 }
1920 else
1921 clear_tv(&di->di_tv);
1922
Bram Moolenaar35eacd72013-05-30 22:06:33 +02001923 Py_XDECREF(todecref);
Bram Moolenaardb913952012-06-29 12:54:53 +02001924
1925 copy_tv(&tv, &di->di_tv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02001926 clear_tv(&tv);
Bram Moolenaardb913952012-06-29 12:54:53 +02001927 return 0;
1928}
1929
Bram Moolenaara9922d62013-05-30 13:01:18 +02001930typedef PyObject *(*hi_to_py)(hashitem_T *);
1931
Bram Moolenaardb913952012-06-29 12:54:53 +02001932 static PyObject *
Bram Moolenaara9922d62013-05-30 13:01:18 +02001933DictionaryListObjects(DictionaryObject *self, hi_to_py hiconvert)
Bram Moolenaardb913952012-06-29 12:54:53 +02001934{
Bram Moolenaard6e39182013-05-21 18:30:34 +02001935 dict_T *dict = self->dict;
Bram Moolenaardb913952012-06-29 12:54:53 +02001936 long_u todo = dict->dv_hashtab.ht_used;
1937 Py_ssize_t i = 0;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001938 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001939 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001940 PyObject *newObj;
Bram Moolenaardb913952012-06-29 12:54:53 +02001941
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001942 ret = PyList_New(todo);
Bram Moolenaardb913952012-06-29 12:54:53 +02001943 for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
1944 {
1945 if (!HASHITEM_EMPTY(hi))
1946 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02001947 if (!(newObj = hiconvert(hi)))
1948 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001949 Py_DECREF(ret);
Bram Moolenaara9922d62013-05-30 13:01:18 +02001950 return NULL;
1951 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001952 PyList_SET_ITEM(ret, i, newObj);
Bram Moolenaardb913952012-06-29 12:54:53 +02001953 --todo;
1954 ++i;
1955 }
1956 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001957 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02001958}
1959
Bram Moolenaara9922d62013-05-30 13:01:18 +02001960 static PyObject *
1961dict_key(hashitem_T *hi)
1962{
1963 return PyBytes_FromString((char *)(hi->hi_key));
1964}
1965
1966 static PyObject *
1967DictionaryListKeys(DictionaryObject *self)
1968{
1969 return DictionaryListObjects(self, dict_key);
1970}
1971
1972 static PyObject *
1973dict_val(hashitem_T *hi)
1974{
1975 dictitem_T *di;
1976
1977 di = dict_lookup(hi);
1978 return ConvertToPyObject(&di->di_tv);
1979}
1980
1981 static PyObject *
1982DictionaryListValues(DictionaryObject *self)
1983{
1984 return DictionaryListObjects(self, dict_val);
1985}
1986
1987 static PyObject *
1988dict_item(hashitem_T *hi)
1989{
1990 PyObject *keyObject;
1991 PyObject *valObject;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02001992 PyObject *ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02001993
1994 if (!(keyObject = dict_key(hi)))
1995 return NULL;
1996
1997 if (!(valObject = dict_val(hi)))
1998 {
1999 Py_DECREF(keyObject);
2000 return NULL;
2001 }
2002
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002003 ret = Py_BuildValue("(OO)", keyObject, valObject);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002004
2005 Py_DECREF(keyObject);
2006 Py_DECREF(valObject);
2007
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002008 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002009}
2010
2011 static PyObject *
2012DictionaryListItems(DictionaryObject *self)
2013{
2014 return DictionaryListObjects(self, dict_item);
2015}
2016
2017 static PyObject *
2018DictionaryUpdate(DictionaryObject *self, PyObject *args, PyObject *kwargs)
2019{
2020 dict_T *dict = self->dict;
2021
2022 if (dict->dv_lock)
2023 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002024 RAISE_LOCKED_DICTIONARY;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002025 return NULL;
2026 }
2027
2028 if (kwargs)
2029 {
2030 typval_T tv;
2031
2032 if (ConvertFromPyMapping(kwargs, &tv) == -1)
2033 return NULL;
2034
2035 VimTryStart();
2036 dict_extend(self->dict, tv.vval.v_dict, (char_u *) "force");
2037 clear_tv(&tv);
2038 if (VimTryEnd())
2039 return NULL;
2040 }
2041 else
2042 {
Bram Moolenaar2d5f38f2014-02-11 18:47:27 +01002043 PyObject *obj = NULL;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002044
Bram Moolenaar2d5f38f2014-02-11 18:47:27 +01002045 if (!PyArg_ParseTuple(args, "|O", &obj))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002046 return NULL;
2047
Bram Moolenaar2d5f38f2014-02-11 18:47:27 +01002048 if (obj == NULL)
2049 {
2050 Py_INCREF(Py_None);
2051 return Py_None;
2052 }
2053
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002054 if (PyObject_HasAttrString(obj, "keys"))
2055 return DictionaryUpdate(self, NULL, obj);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002056 else
2057 {
2058 PyObject *iterator;
2059 PyObject *item;
2060
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002061 if (!(iterator = PyObject_GetIter(obj)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002062 return NULL;
2063
2064 while ((item = PyIter_Next(iterator)))
2065 {
2066 PyObject *fast;
2067 PyObject *keyObject;
2068 PyObject *valObject;
2069 PyObject *todecref;
2070 char_u *key;
2071 dictitem_T *di;
Bram Moolenaar9ed7d342017-11-09 22:10:33 +01002072 hashitem_T *hi;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002073
2074 if (!(fast = PySequence_Fast(item, "")))
2075 {
2076 Py_DECREF(iterator);
2077 Py_DECREF(item);
2078 return NULL;
2079 }
2080
2081 Py_DECREF(item);
2082
2083 if (PySequence_Fast_GET_SIZE(fast) != 2)
2084 {
2085 Py_DECREF(iterator);
2086 Py_DECREF(fast);
Bram Moolenaarc476e522013-06-23 13:46:40 +02002087 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002088 N_("expected sequence element of size 2, "
2089 "but got sequence of size %d"),
Bram Moolenaardee2e312013-06-23 16:35:47 +02002090 (int) PySequence_Fast_GET_SIZE(fast));
Bram Moolenaara9922d62013-05-30 13:01:18 +02002091 return NULL;
2092 }
2093
2094 keyObject = PySequence_Fast_GET_ITEM(fast, 0);
2095
2096 if (!(key = StringToChars(keyObject, &todecref)))
2097 {
2098 Py_DECREF(iterator);
2099 Py_DECREF(fast);
2100 return NULL;
2101 }
2102
2103 di = dictitem_alloc(key);
2104
2105 Py_XDECREF(todecref);
2106
2107 if (di == NULL)
2108 {
2109 Py_DECREF(fast);
2110 Py_DECREF(iterator);
2111 PyErr_NoMemory();
2112 return NULL;
2113 }
Bram Moolenaara9922d62013-05-30 13:01:18 +02002114 di->di_tv.v_type = VAR_UNKNOWN;
2115
2116 valObject = PySequence_Fast_GET_ITEM(fast, 1);
2117
2118 if (ConvertFromPyObject(valObject, &di->di_tv) == -1)
2119 {
2120 Py_DECREF(iterator);
2121 Py_DECREF(fast);
2122 dictitem_free(di);
2123 return NULL;
2124 }
2125
2126 Py_DECREF(fast);
2127
Bram Moolenaar9ed7d342017-11-09 22:10:33 +01002128 hi = hash_find(&dict->dv_hashtab, di->di_key);
2129 if (!HASHITEM_EMPTY(hi) || dict_add(dict, di) == FAIL)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002130 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002131 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002132 Py_DECREF(iterator);
2133 dictitem_free(di);
Bram Moolenaara9922d62013-05-30 13:01:18 +02002134 return NULL;
2135 }
2136 }
2137
2138 Py_DECREF(iterator);
2139
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002140 // Iterator may have finished due to an exception
Bram Moolenaara9922d62013-05-30 13:01:18 +02002141 if (PyErr_Occurred())
2142 return NULL;
2143 }
2144 }
2145 Py_INCREF(Py_None);
2146 return Py_None;
2147}
2148
2149 static PyObject *
2150DictionaryGet(DictionaryObject *self, PyObject *args)
2151{
2152 return _DictionaryItem(self, args,
2153 DICT_FLAG_HAS_DEFAULT|DICT_FLAG_NONE_DEFAULT);
2154}
2155
2156 static PyObject *
2157DictionaryPop(DictionaryObject *self, PyObject *args)
2158{
2159 return _DictionaryItem(self, args, DICT_FLAG_HAS_DEFAULT|DICT_FLAG_POP);
2160}
2161
2162 static PyObject *
Bram Moolenaarde71b562013-06-02 17:41:54 +02002163DictionaryPopItem(DictionaryObject *self)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002164{
Bram Moolenaarde71b562013-06-02 17:41:54 +02002165 hashitem_T *hi;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002166 PyObject *ret;
Bram Moolenaarde71b562013-06-02 17:41:54 +02002167 PyObject *valObject;
2168 dictitem_T *di;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002169
Bram Moolenaarde71b562013-06-02 17:41:54 +02002170 if (self->dict->dv_hashtab.ht_used == 0)
2171 {
2172 PyErr_SetNone(PyExc_KeyError);
2173 return NULL;
2174 }
2175
2176 hi = self->dict->dv_hashtab.ht_array;
2177 while (HASHITEM_EMPTY(hi))
2178 ++hi;
2179
2180 di = dict_lookup(hi);
2181
2182 if (!(valObject = ConvertToPyObject(&di->di_tv)))
Bram Moolenaara9922d62013-05-30 13:01:18 +02002183 return NULL;
2184
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002185 if (!(ret = Py_BuildValue("(" Py_bytes_fmt "O)", hi->hi_key, valObject)))
Bram Moolenaarde71b562013-06-02 17:41:54 +02002186 {
2187 Py_DECREF(valObject);
2188 return NULL;
2189 }
2190
2191 hash_remove(&self->dict->dv_hashtab, hi);
2192 dictitem_free(di);
2193
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002194 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02002195}
2196
2197 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02002198DictionaryHasKey(DictionaryObject *self, PyObject *keyObject)
Bram Moolenaara9922d62013-05-30 13:01:18 +02002199{
Bram Moolenaara9922d62013-05-30 13:01:18 +02002200 return _DictionaryItem(self, keyObject, DICT_FLAG_RETURN_BOOL);
2201}
2202
2203static PySequenceMethods DictionaryAsSeq = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002204 0, // sq_length
2205 0, // sq_concat
2206 0, // sq_repeat
2207 0, // sq_item
2208 0, // sq_slice
2209 0, // sq_ass_item
2210 0, // sq_ass_slice
2211 (objobjproc) DictionaryContains, // sq_contains
2212 0, // sq_inplace_concat
2213 0, // sq_inplace_repeat
Bram Moolenaara9922d62013-05-30 13:01:18 +02002214};
2215
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02002216static PyMappingMethods DictionaryAsMapping = {
2217 (lenfunc) DictionaryLength,
2218 (binaryfunc) DictionaryItem,
2219 (objobjargproc) DictionaryAssItem,
2220};
2221
Bram Moolenaardb913952012-06-29 12:54:53 +02002222static struct PyMethodDef DictionaryMethods[] = {
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02002223 {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
Bram Moolenaara9922d62013-05-30 13:01:18 +02002224 {"values", (PyCFunction)DictionaryListValues, METH_NOARGS, ""},
2225 {"items", (PyCFunction)DictionaryListItems, METH_NOARGS, ""},
2226 {"update", (PyCFunction)DictionaryUpdate, METH_VARARGS|METH_KEYWORDS, ""},
2227 {"get", (PyCFunction)DictionaryGet, METH_VARARGS, ""},
2228 {"pop", (PyCFunction)DictionaryPop, METH_VARARGS, ""},
Bram Moolenaarde71b562013-06-02 17:41:54 +02002229 {"popitem", (PyCFunction)DictionaryPopItem, METH_NOARGS, ""},
Bram Moolenaar389a1792013-06-23 13:00:44 +02002230 {"has_key", (PyCFunction)DictionaryHasKey, METH_O, ""},
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002231 {"__dir__", (PyCFunction)DictionaryDir, METH_NOARGS, ""},
2232 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002233};
2234
2235static PyTypeObject ListType;
2236
2237typedef struct
2238{
2239 PyObject_HEAD
2240 list_T *list;
2241 pylinkedlist_T ref;
2242} ListObject;
2243
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002244#define NEW_LIST(list) ListNew(&ListType, list)
2245
Bram Moolenaardb913952012-06-29 12:54:53 +02002246 static PyObject *
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002247ListNew(PyTypeObject *subtype, list_T *list)
Bram Moolenaardb913952012-06-29 12:54:53 +02002248{
2249 ListObject *self;
2250
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002251 self = (ListObject *) subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02002252 if (self == NULL)
2253 return NULL;
2254 self->list = list;
2255 ++list->lv_refcount;
2256
2257 pyll_add((PyObject *)(self), &self->ref, &lastlist);
2258
2259 return (PyObject *)(self);
2260}
2261
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002262 static list_T *
Bram Moolenaarfb97f282013-07-09 17:42:46 +02002263py_list_alloc(void)
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002264{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002265 list_T *ret;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002266
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002267 if (!(ret = list_alloc()))
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002268 {
2269 PyErr_NoMemory();
2270 return NULL;
2271 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002272 ++ret->lv_refcount;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002273
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002274 return ret;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002275}
2276
2277 static int
2278list_py_concat(list_T *l, PyObject *obj, PyObject *lookup_dict)
2279{
2280 PyObject *iterator;
2281 PyObject *item;
2282 listitem_T *li;
2283
2284 if (!(iterator = PyObject_GetIter(obj)))
2285 return -1;
2286
2287 while ((item = PyIter_Next(iterator)))
2288 {
2289 if (!(li = listitem_alloc()))
2290 {
2291 PyErr_NoMemory();
2292 Py_DECREF(item);
2293 Py_DECREF(iterator);
2294 return -1;
2295 }
2296 li->li_tv.v_lock = 0;
2297 li->li_tv.v_type = VAR_UNKNOWN;
2298
2299 if (_ConvertFromPyObject(item, &li->li_tv, lookup_dict) == -1)
2300 {
2301 Py_DECREF(item);
2302 Py_DECREF(iterator);
2303 listitem_free(li);
2304 return -1;
2305 }
2306
2307 Py_DECREF(item);
2308
2309 list_append(l, li);
2310 }
2311
2312 Py_DECREF(iterator);
2313
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002314 // Iterator may have finished due to an exception
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002315 if (PyErr_Occurred())
2316 return -1;
2317
2318 return 0;
2319}
2320
2321 static PyObject *
2322ListConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2323{
2324 list_T *list;
2325 PyObject *obj = NULL;
2326
2327 if (kwargs)
2328 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002329 PyErr_SET_STRING(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002330 N_("list constructor does not accept keyword arguments"));
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02002331 return NULL;
2332 }
2333
2334 if (!PyArg_ParseTuple(args, "|O", &obj))
2335 return NULL;
2336
2337 if (!(list = py_list_alloc()))
2338 return NULL;
2339
2340 if (obj)
2341 {
2342 PyObject *lookup_dict;
2343
2344 if (!(lookup_dict = PyDict_New()))
2345 {
2346 list_unref(list);
2347 return NULL;
2348 }
2349
2350 if (list_py_concat(list, obj, lookup_dict) == -1)
2351 {
2352 Py_DECREF(lookup_dict);
2353 list_unref(list);
2354 return NULL;
2355 }
2356
2357 Py_DECREF(lookup_dict);
2358 }
2359
2360 return ListNew(subtype, list);
2361}
2362
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002363 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02002364ListDestructor(ListObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002365{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002366 pyll_remove(&self->ref, &lastlist);
2367 list_unref(self->list);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02002368
2369 DESTRUCTOR_FINISH(self);
2370}
2371
Bram Moolenaardb913952012-06-29 12:54:53 +02002372 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02002373ListLength(ListObject *self)
Bram Moolenaardb913952012-06-29 12:54:53 +02002374{
Bram Moolenaard6e39182013-05-21 18:30:34 +02002375 return ((PyInt) (self->list->lv_len));
Bram Moolenaardb913952012-06-29 12:54:53 +02002376}
2377
2378 static PyObject *
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002379ListIndex(ListObject *self, Py_ssize_t index)
Bram Moolenaardb913952012-06-29 12:54:53 +02002380{
2381 listitem_T *li;
2382
Bram Moolenaard6e39182013-05-21 18:30:34 +02002383 if (index >= ListLength(self))
Bram Moolenaardb913952012-06-29 12:54:53 +02002384 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002385 PyErr_SET_STRING(PyExc_IndexError, N_("list index out of range"));
Bram Moolenaardb913952012-06-29 12:54:53 +02002386 return NULL;
2387 }
Bram Moolenaard6e39182013-05-21 18:30:34 +02002388 li = list_find(self->list, (long) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002389 if (li == NULL)
2390 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002391 // No more suitable format specifications in python-2.3
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002392 PyErr_VIM_FORMAT(N_("internal error: failed to get vim list item %d"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02002393 (int) index);
Bram Moolenaardb913952012-06-29 12:54:53 +02002394 return NULL;
2395 }
2396 return ConvertToPyObject(&li->li_tv);
2397}
2398
Bram Moolenaardb913952012-06-29 12:54:53 +02002399 static PyObject *
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002400ListSlice(ListObject *self, Py_ssize_t first, Py_ssize_t step,
2401 Py_ssize_t slicelen)
Bram Moolenaardb913952012-06-29 12:54:53 +02002402{
2403 PyInt i;
Bram Moolenaardb913952012-06-29 12:54:53 +02002404 PyObject *list;
Bram Moolenaardb913952012-06-29 12:54:53 +02002405
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002406 if (step == 0)
2407 {
2408 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
2409 return NULL;
2410 }
Bram Moolenaardb913952012-06-29 12:54:53 +02002411
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002412 list = PyList_New(slicelen);
Bram Moolenaardb913952012-06-29 12:54:53 +02002413 if (list == NULL)
2414 return NULL;
2415
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002416 for (i = 0; i < slicelen; ++i)
Bram Moolenaardb913952012-06-29 12:54:53 +02002417 {
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002418 PyObject *item;
2419
2420 item = ListIndex(self, first + i*step);
Bram Moolenaardb913952012-06-29 12:54:53 +02002421 if (item == NULL)
2422 {
2423 Py_DECREF(list);
2424 return NULL;
2425 }
2426
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002427 PyList_SET_ITEM(list, i, item);
Bram Moolenaardb913952012-06-29 12:54:53 +02002428 }
2429
2430 return list;
2431}
2432
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002433 static PyObject *
2434ListItem(ListObject *self, PyObject* idx)
2435{
2436#if PY_MAJOR_VERSION < 3
2437 if (PyInt_Check(idx))
2438 {
2439 long _idx = PyInt_AsLong(idx);
2440 return ListIndex(self, _idx);
2441 }
2442 else
2443#endif
2444 if (PyLong_Check(idx))
2445 {
2446 long _idx = PyLong_AsLong(idx);
2447 return ListIndex(self, _idx);
2448 }
2449 else if (PySlice_Check(idx))
2450 {
2451 Py_ssize_t start, stop, step, slicelen;
2452
Bram Moolenaar922a4662014-03-30 16:11:43 +02002453 if (PySlice_GetIndicesEx((PySliceObject_T *)idx, ListLength(self),
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002454 &start, &stop, &step, &slicelen) < 0)
2455 return NULL;
2456 return ListSlice(self, start, step, slicelen);
2457 }
2458 else
2459 {
2460 RAISE_INVALID_INDEX_TYPE(idx);
2461 return NULL;
2462 }
2463}
2464
2465 static void
2466list_restore(Py_ssize_t numadded, Py_ssize_t numreplaced, Py_ssize_t slicelen,
2467 list_T *l, listitem_T **lis, listitem_T *lastaddedli)
2468{
2469 while (numreplaced--)
2470 {
2471 list_insert(l, lis[numreplaced], lis[slicelen + numreplaced]);
2472 listitem_remove(l, lis[slicelen + numreplaced]);
2473 }
2474 while (numadded--)
2475 {
2476 listitem_T *next;
2477
2478 next = lastaddedli->li_prev;
2479 listitem_remove(l, lastaddedli);
2480 lastaddedli = next;
2481 }
2482}
2483
2484 static int
2485ListAssSlice(ListObject *self, Py_ssize_t first,
2486 Py_ssize_t step, Py_ssize_t slicelen, PyObject *obj)
2487{
2488 PyObject *iterator;
2489 PyObject *item;
2490 listitem_T *li;
2491 listitem_T *lastaddedli = NULL;
2492 listitem_T *next;
2493 typval_T v;
2494 list_T *l = self->list;
2495 PyInt i;
2496 PyInt j;
2497 PyInt numreplaced = 0;
2498 PyInt numadded = 0;
2499 PyInt size;
Bram Moolenaar3b522612014-02-11 16:00:35 +01002500 listitem_T **lis = NULL;
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002501
2502 size = ListLength(self);
2503
2504 if (l->lv_lock)
2505 {
2506 RAISE_LOCKED_LIST;
2507 return -1;
2508 }
2509
2510 if (step == 0)
2511 {
2512 PyErr_SET_STRING(PyExc_ValueError, N_("slice step cannot be zero"));
2513 return -1;
2514 }
2515
2516 if (step != 1 && slicelen == 0)
2517 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002518 // Nothing to do. Only error out if obj has some items.
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002519 int ret = 0;
2520
2521 if (obj == NULL)
2522 return 0;
2523
2524 if (!(iterator = PyObject_GetIter(obj)))
2525 return -1;
2526
2527 if ((item = PyIter_Next(iterator)))
2528 {
2529 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar4de6a212014-03-08 16:13:44 +01002530 N_("attempt to assign sequence of size greater than %d "
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002531 "to extended slice"), 0);
2532 Py_DECREF(item);
2533 ret = -1;
2534 }
2535 Py_DECREF(iterator);
2536 return ret;
2537 }
2538
2539 if (obj != NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002540 // XXX May allocate zero bytes.
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002541 if (!(lis = PyMem_New(listitem_T *, slicelen * 2)))
2542 {
2543 PyErr_NoMemory();
2544 return -1;
2545 }
2546
2547 if (first == size)
2548 li = NULL;
2549 else
2550 {
2551 li = list_find(l, (long) first);
2552 if (li == NULL)
2553 {
2554 PyErr_VIM_FORMAT(N_("internal error: no vim list item %d"),
2555 (int)first);
2556 if (obj != NULL)
2557 PyMem_Free(lis);
2558 return -1;
2559 }
2560 i = slicelen;
2561 while (i-- && li != NULL)
2562 {
2563 j = step;
2564 next = li;
2565 if (step > 0)
2566 while (next != NULL && ((next = next->li_next) != NULL) && --j);
2567 else
2568 while (next != NULL && ((next = next->li_prev) != NULL) && ++j);
2569
2570 if (obj == NULL)
2571 listitem_remove(l, li);
2572 else
2573 lis[slicelen - i - 1] = li;
2574
2575 li = next;
2576 }
2577 if (li == NULL && i != -1)
2578 {
2579 PyErr_SET_VIM(N_("internal error: not enough list items"));
2580 if (obj != NULL)
2581 PyMem_Free(lis);
2582 return -1;
2583 }
2584 }
2585
2586 if (obj == NULL)
2587 return 0;
2588
2589 if (!(iterator = PyObject_GetIter(obj)))
2590 {
2591 PyMem_Free(lis);
2592 return -1;
2593 }
2594
2595 i = 0;
2596 while ((item = PyIter_Next(iterator)))
2597 {
2598 if (ConvertFromPyObject(item, &v) == -1)
2599 {
2600 Py_DECREF(iterator);
2601 Py_DECREF(item);
2602 PyMem_Free(lis);
2603 return -1;
2604 }
2605 Py_DECREF(item);
2606 if (list_insert_tv(l, &v, numreplaced < slicelen
2607 ? lis[numreplaced]
2608 : li) == FAIL)
2609 {
2610 clear_tv(&v);
2611 PyErr_SET_VIM(N_("internal error: failed to add item to list"));
2612 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2613 PyMem_Free(lis);
2614 return -1;
2615 }
2616 if (numreplaced < slicelen)
2617 {
2618 lis[slicelen + numreplaced] = lis[numreplaced]->li_prev;
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02002619 vimlist_remove(l, lis[numreplaced], lis[numreplaced]);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002620 numreplaced++;
2621 }
2622 else
2623 {
2624 if (li)
2625 lastaddedli = li->li_prev;
2626 else
2627 lastaddedli = l->lv_last;
2628 numadded++;
2629 }
2630 clear_tv(&v);
2631 if (step != 1 && i >= slicelen)
2632 {
2633 Py_DECREF(iterator);
2634 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar4de6a212014-03-08 16:13:44 +01002635 N_("attempt to assign sequence of size greater than %d "
Bram Moolenaar403b3cf2014-02-15 15:59:03 +01002636 "to extended slice"), (int) slicelen);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002637 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2638 PyMem_Free(lis);
2639 return -1;
2640 }
2641 ++i;
2642 }
2643 Py_DECREF(iterator);
2644
2645 if (step != 1 && i != slicelen)
2646 {
2647 PyErr_FORMAT2(PyExc_ValueError,
Bram Moolenaar403b3cf2014-02-15 15:59:03 +01002648 N_("attempt to assign sequence of size %d to extended slice "
2649 "of size %d"), (int) i, (int) slicelen);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002650 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2651 PyMem_Free(lis);
2652 return -1;
2653 }
2654
2655 if (PyErr_Occurred())
2656 {
2657 list_restore(numadded, numreplaced, slicelen, l, lis, lastaddedli);
2658 PyMem_Free(lis);
2659 return -1;
2660 }
2661
2662 for (i = 0; i < numreplaced; i++)
2663 listitem_free(lis[i]);
2664 if (step == 1)
2665 for (i = numreplaced; i < slicelen; i++)
2666 listitem_remove(l, lis[i]);
2667
2668 PyMem_Free(lis);
2669
2670 return 0;
2671}
2672
2673 static int
2674ListAssIndex(ListObject *self, Py_ssize_t index, PyObject *obj)
2675{
2676 typval_T tv;
2677 list_T *l = self->list;
2678 listitem_T *li;
2679 Py_ssize_t length = ListLength(self);
2680
2681 if (l->lv_lock)
2682 {
2683 RAISE_LOCKED_LIST;
2684 return -1;
2685 }
2686 if (index > length || (index == length && obj == NULL))
2687 {
2688 PyErr_SET_STRING(PyExc_IndexError, N_("list index out of range"));
2689 return -1;
2690 }
2691
2692 if (obj == NULL)
2693 {
2694 li = list_find(l, (long) index);
Bram Moolenaar3ec7f4e2014-05-07 17:31:37 +02002695 vimlist_remove(l, li, li);
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002696 clear_tv(&li->li_tv);
2697 vim_free(li);
2698 return 0;
2699 }
2700
2701 if (ConvertFromPyObject(obj, &tv) == -1)
2702 return -1;
2703
2704 if (index == length)
2705 {
2706 if (list_append_tv(l, &tv) == FAIL)
2707 {
2708 clear_tv(&tv);
2709 PyErr_SET_VIM(N_("failed to add item to list"));
2710 return -1;
2711 }
2712 }
2713 else
2714 {
2715 li = list_find(l, (long) index);
2716 clear_tv(&li->li_tv);
2717 copy_tv(&tv, &li->li_tv);
2718 clear_tv(&tv);
2719 }
2720 return 0;
2721}
2722
2723 static Py_ssize_t
2724ListAssItem(ListObject *self, PyObject *idx, PyObject *obj)
2725{
2726#if PY_MAJOR_VERSION < 3
2727 if (PyInt_Check(idx))
2728 {
2729 long _idx = PyInt_AsLong(idx);
2730 return ListAssIndex(self, _idx, obj);
2731 }
2732 else
2733#endif
2734 if (PyLong_Check(idx))
2735 {
2736 long _idx = PyLong_AsLong(idx);
2737 return ListAssIndex(self, _idx, obj);
2738 }
2739 else if (PySlice_Check(idx))
2740 {
2741 Py_ssize_t start, stop, step, slicelen;
2742
Bram Moolenaar922a4662014-03-30 16:11:43 +02002743 if (PySlice_GetIndicesEx((PySliceObject_T *)idx, ListLength(self),
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002744 &start, &stop, &step, &slicelen) < 0)
2745 return -1;
2746 return ListAssSlice(self, start, step, slicelen,
2747 obj);
2748 }
2749 else
2750 {
2751 RAISE_INVALID_INDEX_TYPE(idx);
2752 return -1;
2753 }
2754}
2755
2756 static PyObject *
2757ListConcatInPlace(ListObject *self, PyObject *obj)
2758{
2759 list_T *l = self->list;
2760 PyObject *lookup_dict;
2761
2762 if (l->lv_lock)
2763 {
2764 RAISE_LOCKED_LIST;
2765 return NULL;
2766 }
2767
2768 if (!(lookup_dict = PyDict_New()))
2769 return NULL;
2770
2771 if (list_py_concat(l, obj, lookup_dict) == -1)
2772 {
2773 Py_DECREF(lookup_dict);
2774 return NULL;
2775 }
2776 Py_DECREF(lookup_dict);
2777
2778 Py_INCREF(self);
2779 return (PyObject *)(self);
2780}
2781
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002782typedef struct
2783{
2784 listwatch_T lw;
2785 list_T *list;
2786} listiterinfo_T;
2787
2788 static void
2789ListIterDestruct(listiterinfo_T *lii)
2790{
2791 list_rem_watch(lii->list, &lii->lw);
2792 PyMem_Free(lii);
2793}
2794
2795 static PyObject *
2796ListIterNext(listiterinfo_T **lii)
2797{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002798 PyObject *ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002799
2800 if (!((*lii)->lw.lw_item))
2801 return NULL;
2802
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002803 if (!(ret = ConvertToPyObject(&((*lii)->lw.lw_item->li_tv))))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002804 return NULL;
2805
2806 (*lii)->lw.lw_item = (*lii)->lw.lw_item->li_next;
2807
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002808 return ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002809}
2810
2811 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02002812ListIter(ListObject *self)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002813{
2814 listiterinfo_T *lii;
Bram Moolenaard6e39182013-05-21 18:30:34 +02002815 list_T *l = self->list;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002816
2817 if (!(lii = PyMem_New(listiterinfo_T, 1)))
2818 {
2819 PyErr_NoMemory();
2820 return NULL;
2821 }
2822
2823 list_add_watch(l, &lii->lw);
2824 lii->lw.lw_item = l->lv_first;
2825 lii->list = l;
2826
2827 return IterNew(lii,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02002828 (destructorfun) ListIterDestruct, (nextfun) ListIterNext,
2829 NULL, NULL);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02002830}
2831
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002832static char *ListAttrs[] = {
2833 "locked",
2834 NULL
2835};
2836
2837 static PyObject *
2838ListDir(PyObject *self)
2839{
2840 return ObjectDir(self, ListAttrs);
2841}
2842
Bram Moolenaar66b79852012-09-21 14:00:35 +02002843 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002844ListSetattr(ListObject *self, char *name, PyObject *valObject)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002845{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002846 if (valObject == NULL)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002847 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02002848 PyErr_SET_STRING(PyExc_AttributeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002849 N_("cannot delete vim.List attributes"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002850 return -1;
2851 }
2852
2853 if (strcmp(name, "locked") == 0)
2854 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02002855 if (self->list->lv_lock == VAR_FIXED)
Bram Moolenaar66b79852012-09-21 14:00:35 +02002856 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002857 PyErr_SET_STRING(PyExc_TypeError, N_("cannot modify fixed list"));
Bram Moolenaar66b79852012-09-21 14:00:35 +02002858 return -1;
2859 }
2860 else
2861 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02002862 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarb983f752013-05-15 16:11:50 +02002863 if (istrue == -1)
2864 return -1;
2865 else if (istrue)
Bram Moolenaard6e39182013-05-21 18:30:34 +02002866 self->list->lv_lock = VAR_LOCKED;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002867 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02002868 self->list->lv_lock = 0;
Bram Moolenaar66b79852012-09-21 14:00:35 +02002869 }
2870 return 0;
2871 }
2872 else
2873 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002874 PyErr_FORMAT(PyExc_AttributeError, N_("cannot set attribute %s"), name);
Bram Moolenaar66b79852012-09-21 14:00:35 +02002875 return -1;
2876 }
2877}
2878
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002879static PySequenceMethods ListAsSeq = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01002880 (lenfunc) ListLength, // sq_length, len(x)
2881 (binaryfunc) 0, // RangeConcat, sq_concat, x+y
2882 0, // RangeRepeat, sq_repeat, x*n
2883 (PyIntArgFunc) ListIndex, // sq_item, x[i]
2884 0, // was_sq_slice, x[i:j]
2885 (PyIntObjArgProc) ListAssIndex, // sq_as_item, x[i]=v
2886 0, // was_sq_ass_slice, x[i:j]=v
2887 0, // sq_contains
2888 (binaryfunc) ListConcatInPlace,// sq_inplace_concat
2889 0, // sq_inplace_repeat
Bram Moolenaar063a46b2014-01-14 16:36:51 +01002890};
2891
2892static PyMappingMethods ListAsMapping = {
2893 /* mp_length */ (lenfunc) ListLength,
2894 /* mp_subscript */ (binaryfunc) ListItem,
2895 /* mp_ass_subscript */ (objobjargproc) ListAssItem,
2896};
2897
Bram Moolenaardb913952012-06-29 12:54:53 +02002898static struct PyMethodDef ListMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02002899 {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
2900 {"__dir__", (PyCFunction)ListDir, METH_NOARGS, ""},
2901 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02002902};
2903
2904typedef struct
2905{
2906 PyObject_HEAD
2907 char_u *name;
Bram Moolenaar8110a092016-04-14 15:56:09 +02002908 int argc;
2909 typval_T *argv;
2910 dict_T *self;
2911 pylinkedlist_T ref;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02002912 int auto_rebind;
Bram Moolenaardb913952012-06-29 12:54:53 +02002913} FunctionObject;
2914
2915static PyTypeObject FunctionType;
2916
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02002917#define NEW_FUNCTION(name, argc, argv, self, pt_auto) \
2918 FunctionNew(&FunctionType, (name), (argc), (argv), (self), (pt_auto))
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002919
Bram Moolenaardb913952012-06-29 12:54:53 +02002920 static PyObject *
Bram Moolenaar8110a092016-04-14 15:56:09 +02002921FunctionNew(PyTypeObject *subtype, char_u *name, int argc, typval_T *argv,
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02002922 dict_T *selfdict, int auto_rebind)
Bram Moolenaardb913952012-06-29 12:54:53 +02002923{
2924 FunctionObject *self;
2925
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01002926 self = (FunctionObject *)subtype->tp_alloc(subtype, 0);
Bram Moolenaardb913952012-06-29 12:54:53 +02002927 if (self == NULL)
2928 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002929
2930 if (isdigit(*name))
Bram Moolenaardb913952012-06-29 12:54:53 +02002931 {
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002932 if (!translated_function_exists(name))
2933 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02002934 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002935 N_("unnamed function %s does not exist"), name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002936 return NULL;
2937 }
2938 self->name = vim_strsave(name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002939 }
2940 else
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01002941 {
2942 char_u *p;
2943
2944 if ((p = get_expanded_name(name,
2945 vim_strchr(name, AUTOLOAD_CHAR) == NULL)) == NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002946 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02002947 PyErr_FORMAT(PyExc_ValueError,
2948 N_("function %s does not exist"), name);
Bram Moolenaar018acca2013-05-30 13:37:28 +02002949 return NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002950 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002951
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01002952 if (p[0] == K_SPECIAL && p[1] == KS_EXTRA && p[2] == (int)KE_SNR)
2953 {
2954 char_u *np;
2955 size_t len = STRLEN(p) + 1;
2956
Bram Moolenaar51e14382019-05-25 20:21:28 +02002957 if ((np = alloc(len + 2)) == NULL)
Bram Moolenaar9123c0b2018-12-22 18:59:06 +01002958 {
2959 vim_free(p);
2960 return NULL;
2961 }
2962 mch_memmove(np, "<SNR>", 5);
2963 mch_memmove(np + 5, p + 3, len - 3);
2964 vim_free(p);
2965 self->name = np;
2966 }
2967 else
2968 self->name = p;
2969 }
2970
Bram Moolenaar2d3d60a2016-08-01 16:27:23 +02002971 func_ref(self->name);
Bram Moolenaar8110a092016-04-14 15:56:09 +02002972 self->argc = argc;
2973 self->argv = argv;
2974 self->self = selfdict;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02002975 self->auto_rebind = selfdict == NULL ? TRUE : auto_rebind;
Bram Moolenaar8110a092016-04-14 15:56:09 +02002976
2977 if (self->argv || self->self)
2978 pyll_add((PyObject *)(self), &self->ref, &lastfunc);
2979
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002980 return (PyObject *)(self);
2981}
2982
2983 static PyObject *
2984FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
2985{
2986 PyObject *self;
Bram Moolenaar8110a092016-04-14 15:56:09 +02002987 PyObject *selfdictObject;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02002988 PyObject *autoRebindObject;
Bram Moolenaar8110a092016-04-14 15:56:09 +02002989 PyObject *argsObject = NULL;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02002990 char_u *name;
Bram Moolenaar8110a092016-04-14 15:56:09 +02002991 typval_T selfdicttv;
2992 typval_T argstv;
2993 list_T *argslist = NULL;
2994 dict_T *selfdict = NULL;
2995 int argc = 0;
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02002996 int auto_rebind = TRUE;
Bram Moolenaar8110a092016-04-14 15:56:09 +02002997 typval_T *argv = NULL;
2998 typval_T *curtv;
2999 listitem_T *li;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003000
Bram Moolenaar8110a092016-04-14 15:56:09 +02003001 if (kwargs != NULL)
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003002 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02003003 selfdictObject = PyDict_GetItemString(kwargs, "self");
3004 if (selfdictObject != NULL)
3005 {
3006 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
3007 return NULL;
3008 selfdict = selfdicttv.vval.v_dict;
3009 }
3010 argsObject = PyDict_GetItemString(kwargs, "args");
3011 if (argsObject != NULL)
3012 {
3013 if (ConvertFromPySequence(argsObject, &argstv) == -1)
3014 {
3015 dict_unref(selfdict);
3016 return NULL;
3017 }
3018 argslist = argstv.vval.v_list;
3019
3020 argc = argslist->lv_len;
3021 if (argc != 0)
3022 {
3023 argv = PyMem_New(typval_T, (size_t) argc);
Bram Moolenaarfe4b1862016-04-15 21:47:54 +02003024 if (argv == NULL)
3025 {
3026 PyErr_NoMemory();
3027 dict_unref(selfdict);
3028 list_unref(argslist);
3029 return NULL;
3030 }
Bram Moolenaar8110a092016-04-14 15:56:09 +02003031 curtv = argv;
3032 for (li = argslist->lv_first; li != NULL; li = li->li_next)
3033 copy_tv(&li->li_tv, curtv++);
3034 }
3035 list_unref(argslist);
3036 }
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003037 if (selfdict != NULL)
3038 {
3039 auto_rebind = FALSE;
3040 autoRebindObject = PyDict_GetItemString(kwargs, "auto_rebind");
3041 if (autoRebindObject != NULL)
3042 {
3043 auto_rebind = PyObject_IsTrue(autoRebindObject);
3044 if (auto_rebind == -1)
3045 {
3046 dict_unref(selfdict);
3047 list_unref(argslist);
3048 return NULL;
3049 }
3050 }
3051 }
Bram Moolenaardb913952012-06-29 12:54:53 +02003052 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003053
Bram Moolenaar389a1792013-06-23 13:00:44 +02003054 if (!PyArg_ParseTuple(args, "et", "ascii", &name))
Bram Moolenaar8110a092016-04-14 15:56:09 +02003055 {
3056 dict_unref(selfdict);
3057 while (argc--)
3058 clear_tv(&argv[argc]);
3059 PyMem_Free(argv);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003060 return NULL;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003061 }
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003062
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003063 self = FunctionNew(subtype, name, argc, argv, selfdict, auto_rebind);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003064
Bram Moolenaar389a1792013-06-23 13:00:44 +02003065 PyMem_Free(name);
3066
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003067 return self;
Bram Moolenaardb913952012-06-29 12:54:53 +02003068}
3069
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003070 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003071FunctionDestructor(FunctionObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003072{
Bram Moolenaar8110a092016-04-14 15:56:09 +02003073 int i;
Bram Moolenaard6e39182013-05-21 18:30:34 +02003074 func_unref(self->name);
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02003075 vim_free(self->name);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003076 for (i = 0; i < self->argc; ++i)
3077 clear_tv(&self->argv[i]);
3078 PyMem_Free(self->argv);
3079 dict_unref(self->self);
3080 if (self->argv || self->self)
3081 pyll_remove(&self->ref, &lastfunc);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003082
3083 DESTRUCTOR_FINISH(self);
3084}
3085
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003086static char *FunctionAttrs[] = {
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003087 "softspace", "args", "self", "auto_rebind",
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003088 NULL
3089};
3090
3091 static PyObject *
3092FunctionDir(PyObject *self)
3093{
3094 return ObjectDir(self, FunctionAttrs);
3095}
3096
Bram Moolenaardb913952012-06-29 12:54:53 +02003097 static PyObject *
Bram Moolenaar8110a092016-04-14 15:56:09 +02003098FunctionAttr(FunctionObject *self, char *name)
3099{
3100 list_T *list;
3101 int i;
3102 if (strcmp(name, "name") == 0)
3103 return PyString_FromString((char *)(self->name));
3104 else if (strcmp(name, "args") == 0)
3105 {
Bram Moolenaar9f289532016-08-26 16:39:03 +02003106 if (self->argv == NULL || (list = list_alloc()) == NULL)
Bram Moolenaar8110a092016-04-14 15:56:09 +02003107 return AlwaysNone(NULL);
Bram Moolenaar9f289532016-08-26 16:39:03 +02003108
Bram Moolenaar8110a092016-04-14 15:56:09 +02003109 for (i = 0; i < self->argc; ++i)
3110 list_append_tv(list, &self->argv[i]);
3111 return NEW_LIST(list);
3112 }
3113 else if (strcmp(name, "self") == 0)
3114 return self->self == NULL
3115 ? AlwaysNone(NULL)
3116 : NEW_DICTIONARY(self->self);
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003117 else if (strcmp(name, "auto_rebind") == 0)
3118 return self->auto_rebind
3119 ? AlwaysTrue(NULL)
3120 : AlwaysFalse(NULL);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003121 else if (strcmp(name, "__members__") == 0)
3122 return ObjectDir(NULL, FunctionAttrs);
3123 return NULL;
3124}
3125
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003126/*
3127 * Populate partial_T given function object.
Bram Moolenaar8110a092016-04-14 15:56:09 +02003128 *
3129 * "exported" should be set to true when it is needed to construct a partial
3130 * that may be stored in a variable (i.e. may be freed by Vim).
3131 */
3132 static void
3133set_partial(FunctionObject *self, partial_T *pt, int exported)
3134{
Bram Moolenaar8110a092016-04-14 15:56:09 +02003135 int i;
3136
3137 pt->pt_name = self->name;
3138 if (self->argv)
3139 {
3140 pt->pt_argc = self->argc;
3141 if (exported)
3142 {
Bram Moolenaarc799fe22019-05-28 23:08:19 +02003143 pt->pt_argv = ALLOC_CLEAR_MULT(typval_T, self->argc);
Bram Moolenaar8110a092016-04-14 15:56:09 +02003144 for (i = 0; i < pt->pt_argc; ++i)
3145 copy_tv(&self->argv[i], &pt->pt_argv[i]);
3146 }
3147 else
3148 pt->pt_argv = self->argv;
3149 }
3150 else
3151 {
3152 pt->pt_argc = 0;
3153 pt->pt_argv = NULL;
3154 }
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003155 pt->pt_auto = self->auto_rebind || !exported;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003156 pt->pt_dict = self->self;
3157 if (exported && self->self)
3158 ++pt->pt_dict->dv_refcount;
3159 if (exported)
3160 pt->pt_name = vim_strsave(pt->pt_name);
3161 pt->pt_refcount = 1;
3162}
3163
3164 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003165FunctionCall(FunctionObject *self, PyObject *argsObject, PyObject *kwargs)
Bram Moolenaardb913952012-06-29 12:54:53 +02003166{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003167 char_u *name = self->name;
Bram Moolenaardb913952012-06-29 12:54:53 +02003168 typval_T args;
3169 typval_T selfdicttv;
3170 typval_T rettv;
3171 dict_T *selfdict = NULL;
3172 PyObject *selfdictObject;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003173 PyObject *ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02003174 int error;
Bram Moolenaar8110a092016-04-14 15:56:09 +02003175 partial_T pt;
3176 partial_T *pt_ptr = NULL;
Bram Moolenaardb913952012-06-29 12:54:53 +02003177
Bram Moolenaar8110a092016-04-14 15:56:09 +02003178 if (ConvertFromPySequence(argsObject, &args) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02003179 return NULL;
3180
3181 if (kwargs != NULL)
3182 {
3183 selfdictObject = PyDict_GetItemString(kwargs, "self");
3184 if (selfdictObject != NULL)
3185 {
Bram Moolenaara9922d62013-05-30 13:01:18 +02003186 if (ConvertFromPyMapping(selfdictObject, &selfdicttv) == -1)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003187 {
3188 clear_tv(&args);
Bram Moolenaardb913952012-06-29 12:54:53 +02003189 return NULL;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003190 }
Bram Moolenaardb913952012-06-29 12:54:53 +02003191 selfdict = selfdicttv.vval.v_dict;
3192 }
3193 }
3194
Bram Moolenaar8110a092016-04-14 15:56:09 +02003195 if (self->argv || self->self)
3196 {
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003197 vim_memset(&pt, 0, sizeof(partial_T));
Bram Moolenaar8110a092016-04-14 15:56:09 +02003198 set_partial(self, &pt, FALSE);
3199 pt_ptr = &pt;
3200 }
3201
Bram Moolenaar71700b82013-05-15 17:49:05 +02003202 Py_BEGIN_ALLOW_THREADS
3203 Python_Lock_Vim();
3204
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003205 VimTryStart();
Bram Moolenaar8110a092016-04-14 15:56:09 +02003206 error = func_call(name, &args, pt_ptr, selfdict, &rettv);
Bram Moolenaar71700b82013-05-15 17:49:05 +02003207
3208 Python_Release_Vim();
3209 Py_END_ALLOW_THREADS
3210
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003211 if (VimTryEnd())
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003212 ret = NULL;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003213 else if (error != OK)
Bram Moolenaardb913952012-06-29 12:54:53 +02003214 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003215 ret = NULL;
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003216 PyErr_VIM_FORMAT(N_("failed to run function %s"), (char *)name);
Bram Moolenaardb913952012-06-29 12:54:53 +02003217 }
3218 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003219 ret = ConvertToPyObject(&rettv);
Bram Moolenaardb913952012-06-29 12:54:53 +02003220
Bram Moolenaardb913952012-06-29 12:54:53 +02003221 clear_tv(&args);
3222 clear_tv(&rettv);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003223 if (selfdict != NULL)
3224 clear_tv(&selfdicttv);
Bram Moolenaardb913952012-06-29 12:54:53 +02003225
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003226 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02003227}
3228
Bram Moolenaara5b725c2013-05-30 12:43:54 +02003229 static PyObject *
3230FunctionRepr(FunctionObject *self)
3231{
Bram Moolenaar8110a092016-04-14 15:56:09 +02003232 PyObject *ret;
3233 garray_T repr_ga;
3234 int i;
3235 char_u *tofree = NULL;
3236 typval_T tv;
3237 char_u numbuf[NUMBUFLEN];
3238
3239 ga_init2(&repr_ga, (int)sizeof(char), 70);
3240 ga_concat(&repr_ga, (char_u *)"<vim.Function '");
3241 if (self->name)
3242 ga_concat(&repr_ga, self->name);
3243 else
3244 ga_concat(&repr_ga, (char_u *)"<NULL>");
3245 ga_append(&repr_ga, '\'');
3246 if (self->argv)
3247 {
3248 ga_concat(&repr_ga, (char_u *)", args=[");
3249 ++emsg_silent;
3250 for (i = 0; i < self->argc; i++)
3251 {
3252 if (i != 0)
3253 ga_concat(&repr_ga, (char_u *)", ");
3254 ga_concat(&repr_ga, tv2string(&self->argv[i], &tofree, numbuf,
3255 get_copyID()));
3256 vim_free(tofree);
3257 }
3258 --emsg_silent;
3259 ga_append(&repr_ga, ']');
3260 }
3261 if (self->self)
3262 {
3263 ga_concat(&repr_ga, (char_u *)", self=");
3264 tv.v_type = VAR_DICT;
3265 tv.vval.v_dict = self->self;
3266 ++emsg_silent;
3267 ga_concat(&repr_ga, tv2string(&tv, &tofree, numbuf, get_copyID()));
3268 --emsg_silent;
3269 vim_free(tofree);
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02003270 if (self->auto_rebind)
3271 ga_concat(&repr_ga, (char_u *)", auto_rebind=True");
Bram Moolenaar8110a092016-04-14 15:56:09 +02003272 }
3273 ga_append(&repr_ga, '>');
3274 ret = PyString_FromString((char *)repr_ga.ga_data);
3275 ga_clear(&repr_ga);
3276 return ret;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02003277}
3278
Bram Moolenaardb913952012-06-29 12:54:53 +02003279static struct PyMethodDef FunctionMethods[] = {
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003280 {"__dir__", (PyCFunction)FunctionDir, METH_NOARGS, ""},
3281 { NULL, NULL, 0, NULL}
Bram Moolenaardb913952012-06-29 12:54:53 +02003282};
3283
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003284/*
3285 * Options object
3286 */
3287
3288static PyTypeObject OptionsType;
3289
3290typedef int (*checkfun)(void *);
3291
3292typedef struct
3293{
3294 PyObject_HEAD
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01003295 int opt_type;
3296 void *from;
3297 checkfun Check;
3298 PyObject *fromObj;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003299} OptionsObject;
3300
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003301 static int
3302dummy_check(void *arg UNUSED)
3303{
3304 return 0;
3305}
3306
3307 static PyObject *
3308OptionsNew(int opt_type, void *from, checkfun Check, PyObject *fromObj)
3309{
3310 OptionsObject *self;
3311
Bram Moolenaar774267b2013-05-21 20:51:59 +02003312 self = PyObject_GC_New(OptionsObject, &OptionsType);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003313 if (self == NULL)
3314 return NULL;
3315
3316 self->opt_type = opt_type;
3317 self->from = from;
3318 self->Check = Check;
3319 self->fromObj = fromObj;
3320 if (fromObj)
3321 Py_INCREF(fromObj);
3322
3323 return (PyObject *)(self);
3324}
3325
3326 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003327OptionsDestructor(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003328{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003329 PyObject_GC_UnTrack((void *)(self));
3330 Py_XDECREF(self->fromObj);
3331 PyObject_GC_Del((void *)(self));
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003332}
3333
3334 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003335OptionsTraverse(OptionsObject *self, visitproc visit, void *arg)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003336{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003337 Py_VISIT(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003338 return 0;
3339}
3340
3341 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003342OptionsClear(OptionsObject *self)
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003343{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003344 Py_CLEAR(self->fromObj);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02003345 return 0;
3346}
3347
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003348 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003349OptionsItem(OptionsObject *self, PyObject *keyObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003350{
3351 char_u *key;
3352 int flags;
3353 long numval;
3354 char_u *stringval;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003355 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003356
Bram Moolenaard6e39182013-05-21 18:30:34 +02003357 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003358 return NULL;
3359
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003360 if (!(key = StringToChars(keyObject, &todecref)))
3361 return NULL;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02003362
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003363 if (*key == NUL)
3364 {
3365 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02003366 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003367 return NULL;
3368 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003369
3370 flags = get_option_value_strict(key, &numval, &stringval,
Bram Moolenaard6e39182013-05-21 18:30:34 +02003371 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003372
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003373 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003374
3375 if (flags == 0)
3376 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02003377 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003378 return NULL;
3379 }
3380
3381 if (flags & SOPT_UNSET)
3382 {
3383 Py_INCREF(Py_None);
3384 return Py_None;
3385 }
3386 else if (flags & SOPT_BOOL)
3387 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003388 PyObject *ret;
3389 ret = numval ? Py_True : Py_False;
3390 Py_INCREF(ret);
3391 return ret;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003392 }
3393 else if (flags & SOPT_NUM)
3394 return PyInt_FromLong(numval);
3395 else if (flags & SOPT_STRING)
3396 {
3397 if (stringval)
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003398 {
Bram Moolenaar41009372013-07-01 22:03:04 +02003399 PyObject *ret = PyBytes_FromString((char *)stringval);
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003400 vim_free(stringval);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003401 return ret;
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003402 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003403 else
3404 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02003405 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003406 N_("unable to get option value"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003407 return NULL;
3408 }
3409 }
3410 else
3411 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003412 PyErr_SET_VIM(N_("internal error: unknown option type"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003413 return NULL;
3414 }
3415}
3416
3417 static int
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01003418OptionsContains(OptionsObject *self, PyObject *keyObject)
3419{
3420 char_u *key;
3421 PyObject *todecref;
3422
3423 if (!(key = StringToChars(keyObject, &todecref)))
3424 return -1;
3425
3426 if (*key == NUL)
3427 {
3428 Py_XDECREF(todecref);
3429 return 0;
3430 }
3431
3432 if (get_option_value_strict(key, NULL, NULL, self->opt_type, NULL))
3433 {
3434 Py_XDECREF(todecref);
3435 return 1;
3436 }
3437 else
3438 {
3439 Py_XDECREF(todecref);
3440 return 0;
3441 }
3442}
3443
3444typedef struct
3445{
3446 void *lastoption;
3447 int opt_type;
3448} optiterinfo_T;
3449
3450 static PyObject *
3451OptionsIterNext(optiterinfo_T **oii)
3452{
3453 char_u *name;
3454
3455 if ((name = option_iter_next(&((*oii)->lastoption), (*oii)->opt_type)))
3456 return PyString_FromString((char *)name);
3457
3458 return NULL;
3459}
3460
3461 static PyObject *
3462OptionsIter(OptionsObject *self)
3463{
3464 optiterinfo_T *oii;
3465
3466 if (!(oii = PyMem_New(optiterinfo_T, 1)))
3467 {
3468 PyErr_NoMemory();
3469 return NULL;
3470 }
3471
3472 oii->opt_type = self->opt_type;
3473 oii->lastoption = NULL;
3474
3475 return IterNew(oii,
3476 (destructorfun) PyMem_Free, (nextfun) OptionsIterNext,
3477 NULL, NULL);
3478}
3479
3480 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02003481set_option_value_err(char_u *key, int numval, char_u *stringval, int opt_flags)
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02003482{
Bram Moolenaarb1443b42019-01-13 23:51:14 +01003483 char *errmsg;
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02003484
3485 if ((errmsg = set_option_value(key, numval, stringval, opt_flags)))
3486 {
3487 if (VimTryEnd())
3488 return FAIL;
Bram Moolenaarb1443b42019-01-13 23:51:14 +01003489 PyErr_SetVim(errmsg);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02003490 return FAIL;
3491 }
3492 return OK;
3493}
3494
3495 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02003496set_option_value_for(
3497 char_u *key,
3498 int numval,
3499 char_u *stringval,
3500 int opt_flags,
3501 int opt_type,
3502 void *from)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003503{
Bram Moolenaar0b9aecc2013-05-21 22:13:41 +02003504 win_T *save_curwin = NULL;
3505 tabpage_T *save_curtab = NULL;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003506 bufref_T save_curbuf;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003507 int set_ret = 0;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003508
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003509 VimTryStart();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003510 switch (opt_type)
3511 {
3512 case SREQ_WIN:
Bram Moolenaar105bc352013-05-17 16:03:57 +02003513 if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
Bram Moolenaard6949742013-06-16 14:18:28 +02003514 win_find_tabpage((win_T *)from), FALSE) == FAIL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003515 {
Bram Moolenaarae38d052014-12-17 14:46:09 +01003516 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003517 if (VimTryEnd())
3518 return -1;
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003519 PyErr_SET_VIM(N_("problem while switching windows"));
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003520 return -1;
3521 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003522 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
3523 restore_win(save_curwin, save_curtab, TRUE);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003524 break;
3525 case SREQ_BUF:
Bram Moolenaar105bc352013-05-17 16:03:57 +02003526 switch_buffer(&save_curbuf, (buf_T *)from);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003527 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02003528 restore_buffer(&save_curbuf);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003529 break;
3530 case SREQ_GLOBAL:
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003531 set_ret = set_option_value_err(key, numval, stringval, opt_flags);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003532 break;
3533 }
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003534 if (set_ret == FAIL)
3535 return -1;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02003536 return VimTryEnd();
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003537}
3538
3539 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003540OptionsAssItem(OptionsObject *self, PyObject *keyObject, PyObject *valObject)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003541{
3542 char_u *key;
3543 int flags;
3544 int opt_flags;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003545 int ret = 0;
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003546 PyObject *todecref;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003547
Bram Moolenaard6e39182013-05-21 18:30:34 +02003548 if (self->Check(self->from))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003549 return -1;
3550
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003551 if (!(key = StringToChars(keyObject, &todecref)))
3552 return -1;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02003553
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003554 if (*key == NUL)
3555 {
3556 RAISE_NO_EMPTY_KEYS;
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02003557 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003558 return -1;
3559 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003560
3561 flags = get_option_value_strict(key, NULL, NULL,
Bram Moolenaard6e39182013-05-21 18:30:34 +02003562 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003563
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003564 if (flags == 0)
3565 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02003566 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003567 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003568 return -1;
3569 }
3570
3571 if (valObject == NULL)
3572 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003573 if (self->opt_type == SREQ_GLOBAL)
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003574 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003575 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003576 N_("unable to unset global option %s"), key);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003577 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003578 return -1;
3579 }
3580 else if (!(flags & SOPT_GLOBAL))
3581 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02003582 PyErr_FORMAT(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003583 N_("unable to unset option %s "
3584 "which does not have global value"), key);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003585 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003586 return -1;
3587 }
3588 else
3589 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003590 unset_global_local_option(key, self->from);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003591 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003592 return 0;
3593 }
3594 }
3595
Bram Moolenaard6e39182013-05-21 18:30:34 +02003596 opt_flags = (self->opt_type ? OPT_LOCAL : OPT_GLOBAL);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003597
3598 if (flags & SOPT_BOOL)
3599 {
Bram Moolenaarb983f752013-05-15 16:11:50 +02003600 int istrue = PyObject_IsTrue(valObject);
Bram Moolenaarc96ebe72013-05-21 22:38:18 +02003601
Bram Moolenaarb983f752013-05-15 16:11:50 +02003602 if (istrue == -1)
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003603 ret = -1;
Bram Moolenaar1bc24282013-05-29 21:37:35 +02003604 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003605 ret = set_option_value_for(key, istrue, NULL,
Bram Moolenaar1bc24282013-05-29 21:37:35 +02003606 opt_flags, self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003607 }
3608 else if (flags & SOPT_NUM)
3609 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02003610 long val;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003611
Bram Moolenaar141be8a2013-06-23 14:16:57 +02003612 if (NumberToLong(valObject, &val, NUMBER_INT))
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003613 {
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003614 Py_XDECREF(todecref);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003615 return -1;
3616 }
3617
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003618 ret = set_option_value_for(key, (int) val, NULL, opt_flags,
Bram Moolenaard6e39182013-05-21 18:30:34 +02003619 self->opt_type, self->from);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003620 }
3621 else
3622 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003623 char_u *val;
Bram Moolenaarc2401d62013-12-07 14:28:43 +01003624 PyObject *todecref2;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003625
Bram Moolenaarc2401d62013-12-07 14:28:43 +01003626 if ((val = StringToChars(valObject, &todecref2)))
3627 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003628 ret = set_option_value_for(key, 0, val, opt_flags,
Bram Moolenaare9ba5162013-05-29 22:02:22 +02003629 self->opt_type, self->from);
Bram Moolenaarc2401d62013-12-07 14:28:43 +01003630 Py_XDECREF(todecref2);
3631 }
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003632 else
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003633 ret = -1;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003634 }
3635
Bram Moolenaar35eacd72013-05-30 22:06:33 +02003636 Py_XDECREF(todecref);
Bram Moolenaar1bc24282013-05-29 21:37:35 +02003637
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003638 return ret;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003639}
3640
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01003641static PySequenceMethods OptionsAsSeq = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003642 0, // sq_length
3643 0, // sq_concat
3644 0, // sq_repeat
3645 0, // sq_item
3646 0, // sq_slice
3647 0, // sq_ass_item
3648 0, // sq_ass_slice
3649 (objobjproc) OptionsContains, // sq_contains
3650 0, // sq_inplace_concat
3651 0, // sq_inplace_repeat
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01003652};
3653
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003654static PyMappingMethods OptionsAsMapping = {
3655 (lenfunc) NULL,
3656 (binaryfunc) OptionsItem,
3657 (objobjargproc) OptionsAssItem,
3658};
3659
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003660// Tabpage object
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003661
3662typedef struct
3663{
3664 PyObject_HEAD
3665 tabpage_T *tab;
3666} TabPageObject;
3667
3668static PyObject *WinListNew(TabPageObject *tabObject);
3669
3670static PyTypeObject TabPageType;
3671
3672 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003673CheckTabPage(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003674{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003675 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003676 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003677 PyErr_SET_VIM(N_("attempt to refer to deleted tab page"));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003678 return -1;
3679 }
3680
3681 return 0;
3682}
3683
3684 static PyObject *
3685TabPageNew(tabpage_T *tab)
3686{
3687 TabPageObject *self;
3688
3689 if (TAB_PYTHON_REF(tab))
3690 {
3691 self = TAB_PYTHON_REF(tab);
3692 Py_INCREF(self);
3693 }
3694 else
3695 {
3696 self = PyObject_NEW(TabPageObject, &TabPageType);
3697 if (self == NULL)
3698 return NULL;
3699 self->tab = tab;
3700 TAB_PYTHON_REF(tab) = self;
3701 }
3702
3703 return (PyObject *)(self);
3704}
3705
3706 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003707TabPageDestructor(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003708{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003709 if (self->tab && self->tab != INVALID_TABPAGE_VALUE)
3710 TAB_PYTHON_REF(self->tab) = NULL;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003711
3712 DESTRUCTOR_FINISH(self);
3713}
3714
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003715static char *TabPageAttrs[] = {
3716 "windows", "number", "vars", "window", "valid",
3717 NULL
3718};
3719
3720 static PyObject *
3721TabPageDir(PyObject *self)
3722{
3723 return ObjectDir(self, TabPageAttrs);
3724}
3725
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003726 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003727TabPageAttrValid(TabPageObject *self, char *name)
3728{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003729 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003730
3731 if (strcmp(name, "valid") != 0)
3732 return NULL;
3733
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003734 ret = ((self->tab == INVALID_TABPAGE_VALUE) ? Py_False : Py_True);
3735 Py_INCREF(ret);
3736 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003737}
3738
3739 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003740TabPageAttr(TabPageObject *self, char *name)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003741{
3742 if (strcmp(name, "windows") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003743 return WinListNew(self);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003744 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003745 return PyLong_FromLong((long) get_tab_number(self->tab));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003746 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003747 return NEW_DICTIONARY(self->tab->tp_vars);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003748 else if (strcmp(name, "window") == 0)
3749 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003750 // For current tab window.c does not bother to set or update tp_curwin
Bram Moolenaard6e39182013-05-21 18:30:34 +02003751 if (self->tab == curtab)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003752 return WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003753 else
Bram Moolenaard6e39182013-05-21 18:30:34 +02003754 return WindowNew(self->tab->tp_curwin, self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003755 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003756 else if (strcmp(name, "__members__") == 0)
3757 return ObjectDir(NULL, TabPageAttrs);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003758 return NULL;
3759}
3760
3761 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003762TabPageRepr(TabPageObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003763{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003764 if (self->tab == INVALID_TABPAGE_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003765 return PyString_FromFormat("<tabpage object (deleted) at %p>", (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003766 else
3767 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003768 int t = get_tab_number(self->tab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003769
3770 if (t == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003771 return PyString_FromFormat("<tabpage object (unknown) at %p>",
3772 (self));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003773 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02003774 return PyString_FromFormat("<tabpage %d>", t - 1);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003775 }
3776}
3777
3778static struct PyMethodDef TabPageMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003779 // name, function, calling, documentation
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003780 {"__dir__", (PyCFunction)TabPageDir, METH_NOARGS, ""},
3781 { NULL, NULL, 0, NULL}
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003782};
3783
3784/*
3785 * Window list object
3786 */
3787
3788static PyTypeObject TabListType;
3789static PySequenceMethods TabListAsSeq;
3790
3791typedef struct
3792{
3793 PyObject_HEAD
3794} TabListObject;
3795
3796 static PyInt
3797TabListLength(PyObject *self UNUSED)
3798{
3799 tabpage_T *tp = first_tabpage;
3800 PyInt n = 0;
3801
3802 while (tp != NULL)
3803 {
3804 ++n;
3805 tp = tp->tp_next;
3806 }
3807
3808 return n;
3809}
3810
3811 static PyObject *
3812TabListItem(PyObject *self UNUSED, PyInt n)
3813{
3814 tabpage_T *tp;
3815
3816 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, --n)
3817 if (n == 0)
3818 return TabPageNew(tp);
3819
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003820 PyErr_SET_STRING(PyExc_IndexError, N_("no such tab page"));
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02003821 return NULL;
3822}
3823
Bram Moolenaar6c85e7f2013-06-23 12:51:32 +02003824/*
3825 * Window object
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003826 */
3827
3828typedef struct
3829{
3830 PyObject_HEAD
3831 win_T *win;
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003832 TabPageObject *tabObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003833} WindowObject;
3834
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003835static PyTypeObject WindowType;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003836
3837 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02003838CheckWindow(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003839{
Bram Moolenaard6e39182013-05-21 18:30:34 +02003840 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003841 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02003842 PyErr_SET_VIM(N_("attempt to refer to deleted window"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02003843 return -1;
3844 }
3845
3846 return 0;
3847}
3848
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003849 static PyObject *
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003850WindowNew(win_T *win, tabpage_T *tab)
Bram Moolenaar971db462013-05-12 18:44:48 +02003851{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003852 /*
3853 * We need to handle deletion of windows underneath us.
Bram Moolenaar971db462013-05-12 18:44:48 +02003854 * If we add a "w_python*_ref" field to the win_T structure,
3855 * then we can get at it in win_free() in vim. We then
3856 * need to create only ONE Python object per window - if
3857 * we try to create a second, just INCREF the existing one
3858 * and return it. The (single) Python object referring to
3859 * the window is stored in "w_python*_ref".
3860 * On a win_free() we set the Python object's win_T* field
3861 * to an invalid value. We trap all uses of a window
3862 * object, and reject them if the win_T* field is invalid.
3863 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003864 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02003865 * w_python_ref and w_python3_ref fields respectively.
3866 */
3867
3868 WindowObject *self;
3869
3870 if (WIN_PYTHON_REF(win))
3871 {
3872 self = WIN_PYTHON_REF(win);
3873 Py_INCREF(self);
3874 }
3875 else
3876 {
Bram Moolenaar774267b2013-05-21 20:51:59 +02003877 self = PyObject_GC_New(WindowObject, &WindowType);
Bram Moolenaar971db462013-05-12 18:44:48 +02003878 if (self == NULL)
3879 return NULL;
3880 self->win = win;
3881 WIN_PYTHON_REF(win) = self;
3882 }
3883
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003884 self->tabObject = ((TabPageObject *)(TabPageNew(tab)));
3885
Bram Moolenaar971db462013-05-12 18:44:48 +02003886 return (PyObject *)(self);
3887}
3888
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003889 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02003890WindowDestructor(WindowObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003891{
Bram Moolenaar774267b2013-05-21 20:51:59 +02003892 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaard6e39182013-05-21 18:30:34 +02003893 if (self->win && self->win != INVALID_WINDOW_VALUE)
3894 WIN_PYTHON_REF(self->win) = NULL;
Bram Moolenaar774267b2013-05-21 20:51:59 +02003895 Py_XDECREF(((PyObject *)(self->tabObject)));
3896 PyObject_GC_Del((void *)(self));
3897}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003898
Bram Moolenaar774267b2013-05-21 20:51:59 +02003899 static int
3900WindowTraverse(WindowObject *self, visitproc visit, void *arg)
3901{
3902 Py_VISIT(((PyObject *)(self->tabObject)));
3903 return 0;
3904}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003905
Bram Moolenaar774267b2013-05-21 20:51:59 +02003906 static int
3907WindowClear(WindowObject *self)
3908{
3909 Py_CLEAR(self->tabObject);
3910 return 0;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02003911}
3912
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003913 static win_T *
3914get_firstwin(TabPageObject *tabObject)
3915{
3916 if (tabObject)
3917 {
3918 if (CheckTabPage(tabObject))
3919 return NULL;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01003920 // For current tab window.c does not bother to set or update tp_firstwin
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003921 else if (tabObject->tab == curtab)
3922 return firstwin;
3923 else
3924 return tabObject->tab->tp_firstwin;
3925 }
3926 else
3927 return firstwin;
3928}
Bram Moolenaare950f992018-06-10 13:55:55 +02003929
3930// Use the same order as in the WindowAttr() function.
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003931static char *WindowAttrs[] = {
Bram Moolenaare950f992018-06-10 13:55:55 +02003932 "buffer",
3933 "cursor",
3934 "height",
3935 "row",
3936 "width",
3937 "col",
3938 "vars",
3939 "options",
3940 "number",
3941 "tabpage",
3942 "valid",
Bram Moolenaardd8aca62013-05-29 22:36:10 +02003943 NULL
3944};
3945
3946 static PyObject *
3947WindowDir(PyObject *self)
3948{
3949 return ObjectDir(self, WindowAttrs);
3950}
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003951
Bram Moolenaar971db462013-05-12 18:44:48 +02003952 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003953WindowAttrValid(WindowObject *self, char *name)
3954{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003955 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003956
3957 if (strcmp(name, "valid") != 0)
3958 return NULL;
3959
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02003960 ret = ((self->win == INVALID_WINDOW_VALUE) ? Py_False : Py_True);
3961 Py_INCREF(ret);
3962 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02003963}
3964
3965 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02003966WindowAttr(WindowObject *self, char *name)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003967{
3968 if (strcmp(name, "buffer") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003969 return (PyObject *)BufferNew(self->win->w_buffer);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003970 else if (strcmp(name, "cursor") == 0)
3971 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003972 pos_T *pos = &self->win->w_cursor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003973
3974 return Py_BuildValue("(ll)", (long)(pos->lnum), (long)(pos->col));
3975 }
3976 else if (strcmp(name, "height") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003977 return PyLong_FromLong((long)(self->win->w_height));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003978 else if (strcmp(name, "row") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003979 return PyLong_FromLong((long)(self->win->w_winrow));
Bram Moolenaar4d1da492013-04-24 13:39:15 +02003980 else if (strcmp(name, "width") == 0)
Bram Moolenaar02631462017-09-22 15:20:32 +02003981 return PyLong_FromLong((long)(self->win->w_width));
Bram Moolenaar4e5dfb52013-05-12 19:30:31 +02003982 else if (strcmp(name, "col") == 0)
Bram Moolenaar53f81742017-09-22 14:35:51 +02003983 return PyLong_FromLong((long)(self->win->w_wincol));
Bram Moolenaar230bb3f2013-04-24 14:07:45 +02003984 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02003985 return NEW_DICTIONARY(self->win->w_vars);
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02003986 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003987 return OptionsNew(SREQ_WIN, self->win, (checkfun) CheckWindow,
3988 (PyObject *) self);
Bram Moolenaar6d216452013-05-12 19:00:41 +02003989 else if (strcmp(name, "number") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003990 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003991 if (CheckTabPage(self->tabObject))
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003992 return NULL;
3993 return PyLong_FromLong((long)
Bram Moolenaard6e39182013-05-21 18:30:34 +02003994 get_win_number(self->win, get_firstwin(self->tabObject)));
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02003995 }
3996 else if (strcmp(name, "tabpage") == 0)
3997 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02003998 Py_INCREF(self->tabObject);
3999 return (PyObject *)(self->tabObject);
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02004000 }
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004001 else if (strcmp(name, "__members__") == 0)
4002 return ObjectDir(NULL, WindowAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004003 else
4004 return NULL;
4005}
4006
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004007 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004008WindowSetattr(WindowObject *self, char *name, PyObject *valObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004009{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004010 if (CheckWindow(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004011 return -1;
4012
4013 if (strcmp(name, "buffer") == 0)
4014 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004015 PyErr_SET_STRING(PyExc_TypeError, N_("readonly attribute: buffer"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004016 return -1;
4017 }
4018 else if (strcmp(name, "cursor") == 0)
4019 {
4020 long lnum;
4021 long col;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004022
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004023 if (!PyArg_Parse(valObject, "(ll)", &lnum, &col))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004024 return -1;
4025
Bram Moolenaard6e39182013-05-21 18:30:34 +02004026 if (lnum <= 0 || lnum > self->win->w_buffer->b_ml.ml_line_count)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004027 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004028 PyErr_SET_VIM(N_("cursor position outside buffer"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004029 return -1;
4030 }
4031
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004032 // Check for keyboard interrupts
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004033 if (VimCheckInterrupt())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004034 return -1;
4035
Bram Moolenaard6e39182013-05-21 18:30:34 +02004036 self->win->w_cursor.lnum = lnum;
4037 self->win->w_cursor.col = col;
Bram Moolenaar53901442018-07-25 22:02:36 +02004038 self->win->w_set_curswant = TRUE;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004039 self->win->w_cursor.coladd = 0;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004040 // When column is out of range silently correct it.
Bram Moolenaard6e39182013-05-21 18:30:34 +02004041 check_cursor_col_win(self->win);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004042
Bram Moolenaar03a807a2011-07-07 15:08:58 +02004043 update_screen(VALID);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004044 return 0;
4045 }
4046 else if (strcmp(name, "height") == 0)
4047 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004048 long height;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004049 win_T *savewin;
4050
Bram Moolenaardee2e312013-06-23 16:35:47 +02004051 if (NumberToLong(valObject, &height, NUMBER_INT|NUMBER_UNSIGNED))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004052 return -1;
4053
4054#ifdef FEAT_GUI
4055 need_mouse_correct = TRUE;
4056#endif
4057 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004058 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004059
4060 VimTryStart();
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004061 win_setheight((int) height);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004062 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004063 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004064 return -1;
4065
4066 return 0;
4067 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004068 else if (strcmp(name, "width") == 0)
4069 {
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004070 long width;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004071 win_T *savewin;
4072
Bram Moolenaardee2e312013-06-23 16:35:47 +02004073 if (NumberToLong(valObject, &width, NUMBER_INT|NUMBER_UNSIGNED))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004074 return -1;
4075
4076#ifdef FEAT_GUI
4077 need_mouse_correct = TRUE;
4078#endif
4079 savewin = curwin;
Bram Moolenaard6e39182013-05-21 18:30:34 +02004080 curwin = self->win;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004081
4082 VimTryStart();
Bram Moolenaar141be8a2013-06-23 14:16:57 +02004083 win_setwidth((int) width);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004084 curwin = savewin;
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004085 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004086 return -1;
4087
4088 return 0;
4089 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004090 else
4091 {
4092 PyErr_SetString(PyExc_AttributeError, name);
4093 return -1;
4094 }
4095}
4096
4097 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004098WindowRepr(WindowObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004099{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004100 if (self->win == INVALID_WINDOW_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004101 return PyString_FromFormat("<window object (deleted) at %p>", (self));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004102 else
4103 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02004104 int w = get_win_number(self->win, firstwin);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004105
Bram Moolenaar6d216452013-05-12 19:00:41 +02004106 if (w == 0)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004107 return PyString_FromFormat("<window object (unknown) at %p>",
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004108 (self));
4109 else
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02004110 return PyString_FromFormat("<window %d>", w - 1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004111 }
4112}
4113
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004114static struct PyMethodDef WindowMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004115 // name, function, calling, documentation
Bram Moolenaardd8aca62013-05-29 22:36:10 +02004116 {"__dir__", (PyCFunction)WindowDir, METH_NOARGS, ""},
4117 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004118};
4119
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004120/*
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004121 * Window list object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004122 */
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004123
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004124static PyTypeObject WinListType;
4125static PySequenceMethods WinListAsSeq;
4126
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004127typedef struct
4128{
4129 PyObject_HEAD
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004130 TabPageObject *tabObject;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004131} WinListObject;
4132
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004133 static PyObject *
4134WinListNew(TabPageObject *tabObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004135{
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004136 WinListObject *self;
4137
4138 self = PyObject_NEW(WinListObject, &WinListType);
4139 self->tabObject = tabObject;
4140 Py_INCREF(tabObject);
4141
4142 return (PyObject *)(self);
4143}
4144
4145 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02004146WinListDestructor(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004147{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004148 TabPageObject *tabObject = self->tabObject;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004149
4150 if (tabObject)
Bram Moolenaar425154d2013-05-24 18:58:43 +02004151 {
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004152 Py_DECREF((PyObject *)(tabObject));
Bram Moolenaar425154d2013-05-24 18:58:43 +02004153 }
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004154
4155 DESTRUCTOR_FINISH(self);
4156}
4157
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004158 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02004159WinListLength(WinListObject *self)
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004160{
4161 win_T *w;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004162 PyInt n = 0;
4163
Bram Moolenaard6e39182013-05-21 18:30:34 +02004164 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004165 return -1;
4166
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004167 while (w != NULL)
4168 {
4169 ++n;
4170 w = W_NEXT(w);
4171 }
4172
4173 return n;
4174}
4175
4176 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02004177WinListItem(WinListObject *self, PyInt n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004178{
4179 win_T *w;
4180
Bram Moolenaard6e39182013-05-21 18:30:34 +02004181 if (!(w = get_firstwin(self->tabObject)))
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02004182 return NULL;
4183
4184 for (; w != NULL; w = W_NEXT(w), --n)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004185 if (n == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02004186 return WindowNew(w, self->tabObject? self->tabObject->tab: curtab);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004187
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004188 PyErr_SET_STRING(PyExc_IndexError, N_("no such window"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004189 return NULL;
4190}
4191
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004192/*
4193 * Convert a Python string into a Vim line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004194 *
4195 * The result is in allocated memory. All internal nulls are replaced by
4196 * newline characters. It is an error for the string to contain newline
4197 * characters.
4198 *
4199 * On errors, the Python exception data is set, and NULL is returned.
4200 */
4201 static char *
4202StringToLine(PyObject *obj)
4203{
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004204 char *str;
4205 char *save;
4206 PyObject *bytes = NULL;
Bram Moolenaardee2e312013-06-23 16:35:47 +02004207 Py_ssize_t len = 0;
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004208 PyInt i;
4209 char *p;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004210
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004211 if (PyBytes_Check(obj))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004212 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004213 if (PyBytes_AsStringAndSize(obj, &str, &len) == -1
4214 || str == NULL)
4215 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004216 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004217 else if (PyUnicode_Check(obj))
4218 {
4219 if (!(bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL)))
4220 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004221
Bram Moolenaardaa27022013-06-24 22:33:30 +02004222 if (PyBytes_AsStringAndSize(bytes, &str, &len) == -1
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004223 || str == NULL)
4224 {
4225 Py_DECREF(bytes);
4226 return NULL;
4227 }
4228 }
Bram Moolenaardaa27022013-06-24 22:33:30 +02004229 else
4230 {
4231#if PY_MAJOR_VERSION < 3
4232 PyErr_FORMAT(PyExc_TypeError,
4233 N_("expected str() or unicode() instance, but got %s"),
4234 Py_TYPE_NAME(obj));
4235#else
4236 PyErr_FORMAT(PyExc_TypeError,
4237 N_("expected bytes() or str() instance, but got %s"),
4238 Py_TYPE_NAME(obj));
4239#endif
4240 return NULL;
4241 }
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004242
4243 /*
4244 * Error checking: String must not contain newlines, as we
4245 * are replacing a single line, and we must replace it with
4246 * a single line.
4247 * A trailing newline is removed, so that append(f.readlines()) works.
4248 */
4249 p = memchr(str, '\n', len);
4250 if (p != NULL)
4251 {
4252 if (p == str + len - 1)
4253 --len;
4254 else
4255 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004256 PyErr_SET_VIM(N_("string cannot contain newlines"));
Bram Moolenaar841fbd22013-06-23 14:37:07 +02004257 Py_XDECREF(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004258 return NULL;
4259 }
4260 }
4261
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004262 /*
4263 * Create a copy of the string, with internal nulls replaced by
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004264 * newline characters, as is the vim convention.
4265 */
Bram Moolenaarc799fe22019-05-28 23:08:19 +02004266 save = alloc(len+1);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004267 if (save == NULL)
4268 {
4269 PyErr_NoMemory();
Bram Moolenaar841fbd22013-06-23 14:37:07 +02004270 Py_XDECREF(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004271 return NULL;
4272 }
4273
4274 for (i = 0; i < len; ++i)
4275 {
4276 if (str[i] == '\0')
4277 save[i] = '\n';
4278 else
4279 save[i] = str[i];
4280 }
4281
4282 save[i] = '\0';
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004283 Py_XDECREF(bytes); // Python 2 does nothing here
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004284
4285 return save;
4286}
4287
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004288/*
4289 * Get a line from the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004290 * in Vim format (1-based). The line is returned as a Python
4291 * string object.
4292 */
4293 static PyObject *
4294GetBufferLine(buf_T *buf, PyInt n)
4295{
4296 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
4297}
4298
4299
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004300/*
4301 * Get a list of lines from the specified buffer. The line numbers
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004302 * are in Vim format (1-based). The range is from lo up to, but not
4303 * including, hi. The list is returned as a Python list of string objects.
4304 */
4305 static PyObject *
4306GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
4307{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004308 PyInt i;
4309 PyInt n = hi - lo;
4310 PyObject *list = PyList_New(n);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004311
4312 if (list == NULL)
4313 return NULL;
4314
4315 for (i = 0; i < n; ++i)
4316 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004317 PyObject *string = LineToString(
4318 (char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004319
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004320 // Error check - was the Python string creation OK?
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004321 if (string == NULL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004322 {
4323 Py_DECREF(list);
4324 return NULL;
4325 }
4326
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004327 PyList_SET_ITEM(list, i, string);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004328 }
4329
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004330 // The ownership of the Python list is passed to the caller (ie,
4331 // the caller should Py_DECREF() the object when it is finished
4332 // with it).
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004333
4334 return list;
4335}
4336
4337/*
4338 * Check if deleting lines made the cursor position invalid.
4339 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
4340 * deleted).
4341 */
4342 static void
4343py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
4344{
4345 if (curwin->w_cursor.lnum >= lo)
4346 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004347 // Adjust the cursor position if it's in/after the changed
4348 // lines.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004349 if (curwin->w_cursor.lnum >= hi)
4350 {
4351 curwin->w_cursor.lnum += extra;
4352 check_cursor_col();
4353 }
4354 else if (extra < 0)
4355 {
4356 curwin->w_cursor.lnum = lo;
4357 check_cursor();
4358 }
4359 else
4360 check_cursor_col();
4361 changed_cline_bef_curs();
4362 }
4363 invalidate_botline();
4364}
4365
Bram Moolenaar19e60942011-06-19 00:27:51 +02004366/*
4367 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004368 * in Vim format (1-based). The replacement line is given as
4369 * a Python string object. The object is checked for validity
4370 * and correct format. Errors are returned as a value of FAIL.
4371 * The return value is OK on success.
4372 * If OK is returned and len_change is not NULL, *len_change
4373 * is set to the change in the buffer length.
4374 */
4375 static int
4376SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
4377{
Bram Moolenaar45e5fd12017-06-04 14:58:02 +02004378 bufref_T save_curbuf = {NULL, 0, 0};
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004379 win_T *save_curwin = NULL;
4380 tabpage_T *save_curtab = NULL;
4381
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004382 // First of all, we check the type of the supplied Python object.
4383 // There are three cases:
4384 // 1. NULL, or None - this is a deletion.
4385 // 2. A string - this is a replacement.
4386 // 3. Anything else - this is an error.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004387 if (line == Py_None || line == NULL)
4388 {
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004389 PyErr_Clear();
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004390 switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004391
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004392 VimTryStart();
4393
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004394 if (u_savedel((linenr_T)n, 1L) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02004395 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004396 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004397 RAISE_DELETE_LINE_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004398 else
4399 {
Bram Moolenaar63dbfd32019-03-23 17:41:59 +01004400 if (buf == curbuf && (save_curwin != NULL
4401 || save_curbuf.br_buf == NULL))
4402 // Using an existing window for the buffer, adjust the cursor
4403 // position.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004404 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004405 if (save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004406 // Only adjust marks if we managed to switch to a window that
4407 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004408 deleted_lines_mark((linenr_T)n, 1L);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004409 }
4410
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004411 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004412
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004413 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004414 return FAIL;
4415
4416 if (len_change)
4417 *len_change = -1;
4418
4419 return OK;
4420 }
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004421 else if (PyBytes_Check(line) || PyUnicode_Check(line))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004422 {
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004423 char *save = StringToLine(line);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004424
4425 if (save == NULL)
4426 return FAIL;
4427
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004428 VimTryStart();
4429
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004430 // We do not need to free "save" if ml_replace() consumes it.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004431 PyErr_Clear();
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004432 switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004433
4434 if (u_savesub((linenr_T)n) == FAIL)
4435 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02004436 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004437 vim_free(save);
4438 }
4439 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
4440 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004441 RAISE_REPLACE_LINE_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004442 vim_free(save);
4443 }
4444 else
4445 changed_bytes((linenr_T)n, 0);
4446
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004447 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004448
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004449 // Check that the cursor is not beyond the end of the line now.
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004450 if (buf == curbuf)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004451 check_cursor_col();
4452
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004453 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004454 return FAIL;
4455
4456 if (len_change)
4457 *len_change = 0;
4458
4459 return OK;
4460 }
4461 else
4462 {
4463 PyErr_BadArgument();
4464 return FAIL;
4465 }
4466}
4467
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004468/*
4469 * Replace a range of lines in the specified buffer. The line numbers are in
Bram Moolenaar19e60942011-06-19 00:27:51 +02004470 * Vim format (1-based). The range is from lo up to, but not including, hi.
4471 * The replacement lines are given as a Python list of string objects. The
4472 * list is checked for validity and correct format. Errors are returned as a
4473 * value of FAIL. The return value is OK on success.
4474 * If OK is returned and len_change is not NULL, *len_change
4475 * is set to the change in the buffer length.
4476 */
4477 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004478SetBufferLineList(
4479 buf_T *buf,
4480 PyInt lo,
4481 PyInt hi,
4482 PyObject *list,
4483 PyInt *len_change)
Bram Moolenaar19e60942011-06-19 00:27:51 +02004484{
Bram Moolenaar45e5fd12017-06-04 14:58:02 +02004485 bufref_T save_curbuf = {NULL, 0, 0};
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004486 win_T *save_curwin = NULL;
4487 tabpage_T *save_curtab = NULL;
4488
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004489 // First of all, we check the type of the supplied Python object.
4490 // There are three cases:
4491 // 1. NULL, or None - this is a deletion.
4492 // 2. A list - this is a replacement.
4493 // 3. Anything else - this is an error.
Bram Moolenaar19e60942011-06-19 00:27:51 +02004494 if (list == Py_None || list == NULL)
4495 {
4496 PyInt i;
4497 PyInt n = (int)(hi - lo);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004498
4499 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004500 VimTryStart();
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004501 switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004502
4503 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02004504 RAISE_UNDO_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004505 else
4506 {
4507 for (i = 0; i < n; ++i)
4508 {
4509 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
4510 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004511 RAISE_DELETE_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004512 break;
4513 }
4514 }
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004515 if (buf == curbuf && (save_curwin != NULL
4516 || save_curbuf.br_buf == NULL))
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004517 // Using an existing window for the buffer, adjust the cursor
4518 // position.
Bram Moolenaar19e60942011-06-19 00:27:51 +02004519 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004520 if (save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004521 // Only adjust marks if we managed to switch to a window that
4522 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004523 deleted_lines_mark((linenr_T)lo, (long)i);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004524 }
4525
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004526 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004527
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004528 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02004529 return FAIL;
4530
4531 if (len_change)
4532 *len_change = -n;
4533
4534 return OK;
4535 }
4536 else if (PyList_Check(list))
4537 {
4538 PyInt i;
4539 PyInt new_len = PyList_Size(list);
4540 PyInt old_len = hi - lo;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004541 PyInt extra = 0; // lines added to text, can be negative
Bram Moolenaar19e60942011-06-19 00:27:51 +02004542 char **array;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004543
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004544 if (new_len == 0) // avoid allocating zero bytes
Bram Moolenaar19e60942011-06-19 00:27:51 +02004545 array = NULL;
4546 else
4547 {
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004548 array = PyMem_New(char *, new_len);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004549 if (array == NULL)
4550 {
4551 PyErr_NoMemory();
4552 return FAIL;
4553 }
4554 }
4555
4556 for (i = 0; i < new_len; ++i)
4557 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004558 PyObject *line;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004559
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004560 if (!(line = PyList_GetItem(list, i)) ||
4561 !(array[i] = StringToLine(line)))
Bram Moolenaar19e60942011-06-19 00:27:51 +02004562 {
4563 while (i)
4564 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004565 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004566 return FAIL;
4567 }
4568 }
4569
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004570 VimTryStart();
Bram Moolenaar19e60942011-06-19 00:27:51 +02004571 PyErr_Clear();
Bram Moolenaar105bc352013-05-17 16:03:57 +02004572
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004573 // START of region without "return". Must call restore_buffer()!
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004574 switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004575
4576 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02004577 RAISE_UNDO_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004578
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004579 // If the size of the range is reducing (ie, new_len < old_len) we
4580 // need to delete some old_len. We do this at the start, by
4581 // repeatedly deleting line "lo".
Bram Moolenaar19e60942011-06-19 00:27:51 +02004582 if (!PyErr_Occurred())
4583 {
4584 for (i = 0; i < old_len - new_len; ++i)
4585 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
4586 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004587 RAISE_DELETE_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004588 break;
4589 }
4590 extra -= i;
4591 }
4592
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004593 // For as long as possible, replace the existing old_len with the
4594 // new old_len. This is a more efficient operation, as it requires
4595 // less memory allocation and freeing.
Bram Moolenaar19e60942011-06-19 00:27:51 +02004596 if (!PyErr_Occurred())
4597 {
4598 for (i = 0; i < old_len && i < new_len; ++i)
4599 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
4600 == FAIL)
4601 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004602 RAISE_REPLACE_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004603 break;
4604 }
4605 }
4606 else
4607 i = 0;
4608
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004609 // Now we may need to insert the remaining new old_len. If we do, we
4610 // must free the strings as we finish with them (we can't pass the
4611 // responsibility to vim in this case).
Bram Moolenaar19e60942011-06-19 00:27:51 +02004612 if (!PyErr_Occurred())
4613 {
4614 while (i < new_len)
4615 {
4616 if (ml_append((linenr_T)(lo + i - 1),
4617 (char_u *)array[i], 0, FALSE) == FAIL)
4618 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004619 RAISE_INSERT_LINE_FAIL;
Bram Moolenaar19e60942011-06-19 00:27:51 +02004620 break;
4621 }
4622 vim_free(array[i]);
4623 ++i;
4624 ++extra;
4625 }
4626 }
4627
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004628 // Free any left-over old_len, as a result of an error
Bram Moolenaar19e60942011-06-19 00:27:51 +02004629 while (i < new_len)
4630 {
4631 vim_free(array[i]);
4632 ++i;
4633 }
4634
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004635 // Free the array of old_len. All of its contents have now
4636 // been dealt with (either freed, or the responsibility passed
4637 // to vim.
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004638 PyMem_Free(array);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004639
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004640 // Adjust marks. Invalidate any which lie in the
4641 // changed range, and move any in the remainder of the buffer.
4642 // Only adjust marks if we managed to switch to a window that holds
4643 // the buffer, otherwise line numbers will be invalid.
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004644 if (save_curbuf.br_buf == NULL)
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004645 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
Bram Moolenaar19e60942011-06-19 00:27:51 +02004646 (long)MAXLNUM, (long)extra);
4647 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
4648
Bram Moolenaar63dbfd32019-03-23 17:41:59 +01004649 if (buf == curbuf && (save_curwin != NULL
4650 || save_curbuf.br_buf == NULL))
4651 // Using an existing window for the buffer, adjust the cursor
4652 // position.
Bram Moolenaar19e60942011-06-19 00:27:51 +02004653 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
4654
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004655 // END of region without "return".
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004656 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
Bram Moolenaar19e60942011-06-19 00:27:51 +02004657
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004658 if (VimTryEnd())
Bram Moolenaar19e60942011-06-19 00:27:51 +02004659 return FAIL;
4660
4661 if (len_change)
4662 *len_change = new_len - old_len;
4663
4664 return OK;
4665 }
4666 else
4667 {
4668 PyErr_BadArgument();
4669 return FAIL;
4670 }
4671}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004672
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004673/*
4674 * Insert a number of lines into the specified buffer after the specified line.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004675 * The line number is in Vim format (1-based). The lines to be inserted are
4676 * given as a Python list of string objects or as a single string. The lines
4677 * to be added are checked for validity and correct format. Errors are
4678 * returned as a value of FAIL. The return value is OK on success.
4679 * If OK is returned and len_change is not NULL, *len_change
4680 * is set to the change in the buffer length.
4681 */
4682 static int
4683InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
4684{
Bram Moolenaar45e5fd12017-06-04 14:58:02 +02004685 bufref_T save_curbuf = {NULL, 0, 0};
Bram Moolenaar95064ec2013-07-17 17:15:25 +02004686 win_T *save_curwin = NULL;
Bram Moolenaar95064ec2013-07-17 17:15:25 +02004687 tabpage_T *save_curtab = NULL;
4688
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004689 // First of all, we check the type of the supplied Python object.
4690 // It must be a string or a list, or the call is in error.
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02004691 if (PyBytes_Check(lines) || PyUnicode_Check(lines))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004692 {
Bram Moolenaar95064ec2013-07-17 17:15:25 +02004693 char *str = StringToLine(lines);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004694
4695 if (str == NULL)
4696 return FAIL;
4697
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004698 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004699 VimTryStart();
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004700 switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004701
Bram Moolenaar95064ec2013-07-17 17:15:25 +02004702 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02004703 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004704 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004705 RAISE_INSERT_LINE_FAIL;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004706 else if (save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004707 // Only adjust marks if we managed to switch to a window that
4708 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004709 appended_lines_mark((linenr_T)n, 1L);
4710
4711 vim_free(str);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004712 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004713 update_screen(VALID);
4714
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004715 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004716 return FAIL;
4717
4718 if (len_change)
4719 *len_change = 1;
4720
4721 return OK;
4722 }
4723 else if (PyList_Check(lines))
4724 {
4725 PyInt i;
4726 PyInt size = PyList_Size(lines);
4727 char **array;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004728
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004729 array = PyMem_New(char *, size);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004730 if (array == NULL)
4731 {
4732 PyErr_NoMemory();
4733 return FAIL;
4734 }
4735
4736 for (i = 0; i < size; ++i)
4737 {
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004738 PyObject *line;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004739
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02004740 if (!(line = PyList_GetItem(lines, i)) ||
4741 !(array[i] = StringToLine(line)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004742 {
4743 while (i)
4744 vim_free(array[--i]);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004745 PyMem_Free(array);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004746 return FAIL;
4747 }
4748 }
4749
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004750 PyErr_Clear();
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004751 VimTryStart();
Bram Moolenaaraf003f62013-07-24 17:11:46 +02004752 switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004753
4754 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
Bram Moolenaarc476e522013-06-23 13:46:40 +02004755 RAISE_UNDO_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004756 else
4757 {
4758 for (i = 0; i < size; ++i)
4759 {
4760 if (ml_append((linenr_T)(n + i),
4761 (char_u *)array[i], 0, FALSE) == FAIL)
4762 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004763 RAISE_INSERT_LINE_FAIL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004764
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004765 // Free the rest of the lines
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004766 while (i < size)
4767 vim_free(array[i++]);
4768
4769 break;
4770 }
4771 vim_free(array[i]);
4772 }
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004773 if (i > 0 && save_curbuf.br_buf == NULL)
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004774 // Only adjust marks if we managed to switch to a window that
4775 // holds the buffer, otherwise line numbers will be invalid.
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004776 appended_lines_mark((linenr_T)n, (long)i);
4777 }
4778
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004779 // Free the array of lines. All of its contents have now
4780 // been freed.
Bram Moolenaare9ba5162013-05-29 22:02:22 +02004781 PyMem_Free(array);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02004782 restore_win_for_buf(save_curwin, save_curtab, &save_curbuf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004783
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004784 update_screen(VALID);
4785
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02004786 if (VimTryEnd())
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004787 return FAIL;
4788
4789 if (len_change)
4790 *len_change = size;
4791
4792 return OK;
4793 }
4794 else
4795 {
4796 PyErr_BadArgument();
4797 return FAIL;
4798 }
4799}
4800
4801/*
4802 * Common routines for buffers and line ranges
4803 * -------------------------------------------
4804 */
4805
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004806typedef struct
4807{
4808 PyObject_HEAD
4809 buf_T *buf;
4810} BufferObject;
4811
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004812 static int
Bram Moolenaard6e39182013-05-21 18:30:34 +02004813CheckBuffer(BufferObject *self)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004814{
Bram Moolenaard6e39182013-05-21 18:30:34 +02004815 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004816 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004817 PyErr_SET_VIM(N_("attempt to refer to deleted buffer"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004818 return -1;
4819 }
4820
4821 return 0;
4822}
4823
4824 static PyObject *
4825RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
4826{
4827 if (CheckBuffer(self))
4828 return NULL;
4829
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004830 if (end == -1)
4831 end = self->buf->b_ml.ml_line_count;
4832
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004833 if (n < 0)
4834 n += end - start + 1;
4835
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004836 if (n < 0 || n > end - start)
4837 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004838 PyErr_SET_STRING(PyExc_IndexError, N_("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004839 return NULL;
4840 }
4841
4842 return GetBufferLine(self->buf, n+start);
4843}
4844
4845 static PyObject *
4846RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
4847{
4848 PyInt size;
4849
4850 if (CheckBuffer(self))
4851 return NULL;
4852
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004853 if (end == -1)
4854 end = self->buf->b_ml.ml_line_count;
4855
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004856 size = end - start + 1;
4857
4858 if (lo < 0)
4859 lo = 0;
4860 else if (lo > size)
4861 lo = size;
4862 if (hi < 0)
4863 hi = 0;
4864 if (hi < lo)
4865 hi = lo;
4866 else if (hi > size)
4867 hi = size;
4868
4869 return GetBufferLineList(self->buf, lo+start, hi+start);
4870}
4871
4872 static PyInt
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004873RBAsItem(
4874 BufferObject *self,
4875 PyInt n,
4876 PyObject *valObject,
4877 PyInt start,
4878 PyInt end,
4879 PyInt *new_end)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004880{
4881 PyInt len_change;
4882
4883 if (CheckBuffer(self))
4884 return -1;
4885
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004886 if (end == -1)
4887 end = self->buf->b_ml.ml_line_count;
4888
Bram Moolenaarbd80f352013-05-12 21:16:23 +02004889 if (n < 0)
4890 n += end - start + 1;
4891
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004892 if (n < 0 || n > end - start)
4893 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004894 PyErr_SET_STRING(PyExc_IndexError, N_("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004895 return -1;
4896 }
4897
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004898 if (SetBufferLine(self->buf, n+start, valObject, &len_change) == FAIL)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004899 return -1;
4900
4901 if (new_end)
4902 *new_end = end + len_change;
4903
4904 return 0;
4905}
4906
Bram Moolenaar19e60942011-06-19 00:27:51 +02004907 static PyInt
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004908RBAsSlice(
4909 BufferObject *self,
4910 PyInt lo,
4911 PyInt hi,
4912 PyObject *valObject,
4913 PyInt start,
4914 PyInt end,
4915 PyInt *new_end)
Bram Moolenaar19e60942011-06-19 00:27:51 +02004916{
4917 PyInt size;
4918 PyInt len_change;
4919
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004920 // Self must be a valid buffer
Bram Moolenaar19e60942011-06-19 00:27:51 +02004921 if (CheckBuffer(self))
4922 return -1;
4923
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004924 if (end == -1)
4925 end = self->buf->b_ml.ml_line_count;
4926
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004927 // Sort out the slice range
Bram Moolenaar19e60942011-06-19 00:27:51 +02004928 size = end - start + 1;
4929
4930 if (lo < 0)
4931 lo = 0;
4932 else if (lo > size)
4933 lo = size;
4934 if (hi < 0)
4935 hi = 0;
4936 if (hi < lo)
4937 hi = lo;
4938 else if (hi > size)
4939 hi = size;
4940
4941 if (SetBufferLineList(self->buf, lo + start, hi + start,
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004942 valObject, &len_change) == FAIL)
Bram Moolenaar19e60942011-06-19 00:27:51 +02004943 return -1;
4944
4945 if (new_end)
4946 *new_end = end + len_change;
4947
4948 return 0;
4949}
4950
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004951
4952 static PyObject *
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02004953RBAppend(
4954 BufferObject *self,
4955 PyObject *args,
4956 PyInt start,
4957 PyInt end,
4958 PyInt *new_end)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004959{
4960 PyObject *lines;
4961 PyInt len_change;
4962 PyInt max;
4963 PyInt n;
4964
4965 if (CheckBuffer(self))
4966 return NULL;
4967
Bram Moolenaar8f1723d2013-05-12 20:36:14 +02004968 if (end == -1)
4969 end = self->buf->b_ml.ml_line_count;
4970
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004971 max = n = end - start + 1;
4972
4973 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
4974 return NULL;
4975
4976 if (n < 0 || n > max)
4977 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02004978 PyErr_SET_STRING(PyExc_IndexError, N_("line number out of range"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004979 return NULL;
4980 }
4981
4982 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
4983 return NULL;
4984
4985 if (new_end)
4986 *new_end = end + len_change;
4987
4988 Py_INCREF(Py_None);
4989 return Py_None;
4990}
4991
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01004992// Range object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004993
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004994static PyTypeObject RangeType;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02004995static PySequenceMethods RangeAsSeq;
4996static PyMappingMethods RangeAsMapping;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02004997
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02004998typedef struct
4999{
5000 PyObject_HEAD
5001 BufferObject *buf;
5002 PyInt start;
5003 PyInt end;
5004} RangeObject;
5005
5006 static PyObject *
5007RangeNew(buf_T *buf, PyInt start, PyInt end)
5008{
5009 BufferObject *bufr;
5010 RangeObject *self;
Bram Moolenaar774267b2013-05-21 20:51:59 +02005011 self = PyObject_GC_New(RangeObject, &RangeType);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005012 if (self == NULL)
5013 return NULL;
5014
5015 bufr = (BufferObject *)BufferNew(buf);
5016 if (bufr == NULL)
5017 {
5018 Py_DECREF(self);
5019 return NULL;
5020 }
5021 Py_INCREF(bufr);
5022
5023 self->buf = bufr;
5024 self->start = start;
5025 self->end = end;
5026
5027 return (PyObject *)(self);
5028}
5029
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005030 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02005031RangeDestructor(RangeObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005032{
Bram Moolenaar774267b2013-05-21 20:51:59 +02005033 PyObject_GC_UnTrack((void *)(self));
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005034 Py_XDECREF(self->buf);
Bram Moolenaar774267b2013-05-21 20:51:59 +02005035 PyObject_GC_Del((void *)(self));
5036}
5037
5038 static int
5039RangeTraverse(RangeObject *self, visitproc visit, void *arg)
5040{
5041 Py_VISIT(((PyObject *)(self->buf)));
5042 return 0;
5043}
5044
5045 static int
5046RangeClear(RangeObject *self)
5047{
5048 Py_CLEAR(self->buf);
5049 return 0;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005050}
5051
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005052 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02005053RangeLength(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005054{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005055 // HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION?
Bram Moolenaard6e39182013-05-21 18:30:34 +02005056 if (CheckBuffer(self->buf))
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005057 return -1; // ???
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005058
Bram Moolenaard6e39182013-05-21 18:30:34 +02005059 return (self->end - self->start + 1);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005060}
5061
5062 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005063RangeItem(RangeObject *self, PyInt n)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005064{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005065 return RBItem(self->buf, n, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005066}
5067
5068 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005069RangeSlice(RangeObject *self, PyInt lo, PyInt hi)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005070{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005071 return RBSlice(self->buf, lo, hi, self->start, self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005072}
5073
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005074static char *RangeAttrs[] = {
5075 "start", "end",
5076 NULL
5077};
5078
5079 static PyObject *
5080RangeDir(PyObject *self)
5081{
5082 return ObjectDir(self, RangeAttrs);
5083}
5084
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005085 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005086RangeAppend(RangeObject *self, PyObject *args)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005087{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005088 return RBAppend(self->buf, args, self->start, self->end, &self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005089}
5090
5091 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005092RangeRepr(RangeObject *self)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005093{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005094 if (self->buf->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005095 return PyString_FromFormat("<range object (for deleted buffer) at %p>",
5096 (self));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005097 else
5098 {
Bram Moolenaard6e39182013-05-21 18:30:34 +02005099 char *name = (char *)self->buf->buf->b_fname;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005100
5101 if (name == NULL)
5102 name = "";
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005103
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005104 return PyString_FromFormat("<range %s (%d:%d)>",
Bram Moolenaarf62d9422013-05-30 19:01:24 +02005105 name, (int)self->start, (int)self->end);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005106 }
5107}
5108
5109static struct PyMethodDef RangeMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005110 // name, function, calling, documentation
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02005111 {"append", (PyCFunction)RangeAppend, METH_VARARGS, "Append data to the Vim range" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005112 {"__dir__", (PyCFunction)RangeDir, METH_NOARGS, ""},
5113 { NULL, NULL, 0, NULL}
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005114};
5115
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005116static PyTypeObject BufferType;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005117static PySequenceMethods BufferAsSeq;
5118static PyMappingMethods BufferAsMapping;
5119
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005120 static PyObject *
Bram Moolenaar971db462013-05-12 18:44:48 +02005121BufferNew(buf_T *buf)
5122{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005123 /*
5124 * We need to handle deletion of buffers underneath us.
Bram Moolenaar971db462013-05-12 18:44:48 +02005125 * If we add a "b_python*_ref" field to the buf_T structure,
5126 * then we can get at it in buf_freeall() in vim. We then
5127 * need to create only ONE Python object per buffer - if
5128 * we try to create a second, just INCREF the existing one
5129 * and return it. The (single) Python object referring to
5130 * the buffer is stored in "b_python*_ref".
5131 * Question: what to do on a buf_freeall(). We'll probably
5132 * have to either delete the Python object (DECREF it to
5133 * zero - a bad idea, as it leaves dangling refs!) or
5134 * set the buf_T * value to an invalid value (-1?), which
5135 * means we need checks in all access functions... Bah.
5136 *
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005137 * Python2 and Python3 get different fields and different objects:
Bram Moolenaar971db462013-05-12 18:44:48 +02005138 * b_python_ref and b_python3_ref fields respectively.
5139 */
5140
5141 BufferObject *self;
5142
5143 if (BUF_PYTHON_REF(buf) != NULL)
5144 {
5145 self = BUF_PYTHON_REF(buf);
5146 Py_INCREF(self);
5147 }
5148 else
5149 {
5150 self = PyObject_NEW(BufferObject, &BufferType);
5151 if (self == NULL)
5152 return NULL;
5153 self->buf = buf;
5154 BUF_PYTHON_REF(buf) = self;
5155 }
5156
5157 return (PyObject *)(self);
5158}
5159
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005160 static void
Bram Moolenaard6e39182013-05-21 18:30:34 +02005161BufferDestructor(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005162{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005163 if (self->buf && self->buf != INVALID_BUFFER_VALUE)
5164 BUF_PYTHON_REF(self->buf) = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005165
5166 DESTRUCTOR_FINISH(self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005167}
5168
Bram Moolenaar971db462013-05-12 18:44:48 +02005169 static PyInt
Bram Moolenaard6e39182013-05-21 18:30:34 +02005170BufferLength(BufferObject *self)
Bram Moolenaar971db462013-05-12 18:44:48 +02005171{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005172 // HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION?
Bram Moolenaard6e39182013-05-21 18:30:34 +02005173 if (CheckBuffer(self))
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005174 return -1; // ???
Bram Moolenaar971db462013-05-12 18:44:48 +02005175
Bram Moolenaard6e39182013-05-21 18:30:34 +02005176 return (PyInt)(self->buf->b_ml.ml_line_count);
Bram Moolenaar971db462013-05-12 18:44:48 +02005177}
5178
5179 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005180BufferItem(BufferObject *self, PyInt n)
Bram Moolenaar971db462013-05-12 18:44:48 +02005181{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005182 return RBItem(self, n, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02005183}
5184
5185 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005186BufferSlice(BufferObject *self, PyInt lo, PyInt hi)
Bram Moolenaar971db462013-05-12 18:44:48 +02005187{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005188 return RBSlice(self, lo, hi, 1, -1);
Bram Moolenaar971db462013-05-12 18:44:48 +02005189}
5190
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005191static char *BufferAttrs[] = {
5192 "name", "number", "vars", "options", "valid",
5193 NULL
5194};
5195
5196 static PyObject *
5197BufferDir(PyObject *self)
5198{
5199 return ObjectDir(self, BufferAttrs);
5200}
5201
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005202 static PyObject *
Bram Moolenaar9e822c02013-05-29 22:15:30 +02005203BufferAttrValid(BufferObject *self, char *name)
5204{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005205 PyObject *ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02005206
5207 if (strcmp(name, "valid") != 0)
5208 return NULL;
5209
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005210 ret = ((self->buf == INVALID_BUFFER_VALUE) ? Py_False : Py_True);
5211 Py_INCREF(ret);
5212 return ret;
Bram Moolenaar9e822c02013-05-29 22:15:30 +02005213}
5214
5215 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005216BufferAttr(BufferObject *self, char *name)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005217{
5218 if (strcmp(name, "name") == 0)
Bram Moolenaar432b09c2013-05-29 22:26:18 +02005219 return PyString_FromString((self->buf->b_ffname == NULL
Bram Moolenaar41009372013-07-01 22:03:04 +02005220 ? "" : (char *)self->buf->b_ffname));
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005221 else if (strcmp(name, "number") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02005222 return Py_BuildValue(Py_ssize_t_fmt, self->buf->b_fnum);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005223 else if (strcmp(name, "vars") == 0)
Bram Moolenaara9922d62013-05-30 13:01:18 +02005224 return NEW_DICTIONARY(self->buf->b_vars);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005225 else if (strcmp(name, "options") == 0)
Bram Moolenaard6e39182013-05-21 18:30:34 +02005226 return OptionsNew(SREQ_BUF, self->buf, (checkfun) CheckBuffer,
5227 (PyObject *) self);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005228 else if (strcmp(name, "__members__") == 0)
5229 return ObjectDir(NULL, BufferAttrs);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005230 else
5231 return NULL;
5232}
5233
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005234 static int
5235BufferSetattr(BufferObject *self, char *name, PyObject *valObject)
5236{
5237 if (CheckBuffer(self))
5238 return -1;
5239
5240 if (strcmp(name, "name") == 0)
5241 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005242 char_u *val;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005243 aco_save_T aco;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005244 int ren_ret;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005245 PyObject *todecref;
5246
5247 if (!(val = StringToChars(valObject, &todecref)))
5248 return -1;
5249
5250 VimTryStart();
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005251 // Using aucmd_*: autocommands will be executed by rename_buffer
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005252 aucmd_prepbuf(&aco, self->buf);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005253 ren_ret = rename_buffer(val);
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005254 aucmd_restbuf(&aco);
5255 Py_XDECREF(todecref);
5256 if (VimTryEnd())
5257 return -1;
5258
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005259 if (ren_ret == FAIL)
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005260 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005261 PyErr_SET_VIM(N_("failed to rename buffer"));
Bram Moolenaare9ba5162013-05-29 22:02:22 +02005262 return -1;
5263 }
5264 return 0;
5265 }
5266 else
5267 {
5268 PyErr_SetString(PyExc_AttributeError, name);
5269 return -1;
5270 }
5271}
5272
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005273 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005274BufferAppend(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005275{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005276 return RBAppend(self, args, 1, -1, NULL);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005277}
5278
5279 static PyObject *
Bram Moolenaar389a1792013-06-23 13:00:44 +02005280BufferMark(BufferObject *self, PyObject *pmarkObject)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005281{
5282 pos_T *posp;
Bram Moolenaar389a1792013-06-23 13:00:44 +02005283 char_u *pmark;
5284 char_u mark;
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005285 bufref_T savebuf;
Bram Moolenaar389a1792013-06-23 13:00:44 +02005286 PyObject *todecref;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005287
Bram Moolenaard6e39182013-05-21 18:30:34 +02005288 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005289 return NULL;
5290
Bram Moolenaar389a1792013-06-23 13:00:44 +02005291 if (!(pmark = StringToChars(pmarkObject, &todecref)))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005292 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005293
Bram Moolenaar389a1792013-06-23 13:00:44 +02005294 if (pmark[0] == '\0' || pmark[1] != '\0')
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02005295 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005296 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005297 N_("mark name must be a single character"));
Bram Moolenaar841fbd22013-06-23 14:37:07 +02005298 Py_XDECREF(todecref);
Bram Moolenaar494ff7e2013-05-30 13:17:17 +02005299 return NULL;
5300 }
5301
5302 mark = *pmark;
Bram Moolenaar389a1792013-06-23 13:00:44 +02005303
5304 Py_XDECREF(todecref);
5305
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005306 VimTryStart();
Bram Moolenaard6e39182013-05-21 18:30:34 +02005307 switch_buffer(&savebuf, self->buf);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005308 posp = getmark(mark, FALSE);
Bram Moolenaar7c0a2f32016-07-10 22:11:16 +02005309 restore_buffer(&savebuf);
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005310 if (VimTryEnd())
5311 return NULL;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005312
5313 if (posp == NULL)
5314 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005315 PyErr_SET_VIM(N_("invalid mark name"));
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005316 return NULL;
5317 }
5318
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005319 if (posp->lnum <= 0)
5320 {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005321 // Or raise an error?
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005322 Py_INCREF(Py_None);
5323 return Py_None;
5324 }
5325
5326 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
5327}
5328
5329 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005330BufferRange(BufferObject *self, PyObject *args)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005331{
5332 PyInt start;
5333 PyInt end;
5334
Bram Moolenaard6e39182013-05-21 18:30:34 +02005335 if (CheckBuffer(self))
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005336 return NULL;
5337
5338 if (!PyArg_ParseTuple(args, "nn", &start, &end))
5339 return NULL;
5340
Bram Moolenaard6e39182013-05-21 18:30:34 +02005341 return RangeNew(self->buf, start, end);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005342}
5343
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005344 static PyObject *
Bram Moolenaard6e39182013-05-21 18:30:34 +02005345BufferRepr(BufferObject *self)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005346{
Bram Moolenaard6e39182013-05-21 18:30:34 +02005347 if (self->buf == INVALID_BUFFER_VALUE)
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005348 return PyString_FromFormat("<buffer object (deleted) at %p>", self);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005349 else
5350 {
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005351 char *name = (char *)self->buf->b_fname;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005352
5353 if (name == NULL)
5354 name = "";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005355
Bram Moolenaar1a3b5692013-05-30 12:40:39 +02005356 return PyString_FromFormat("<buffer %s>", name);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005357 }
5358}
5359
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005360static struct PyMethodDef BufferMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005361 // name, function, calling, documentation
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02005362 {"append", (PyCFunction)BufferAppend, METH_VARARGS, "Append data to Vim buffer" },
Bram Moolenaar389a1792013-06-23 13:00:44 +02005363 {"mark", (PyCFunction)BufferMark, METH_O, "Return (row,col) representing position of named mark" },
Bram Moolenaar182dc4f2013-05-21 19:01:55 +02005364 {"range", (PyCFunction)BufferRange, METH_VARARGS, "Return a range object which represents the part of the given buffer between line numbers s and e" },
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005365 {"__dir__", (PyCFunction)BufferDir, METH_NOARGS, ""},
5366 { NULL, NULL, 0, NULL}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005367};
5368
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005369/*
5370 * Buffer list object - Implementation
5371 */
5372
5373static PyTypeObject BufMapType;
5374
5375typedef struct
5376{
5377 PyObject_HEAD
5378} BufMapObject;
5379
5380 static PyInt
5381BufMapLength(PyObject *self UNUSED)
5382{
5383 buf_T *b = firstbuf;
5384 PyInt n = 0;
5385
5386 while (b)
5387 {
5388 ++n;
5389 b = b->b_next;
5390 }
5391
5392 return n;
5393}
5394
5395 static PyObject *
5396BufMapItem(PyObject *self UNUSED, PyObject *keyObject)
5397{
5398 buf_T *b;
Bram Moolenaar141be8a2013-06-23 14:16:57 +02005399 long bnr;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005400
Bram Moolenaar141be8a2013-06-23 14:16:57 +02005401 if (NumberToLong(keyObject, &bnr, NUMBER_INT|NUMBER_NATURAL))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005402 return NULL;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005403
Bram Moolenaar141be8a2013-06-23 14:16:57 +02005404 b = buflist_findnr((int) bnr);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005405
5406 if (b)
5407 return BufferNew(b);
5408 else
5409 {
Bram Moolenaar4d188da2013-05-15 15:35:09 +02005410 PyErr_SetObject(PyExc_KeyError, keyObject);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005411 return NULL;
5412 }
5413}
5414
5415 static void
5416BufMapIterDestruct(PyObject *buffer)
5417{
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005418 // Iteration was stopped before all buffers were processed
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005419 if (buffer)
5420 {
5421 Py_DECREF(buffer);
5422 }
5423}
5424
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02005425 static int
5426BufMapIterTraverse(PyObject *buffer, visitproc visit, void *arg)
5427{
Bram Moolenaar774267b2013-05-21 20:51:59 +02005428 if (buffer)
5429 Py_VISIT(buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02005430 return 0;
5431}
5432
5433 static int
5434BufMapIterClear(PyObject **buffer)
5435{
Bram Moolenaar774267b2013-05-21 20:51:59 +02005436 if (*buffer)
5437 Py_CLEAR(*buffer);
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02005438 return 0;
5439}
5440
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005441 static PyObject *
5442BufMapIterNext(PyObject **buffer)
5443{
5444 PyObject *next;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005445 PyObject *ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005446
5447 if (!*buffer)
5448 return NULL;
5449
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005450 ret = *buffer;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005451
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005452 if (CheckBuffer((BufferObject *)(ret)))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005453 {
5454 *buffer = NULL;
5455 return NULL;
5456 }
5457
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005458 if (!((BufferObject *)(ret))->buf->b_next)
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005459 next = NULL;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005460 else if (!(next = BufferNew(((BufferObject *)(ret))->buf->b_next)))
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005461 return NULL;
5462 *buffer = next;
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005463 // Do not increment reference: we no longer hold it (decref), but whoever
5464 // on other side will hold (incref). Decref+incref = nothing.
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005465 return ret;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005466}
5467
5468 static PyObject *
5469BufMapIter(PyObject *self UNUSED)
5470{
5471 PyObject *buffer;
5472
5473 buffer = BufferNew(firstbuf);
5474 return IterNew(buffer,
Bram Moolenaarcfef5ff2013-05-17 16:24:32 +02005475 (destructorfun) BufMapIterDestruct, (nextfun) BufMapIterNext,
5476 (traversefun) BufMapIterTraverse, (clearfun) BufMapIterClear);
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02005477}
5478
5479static PyMappingMethods BufMapAsMapping = {
5480 (lenfunc) BufMapLength,
5481 (binaryfunc) BufMapItem,
5482 (objobjargproc) 0,
5483};
5484
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005485// Current items object
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02005486
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005487static char *CurrentAttrs[] = {
5488 "buffer", "window", "line", "range", "tabpage",
5489 NULL
5490};
5491
5492 static PyObject *
5493CurrentDir(PyObject *self)
5494{
5495 return ObjectDir(self, CurrentAttrs);
5496}
5497
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005498 static PyObject *
5499CurrentGetattr(PyObject *self UNUSED, char *name)
5500{
5501 if (strcmp(name, "buffer") == 0)
5502 return (PyObject *)BufferNew(curbuf);
5503 else if (strcmp(name, "window") == 0)
Bram Moolenaarcabf80f2013-05-17 16:18:33 +02005504 return (PyObject *)WindowNew(curwin, curtab);
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02005505 else if (strcmp(name, "tabpage") == 0)
5506 return (PyObject *)TabPageNew(curtab);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005507 else if (strcmp(name, "line") == 0)
5508 return GetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum);
5509 else if (strcmp(name, "range") == 0)
5510 return RangeNew(curbuf, RangeStart, RangeEnd);
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005511 else if (strcmp(name, "__members__") == 0)
5512 return ObjectDir(NULL, CurrentAttrs);
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005513 else
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005514#if PY_MAJOR_VERSION < 3
5515 return Py_FindMethod(WindowMethods, self, name);
5516#else
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005517 return NULL;
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005518#endif
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005519}
5520
5521 static int
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005522CurrentSetattr(PyObject *self UNUSED, char *name, PyObject *valObject)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005523{
5524 if (strcmp(name, "line") == 0)
5525 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005526 if (SetBufferLine(curbuf, (PyInt)curwin->w_cursor.lnum, valObject,
5527 NULL) == FAIL)
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005528 return -1;
5529
5530 return 0;
5531 }
Bram Moolenaare7614592013-05-15 15:51:08 +02005532 else if (strcmp(name, "buffer") == 0)
5533 {
5534 int count;
5535
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005536 if (valObject->ob_type != &BufferType)
Bram Moolenaare7614592013-05-15 15:51:08 +02005537 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005538 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005539 N_("expected vim.Buffer object, but got %s"),
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005540 Py_TYPE_NAME(valObject));
Bram Moolenaare7614592013-05-15 15:51:08 +02005541 return -1;
5542 }
5543
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005544 if (CheckBuffer((BufferObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02005545 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005546 count = ((BufferObject *)(valObject))->buf->b_fnum;
Bram Moolenaare7614592013-05-15 15:51:08 +02005547
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005548 VimTryStart();
Bram Moolenaare7614592013-05-15 15:51:08 +02005549 if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, count, 0) == FAIL)
5550 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005551 if (VimTryEnd())
5552 return -1;
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005553 PyErr_VIM_FORMAT(N_("failed to switch to buffer %d"), count);
Bram Moolenaare7614592013-05-15 15:51:08 +02005554 return -1;
5555 }
5556
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005557 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02005558 }
5559 else if (strcmp(name, "window") == 0)
5560 {
5561 int count;
5562
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005563 if (valObject->ob_type != &WindowType)
Bram Moolenaare7614592013-05-15 15:51:08 +02005564 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005565 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005566 N_("expected vim.Window object, but got %s"),
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005567 Py_TYPE_NAME(valObject));
Bram Moolenaare7614592013-05-15 15:51:08 +02005568 return -1;
5569 }
5570
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005571 if (CheckWindow((WindowObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02005572 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005573 count = get_win_number(((WindowObject *)(valObject))->win, firstwin);
Bram Moolenaare7614592013-05-15 15:51:08 +02005574
5575 if (!count)
5576 {
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005577 PyErr_SET_STRING(PyExc_ValueError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005578 N_("failed to find window in the current tab page"));
Bram Moolenaare7614592013-05-15 15:51:08 +02005579 return -1;
5580 }
5581
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005582 VimTryStart();
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005583 win_goto(((WindowObject *)(valObject))->win);
5584 if (((WindowObject *)(valObject))->win != curwin)
Bram Moolenaare7614592013-05-15 15:51:08 +02005585 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005586 if (VimTryEnd())
5587 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005588 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005589 N_("did not switch to the specified window"));
Bram Moolenaare7614592013-05-15 15:51:08 +02005590 return -1;
5591 }
5592
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005593 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02005594 }
5595 else if (strcmp(name, "tabpage") == 0)
5596 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005597 if (valObject->ob_type != &TabPageType)
Bram Moolenaare7614592013-05-15 15:51:08 +02005598 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005599 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005600 N_("expected vim.TabPage object, but got %s"),
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005601 Py_TYPE_NAME(valObject));
Bram Moolenaare7614592013-05-15 15:51:08 +02005602 return -1;
5603 }
5604
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005605 if (CheckTabPage((TabPageObject *)(valObject)))
Bram Moolenaare7614592013-05-15 15:51:08 +02005606 return -1;
5607
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005608 VimTryStart();
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005609 goto_tabpage_tp(((TabPageObject *)(valObject))->tab, TRUE, TRUE);
5610 if (((TabPageObject *)(valObject))->tab != curtab)
Bram Moolenaare7614592013-05-15 15:51:08 +02005611 {
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005612 if (VimTryEnd())
5613 return -1;
Bram Moolenaar0bd80cc2013-06-23 13:28:17 +02005614 PyErr_SET_STRING(PyExc_RuntimeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02005615 N_("did not switch to the specified tab page"));
Bram Moolenaare7614592013-05-15 15:51:08 +02005616 return -1;
5617 }
5618
Bram Moolenaara7b64ce2013-05-21 20:40:40 +02005619 return VimTryEnd();
Bram Moolenaare7614592013-05-15 15:51:08 +02005620 }
Bram Moolenaar4d1da492013-04-24 13:39:15 +02005621 else
5622 {
5623 PyErr_SetString(PyExc_AttributeError, name);
5624 return -1;
5625 }
5626}
5627
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005628static struct PyMethodDef CurrentMethods[] = {
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005629 // name, function, calling, documentation
Bram Moolenaardd8aca62013-05-29 22:36:10 +02005630 {"__dir__", (PyCFunction)CurrentDir, METH_NOARGS, ""},
5631 { NULL, NULL, 0, NULL}
5632};
5633
Bram Moolenaardb913952012-06-29 12:54:53 +02005634 static void
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005635init_range_cmd(exarg_T *eap)
5636{
5637 RangeStart = eap->line1;
5638 RangeEnd = eap->line2;
5639}
5640
5641 static void
5642init_range_eval(typval_T *rettv UNUSED)
5643{
5644 RangeStart = (PyInt) curwin->w_cursor.lnum;
5645 RangeEnd = RangeStart;
5646}
5647
5648 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005649run_cmd(const char *cmd, void *arg UNUSED
5650#ifdef PY_CAN_RECURSE
5651 , PyGILState_STATE *pygilstate UNUSED
5652#endif
5653 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005654{
Bram Moolenaar41009372013-07-01 22:03:04 +02005655 PyObject *run_ret;
5656 run_ret = PyRun_String((char *)cmd, Py_file_input, globals, globals);
5657 if (run_ret != NULL)
5658 {
5659 Py_DECREF(run_ret);
5660 }
5661 else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
5662 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005663 semsg(_(e_py_systemexit), "python");
Bram Moolenaar41009372013-07-01 22:03:04 +02005664 PyErr_Clear();
5665 }
5666 else
5667 PyErr_PrintEx(1);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005668}
5669
5670static const char *code_hdr = "def " DOPY_FUNC "(line, linenr):\n ";
5671static int code_hdr_len = 30;
5672
5673 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005674run_do(const char *cmd, void *arg UNUSED
5675#ifdef PY_CAN_RECURSE
5676 , PyGILState_STATE *pygilstate
5677#endif
5678 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005679{
5680 PyInt lnum;
5681 size_t len;
5682 char *code;
5683 int status;
5684 PyObject *pyfunc, *pymain;
Bram Moolenaar41009372013-07-01 22:03:04 +02005685 PyObject *run_ret;
Bram Moolenaara58883b2017-01-29 21:31:09 +01005686 buf_T *was_curbuf = curbuf;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005687
Bram Moolenaar4ac66762013-05-28 22:31:46 +02005688 if (u_save((linenr_T)RangeStart - 1, (linenr_T)RangeEnd + 1) != OK)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005689 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005690 emsg(_("cannot save undo information"));
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005691 return;
5692 }
5693
5694 len = code_hdr_len + STRLEN(cmd);
5695 code = PyMem_New(char, len + 1);
5696 memcpy(code, code_hdr, code_hdr_len);
5697 STRCPY(code + code_hdr_len, cmd);
Bram Moolenaar41009372013-07-01 22:03:04 +02005698 run_ret = PyRun_String(code, Py_file_input, globals, globals);
5699 status = -1;
5700 if (run_ret != NULL)
5701 {
5702 status = 0;
5703 Py_DECREF(run_ret);
5704 }
5705 else if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
5706 {
5707 PyMem_Free(code);
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005708 semsg(_(e_py_systemexit), "python");
Bram Moolenaar41009372013-07-01 22:03:04 +02005709 PyErr_Clear();
5710 return;
5711 }
5712 else
5713 PyErr_PrintEx(1);
5714
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005715 PyMem_Free(code);
5716
5717 if (status)
5718 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005719 emsg(_("failed to run the code"));
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005720 return;
5721 }
5722
5723 status = 0;
5724 pymain = PyImport_AddModule("__main__");
5725 pyfunc = PyObject_GetAttrString(pymain, DOPY_FUNC);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005726#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005727 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005728#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005729
5730 for (lnum = RangeStart; lnum <= RangeEnd; ++lnum)
5731 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005732 PyObject *line;
5733 PyObject *linenr;
5734 PyObject *ret;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005735
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005736#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005737 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005738#endif
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005739 // Check the line number, the command my have deleted lines.
Bram Moolenaara58883b2017-01-29 21:31:09 +01005740 if (lnum > curbuf->b_ml.ml_line_count
5741 || !(line = GetBufferLine(curbuf, lnum)))
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005742 goto err;
5743 if (!(linenr = PyInt_FromLong((long) lnum)))
5744 {
5745 Py_DECREF(line);
5746 goto err;
5747 }
5748 ret = PyObject_CallFunctionObjArgs(pyfunc, line, linenr, NULL);
5749 Py_DECREF(line);
5750 Py_DECREF(linenr);
5751 if (!ret)
5752 goto err;
5753
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01005754 // Check that the command didn't switch to another buffer.
Bram Moolenaara58883b2017-01-29 21:31:09 +01005755 if (curbuf != was_curbuf)
5756 {
5757 Py_XDECREF(ret);
5758 goto err;
5759 }
5760
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005761 if (ret != Py_None)
5762 if (SetBufferLine(curbuf, lnum, ret, NULL) == FAIL)
Bram Moolenaara58883b2017-01-29 21:31:09 +01005763 {
5764 Py_XDECREF(ret);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005765 goto err;
Bram Moolenaara58883b2017-01-29 21:31:09 +01005766 }
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005767
5768 Py_XDECREF(ret);
5769 PythonIO_Flush();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005770#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005771 PyGILState_Release(*pygilstate);
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005772#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005773 }
5774 goto out;
5775err:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005776#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005777 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005778#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005779 PyErr_PrintEx(0);
5780 PythonIO_Flush();
5781 status = 1;
5782out:
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005783#ifdef PY_CAN_RECURSE
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005784 if (!status)
5785 *pygilstate = PyGILState_Ensure();
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005786#endif
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005787 Py_DECREF(pyfunc);
5788 PyObject_SetAttrString(pymain, DOPY_FUNC, NULL);
5789 if (status)
5790 return;
5791 check_cursor();
5792 update_curbuf(NOT_VALID);
5793}
5794
5795 static void
Bram Moolenaar2a0f3d32013-05-21 22:23:56 +02005796run_eval(const char *cmd, typval_T *rettv
5797#ifdef PY_CAN_RECURSE
5798 , PyGILState_STATE *pygilstate UNUSED
5799#endif
5800 )
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005801{
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005802 PyObject *run_ret;
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005803
Bram Moolenaar41009372013-07-01 22:03:04 +02005804 run_ret = PyRun_String((char *)cmd, Py_eval_input, globals, globals);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005805 if (run_ret == NULL)
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005806 {
Bram Moolenaar91aeaf42013-07-06 13:02:30 +02005807 if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_SystemExit))
Bram Moolenaar41009372013-07-01 22:03:04 +02005808 {
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005809 semsg(_(e_py_systemexit), "python");
Bram Moolenaar41009372013-07-01 22:03:04 +02005810 PyErr_Clear();
5811 }
Bram Moolenaar91aeaf42013-07-06 13:02:30 +02005812 else
5813 {
5814 if (PyErr_Occurred() && !msg_silent)
5815 PyErr_PrintEx(0);
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005816 emsg(_("E858: Eval did not return a valid python object"));
Bram Moolenaar91aeaf42013-07-06 13:02:30 +02005817 }
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005818 }
5819 else
5820 {
Bram Moolenaarde323092017-11-09 19:56:08 +01005821 if (ConvertFromPyObject(run_ret, rettv) == -1)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01005822 emsg(_("E859: Failed to convert returned python object to vim value"));
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02005823 Py_DECREF(run_ret);
Bram Moolenaarb52f4c02013-05-21 18:19:38 +02005824 }
5825 PyErr_Clear();
5826}
5827
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005828 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02005829set_ref_in_py(const int copyID)
5830{
5831 pylinkedlist_T *cur;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02005832 list_T *ll;
5833 int i;
5834 int abort = FALSE;
Bram Moolenaar8110a092016-04-14 15:56:09 +02005835 FunctionObject *func;
Bram Moolenaardb913952012-06-29 12:54:53 +02005836
5837 if (lastdict != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005838 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02005839 for (cur = lastdict ; !abort && cur != NULL ; cur = cur->pll_prev)
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02005840 abort = set_ref_in_dict(((DictionaryObject *)(cur->pll_obj))->dict,
5841 copyID);
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005842 }
Bram Moolenaardb913952012-06-29 12:54:53 +02005843
5844 if (lastlist != NULL)
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005845 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02005846 for (cur = lastlist ; !abort && cur != NULL ; cur = cur->pll_prev)
Bram Moolenaardb913952012-06-29 12:54:53 +02005847 {
5848 ll = ((ListObject *) (cur->pll_obj))->list;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02005849 abort = set_ref_in_list(ll, copyID);
Bram Moolenaardb913952012-06-29 12:54:53 +02005850 }
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005851 }
5852
Bram Moolenaar8110a092016-04-14 15:56:09 +02005853 if (lastfunc != NULL)
5854 {
5855 for (cur = lastfunc ; !abort && cur != NULL ; cur = cur->pll_prev)
5856 {
5857 func = (FunctionObject *) cur->pll_obj;
Bram Moolenaar7be3ab22019-06-23 01:46:15 +02005858 abort = set_ref_in_dict(func->self, copyID);
Bram Moolenaar8110a092016-04-14 15:56:09 +02005859 if (func->argc)
5860 for (i = 0; !abort && i < func->argc; ++i)
5861 abort = abort
5862 || set_ref_in_item(&func->argv[i], copyID, NULL, NULL);
5863 }
5864 }
5865
Bram Moolenaar2459a5e2015-02-03 12:55:18 +01005866 return abort;
Bram Moolenaardb913952012-06-29 12:54:53 +02005867}
5868
5869 static int
5870set_string_copy(char_u *str, typval_T *tv)
5871{
5872 tv->vval.v_string = vim_strsave(str);
5873 if (tv->vval.v_string == NULL)
5874 {
5875 PyErr_NoMemory();
5876 return -1;
5877 }
5878 return 0;
5879}
5880
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005881 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005882pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005883{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005884 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005885 char_u *key;
5886 dictitem_T *di;
5887 PyObject *keyObject;
5888 PyObject *valObject;
5889 Py_ssize_t iter = 0;
5890
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005891 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005892 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005893
5894 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005895 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005896
5897 while (PyDict_Next(obj, &iter, &keyObject, &valObject))
5898 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005899 PyObject *todecref = NULL;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005900
Bram Moolenaara03e6312013-05-29 22:49:26 +02005901 if (keyObject == NULL || valObject == NULL)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005902 {
5903 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005904 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005905 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005906
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005907 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005908 {
5909 dict_unref(dict);
5910 return -1;
5911 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005912
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005913 if (*key == NUL)
5914 {
5915 dict_unref(dict);
5916 Py_XDECREF(todecref);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005917 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005918 return -1;
5919 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005920
5921 di = dictitem_alloc(key);
5922
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005923 Py_XDECREF(todecref);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005924
5925 if (di == NULL)
5926 {
5927 PyErr_NoMemory();
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005928 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005929 return -1;
5930 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005931
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005932 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005933 {
5934 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005935 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005936 return -1;
5937 }
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005938
5939 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005940 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02005941 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaara03e6312013-05-29 22:49:26 +02005942 clear_tv(&di->di_tv);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005943 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005944 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005945 return -1;
5946 }
5947 }
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005948
5949 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005950 return 0;
5951}
5952
5953 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005954pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005955{
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005956 dict_T *dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005957 char_u *key;
5958 dictitem_T *di;
5959 PyObject *list;
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005960 PyObject *iterator;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005961 PyObject *keyObject;
5962 PyObject *valObject;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005963
Bram Moolenaar35eacd72013-05-30 22:06:33 +02005964 if (!(dict = py_dict_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005965 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005966
5967 tv->v_type = VAR_DICT;
Bram Moolenaarb38caae2013-05-29 22:39:52 +02005968 tv->vval.v_dict = dict;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005969
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005970 if (!(list = PyMapping_Keys(obj)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005971 {
5972 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005973 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005974 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005975
5976 if (!(iterator = PyObject_GetIter(list)))
5977 {
5978 dict_unref(dict);
5979 Py_DECREF(list);
5980 return -1;
5981 }
5982 Py_DECREF(list);
5983
5984 while ((keyObject = PyIter_Next(iterator)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005985 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005986 PyObject *todecref;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02005987
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005988 if (!(key = StringToChars(keyObject, &todecref)))
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005989 {
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005990 Py_DECREF(keyObject);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02005991 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005992 dict_unref(dict);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02005993 return -1;
5994 }
Bram Moolenaar4f2109d2013-06-02 18:07:37 +02005995
Bram Moolenaarfc714b32013-05-30 14:52:37 +02005996 if (*key == NUL)
5997 {
5998 Py_DECREF(keyObject);
5999 Py_DECREF(iterator);
6000 Py_XDECREF(todecref);
6001 dict_unref(dict);
Bram Moolenaar35eacd72013-05-30 22:06:33 +02006002 RAISE_NO_EMPTY_KEYS;
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006003 return -1;
6004 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006005
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006006 if (!(valObject = PyObject_GetItem(obj, keyObject)))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006007 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006008 Py_DECREF(keyObject);
6009 Py_DECREF(iterator);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006010 Py_XDECREF(todecref);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006011 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006012 return -1;
6013 }
6014
6015 di = dictitem_alloc(key);
6016
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006017 Py_DECREF(keyObject);
Bram Moolenaarfc714b32013-05-30 14:52:37 +02006018 Py_XDECREF(todecref);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006019
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006020 if (di == NULL)
6021 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006022 Py_DECREF(iterator);
6023 Py_DECREF(valObject);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006024 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006025 PyErr_NoMemory();
6026 return -1;
6027 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006028
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006029 if (_ConvertFromPyObject(valObject, &di->di_tv, lookup_dict) == -1)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006030 {
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006031 Py_DECREF(iterator);
6032 Py_DECREF(valObject);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006033 vim_free(di);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006034 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006035 return -1;
6036 }
Bram Moolenaara03e6312013-05-29 22:49:26 +02006037
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006038 Py_DECREF(valObject);
6039
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006040 if (dict_add(dict, di) == FAIL)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006041 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02006042 RAISE_KEY_ADD_FAIL(di->di_key);
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006043 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006044 dictitem_free(di);
6045 dict_unref(dict);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006046 return -1;
6047 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006048 }
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006049 Py_DECREF(iterator);
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006050 --dict->dv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006051 return 0;
6052}
6053
6054 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006055pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006056{
6057 list_T *l;
6058
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006059 if (!(l = py_list_alloc()))
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006060 return -1;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006061
6062 tv->v_type = VAR_LIST;
6063 tv->vval.v_list = l;
6064
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006065 if (list_py_concat(l, obj, lookup_dict) == -1)
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006066 {
6067 list_unref(l);
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006068 return -1;
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006069 }
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006070
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006071 --l->lv_refcount;
Bram Moolenaar3d0c52d2013-05-12 19:45:35 +02006072 return 0;
6073}
6074
Bram Moolenaardb913952012-06-29 12:54:53 +02006075typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
6076
6077 static int
6078convert_dl(PyObject *obj, typval_T *tv,
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006079 pytotvfunc py_to_tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02006080{
6081 PyObject *capsule;
6082 char hexBuf[sizeof(void *) * 2 + 3];
6083
Bram Moolenaar792f0e32018-02-27 17:27:13 +01006084 sprintf(hexBuf, "%p", (void *)obj);
Bram Moolenaardb913952012-06-29 12:54:53 +02006085
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006086#ifdef PY_USE_CAPSULE
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006087 capsule = PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006088#else
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006089 capsule = (PyObject *)PyDict_GetItemString(lookup_dict, hexBuf);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006090#endif
Bram Moolenaar221d6872012-06-30 13:34:34 +02006091 if (capsule == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02006092 {
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006093#ifdef PY_USE_CAPSULE
Bram Moolenaardb913952012-06-29 12:54:53 +02006094 capsule = PyCapsule_New(tv, NULL, NULL);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006095#else
Bram Moolenaar221d6872012-06-30 13:34:34 +02006096 capsule = PyCObject_FromVoidPtr(tv, NULL);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006097#endif
Bram Moolenaara03e6312013-05-29 22:49:26 +02006098 if (PyDict_SetItemString(lookup_dict, hexBuf, capsule))
6099 {
6100 Py_DECREF(capsule);
6101 tv->v_type = VAR_UNKNOWN;
6102 return -1;
6103 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02006104
6105 Py_DECREF(capsule);
6106
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006107 if (py_to_tv(obj, tv, lookup_dict) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02006108 {
6109 tv->v_type = VAR_UNKNOWN;
6110 return -1;
6111 }
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006112 // As we are not using copy_tv which increments reference count we must
6113 // do it ourself.
Bram Moolenaar81e7a9c2016-02-06 19:57:20 +01006114 if (tv->v_type == VAR_DICT)
6115 ++tv->vval.v_dict->dv_refcount;
6116 else if (tv->v_type == VAR_LIST)
6117 ++tv->vval.v_list->lv_refcount;
Bram Moolenaardb913952012-06-29 12:54:53 +02006118 }
6119 else
6120 {
Bram Moolenaar2afa3232012-06-29 16:28:28 +02006121 typval_T *v;
6122
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006123#ifdef PY_USE_CAPSULE
Bram Moolenaar2afa3232012-06-29 16:28:28 +02006124 v = PyCapsule_GetPointer(capsule, NULL);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006125#else
Bram Moolenaar221d6872012-06-30 13:34:34 +02006126 v = PyCObject_AsVoidPtr(capsule);
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006127#endif
Bram Moolenaardb913952012-06-29 12:54:53 +02006128 copy_tv(v, tv);
6129 }
6130 return 0;
6131}
6132
6133 static int
Bram Moolenaara9922d62013-05-30 13:01:18 +02006134ConvertFromPyMapping(PyObject *obj, typval_T *tv)
6135{
6136 PyObject *lookup_dict;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006137 int ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006138
6139 if (!(lookup_dict = PyDict_New()))
6140 return -1;
6141
6142 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
6143 {
6144 tv->v_type = VAR_DICT;
6145 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
6146 ++tv->vval.v_dict->dv_refcount;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006147 ret = 0;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006148 }
6149 else if (PyDict_Check(obj))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006150 ret = convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaara9922d62013-05-30 13:01:18 +02006151 else if (PyMapping_Check(obj))
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006152 ret = convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaara9922d62013-05-30 13:01:18 +02006153 else
6154 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02006155 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006156 N_("unable to convert %s to vim dictionary"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02006157 Py_TYPE_NAME(obj));
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006158 ret = -1;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006159 }
6160 Py_DECREF(lookup_dict);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006161 return ret;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006162}
6163
6164 static int
Bram Moolenaar8110a092016-04-14 15:56:09 +02006165ConvertFromPySequence(PyObject *obj, typval_T *tv)
6166{
6167 PyObject *lookup_dict;
Bram Moolenaar66210042016-04-15 20:40:41 +02006168 int ret;
Bram Moolenaar8110a092016-04-14 15:56:09 +02006169
6170 if (!(lookup_dict = PyDict_New()))
6171 return -1;
6172
6173 if (PyType_IsSubtype(obj->ob_type, &ListType))
6174 {
6175 tv->v_type = VAR_LIST;
6176 tv->vval.v_list = (((ListObject *)(obj))->list);
6177 ++tv->vval.v_list->lv_refcount;
Bram Moolenaar66210042016-04-15 20:40:41 +02006178 ret = 0;
Bram Moolenaar8110a092016-04-14 15:56:09 +02006179 }
6180 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaar66210042016-04-15 20:40:41 +02006181 ret = convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaar8110a092016-04-14 15:56:09 +02006182 else
6183 {
6184 PyErr_FORMAT(PyExc_TypeError,
6185 N_("unable to convert %s to vim list"),
6186 Py_TYPE_NAME(obj));
6187 ret = -1;
6188 }
6189 Py_DECREF(lookup_dict);
6190 return ret;
6191}
6192
6193 static int
Bram Moolenaardb913952012-06-29 12:54:53 +02006194ConvertFromPyObject(PyObject *obj, typval_T *tv)
6195{
6196 PyObject *lookup_dict;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006197 int ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02006198
Bram Moolenaar9bb77d62013-05-30 12:14:49 +02006199 if (!(lookup_dict = PyDict_New()))
6200 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006201 ret = _ConvertFromPyObject(obj, tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02006202 Py_DECREF(lookup_dict);
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006203 return ret;
Bram Moolenaardb913952012-06-29 12:54:53 +02006204}
6205
6206 static int
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006207_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookup_dict)
Bram Moolenaardb913952012-06-29 12:54:53 +02006208{
Bram Moolenaara9922d62013-05-30 13:01:18 +02006209 if (PyType_IsSubtype(obj->ob_type, &DictionaryType))
Bram Moolenaardb913952012-06-29 12:54:53 +02006210 {
6211 tv->v_type = VAR_DICT;
6212 tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
6213 ++tv->vval.v_dict->dv_refcount;
6214 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02006215 else if (PyType_IsSubtype(obj->ob_type, &ListType))
Bram Moolenaardb913952012-06-29 12:54:53 +02006216 {
6217 tv->v_type = VAR_LIST;
6218 tv->vval.v_list = (((ListObject *)(obj))->list);
6219 ++tv->vval.v_list->lv_refcount;
6220 }
Bram Moolenaar841fbd22013-06-23 14:37:07 +02006221 else if (PyType_IsSubtype(obj->ob_type, &FunctionType))
Bram Moolenaardb913952012-06-29 12:54:53 +02006222 {
Bram Moolenaar8110a092016-04-14 15:56:09 +02006223 FunctionObject *func = (FunctionObject *) obj;
6224 if (func->self != NULL || func->argv != NULL)
6225 {
Bram Moolenaarc799fe22019-05-28 23:08:19 +02006226 partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
6227
Bram Moolenaar8110a092016-04-14 15:56:09 +02006228 set_partial(func, pt, TRUE);
6229 tv->vval.v_partial = pt;
6230 tv->v_type = VAR_PARTIAL;
6231 }
6232 else
6233 {
6234 if (set_string_copy(func->name, tv) == -1)
6235 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02006236
Bram Moolenaar8110a092016-04-14 15:56:09 +02006237 tv->v_type = VAR_FUNC;
6238 }
6239 func_ref(func->name);
Bram Moolenaardb913952012-06-29 12:54:53 +02006240 }
Bram Moolenaardb913952012-06-29 12:54:53 +02006241 else if (PyBytes_Check(obj))
6242 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006243 char_u *str;
Bram Moolenaardb913952012-06-29 12:54:53 +02006244
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006245 if (PyBytes_AsStringAndSize(obj, (char **) &str, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02006246 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006247 if (str == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02006248 return -1;
6249
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006250 if (set_string_copy(str, tv) == -1)
Bram Moolenaardb913952012-06-29 12:54:53 +02006251 return -1;
6252
6253 tv->v_type = VAR_STRING;
6254 }
6255 else if (PyUnicode_Check(obj))
6256 {
6257 PyObject *bytes;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006258 char_u *str;
Bram Moolenaardb913952012-06-29 12:54:53 +02006259
Bram Moolenaar808c2bc2013-06-23 13:11:18 +02006260 bytes = PyUnicode_AsEncodedString(obj, ENC_OPT, NULL);
Bram Moolenaardb913952012-06-29 12:54:53 +02006261 if (bytes == NULL)
6262 return -1;
6263
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006264 if(PyBytes_AsStringAndSize(bytes, (char **) &str, NULL) == -1)
Bram Moolenaarafa6b9a2012-09-05 19:09:11 +02006265 return -1;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006266 if (str == NULL)
Bram Moolenaardb913952012-06-29 12:54:53 +02006267 return -1;
6268
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006269 if (set_string_copy(str, tv))
Bram Moolenaardb913952012-06-29 12:54:53 +02006270 {
6271 Py_XDECREF(bytes);
6272 return -1;
6273 }
6274 Py_XDECREF(bytes);
6275
6276 tv->v_type = VAR_STRING;
6277 }
Bram Moolenaar335e0b62013-04-24 13:47:45 +02006278#if PY_MAJOR_VERSION < 3
Bram Moolenaardb913952012-06-29 12:54:53 +02006279 else if (PyInt_Check(obj))
6280 {
6281 tv->v_type = VAR_NUMBER;
6282 tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02006283 if (PyErr_Occurred())
6284 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02006285 }
6286#endif
6287 else if (PyLong_Check(obj))
6288 {
6289 tv->v_type = VAR_NUMBER;
6290 tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02006291 if (PyErr_Occurred())
6292 return -1;
Bram Moolenaardb913952012-06-29 12:54:53 +02006293 }
6294 else if (PyDict_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006295 return convert_dl(obj, tv, pydict_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02006296#ifdef FEAT_FLOAT
6297 else if (PyFloat_Check(obj))
6298 {
6299 tv->v_type = VAR_FLOAT;
6300 tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
6301 }
6302#endif
Bram Moolenaarbcb40972013-05-30 13:22:13 +02006303 else if (PyObject_HasAttrString(obj, "keys"))
6304 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006305 // PyObject_GetIter can create built-in iterator for any sequence object
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02006306 else if (PyIter_Check(obj) || PySequence_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006307 return convert_dl(obj, tv, pyseq_to_tv, lookup_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02006308 else if (PyMapping_Check(obj))
Bram Moolenaarb38caae2013-05-29 22:39:52 +02006309 return convert_dl(obj, tv, pymap_to_tv, lookup_dict);
Bram Moolenaar141be8a2013-06-23 14:16:57 +02006310 else if (PyNumber_Check(obj))
6311 {
6312 PyObject *num;
6313
6314 if (!(num = PyNumber_Long(obj)))
6315 return -1;
6316
6317 tv->v_type = VAR_NUMBER;
6318 tv->vval.v_number = (varnumber_T) PyLong_AsLong(num);
6319
6320 Py_DECREF(num);
6321 }
Bram Moolenaarde323092017-11-09 19:56:08 +01006322 else if (obj == Py_None)
6323 {
6324 tv->v_type = VAR_SPECIAL;
6325 tv->vval.v_number = VVAL_NONE;
6326 }
Bram Moolenaardb913952012-06-29 12:54:53 +02006327 else
6328 {
Bram Moolenaarc476e522013-06-23 13:46:40 +02006329 PyErr_FORMAT(PyExc_TypeError,
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006330 N_("unable to convert %s to vim structure"),
Bram Moolenaarc476e522013-06-23 13:46:40 +02006331 Py_TYPE_NAME(obj));
Bram Moolenaardb913952012-06-29 12:54:53 +02006332 return -1;
6333 }
6334 return 0;
6335}
6336
6337 static PyObject *
6338ConvertToPyObject(typval_T *tv)
6339{
Bram Moolenaar8110a092016-04-14 15:56:09 +02006340 typval_T *argv;
6341 int i;
Bram Moolenaardb913952012-06-29 12:54:53 +02006342 if (tv == NULL)
6343 {
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006344 PyErr_SET_VIM(N_("internal error: NULL reference passed"));
Bram Moolenaardb913952012-06-29 12:54:53 +02006345 return NULL;
6346 }
6347 switch (tv->v_type)
6348 {
6349 case VAR_STRING:
Bram Moolenaard1f13fd2012-10-05 21:30:07 +02006350 return PyBytes_FromString(tv->vval.v_string == NULL
6351 ? "" : (char *)tv->vval.v_string);
Bram Moolenaardb913952012-06-29 12:54:53 +02006352 case VAR_NUMBER:
6353 return PyLong_FromLong((long) tv->vval.v_number);
6354#ifdef FEAT_FLOAT
6355 case VAR_FLOAT:
6356 return PyFloat_FromDouble((double) tv->vval.v_float);
6357#endif
6358 case VAR_LIST:
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02006359 return NEW_LIST(tv->vval.v_list);
Bram Moolenaardb913952012-06-29 12:54:53 +02006360 case VAR_DICT:
Bram Moolenaara9922d62013-05-30 13:01:18 +02006361 return NEW_DICTIONARY(tv->vval.v_dict);
Bram Moolenaardb913952012-06-29 12:54:53 +02006362 case VAR_FUNC:
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02006363 return NEW_FUNCTION(tv->vval.v_string == NULL
Bram Moolenaar8110a092016-04-14 15:56:09 +02006364 ? (char_u *)"" : tv->vval.v_string,
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02006365 0, NULL, NULL, TRUE);
Bram Moolenaar4c908612016-03-24 21:58:12 +01006366 case VAR_PARTIAL:
Bram Moolenaar8110a092016-04-14 15:56:09 +02006367 if (tv->vval.v_partial->pt_argc)
6368 {
6369 argv = PyMem_New(typval_T, (size_t)tv->vval.v_partial->pt_argc);
6370 for (i = 0; i < tv->vval.v_partial->pt_argc; i++)
6371 copy_tv(&tv->vval.v_partial->pt_argv[i], &argv[i]);
6372 }
6373 else
6374 argv = NULL;
6375 if (tv->vval.v_partial->pt_dict != NULL)
6376 tv->vval.v_partial->pt_dict->dv_refcount++;
Bram Moolenaar4c908612016-03-24 21:58:12 +01006377 return NEW_FUNCTION(tv->vval.v_partial == NULL
Bram Moolenaar437bafe2016-08-01 15:40:54 +02006378 ? (char_u *)"" : partial_name(tv->vval.v_partial),
Bram Moolenaar8110a092016-04-14 15:56:09 +02006379 tv->vval.v_partial->pt_argc, argv,
Bram Moolenaar2177f9f2016-05-25 20:39:09 +02006380 tv->vval.v_partial->pt_dict,
6381 tv->vval.v_partial->pt_auto);
Bram Moolenaar6e5ea8d2019-01-12 22:47:31 +01006382 case VAR_BLOB:
6383 return PyBytes_FromStringAndSize(
6384 (char*) tv->vval.v_blob->bv_ga.ga_data,
6385 (Py_ssize_t) tv->vval.v_blob->bv_ga.ga_len);
Bram Moolenaardb913952012-06-29 12:54:53 +02006386 case VAR_UNKNOWN:
Bram Moolenaar4c908612016-03-24 21:58:12 +01006387 case VAR_CHANNEL:
6388 case VAR_JOB:
Bram Moolenaardb913952012-06-29 12:54:53 +02006389 Py_INCREF(Py_None);
6390 return Py_None;
Bram Moolenaar4c908612016-03-24 21:58:12 +01006391 case VAR_SPECIAL:
6392 switch (tv->vval.v_number)
6393 {
6394 case VVAL_FALSE: return AlwaysFalse(NULL);
6395 case VVAL_TRUE: return AlwaysTrue(NULL);
6396 case VVAL_NONE:
6397 case VVAL_NULL: return AlwaysNone(NULL);
6398 }
Bram Moolenaar6f1404f2013-06-23 16:04:08 +02006399 PyErr_SET_VIM(N_("internal error: invalid value type"));
Bram Moolenaardb913952012-06-29 12:54:53 +02006400 return NULL;
6401 }
Bram Moolenaar4c908612016-03-24 21:58:12 +01006402 return NULL;
Bram Moolenaardb913952012-06-29 12:54:53 +02006403}
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006404
6405typedef struct
6406{
6407 PyObject_HEAD
6408} CurrentObject;
6409static PyTypeObject CurrentType;
6410
6411 static void
6412init_structs(void)
6413{
6414 vim_memset(&OutputType, 0, sizeof(OutputType));
6415 OutputType.tp_name = "vim.message";
6416 OutputType.tp_basicsize = sizeof(OutputObject);
6417 OutputType.tp_flags = Py_TPFLAGS_DEFAULT;
6418 OutputType.tp_doc = "vim message object";
6419 OutputType.tp_methods = OutputMethods;
6420#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006421 OutputType.tp_getattro = (getattrofunc)OutputGetattro;
6422 OutputType.tp_setattro = (setattrofunc)OutputSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006423 OutputType.tp_alloc = call_PyType_GenericAlloc;
6424 OutputType.tp_new = call_PyType_GenericNew;
6425 OutputType.tp_free = call_PyObject_Free;
Bram Moolenaard4a8c982018-05-15 22:31:18 +02006426 OutputType.tp_base = &PyStdPrinter_Type;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006427#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006428 OutputType.tp_getattr = (getattrfunc)OutputGetattr;
6429 OutputType.tp_setattr = (setattrfunc)OutputSetattr;
Bram Moolenaard4a8c982018-05-15 22:31:18 +02006430 // Disabled, because this causes a crash in test86
6431 // OutputType.tp_base = &PyFile_Type;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006432#endif
6433
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006434 vim_memset(&IterType, 0, sizeof(IterType));
6435 IterType.tp_name = "vim.iter";
6436 IterType.tp_basicsize = sizeof(IterObject);
Bram Moolenaar07b88642013-05-29 22:58:32 +02006437 IterType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006438 IterType.tp_doc = "generic iterator object";
Bram Moolenaard6e39182013-05-21 18:30:34 +02006439 IterType.tp_iter = (getiterfunc)IterIter;
6440 IterType.tp_iternext = (iternextfunc)IterNext;
6441 IterType.tp_dealloc = (destructor)IterDestructor;
6442 IterType.tp_traverse = (traverseproc)IterTraverse;
6443 IterType.tp_clear = (inquiry)IterClear;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006444
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006445 vim_memset(&BufferType, 0, sizeof(BufferType));
6446 BufferType.tp_name = "vim.buffer";
6447 BufferType.tp_basicsize = sizeof(BufferType);
Bram Moolenaard6e39182013-05-21 18:30:34 +02006448 BufferType.tp_dealloc = (destructor)BufferDestructor;
6449 BufferType.tp_repr = (reprfunc)BufferRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006450 BufferType.tp_as_sequence = &BufferAsSeq;
6451 BufferType.tp_as_mapping = &BufferAsMapping;
6452 BufferType.tp_flags = Py_TPFLAGS_DEFAULT;
6453 BufferType.tp_doc = "vim buffer object";
6454 BufferType.tp_methods = BufferMethods;
6455#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006456 BufferType.tp_getattro = (getattrofunc)BufferGetattro;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006457 BufferType.tp_setattro = (setattrofunc)BufferSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006458 BufferType.tp_alloc = call_PyType_GenericAlloc;
6459 BufferType.tp_new = call_PyType_GenericNew;
6460 BufferType.tp_free = call_PyObject_Free;
6461#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006462 BufferType.tp_getattr = (getattrfunc)BufferGetattr;
Bram Moolenaare9ba5162013-05-29 22:02:22 +02006463 BufferType.tp_setattr = (setattrfunc)BufferSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006464#endif
6465
6466 vim_memset(&WindowType, 0, sizeof(WindowType));
6467 WindowType.tp_name = "vim.window";
6468 WindowType.tp_basicsize = sizeof(WindowObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02006469 WindowType.tp_dealloc = (destructor)WindowDestructor;
6470 WindowType.tp_repr = (reprfunc)WindowRepr;
Bram Moolenaar07b88642013-05-29 22:58:32 +02006471 WindowType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006472 WindowType.tp_doc = "vim Window object";
6473 WindowType.tp_methods = WindowMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02006474 WindowType.tp_traverse = (traverseproc)WindowTraverse;
6475 WindowType.tp_clear = (inquiry)WindowClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006476#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006477 WindowType.tp_getattro = (getattrofunc)WindowGetattro;
6478 WindowType.tp_setattro = (setattrofunc)WindowSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006479 WindowType.tp_alloc = call_PyType_GenericAlloc;
6480 WindowType.tp_new = call_PyType_GenericNew;
6481 WindowType.tp_free = call_PyObject_Free;
6482#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006483 WindowType.tp_getattr = (getattrfunc)WindowGetattr;
6484 WindowType.tp_setattr = (setattrfunc)WindowSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006485#endif
6486
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02006487 vim_memset(&TabPageType, 0, sizeof(TabPageType));
6488 TabPageType.tp_name = "vim.tabpage";
6489 TabPageType.tp_basicsize = sizeof(TabPageObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02006490 TabPageType.tp_dealloc = (destructor)TabPageDestructor;
6491 TabPageType.tp_repr = (reprfunc)TabPageRepr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02006492 TabPageType.tp_flags = Py_TPFLAGS_DEFAULT;
6493 TabPageType.tp_doc = "vim tab page object";
6494 TabPageType.tp_methods = TabPageMethods;
6495#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006496 TabPageType.tp_getattro = (getattrofunc)TabPageGetattro;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02006497 TabPageType.tp_alloc = call_PyType_GenericAlloc;
6498 TabPageType.tp_new = call_PyType_GenericNew;
6499 TabPageType.tp_free = call_PyObject_Free;
6500#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006501 TabPageType.tp_getattr = (getattrfunc)TabPageGetattr;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02006502#endif
6503
Bram Moolenaardfa38d42013-05-15 13:38:47 +02006504 vim_memset(&BufMapType, 0, sizeof(BufMapType));
6505 BufMapType.tp_name = "vim.bufferlist";
6506 BufMapType.tp_basicsize = sizeof(BufMapObject);
6507 BufMapType.tp_as_mapping = &BufMapAsMapping;
6508 BufMapType.tp_flags = Py_TPFLAGS_DEFAULT;
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006509 BufMapType.tp_iter = BufMapIter;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006510 BufferType.tp_doc = "vim buffer list";
6511
6512 vim_memset(&WinListType, 0, sizeof(WinListType));
6513 WinListType.tp_name = "vim.windowlist";
6514 WinListType.tp_basicsize = sizeof(WinListType);
6515 WinListType.tp_as_sequence = &WinListAsSeq;
6516 WinListType.tp_flags = Py_TPFLAGS_DEFAULT;
6517 WinListType.tp_doc = "vim window list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02006518 WinListType.tp_dealloc = (destructor)WinListDestructor;
Bram Moolenaar5e538ec2013-05-15 15:12:29 +02006519
6520 vim_memset(&TabListType, 0, sizeof(TabListType));
6521 TabListType.tp_name = "vim.tabpagelist";
6522 TabListType.tp_basicsize = sizeof(TabListType);
6523 TabListType.tp_as_sequence = &TabListAsSeq;
6524 TabListType.tp_flags = Py_TPFLAGS_DEFAULT;
6525 TabListType.tp_doc = "vim tab page list";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006526
6527 vim_memset(&RangeType, 0, sizeof(RangeType));
6528 RangeType.tp_name = "vim.range";
6529 RangeType.tp_basicsize = sizeof(RangeObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02006530 RangeType.tp_dealloc = (destructor)RangeDestructor;
6531 RangeType.tp_repr = (reprfunc)RangeRepr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006532 RangeType.tp_as_sequence = &RangeAsSeq;
6533 RangeType.tp_as_mapping = &RangeAsMapping;
Bram Moolenaar07b88642013-05-29 22:58:32 +02006534 RangeType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006535 RangeType.tp_doc = "vim Range object";
6536 RangeType.tp_methods = RangeMethods;
Bram Moolenaar774267b2013-05-21 20:51:59 +02006537 RangeType.tp_traverse = (traverseproc)RangeTraverse;
6538 RangeType.tp_clear = (inquiry)RangeClear;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006539#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006540 RangeType.tp_getattro = (getattrofunc)RangeGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006541 RangeType.tp_alloc = call_PyType_GenericAlloc;
6542 RangeType.tp_new = call_PyType_GenericNew;
6543 RangeType.tp_free = call_PyObject_Free;
6544#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006545 RangeType.tp_getattr = (getattrfunc)RangeGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006546#endif
6547
6548 vim_memset(&CurrentType, 0, sizeof(CurrentType));
6549 CurrentType.tp_name = "vim.currentdata";
6550 CurrentType.tp_basicsize = sizeof(CurrentObject);
6551 CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
6552 CurrentType.tp_doc = "vim current object";
Bram Moolenaardd8aca62013-05-29 22:36:10 +02006553 CurrentType.tp_methods = CurrentMethods;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006554#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006555 CurrentType.tp_getattro = (getattrofunc)CurrentGetattro;
6556 CurrentType.tp_setattro = (setattrofunc)CurrentSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006557#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006558 CurrentType.tp_getattr = (getattrfunc)CurrentGetattr;
6559 CurrentType.tp_setattr = (setattrfunc)CurrentSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006560#endif
6561
6562 vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
6563 DictionaryType.tp_name = "vim.dictionary";
6564 DictionaryType.tp_basicsize = sizeof(DictionaryObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02006565 DictionaryType.tp_dealloc = (destructor)DictionaryDestructor;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006566 DictionaryType.tp_as_sequence = &DictionaryAsSeq;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006567 DictionaryType.tp_as_mapping = &DictionaryAsMapping;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006568 DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006569 DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
6570 DictionaryType.tp_methods = DictionaryMethods;
Bram Moolenaara9922d62013-05-30 13:01:18 +02006571 DictionaryType.tp_iter = (getiterfunc)DictionaryIter;
6572 DictionaryType.tp_new = (newfunc)DictionaryConstructor;
6573 DictionaryType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006574#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006575 DictionaryType.tp_getattro = (getattrofunc)DictionaryGetattro;
6576 DictionaryType.tp_setattro = (setattrofunc)DictionarySetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006577#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006578 DictionaryType.tp_getattr = (getattrfunc)DictionaryGetattr;
6579 DictionaryType.tp_setattr = (setattrfunc)DictionarySetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006580#endif
6581
6582 vim_memset(&ListType, 0, sizeof(ListType));
6583 ListType.tp_name = "vim.list";
Bram Moolenaard6e39182013-05-21 18:30:34 +02006584 ListType.tp_dealloc = (destructor)ListDestructor;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006585 ListType.tp_basicsize = sizeof(ListObject);
6586 ListType.tp_as_sequence = &ListAsSeq;
6587 ListType.tp_as_mapping = &ListAsMapping;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02006588 ListType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006589 ListType.tp_doc = "list pushing modifications to vim structure";
6590 ListType.tp_methods = ListMethods;
Bram Moolenaard6e39182013-05-21 18:30:34 +02006591 ListType.tp_iter = (getiterfunc)ListIter;
Bram Moolenaar78cddbe2013-05-30 13:05:58 +02006592 ListType.tp_new = (newfunc)ListConstructor;
6593 ListType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006594#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006595 ListType.tp_getattro = (getattrofunc)ListGetattro;
6596 ListType.tp_setattro = (setattrofunc)ListSetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006597#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006598 ListType.tp_getattr = (getattrfunc)ListGetattr;
6599 ListType.tp_setattr = (setattrfunc)ListSetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006600#endif
6601
6602 vim_memset(&FunctionType, 0, sizeof(FunctionType));
Bram Moolenaarb6c589a2013-05-15 14:39:52 +02006603 FunctionType.tp_name = "vim.function";
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006604 FunctionType.tp_basicsize = sizeof(FunctionObject);
Bram Moolenaard6e39182013-05-21 18:30:34 +02006605 FunctionType.tp_dealloc = (destructor)FunctionDestructor;
6606 FunctionType.tp_call = (ternaryfunc)FunctionCall;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02006607 FunctionType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006608 FunctionType.tp_doc = "object that calls vim function";
6609 FunctionType.tp_methods = FunctionMethods;
Bram Moolenaara5b725c2013-05-30 12:43:54 +02006610 FunctionType.tp_repr = (reprfunc)FunctionRepr;
Bram Moolenaar355fd9b2013-05-30 13:14:13 +02006611 FunctionType.tp_new = (newfunc)FunctionConstructor;
6612 FunctionType.tp_alloc = (allocfunc)PyType_GenericAlloc;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006613#if PY_MAJOR_VERSION >= 3
Bram Moolenaard6e39182013-05-21 18:30:34 +02006614 FunctionType.tp_getattro = (getattrofunc)FunctionGetattro;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006615#else
Bram Moolenaard6e39182013-05-21 18:30:34 +02006616 FunctionType.tp_getattr = (getattrfunc)FunctionGetattr;
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006617#endif
6618
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006619 vim_memset(&OptionsType, 0, sizeof(OptionsType));
6620 OptionsType.tp_name = "vim.options";
6621 OptionsType.tp_basicsize = sizeof(OptionsObject);
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006622 OptionsType.tp_as_sequence = &OptionsAsSeq;
Bram Moolenaar07b88642013-05-29 22:58:32 +02006623 OptionsType.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006624 OptionsType.tp_doc = "object for manipulating options";
Bram Moolenaar1028f4d2014-01-14 16:55:00 +01006625 OptionsType.tp_iter = (getiterfunc)OptionsIter;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006626 OptionsType.tp_as_mapping = &OptionsAsMapping;
Bram Moolenaard6e39182013-05-21 18:30:34 +02006627 OptionsType.tp_dealloc = (destructor)OptionsDestructor;
6628 OptionsType.tp_traverse = (traverseproc)OptionsTraverse;
6629 OptionsType.tp_clear = (inquiry)OptionsClear;
Bram Moolenaar84e0f6c2013-05-06 03:52:55 +02006630
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006631#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaar81c40c52013-06-12 14:41:04 +02006632 vim_memset(&LoaderType, 0, sizeof(LoaderType));
6633 LoaderType.tp_name = "vim.Loader";
6634 LoaderType.tp_basicsize = sizeof(LoaderObject);
6635 LoaderType.tp_flags = Py_TPFLAGS_DEFAULT;
6636 LoaderType.tp_doc = "vim message object";
6637 LoaderType.tp_methods = LoaderMethods;
6638 LoaderType.tp_dealloc = (destructor)LoaderDestructor;
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006639#endif
Bram Moolenaar81c40c52013-06-12 14:41:04 +02006640
Bram Moolenaar4d1da492013-04-24 13:39:15 +02006641#if PY_MAJOR_VERSION >= 3
6642 vim_memset(&vimmodule, 0, sizeof(vimmodule));
6643 vimmodule.m_name = "vim";
6644 vimmodule.m_doc = "Vim Python interface\n";
6645 vimmodule.m_size = -1;
6646 vimmodule.m_methods = VimMethods;
6647#endif
6648}
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006649
6650#define PYTYPE_READY(type) \
6651 if (PyType_Ready(&type)) \
6652 return -1;
6653
6654 static int
Bram Moolenaarfb97f282013-07-09 17:42:46 +02006655init_types(void)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006656{
6657 PYTYPE_READY(IterType);
6658 PYTYPE_READY(BufferType);
6659 PYTYPE_READY(RangeType);
6660 PYTYPE_READY(WindowType);
6661 PYTYPE_READY(TabPageType);
6662 PYTYPE_READY(BufMapType);
6663 PYTYPE_READY(WinListType);
6664 PYTYPE_READY(TabListType);
6665 PYTYPE_READY(CurrentType);
6666 PYTYPE_READY(DictionaryType);
6667 PYTYPE_READY(ListType);
6668 PYTYPE_READY(FunctionType);
6669 PYTYPE_READY(OptionsType);
6670 PYTYPE_READY(OutputType);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006671#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02006672 PYTYPE_READY(LoaderType);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006673#endif
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006674 return 0;
6675}
6676
6677 static int
Bram Moolenaar5ab9d982013-06-16 14:25:57 +02006678init_sys_path(void)
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006679{
6680 PyObject *path;
6681 PyObject *path_hook;
6682 PyObject *path_hooks;
6683
6684 if (!(path_hook = PyObject_GetAttrString(vim_module, "path_hook")))
6685 return -1;
6686
6687 if (!(path_hooks = PySys_GetObject("path_hooks")))
6688 {
6689 PyErr_Clear();
6690 path_hooks = PyList_New(1);
6691 PyList_SET_ITEM(path_hooks, 0, path_hook);
6692 if (PySys_SetObject("path_hooks", path_hooks))
6693 {
6694 Py_DECREF(path_hooks);
6695 return -1;
6696 }
6697 Py_DECREF(path_hooks);
6698 }
6699 else if (PyList_Check(path_hooks))
6700 {
6701 if (PyList_Append(path_hooks, path_hook))
6702 {
6703 Py_DECREF(path_hook);
6704 return -1;
6705 }
6706 Py_DECREF(path_hook);
6707 }
6708 else
6709 {
6710 VimTryStart();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006711 emsg(_("Failed to set path hook: sys.path_hooks is not a list\n"
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006712 "You should now do the following:\n"
6713 "- append vim.path_hook to sys.path_hooks\n"
6714 "- append vim.VIM_SPECIAL_PATH to sys.path\n"));
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006715 VimTryEnd(); // Discard the error
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006716 Py_DECREF(path_hook);
6717 return 0;
6718 }
6719
6720 if (!(path = PySys_GetObject("path")))
6721 {
6722 PyErr_Clear();
6723 path = PyList_New(1);
6724 Py_INCREF(vim_special_path_object);
6725 PyList_SET_ITEM(path, 0, vim_special_path_object);
6726 if (PySys_SetObject("path", path))
6727 {
6728 Py_DECREF(path);
6729 return -1;
6730 }
6731 Py_DECREF(path);
6732 }
6733 else if (PyList_Check(path))
6734 {
6735 if (PyList_Append(path, vim_special_path_object))
6736 return -1;
6737 }
6738 else
6739 {
6740 VimTryStart();
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01006741 emsg(_("Failed to set path: sys.path is not a list\n"
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006742 "You should now append vim.VIM_SPECIAL_PATH to sys.path"));
Bram Moolenaar9bf703d2019-11-30 19:44:38 +01006743 VimTryEnd(); // Discard the error
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006744 }
6745
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006746 return 0;
6747}
6748
6749static BufMapObject TheBufferMap =
6750{
6751 PyObject_HEAD_INIT(&BufMapType)
6752};
6753
6754static WinListObject TheWindowList =
6755{
6756 PyObject_HEAD_INIT(&WinListType)
6757 NULL
6758};
6759
6760static CurrentObject TheCurrent =
6761{
6762 PyObject_HEAD_INIT(&CurrentType)
6763};
6764
6765static TabListObject TheTabPageList =
6766{
6767 PyObject_HEAD_INIT(&TabListType)
6768};
6769
6770static struct numeric_constant {
6771 char *name;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006772 int val;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006773} numeric_constants[] = {
6774 {"VAR_LOCKED", VAR_LOCKED},
6775 {"VAR_FIXED", VAR_FIXED},
6776 {"VAR_SCOPE", VAR_SCOPE},
6777 {"VAR_DEF_SCOPE", VAR_DEF_SCOPE},
6778};
6779
6780static struct object_constant {
6781 char *name;
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006782 PyObject *valObject;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006783} object_constants[] = {
6784 {"buffers", (PyObject *)(void *)&TheBufferMap},
6785 {"windows", (PyObject *)(void *)&TheWindowList},
6786 {"tabpages", (PyObject *)(void *)&TheTabPageList},
6787 {"current", (PyObject *)(void *)&TheCurrent},
Bram Moolenaarcac867a2013-05-21 19:50:34 +02006788
6789 {"Buffer", (PyObject *)&BufferType},
6790 {"Range", (PyObject *)&RangeType},
6791 {"Window", (PyObject *)&WindowType},
6792 {"TabPage", (PyObject *)&TabPageType},
6793 {"Dictionary", (PyObject *)&DictionaryType},
6794 {"List", (PyObject *)&ListType},
6795 {"Function", (PyObject *)&FunctionType},
6796 {"Options", (PyObject *)&OptionsType},
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006797#if PY_VERSION_HEX < 0x030700f0
Bram Moolenaar81c40c52013-06-12 14:41:04 +02006798 {"_Loader", (PyObject *)&LoaderType},
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006799#endif
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006800};
6801
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006802#define ADD_OBJECT(m, name, obj) \
Bram Moolenaardee2e312013-06-23 16:35:47 +02006803 if (PyModule_AddObject(m, name, obj)) \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006804 return -1;
6805
6806#define ADD_CHECKED_OBJECT(m, name, obj) \
6807 { \
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006808 PyObject *valObject = obj; \
6809 if (!valObject) \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006810 return -1; \
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006811 ADD_OBJECT(m, name, valObject); \
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006812 }
6813
6814 static int
Bram Moolenaardee2e312013-06-23 16:35:47 +02006815populate_module(PyObject *m)
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006816{
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02006817 int i;
6818 PyObject *other_module;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02006819 PyObject *attr;
Bram Moolenaar81c40c52013-06-12 14:41:04 +02006820 PyObject *imp;
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006821#if PY_VERSION_HEX >= 0x030700f0
6822 PyObject *dict;
6823 PyObject *cls;
6824#endif
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006825
6826 for (i = 0; i < (int)(sizeof(numeric_constants)
6827 / sizeof(struct numeric_constant));
6828 ++i)
6829 ADD_CHECKED_OBJECT(m, numeric_constants[i].name,
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006830 PyInt_FromLong(numeric_constants[i].val));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006831
6832 for (i = 0; i < (int)(sizeof(object_constants)
6833 / sizeof(struct object_constant));
6834 ++i)
6835 {
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006836 PyObject *valObject;
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006837
Bram Moolenaarc4b99e02013-06-23 14:30:47 +02006838 valObject = object_constants[i].valObject;
6839 Py_INCREF(valObject);
6840 ADD_OBJECT(m, object_constants[i].name, valObject);
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006841 }
6842
6843 if (!(VimError = PyErr_NewException("vim.error", NULL, NULL)))
6844 return -1;
6845 ADD_OBJECT(m, "error", VimError);
6846
Bram Moolenaarda6c0332019-09-01 16:01:30 +02006847 ADD_CHECKED_OBJECT(m, "vars", NEW_DICTIONARY(get_globvar_dict()));
6848 ADD_CHECKED_OBJECT(m, "vvars", NEW_DICTIONARY(get_vimvar_dict()));
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006849 ADD_CHECKED_OBJECT(m, "options",
6850 OptionsNew(SREQ_GLOBAL, NULL, dummy_check, NULL));
Bram Moolenaarf4258302013-06-02 18:20:17 +02006851
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02006852 if (!(other_module = PyImport_ImportModule("os")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006853 return -1;
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02006854 ADD_OBJECT(m, "os", other_module);
Bram Moolenaarf4258302013-06-02 18:20:17 +02006855
Bram Moolenaar22081f42016-06-01 20:38:34 +02006856#if PY_MAJOR_VERSION >= 3
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02006857 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwd")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006858 return -1;
Bram Moolenaar22081f42016-06-01 20:38:34 +02006859#else
6860 if (!(py_getcwd = PyObject_GetAttrString(other_module, "getcwdu")))
6861 return -1;
6862#endif
Bram Moolenaarf4258302013-06-02 18:20:17 +02006863 ADD_OBJECT(m, "_getcwd", py_getcwd)
6864
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02006865 if (!(py_chdir = PyObject_GetAttrString(other_module, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006866 return -1;
6867 ADD_OBJECT(m, "_chdir", py_chdir);
Bram Moolenaardee2e312013-06-23 16:35:47 +02006868 if (!(attr = PyObject_GetAttrString(m, "chdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006869 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02006870 if (PyObject_SetAttrString(other_module, "chdir", attr))
6871 {
6872 Py_DECREF(attr);
6873 return -1;
6874 }
6875 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02006876
Bram Moolenaarc1ba10c2013-06-10 20:39:03 +02006877 if ((py_fchdir = PyObject_GetAttrString(other_module, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006878 {
6879 ADD_OBJECT(m, "_fchdir", py_fchdir);
Bram Moolenaardee2e312013-06-23 16:35:47 +02006880 if (!(attr = PyObject_GetAttrString(m, "fchdir")))
Bram Moolenaarf4258302013-06-02 18:20:17 +02006881 return -1;
Bram Moolenaarf9c9b322013-06-10 20:47:36 +02006882 if (PyObject_SetAttrString(other_module, "fchdir", attr))
6883 {
6884 Py_DECREF(attr);
6885 return -1;
6886 }
6887 Py_DECREF(attr);
Bram Moolenaarf4258302013-06-02 18:20:17 +02006888 }
Bram Moolenaare9056b12013-06-03 20:04:48 +02006889 else
6890 PyErr_Clear();
Bram Moolenaarf4258302013-06-02 18:20:17 +02006891
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006892 if (!(vim_special_path_object = PyString_FromString(vim_special_path)))
6893 return -1;
6894
6895 ADD_OBJECT(m, "VIM_SPECIAL_PATH", vim_special_path_object);
6896
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006897#if PY_VERSION_HEX >= 0x030700f0
6898 if (!(imp = PyImport_ImportModule("importlib.machinery")))
6899 return -1;
6900
6901 dict = PyModule_GetDict(imp);
6902
6903 if (!(cls = PyDict_GetItemString(dict, "PathFinder")))
6904 {
6905 Py_DECREF(imp);
6906 return -1;
6907 }
6908
6909 if (!(py_find_spec = PyObject_GetAttrString(cls, "find_spec")))
6910 {
6911 Py_DECREF(imp);
6912 return -1;
6913 }
6914
Bram Moolenaarb999ba22019-02-14 13:28:45 +01006915 if ((py_find_module = PyObject_GetAttrString(cls, "find_module")))
6916 {
6917 // find_module() is deprecated, this may stop working in some later
6918 // version.
6919 ADD_OBJECT(m, "_find_module", py_find_module);
6920 }
6921
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006922 Py_DECREF(imp);
6923
6924 ADD_OBJECT(m, "_find_spec", py_find_spec);
6925#else
Bram Moolenaar81c40c52013-06-12 14:41:04 +02006926 if (!(imp = PyImport_ImportModule("imp")))
6927 return -1;
6928
6929 if (!(py_find_module = PyObject_GetAttrString(imp, "find_module")))
6930 {
6931 Py_DECREF(imp);
6932 return -1;
6933 }
6934
6935 if (!(py_load_module = PyObject_GetAttrString(imp, "load_module")))
6936 {
6937 Py_DECREF(py_find_module);
6938 Py_DECREF(imp);
6939 return -1;
6940 }
6941
6942 Py_DECREF(imp);
6943
Bram Moolenaar9f3685a2013-06-12 14:20:36 +02006944 ADD_OBJECT(m, "_find_module", py_find_module);
6945 ADD_OBJECT(m, "_load_module", py_load_module);
Bram Moolenaar79a494d2018-07-22 04:30:21 +02006946#endif
Bram Moolenaarc09a6d62013-06-10 21:27:29 +02006947
Bram Moolenaar1dc28782013-05-21 19:11:01 +02006948 return 0;
6949}