2 * Copyright Neil Brown ©2015-2023 <neil@brown.name>
3 * May be distributed under terms of GPLv2 - see file:COPYING
5 * Python3 bindings for edlib.
6 * An edlib command "global-load-modules:python" will read and execute
8 * It must "import edlib" and it can use "edlib.editor" to get the editor
11 * Types available are:
12 * edlib.pane - a generic pane. These form a tree of which edlib.editor
14 * get/set operations for x,y,z,w,h,cx,cy as numbers
15 * changes x,y,w,h call pane_resize()
16 * z cannot be changed (only pane_register() does that )
17 * cx,cy can be changed freely.
18 * 'parent' and 'focus' can be read but not written
19 * method for 'children' provides first child as an iterator.
20 * method abs() converts relative co-ords to absolute.
21 * rel() converts absolute co-ords to relative.
22 * edlib.mark - these reference locations in a document. The document is
23 * not directly accessible, it can only be accessed through
24 * a pane (which may translate events and results).
25 * get/set for viewnum (cannot be set)
26 * iterator for both 'all' and 'view' lists.
29 * edlib.comm - a command which can be used to invoke code in other
30 * module editors. These look like any other python
31 * callable. They cannot be explicitly created, but can
32 * be received from and passed to other commands.
37 /* Need to define stuff that pyconfig needs */
42 //#define PyType_HasFeature __PyType_HasFeature
44 #undef PyType_HasFeature __PyType_HasFeature
45 int PyType_HasFeature(PyTypeObject *type, unsigned long feature);
48 #define Py_INCREF(op) (0)
50 #define Py_DECREF(op) (0)
52 #define Py_XDECREF(op) (0)
54 #define Py_IS_TYPE(ob, type) (ob == (void*)type)
59 #define MARK_DATA_PTR struct Mark
60 #define PRIVATE_DOC_REF
70 #define DOC_DATA_TYPE struct python_doc
80 #include "core-pane.h"
82 #define SAFE_CI {.key=safe_cast NULL,\
83 .home=safe_cast NULL,\
84 .focus=safe_cast NULL,\
85 .comm=safe_cast NULL,\
88 static PyObject *Edlib_CommandFailed;
89 static PyObject *EdlibModule;
91 static struct pane *ed_pane;
93 static char *module_dir;
94 static char *python_as_string(PyObject *s, PyObject **tofree safe);
96 /* Python commands visible to edlib are wrapped in
97 * the python_command. There is only one per callback,
98 * so that edlib code can compare for equalty.
100 struct python_command {
103 struct list_head lst;
105 static LIST_HEAD(exported_commands);
107 DEF_CMD(python_call);
108 DEF_CMD(python_pane_call);
109 DEF_CMD(python_doc_call);
110 static void python_free_command(struct command *c safe);
112 static struct python_command *export_callable(PyObject *callable safe,
115 struct python_command *c;
116 const char *name = NULL;
119 if (nm && PyUnicode_Check(nm))
120 name = PyUnicode_AsUTF8(nm);
125 list_for_each_entry(c, &exported_commands, lst)
126 if (c->callable == callable) {
131 c = malloc(sizeof(*c));
133 c->c.free = python_free_command;
135 if (strcmp(name, "handle_close") == 0 ||
137 strcmp(name+len-10, "_closed_ok") == 0))
143 c->callable = callable;
144 list_add(&c->lst, &exported_commands);
155 static PyTypeObject PaneType;
161 static PyTypeObject PaneIterType;
163 typedef struct pydoc {
170 static PyTypeObject DocType;
172 typedef struct Mark {
176 static PyTypeObject MarkType;
177 static void mark_refcnt(struct mark *m safe, int inc);
181 struct command *comm;
183 static PyTypeObject CommType;
185 static inline bool pane_valid(Pane *p safe)
187 if (p->pane && p->pane->handle)
189 PyErr_SetString(PyExc_TypeError, "Pane has been freed");
193 static inline bool doc_valid(Doc *p safe)
195 if (p->pane && p->pane->handle)
197 PyErr_SetString(PyExc_TypeError, "Doc pane has been freed");
201 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
202 PyObject **s1 safe, PyObject **s2 safe);
204 static int in_pane_frompane = 0;
205 static inline PyObject *safe Pane_Frompane(struct pane *p)
208 if (p && p->handle && p->handle->func == python_pane_call.func) {
211 } else if (p && p->handle && p->handle->func == python_doc_call.func) {
212 struct python_doc *pd = p->doc_data;
213 Doc *pdoc = pd->pdoc;
217 in_pane_frompane = 1;
218 pane = (Pane *)PyObject_CallObject((PyObject*)&PaneType, NULL);
219 in_pane_frompane = 0;
223 pane->pane = pane_get(p);
227 return (PyObject*)pane;
230 static inline PyObject *safe Mark_Frommark(struct mark *m safe)
234 if (mark_valid(m) && m->mtype == &MarkType && m->mdata) {
235 /* This is a vmark, re-use the PyObject */
237 return (PyObject*)m->mdata;
239 mark = (Mark *)PyObject_CallObject((PyObject*)&MarkType, NULL);
240 if (mark && mark_valid(m))
242 return (PyObject*)mark;
245 static inline PyObject *safe Comm_Fromcomm(struct command *c safe)
247 Comm *comm = (Comm *)PyObject_CallObject((PyObject*)&CommType, NULL);
249 comm->comm = command_get(c);
250 return (PyObject*)comm;
253 static PyObject *py_LOG(PyObject *self, PyObject *args);
254 static void PyErr_LOG(void)
256 /* cribbed from https://groups.google.com/forum/#!topic/comp.lang.python/khLrxC6EOKc */
257 char *errorMsg = NULL;
258 PyObject *modIO = NULL;
259 PyObject *modTB = NULL;
260 PyObject *obFuncStringIO = NULL;
261 PyObject *obIO = NULL;
262 PyObject *obFuncTB = NULL;
263 PyObject *argsTB = NULL;
264 PyObject *obResult = NULL;
265 PyObject *tofree = NULL;
266 PyObject *exc_typ, *exc_val, *exc_tb;
268 if (!PyErr_Occurred())
271 PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
272 PyErr_NormalizeException(&exc_typ, &exc_val, &exc_tb);
274 PyException_SetTraceback(exc_val, exc_tb);
276 /* Import the modules we need - StringIO and traceback */
277 errorMsg = "Can't import io";
278 modIO = PyImport_ImportModule("io");
282 errorMsg = "Can't import traceback";
283 modTB = PyImport_ImportModule("traceback");
287 /* Construct a cStringIO object */
288 errorMsg = "Can't find io.StringIO";
289 obFuncStringIO = PyObject_GetAttrString(modIO, "StringIO");
292 errorMsg = "io.StringIO() failed";
293 obIO = PyObject_CallObject(obFuncStringIO, NULL);
297 /* Get the traceback.print_exception function, and call it. */
298 errorMsg = "Can't find traceback.print_exception";
299 obFuncTB = PyObject_GetAttrString(modTB, "print_exception");
302 errorMsg = "can't make print_exception arguments";
303 argsTB = Py_BuildValue("OOOOO",
304 exc_typ ? exc_typ : Py_None,
305 exc_val ? exc_val : Py_None,
306 exc_tb ? exc_tb : Py_None,
312 errorMsg = "traceback.print_exception() failed";
313 obResult = PyObject_CallObject(obFuncTB, argsTB);
319 /* Now call the getvalue() method in the StringIO instance */
320 Py_DECREF(obFuncStringIO);
321 errorMsg = "cant find getvalue function";
322 obFuncStringIO = PyObject_GetAttrString(obIO, "getvalue");
325 Py_XDECREF(obResult);
326 errorMsg = "getvalue() failed.";
327 obResult = PyObject_CallObject(obFuncStringIO, NULL);
331 /* And it should be a string all ready to go - report it. */
332 errorMsg = python_as_string(obResult, &tofree);;
333 LOG("Python error:\n%s", errorMsg);
336 call("editor:notify:Message:broadcast",ed_pane, 0, NULL,
337 "Python Error - see log") <= 0))
338 /* Failed to alert anyone - write to stderr */
339 fwrite(errorMsg, 1, strlen(errorMsg), stderr);
347 Py_XDECREF(obFuncStringIO);
349 Py_XDECREF(obFuncTB);
351 Py_XDECREF(obResult);
358 DEF_CMD(python_load_module)
360 const char *name = ci->str;
366 PyObject *builtins, *compile, *args, *bytecode;
370 snprintf(buf, sizeof(buf), "%s/python/%s.py", module_dir, name);
371 fd = open(buf, O_RDONLY);
374 size = lseek(fd, 0, SEEK_END);
375 lseek(fd, 0, SEEK_SET);
376 code = malloc(size+1);
381 size = read(fd, code, size);
389 LOG("Loading python module %s from %s", name, buf);
391 builtins = PyEval_GetBuiltins();
392 compile = PyDict_GetItemString(builtins, "compile");
393 args = safe_cast Py_BuildValue("(sss)", code, buf, "exec");
394 bytecode = PyObject_Call(compile, args, NULL);
397 if (bytecode == NULL) {
402 snprintf(buf2, sizeof(buf2), "edlib.%s", name);
404 if (PyImport_ExecCodeModule(buf2, bytecode) == NULL)
410 static PyObject *safe python_string(const char *s safe, int len)
413 const char *e = NULL;
418 while ((!e || c < e) && *c && !(*c & 0x80))
420 while ((wch = get_utf8(&c, e)) != WEOF)
421 if (wch == WERR || wch > 0x10FFFF)
424 return safe_cast PyUnicode_DecodeUTF8(s, c - s, NULL);
427 static char *python_as_string(PyObject *s, PyObject **tofree safe)
429 if (s && PyUnicode_Check(s)) {
430 s = PyUnicode_AsUTF8String(s);
433 if (s && PyBytes_Check(s)) {
434 char *ret = PyBytes_AsString(s);
435 unsigned char *r = (unsigned char*)ret;
436 if (r && r[0] == 0xef && r[1] == 0xbb && r[2] == 0xbf)
437 /* UTF-8 Byte Order Mark */
445 static int dict_add(PyObject *kwds, char *name, PyObject *val)
449 PyDict_SetItemString(kwds, name, val);
454 static void python_interrupt(int sig)
456 /* Python code has been running for too long,
462 REDEF_CB(python_call)
464 struct python_command *pc = container_of(ci->comm, struct python_command, c);
465 PyObject *ret = NULL, *args, *kwds, *str;
467 bool unterminated = False;
468 int klen = strlen(ci->key);
471 strcmp(ci->key + klen - 13, " unterminated") == 0)
474 args = safe_cast Py_BuildValue("(s)", ci->key);
476 rv = rv && dict_add(kwds, "home", Pane_Frompane(ci->home));
477 rv = rv && dict_add(kwds, "focus",
478 Pane_Frompane(ci->focus));
479 rv = rv && dict_add(kwds, "mark",
480 ci->mark ? Mark_Frommark(ci->mark):
481 (Py_INCREF(Py_None), Py_None));
482 rv = rv && dict_add(kwds, "mark2",
483 ci->mark2 ? Mark_Frommark(ci->mark2):
484 (Py_INCREF(Py_None), Py_None));
487 str = python_string(ci->str, unterminated ? ci->num2 : -1);
493 dict_add(kwds, "str", str);
494 dict_add(kwds, "str1", str);
500 rv = rv && dict_add(kwds, "str2",
501 ci->str2 ? python_string(ci->str2, -1):
502 (Py_INCREF(Py_None), safe_cast Py_None));
503 rv = rv && dict_add(kwds, "comm", Comm_Fromcomm(ci->comm));
504 rv = rv && dict_add(kwds, "comm2",
505 ci->comm2 ? Comm_Fromcomm(ci->comm2):
506 (Py_INCREF(Py_None), Py_None));
507 rv = rv && dict_add(kwds, "num",
508 Py_BuildValue("i", ci->num));
509 rv = rv && dict_add(kwds, "rpt_num",
510 Py_BuildValue("i", RPT_NUM(ci)));
511 rv = rv && dict_add(kwds, "num2",
512 Py_BuildValue("i", ci->num2));
513 rv = rv && dict_add(kwds, "xy",
514 Py_BuildValue("ii", ci->x, ci->y));
516 if (rv && pc->callable) {
517 signal(SIGALRM, python_interrupt);
519 ret = PyObject_Call(pc->callable, args, kwds);
521 signal(SIGALRM, SIG_DFL);
528 /* FIXME cancel error?? */
533 else if (PyLong_Check(ret))
534 rv = PyLong_AsLong(ret);
535 else if (PyBool_Check(ret))
536 rv = (ret == Py_True);
537 else if (PyUnicode_Check(ret) && PyUnicode_GET_LENGTH(ret) >= 1)
538 rv = CHAR_RET(PyUnicode_READ_CHAR(ret, 0));
545 REDEF_CMD(python_doc_call)
547 int rv = python_pane_call_func(ci);
548 if (rv == Efallthrough)
549 rv = key_lookup(doc_default_cmd, ci);
553 static void do_map_init(Pane *self safe)
556 PyObject *l = PyObject_Dir((PyObject*)self);
559 if (!self->map || !self->pane || !l)
562 /* First add the ranges, so individuals can over-ride them */
563 for (i = 0; i < n ; i++) {
564 PyObject *e = PyList_GetItem(l, i);
565 PyObject *m = PyObject_GetAttr((PyObject*)self, e);
567 if (m && PyMethod_Check(m)) {
568 PyObject *doc = PyObject_GetAttrString(m, "__doc__");
569 if (doc && doc != Py_None) {
570 PyObject *tofree = NULL;
571 char *docs = python_as_string(doc, &tofree);
574 strstarts(docs, "handle-range") &&
577 char *s1 = strchr(docs+13, sep);
578 char *s2 = s1 ? strchr(s1+1, sep) : NULL;
580 char *a = strndup(docs+13, s1-(docs+13));
581 char *b = strndup(s1+1, s2-(s1+1));
583 struct python_command *comm =
584 export_callable(m, e);
585 key_add_range(self->map, a, b,
588 command_put(&comm->c);
592 strstarts(docs, "handle-prefix:")) {
593 char *a = strconcat(self->pane, docs+14);
594 char *b = strconcat(self->pane,
595 a, "\xFF\xFF\xFF\xFF");
596 struct python_command *comm =
597 export_callable(m, e);
598 key_add_range(self->map, a, b,
600 command_put(&comm->c);
608 /* Now add the non-ranges */
609 for (i = 0; i < n ; i++) {
610 PyObject *e = PyList_GetItem(l, i);
611 PyObject *m = PyObject_GetAttr((PyObject*)self, e);
613 if (m && PyMethod_Check(m)) {
614 PyObject *doc = PyObject_GetAttrString(m, "__doc__");
616 PyObject *tofree = NULL;
617 if (doc && doc != Py_None &&
618 (docs = python_as_string(doc, &tofree)) != NULL) {
620 if (strstarts(docs, "handle:")) {
621 struct python_command *comm =
622 export_callable(m, e);
623 key_add(self->map, docs+7, &comm->c);
624 command_put(&comm->c);
626 if (strstarts(docs, "handle-list") &&
629 char *s1 = docs + 12;
630 while (s1 && *s1 && *s1 != sep) {
631 struct python_command *comm =
632 export_callable(m, e);
634 char *s2 = strchr(s1, sep);
636 a = strndup(s1, s2-s1);
642 key_add(self->map, a, &comm->c);
644 command_put(&comm->c);
657 REDEF_CB(python_pane_call)
659 Pane *home = container_of(ci->comm, Pane, cmd);
661 if (!home || !home->map)
666 return key_lookup(home->map, ci);
669 static Pane *pane_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
673 self = (Pane *)type->tp_alloc(type, 0);
680 static Doc *Doc_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
684 self = (Doc *)type->tp_alloc(type, 0);
691 static void python_pane_free(struct command *c safe)
693 Pane *p = container_of(c, Pane, cmd);
694 struct pane *pn = p->pane;
695 /* pane has been closed */
700 if (pn && PyObject_TypeCheck(p, &DocType))
701 doc_free(&pn->doc_data->doc, safe_cast pn);
707 DEF_CMD_CLOSED(python_close_mark)
709 struct mark *m = ci->mark;
711 if (m && m->viewnum >= 0 && m->mtype == &MarkType && m->mdata) {
721 static int do_Pane_init(Pane *self safe, PyObject *args, PyObject *kwds,
726 static const char *keywords[] = {"parent", "z", NULL};
729 PyErr_SetString(PyExc_TypeError, "Pane already initialised");
732 if (in_pane_frompane)
733 /* An internal Pane_Frompane call - it will set .pane,
734 * and we don't want a .handler.
738 /* Pane(parent=None, z=0) */
739 ret = PyArg_ParseTupleAndKeywords(args, kwds, "O!|i", (char**)keywords,
740 &PaneType, parentp, zp);
744 self->map = key_alloc();
745 key_add(self->map, "Close:mark", &python_close_mark);
746 self->cmd = python_pane_call;
747 self->cmd.closed_ok = 1;
748 self->cmd.free = python_pane_free;
749 if (self->ob_base.ob_type)
750 self->cmd.name = self->ob_base.ob_type->tp_name;
755 static int Pane_init(Pane *self safe, PyObject *args, PyObject *kwds)
759 int ret = do_Pane_init(self, args, kwds, &parent, &z);
763 if (!parent || !parent->pane)
766 /* The pane holds a reference to the Pane through the ->handle
770 self->pane = pane_register(parent->pane, z, &self->cmd, self);
774 pane_get(self->pane);
778 static int Doc_init(Doc *self, PyObject *args, PyObject *kwds)
781 struct python_doc *pd;
783 int ret = do_Pane_init((Pane*safe)self, args, kwds, &parent, &z);
787 if (!self || !parent || !parent->pane)
790 self->cmd.func = python_doc_call_func;
791 self->pane = doc_register(parent->pane, &self->cmd);
793 pane_get(self->pane);
794 pd = self->pane->doc_data;
796 pd->doc.refcnt = mark_refcnt;
801 static inline void do_free(PyObject *ob safe)
803 if (ob->ob_type && ob->ob_type->tp_free)
804 ob->ob_type->tp_free(ob);
807 DEF_CMD(python_null_call)
812 static void python_pane_free_final(struct command *c safe)
814 Pane *p = container_of(c, Pane, cmd);
819 do_free((PyObject*safe)p);
822 static void pane_dealloc(Pane *self safe)
824 struct pane *p = self->pane;
826 /* if initialization failed, then dealloc happens before the
827 * pane gets closed. In that case we need to modify the
828 * free sequence so do_free() gets called after the close.
831 if (p && p->handle && p->handle->func == python_pane_call.func) {
832 p->handle = &python_null_call;
833 p->handle->free = python_pane_free_final;
835 } else if (p && p->handle && p->handle->func == python_doc_call.func) {
836 p->handle = &python_null_call;
837 p->handle->free = python_pane_free_final;
842 do_free((PyObject*safe)self);
846 static PyObject *pane_children(Pane *self safe, PyObject *args)
850 if (!pane_valid(self))
852 ret = (PaneIter*)PyObject_CallObject((PyObject*)&PaneIterType, NULL);
854 if (list_empty(&self->pane->children))
857 ret->pane = list_first_entry(&self->pane->children,
858 struct pane, siblings);
860 return (PyObject*)ret;
863 static Pane *pane_iter_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
867 self = (Pane *)type->tp_alloc(type, 0);
873 static void paneiter_dealloc(PaneIter *self safe)
875 do_free((PyObject*safe)self);
878 static PyObject *Pane_clone_children(Pane *self safe, PyObject *args)
883 if (!pane_valid(self))
886 ret = PyArg_ParseTuple(args, "O!", &PaneType, &other);
887 if (ret <= 0 || !other)
890 pane_clone_children(self->pane, other->pane);
895 static PyObject *Pane_take_focus(Pane *self safe, PyObject *args)
897 if (!pane_valid(self))
900 pane_take_focus(self->pane);
905 static PyObject *Pane_has_focus(Pane *self safe, PyObject *args)
910 if (!pane_valid(self))
913 ret = PyArg_ParseTuple(args, "|O!", &PaneType, &other);
917 if (pane_has_focus(self->pane, other ? other->pane : NULL)) {
926 static PaneIter *pane_this_iter(PaneIter *self safe)
932 static PyObject *pane_iter_next(PaneIter *self safe)
936 /* Reached the end */
938 ret = Pane_Frompane(self->pane);
939 if (self->pane->siblings.next == &self->pane->parent->children)
940 /* Reached the end of the list */
943 self->pane = list_next_entry(self->pane, siblings);
955 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
956 struct pane *p = ci->focus;
962 pr->ret = Pane_Frompane(ci->focus);
968 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
972 if (!mark_valid(ci->mark))
974 if (ci->mark->viewnum == MARK_UNGROUPED) {
975 /* Cannot rely on this mark persisting, take a copy */
976 struct mark *m = mark_dup(ci->mark);
977 pr->ret = Mark_Frommark(m);
978 m->mtype = (void*)pr->ret;
980 pr->ret = Mark_Frommark(ci->mark);
986 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
990 if (!mark_valid(ci->mark2))
992 pr->ret = Mark_Frommark(ci->mark2);
998 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1003 if (mark_valid(ci->mark))
1004 m1 = Mark_Frommark(ci->mark);
1007 if (mark_valid(ci->mark2))
1008 m2 = Mark_Frommark(ci->mark2);
1012 pr->ret = Py_BuildValue("OO", m1, m2);
1013 if (mark_valid(ci->mark))
1015 if (mark_valid(ci->mark2))
1022 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1027 return Efallthrough;
1028 pr->ret = python_string(ci->str, -1);
1034 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1039 return Efallthrough;
1040 pr->ret = safe_cast PyBytes_FromStringAndSize(ci->str, ci->num);
1046 struct pyret *pr = container_of(ci->comm, struct pyret, comm);
1051 return Efallthrough;
1052 pr->ret = Comm_Fromcomm(ci->comm2);
1056 static struct command *map_ret(char *ret safe)
1058 if (strcmp(ret, "pane") == 0)
1060 if (strcmp(ret, "mark") == 0)
1062 if (strcmp(ret, "mark2") == 0)
1064 if (strcmp(ret, "marks") == 0)
1065 return &take_2_marks;
1066 if (strcmp(ret, "str") == 0)
1068 if (strcmp(ret, "bytes") == 0)
1070 if (strcmp(ret, "comm") == 0)
1075 static bool handle_ret(PyObject *kwds, struct cmd_info *ci safe,
1076 struct pyret *pr safe)
1080 PyObject *ret, *s3 = NULL;
1082 memset(pr, 0, sizeof(*pr));
1084 ret = kwds ? PyDict_GetItemString(kwds, "ret") : NULL;
1088 if (!PyUnicode_Check(ret) ||
1089 (rets = python_as_string(ret, &s3)) == NULL) {
1090 PyErr_SetString(PyExc_TypeError, "ret= must be given a string");
1093 if (strcmp(rets, "char") == 0) {
1094 pr->return_char = 1;
1098 PyErr_SetString(PyExc_TypeError, "ret= not permitted with comm2");
1104 PyErr_SetString(PyExc_TypeError, "ret= type not valid");
1109 ci->comm2 = &pr->comm;
1115 static void set_err(int rv)
1119 PyErr_SetObject(Edlib_CommandFailed,
1120 PyUnicode_FromFormat("Enoarg"));
1123 PyErr_SetObject(Edlib_CommandFailed,
1124 PyUnicode_FromFormat("Einval"));
1127 PyErr_SetObject(Edlib_CommandFailed,
1128 PyUnicode_FromFormat("Enosup"));
1131 PyErr_SetObject(Edlib_CommandFailed,
1132 PyUnicode_FromFormat("Efail"));
1135 PyErr_SetObject(Edlib_CommandFailed,
1136 PyUnicode_FromFormat("%d", rv));
1140 static PyObject *choose_ret(int rv, struct pyret *pr safe)
1142 if (pr->comm.func && rv >= Efalse) {
1148 Py_XDECREF(pr->ret);
1153 if (pr->return_char) {
1155 Py_INCREF(Py_False);
1158 if (rv == CHAR_RET(WEOF)) {
1162 return PyUnicode_FromFormat("%c", rv & 0x1FFFFF);
1164 return PyLong_FromLong(rv);
1167 static PyObject *Pane_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1169 struct cmd_info ci = SAFE_CI;
1174 sighandler_t oldhan;
1176 if (!pane_valid(self))
1179 ci.home = self->pane;
1181 if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1182 !handle_ret(kwds, &ci, &pr)) {
1183 Py_XDECREF(s1); Py_XDECREF(s2);
1184 command_put(ci.comm2);
1189 oldhan = signal(SIGALRM, SIG_DFL);
1190 rv = key_handle(&ci);
1191 if (oldhan != SIG_DFL) {
1192 signal(SIGALRM, oldhan);
1196 /* Just in case ... */
1199 Py_XDECREF(s1); Py_XDECREF(s2);
1200 command_put(ci.comm2);
1202 return choose_ret(rv, &pr);
1205 static PyObject *pane_direct_call(Pane *self safe, PyObject *args safe, PyObject *kwds)
1207 struct cmd_info ci = SAFE_CI;
1212 if (!pane_valid(self))
1215 ci.home = self->pane;
1217 if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
1218 !handle_ret(kwds, &ci, &pr)) {
1219 Py_XDECREF(s1); Py_XDECREF(s2);
1220 command_put(ci.comm2);
1224 ci.comm = ci.home->handle;
1225 rv = ci.comm->func(&ci);
1227 Py_XDECREF(s1); Py_XDECREF(s2);
1228 command_put(ci.comm2);
1229 return choose_ret(rv, &pr);
1232 static PyObject *Pane_notify(Pane *self safe, PyObject *args safe, PyObject *kwds)
1234 struct cmd_info ci = SAFE_CI;
1238 if (!pane_valid(self))
1241 ci.home = self->pane;
1243 if (!get_cmd_info(&ci, args, kwds, &s1, &s2)) {
1244 Py_XDECREF(s1); Py_XDECREF(s2);
1245 command_put(ci.comm2);
1249 rv = home_pane_notify(ci.home, ci.key, ci.focus, ci.num, ci.mark, ci.str,
1250 ci.num2, ci.mark2, ci.str2,
1253 Py_XDECREF(s1); Py_XDECREF(s2);
1254 command_put(ci.comm2);
1259 return PyLong_FromLong(rv);
1262 static PyObject *Pane_mapxy(Pane *self safe, PyObject *args)
1268 int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1269 if (ret <= 0 || !self->pane || !other || !other->pane)
1272 xy = pane_mapxy(other->pane, self->pane, x, y, False);
1273 return Py_BuildValue("ii", xy.x, xy.y);
1276 static PyObject *Pane_clipxy(Pane *self safe, PyObject *args)
1282 int ret = PyArg_ParseTuple(args, "O!hh", &PaneType, &other, &x, &y);
1283 if (ret <= 0 || !self->pane || !other || !other->pane)
1286 xy = pane_mapxy(other->pane, self->pane, x, y, True);
1287 return Py_BuildValue("ii", xy.x, xy.y);
1290 static PyObject *Pane_add_notify(Pane *self safe, PyObject *args)
1294 int ret = PyArg_ParseTuple(args, "O!s", &PaneType, &other, &event);
1295 if (ret <= 0 || !other || !event)
1297 if (self->pane && other->pane)
1298 pane_add_notify(self->pane, other->pane, event);
1304 static PyObject *Pane_drop_notify(Pane *self safe, PyObject *args)
1307 int ret = PyArg_ParseTuple(args, "s", &event);
1308 if (ret <= 0 || !event)
1311 pane_drop_notifiers(self->pane, event);
1317 static PyObject *Pane_damaged(Pane *self safe, PyObject *args)
1319 int damage = DAMAGED_REFRESH;
1320 int ret = PyArg_ParseTuple(args, "|i", &damage);
1324 pane_damaged(self->pane, damage);
1330 static PyObject *Pane_close(Pane *self safe, PyObject *args)
1332 struct pane *p = self->pane;
1341 static PyObject *Pane_get_scale(Pane *self safe, PyObject *args)
1343 struct pane *p = self->pane;
1344 struct xy xy = {1000, 1000};
1348 return Py_BuildValue("ii", xy.x, xy.y);
1351 static PyObject *Pane_set_time(Pane *self safe, PyObject *args)
1353 struct pane *p = self->pane;
1360 static PyObject *Pane_too_long(Pane *self safe, PyObject *args)
1362 struct pane *p = self->pane;
1364 if (!p || pane_too_long(p, 0)) {
1368 Py_INCREF(Py_False);
1373 static PyObject *Pane_mychild(Pane *self safe, PyObject *args)
1376 int ret = PyArg_ParseTuple(args, "O!", &PaneType, &child);
1377 if (ret <= 0 || !child)
1379 if (self->pane && child->pane) {
1380 struct pane *p = pane_my_child(self->pane, child->pane);
1382 return Pane_Frompane(p);
1388 static PyObject *Pane_clip(Pane *self safe, PyObject *args)
1390 Mark *start = NULL, *end = NULL;
1393 int ret = PyArg_ParseTuple(args, "iO!O!|i", &view, &MarkType, &start,
1394 &MarkType, &end, &tostart);
1396 if (ret > 0 && start && end && self->pane &&
1397 start->mark && end->mark && view >= 0)
1398 marks_clip(self->pane, start->mark, end->mark, view, self->pane,
1404 static PyObject *Pane_reparent(Pane *self safe, PyObject *args)
1406 Pane *newparent = NULL;
1407 int ret = PyArg_ParseTuple(args, "O!", &PaneType, &newparent);
1409 if (ret > 0 && newparent && self->pane && newparent->pane) {
1410 pane_reparent(self->pane, newparent->pane);
1411 if (self->pane->parent != newparent->pane) {
1412 PyErr_SetString(PyExc_TypeError, "reparent failed");
1420 static PyObject *Pane_move_after(Pane *self safe, PyObject *args)
1423 int ret = PyArg_ParseTuple(args, "O", &peer);
1425 if (ret > 0 && peer && self->pane) {
1426 if ((PyObject*)peer == Py_None)
1427 pane_move_after(self->pane, NULL);
1428 else if (PyObject_TypeCheck(peer, &PaneType) && peer->pane)
1429 pane_move_after(self->pane, peer->pane);
1435 static PyObject *Pane_step(Pane *self safe, PyObject *args, int dir, int move)
1438 int ret = PyArg_ParseTuple(args, "O!", &MarkType, &m);
1441 if (!pane_valid(self))
1443 if (ret <= 0 || !m || !mark_valid(m->mark)) {
1444 PyErr_SetString(PyExc_TypeError, "Arg must be a mark");
1449 wch = doc_move(self->pane, m->mark, dir);
1451 wch = doc_pending(self->pane, m->mark, dir);
1456 return PyUnicode_FromFormat("%c", wch);
1459 static PyObject *Pane_step_next(Pane *self safe, PyObject *args)
1461 return Pane_step(self, args, 1, 1);
1464 static PyObject *Pane_step_prev(Pane *self safe, PyObject *args)
1466 return Pane_step(self, args, -1, 1);
1469 static PyObject *Pane_step_following(Pane *self safe, PyObject *args)
1471 return Pane_step(self, args, 1, 0);
1474 static PyObject *Pane_step_prior(Pane *self safe, PyObject *args)
1476 return Pane_step(self, args, -1, 0);
1479 static PyObject *Pane_get_vmarks(Pane *self safe, PyObject *args)
1486 if (!pane_valid(self))
1488 ret = PyArg_ParseTuple(args, "i|O!", &view, &PaneType, &owner);
1489 if (ret <= 0 || view < 0 || (owner && !pane_valid(owner))) {
1493 memset(&pr, 0, sizeof(pr));
1494 pr.comm = take_2_marks;
1495 home_call_comm(self->pane, "doc:vmark-get",
1496 owner ? owner->pane : self->pane,
1504 static PyObject *Pane_vmark_at_or_before(Pane *self safe, PyObject *args)
1512 if (!pane_valid(self))
1514 ret = PyArg_ParseTuple(args, "iO!|O!", &view, &MarkType, &m,
1516 if (ret <= 0 || view < 0 || !m || !mark_valid(m->mark) ||
1517 (owner && !pane_valid(owner))) {
1521 memset(&pr, 0, sizeof(pr));
1522 pr.comm = take_mark;
1523 home_call_comm(self->pane, "doc:vmark-prev",
1524 owner ? owner->pane : self->pane,
1525 &pr.comm, view, m->mark);
1532 static const PyMethodDef pane_methods[] = {
1533 {"close", (PyCFunction)Pane_close, METH_NOARGS,
1535 {"children", (PyCFunction)pane_children, METH_NOARGS,
1536 "provides an iterator which will iterate over all children"},
1537 {"clone_children", (PyCFunction)Pane_clone_children, METH_VARARGS,
1538 "Clone all children onto the target"},
1539 {"take_focus", (PyCFunction)Pane_take_focus, METH_NOARGS,
1540 "Claim the focus for this pane"},
1541 {"has_focus", (PyCFunction)Pane_has_focus, METH_VARARGS,
1542 "Check if pane is focus of display"},
1543 {"call", (void*)(PyCFunctionWithKeywords)Pane_call, METH_VARARGS|METH_KEYWORDS,
1544 "Call a command from a pane"},
1545 {"notify", (void*)(PyCFunctionWithKeywords)Pane_notify, METH_VARARGS|METH_KEYWORDS,
1546 "Send a notification from a pane"},
1547 {"mapxy", (PyCFunction)Pane_mapxy, METH_VARARGS,
1548 "Convert pane-relative co-ords between panes"},
1549 {"clipxy", (PyCFunction)Pane_clipxy, METH_VARARGS,
1550 "Convert pane-relative co-ords between panes, clipping to all panes"},
1551 {"add_notify", (PyCFunction)Pane_add_notify, METH_VARARGS,
1552 "Add notifier for an event on some other pane"},
1553 {"drop_notify", (PyCFunction)Pane_drop_notify, METH_VARARGS,
1554 "Drop notification to this pane for an event"},
1555 {"damaged", (PyCFunction)Pane_damaged, METH_VARARGS,
1556 "Mark pane as damaged"},
1557 {"scale", (PyCFunction)Pane_get_scale, METH_NOARGS,
1558 "Get the x,y scale numbers for this pane"},
1559 {"mychild", (PyCFunction)Pane_mychild, METH_VARARGS,
1560 "Get ancestor of pane which is my child, or None"},
1561 {"clip", (PyCFunction)Pane_clip, METH_VARARGS,
1562 "clip all 'type' marks in the given range"},
1563 {"reparent", (PyCFunction)Pane_reparent, METH_VARARGS,
1564 "Give a pane a new parent"},
1565 {"move_after", (PyCFunction)Pane_move_after, METH_VARARGS,
1566 "Move a pane after another in order of children"},
1567 {"next", (PyCFunction)Pane_step_next, METH_VARARGS,
1568 "Move mark forward returning the character"},
1569 {"prev", (PyCFunction)Pane_step_prev, METH_VARARGS,
1570 "Move mark back returning the character"},
1571 {"following", (PyCFunction)Pane_step_following, METH_VARARGS,
1572 "returning the character after mark"},
1573 {"prior", (PyCFunction)Pane_step_prior, METH_VARARGS,
1574 "returning the character before mark"},
1575 {"vmarks", (PyCFunction)Pane_get_vmarks, METH_VARARGS,
1576 "return first and last vmark given view number"},
1577 {"vmark_at_or_before", (PyCFunction)Pane_vmark_at_or_before, METH_VARARGS,
1578 "return vmark at-or-before given mark"},
1579 {"set_time", (PyCFunction)Pane_set_time, METH_NOARGS,
1580 "Set start time for long running operation"},
1581 {"too_long", (PyCFunction)Pane_too_long, METH_NOARGS,
1582 "Check if command in pane has been running for too long"},
1586 static PyObject *pane_getnum(Pane *p safe, char *which safe)
1594 case 'x': n = p->pane->x; break;
1595 case 'y': n = p->pane->y; break;
1596 case 'w': n = p->pane->w > 0 ? p->pane->w : 1; break;
1597 case 'h': n = p->pane->h > 0 ? p->pane->h : 1; break;
1598 case 'X': n = p->pane->cx; break;
1599 case 'Y': n = p->pane->cy; break;
1600 case 'z': n = p->pane->z; break;
1601 case 'Z': n = p->pane->abs_z; break;
1603 return PyLong_FromLong(n);
1606 static int pane_setnum(Pane *p safe, PyObject *v, char *which safe)
1614 if (*which == 'z') {
1615 PyErr_SetString(PyExc_TypeError, "z cannot be set");
1618 if (*which == 'Z') {
1619 PyErr_SetString(PyExc_TypeError, "abs_z cannot be set");
1622 val = PyLong_AsLong(v);
1623 if (val == -1 && PyErr_Occurred())
1626 x = p->pane->x; y = p->pane->y;
1627 w = p->pane->w; h = p->pane->h;
1629 case 'x': x = val; break;
1630 case 'y': y = val; break;
1631 case 'w': w = val; break;
1632 case 'h': h = val; break;
1633 case 'X': p->pane->cx = val; return 0;
1634 case 'Y': p->pane->cy = val; return 0;
1636 pane_resize(p->pane, x, y, w, h);
1640 static Pane *pane_getpane(Pane *p safe, char *which safe)
1642 struct pane *new = NULL;
1649 new = p->pane->parent;
1651 new = p->pane->focus;
1653 new = pane_root(p->pane);
1655 new = pane_focus(p->pane);
1657 new = pane_leaf(p->pane);
1660 newpane = (Pane*)Py_None;
1662 newpane = (Pane *)Pane_Frompane(new);
1667 static int pane_nosetpane(Pane *p, PyObject *v, void *which)
1669 PyErr_SetString(PyExc_TypeError, "Cannot set panes");
1673 static PyObject *pane_repr(Pane *self safe)
1677 if (!pane_valid(self))
1678 asprintf(&s, "<edlib.Pane FREED!!! %p>", self);
1680 asprintf(&s, "<edlib.Pane %p-%s>", self->pane, self->pane->name);
1681 ret = Py_BuildValue("s", s);
1686 static PyObject *doc_repr(Doc *self safe)
1690 if (!doc_valid(self))
1691 asprintf(&s, "<edlib.Doc FREED!!! %p>", self);
1693 asprintf(&s, "<edlib.Doc %p-%s>", self->pane, self->pane->name);
1694 ret = Py_BuildValue("s", s);
1699 static long pane_hash(Pane *p safe)
1701 return (long)p->pane;
1704 static PyObject *pane_cmp(Pane *p1 safe, Pane *p2 safe, int op)
1706 Py_RETURN_RICHCOMPARE(p1->pane, p2->pane, op);
1709 static const PyGetSetDef pane_getseters[] = {
1711 (getter)pane_getnum, (setter)pane_setnum,
1712 "X offset in parent", "x" },
1714 (getter)pane_getnum, (setter)pane_setnum,
1715 "Y offset in parent", "y" },
1717 (getter)pane_getnum, (setter)pane_setnum,
1718 "Z offset in parent", "z" },
1720 (getter)pane_getnum, (setter)pane_setnum,
1721 "width of pane", "w" },
1723 (getter)pane_getnum, (setter)pane_setnum,
1724 "heigth of pane", "h" },
1726 (getter)pane_getnum, (setter)pane_setnum,
1727 "Cursor X offset in pane", "X" },
1729 (getter)pane_getnum, (setter)pane_setnum,
1730 "Cursor Y offset in pane", "Y" },
1732 (getter)pane_getnum, (setter)pane_setnum,
1733 "global Z offset", "Z" },
1735 (getter)pane_getpane, (setter)pane_nosetpane,
1736 "Parent pane", "p"},
1738 (getter)pane_getpane, (setter)pane_nosetpane,
1739 "Focal child", "f"},
1741 (getter)pane_getpane, (setter)pane_nosetpane,
1744 (getter)pane_getpane, (setter)pane_nosetpane,
1745 "Final focus pane", "F"},
1747 (getter)pane_getpane, (setter)pane_nosetpane,
1749 {NULL} /* Sentinel */
1752 static PyObject *Pane_get_item(Pane *self safe, PyObject *key safe)
1755 PyObject *t1 = NULL;
1757 if (!pane_valid(self))
1760 k = python_as_string(key, &t1);
1762 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1765 v = pane_attr_get(self->pane, k);
1768 return Py_BuildValue("s", v);
1773 static int Pane_set_item(Pane *self safe, PyObject *key, PyObject *val)
1776 PyObject *t1 = NULL, *t2 = NULL;
1778 if (!pane_valid(self))
1781 k = python_as_string(key, &t1);
1783 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
1786 v = python_as_string(val, &t2);
1787 if (val != Py_None && !v) {
1788 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
1792 attr_set_str(&self->pane->attrs, k, v);
1798 static const PyMappingMethods pane_mapping = {
1800 .mp_subscript = (binaryfunc)Pane_get_item,
1801 .mp_ass_subscript = (objobjargproc)Pane_set_item,
1804 static PyTypeObject PaneType = {
1805 PyVarObject_HEAD_INIT(NULL, 0)
1806 .tp_name = "edlib.Pane",
1807 .tp_basicsize = sizeof(Pane),
1808 .tp_dealloc = (destructor)pane_dealloc,
1809 .tp_richcompare = (richcmpfunc)pane_cmp,
1810 .tp_repr = (reprfunc)pane_repr,
1811 .tp_as_mapping = (PyMappingMethods*)&pane_mapping,
1812 .tp_hash = (hashfunc)pane_hash,
1813 .tp_call = (ternaryfunc)pane_direct_call,
1814 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1815 .tp_doc = "edlib panes",
1816 .tp_methods = (PyMethodDef*)pane_methods,
1817 .tp_getset = (PyGetSetDef*)pane_getseters,
1818 .tp_init = (initproc)Pane_init,
1819 .tp_new = (newfunc)pane_new,
1822 static PyTypeObject PaneIterType = {
1823 PyVarObject_HEAD_INIT(NULL, 0)
1824 .tp_name = "edlib.PaneIter",
1825 .tp_basicsize = sizeof(PaneIter),
1826 .tp_dealloc = (destructor)paneiter_dealloc,
1827 .tp_flags = Py_TPFLAGS_DEFAULT,
1828 .tp_doc = "edlib pane iterator",
1829 .tp_iter = (getiterfunc)pane_this_iter,
1830 .tp_iternext = (iternextfunc)pane_iter_next,
1831 .tp_new = (newfunc)pane_iter_new,
1834 static PyObject *first_mark(Doc *self safe, PyObject *args)
1838 if (!doc_valid(self))
1841 m = mark_first(&self->pane->doc_data->doc);
1846 return Mark_Frommark(m);
1849 static PyObject *to_end(Doc *self safe, PyObject *args)
1855 if (!doc_valid(self))
1858 ret = PyArg_ParseTuple(args, "O!p", &MarkType, &mark, &end);
1859 if (ret <= 0 || !mark || !mark_valid(mark->mark)) {
1860 PyErr_SetString(PyExc_TypeError, "Mark undefined or uninitialized");
1864 mark_to_end(self->pane, mark->mark, end);
1869 static const PyMethodDef doc_methods[] = {
1870 {"first_mark", (PyCFunction)first_mark, METH_NOARGS,
1871 "first mark of document"},
1872 {"to_end", (PyCFunction)to_end, METH_VARARGS,
1873 "Move mark to one end of document"},
1877 static PyTypeObject DocType = {
1878 PyVarObject_HEAD_INIT(NULL, 0)
1879 .tp_name = "edlib.Doc",
1880 .tp_basicsize = sizeof(Doc),
1881 .tp_dealloc = (destructor)pane_dealloc,
1882 .tp_repr = (reprfunc)doc_repr,
1883 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1884 .tp_doc = "edlib document",
1885 .tp_methods = (PyMethodDef*)doc_methods,
1886 .tp_base = &PaneType,
1887 .tp_init = (initproc)Doc_init,
1888 .tp_new = (newfunc)Doc_new,
1891 static PyObject *mark_getoffset(Mark *m safe, void *x)
1894 if (!mark_valid(m->mark)) {
1895 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1898 d = &m->mark->owner->doc;
1899 if (d->refcnt == mark_refcnt)
1900 return PyLong_FromLong(m->mark->ref.o);
1901 return PyLong_FromLong(0);
1904 static int mark_setoffset(Mark *m safe, PyObject *v safe, void *x)
1909 if (!mark_valid(m->mark)) {
1910 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1913 val = PyLong_AsLong(v);
1914 if (val == -1 && PyErr_Occurred())
1916 d = &m->mark->owner->doc;
1917 if (d->refcnt == mark_refcnt)
1918 m->mark->ref.o = val;
1920 PyErr_SetString(PyExc_TypeError, "Setting offset on non-local mark");
1926 static PyObject *mark_getseq(Mark *m safe, void *x)
1928 if (!mark_valid(m->mark)) {
1929 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1932 return PyLong_FromLong(m->mark->seq);
1935 static int mark_nosetseq(Mark *m, PyObject *v, void *which)
1937 PyErr_SetString(PyExc_TypeError, "Cannot set mark seq number");
1941 static void mark_refcnt(struct mark *m safe, int inc)
1946 Py_INCREF(m->ref.c);
1950 Py_DECREF(m->ref.c);
1955 static PyObject *mark_getpos(Mark *m safe, void *x)
1958 if (!mark_valid(m->mark)) {
1959 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1962 d = &m->mark->owner->doc;
1963 if (d->refcnt == mark_refcnt && m->mark->ref.c) {
1964 Py_INCREF(m->mark->ref.c);
1965 return m->mark->ref.c;
1972 static int mark_setpos(Mark *m safe, PyObject *v, void *x)
1977 if (!mark_valid(m->mark)) {
1978 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
1981 d = &m->mark->owner->doc;
1982 if (d->refcnt != mark_refcnt) {
1983 PyErr_SetString(PyExc_TypeError, "Cannot set ref for non-local mark");
1986 d->refcnt(m->mark, -1);
1989 /* If an adjacent mark has a ref.c with a matching value
1990 * use that instead, so that mark_same() works.
1992 if ((m2 = mark_next(m->mark)) != NULL &&
1993 m2->owner->doc.refcnt == mark_refcnt &&
1994 m2->ref.c != NULL && v != NULL &&
1995 PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
1996 m->mark->ref.c = m2->ref.c;
1997 else if ((m2 = mark_prev(m->mark)) != NULL &&
1998 m2->owner->doc.refcnt == mark_refcnt &&
1999 m2->ref.c != NULL && v != NULL &&
2000 PyObject_RichCompareBool(v, m2->ref.c, Py_EQ) == 1)
2001 m->mark->ref.c = m2->ref.c;
2004 d->refcnt(m->mark, 1);
2008 static PyObject *mark_getview(Mark *m safe, void *x)
2010 if (!mark_valid(m->mark)) {
2011 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2014 return PyLong_FromLong(m->mark->viewnum);
2017 static int mark_nosetview(Mark *m, PyObject *v, void *which)
2019 PyErr_SetString(PyExc_TypeError, "Cannot set mark viewnum");
2023 static PyObject *mark_compare(Mark *a safe, Mark *b safe, int op)
2025 if ((PyObject*)a == Py_None)
2026 Py_RETURN_RICHCOMPARE(0, 1, op);
2027 else if ((PyObject*)b == Py_None)
2028 Py_RETURN_RICHCOMPARE(1, 0, op);
2029 else if (PyObject_TypeCheck(a, &MarkType) == 0 ||
2030 PyObject_TypeCheck(b, &MarkType) == 0) {
2031 PyErr_SetString(PyExc_TypeError, "Mark compared with non-Mark");
2033 } else if (!mark_valid(a->mark) || !mark_valid(b->mark))
2036 int cmp = a->mark->seq - b->mark->seq;
2037 if (mark_same(a->mark, b->mark))
2039 Py_RETURN_RICHCOMPARE(cmp, 0, op);
2043 static const PyGetSetDef mark_getseters[] = {
2045 (getter)mark_getpos, (setter)mark_setpos,
2046 "Position ref", NULL},
2048 (getter)mark_getoffset, (setter)mark_setoffset,
2049 "Position offset", NULL},
2051 (getter)mark_getview, (setter)mark_nosetview,
2052 "Index for view list", NULL},
2054 (getter)mark_getseq, (setter)mark_nosetseq,
2055 "Sequence number of mark", NULL},
2056 {NULL} /* Sentinel */
2059 static Mark *Mark_new(PyTypeObject *type safe, PyObject *args, PyObject *kwds)
2063 self = (Mark *)type->tp_alloc(type, 0);
2070 static int Mark_init(Mark *self safe, PyObject *args safe, PyObject *kwds)
2074 int view = MARK_UNGROUPED;
2076 static const char *keywords[] = {"pane","view","orig", "owner", NULL};
2079 if (!PyTuple_Check(args) ||
2080 (PyTuple_GET_SIZE(args) == 0 && kwds == NULL))
2081 /* Internal Mark_Frommark call */
2084 ret = PyArg_ParseTupleAndKeywords(args, kwds, "|O!iO!O!", (char**)keywords,
2092 PyErr_SetString(PyExc_TypeError,
2093 "Only one of 'pane' and 'orig' may be set");
2096 if (!doc && !orig) {
2097 PyErr_SetString(PyExc_TypeError,
2098 "At least one of 'pane' and 'orig' must be set");
2101 if (doc && doc->pane) {
2102 struct pane *p = doc->pane;
2103 struct pane *op = owner ? owner->pane : NULL;
2106 self->mark = vmark_new(p, view, op);
2107 } else if (orig && mark_valid(orig->mark)) {
2108 self->mark = mark_dup_view(orig->mark);
2111 PyErr_SetString(PyExc_TypeError, "Mark creation failed");
2114 if (self->mark->viewnum >= 0) {
2115 /* vmarks can use mdata and don't disappear until
2116 * explicitly released.
2118 self->mark->mtype = &MarkType;
2119 self->mark->mdata = self;
2122 /* Other marks cannot use mdata and get freed when
2123 * the original PyObject is destroyed
2125 self->mark->mtype = (void*)self;
2130 static void mark_dealloc(Mark *self safe)
2132 if (mark_valid(self->mark) && self->mark->mtype == (void*)self) {
2133 /* Python allocated this mark, so can free it. */
2134 struct mark *m = self->mark;
2140 do_free((PyObject*safe)self);
2143 static PyObject *Mark_to_mark(Mark *self safe, PyObject *args)
2146 int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2147 if (ret <= 0 || !other ||
2148 !mark_valid(self->mark) || !mark_valid(other->mark))
2150 mark_to_mark(self->mark, other->mark);
2156 static PyObject *Mark_to_mark_noref(Mark *self safe, PyObject *args)
2159 int ret = PyArg_ParseTuple(args, "O!", &MarkType, &other);
2160 if (ret <= 0 || !other ||
2161 !mark_valid(self->mark) || !mark_valid(other->mark))
2163 mark_to_mark_noref(self->mark, other->mark);
2169 static PyObject *Mark_clip(Mark *self safe, PyObject *args)
2171 Mark *start = NULL, *end = NULL;
2173 int ret = PyArg_ParseTuple(args, "O!O!|p", &MarkType, &start,
2174 &MarkType, &end, &tostart);
2176 if (ret > 0 && start && end && mark_valid(self->mark) &&
2177 mark_valid(start->mark) && mark_valid(end->mark))
2178 mark_clip(self->mark, start->mark, end->mark, tostart);
2184 static PyObject *Mark_step(Mark *self safe, PyObject *args)
2186 /* Convenience function to help implement doc:char */
2188 int ret = PyArg_ParseTuple(args, "i", &forward);
2190 if (ret > 0 && self->mark)
2191 mark_step(self->mark, forward);
2197 static PyObject *Mark_step_sharesref(Mark *self safe, PyObject *args)
2199 /* Convenience function to help implement doc:char */
2201 int ret = PyArg_ParseTuple(args, "i", &forward);
2203 if (ret > 0 && self->mark)
2204 mark_step_sharesref(self->mark, forward);
2210 static PyObject *Mark_next(Mark *self safe, PyObject *args)
2213 if (!mark_valid(self->mark)) {
2214 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2217 if (self->mark->viewnum >= 0)
2218 next = vmark_next(self->mark);
2222 return Mark_Frommark(next);
2227 static PyObject *Mark_prev(Mark *self safe, PyObject *args)
2230 if (!mark_valid(self->mark)) {
2231 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2234 if (self->mark->viewnum >= 0)
2235 prev = vmark_prev(self->mark);
2239 return Mark_Frommark(prev);
2244 static PyObject *Mark_next_any(Mark *self safe, PyObject *args)
2247 if (!mark_valid(self->mark)) {
2248 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2251 next = mark_next(self->mark);
2253 return Mark_Frommark(next);
2258 static PyObject *Mark_prev_any(Mark *self safe, PyObject *args)
2261 if (!mark_valid(self->mark)) {
2262 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2265 prev = mark_prev(self->mark);
2267 return Mark_Frommark(prev);
2272 static PyObject *Mark_dup(Mark *self safe, PyObject *args)
2275 if (!mark_valid(self->mark)) {
2276 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2279 new = mark_dup(self->mark);
2281 Mark *ret = (Mark*)Mark_Frommark(new);
2282 /* We want this mark to be freed when the Mark
2285 new->mtype = (void*)ret;
2286 return (PyObject*)ret;
2293 static PyObject *Mark_release(Mark *self safe, PyObject *args)
2295 struct mark *m = self->mark;
2297 if (!mark_valid(m)) {
2298 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2301 if (m->viewnum == MARK_UNGROUPED || m->viewnum == MARK_POINT) {
2302 PyErr_SetString(PyExc_TypeError,
2303 "Cannot release ungrouped marks or points");
2306 if (m->mtype != &MarkType) {
2307 PyErr_SetString(PyExc_TypeError,
2308 "Mark is not managed by python, and cannot be released");
2312 /* We are dropping this mark - there cannot be any other ref */
2313 ASSERT(m->mdata == self);
2324 static PyObject *Mark_watch(Mark *self safe, PyObject *args)
2326 struct mark *m = self->mark;
2328 if (!mark_valid(m)) {
2329 PyErr_SetString(PyExc_TypeError, "Mark has been freed");
2337 static const PyMethodDef mark_methods[] = {
2338 {"to_mark", (PyCFunction)Mark_to_mark, METH_VARARGS,
2339 "Move one mark to another"},
2340 {"to_mark_noref", (PyCFunction)Mark_to_mark_noref, METH_VARARGS,
2341 "Move one mark to another but don't update ref"},
2342 {"next", (PyCFunction)Mark_next, METH_NOARGS,
2344 {"prev", (PyCFunction)Mark_prev, METH_NOARGS,
2346 {"next_any", (PyCFunction)Mark_next_any, METH_NOARGS,
2348 {"prev_any", (PyCFunction)Mark_prev_any, METH_NOARGS,
2349 "previous any_mark"},
2350 {"dup", (PyCFunction)Mark_dup, METH_NOARGS,
2351 "duplicate a mark, as ungrouped"},
2352 {"clip", (PyCFunction)Mark_clip, METH_VARARGS,
2353 "If this mark is in range, move to end"},
2354 {"release", (PyCFunction)Mark_release, METH_NOARGS,
2355 "release a vmark so it can disappear"},
2356 {"watch", (PyCFunction)Mark_watch, METH_NOARGS,
2357 "acknowledge movement of a point - allow further notifications"},
2358 {"step", (PyCFunction)Mark_step, METH_VARARGS,
2359 "Move mark over any adjacent marks with same reference"},
2360 {"step_sharesref", (PyCFunction)Mark_step_sharesref, METH_VARARGS,
2361 "Move mark over any adjacent marks with same reference"},
2365 static PyObject *mark_get_item(Mark *self safe, PyObject *key safe)
2368 PyObject *t1 = NULL;
2370 if (!mark_valid(self->mark)) {
2371 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2374 k = python_as_string(key, &t1);
2376 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2379 v = attr_find(self->mark->attrs, k);
2382 return Py_BuildValue("s", v);
2387 static int mark_set_item(Mark *self safe, PyObject *key safe, PyObject *val safe)
2390 PyObject *t1 = NULL, *t2 = NULL;
2391 if (!mark_valid(self->mark)) {
2392 PyErr_SetString(PyExc_TypeError, "Mark is NULL");
2395 k = python_as_string(key, &t1);
2397 PyErr_SetString(PyExc_TypeError, "Key must be a string or unicode");
2400 v = python_as_string(val, &t2);
2401 if (val != Py_None && !v) {
2402 PyErr_SetString(PyExc_TypeError, "value must be a string or unicode");
2406 attr_set_str(&self->mark->attrs, k, v);
2412 static PyObject *mark_repr(Mark *self safe)
2414 char *s = NULL, *dm;
2418 asprintf(&s, "<edlib.Mark NULL %p>", self);
2419 else if (!mark_valid(self->mark))
2420 asprintf(&s, "<edlib.Mark FREED %p>", self);
2421 else if ((dm = call_ret(str, "doc:debug:mark", self->mark->owner,
2424 asprintf(&s, "<edlib.Mark seq=%d v=%d %s>",
2425 self->mark->seq, self->mark->viewnum, dm);
2427 asprintf(&s, "<edlib.Mark seq=%d v=%d i=%d %p>",
2428 self->mark->seq, self->mark->viewnum,
2429 self->mark->ref.o, self->mark);
2431 ret = Py_BuildValue("s", s);
2436 static const PyMappingMethods mark_mapping = {
2438 .mp_subscript = (binaryfunc)mark_get_item,
2439 .mp_ass_subscript = (objobjargproc)mark_set_item,
2442 static int mark_bool(Mark *self safe)
2444 return mark_valid(self->mark);
2447 static const PyNumberMethods mark_as_num = {
2448 .nb_bool = (inquiry) mark_bool,
2451 static PyTypeObject MarkType = {
2452 PyVarObject_HEAD_INIT(NULL, 0)
2453 .tp_name = "edlib.Mark",
2454 .tp_basicsize = sizeof(Mark),
2455 .tp_dealloc = (destructor)mark_dealloc,
2456 .tp_as_mapping = (PyMappingMethods*)&mark_mapping,
2457 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2458 .tp_doc = "edlib marks",
2459 .tp_richcompare = (richcmpfunc)mark_compare,
2460 .tp_methods = (PyMethodDef*)mark_methods,
2461 .tp_getset = (PyGetSetDef*)mark_getseters,
2462 .tp_init = (initproc)Mark_init,
2463 .tp_new = (newfunc)Mark_new,
2464 .tp_repr = (reprfunc)mark_repr,
2465 .tp_as_number = (PyNumberMethods*)&mark_as_num,
2468 static void comm_dealloc(Comm *self safe)
2470 command_put(self->comm);
2471 do_free((PyObject*safe)self);
2474 static PyObject *comm_repr(Comm *self safe)
2480 asprintf(&s, "<edlib.Comm refcnt=%d %p>",
2481 self->comm->refcnt, self->comm);
2483 asprintf(&s, "<edlib.Comm NULL %p>", self);
2484 ret = Py_BuildValue("s", s);
2489 static PyObject *Comm_call(Comm *c safe, PyObject *args safe, PyObject *kwds)
2491 struct cmd_info ci = SAFE_CI;
2498 if (!get_cmd_info(&ci, args, kwds, &s1, &s2) ||
2499 !handle_ret(kwds, &ci, &pr)) {
2500 Py_XDECREF(s1); Py_XDECREF(s2);
2501 command_put(ci.comm2);
2505 rv = c->comm->func(&ci);
2506 Py_XDECREF(s1); Py_XDECREF(s2);
2507 command_put(ci.comm2);
2509 return choose_ret(rv, &pr);
2512 static PyObject *comm_cmp(Comm *c1 safe, Comm *c2 safe, int op)
2514 Py_RETURN_RICHCOMPARE(c1->comm, c2->comm, op);
2517 static Comm *comm_new(PyTypeObject *type safe, PyObject *args safe, PyObject *kwds)
2521 self = (Comm *)type->tp_alloc(type, 0);
2527 static PyTypeObject CommType = {
2528 PyVarObject_HEAD_INIT(NULL, 0)
2529 .tp_name = "edlib.Comm",
2530 .tp_basicsize = sizeof(Comm),
2531 .tp_dealloc = (destructor)comm_dealloc,
2532 .tp_richcompare = (richcmpfunc)comm_cmp,
2533 .tp_repr = (reprfunc)comm_repr,
2534 .tp_call = (ternaryfunc)Comm_call,
2535 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2536 .tp_doc = "edlib command",
2537 .tp_new = (newfunc)comm_new,
2540 static void python_free_command(struct command *c safe)
2542 struct python_command *pc = container_of(c, struct python_command, c);
2545 Py_DECREF(pc->callable);
2550 /* The 'call' function takes liberties with arg passing.
2551 * Positional args must start with the key, and then are handled based on
2552 * there type. They can be panes, strigns, ints, pairs, marks, commands.
2553 * Panes are assigned to focus, then home.
2554 * Strings (after the key) are assigned to 'str' then 'str2'.
2556 * Ints are assigned to num then num2
2557 * Pairs (must be of ints) are assigned to x,y then hx,hy.
2558 * Marks are assigned to mark then mark2
2559 * A command is assigned to comm2 (comm is set automatically)
2560 * kwd arguments can also be used, currently
2561 * key, home, focus, xy, hxy, str, str2, mark, mark2, comm2.
2562 * A 'None' arg is ignored - probably a mark or string or something. Just use NULL
2564 static bool get_cmd_info(struct cmd_info *ci safe, PyObject *args safe, PyObject *kwds,
2565 PyObject **s1 safe, PyObject **s2 safe)
2570 int num_set = 0, num2_set = 0;
2575 if (!PyTuple_Check(args))
2577 argc = PyTuple_GET_SIZE(args);
2579 /* First positional arg must be the key */
2580 a = PyTuple_GetItem(args, 0);
2581 if (!PyUnicode_Check(a)) {
2582 PyErr_SetString(PyExc_TypeError, "First arg must be key");
2585 ci->key = safe_cast PyUnicode_AsUTF8(a);
2587 for (i = 1; i < argc; i++) {
2588 a = PyTuple_GetItem(args, i);
2589 if (!a || a == Py_None)
2590 /* quietly ignore */;
2591 else if (PyObject_TypeCheck(a, &PaneType)) {
2592 if ((void*)ci->home == NULL)
2593 ci->home = safe_cast ((Pane*)a)->pane;
2594 else if ((void*)ci->focus == NULL)
2595 ci->focus = safe_cast ((Pane*)a)->pane;
2597 PyErr_SetString(PyExc_TypeError, "Only 2 Pane args permitted");
2600 } else if (PyObject_TypeCheck(a, &MarkType)) {
2601 if (ci->mark == NULL)
2602 ci->mark = ((Mark*)a)->mark;
2603 else if (ci->mark2 == NULL)
2604 ci->mark2 = ((Mark*)a)->mark;
2606 PyErr_SetString(PyExc_TypeError, "Only 2 Mark args permitted");
2609 } else if (PyUnicode_Check(a)) {
2612 if (ci->str && ci->str2) {
2613 PyErr_SetString(PyExc_TypeError, "Only 3 String args permitted");
2616 str = python_as_string(a, &s);
2623 if (ci->str == NULL)
2627 } else if (PyLong_Check(a)) {
2629 ci->num = PyLong_AsLong(a);
2631 } else if (!num2_set) {
2632 ci->num2 = PyLong_AsLong(a);
2635 PyErr_SetString(PyExc_TypeError, "Only 2 Number args permitted");
2638 } else if (PyTuple_Check(a)) {
2639 int n = PyTuple_GET_SIZE(a);
2642 PyErr_SetString(PyExc_TypeError, "Only 2-element tuples permitted");
2645 n1 = PyTuple_GetItem(a, 0);
2646 n2 = PyTuple_GetItem(a, 1);
2647 if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2648 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2652 ci->x = PyLong_AsLong(n1);
2653 ci->y = PyLong_AsLong(n2);
2656 PyErr_SetString(PyExc_TypeError, "Only one tuple permitted");
2659 } else if (PyObject_TypeCheck(a, &CommType)) {
2661 if (ci->comm2 == NULL && c->comm) {
2662 ci->comm2 = command_get(c->comm);
2664 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2667 } else if (PyCallable_Check(a)) {
2668 struct python_command *pc = export_callable(a, NULL);
2670 if (ci->comm2 == NULL)
2673 command_put(&pc->c);
2674 PyErr_SetString(PyExc_TypeError, "Only one callable permitted");
2678 PyErr_Format(PyExc_TypeError, "Unsupported arg type %d", i);
2682 if (kwds && PyDict_Check(kwds)) {
2683 a = PyDict_GetItemString(kwds, "str1");
2684 if (!a || a == Py_None)
2685 a = PyDict_GetItemString(kwds, "str");
2686 if (a && a != Py_None) {
2687 if (*s1 || ci->str) {
2688 PyErr_SetString(PyExc_TypeError,
2689 "'str' given with other strings");
2692 if (!PyUnicode_Check(a)) {
2693 PyErr_SetString(PyExc_TypeError,
2694 "'str' must be string or unicode");
2697 ci->str = python_as_string(a, s1);
2699 a = PyDict_GetItemString(kwds, "str2");
2700 if (a && a != Py_None) {
2701 if (*s2 || ci->str2) {
2702 PyErr_SetString(PyExc_TypeError,
2703 "'str2' given with 2 strings");
2706 if (!PyUnicode_Check(a)) {
2707 PyErr_SetString(PyExc_TypeError,
2708 "'str2' must be string or unicode");
2711 ci->str2 = python_as_string(a, s2);
2713 a = PyDict_GetItemString(kwds, "mark");
2714 if (a && a != Py_None) {
2716 PyErr_SetString(PyExc_TypeError,
2717 "'mark' given with other marks");
2720 if (!PyObject_TypeCheck(a, &MarkType)) {
2721 PyErr_SetString(PyExc_TypeError,
2722 "'mark' must be an edlib.Mark");
2725 ci->mark = ((Mark*)a)->mark;
2727 a = PyDict_GetItemString(kwds, "mark2");
2728 if (a && a != Py_None) {
2730 PyErr_SetString(PyExc_TypeError,
2731 "'mark2' given with 2 other marks");
2734 if (!PyObject_TypeCheck(a, &MarkType)) {
2735 PyErr_SetString(PyExc_TypeError,
2736 "'mark2' must be an edlib.Mark");
2739 ci->mark2 = ((Mark*)a)->mark;
2741 a = PyDict_GetItemString(kwds, "num");
2744 PyErr_SetString(PyExc_TypeError,
2745 "'num' given with other numbers");
2748 if (!PyLong_Check(a)) {
2749 PyErr_SetString(PyExc_TypeError,
2750 "'num' must be an integer");
2753 ci->num = PyLong_AsLong(a);
2756 a = PyDict_GetItemString(kwds, "num2");
2759 PyErr_SetString(PyExc_TypeError,
2760 "'num2' given with 2 other numbers");
2763 if (!PyLong_Check(a)) {
2764 PyErr_SetString(PyExc_TypeError,
2765 "'num2' must be an integer");
2768 ci->num2 = PyLong_AsLong(a);
2771 a = PyDict_GetItemString(kwds, "focus");
2772 if (a && a != Py_None) {
2774 if ((void*)ci->focus) {
2775 PyErr_SetString(PyExc_TypeError,
2776 "'focus' given with other pane");
2779 if (!PyObject_TypeCheck(a, &PaneType)) {
2780 PyErr_SetString(PyExc_TypeError,
2781 "'focus' must be a pane");
2786 ci->focus = p->pane;
2788 PyErr_SetString(PyExc_TypeError, "focus value invalid");
2792 a = PyDict_GetItemString(kwds, "xy");
2793 if (a && a != Py_None) {
2796 PyErr_SetString(PyExc_TypeError,
2797 "'xy' given with other tuple");
2800 if (!PyTuple_Check(a) || PyTuple_GET_SIZE(a) != 2) {
2801 PyErr_SetString(PyExc_TypeError,
2802 "'xy' must be a tuple of 2 integers");
2805 n1 = PyTuple_GetItem(a, 0);
2806 n2 = PyTuple_GetItem(a, 1);
2807 if (!PyLong_Check(n1) || !PyLong_Check(n2)) {
2808 PyErr_SetString(PyExc_TypeError, "Only tuples of integers permitted");
2811 ci->x = PyLong_AsLong(n1);
2812 ci->y = PyLong_AsLong(n2);
2815 a = PyDict_GetItemString(kwds, "comm2");
2816 if (a && a != Py_None) {
2818 PyErr_SetString(PyExc_TypeError,
2819 "'comm2' given with other command");
2822 if (PyObject_TypeCheck(a, &CommType)) {
2825 ci->comm2 = command_get(c->comm);
2827 PyErr_SetString(PyExc_TypeError, "comm2 value invalid");
2830 } else if (PyCallable_Check(a)) {
2831 struct python_command *pc = export_callable(a, NULL);
2835 PyErr_SetString(PyExc_TypeError,
2836 "'comm2' must be a callable");
2841 if (!(void*)ci->key) {
2842 PyErr_SetString(PyExc_TypeError, "No key specified");
2845 if (!(void*)ci->home) {
2846 PyErr_SetString(PyExc_TypeError, "No pane specified");
2849 if (!(void*)ci->focus)
2850 ci->focus = ci->home;
2855 static PyObject *py_time_start(PyObject *self, PyObject *args)
2858 int ret = PyArg_ParseTuple(args, "i", &type);
2868 static PyObject *py_time_stop(PyObject *self, PyObject *args)
2871 int ret = PyArg_ParseTuple(args, "i", &type);
2881 static PyObject *py_LOG(PyObject *self, PyObject *args)
2883 int argc = PySequence_Length(args);
2888 for (i = 0; i < argc && l < (int)sizeof(buf) - 2; i++) {
2889 PyObject *o = PySequence_GetItem(args, i);
2890 PyObject *s, *tofree = NULL;
2896 s = PyObject_Str(o);
2900 str = python_as_string(s, &tofree);
2901 slen = str ? strlen(str) : 0;
2902 if (slen + l + 2 > sizeof(buf))
2903 slen = sizeof(buf) - l - 2;
2907 strncpy(buf+l, str, slen);
2920 static PyObject *py_LOG_BT(PyObject *self, PyObject *args)
2927 static const PyMethodDef edlib_methods[] = {
2928 {"time_start", py_time_start, METH_VARARGS,
2929 "Record start time"},
2930 {"time_stop", py_time_stop, METH_VARARGS,
2931 "Record stop time"},
2932 {"LOG", py_LOG, METH_VARARGS,
2933 "Generate log message"},
2934 {"LOG_BT", py_LOG_BT, METH_NOARGS,
2935 "Generate backtrace message"},
2936 {NULL, NULL, 0, NULL}
2939 /* This must be visible when the module is loaded so it
2940 * cannot be static. sparse doesn't like variables that are
2941 * neither extern nor static. So mark it extern
2943 extern char *edlib_module_path;
2944 char *edlib_module_path;
2946 void edlib_init(struct pane *ed safe)
2950 char *argv[2]= { "edlib", NULL };
2952 if (edlib_module_path)
2953 module_dir = strdup(edlib_module_path);
2957 PyConfig_InitPythonConfig(&config);
2958 config.isolated = 1;
2959 PyConfig_SetBytesArgv(&config, 0, argv);
2960 Py_InitializeFromConfig(&config);
2961 PyConfig_Clear(&config);
2963 PaneType.tp_new = PyType_GenericNew;
2964 PaneIterType.tp_new = PyType_GenericNew;
2965 DocType.tp_new = PyType_GenericNew;
2966 MarkType.tp_new = PyType_GenericNew;
2967 CommType.tp_new = PyType_GenericNew;
2968 if (PyType_Ready(&PaneType) < 0 ||
2969 PyType_Ready(&PaneIterType) < 0 ||
2970 PyType_Ready(&DocType) < 0 ||
2971 PyType_Ready(&MarkType) < 0 ||
2972 PyType_Ready(&CommType) < 0)
2975 m = PyImport_AddModule("edlib");
2981 PyModule_SetDocString(m , "edlib - one more editor is never enough");
2983 PyModule_AddFunctions(m, (PyMethodDef*)edlib_methods);
2984 PyModule_AddObject(m, "editor", Pane_Frompane(ed));
2985 PyModule_AddObject(m, "Pane", (PyObject *)&PaneType);
2986 PyModule_AddObject(m, "PaneIter", (PyObject *)&PaneIterType);
2987 PyModule_AddObject(m, "Mark", (PyObject *)&MarkType);
2988 PyModule_AddObject(m, "Comm", (PyObject *)&CommType);
2989 PyModule_AddObject(m, "Doc", (PyObject *)&DocType);
2990 PyModule_AddIntMacro(m, DAMAGED_CHILD);
2991 PyModule_AddIntMacro(m, DAMAGED_SIZE);
2992 PyModule_AddIntMacro(m, DAMAGED_VIEW);
2993 PyModule_AddIntMacro(m, DAMAGED_REFRESH);
2994 PyModule_AddIntMacro(m, DAMAGED_POSTORDER);
2995 PyModule_AddIntMacro(m, DAMAGED_CLOSED);
2996 PyModule_AddIntMacro(m, Efallthrough);
2997 PyModule_AddIntMacro(m, Enoarg);
2998 PyModule_AddIntMacro(m, Einval);
2999 PyModule_AddIntMacro(m, Efalse);
3000 PyModule_AddIntMacro(m, Efail);
3001 PyModule_AddIntMacro(m, Enosup);
3002 PyModule_AddIntMacro(m, Efail);
3003 PyModule_AddIntMacro(m, NO_NUMERIC);
3005 PyModule_AddIntMacro(m, TIME_KEY);
3006 PyModule_AddIntMacro(m, TIME_WINDOW);
3007 PyModule_AddIntMacro(m, TIME_READ);
3008 PyModule_AddIntMacro(m, TIME_SIG);
3009 PyModule_AddIntMacro(m, TIME_TIMER);
3010 PyModule_AddIntMacro(m, TIME_IDLE);
3011 PyModule_AddIntMacro(m, TIME_REFRESH);
3012 PyModule_AddIntMacro(m, TIME_MISC);
3014 PyModule_AddIntMacro(m, RXLF_ANCHORED);
3015 PyModule_AddIntMacro(m, RXLF_BACKTRACK);
3017 PyModule_AddIntMacro(m, MARK_UNGROUPED);
3018 PyModule_AddIntMacro(m, MARK_POINT);
3020 PyModule_AddIntConstant(m, "WEOF", 0x3FFFFF);
3022 PyModule_AddIntConstant(m, "testing", edlib_testing(ed));
3024 Edlib_CommandFailed = PyErr_NewException("edlib.commandfailed", NULL, NULL);
3025 Py_INCREF(Edlib_CommandFailed);
3026 PyModule_AddObject(m, "commandfailed", Edlib_CommandFailed);
3031 call_comm("global-set-command", ed, &python_load_module,
3032 0, NULL, "global-load-modules:python");