Add a window.select() method.
[screen-lua.git] / src / python.c
blobce59f39e11d944f924e7c5d89331465366449fc4
1 /* Python scripting support
3 * Copyright (c) 2009 Sadrul Habib Chowdhury (sadrul@users.sf.net)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file COPYING); if not, write to the
17 * Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
20 ****************************************************************
22 #include <sys/types.h>
24 #include "config.h"
25 #include "screen.h"
26 #include "script.h"
27 #include <sys/stat.h>
28 #include <unistd.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
34 #include "extern.h"
35 #include "logfile.h"
37 #include <Python.h>
38 #include <structmember.h>
40 #define RETURN_NONE do { Py_INCREF(Py_None); return Py_None; } while (0)
42 extern struct win *windows;
43 extern struct display *display, *displays;
44 extern struct layer *flayer;
46 static PyObject * SPy_Get(PyObject *obj, void *closure);
47 static PyObject * SPy_Set(PyObject *obj, PyObject *value, void *closure);
48 static int PyDispatch(void *handler, const char *params, va_list va);
50 typedef struct
52 PyObject *callback;
53 struct listener *listener;
54 } SPyCallback;
56 typedef struct
58 char *name;
59 char *doc;
61 int type;
62 size_t offset1;
63 size_t offset2;
64 PyObject * (*conv)(void *);
65 } SPyClosure;
67 #define REGISTER_TYPE(type, Type, closures, methods) \
68 static int \
69 register_##type(PyObject *module) \
70 { \
71 static PyGetSetDef getsets[sizeof(closures)]; \
72 int i, count = sizeof(closures); \
73 for (i = 0; i < count; i++) \
74 { \
75 getsets[i].name = closures[i].name; \
76 getsets[i].doc = closures[i].doc; \
77 getsets[i].closure = &closures[i]; \
78 getsets[i].get = SPy_Get; \
79 getsets[i].set = SPy_Set; \
80 } \
81 PyType##Type.tp_getset = getsets; \
82 PyType##Type.tp_methods = methods; \
83 PyType_Ready(&PyType##Type); \
84 Py_INCREF(&PyType##Type); \
85 PyModule_AddObject(module, #Type, (PyObject *)&PyType##Type); \
86 return 1; \
89 #define DEFINE_TYPE(str, Type) \
90 typedef struct \
91 { \
92 PyObject_HEAD \
93 str *_obj; \
94 } Py##Type; \
96 static PyTypeObject PyType##Type = \
97 { \
98 PyObject_HEAD_INIT(NULL) \
99 .ob_size = 0, \
100 .tp_name = "screen." #Type, \
101 .tp_basicsize = sizeof(Py##Type), \
102 .tp_flags = Py_TPFLAGS_DEFAULT, \
103 .tp_doc = #Type " object", \
104 .tp_methods = NULL, \
105 .tp_getset = NULL, \
106 }; \
108 static PyObject * \
109 PyObject_From##Type(str *_obj) \
111 Py##Type *obj = PyType##Type.tp_alloc(&PyType##Type, 0); \
112 obj->_obj = _obj; \
113 return (PyObject *)obj; \
116 static PyObject *
117 PyString_FromStringSafe(const char *str)
119 if (str)
120 return PyString_FromString(str);
121 RETURN_NONE;
124 /** Window {{{ */
125 DEFINE_TYPE(struct win, Window)
127 #define SPY_CLOSURE(name, doc, type, member, func) \
128 {name, doc, type, offsetof(PyWindow, _obj), offsetof(struct win, member), func}
129 static SPyClosure wclosures[] =
131 SPY_CLOSURE("title", "Window title", T_STRING, w_title, NULL),
132 SPY_CLOSURE("number", "Window number", T_INT, w_number, NULL),
133 SPY_CLOSURE("dir", "Window directory", T_STRING, w_dir, NULL),
134 SPY_CLOSURE("tty", "TTY belonging to the window", T_STRING_INPLACE, w_tty, NULL),
135 SPY_CLOSURE("group", "The group the window belongs to", T_OBJECT_EX, w_group, PyObject_FromWindow),
136 SPY_CLOSURE("pid", "Window pid", T_INT, w_pid, NULL),
137 {NULL}
140 static PyObject *
141 window_select(PyObject *self)
143 PyWindow *win = self;
144 struct win *w = win->_obj;
145 SwitchWindow(w->w_number);
146 RETURN_NONE;
149 static PyMethodDef wmethods[] = {
150 {"select", (PyCFunction)window_select, METH_NOARGS, "Select the window."},
151 {NULL},
154 REGISTER_TYPE(window, Window, wclosures, wmethods)
155 #undef SPY_CLOSURE
156 /** }}} */
158 /** Display {{{ */
159 DEFINE_TYPE(struct display, Display)
161 #define SPY_CLOSURE(name, doc, type, member, func) \
162 {name, doc, type, offsetof(PyDisplay, _obj), offsetof(struct display, member), func}
163 static SPyClosure dclosures[] =
165 SPY_CLOSURE("tty", "Display TTY", T_STRING_INPLACE, d_usertty, NULL),
166 SPY_CLOSURE("term", "Display Term", T_STRING_INPLACE, d_termname, NULL),
167 SPY_CLOSURE("fore", "Foreground window of the display", T_OBJECT_EX, d_fore, PyObject_FromWindow),
168 SPY_CLOSURE("width", "Display width", T_INT, d_width, NULL),
169 SPY_CLOSURE("height", "Display height", T_INT, d_height, NULL),
170 {NULL}
172 REGISTER_TYPE(display, Display, dclosures, NULL)
173 #undef SPY_CLOSURE
174 /** }}} */
176 /** Callback {{{ */
177 DEFINE_TYPE(SPyCallback, Callback)
178 static SPyClosure cclosures[] = {{NULL}};
180 static void
181 FreeCallback(SPyCallback *scallback)
183 Py_XDECREF(scallback->callback);
184 Free(scallback);
187 static PyObject *
188 callback_unhook(PyObject *obj)
190 PyCallback *cb = obj;
191 SPyCallback *scallback = cb->_obj;
192 if (!scallback)
193 return NULL;
194 unregister_listener(scallback->listener);
195 FreeCallback(scallback);
196 cb->_obj = NULL;
197 RETURN_NONE;
200 static PyMethodDef cmethods[] = {
201 {"unhook", (PyCFunction)callback_unhook, METH_NOARGS, "Unhook this event callback."},
202 {NULL}
204 REGISTER_TYPE(callback, Callback, cclosures, cmethods)
205 /** }}} */
207 static PyObject *
208 SPy_Get(PyObject *obj, void *closure)
210 SPyClosure *sc = closure;
211 char **first = (char *)obj + sc->offset1;
212 char **second = (char *)*first + sc->offset2;
213 PyObject *(*cb)(void *) = sc->conv;
214 void *data = *second;
216 if (!cb)
218 switch (sc->type)
220 case T_STRING:
221 cb = PyString_FromStringSafe;
222 data = *second;
223 break;
224 case T_STRING_INPLACE:
225 cb = PyString_FromStringSafe;
226 data = second;
227 break;
228 case T_INT:
229 cb = PyInt_FromLong;
230 data = *second;
231 break;
234 return cb(data);
237 static PyObject *
238 SPy_Set(PyObject *obj, PyObject *value, void *closure)
240 return NULL;
243 static int
244 PyDispatch(void *handler, const char *params, va_list va)
246 PyCallback *callback = handler;
247 PyObject *args, *ret;
248 int count, retval;
249 const char *p;
250 SPyCallback *scallback = callback->_obj;
252 for (count = 0, p = params; *p; p++, count++)
254 if (count > 0)
255 args = PyTuple_New(count);
256 else
257 args = NULL;
259 for (count = 0, p = params; *p; p++, count++)
261 PyObject *item = NULL;
262 switch (*p)
264 case 's':
265 item = PyString_FromStringSafe(va_arg(va, char *));
266 break;
267 case 'S':
269 char **ls = va_arg(va, char **), **iter;
270 int c = 0;
271 for (iter = ls; iter && *iter; iter++, c++)
273 if (c == 0)
274 break;
275 item = PyTuple_New(c);
276 for (c = 0, iter = ls; iter && *iter; iter++, c++)
277 PyTuple_SetItem(item, c, PyString_FromStringSafe(*iter));
279 break;
280 case 'i':
281 item = PyInt_FromLong(va_arg(va, int));
282 break;
283 case 'd':
284 item = PyObject_FromDisplay(va_arg(va, struct display *));
285 break;
288 if (!item)
290 item = Py_None;
291 Py_INCREF(Py_None);
293 PyTuple_SetItem(args, count, item);
296 ret = PyObject_CallObject(scallback->callback, args);
297 Py_DECREF(args);
298 if (!ret)
299 return 0;
301 retval = (int)PyInt_AsLong(ret);
302 Py_DECREF(ret);
303 return retval;
306 /** Screen {{{ */
307 static PyObject *
308 screen_display(PyObject *self)
310 if (!display)
312 RETURN_NONE;
314 return PyObject_FromDisplay(display);
317 static PyObject *
318 screen_displays(PyObject *self)
320 struct display *d = displays;
321 int count = 0;
322 for (; d; d = d->d_next)
323 ++count;
324 PyObject *tuple = PyTuple_New(count);
326 for (d = displays, count = 0; d; d = d->d_next, ++count)
327 PyTuple_SetItem(tuple, count, PyObject_FromDisplay(d));
329 return tuple;
332 static PyObject *
333 screen_windows(PyObject *self)
335 struct win *w = windows;
336 int count = 0;
337 for (; w; w = w->w_next)
338 ++count;
339 PyObject *tuple = PyTuple_New(count);
341 for (w = windows, count = 0; w; w = w->w_next, ++count)
342 PyTuple_SetItem(tuple, count, PyObject_FromWindow(w));
344 return tuple;
347 static PyObject *
348 hook_event(PyObject *self, PyObject *args, PyObject *kw)
350 static char *kwlist[] = {"event", "callback", NULL};
351 PyObject *callback;
352 char *name;
354 struct script_event *sev;
355 struct listener *l;
356 SPyCallback *scallback;
358 if (!PyArg_ParseTupleAndKeywords(args, kw, "sO:screen.hook", kwlist, &name, &callback))
359 return NULL; /* Return Py_None instead? */
361 if (!PyCallable_Check(callback))
363 PyErr_SetString(PyExc_TypeError, "The event-callback functions must be callable.");
364 LMsg(0, "The event-callback functions must be callable.");
365 return NULL;
368 sev = object_get_event(NULL, name);
369 if (!sev)
371 LMsg(0, "No event named '%s'", name);
372 return NULL;
375 l = malloc(sizeof(struct listener));
377 scallback = malloc(sizeof(SPyCallback));
378 scallback->callback = callback;
379 scallback->listener = l;
380 Py_INCREF(scallback->callback);
382 l->handler = PyObject_FromCallback(scallback);
383 l->priv = 0;
384 l->dispatcher = PyDispatch;
385 if (register_listener(sev, l))
387 Py_DECREF((PyObject *)l->handler);
388 FreeCallback(scallback);
389 Free(l);
391 LMsg(0, "Hook could not be registered.");
393 RETURN_NONE;
396 Py_INCREF((PyObject *)l->handler);
397 return l->handler;
400 static void
401 screen_input_cb(char *buf, int len, char *p)
403 PyObject *callback = p;
404 PyObject *str = PyTuple_New(1);
405 PyTuple_SetItem(str, 0, PyString_FromStringSafe(buf));
406 PyObject_CallObject(callback, str);
407 Py_DECREF(str);
408 Py_DECREF(callback);
411 static PyObject *
412 screen_input(PyObject *self, PyObject *args, PyObject *kw)
414 static char *kwlist[] = {"prompt", "callback", "value (optional)", NULL};
415 char *prompt, *pre = NULL;
416 PyObject *callback;
418 if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|s:screen.input", kwlist, &prompt, &callback, &pre))
420 LMsg(0, "Could not parse all the parameters to screen.input call.");
421 return NULL;
424 if (!PyCallable_Check(callback))
426 LMsg(0, "Input callback must be a callable object.");
427 return NULL;
430 Py_INCREF(callback);
431 Input(prompt, 100 /* huh? */,
432 INP_COOKED, screen_input_cb, callback, 0);
434 if (pre && *pre)
436 int len = strlen(pre);
437 LayProcess(&pre, &len);
440 RETURN_NONE;
443 const PyMethodDef py_methods[] = {
444 {"display", (PyCFunction)screen_display, METH_NOARGS, "Get the current display."},
445 {"displays", (PyCFunction)screen_displays, METH_NOARGS, "Get the list of displays."},
446 {"hook", (PyCFunction)hook_event, METH_VARARGS|METH_KEYWORDS, "Hook a callback to an event."},
447 {"input", (PyCFunction)screen_input, METH_VARARGS|METH_KEYWORDS, "Read user input interactively."},
448 {"windows", (PyCFunction)screen_windows, METH_NOARGS, "Get the list of windows."},
449 {NULL, NULL, 0, NULL}
451 /** }}} */
453 static int
454 SPyInit(void)
456 PyObject *m;
458 Py_Initialize();
460 m = Py_InitModule3 ("screen", py_methods, NULL);
461 register_window(m);
462 register_display(m);
463 register_callback(m);
465 return 0;
468 static int
469 SPyFinit(void)
471 Py_Finalize();
472 return 0;
475 static int
476 SPySource(const char *file, int async)
478 FILE *f = fopen(file, "rb");
479 int ret = PyRun_SimpleFile(f, file);
480 fclose(f);
482 if (ret == 0)
483 return 1; /* Success */
485 if (PyErr_Occurred())
487 PyErr_Print();
488 return 0;
491 return 1;
494 struct binding py_binding =
496 "python",
499 SPyInit,
500 SPyFinit,
502 SPySource,