blob: 07eedb5f314be33b686dad8a74d72e6029ebb449 [file] [log] [blame]
Bram Moolenaar170bf1a2010-07-24 23:51:45 +02001/* vi:set ts=8 sts=4 sw=4:
2 *
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/*
10 * Python extensions by Paul Moore, David Leonard, Roland Puntaier.
11 *
12 * Common code for if_python.c and if_python3.c.
13 */
14
Bram Moolenaar91805fc2011-06-26 04:01:44 +020015#ifdef FEAT_MBYTE
16# define ENC_OPT p_enc
17#else
18# define ENC_OPT "latin1"
19#endif
20
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020021/*
22 * obtain a lock on the Vim data structures
23 */
24 static void
25Python_Lock_Vim(void)
26{
27}
28
29/*
30 * release a lock on the Vim data structures
31 */
32 static void
33Python_Release_Vim(void)
34{
35}
36
37/* Output object definition
38 */
39
40static PyObject *OutputWrite(PyObject *, PyObject *);
41static PyObject *OutputWritelines(PyObject *, PyObject *);
Bram Moolenaara29a37d2011-03-22 15:47:44 +010042static PyObject *OutputFlush(PyObject *, PyObject *);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020043
Bram Moolenaar2eea1982010-09-21 16:49:37 +020044/* Function to write a line, points to either msg() or emsg(). */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020045typedef void (*writefn)(char_u *);
46static void writer(writefn fn, char_u *str, PyInt n);
47
48typedef struct
49{
50 PyObject_HEAD
51 long softspace;
52 long error;
53} OutputObject;
54
55static struct PyMethodDef OutputMethods[] = {
56 /* name, function, calling, documentation */
Bram Moolenaara29a37d2011-03-22 15:47:44 +010057 {"write", OutputWrite, 1, ""},
58 {"writelines", OutputWritelines, 1, ""},
59 {"flush", OutputFlush, 1, ""},
60 { NULL, NULL, 0, NULL}
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020061};
62
Bram Moolenaarca8a4df2010-07-31 19:54:14 +020063#define PyErr_SetVim(str) PyErr_SetString(VimError, str)
64
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020065/*************/
66
67/* Output buffer management
68 */
69
70 static PyObject *
71OutputWrite(PyObject *self, PyObject *args)
72{
73 int len;
Bram Moolenaar19e60942011-06-19 00:27:51 +020074 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020075 int error = ((OutputObject *)(self))->error;
76
Bram Moolenaar91805fc2011-06-26 04:01:44 +020077 if (!PyArg_ParseTuple(args, "es#", ENC_OPT, &str, &len))
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020078 return NULL;
79
80 Py_BEGIN_ALLOW_THREADS
81 Python_Lock_Vim();
82 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
83 Python_Release_Vim();
84 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +020085 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +020086
87 Py_INCREF(Py_None);
88 return Py_None;
89}
90
91 static PyObject *
92OutputWritelines(PyObject *self, PyObject *args)
93{
94 PyInt n;
95 PyInt i;
96 PyObject *list;
97 int error = ((OutputObject *)(self))->error;
98
99 if (!PyArg_ParseTuple(args, "O", &list))
100 return NULL;
101 Py_INCREF(list);
102
103 if (!PyList_Check(list)) {
104 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
105 Py_DECREF(list);
106 return NULL;
107 }
108
109 n = PyList_Size(list);
110
111 for (i = 0; i < n; ++i)
112 {
113 PyObject *line = PyList_GetItem(list, i);
Bram Moolenaar19e60942011-06-19 00:27:51 +0200114 char *str = NULL;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200115 PyInt len;
116
Bram Moolenaar91805fc2011-06-26 04:01:44 +0200117 if (!PyArg_Parse(line, "es#", ENC_OPT, &str, &len)) {
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200118 PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
119 Py_DECREF(list);
120 return NULL;
121 }
122
123 Py_BEGIN_ALLOW_THREADS
124 Python_Lock_Vim();
125 writer((writefn)(error ? emsg : msg), (char_u *)str, len);
126 Python_Release_Vim();
127 Py_END_ALLOW_THREADS
Bram Moolenaar19e60942011-06-19 00:27:51 +0200128 PyMem_Free(str);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200129 }
130
131 Py_DECREF(list);
132 Py_INCREF(Py_None);
133 return Py_None;
134}
135
Bram Moolenaara29a37d2011-03-22 15:47:44 +0100136 static PyObject *
137OutputFlush(PyObject *self UNUSED, PyObject *args UNUSED)
138{
139 /* do nothing */
140 Py_INCREF(Py_None);
141 return Py_None;
142}
143
144
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200145/* Buffer IO, we write one whole line at a time. */
146static garray_T io_ga = {0, 0, 1, 80, NULL};
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200147static writefn old_fn = NULL;
148
149 static void
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200150PythonIO_Flush(void)
151{
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200152 if (old_fn != NULL && io_ga.ga_len > 0)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200153 {
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200154 ((char_u *)io_ga.ga_data)[io_ga.ga_len] = NUL;
155 old_fn((char_u *)io_ga.ga_data);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200156 }
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200157 io_ga.ga_len = 0;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200158}
159
160 static void
161writer(writefn fn, char_u *str, PyInt n)
162{
163 char_u *ptr;
164
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200165 /* Flush when switching output function. */
166 if (fn != old_fn)
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200167 PythonIO_Flush();
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200168 old_fn = fn;
169
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200170 /* Write each NL separated line. Text after the last NL is kept for
171 * writing later. */
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200172 while (n > 0 && (ptr = memchr(str, '\n', n)) != NULL)
173 {
174 PyInt len = ptr - str;
175
Bram Moolenaar6b5ef062010-10-27 12:18:00 +0200176 if (ga_grow(&io_ga, (int)(len + 1)) == FAIL)
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200177 break;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200178
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200179 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)len);
180 ((char *)io_ga.ga_data)[io_ga.ga_len + len] = NUL;
181 fn((char_u *)io_ga.ga_data);
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200182 str = ptr + 1;
183 n -= len + 1;
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200184 io_ga.ga_len = 0;
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200185 }
186
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200187 /* Put the remaining text into io_ga for later printing. */
Bram Moolenaar6b5ef062010-10-27 12:18:00 +0200188 if (n > 0 && ga_grow(&io_ga, (int)(n + 1)) == OK)
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200189 {
190 mch_memmove(((char *)io_ga.ga_data) + io_ga.ga_len, str, (size_t)n);
Bram Moolenaar6b5ef062010-10-27 12:18:00 +0200191 io_ga.ga_len += (int)n;
Bram Moolenaar2eea1982010-09-21 16:49:37 +0200192 }
Bram Moolenaar170bf1a2010-07-24 23:51:45 +0200193}
194
195/***************/
196
197static PyTypeObject OutputType;
198
199static OutputObject Output =
200{
201 PyObject_HEAD_INIT(&OutputType)
202 0,
203 0
204};
205
206static OutputObject Error =
207{
208 PyObject_HEAD_INIT(&OutputType)
209 0,
210 1
211};
212
213 static int
214PythonIO_Init_io(void)
215{
216 PySys_SetObject("stdout", (PyObject *)(void *)&Output);
217 PySys_SetObject("stderr", (PyObject *)(void *)&Error);
218
219 if (PyErr_Occurred())
220 {
221 EMSG(_("E264: Python: Error initialising I/O objects"));
222 return -1;
223 }
224
225 return 0;
226}
227
228
229static PyObject *VimError;
230
231/* Check to see whether a Vim error has been reported, or a keyboard
232 * interrupt has been detected.
233 */
234 static int
235VimErrorCheck(void)
236{
237 if (got_int)
238 {
239 PyErr_SetNone(PyExc_KeyboardInterrupt);
240 return 1;
241 }
242 else if (did_emsg && !PyErr_Occurred())
243 {
244 PyErr_SetNone(VimError);
245 return 1;
246 }
247
248 return 0;
249}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200250
251/* Vim module - Implementation
252 */
253 static PyObject *
254VimCommand(PyObject *self UNUSED, PyObject *args)
255{
256 char *cmd;
257 PyObject *result;
258
259 if (!PyArg_ParseTuple(args, "s", &cmd))
260 return NULL;
261
262 PyErr_Clear();
263
264 Py_BEGIN_ALLOW_THREADS
265 Python_Lock_Vim();
266
267 do_cmdline_cmd((char_u *)cmd);
268 update_screen(VALID);
269
270 Python_Release_Vim();
271 Py_END_ALLOW_THREADS
272
273 if (VimErrorCheck())
274 result = NULL;
275 else
276 result = Py_None;
277
278 Py_XINCREF(result);
279 return result;
280}
281
282#ifdef FEAT_EVAL
283/*
284 * Function to translate a typval_T into a PyObject; this will recursively
285 * translate lists/dictionaries into their Python equivalents.
286 *
287 * The depth parameter is to avoid infinite recursion, set it to 1 when
288 * you call VimToPython.
289 */
290 static PyObject *
291VimToPython(typval_T *our_tv, int depth, PyObject *lookupDict)
292{
293 PyObject *result;
294 PyObject *newObj;
295 char ptrBuf[NUMBUFLEN];
296
297 /* Avoid infinite recursion */
298 if (depth > 100)
299 {
300 Py_INCREF(Py_None);
301 result = Py_None;
302 return result;
303 }
304
305 /* Check if we run into a recursive loop. The item must be in lookupDict
306 * then and we can use it again. */
307 if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
308 || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
309 {
310 sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U,
311 our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list
312 : (long_u)our_tv->vval.v_dict);
313 result = PyDict_GetItemString(lookupDict, ptrBuf);
314 if (result != NULL)
315 {
316 Py_INCREF(result);
317 return result;
318 }
319 }
320
321 if (our_tv->v_type == VAR_STRING)
322 {
323 result = Py_BuildValue("s", our_tv->vval.v_string);
324 }
325 else if (our_tv->v_type == VAR_NUMBER)
326 {
327 char buf[NUMBUFLEN];
328
329 /* For backwards compatibility numbers are stored as strings. */
330 sprintf(buf, "%ld", (long)our_tv->vval.v_number);
331 result = Py_BuildValue("s", buf);
332 }
333# ifdef FEAT_FLOAT
334 else if (our_tv->v_type == VAR_FLOAT)
335 {
336 char buf[NUMBUFLEN];
337
338 sprintf(buf, "%f", our_tv->vval.v_float);
339 result = Py_BuildValue("s", buf);
340 }
341# endif
342 else if (our_tv->v_type == VAR_LIST)
343 {
344 list_T *list = our_tv->vval.v_list;
345 listitem_T *curr;
346
347 result = PyList_New(0);
348
349 if (list != NULL)
350 {
351 PyDict_SetItemString(lookupDict, ptrBuf, result);
352
353 for (curr = list->lv_first; curr != NULL; curr = curr->li_next)
354 {
355 newObj = VimToPython(&curr->li_tv, depth + 1, lookupDict);
356 PyList_Append(result, newObj);
357 Py_DECREF(newObj);
358 }
359 }
360 }
361 else if (our_tv->v_type == VAR_DICT)
362 {
363 result = PyDict_New();
364
365 if (our_tv->vval.v_dict != NULL)
366 {
367 hashtab_T *ht = &our_tv->vval.v_dict->dv_hashtab;
368 long_u todo = ht->ht_used;
369 hashitem_T *hi;
370 dictitem_T *di;
371
372 PyDict_SetItemString(lookupDict, ptrBuf, result);
373
374 for (hi = ht->ht_array; todo > 0; ++hi)
375 {
376 if (!HASHITEM_EMPTY(hi))
377 {
378 --todo;
379
380 di = dict_lookup(hi);
381 newObj = VimToPython(&di->di_tv, depth + 1, lookupDict);
382 PyDict_SetItemString(result, (char *)hi->hi_key, newObj);
383 Py_DECREF(newObj);
384 }
385 }
386 }
387 }
388 else
389 {
390 Py_INCREF(Py_None);
391 result = Py_None;
392 }
393
394 return result;
395}
396#endif
397
398 static PyObject *
Bram Moolenaar09092152010-08-08 16:38:42 +0200399VimEval(PyObject *self UNUSED, PyObject *args UNUSED)
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200400{
401#ifdef FEAT_EVAL
402 char *expr;
403 typval_T *our_tv;
404 PyObject *result;
405 PyObject *lookup_dict;
406
407 if (!PyArg_ParseTuple(args, "s", &expr))
408 return NULL;
409
410 Py_BEGIN_ALLOW_THREADS
411 Python_Lock_Vim();
412 our_tv = eval_expr((char_u *)expr, NULL);
413
414 Python_Release_Vim();
415 Py_END_ALLOW_THREADS
416
417 if (our_tv == NULL)
418 {
419 PyErr_SetVim(_("invalid expression"));
420 return NULL;
421 }
422
423 /* Convert the Vim type into a Python type. Create a dictionary that's
424 * used to check for recursive loops. */
425 lookup_dict = PyDict_New();
426 result = VimToPython(our_tv, 1, lookup_dict);
427 Py_DECREF(lookup_dict);
428
429
430 Py_BEGIN_ALLOW_THREADS
431 Python_Lock_Vim();
432 free_tv(our_tv);
433 Python_Release_Vim();
434 Py_END_ALLOW_THREADS
435
436 return result;
437#else
438 PyErr_SetVim(_("expressions disabled at compile time"));
439 return NULL;
440#endif
441}
442
443/*
444 * Vim module - Definitions
445 */
446
447static struct PyMethodDef VimMethods[] = {
448 /* name, function, calling, documentation */
449 {"command", VimCommand, 1, "Execute a Vim ex-mode command" },
450 {"eval", VimEval, 1, "Evaluate an expression using Vim evaluator" },
451 { NULL, NULL, 0, NULL }
452};
453
454typedef struct
455{
456 PyObject_HEAD
457 buf_T *buf;
458}
459BufferObject;
460
461#define INVALID_BUFFER_VALUE ((buf_T *)(-1))
462
463/*
464 * Buffer list object - Implementation
465 */
466
467 static PyInt
468BufListLength(PyObject *self UNUSED)
469{
470 buf_T *b = firstbuf;
471 PyInt n = 0;
472
473 while (b)
474 {
475 ++n;
476 b = b->b_next;
477 }
478
479 return n;
480}
481
482 static PyObject *
483BufListItem(PyObject *self UNUSED, PyInt n)
484{
485 buf_T *b;
486
487 for (b = firstbuf; b; b = b->b_next, --n)
488 {
489 if (n == 0)
490 return BufferNew(b);
491 }
492
493 PyErr_SetString(PyExc_IndexError, _("no such buffer"));
494 return NULL;
495}
496
497typedef struct
498{
499 PyObject_HEAD
500 win_T *win;
501} WindowObject;
502
503#define INVALID_WINDOW_VALUE ((win_T *)(-1))
504
505 static int
506CheckWindow(WindowObject *this)
507{
508 if (this->win == INVALID_WINDOW_VALUE)
509 {
510 PyErr_SetVim(_("attempt to refer to deleted window"));
511 return -1;
512 }
513
514 return 0;
515}
516
517static int WindowSetattr(PyObject *, char *, PyObject *);
518static PyObject *WindowRepr(PyObject *);
519
520 static int
521WindowSetattr(PyObject *self, char *name, PyObject *val)
522{
523 WindowObject *this = (WindowObject *)(self);
524
525 if (CheckWindow(this))
526 return -1;
527
528 if (strcmp(name, "buffer") == 0)
529 {
530 PyErr_SetString(PyExc_TypeError, _("readonly attribute"));
531 return -1;
532 }
533 else if (strcmp(name, "cursor") == 0)
534 {
535 long lnum;
536 long col;
537 long len;
538
539 if (!PyArg_Parse(val, "(ll)", &lnum, &col))
540 return -1;
541
542 if (lnum <= 0 || lnum > this->win->w_buffer->b_ml.ml_line_count)
543 {
544 PyErr_SetVim(_("cursor position outside buffer"));
545 return -1;
546 }
547
548 /* Check for keyboard interrupts */
549 if (VimErrorCheck())
550 return -1;
551
552 /* When column is out of range silently correct it. */
553 len = (long)STRLEN(ml_get_buf(this->win->w_buffer, lnum, FALSE));
554 if (col > len)
555 col = len;
556
557 this->win->w_cursor.lnum = lnum;
558 this->win->w_cursor.col = col;
559#ifdef FEAT_VIRTUALEDIT
560 this->win->w_cursor.coladd = 0;
561#endif
562 update_screen(VALID);
563
564 return 0;
565 }
566 else if (strcmp(name, "height") == 0)
567 {
568 int height;
569 win_T *savewin;
570
571 if (!PyArg_Parse(val, "i", &height))
572 return -1;
573
574#ifdef FEAT_GUI
575 need_mouse_correct = TRUE;
576#endif
577 savewin = curwin;
578 curwin = this->win;
579 win_setheight(height);
580 curwin = savewin;
581
582 /* Check for keyboard interrupts */
583 if (VimErrorCheck())
584 return -1;
585
586 return 0;
587 }
588#ifdef FEAT_VERTSPLIT
589 else if (strcmp(name, "width") == 0)
590 {
591 int width;
592 win_T *savewin;
593
594 if (!PyArg_Parse(val, "i", &width))
595 return -1;
596
597#ifdef FEAT_GUI
598 need_mouse_correct = TRUE;
599#endif
600 savewin = curwin;
601 curwin = this->win;
602 win_setwidth(width);
603 curwin = savewin;
604
605 /* Check for keyboard interrupts */
606 if (VimErrorCheck())
607 return -1;
608
609 return 0;
610 }
611#endif
612 else
613 {
614 PyErr_SetString(PyExc_AttributeError, name);
615 return -1;
616 }
617}
618
619 static PyObject *
620WindowRepr(PyObject *self)
621{
622 static char repr[100];
623 WindowObject *this = (WindowObject *)(self);
624
625 if (this->win == INVALID_WINDOW_VALUE)
626 {
627 vim_snprintf(repr, 100, _("<window object (deleted) at %p>"), (self));
628 return PyString_FromString(repr);
629 }
630 else
631 {
632 int i = 0;
633 win_T *w;
634
635 for (w = firstwin; w != NULL && w != this->win; w = W_NEXT(w))
636 ++i;
637
638 if (w == NULL)
639 vim_snprintf(repr, 100, _("<window object (unknown) at %p>"),
640 (self));
641 else
642 vim_snprintf(repr, 100, _("<window %d>"), i);
643
644 return PyString_FromString(repr);
645 }
646}
647
648/*
649 * Window list object - Implementation
650 */
651 static PyInt
652WinListLength(PyObject *self UNUSED)
653{
654 win_T *w = firstwin;
655 PyInt n = 0;
656
657 while (w != NULL)
658 {
659 ++n;
660 w = W_NEXT(w);
661 }
662
663 return n;
664}
665
666 static PyObject *
667WinListItem(PyObject *self UNUSED, PyInt n)
668{
669 win_T *w;
670
671 for (w = firstwin; w != NULL; w = W_NEXT(w), --n)
672 if (n == 0)
673 return WindowNew(w);
674
675 PyErr_SetString(PyExc_IndexError, _("no such window"));
676 return NULL;
677}
678
679/* Convert a Python string into a Vim line.
680 *
681 * The result is in allocated memory. All internal nulls are replaced by
682 * newline characters. It is an error for the string to contain newline
683 * characters.
684 *
685 * On errors, the Python exception data is set, and NULL is returned.
686 */
687 static char *
688StringToLine(PyObject *obj)
689{
690 const char *str;
691 char *save;
Bram Moolenaar19e60942011-06-19 00:27:51 +0200692 PyObject *bytes;
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200693 PyInt len;
694 PyInt i;
695 char *p;
696
697 if (obj == NULL || !PyString_Check(obj))
698 {
699 PyErr_BadArgument();
700 return NULL;
701 }
702
Bram Moolenaar19e60942011-06-19 00:27:51 +0200703 bytes = PyString_AsBytes(obj); /* for Python 2 this does nothing */
704 str = PyString_AsString(bytes);
705 len = PyString_Size(bytes);
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200706
707 /*
708 * Error checking: String must not contain newlines, as we
709 * are replacing a single line, and we must replace it with
710 * a single line.
711 * A trailing newline is removed, so that append(f.readlines()) works.
712 */
713 p = memchr(str, '\n', len);
714 if (p != NULL)
715 {
716 if (p == str + len - 1)
717 --len;
718 else
719 {
720 PyErr_SetVim(_("string cannot contain newlines"));
721 return NULL;
722 }
723 }
724
725 /* Create a copy of the string, with internal nulls replaced by
726 * newline characters, as is the vim convention.
727 */
728 save = (char *)alloc((unsigned)(len+1));
729 if (save == NULL)
730 {
731 PyErr_NoMemory();
732 return NULL;
733 }
734
735 for (i = 0; i < len; ++i)
736 {
737 if (str[i] == '\0')
738 save[i] = '\n';
739 else
740 save[i] = str[i];
741 }
742
743 save[i] = '\0';
Bram Moolenaar19e60942011-06-19 00:27:51 +0200744 PyString_FreeBytes(bytes); /* Python 2 does nothing here */
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200745
746 return save;
747}
748
749/* Get a line from the specified buffer. The line number is
750 * in Vim format (1-based). The line is returned as a Python
751 * string object.
752 */
753 static PyObject *
754GetBufferLine(buf_T *buf, PyInt n)
755{
756 return LineToString((char *)ml_get_buf(buf, (linenr_T)n, FALSE));
757}
758
759
760/* Get a list of lines from the specified buffer. The line numbers
761 * are in Vim format (1-based). The range is from lo up to, but not
762 * including, hi. The list is returned as a Python list of string objects.
763 */
764 static PyObject *
765GetBufferLineList(buf_T *buf, PyInt lo, PyInt hi)
766{
767 PyInt i;
768 PyInt n = hi - lo;
769 PyObject *list = PyList_New(n);
770
771 if (list == NULL)
772 return NULL;
773
774 for (i = 0; i < n; ++i)
775 {
776 PyObject *str = LineToString((char *)ml_get_buf(buf, (linenr_T)(lo+i), FALSE));
777
778 /* Error check - was the Python string creation OK? */
779 if (str == NULL)
780 {
781 Py_DECREF(list);
782 return NULL;
783 }
784
785 /* Set the list item */
786 if (PyList_SetItem(list, i, str))
787 {
788 Py_DECREF(str);
789 Py_DECREF(list);
790 return NULL;
791 }
792 }
793
794 /* The ownership of the Python list is passed to the caller (ie,
795 * the caller should Py_DECREF() the object when it is finished
796 * with it).
797 */
798
799 return list;
800}
801
802/*
803 * Check if deleting lines made the cursor position invalid.
804 * Changed the lines from "lo" to "hi" and added "extra" lines (negative if
805 * deleted).
806 */
807 static void
808py_fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
809{
810 if (curwin->w_cursor.lnum >= lo)
811 {
812 /* Adjust the cursor position if it's in/after the changed
813 * lines. */
814 if (curwin->w_cursor.lnum >= hi)
815 {
816 curwin->w_cursor.lnum += extra;
817 check_cursor_col();
818 }
819 else if (extra < 0)
820 {
821 curwin->w_cursor.lnum = lo;
822 check_cursor();
823 }
824 else
825 check_cursor_col();
826 changed_cline_bef_curs();
827 }
828 invalidate_botline();
829}
830
Bram Moolenaar19e60942011-06-19 00:27:51 +0200831/*
832 * Replace a line in the specified buffer. The line number is
Bram Moolenaarca8a4df2010-07-31 19:54:14 +0200833 * in Vim format (1-based). The replacement line is given as
834 * a Python string object. The object is checked for validity
835 * and correct format. Errors are returned as a value of FAIL.
836 * The return value is OK on success.
837 * If OK is returned and len_change is not NULL, *len_change
838 * is set to the change in the buffer length.
839 */
840 static int
841SetBufferLine(buf_T *buf, PyInt n, PyObject *line, PyInt *len_change)
842{
843 /* First of all, we check the thpe of the supplied Python object.
844 * There are three cases:
845 * 1. NULL, or None - this is a deletion.
846 * 2. A string - this is a replacement.
847 * 3. Anything else - this is an error.
848 */
849 if (line == Py_None || line == NULL)
850 {
851 buf_T *savebuf = curbuf;
852
853 PyErr_Clear();
854 curbuf = buf;
855
856 if (u_savedel((linenr_T)n, 1L) == FAIL)
857 PyErr_SetVim(_("cannot save undo information"));
858 else if (ml_delete((linenr_T)n, FALSE) == FAIL)
859 PyErr_SetVim(_("cannot delete line"));
860 else
861 {
862 if (buf == curwin->w_buffer)
863 py_fix_cursor((linenr_T)n, (linenr_T)n + 1, (linenr_T)-1);
864 deleted_lines_mark((linenr_T)n, 1L);
865 }
866
867 curbuf = savebuf;
868
869 if (PyErr_Occurred() || VimErrorCheck())
870 return FAIL;
871
872 if (len_change)
873 *len_change = -1;
874
875 return OK;
876 }
877 else if (PyString_Check(line))
878 {
879 char *save = StringToLine(line);
880 buf_T *savebuf = curbuf;
881
882 if (save == NULL)
883 return FAIL;
884
885 /* We do not need to free "save" if ml_replace() consumes it. */
886 PyErr_Clear();
887 curbuf = buf;
888
889 if (u_savesub((linenr_T)n) == FAIL)
890 {
891 PyErr_SetVim(_("cannot save undo information"));
892 vim_free(save);
893 }
894 else if (ml_replace((linenr_T)n, (char_u *)save, FALSE) == FAIL)
895 {
896 PyErr_SetVim(_("cannot replace line"));
897 vim_free(save);
898 }
899 else
900 changed_bytes((linenr_T)n, 0);
901
902 curbuf = savebuf;
903
904 /* Check that the cursor is not beyond the end of the line now. */
905 if (buf == curwin->w_buffer)
906 check_cursor_col();
907
908 if (PyErr_Occurred() || VimErrorCheck())
909 return FAIL;
910
911 if (len_change)
912 *len_change = 0;
913
914 return OK;
915 }
916 else
917 {
918 PyErr_BadArgument();
919 return FAIL;
920 }
921}
922
Bram Moolenaar19e60942011-06-19 00:27:51 +0200923/* Replace a range of lines in the specified buffer. The line numbers are in
924 * Vim format (1-based). The range is from lo up to, but not including, hi.
925 * The replacement lines are given as a Python list of string objects. The
926 * list is checked for validity and correct format. Errors are returned as a
927 * value of FAIL. The return value is OK on success.
928 * If OK is returned and len_change is not NULL, *len_change
929 * is set to the change in the buffer length.
930 */
931 static int
932SetBufferLineList(buf_T *buf, PyInt lo, PyInt hi, PyObject *list, PyInt *len_change)
933{
934 /* First of all, we check the thpe of the supplied Python object.
935 * There are three cases:
936 * 1. NULL, or None - this is a deletion.
937 * 2. A list - this is a replacement.
938 * 3. Anything else - this is an error.
939 */
940 if (list == Py_None || list == NULL)
941 {
942 PyInt i;
943 PyInt n = (int)(hi - lo);
944 buf_T *savebuf = curbuf;
945
946 PyErr_Clear();
947 curbuf = buf;
948
949 if (u_savedel((linenr_T)lo, (long)n) == FAIL)
950 PyErr_SetVim(_("cannot save undo information"));
951 else
952 {
953 for (i = 0; i < n; ++i)
954 {
955 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
956 {
957 PyErr_SetVim(_("cannot delete line"));
958 break;
959 }
960 }
961 if (buf == curwin->w_buffer)
962 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)-n);
963 deleted_lines_mark((linenr_T)lo, (long)i);
964 }
965
966 curbuf = savebuf;
967
968 if (PyErr_Occurred() || VimErrorCheck())
969 return FAIL;
970
971 if (len_change)
972 *len_change = -n;
973
974 return OK;
975 }
976 else if (PyList_Check(list))
977 {
978 PyInt i;
979 PyInt new_len = PyList_Size(list);
980 PyInt old_len = hi - lo;
981 PyInt extra = 0; /* lines added to text, can be negative */
982 char **array;
983 buf_T *savebuf;
984
985 if (new_len == 0) /* avoid allocating zero bytes */
986 array = NULL;
987 else
988 {
989 array = (char **)alloc((unsigned)(new_len * sizeof(char *)));
990 if (array == NULL)
991 {
992 PyErr_NoMemory();
993 return FAIL;
994 }
995 }
996
997 for (i = 0; i < new_len; ++i)
998 {
999 PyObject *line = PyList_GetItem(list, i);
1000
1001 array[i] = StringToLine(line);
1002 if (array[i] == NULL)
1003 {
1004 while (i)
1005 vim_free(array[--i]);
1006 vim_free(array);
1007 return FAIL;
1008 }
1009 }
1010
1011 savebuf = curbuf;
1012
1013 PyErr_Clear();
1014 curbuf = buf;
1015
1016 if (u_save((linenr_T)(lo-1), (linenr_T)hi) == FAIL)
1017 PyErr_SetVim(_("cannot save undo information"));
1018
1019 /* If the size of the range is reducing (ie, new_len < old_len) we
1020 * need to delete some old_len. We do this at the start, by
1021 * repeatedly deleting line "lo".
1022 */
1023 if (!PyErr_Occurred())
1024 {
1025 for (i = 0; i < old_len - new_len; ++i)
1026 if (ml_delete((linenr_T)lo, FALSE) == FAIL)
1027 {
1028 PyErr_SetVim(_("cannot delete line"));
1029 break;
1030 }
1031 extra -= i;
1032 }
1033
1034 /* For as long as possible, replace the existing old_len with the
1035 * new old_len. This is a more efficient operation, as it requires
1036 * less memory allocation and freeing.
1037 */
1038 if (!PyErr_Occurred())
1039 {
1040 for (i = 0; i < old_len && i < new_len; ++i)
1041 if (ml_replace((linenr_T)(lo+i), (char_u *)array[i], FALSE)
1042 == FAIL)
1043 {
1044 PyErr_SetVim(_("cannot replace line"));
1045 break;
1046 }
1047 }
1048 else
1049 i = 0;
1050
1051 /* Now we may need to insert the remaining new old_len. If we do, we
1052 * must free the strings as we finish with them (we can't pass the
1053 * responsibility to vim in this case).
1054 */
1055 if (!PyErr_Occurred())
1056 {
1057 while (i < new_len)
1058 {
1059 if (ml_append((linenr_T)(lo + i - 1),
1060 (char_u *)array[i], 0, FALSE) == FAIL)
1061 {
1062 PyErr_SetVim(_("cannot insert line"));
1063 break;
1064 }
1065 vim_free(array[i]);
1066 ++i;
1067 ++extra;
1068 }
1069 }
1070
1071 /* Free any left-over old_len, as a result of an error */
1072 while (i < new_len)
1073 {
1074 vim_free(array[i]);
1075 ++i;
1076 }
1077
1078 /* Free the array of old_len. All of its contents have now
1079 * been dealt with (either freed, or the responsibility passed
1080 * to vim.
1081 */
1082 vim_free(array);
1083
1084 /* Adjust marks. Invalidate any which lie in the
1085 * changed range, and move any in the remainder of the buffer.
1086 */
1087 mark_adjust((linenr_T)lo, (linenr_T)(hi - 1),
1088 (long)MAXLNUM, (long)extra);
1089 changed_lines((linenr_T)lo, 0, (linenr_T)hi, (long)extra);
1090
1091 if (buf == curwin->w_buffer)
1092 py_fix_cursor((linenr_T)lo, (linenr_T)hi, (linenr_T)extra);
1093
1094 curbuf = savebuf;
1095
1096 if (PyErr_Occurred() || VimErrorCheck())
1097 return FAIL;
1098
1099 if (len_change)
1100 *len_change = new_len - old_len;
1101
1102 return OK;
1103 }
1104 else
1105 {
1106 PyErr_BadArgument();
1107 return FAIL;
1108 }
1109}
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001110
1111/* Insert a number of lines into the specified buffer after the specifed line.
1112 * The line number is in Vim format (1-based). The lines to be inserted are
1113 * given as a Python list of string objects or as a single string. The lines
1114 * to be added are checked for validity and correct format. Errors are
1115 * returned as a value of FAIL. The return value is OK on success.
1116 * If OK is returned and len_change is not NULL, *len_change
1117 * is set to the change in the buffer length.
1118 */
1119 static int
1120InsertBufferLines(buf_T *buf, PyInt n, PyObject *lines, PyInt *len_change)
1121{
1122 /* First of all, we check the type of the supplied Python object.
1123 * It must be a string or a list, or the call is in error.
1124 */
1125 if (PyString_Check(lines))
1126 {
1127 char *str = StringToLine(lines);
1128 buf_T *savebuf;
1129
1130 if (str == NULL)
1131 return FAIL;
1132
1133 savebuf = curbuf;
1134
1135 PyErr_Clear();
1136 curbuf = buf;
1137
1138 if (u_save((linenr_T)n, (linenr_T)(n+1)) == FAIL)
1139 PyErr_SetVim(_("cannot save undo information"));
1140 else if (ml_append((linenr_T)n, (char_u *)str, 0, FALSE) == FAIL)
1141 PyErr_SetVim(_("cannot insert line"));
1142 else
1143 appended_lines_mark((linenr_T)n, 1L);
1144
1145 vim_free(str);
1146 curbuf = savebuf;
1147 update_screen(VALID);
1148
1149 if (PyErr_Occurred() || VimErrorCheck())
1150 return FAIL;
1151
1152 if (len_change)
1153 *len_change = 1;
1154
1155 return OK;
1156 }
1157 else if (PyList_Check(lines))
1158 {
1159 PyInt i;
1160 PyInt size = PyList_Size(lines);
1161 char **array;
1162 buf_T *savebuf;
1163
1164 array = (char **)alloc((unsigned)(size * sizeof(char *)));
1165 if (array == NULL)
1166 {
1167 PyErr_NoMemory();
1168 return FAIL;
1169 }
1170
1171 for (i = 0; i < size; ++i)
1172 {
1173 PyObject *line = PyList_GetItem(lines, i);
1174 array[i] = StringToLine(line);
1175
1176 if (array[i] == NULL)
1177 {
1178 while (i)
1179 vim_free(array[--i]);
1180 vim_free(array);
1181 return FAIL;
1182 }
1183 }
1184
1185 savebuf = curbuf;
1186
1187 PyErr_Clear();
1188 curbuf = buf;
1189
1190 if (u_save((linenr_T)n, (linenr_T)(n + 1)) == FAIL)
1191 PyErr_SetVim(_("cannot save undo information"));
1192 else
1193 {
1194 for (i = 0; i < size; ++i)
1195 {
1196 if (ml_append((linenr_T)(n + i),
1197 (char_u *)array[i], 0, FALSE) == FAIL)
1198 {
1199 PyErr_SetVim(_("cannot insert line"));
1200
1201 /* Free the rest of the lines */
1202 while (i < size)
1203 vim_free(array[i++]);
1204
1205 break;
1206 }
1207 vim_free(array[i]);
1208 }
1209 if (i > 0)
1210 appended_lines_mark((linenr_T)n, (long)i);
1211 }
1212
1213 /* Free the array of lines. All of its contents have now
1214 * been freed.
1215 */
1216 vim_free(array);
1217
1218 curbuf = savebuf;
1219 update_screen(VALID);
1220
1221 if (PyErr_Occurred() || VimErrorCheck())
1222 return FAIL;
1223
1224 if (len_change)
1225 *len_change = size;
1226
1227 return OK;
1228 }
1229 else
1230 {
1231 PyErr_BadArgument();
1232 return FAIL;
1233 }
1234}
1235
1236/*
1237 * Common routines for buffers and line ranges
1238 * -------------------------------------------
1239 */
1240
1241 static int
1242CheckBuffer(BufferObject *this)
1243{
1244 if (this->buf == INVALID_BUFFER_VALUE)
1245 {
1246 PyErr_SetVim(_("attempt to refer to deleted buffer"));
1247 return -1;
1248 }
1249
1250 return 0;
1251}
1252
1253 static PyObject *
1254RBItem(BufferObject *self, PyInt n, PyInt start, PyInt end)
1255{
1256 if (CheckBuffer(self))
1257 return NULL;
1258
1259 if (n < 0 || n > end - start)
1260 {
1261 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
1262 return NULL;
1263 }
1264
1265 return GetBufferLine(self->buf, n+start);
1266}
1267
1268 static PyObject *
1269RBSlice(BufferObject *self, PyInt lo, PyInt hi, PyInt start, PyInt end)
1270{
1271 PyInt size;
1272
1273 if (CheckBuffer(self))
1274 return NULL;
1275
1276 size = end - start + 1;
1277
1278 if (lo < 0)
1279 lo = 0;
1280 else if (lo > size)
1281 lo = size;
1282 if (hi < 0)
1283 hi = 0;
1284 if (hi < lo)
1285 hi = lo;
1286 else if (hi > size)
1287 hi = size;
1288
1289 return GetBufferLineList(self->buf, lo+start, hi+start);
1290}
1291
1292 static PyInt
1293RBAsItem(BufferObject *self, PyInt n, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
1294{
1295 PyInt len_change;
1296
1297 if (CheckBuffer(self))
1298 return -1;
1299
1300 if (n < 0 || n > end - start)
1301 {
1302 PyErr_SetString(PyExc_IndexError, _("line number out of range"));
1303 return -1;
1304 }
1305
1306 if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
1307 return -1;
1308
1309 if (new_end)
1310 *new_end = end + len_change;
1311
1312 return 0;
1313}
1314
Bram Moolenaar19e60942011-06-19 00:27:51 +02001315 static PyInt
1316RBAsSlice(BufferObject *self, PyInt lo, PyInt hi, PyObject *val, PyInt start, PyInt end, PyInt *new_end)
1317{
1318 PyInt size;
1319 PyInt len_change;
1320
1321 /* Self must be a valid buffer */
1322 if (CheckBuffer(self))
1323 return -1;
1324
1325 /* Sort out the slice range */
1326 size = end - start + 1;
1327
1328 if (lo < 0)
1329 lo = 0;
1330 else if (lo > size)
1331 lo = size;
1332 if (hi < 0)
1333 hi = 0;
1334 if (hi < lo)
1335 hi = lo;
1336 else if (hi > size)
1337 hi = size;
1338
1339 if (SetBufferLineList(self->buf, lo + start, hi + start,
1340 val, &len_change) == FAIL)
1341 return -1;
1342
1343 if (new_end)
1344 *new_end = end + len_change;
1345
1346 return 0;
1347}
1348
Bram Moolenaarca8a4df2010-07-31 19:54:14 +02001349
1350 static PyObject *
1351RBAppend(BufferObject *self, PyObject *args, PyInt start, PyInt end, PyInt *new_end)
1352{
1353 PyObject *lines;
1354 PyInt len_change;
1355 PyInt max;
1356 PyInt n;
1357
1358 if (CheckBuffer(self))
1359 return NULL;
1360
1361 max = n = end - start + 1;
1362
1363 if (!PyArg_ParseTuple(args, "O|n", &lines, &n))
1364 return NULL;
1365
1366 if (n < 0 || n > max)
1367 {
1368 PyErr_SetString(PyExc_ValueError, _("line number out of range"));
1369 return NULL;
1370 }
1371
1372 if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
1373 return NULL;
1374
1375 if (new_end)
1376 *new_end = end + len_change;
1377
1378 Py_INCREF(Py_None);
1379 return Py_None;
1380}
1381
1382
1383/* Buffer object - Definitions
1384 */
1385
1386typedef struct
1387{
1388 PyObject_HEAD
1389 BufferObject *buf;
1390 PyInt start;
1391 PyInt end;
1392} RangeObject;
1393
1394 static PyObject *
1395RangeNew(buf_T *buf, PyInt start, PyInt end)
1396{
1397 BufferObject *bufr;
1398 RangeObject *self;
1399 self = PyObject_NEW(RangeObject, &RangeType);
1400 if (self == NULL)
1401 return NULL;
1402
1403 bufr = (BufferObject *)BufferNew(buf);
1404 if (bufr == NULL)
1405 {
1406 Py_DECREF(self);
1407 return NULL;
1408 }
1409 Py_INCREF(bufr);
1410
1411 self->buf = bufr;
1412 self->start = start;
1413 self->end = end;
1414
1415 return (PyObject *)(self);
1416}
1417
1418 static PyObject *
1419BufferAppend(PyObject *self, PyObject *args)
1420{
1421 return RBAppend((BufferObject *)(self), args, 1,
1422 (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count,
1423 NULL);
1424}
1425
1426 static PyObject *
1427BufferMark(PyObject *self, PyObject *args)
1428{
1429 pos_T *posp;
1430 char *pmark;
1431 char mark;
1432 buf_T *curbuf_save;
1433
1434 if (CheckBuffer((BufferObject *)(self)))
1435 return NULL;
1436
1437 if (!PyArg_ParseTuple(args, "s", &pmark))
1438 return NULL;
1439 mark = *pmark;
1440
1441 curbuf_save = curbuf;
1442 curbuf = ((BufferObject *)(self))->buf;
1443 posp = getmark(mark, FALSE);
1444 curbuf = curbuf_save;
1445
1446 if (posp == NULL)
1447 {
1448 PyErr_SetVim(_("invalid mark name"));
1449 return NULL;
1450 }
1451
1452 /* Ckeck for keyboard interrupt */
1453 if (VimErrorCheck())
1454 return NULL;
1455
1456 if (posp->lnum <= 0)
1457 {
1458 /* Or raise an error? */
1459 Py_INCREF(Py_None);
1460 return Py_None;
1461 }
1462
1463 return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
1464}
1465
1466 static PyObject *
1467BufferRange(PyObject *self, PyObject *args)
1468{
1469 PyInt start;
1470 PyInt end;
1471
1472 if (CheckBuffer((BufferObject *)(self)))
1473 return NULL;
1474
1475 if (!PyArg_ParseTuple(args, "nn", &start, &end))
1476 return NULL;
1477
1478 return RangeNew(((BufferObject *)(self))->buf, start, end);
1479}
1480
1481static struct PyMethodDef BufferMethods[] = {
1482 /* name, function, calling, documentation */
1483 {"append", BufferAppend, 1, "Append data to Vim buffer" },
1484 {"mark", BufferMark, 1, "Return (row,col) representing position of named mark" },
1485 {"range", BufferRange, 1, "Return a range object which represents the part of the given buffer between line numbers s and e" },
1486 { NULL, NULL, 0, NULL }
1487};
1488
1489 static PyObject *
1490RangeAppend(PyObject *self, PyObject *args)
1491{
1492 return RBAppend(((RangeObject *)(self))->buf, args,
1493 ((RangeObject *)(self))->start,
1494 ((RangeObject *)(self))->end,
1495 &((RangeObject *)(self))->end);
1496}
1497
1498 static PyInt
1499RangeLength(PyObject *self)
1500{
1501 /* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
1502 if (CheckBuffer(((RangeObject *)(self))->buf))
1503 return -1; /* ??? */
1504
1505 return (((RangeObject *)(self))->end - ((RangeObject *)(self))->start + 1);
1506}
1507
1508 static PyObject *
1509RangeItem(PyObject *self, PyInt n)
1510{
1511 return RBItem(((RangeObject *)(self))->buf, n,
1512 ((RangeObject *)(self))->start,
1513 ((RangeObject *)(self))->end);
1514}
1515
1516 static PyObject *
1517RangeRepr(PyObject *self)
1518{
1519 static char repr[100];
1520 RangeObject *this = (RangeObject *)(self);
1521
1522 if (this->buf->buf == INVALID_BUFFER_VALUE)
1523 {
1524 vim_snprintf(repr, 100, "<range object (for deleted buffer) at %p>",
1525 (self));
1526 return PyString_FromString(repr);
1527 }
1528 else
1529 {
1530 char *name = (char *)this->buf->buf->b_fname;
1531 int len;
1532
1533 if (name == NULL)
1534 name = "";
1535 len = (int)strlen(name);
1536
1537 if (len > 45)
1538 name = name + (45 - len);
1539
1540 vim_snprintf(repr, 100, "<range %s%s (%d:%d)>",
1541 len > 45 ? "..." : "", name,
1542 this->start, this->end);
1543
1544 return PyString_FromString(repr);
1545 }
1546}
1547
1548 static PyObject *
1549RangeSlice(PyObject *self, PyInt lo, PyInt hi)
1550{
1551 return RBSlice(((RangeObject *)(self))->buf, lo, hi,
1552 ((RangeObject *)(self))->start,
1553 ((RangeObject *)(self))->end);
1554}
1555
1556/*
1557 * Line range object - Definitions
1558 */
1559
1560static struct PyMethodDef RangeMethods[] = {
1561 /* name, function, calling, documentation */
1562 {"append", RangeAppend, 1, "Append data to the Vim range" },
1563 { NULL, NULL, 0, NULL }
1564};
1565