OILS / pyext / line_input.c View on Github | oils.pub

2000 lines, 1144 significant
1/* This module makes GNU readline available to Python. It has ideas
2 * contributed by Lee Busby, LLNL, and William Magro, Cornell Theory
3 * Center. The completer interface was inspired by Lele Gaifax. More
4 * recently, it was largely rewritten by Guido van Rossum.
5 */
6
7/* Standard definitions */
8#include "Python.h"
9#include <setjmp.h>
10#include <signal.h>
11#include <errno.h>
12#include <sys/time.h>
13
14/* ------------------------------------------------------------------------- */
15
16/* OVM_MAIN: This section copied from autotool-generated pyconfig.h.
17 * We're not detecting any of it in Oil's configure script. They are for
18 * ancient readline versions.
19 * */
20
21/* Define if you have readline 2.1 */
22#define HAVE_RL_CALLBACK 1
23
24/* Define if you can turn off readline's signal handling. */
25#define HAVE_RL_CATCH_SIGNAL 1
26
27/* Define if you have readline 2.2 */
28#define HAVE_RL_COMPLETION_APPEND_CHARACTER 1
29
30/* Define if you have readline 4.0 */
31#define HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK 1
32
33/* Define if you have readline 4.2 */
34#define HAVE_RL_COMPLETION_MATCHES 1
35
36/* Define if you have rl_completion_suppress_append */
37#define HAVE_RL_COMPLETION_SUPPRESS_APPEND 1
38
39/* Define if you have readline 4.0 */
40#define HAVE_RL_PRE_INPUT_HOOK 1
41
42/* Define if you have readline 4.0 */
43#define HAVE_RL_RESIZE_TERMINAL 1
44
45/* ------------------------------------------------------------------------- */
46
47#if defined(HAVE_SETLOCALE)
48/* GNU readline() mistakenly sets the LC_CTYPE locale.
49 * This is evil. Only the user or the app's main() should do this!
50 * We must save and restore the locale around the rl_initialize() call.
51 */
52#define SAVE_LOCALE
53#include <locale.h>
54#endif
55
56#ifdef SAVE_LOCALE
57# define RESTORE_LOCALE(sl) { setlocale(LC_CTYPE, sl); free(sl); }
58#else
59# define RESTORE_LOCALE(sl)
60#endif
61
62/* GNU readline definitions */
63#undef HAVE_CONFIG_H /* Else readline/chardefs.h includes strings.h */
64#include <readline/readline.h>
65#include <readline/history.h>
66
67#ifdef HAVE_RL_COMPLETION_MATCHES
68#define completion_matches(x, y) \
69 rl_completion_matches((x), ((rl_compentry_func_t *)(y)))
70#else
71#if defined(_RL_FUNCTION_TYPEDEF)
72extern char **completion_matches(char *, rl_compentry_func_t *);
73#else
74
75#if !defined(__APPLE__)
76extern char **completion_matches(char *, CPFunction *);
77#endif
78#endif
79#endif
80
81#ifdef __APPLE__
82/*
83 * It is possible to link the readline module to the readline
84 * emulation library of editline/libedit.
85 *
86 * On OSX this emulation library is not 100% API compatible
87 * with the "real" readline and cannot be detected at compile-time,
88 * hence we use a runtime check to detect if we're using libedit
89 *
90 * Currently there is one known API incompatibility:
91 * - 'get_history' has a 1-based index with GNU readline, and a 0-based
92 * index with older versions of libedit's emulation.
93 * - Note that replace_history and remove_history use a 0-based index
94 * with both implementations.
95 */
96static int using_libedit_emulation = 0;
97static const char libedit_version_tag[] = "EditLine wrapper";
98
99static int libedit_history_start = 0;
100#endif /* __APPLE__ */
101
102#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
103static void
104on_completion_display_matches_hook(char **matches,
105 int num_matches, int max_length);
106#endif
107
108/* Memory allocated for rl_completer_word_break_characters
109 (see issue #17289 for the motivation). */
110static char *completer_word_break_characters;
111
112/* Exported function to send one line to readline's init file parser */
113
114static PyObject *
115parse_and_bind(PyObject *self, PyObject *args)
116{
117 char *s, *copy;
118 int binding_result;
119
120 if (!PyArg_ParseTuple(args, "s:parse_and_bind", &s))
121 return NULL;
122 /* Make a copy -- rl_parse_and_bind() modifies its argument */
123 /* Bernard Herzog */
124 copy = malloc(1 + strlen(s));
125 if (copy == NULL)
126 return PyErr_NoMemory();
127 strcpy(copy, s);
128
129 binding_result = rl_parse_and_bind(copy);
130 free(copy); /* Free the copy */
131
132 if (binding_result != 0) {
133 PyErr_Format(PyExc_ValueError, "'%s': invalid binding", s);
134 return NULL;
135 }
136
137 Py_RETURN_NONE;
138}
139
140PyDoc_STRVAR(doc_parse_and_bind,
141"parse_and_bind(string) -> None\n\
142Bind a key sequence to a readline function (or a variable to a value).");
143
144
145
146/* Exported function to parse a readline init file */
147
148static PyObject *
149read_init_file(PyObject *self, PyObject *args)
150{
151 char *s = NULL;
152 if (!PyArg_ParseTuple(args, "|z:read_init_file", &s))
153 return NULL;
154 errno = rl_read_init_file(s);
155 if (errno)
156 return PyErr_SetFromErrno(PyExc_IOError);
157 Py_RETURN_NONE;
158}
159
160PyDoc_STRVAR(doc_read_init_file,
161"read_init_file([filename]) -> None\n\
162Execute a readline initialization file.\n\
163The default filename is the last filename used.");
164
165
166/* Exported function to load a readline history file */
167
168static PyObject *
169read_history_file(PyObject *self, PyObject *args)
170{
171 char *s = NULL;
172 if (!PyArg_ParseTuple(args, "|z:read_history_file", &s))
173 return NULL;
174 errno = read_history(s);
175 if (errno)
176 return PyErr_SetFromErrno(PyExc_IOError);
177 Py_RETURN_NONE;
178}
179
180static int _history_length = -1; /* do not truncate history by default */
181PyDoc_STRVAR(doc_read_history_file,
182"read_history_file([filename]) -> None\n\
183Load a readline history file.\n\
184The default filename is ~/.history.");
185
186
187/* Exported function to save a readline history file */
188
189static PyObject *
190write_history_file(PyObject *self, PyObject *args)
191{
192 char *s = NULL;
193 if (!PyArg_ParseTuple(args, "|z:write_history_file", &s))
194 return NULL;
195 errno = write_history(s);
196 if (!errno && _history_length >= 0)
197 history_truncate_file(s, _history_length);
198 if (errno)
199 return PyErr_SetFromErrno(PyExc_IOError);
200 Py_RETURN_NONE;
201}
202
203PyDoc_STRVAR(doc_write_history_file,
204"write_history_file([filename]) -> None\n\
205Save a readline history file.\n\
206The default filename is ~/.history.");
207
208
209/* Set history length */
210
211static PyObject*
212set_history_length(PyObject *self, PyObject *args)
213{
214 int length = _history_length;
215 if (!PyArg_ParseTuple(args, "i:set_history_length", &length))
216 return NULL;
217 _history_length = length;
218 Py_RETURN_NONE;
219}
220
221PyDoc_STRVAR(set_history_length_doc,
222"set_history_length(length) -> None\n\
223set the maximal number of lines which will be written to\n\
224the history file. A negative length is used to inhibit\n\
225history truncation.");
226
227
228/* Get history length */
229
230static PyObject*
231get_history_length(PyObject *self, PyObject *noarg)
232{
233 return PyInt_FromLong(_history_length);
234}
235
236PyDoc_STRVAR(get_history_length_doc,
237"get_history_length() -> int\n\
238return the maximum number of lines that will be written to\n\
239the history file.");
240
241
242/* Generic hook function setter */
243
244static PyObject *
245set_hook(const char *funcname, PyObject **hook_var, PyObject *args)
246{
247 PyObject *function = Py_None;
248 char buf[80];
249 PyOS_snprintf(buf, sizeof(buf), "|O:set_%.50s", funcname);
250 if (!PyArg_ParseTuple(args, buf, &function))
251 return NULL;
252 if (function == Py_None) {
253 Py_CLEAR(*hook_var);
254 }
255 else if (PyCallable_Check(function)) {
256 PyObject *tmp = *hook_var;
257 Py_INCREF(function);
258 *hook_var = function;
259 Py_XDECREF(tmp);
260 }
261 else {
262 PyOS_snprintf(buf, sizeof(buf),
263 "set_%.50s(func): argument not callable",
264 funcname);
265 PyErr_SetString(PyExc_TypeError, buf);
266 return NULL;
267 }
268 Py_RETURN_NONE;
269}
270
271
272/* Exported functions to specify hook functions in Python */
273
274static PyObject *completion_display_matches_hook = NULL;
275static PyObject *startup_hook = NULL;
276static PyObject *bind_shell_command_hook = NULL;
277
278#ifdef HAVE_RL_PRE_INPUT_HOOK
279static PyObject *pre_input_hook = NULL;
280#endif
281
282static PyObject *
283set_completion_display_matches_hook(PyObject *self, PyObject *args)
284{
285 PyObject *result = set_hook("completion_display_matches_hook",
286 &completion_display_matches_hook, args);
287#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
288 /* We cannot set this hook globally, since it replaces the
289 default completion display. */
290 rl_completion_display_matches_hook =
291 completion_display_matches_hook ?
292#if defined(_RL_FUNCTION_TYPEDEF)
293 (rl_compdisp_func_t *)on_completion_display_matches_hook : 0;
294#else
295 (VFunction *)on_completion_display_matches_hook : 0;
296#endif
297#endif
298 return result;
299
300}
301
302PyDoc_STRVAR(doc_set_completion_display_matches_hook,
303"set_completion_display_matches_hook([function]) -> None\n\
304Set or remove the completion display function.\n\
305The function is called as\n\
306 function(substitution, [matches], longest_match_length)\n\
307once each time matches need to be displayed.");
308
309static PyObject *
310set_startup_hook(PyObject *self, PyObject *args)
311{
312 return set_hook("startup_hook", &startup_hook, args);
313}
314
315PyDoc_STRVAR(doc_set_startup_hook,
316"set_startup_hook([function]) -> None\n\
317Set or remove the function invoked by the rl_startup_hook callback.\n\
318The function is called with no arguments just\n\
319before readline prints the first prompt.");
320
321
322#ifdef HAVE_RL_PRE_INPUT_HOOK
323
324/* Set pre-input hook */
325
326static PyObject *
327set_pre_input_hook(PyObject *self, PyObject *args)
328{
329 return set_hook("pre_input_hook", &pre_input_hook, args);
330}
331
332PyDoc_STRVAR(doc_set_pre_input_hook,
333"set_pre_input_hook([function]) -> None\n\
334Set or remove the function invoked by the rl_pre_input_hook callback.\n\
335The function is called with no arguments after the first prompt\n\
336has been printed and just before readline starts reading input\n\
337characters.");
338
339#endif
340
341
342
343/* Exported function to specify a word completer in Python */
344
345static PyObject *completer = NULL;
346
347static PyObject *begidx = NULL;
348static PyObject *endidx = NULL;
349
350
351/* Get the completion type for the scope of the tab-completion */
352static PyObject *
353get_completion_type(PyObject *self, PyObject *noarg)
354{
355 return PyInt_FromLong(rl_completion_type);
356}
357
358PyDoc_STRVAR(doc_get_completion_type,
359"get_completion_type() -> int\n\
360Get the type of completion being attempted.");
361
362
363/* Set bind -x Python command hook */
364
365static PyObject *
366set_bind_shell_command_hook(PyObject *self, PyObject *args)
367{
368 return set_hook("bind_shell_command_hook", &bind_shell_command_hook, args);
369}
370
371PyDoc_STRVAR(doc_set_bind_shell_command_hook,
372"set_bind_shell_command_hook([function]) -> None\n\
373Set or remove the function invoked by the rl_bind_keyseq_in_map callback.\n\
374The function is called with three arguments: the string to parse and evaluate,\n\
375the contents of the readline buffer to put in the READLINE_LINE env var,\n\
376and the int of the cursor's point in the buffer to put in READLINE_POINT.\n\
377It must return the READLINE_* vars in a tuple.");
378
379
380/* Get the beginning index for the scope of the tab-completion */
381
382static PyObject *
383get_begidx(PyObject *self, PyObject *noarg)
384{
385 Py_INCREF(begidx);
386 return begidx;
387}
388
389PyDoc_STRVAR(doc_get_begidx,
390"get_begidx() -> int\n\
391get the beginning index of the completion scope");
392
393
394/* Get the ending index for the scope of the tab-completion */
395
396static PyObject *
397get_endidx(PyObject *self, PyObject *noarg)
398{
399 Py_INCREF(endidx);
400 return endidx;
401}
402
403PyDoc_STRVAR(doc_get_endidx,
404"get_endidx() -> int\n\
405get the ending index of the completion scope");
406
407
408/* Set the tab-completion word-delimiters that readline uses */
409
410static PyObject *
411set_completer_delims(PyObject *self, PyObject *args)
412{
413 char *break_chars;
414
415 if (!PyArg_ParseTuple(args, "s:set_completer_delims", &break_chars)) {
416 return NULL;
417 }
418 /* Keep a reference to the allocated memory in the module state in case
419 some other module modifies rl_completer_word_break_characters
420 (see issue #17289). */
421 break_chars = strdup(break_chars);
422 if (break_chars) {
423 free(completer_word_break_characters);
424 completer_word_break_characters = break_chars;
425 rl_completer_word_break_characters = break_chars;
426 Py_RETURN_NONE;
427 }
428 else
429 return PyErr_NoMemory();
430}
431
432PyDoc_STRVAR(doc_set_completer_delims,
433"set_completer_delims(string) -> None\n\
434set the word delimiters for completion");
435
436/* _py_free_history_entry: Utility function to free a history entry. */
437
438#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0500
439
440/* Readline version >= 5.0 introduced a timestamp field into the history entry
441 structure; this needs to be freed to avoid a memory leak. This version of
442 readline also introduced the handy 'free_history_entry' function, which
443 takes care of the timestamp. */
444
445static void
446_py_free_history_entry(HIST_ENTRY *entry)
447{
448 histdata_t data = free_history_entry(entry);
449 free(data);
450}
451
452#else
453
454/* No free_history_entry function; free everything manually. */
455
456static void
457_py_free_history_entry(HIST_ENTRY *entry)
458{
459 if (entry->line)
460 free((void *)entry->line);
461 if (entry->data)
462 free(entry->data);
463 free(entry);
464}
465
466#endif
467
468static PyObject *
469py_remove_history(PyObject *self, PyObject *args)
470{
471 int entry_number;
472 HIST_ENTRY *entry;
473
474 if (!PyArg_ParseTuple(args, "i:remove_history_item", &entry_number))
475 return NULL;
476 if (entry_number < 0) {
477 PyErr_SetString(PyExc_ValueError,
478 "History index cannot be negative");
479 return NULL;
480 }
481 entry = remove_history(entry_number);
482 if (!entry) {
483 PyErr_Format(PyExc_ValueError,
484 "No history item at position %d",
485 entry_number);
486 return NULL;
487 }
488 /* free memory allocated for the history entry */
489 _py_free_history_entry(entry);
490 Py_RETURN_NONE;
491}
492
493PyDoc_STRVAR(doc_remove_history,
494"remove_history_item(pos) -> None\n\
495remove history item given by its position");
496
497static PyObject *
498py_replace_history(PyObject *self, PyObject *args)
499{
500 int entry_number;
501 char *line;
502 HIST_ENTRY *old_entry;
503
504 if (!PyArg_ParseTuple(args, "is:replace_history_item", &entry_number,
505 &line)) {
506 return NULL;
507 }
508 if (entry_number < 0) {
509 PyErr_SetString(PyExc_ValueError,
510 "History index cannot be negative");
511 return NULL;
512 }
513 old_entry = replace_history_entry(entry_number, line, (void *)NULL);
514 if (!old_entry) {
515 PyErr_Format(PyExc_ValueError,
516 "No history item at position %d",
517 entry_number);
518 return NULL;
519 }
520 /* free memory allocated for the old history entry */
521 _py_free_history_entry(old_entry);
522 Py_RETURN_NONE;
523}
524
525PyDoc_STRVAR(doc_replace_history,
526"replace_history_item(pos, line) -> None\n\
527replaces history item given by its position with contents of line");
528
529/* Add a line to the history buffer */
530
531static PyObject *
532py_add_history(PyObject *self, PyObject *args)
533{
534 char *line;
535
536 if(!PyArg_ParseTuple(args, "s:add_history", &line)) {
537 return NULL;
538 }
539 add_history(line);
540 Py_RETURN_NONE;
541}
542
543PyDoc_STRVAR(doc_add_history,
544"add_history(string) -> None\n\
545add an item to the history buffer");
546
547
548/* Get the tab-completion word-delimiters that readline uses */
549
550static PyObject *
551get_completer_delims(PyObject *self, PyObject *noarg)
552{
553 return PyString_FromString(rl_completer_word_break_characters);
554}
555
556PyDoc_STRVAR(doc_get_completer_delims,
557"get_completer_delims() -> string\n\
558get the word delimiters for completion");
559
560
561/* Set the completer function */
562
563static PyObject *
564set_completer(PyObject *self, PyObject *args)
565{
566 return set_hook("completer", &completer, args);
567}
568
569PyDoc_STRVAR(doc_set_completer,
570"set_completer([function]) -> None\n\
571Set or remove the completer function.\n\
572The function is called as function(text, state),\n\
573for state in 0, 1, 2, ..., until it returns a non-string.\n\
574It should return the next possible completion starting with 'text'.");
575
576
577static PyObject *
578get_completer(PyObject *self, PyObject *noargs)
579{
580 if (completer == NULL) {
581 Py_RETURN_NONE;
582 }
583 Py_INCREF(completer);
584 return completer;
585}
586
587PyDoc_STRVAR(doc_get_completer,
588"get_completer() -> function\n\
589\n\
590Returns current completer function.");
591
592/* Private function to get current length of history. XXX It may be
593 * possible to replace this with a direct use of history_length instead,
594 * but it's not clear whether BSD's libedit keeps history_length up to date.
595 * See issue #8065.*/
596
597static int
598_py_get_history_length(void)
599{
600 HISTORY_STATE *hist_st = history_get_history_state();
601 int length = hist_st->length;
602 /* the history docs don't say so, but the address of hist_st changes each
603 time history_get_history_state is called which makes me think it's
604 freshly malloc'd memory... on the other hand, the address of the last
605 line stays the same as long as history isn't extended, so it appears to
606 be malloc'd but managed by the history package... */
607 free(hist_st);
608 return length;
609}
610
611/* Exported function to get any element of history */
612
613static PyObject *
614get_history_item(PyObject *self, PyObject *args)
615{
616 int idx = 0;
617 HIST_ENTRY *hist_ent;
618
619 if (!PyArg_ParseTuple(args, "i:get_history_item", &idx))
620 return NULL;
621#ifdef __APPLE__
622 if (using_libedit_emulation) {
623 /* Older versions of libedit's readline emulation
624 * use 0-based indexes, while readline and newer
625 * versions of libedit use 1-based indexes.
626 */
627 int length = _py_get_history_length();
628
629 idx = idx - 1 + libedit_history_start;
630
631 /*
632 * Apple's readline emulation crashes when
633 * the index is out of range, therefore
634 * test for that and fail gracefully.
635 */
636 if (idx < (0 + libedit_history_start)
637 || idx >= (length + libedit_history_start)) {
638 Py_RETURN_NONE;
639 }
640 }
641#endif /* __APPLE__ */
642 if ((hist_ent = history_get(idx)))
643 return PyString_FromString(hist_ent->line);
644 else {
645 Py_RETURN_NONE;
646 }
647}
648
649PyDoc_STRVAR(doc_get_history_item,
650"get_history_item() -> string\n\
651return the current contents of history item at index.");
652
653
654/* Exported function to get current length of history */
655
656static PyObject *
657get_current_history_length(PyObject *self, PyObject *noarg)
658{
659 return PyInt_FromLong((long)_py_get_history_length());
660}
661
662PyDoc_STRVAR(doc_get_current_history_length,
663"get_current_history_length() -> integer\n\
664return the current (not the maximum) length of history.");
665
666
667/* Exported function to read the current line buffer */
668
669static PyObject *
670get_line_buffer(PyObject *self, PyObject *noarg)
671{
672 return PyString_FromString(rl_line_buffer);
673}
674
675PyDoc_STRVAR(doc_get_line_buffer,
676"get_line_buffer() -> string\n\
677return the current contents of the line buffer.");
678
679
680#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
681
682/* Exported function to clear the current history */
683
684static PyObject *
685py_clear_history(PyObject *self, PyObject *noarg)
686{
687 clear_history();
688 Py_RETURN_NONE;
689}
690
691PyDoc_STRVAR(doc_clear_history,
692"clear_history() -> None\n\
693Clear the current readline history.");
694#endif
695
696/* Added for OSH. We need to call this in our SIGWINCH handler so global
697 * variables in readline get updated. */
698static PyObject *
699py_resize_terminal(PyObject *self, PyObject *noarg)
700{
701 rl_resize_terminal();
702 Py_RETURN_NONE;
703}
704
705/* Exported function to insert text into the line buffer */
706
707static PyObject *
708insert_text(PyObject *self, PyObject *args)
709{
710 char *s;
711 if (!PyArg_ParseTuple(args, "s:insert_text", &s))
712 return NULL;
713 rl_insert_text(s);
714 Py_RETURN_NONE;
715}
716
717PyDoc_STRVAR(doc_insert_text,
718"insert_text(string) -> None\n\
719Insert text into the line buffer at the cursor position.");
720
721
722/* Redisplay the line buffer */
723
724static PyObject *
725redisplay(PyObject *self, PyObject *noarg)
726{
727 rl_redisplay();
728 Py_RETURN_NONE;
729}
730
731PyDoc_STRVAR(doc_redisplay,
732"redisplay() -> None\n\
733Change what's displayed on the screen to reflect the current\n\
734contents of the line buffer.");
735
736
737/* Functions added to implement the 'bind' builtin in OSH */
738
739/* -x/-X command keymaps */
740static Keymap emacs_cmd_map;
741static Keymap vi_insert_cmd_map;
742static Keymap vi_movement_cmd_map;
743
744/*
745 These forcibly cast between a Keymap* and a rl_command_func_t*. Readline
746 uses an additional `.type` field to keep track of the pointer's true type.
747*/
748#define RL_KEYMAP_TO_FUNCTION(data) (rl_command_func_t *)(data)
749#define RL_FUNCTION_TO_KEYMAP(map, key) (Keymap)(map[key].function)
750
751static void
752_init_command_maps(void)
753{
754 printf("initializing command maps\n");
755 emacs_cmd_map = rl_make_bare_keymap();
756 vi_insert_cmd_map = rl_make_bare_keymap();
757 vi_movement_cmd_map = rl_make_bare_keymap();
758
759 /* Ensure that Esc- and Ctrl-X are also keymaps */
760 emacs_cmd_map[CTRL('X')].type = ISKMAP;
761 emacs_cmd_map[CTRL('X')].function = RL_KEYMAP_TO_FUNCTION(rl_make_bare_keymap());
762 emacs_cmd_map[ESC].type = ISKMAP;
763 emacs_cmd_map[ESC].function = RL_KEYMAP_TO_FUNCTION(rl_make_bare_keymap());
764}
765
766static Keymap
767_get_associated_cmd_map(Keymap kmap)
768{
769 if (emacs_cmd_map == NULL)
770 _init_command_maps();
771
772 if (kmap == emacs_standard_keymap) {
773 printf("returning emacs_cmd_map\n");
774 return emacs_cmd_map;
775 }
776 else if (kmap == vi_insertion_keymap){
777 printf("returning vi_insert_cmd_map\n");
778 return vi_insert_cmd_map;
779 }
780 else if (kmap == vi_movement_keymap){
781 printf("returning vi_movement_cmd_map\n");
782 return vi_movement_cmd_map;
783 }
784 else if (kmap == emacs_meta_keymap){
785 printf("returning RL_FUNCTION_TO_KEYMAP(emacs_cmd_map, ESC)\n");
786 return (RL_FUNCTION_TO_KEYMAP(emacs_cmd_map, ESC));}
787 else if (kmap == emacs_ctlx_keymap){
788 printf("returning RL_FUNCTION_TO_KEYMAP(emacs_cmd_map, CTRL('X'))\n");
789 return (RL_FUNCTION_TO_KEYMAP(emacs_cmd_map, CTRL('X')));}
790
791 printf("FOUND NO CMD MAP!!!\n");
792 return (Keymap) NULL;
793}
794
795/* List binding functions */
796static PyObject*
797list_funmap_names(PyObject *self, PyObject *args)
798{
799 rl_list_funmap_names();
800 // printf ("Compiled w/ readline version: %s\n", rl_library_version ? rl_library_version : "unknown");
801 Py_RETURN_NONE;
802}
803
804PyDoc_STRVAR(doc_list_funmap_names,
805"list_funmap_names() -> None\n\
806Print all of the available readline functions.");
807
808/* Print readline functions and their bindings */
809
810static PyObject*
811function_dumper(PyObject *self, PyObject *args)
812{
813 int print_readably;
814
815 if (!PyArg_ParseTuple(args, "i:function_dumper", &print_readably))
816 return NULL;
817
818 rl_function_dumper(print_readably);
819 Py_RETURN_NONE;
820}
821
822PyDoc_STRVAR(doc_list_function_dumper,
823"function_dumper(bool) -> None\n\
824Print all readline functions and their bindings.");
825
826/* Print macros, their bindings, and their string outputs */
827
828static PyObject*
829macro_dumper(PyObject *self, PyObject *args)
830{
831 int print_readably;
832
833 if (!PyArg_ParseTuple(args, "i:macro_dumper", &print_readably))
834 return NULL;
835
836 rl_macro_dumper(print_readably);
837 Py_RETURN_NONE;
838}
839
840PyDoc_STRVAR(doc_list_macro_dumper,
841"macro_dumper(bool) -> None\n\
842Print all readline sequences bound to macros and the strings they output.");
843
844/* List readline variables */
845
846static PyObject*
847variable_dumper(PyObject *self, PyObject *args)
848{
849 int print_readably;
850
851 if (!PyArg_ParseTuple(args, "i:variable_dumper", &print_readably))
852 return NULL;
853
854 rl_variable_dumper(print_readably);
855 Py_RETURN_NONE;
856}
857
858PyDoc_STRVAR(doc_list_variable_dumper,
859"variable_dumper(bool) -> None\n\
860List readline variables and their values.");
861
862
863/* Query bindings for a function name */
864
865// readline returns null-terminated string arrays
866void _strvec_dispose(char **strvec) {
867 register int i;
868
869 if (strvec == NULL)
870 return;
871
872 for (i = 0; strvec[i]; i++) {
873 free(strvec[i]);
874 }
875
876 free(strvec);
877}
878
879// Nicely prints a strvec with commas and an and
880// like '"foo", "bar", and "moop"'
881void _pprint_strvec_list(char **strvec) {
882 int i;
883
884 for (i = 0; strvec[i]; i++) {
885 printf("\"%s\"", strvec[i]);
886 if (strvec[i + 1]) {
887 printf(", ");
888 if (!strvec[i + 2])
889 printf("and ");
890 }
891 }
892}
893
894/*
895NB: readline (and bash) have a bug where they don't see certain keyseqs, even
896if the bindings work. E.g., if you bind a number key like "\C-7", it will be
897bound, but reporting code like query_bindings and function_dumper won't count it.
898*/
899
900static PyObject*
901query_bindings(PyObject *self, PyObject *args)
902{
903 char *fn_name;
904 rl_command_func_t *cmd_fn;
905 char **key_seqs;
906
907 if (!PyArg_ParseTuple(args, "s:query_bindings", &fn_name))
908 return NULL;
909
910 cmd_fn = rl_named_function(fn_name);
911
912 if (cmd_fn == NULL) {
913 PyErr_Format(PyExc_ValueError, "`%s': unknown function name", fn_name);
914 return NULL;
915 }
916
917 key_seqs = rl_invoking_keyseqs(cmd_fn);
918
919 if (!key_seqs) {
920 // print to stdout, but return an error
921 printf("%s is not bound to any keys.\n", fn_name);
922 PyErr_SetNone(PyExc_ValueError);
923 return NULL;
924 }
925
926 printf("%s can be invoked via ", fn_name);
927 _pprint_strvec_list(key_seqs);
928 printf(".\n");
929
930 _strvec_dispose(key_seqs);
931
932 Py_RETURN_NONE;
933}
934
935PyDoc_STRVAR(doc_query_bindings,
936"query_bindings(str) -> None\n\
937Query bindings to see what's bound to a given function.");
938
939
940static PyObject*
941unbind_rl_function(PyObject *self, PyObject *args)
942{
943 char *fn_name;
944 rl_command_func_t *cmd_fn;
945
946 if (!PyArg_ParseTuple(args, "s:unbind_rl_function", &fn_name))
947 return NULL;
948
949 cmd_fn = rl_named_function(fn_name);
950 if (cmd_fn == NULL) {
951 PyErr_Format(PyExc_ValueError, "`%s': unknown function name", fn_name);
952 return NULL;
953 }
954
955 rl_unbind_function_in_map(cmd_fn, rl_get_keymap());
956 Py_RETURN_NONE;
957}
958
959PyDoc_STRVAR(doc_unbind_rl_function,
960"unbind_rl_function(function_name) -> None\n\
961Unbind all keys bound to the named readline function in the current keymap.");
962
963
964static PyObject*
965unbind_shell_cmd(PyObject *self, PyObject *args)
966{
967 char *keyseq;
968 Keymap cmd_map;
969
970 if (!PyArg_ParseTuple(args, "s:unbind_shell_cmd", &keyseq))
971 return NULL;
972
973 cmd_map = _get_associated_cmd_map(rl_get_keymap());
974 if (cmd_map == NULL) {
975 PyErr_SetString(PyExc_ValueError, "Could not get command map for current keymap");
976 return NULL;
977 }
978
979 if (rl_bind_keyseq_in_map(keyseq, (rl_command_func_t *)NULL, cmd_map) != 0) {
980 PyErr_Format(PyExc_ValueError, "'%s': can't unbind from shell command keymap", keyseq);
981 return NULL;
982 }
983
984 Py_RETURN_NONE;
985}
986
987PyDoc_STRVAR(doc_unbind_shell_cmd,
988"unbind_shell_cmd(key_sequence) -> None\n\
989Unbind a key sequence from the current keymap's associated shell command map.");
990
991
992static PyObject*
993print_shell_cmd_map(PyObject *self, PyObject *noarg)
994{
995 // FIXME: this is wrong, it uses the rl func map, not the shell command map
996 Keymap curr_map, cmd_map;
997
998 curr_map = rl_get_keymap();
999 cmd_map = _get_associated_cmd_map(curr_map);
1000
1001 if (cmd_map == NULL) {
1002 PyErr_SetString(PyExc_ValueError, "Could not get shell command map for current keymap");
1003 return NULL;
1004 }
1005
1006 rl_set_keymap(cmd_map);
1007 rl_macro_dumper(1);
1008 rl_set_keymap(curr_map);
1009
1010 Py_RETURN_NONE;
1011}
1012
1013PyDoc_STRVAR(doc_print_shell_cmd_map,
1014"print_shell_cmd_map() -> None\n\
1015Print all bindings for shell commands in the current keymap.");
1016
1017
1018/* Remove all bindings for a given keyseq */
1019
1020static PyObject*
1021unbind_keyseq(PyObject *self, PyObject *args)
1022{
1023 char *seq, *keyseq;
1024 int kslen, type;
1025 rl_command_func_t *fn;
1026
1027 if (!PyArg_ParseTuple(args, "s:unbind_keyseq", &seq))
1028 return NULL;
1029
1030 // Commented code below based on bash 5.x unbinding code, which fails on
1031 // readline versions before 2019.
1032
1033 // keyseq = (char *)malloc((2 * strlen(seq)) + 1);
1034 // if (rl_translate_keyseq(seq, keyseq, &kslen) != 0) {
1035 // free(keyseq);
1036 // PyErr_Format(PyExc_ValueError, "'%s': cannot translate key sequence", seq);
1037 // return NULL;
1038 // }
1039
1040 // fn = rl_function_of_keyseq_len(keyseq, kslen, (Keymap)NULL, &type);
1041 // if (!fn) {
1042 // free(keyseq);
1043 // Py_RETURN_NONE;
1044 // }
1045
1046 // if (type == ISKMAP) {
1047 // fn = ((Keymap)fn)[ANYOTHERKEY].function;
1048 // }
1049
1050 // if (rl_bind_keyseq(seq, (rl_command_func_t *)NULL) != 0) {
1051 // free(keyseq);
1052 // PyErr_Format(PyExc_ValueError, "'%s': cannot unbind", seq);
1053 // return NULL;
1054 // }
1055
1056 // /*
1057 // TODO: Handle shell command unbinding if f == bash_execute_unix_command or
1058 // rather, whatever the osh equivalent will be
1059 // */
1060
1061 // free(keyseq);
1062 // Py_RETURN_NONE;
1063
1064 // End bash 5.x unbinding code
1065
1066
1067
1068 // Code below based on bash 4 unbinding code from 2011
1069
1070 if (rl_bind_keyseq (seq, (rl_command_func_t *)NULL) != 0) {
1071 PyErr_Format(PyExc_ValueError, "'%s': cannot unbind", seq);
1072 return NULL;
1073 }
1074
1075 Py_RETURN_NONE;
1076}
1077
1078PyDoc_STRVAR(doc_unbind_keyseq,
1079"unbind_keyseq(sequence) -> None\n\
1080Unbind a key sequence from the current keymap.");
1081
1082
1083/* Support fns for bind -x */
1084
1085static void
1086debug_print(const char *fmt, ...) {
1087 va_list args;
1088 va_start(args, fmt);
1089 printf("[osh_execute] ");
1090 vprintf(fmt, args);
1091 printf("\n");
1092 va_end(args);
1093}
1094
1095static void
1096make_line_if_needed(char *new_line)
1097{
1098 if (strcmp(new_line, rl_line_buffer) != 0) {
1099 rl_point = rl_end;
1100
1101 rl_add_undo(UNDO_BEGIN, 0, 0, 0);
1102 rl_delete_text(0, rl_point);
1103 rl_point = rl_end = rl_mark = 0;
1104 rl_insert_text(new_line);
1105 rl_add_undo(UNDO_END, 0, 0, 0);
1106 }
1107}
1108
1109static char*
1110get_bound_command(Keymap cmd_map) {
1111 int type;
1112 char *cmd = (char *)rl_function_of_keyseq(rl_executing_keyseq, cmd_map, &type);
1113
1114 if (cmd == NULL || type != ISMACR) {
1115 PyErr_SetString(PyExc_RuntimeError,
1116 "Cannot find shell command bound to this key sequence");
1117 return NULL;
1118 }
1119
1120 debug_print("Found bound command: %s", cmd);
1121 return cmd;
1122}
1123
1124static void
1125clear_current_line(int use_ce) {
1126 if (use_ce) {
1127 debug_print("Clearing line with termcap 'ce'");
1128 rl_clear_visible_line();
1129 fflush(rl_outstream);
1130 } else {
1131 debug_print("No termcap 'ce', using newline");
1132 rl_crlf();
1133 }
1134}
1135
1136
1137/* Save readline state to Python variables */
1138static int
1139save_readline_state(void) {
1140 PyObject *line = NULL, *point = NULL;
1141
1142 debug_print("Saving readline state - line: '%s', point: %d",
1143 rl_line_buffer, rl_point);
1144
1145 /* Create Python string for readline line */
1146 line = PyString_FromString(rl_line_buffer);
1147 if (!line) {
1148 PyErr_SetString(PyExc_RuntimeError,
1149 "Failed to convert readline line to Python string");
1150 return 0;
1151 }
1152
1153 /* Create Python int for readline point */
1154 point = PyInt_FromLong(rl_point);
1155 if (!point) {
1156 Py_DECREF(line);
1157 PyErr_SetString(PyExc_RuntimeError,
1158 "Failed to convert readline point to Python int");
1159 return 0;
1160 }
1161
1162 /* Set the Python variables */
1163 if (PyDict_SetItemString(PyEval_GetGlobals(), "READLINE_LINE", line) < 0 ||
1164 PyDict_SetItemString(PyEval_GetGlobals(), "READLINE_POINT", point) < 0) {
1165 Py_DECREF(line);
1166 Py_DECREF(point);
1167 PyErr_SetString(PyExc_RuntimeError,
1168 "Failed to set READLINE_LINE/POINT variables");
1169 return 0;
1170 }
1171
1172 Py_DECREF(line);
1173 Py_DECREF(point);
1174 return 1;
1175}
1176
1177/* Update readline state from Python variables */
1178static int
1179restore_readline_state(void) {
1180 PyObject *line = NULL, *point = NULL;
1181 const char *new_line;
1182 long new_point;
1183
1184 debug_print("Restoring readline state from Python variables");
1185
1186 /* Get the Python variables */
1187 line = PyDict_GetItemString(PyEval_GetGlobals(), "READLINE_LINE");
1188 point = PyDict_GetItemString(PyEval_GetGlobals(), "READLINE_POINT");
1189
1190 if (line && PyString_Check(line)) {
1191 new_line = PyString_AsString(line);
1192 debug_print("Got new line from Python: '%s'", new_line);
1193
1194 /* Update if different */
1195 if (strcmp(new_line, rl_line_buffer) != 0) {
1196 debug_print("Line changed, updating readline buffer");
1197 make_line_if_needed((char *)new_line);
1198 }
1199 }
1200
1201 if (point && PyInt_Check(point)) {
1202 new_point = PyInt_AsLong(point);
1203 debug_print("Got new point from Python: %ld", new_point);
1204
1205 /* Validate and update point if needed */
1206 if (new_point != rl_point) {
1207 if (new_point > rl_end)
1208 new_point = rl_end;
1209 else if (new_point < 0)
1210 new_point = 0;
1211
1212 debug_print("Point changed, updating to: %ld", new_point);
1213 rl_point = new_point;
1214 }
1215 }
1216
1217 return 1;
1218}
1219
1220/* Main entry point for executing shell commands. Based on bash_execute_unix_command */
1221
1222static int
1223on_bind_shell_command_hook(int count /* unused */, int key /* unused */) {
1224 char *cmd;
1225 int use_ce;
1226 Keymap cmd_map;
1227 PyObject *r = NULL;
1228 #ifdef WITH_THREAD
1229 PyGILState_STATE gilstate;
1230 #endif
1231 int cmd_return_code;
1232 char *line_buffer;
1233 char *point;
1234 int result;
1235
1236 debug_print("Starting shell command execution");
1237
1238 if (bind_shell_command_hook == NULL) {
1239 PyErr_SetString(PyExc_RuntimeError, "No bind_shell_command_hook set");
1240 return 1;
1241 }
1242
1243 cmd_map = _get_associated_cmd_map(rl_get_keymap());
1244 cmd = get_bound_command(cmd_map);
1245 if (!cmd) {
1246 PyErr_SetString(PyExc_RuntimeError, "on_bind_shell_command_hook: Cannot find shell command in keymap");
1247 rl_crlf();
1248 rl_forced_update_display();
1249 return 1;
1250 }
1251
1252 use_ce = rl_get_termcap("ce") != NULL;
1253 clear_current_line(use_ce);
1254
1255 debug_print("Preparing to execute shell command: '%s'", cmd);
1256 debug_print("rl_line_buffer: '%s'", rl_line_buffer);
1257 debug_print("rl_point: '%i'", rl_point);
1258
1259#ifdef WITH_THREAD
1260 gilstate = PyGILState_Ensure();
1261#endif
1262
1263 r = PyObject_CallFunction(bind_shell_command_hook,
1264 "ssi", cmd, rl_line_buffer, rl_point);
1265 if (r == NULL) {
1266 PyErr_Print();
1267 result = 1;
1268 goto cleanup;
1269 }
1270 if (!PyArg_ParseTuple(r, "iss", &cmd_return_code, &line_buffer, &point)) {
1271 PyErr_SetString(PyExc_ValueError, "Expected (int, str, str) tuple from bind_shell_command_hook");
1272 result = 1;
1273 goto cleanup;
1274 }
1275
1276 debug_print("Command return code: %d", cmd_return_code);
1277 debug_print("New line buffer: '%s'", line_buffer);
1278 debug_print("New point: '%s'", point);
1279
1280 // if (save_readline_state() != 1 || restore_readline_state() != 1) {
1281 // PyErr_SetString(PyExc_RuntimeError, "Failed to update readline state");
1282 // result = 1;
1283 // goto cleanup;
1284 // }
1285
1286
1287 /* Redraw the prompt */
1288 if (use_ce) // need to handle a `&& return code != 124` somehow
1289 rl_redraw_prompt_last_line();
1290 else
1291 rl_forced_update_display();
1292
1293 result = 0;
1294 debug_print("Completed shell command execution");
1295
1296cleanup:
1297 Py_XDECREF(r);
1298#ifdef WITH_THREAD
1299 PyGILState_Release(gilstate);
1300#endif
1301
1302done:
1303 return result;
1304}
1305
1306
1307// static int
1308// on_bind_shell_command_hook(int count /* unused */, int key /* unused */) {
1309// char *cmd;
1310// int use_ce;
1311// Keymap cmd_map;
1312// PyObject *r=NULL;
1313
1314// debug_print("Starting shell command execution");
1315
1316// if (bind_shell_command_hook == NULL) {
1317// PyErr_SetString(PyExc_RuntimeError, "No bind_shell_command_hook set");
1318// return 1;
1319// }
1320
1321// cmd_map = _get_associated_cmd_map(rl_get_keymap());
1322// cmd = get_bound_command(cmd_map);
1323// if (!cmd)
1324// return 1;
1325
1326// /* Clear the current line */
1327// use_ce = rl_get_termcap("ce") != NULL;
1328// clear_current_line(use_ce);
1329
1330// // /* Save the current readline state */
1331// // if (!save_readline_state())
1332// // return 1;
1333
1334// /* TODO: Actually execute the shell command */
1335// debug_print("Preparing to execute shell command: '%s'", cmd);
1336// debug_print("rl_line_buffer: '%s'", rl_line_buffer);
1337// debug_print("rl_point: '%i'", rl_point);
1338// r = PyObject_CallFunction(bind_shell_command_hook,
1339// "ssi", cmd, rl_line_buffer, rl_point);
1340
1341// if (r == NULL) {
1342// PyErr_Print();
1343// return 1;
1344// }
1345
1346
1347
1348// // /* Restore readline state */
1349// // if (!restore_readline_state())
1350// // return 1;
1351
1352// Py_XDECREF(r); r=NULL;
1353
1354// /* Redraw the prompt */
1355// if (use_ce)
1356// rl_redraw_prompt_last_line();
1357// else
1358// rl_forced_update_display();
1359
1360// debug_print("Completed shell command execution");
1361
1362// return 0;
1363// }
1364
1365/* Binds a key sequence to arbitrary shell code, not readline fns */
1366static PyObject*
1367bind_shell_command(PyObject *self, PyObject *args) {
1368 // const char *kseq;
1369 // const char *cmd;
1370 char *kseq;
1371 char *cmd;
1372 Keymap kmap, cmd_xmap;
1373
1374 // if (!PyArg_ParseTuple(args, "ss:bind_shell_command", &kseq, &cmd)) {
1375 // return NULL;
1376 // }
1377 if (!PyArg_ParseTuple(args, "eses:bind_shell_command", "utf-8", &kseq, "utf-8", &cmd)) {
1378 return NULL;
1379 }
1380
1381 kmap = rl_get_keymap();
1382 cmd_xmap = _get_associated_cmd_map(kmap);
1383
1384 printf("Binding %s to: %s.\n", kseq, cmd);
1385
1386 if (rl_generic_bind(ISMACR, kseq, (char *)cmd, cmd_xmap) != 0
1387 || rl_bind_keyseq_in_map (kseq, on_bind_shell_command_hook, kmap) != 0) {
1388 PyErr_Format(PyExc_RuntimeError, "Failed to bind key sequence '%s' to command '%s'", kseq, cmd);
1389 return NULL;
1390 }
1391
1392 Py_RETURN_NONE;
1393}
1394
1395PyDoc_STRVAR(doc_bind_shell_command,
1396"bind_shell_command(key_sequence, command) -> None\n\
1397Bind a key sequence to a shell command in the current keymap.");
1398
1399
1400/* Keymap toggling code */
1401static Keymap orig_keymap = NULL;
1402
1403static PyObject*
1404use_temp_keymap(PyObject *self, PyObject *args)
1405{
1406 char *keymap_name;
1407 Keymap new_keymap;
1408
1409 if (!PyArg_ParseTuple(args, "s:use_temp_keymap", &keymap_name))
1410 return NULL;
1411
1412 new_keymap = rl_get_keymap_by_name(keymap_name);
1413 if (new_keymap == NULL) {
1414 PyErr_Format(PyExc_ValueError, "`%s': unknown keymap name", keymap_name);
1415 return NULL;
1416 }
1417
1418 orig_keymap = rl_get_keymap();
1419 rl_set_keymap(new_keymap);
1420
1421 Py_RETURN_NONE;
1422}
1423
1424PyDoc_STRVAR(doc_use_temp_keymap,
1425"use_temp_keymap(keymap_name) -> None\n\
1426Temporarily switch to named keymap, saving the current one.");
1427
1428static PyObject*
1429restore_orig_keymap(PyObject *self, PyObject *args)
1430{
1431 if (orig_keymap != NULL) {
1432 rl_set_keymap(orig_keymap);
1433 orig_keymap = NULL;
1434 }
1435
1436 Py_RETURN_NONE;
1437}
1438
1439PyDoc_STRVAR(doc_restore_orig_keymap,
1440"restore_orig_keymap() -> None\n\
1441Restore the previously saved keymap if one exists.");
1442
1443/* Table of functions exported by the module */
1444
1445static struct PyMethodDef readline_methods[] = {
1446 {"parse_and_bind", parse_and_bind, METH_VARARGS, doc_parse_and_bind},
1447 {"get_line_buffer", get_line_buffer, METH_NOARGS, doc_get_line_buffer},
1448 {"insert_text", insert_text, METH_VARARGS, doc_insert_text},
1449 {"redisplay", redisplay, METH_NOARGS, doc_redisplay},
1450 {"read_init_file", read_init_file, METH_VARARGS, doc_read_init_file},
1451 {"read_history_file", read_history_file,
1452 METH_VARARGS, doc_read_history_file},
1453 {"write_history_file", write_history_file,
1454 METH_VARARGS, doc_write_history_file},
1455 {"get_history_item", get_history_item,
1456 METH_VARARGS, doc_get_history_item},
1457 {"get_current_history_length", (PyCFunction)get_current_history_length,
1458 METH_NOARGS, doc_get_current_history_length},
1459 {"set_history_length", set_history_length,
1460 METH_VARARGS, set_history_length_doc},
1461 {"get_history_length", get_history_length,
1462 METH_NOARGS, get_history_length_doc},
1463 {"set_completer", set_completer, METH_VARARGS, doc_set_completer},
1464 {"get_completer", get_completer, METH_NOARGS, doc_get_completer},
1465 {"get_completion_type", get_completion_type,
1466 METH_NOARGS, doc_get_completion_type},
1467 {"get_begidx", get_begidx, METH_NOARGS, doc_get_begidx},
1468 {"get_endidx", get_endidx, METH_NOARGS, doc_get_endidx},
1469
1470 {"set_completer_delims", set_completer_delims,
1471 METH_VARARGS, doc_set_completer_delims},
1472 {"add_history", py_add_history, METH_VARARGS, doc_add_history},
1473 {"remove_history_item", py_remove_history, METH_VARARGS, doc_remove_history},
1474 {"replace_history_item", py_replace_history, METH_VARARGS, doc_replace_history},
1475 {"get_completer_delims", get_completer_delims,
1476 METH_NOARGS, doc_get_completer_delims},
1477
1478 {"set_completion_display_matches_hook", set_completion_display_matches_hook,
1479 METH_VARARGS, doc_set_completion_display_matches_hook},
1480 {"set_startup_hook", set_startup_hook,
1481 METH_VARARGS, doc_set_startup_hook},
1482 {"set_pre_input_hook", set_pre_input_hook,
1483 METH_VARARGS, doc_set_pre_input_hook},
1484 {"clear_history", py_clear_history, METH_NOARGS, doc_clear_history},
1485 {"resize_terminal", py_resize_terminal, METH_NOARGS, ""},
1486
1487 /* Functions added to implement the 'bind' builtin in OSH */
1488 {"list_funmap_names", list_funmap_names, METH_NOARGS, doc_list_funmap_names},
1489 {"function_dumper", function_dumper, METH_VARARGS, doc_list_function_dumper},
1490 {"macro_dumper", macro_dumper, METH_VARARGS, doc_list_macro_dumper},
1491 {"variable_dumper", variable_dumper, METH_VARARGS, doc_list_variable_dumper},
1492 {"query_bindings", query_bindings, METH_VARARGS, doc_query_bindings},
1493 {"unbind_rl_function", unbind_rl_function, METH_VARARGS, doc_unbind_rl_function},
1494 {"use_temp_keymap", use_temp_keymap, METH_VARARGS, doc_use_temp_keymap},
1495 {"restore_orig_keymap", restore_orig_keymap, METH_NOARGS, doc_restore_orig_keymap},
1496 {"unbind_shell_cmd", unbind_shell_cmd, METH_VARARGS, doc_unbind_shell_cmd},
1497 {"print_shell_cmd_map", print_shell_cmd_map, METH_NOARGS, doc_print_shell_cmd_map},
1498 {"unbind_keyseq", unbind_keyseq, METH_VARARGS, doc_unbind_keyseq},
1499 {"bind_shell_command", bind_shell_command, METH_VARARGS, doc_bind_shell_command},
1500 {"set_bind_shell_command_hook", set_bind_shell_command_hook,
1501 METH_VARARGS, doc_set_bind_shell_command_hook},
1502 {0, 0}
1503};
1504
1505
1506/* C function to call the Python hooks. */
1507
1508static int
1509on_hook(PyObject *func)
1510{
1511 int result = 0;
1512 if (func != NULL) {
1513 PyObject *r;
1514#ifdef WITH_THREAD
1515 PyGILState_STATE gilstate = PyGILState_Ensure();
1516#endif
1517 r = PyObject_CallFunction(func, NULL);
1518 if (r == NULL)
1519 goto error;
1520 if (r == Py_None)
1521 result = 0;
1522 else {
1523 result = PyInt_AsLong(r);
1524 if (result == -1 && PyErr_Occurred())
1525 goto error;
1526 }
1527 Py_DECREF(r);
1528 goto done;
1529 error:
1530 PyErr_Clear();
1531 Py_XDECREF(r);
1532 done:
1533#ifdef WITH_THREAD
1534 PyGILState_Release(gilstate);
1535#endif
1536 return result;
1537 }
1538 return result;
1539}
1540
1541static int
1542#if defined(_RL_FUNCTION_TYPEDEF)
1543on_startup_hook(void)
1544#else
1545on_startup_hook()
1546#endif
1547{
1548 return on_hook(startup_hook);
1549}
1550
1551#ifdef HAVE_RL_PRE_INPUT_HOOK
1552static int
1553#if defined(_RL_FUNCTION_TYPEDEF)
1554on_pre_input_hook(void)
1555#else
1556on_pre_input_hook()
1557#endif
1558{
1559 return on_hook(pre_input_hook);
1560}
1561#endif
1562
1563
1564/* C function to call the Python completion_display_matches */
1565
1566#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
1567static void
1568on_completion_display_matches_hook(char **matches,
1569 int num_matches, int max_length)
1570{
1571 int i;
1572 PyObject *m=NULL, *s=NULL, *r=NULL;
1573#ifdef WITH_THREAD
1574 PyGILState_STATE gilstate = PyGILState_Ensure();
1575#endif
1576 m = PyList_New(num_matches);
1577 if (m == NULL)
1578 goto error;
1579 for (i = 0; i < num_matches; i++) {
1580 s = PyString_FromString(matches[i+1]);
1581 if (s == NULL)
1582 goto error;
1583 if (PyList_SetItem(m, i, s) == -1)
1584 goto error;
1585 }
1586
1587 r = PyObject_CallFunction(completion_display_matches_hook,
1588 "sOi", matches[0], m, max_length);
1589
1590 Py_DECREF(m); m=NULL;
1591
1592 if (r == NULL ||
1593 (r != Py_None && PyInt_AsLong(r) == -1 && PyErr_Occurred())) {
1594 goto error;
1595 }
1596 Py_XDECREF(r); r=NULL;
1597
1598 if (0) {
1599 error:
1600 PyErr_Clear();
1601 Py_XDECREF(m);
1602 Py_XDECREF(r);
1603 }
1604#ifdef WITH_THREAD
1605 PyGILState_Release(gilstate);
1606#endif
1607}
1608
1609#endif
1610
1611#ifdef HAVE_RL_RESIZE_TERMINAL
1612static volatile sig_atomic_t sigwinch_received;
1613static PyOS_sighandler_t sigwinch_ohandler;
1614
1615static void
1616readline_sigwinch_handler(int signum)
1617{
1618 sigwinch_received = 1;
1619 if (sigwinch_ohandler &&
1620 sigwinch_ohandler != SIG_IGN && sigwinch_ohandler != SIG_DFL)
1621 sigwinch_ohandler(signum);
1622}
1623#endif
1624
1625/* C function to call the Python completer. */
1626
1627static char *
1628on_completion(const char *text, int state)
1629{
1630 char *result = NULL;
1631 if (completer != NULL) {
1632 PyObject *r;
1633#ifdef WITH_THREAD
1634 PyGILState_STATE gilstate = PyGILState_Ensure();
1635#endif
1636 rl_attempted_completion_over = 1;
1637 r = PyObject_CallFunction(completer, "si", text, state);
1638 if (r == NULL)
1639 goto error;
1640 if (r == Py_None) {
1641 result = NULL;
1642 }
1643 else {
1644 char *s = PyString_AsString(r);
1645 if (s == NULL)
1646 goto error;
1647 result = strdup(s);
1648 }
1649 Py_DECREF(r);
1650 goto done;
1651 error:
1652 PyErr_Clear();
1653 Py_XDECREF(r);
1654 done:
1655#ifdef WITH_THREAD
1656 PyGILState_Release(gilstate);
1657#endif
1658 return result;
1659 }
1660 return result;
1661}
1662
1663
1664/* A more flexible constructor that saves the "begidx" and "endidx"
1665 * before calling the normal completer */
1666
1667static char **
1668flex_complete(const char *text, int start, int end)
1669{
1670#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1671 rl_completion_append_character ='\0';
1672#endif
1673#ifdef HAVE_RL_COMPLETION_SUPPRESS_APPEND
1674 rl_completion_suppress_append = 0;
1675#endif
1676 Py_XDECREF(begidx);
1677 Py_XDECREF(endidx);
1678 begidx = PyInt_FromLong((long) start);
1679 endidx = PyInt_FromLong((long) end);
1680 return completion_matches(text, *on_completion);
1681}
1682
1683
1684/* Helper to initialize GNU readline properly. */
1685
1686static void
1687setup_readline(void)
1688{
1689#ifdef SAVE_LOCALE
1690 char *saved_locale = strdup(setlocale(LC_CTYPE, NULL));
1691 if (!saved_locale)
1692 Py_FatalError("not enough memory to save locale");
1693#endif
1694
1695#ifdef __APPLE__
1696 /* the libedit readline emulation resets key bindings etc
1697 * when calling rl_initialize. So call it upfront
1698 */
1699 if (using_libedit_emulation)
1700 rl_initialize();
1701
1702 /* Detect if libedit's readline emulation uses 0-based
1703 * indexing or 1-based indexing.
1704 */
1705 add_history("1");
1706 if (history_get(1) == NULL) {
1707 libedit_history_start = 0;
1708 } else {
1709 libedit_history_start = 1;
1710 }
1711 clear_history();
1712#endif /* __APPLE__ */
1713
1714 using_history();
1715
1716 rl_readline_name = "oils";
1717#if defined(PYOS_OS2) && defined(PYCC_GCC)
1718 /* Allow $if term= in .inputrc to work */
1719 rl_terminal_name = getenv("TERM");
1720#endif
1721 /* Force rebind of TAB to insert-tab */
1722 rl_bind_key('\t', rl_insert);
1723 /* Bind both ESC-TAB and ESC-ESC to the completion function */
1724 rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
1725 rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
1726#ifdef HAVE_RL_RESIZE_TERMINAL
1727 /* Set up signal handler for window resize */
1728 sigwinch_ohandler = PyOS_setsig(SIGWINCH, readline_sigwinch_handler);
1729#endif
1730 /* Set our hook functions */
1731 rl_startup_hook = on_startup_hook;
1732#ifdef HAVE_RL_PRE_INPUT_HOOK
1733 rl_pre_input_hook = on_pre_input_hook;
1734#endif
1735 /* Set our completion function */
1736 rl_attempted_completion_function = flex_complete;
1737 /* Set Python word break characters */
1738 completer_word_break_characters =
1739 rl_completer_word_break_characters =
1740 strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?");
1741 /* All nonalphanums except '.' */
1742
1743 begidx = PyInt_FromLong(0L);
1744 endidx = PyInt_FromLong(0L);
1745
1746#ifdef __APPLE__
1747 if (!using_libedit_emulation)
1748#endif
1749 {
1750 if (!isatty(STDOUT_FILENO)) {
1751 /* Issue #19884: stdout is not a terminal. Disable meta modifier
1752 keys to not write the ANSI sequence "\033[1034h" into stdout. On
1753 terminals supporting 8 bit characters like TERM=xterm-256color
1754 (which is now the default Fedora since Fedora 18), the meta key is
1755 used to enable support of 8 bit characters (ANSI sequence
1756 "\033[1034h").
1757
1758 With libedit, this call makes readline() crash. */
1759 rl_variable_bind ("enable-meta-key", "off");
1760 }
1761 }
1762
1763 /* Initialize (allows .inputrc to override)
1764 *
1765 * XXX: A bug in the readline-2.2 library causes a memory leak
1766 * inside this function. Nothing we can do about it.
1767 */
1768#ifdef __APPLE__
1769 if (using_libedit_emulation)
1770 rl_read_init_file(NULL);
1771 else
1772#endif /* __APPLE__ */
1773 rl_initialize();
1774
1775 RESTORE_LOCALE(saved_locale)
1776}
1777
1778/* Wrapper around GNU readline that handles signals differently. */
1779
1780
1781#if defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT)
1782
1783static char *completed_input_string;
1784static void
1785rlhandler(char *text)
1786{
1787 completed_input_string = text;
1788 rl_callback_handler_remove();
1789}
1790
1791static char *
1792readline_until_enter_or_signal(char *prompt, int *signal)
1793{
1794 char * not_done_reading = "";
1795 fd_set selectset;
1796
1797 *signal = 0;
1798#ifdef HAVE_RL_CATCH_SIGNAL
1799 rl_catch_signals = 0;
1800#endif
1801 /* OVM_MAIN: Oil is handling SIGWINCH, so readline shouldn't handle it.
1802 * Without this line, strace reveals that GNU readline is constantly
1803 * turning it on and off.
1804 * */
1805 rl_catch_sigwinch = 0;
1806
1807 rl_callback_handler_install (prompt, rlhandler);
1808 FD_ZERO(&selectset);
1809
1810 completed_input_string = not_done_reading;
1811
1812 while (completed_input_string == not_done_reading) {
1813 int has_input = 0;
1814
1815 while (!has_input)
1816 { struct timeval timeout = {0, 100000}; /* 0.1 seconds */
1817
1818 /* [Bug #1552726] Only limit the pause if an input hook has been
1819 defined. */
1820 struct timeval *timeoutp = NULL;
1821 if (PyOS_InputHook)
1822 timeoutp = &timeout;
1823#ifdef HAVE_RL_RESIZE_TERMINAL
1824 /* Update readline's view of the window size after SIGWINCH */
1825 if (sigwinch_received) {
1826 sigwinch_received = 0;
1827 rl_resize_terminal();
1828 }
1829#endif
1830 FD_SET(fileno(rl_instream), &selectset);
1831 /* select resets selectset if no input was available */
1832 has_input = select(fileno(rl_instream) + 1, &selectset,
1833 NULL, NULL, timeoutp);
1834 if(PyOS_InputHook) PyOS_InputHook();
1835 }
1836
1837 if(has_input > 0) {
1838 rl_callback_read_char();
1839 }
1840 else if (errno == EINTR) {
1841 int s;
1842#ifdef WITH_THREAD
1843 PyEval_RestoreThread(_PyOS_ReadlineTState);
1844#endif
1845 s = PyErr_CheckSignals();
1846#ifdef WITH_THREAD
1847 PyEval_SaveThread();
1848#endif
1849 if (s < 0) {
1850 rl_free_line_state();
1851#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0700
1852 rl_callback_sigcleanup();
1853#endif
1854 rl_cleanup_after_signal();
1855 rl_callback_handler_remove();
1856 *signal = 1;
1857 completed_input_string = NULL;
1858 }
1859 }
1860 }
1861
1862 return completed_input_string;
1863}
1864
1865
1866#else
1867
1868/* Interrupt handler */
1869
1870static jmp_buf jbuf;
1871
1872/* ARGSUSED */
1873static void
1874onintr(int sig)
1875{
1876 longjmp(jbuf, 1);
1877}
1878
1879
1880static char *
1881readline_until_enter_or_signal(char *prompt, int *signal)
1882{
1883 PyOS_sighandler_t old_inthandler;
1884 char *p;
1885
1886 *signal = 0;
1887
1888 old_inthandler = PyOS_setsig(SIGINT, onintr);
1889 if (setjmp(jbuf)) {
1890#ifdef HAVE_SIGRELSE
1891 /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */
1892 sigrelse(SIGINT);
1893#endif
1894 PyOS_setsig(SIGINT, old_inthandler);
1895 *signal = 1;
1896 return NULL;
1897 }
1898 rl_event_hook = PyOS_InputHook;
1899 p = readline(prompt);
1900 PyOS_setsig(SIGINT, old_inthandler);
1901
1902 return p;
1903}
1904#endif /*defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT) */
1905
1906
1907static char *
1908call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
1909{
1910 size_t n;
1911 char *p, *q;
1912 int signal;
1913
1914#ifdef SAVE_LOCALE
1915 char *saved_locale = strdup(setlocale(LC_CTYPE, NULL));
1916 if (!saved_locale)
1917 Py_FatalError("not enough memory to save locale");
1918 setlocale(LC_CTYPE, "");
1919#endif
1920
1921 if (sys_stdin != rl_instream || sys_stdout != rl_outstream) {
1922 rl_instream = sys_stdin;
1923 rl_outstream = sys_stdout;
1924#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1925 rl_prep_terminal (1);
1926#endif
1927 }
1928
1929 p = readline_until_enter_or_signal(prompt, &signal);
1930
1931 /* we got an interrupt signal */
1932 if (signal) {
1933 RESTORE_LOCALE(saved_locale)
1934 return NULL;
1935 }
1936
1937 /* We got an EOF, return an empty string. */
1938 if (p == NULL) {
1939 p = PyMem_Malloc(1);
1940 if (p != NULL)
1941 *p = '\0';
1942 RESTORE_LOCALE(saved_locale)
1943 return p;
1944 }
1945
1946 /* we have a valid line */
1947 n = strlen(p);
1948 /* Copy the malloc'ed buffer into a PyMem_Malloc'ed one and
1949 release the original. */
1950 q = p;
1951 p = PyMem_Malloc(n+2);
1952 if (p != NULL) {
1953 strncpy(p, q, n);
1954 p[n] = '\n';
1955 p[n+1] = '\0';
1956 }
1957 free(q);
1958 RESTORE_LOCALE(saved_locale)
1959 return p;
1960}
1961
1962
1963/* Initialize the module */
1964
1965PyDoc_STRVAR(doc_module,
1966"Importing this module enables command line editing using GNU readline.");
1967
1968#ifdef __APPLE__
1969PyDoc_STRVAR(doc_module_le,
1970"Importing this module enables command line editing using libedit readline.");
1971#endif /* __APPLE__ */
1972
1973PyMODINIT_FUNC
1974initline_input(void)
1975{
1976 PyObject *m;
1977
1978#ifdef __APPLE__
1979 if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
1980 using_libedit_emulation = 1;
1981 }
1982
1983 if (using_libedit_emulation)
1984 m = Py_InitModule4("line_input", readline_methods, doc_module_le,
1985 (PyObject *)NULL, PYTHON_API_VERSION);
1986 else
1987
1988#endif /* __APPLE__ */
1989
1990 m = Py_InitModule4("line_input", readline_methods, doc_module,
1991 (PyObject *)NULL, PYTHON_API_VERSION);
1992 if (m == NULL)
1993 return;
1994
1995 PyOS_ReadlineFunctionPointer = call_readline;
1996 setup_readline();
1997
1998 PyModule_AddIntConstant(m, "_READLINE_VERSION", RL_READLINE_VERSION);
1999 PyModule_AddIntConstant(m, "_READLINE_RUNTIME_VERSION", rl_readline_version);
2000}