1 /* Keystroke bindings for Python. */
14 #include "config/kbdbind.h"
15 #include "intl/gettext/libintl.h"
16 #include "main/event.h"
17 #include "scripting/python/core.h"
18 #include "session/session.h"
19 #include "util/error.h"
20 #include "util/string.h"
22 static PyObject
*keybindings
= NULL
;
24 /* C wrapper that invokes Python callbacks for bind_key_to_event_name(). */
26 static enum evhook_status
27 invoke_keybinding_callback(va_list ap
, void *data
)
29 PyObject
*callback
= data
;
30 struct session
*saved_python_ses
= python_ses
;
33 python_ses
= va_arg(ap
, struct session
*);
35 result
= PyObject_CallFunction(callback
, NULL
);
41 python_ses
= saved_python_ses
;
43 return EVENT_HOOK_STATUS_NEXT
;
46 /* Check that a keymap name is valid. */
49 keymap_is_valid(const unsigned char *keymap
)
51 enum keymap_id keymap_id
;
53 for (keymap_id
= 0; keymap_id
< KEYMAP_MAX
; ++keymap_id
)
54 if (!strcmp(keymap
, get_keymap_name(keymap_id
)))
56 return (keymap_id
!= KEYMAP_MAX
);
59 /* Python interface for binding keystrokes to callable objects. */
61 static char python_bind_key_doc
[] =
62 PYTHON_DOCSTRING("bind_key(keystroke, callback[, keymap]) -> None\n\
64 Bind a keystroke to a callable object.\n\
68 keystroke -- A string containing a keystroke. The syntax for\n\
69 keystrokes is described in the elinkskeys(5) man page.\n\
70 callback -- A callable object to be called when the keystroke is\n\
71 typed. It will be called without any arguments.\n\
73 Optional arguments:\n\
75 keymap -- A string containing the name of a keymap. Valid keymap\n\
76 names can be found in the elinkskeys(5) man page. By\n\
77 default the \"main\" keymap is used.\n");
80 python_bind_key(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
82 const unsigned char *keystroke
;
84 unsigned char *keymap
= "main";
86 PyObject
*old_callback
;
87 struct string event_name
;
89 unsigned char *error_msg
;
90 static char *kwlist
[] = {"keystroke", "callback", "keymap", NULL
};
92 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "sO|s:bind_key", kwlist
,
93 &keystroke
, &callback
, &keymap
))
96 assert(keystroke
&& callback
&& keymap
);
98 PyErr_SetString(python_elinks_err
, N_("Internal error"));
102 if (!keymap_is_valid(keymap
)) {
103 PyErr_Format(python_elinks_err
, "%s \"%s\"",
104 N_("Unrecognised keymap"), keymap
);
109 * The callback object needs to be kept alive for as long as the
110 * keystroke is bound, so we stash a reference to it in a dictionary.
111 * We don't need to use the dictionary to find callbacks; its sole
112 * purpose is to prevent these objects from being garbage-collected
113 * by the Python interpreter.
115 * If binding the key fails for any reason after this point then
116 * we'll need to restore the dictionary to its previous state, which
117 * is temporarily preserved in @old_callback.
119 key_tuple
= Py_BuildValue("ss", keymap
, keystroke
);
122 old_callback
= PyDict_GetItem(keybindings
, key_tuple
);
123 Py_XINCREF(old_callback
);
124 if (PyDict_SetItem(keybindings
, key_tuple
, callback
) != 0) {
125 Py_DECREF(key_tuple
);
126 Py_XDECREF(old_callback
);
130 if (!init_string(&event_name
)) {
134 if (!add_format_to_string(&event_name
, "python-func %p", callback
)) {
135 PyErr_SetFromErrno(python_elinks_err
);
136 done_string(&event_name
);
139 event_id
= bind_key_to_event_name(keymap
, keystroke
, event_name
.source
,
141 done_string(&event_name
);
143 PyErr_SetString(python_elinks_err
, error_msg
);
147 event_id
= register_event_hook(event_id
, invoke_keybinding_callback
, 0,
149 if (event_id
== EVENT_NONE
) {
150 PyErr_SetString(python_elinks_err
,
151 N_("Error registering event hook"));
155 Py_DECREF(key_tuple
);
156 Py_XDECREF(old_callback
);
163 * If an error occurred, try to restore the keybindings dictionary
164 * to its previous state.
167 (void) PyDict_SetItem(keybindings
, key_tuple
, old_callback
);
168 Py_DECREF(old_callback
);
170 (void) PyDict_DelItem(keybindings
, key_tuple
);
173 Py_DECREF(key_tuple
);
177 static PyMethodDef keybinding_methods
[] = {
178 {"bind_key", (PyCFunction
) python_bind_key
,
179 METH_VARARGS
| METH_KEYWORDS
,
180 python_bind_key_doc
},
182 {NULL
, NULL
, 0, NULL
}
186 python_init_keybinding_interface(PyObject
*dict
, PyObject
*name
)
188 keybindings
= PyDict_New();
189 if (!keybindings
) return -1;
191 return add_python_methods(dict
, name
, keybinding_methods
);
195 python_done_keybinding_interface(void)
199 /* This is equivalent to Py_CLEAR(), but it works with older
200 * versions of Python predating that macro: */