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

2004 lines, 1148 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
1445#ifdef OVM_MAIN
1446#include "pyext/line_input.c/readline_methods.def"
1447#else
1448static struct PyMethodDef readline_methods[] = {
1449 {"parse_and_bind", parse_and_bind, METH_VARARGS, doc_parse_and_bind},
1450 {"get_line_buffer", get_line_buffer, METH_NOARGS, doc_get_line_buffer},
1451 {"insert_text", insert_text, METH_VARARGS, doc_insert_text},
1452 {"redisplay", redisplay, METH_NOARGS, doc_redisplay},
1453 {"read_init_file", read_init_file, METH_VARARGS, doc_read_init_file},
1454 {"read_history_file", read_history_file,
1455 METH_VARARGS, doc_read_history_file},
1456 {"write_history_file", write_history_file,
1457 METH_VARARGS, doc_write_history_file},
1458 {"get_history_item", get_history_item,
1459 METH_VARARGS, doc_get_history_item},
1460 {"get_current_history_length", (PyCFunction)get_current_history_length,
1461 METH_NOARGS, doc_get_current_history_length},
1462 {"set_history_length", set_history_length,
1463 METH_VARARGS, set_history_length_doc},
1464 {"get_history_length", get_history_length,
1465 METH_NOARGS, get_history_length_doc},
1466 {"set_completer", set_completer, METH_VARARGS, doc_set_completer},
1467 {"get_completer", get_completer, METH_NOARGS, doc_get_completer},
1468 {"get_completion_type", get_completion_type,
1469 METH_NOARGS, doc_get_completion_type},
1470 {"get_begidx", get_begidx, METH_NOARGS, doc_get_begidx},
1471 {"get_endidx", get_endidx, METH_NOARGS, doc_get_endidx},
1472
1473 {"set_completer_delims", set_completer_delims,
1474 METH_VARARGS, doc_set_completer_delims},
1475 {"add_history", py_add_history, METH_VARARGS, doc_add_history},
1476 {"remove_history_item", py_remove_history, METH_VARARGS, doc_remove_history},
1477 {"replace_history_item", py_replace_history, METH_VARARGS, doc_replace_history},
1478 {"get_completer_delims", get_completer_delims,
1479 METH_NOARGS, doc_get_completer_delims},
1480
1481 {"set_completion_display_matches_hook", set_completion_display_matches_hook,
1482 METH_VARARGS, doc_set_completion_display_matches_hook},
1483 {"set_startup_hook", set_startup_hook,
1484 METH_VARARGS, doc_set_startup_hook},
1485 {"set_pre_input_hook", set_pre_input_hook,
1486 METH_VARARGS, doc_set_pre_input_hook},
1487 {"clear_history", py_clear_history, METH_NOARGS, doc_clear_history},
1488 {"resize_terminal", py_resize_terminal, METH_NOARGS, ""},
1489
1490 /* Functions added to implement the 'bind' builtin in OSH */
1491 {"list_funmap_names", list_funmap_names, METH_NOARGS, doc_list_funmap_names},
1492 {"function_dumper", function_dumper, METH_VARARGS, doc_list_function_dumper},
1493 {"macro_dumper", macro_dumper, METH_VARARGS, doc_list_macro_dumper},
1494 {"variable_dumper", variable_dumper, METH_VARARGS, doc_list_variable_dumper},
1495 {"query_bindings", query_bindings, METH_VARARGS, doc_query_bindings},
1496 {"unbind_rl_function", unbind_rl_function, METH_VARARGS, doc_unbind_rl_function},
1497 {"use_temp_keymap", use_temp_keymap, METH_VARARGS, doc_use_temp_keymap},
1498 {"restore_orig_keymap", restore_orig_keymap, METH_NOARGS, doc_restore_orig_keymap},
1499 {"unbind_shell_cmd", unbind_shell_cmd, METH_VARARGS, doc_unbind_shell_cmd},
1500 {"print_shell_cmd_map", print_shell_cmd_map, METH_NOARGS, doc_print_shell_cmd_map},
1501 {"unbind_keyseq", unbind_keyseq, METH_VARARGS, doc_unbind_keyseq},
1502 {"bind_shell_command", bind_shell_command, METH_VARARGS, doc_bind_shell_command},
1503 {"set_bind_shell_command_hook", set_bind_shell_command_hook,
1504 METH_VARARGS, doc_set_bind_shell_command_hook},
1505 {0, 0}
1506};
1507#endif
1508
1509
1510/* C function to call the Python hooks. */
1511
1512static int
1513on_hook(PyObject *func)
1514{
1515 int result = 0;
1516 if (func != NULL) {
1517 PyObject *r;
1518#ifdef WITH_THREAD
1519 PyGILState_STATE gilstate = PyGILState_Ensure();
1520#endif
1521 r = PyObject_CallFunction(func, NULL);
1522 if (r == NULL)
1523 goto error;
1524 if (r == Py_None)
1525 result = 0;
1526 else {
1527 result = PyInt_AsLong(r);
1528 if (result == -1 && PyErr_Occurred())
1529 goto error;
1530 }
1531 Py_DECREF(r);
1532 goto done;
1533 error:
1534 PyErr_Clear();
1535 Py_XDECREF(r);
1536 done:
1537#ifdef WITH_THREAD
1538 PyGILState_Release(gilstate);
1539#endif
1540 return result;
1541 }
1542 return result;
1543}
1544
1545static int
1546#if defined(_RL_FUNCTION_TYPEDEF)
1547on_startup_hook(void)
1548#else
1549on_startup_hook()
1550#endif
1551{
1552 return on_hook(startup_hook);
1553}
1554
1555#ifdef HAVE_RL_PRE_INPUT_HOOK
1556static int
1557#if defined(_RL_FUNCTION_TYPEDEF)
1558on_pre_input_hook(void)
1559#else
1560on_pre_input_hook()
1561#endif
1562{
1563 return on_hook(pre_input_hook);
1564}
1565#endif
1566
1567
1568/* C function to call the Python completion_display_matches */
1569
1570#ifdef HAVE_RL_COMPLETION_DISPLAY_MATCHES_HOOK
1571static void
1572on_completion_display_matches_hook(char **matches,
1573 int num_matches, int max_length)
1574{
1575 int i;
1576 PyObject *m=NULL, *s=NULL, *r=NULL;
1577#ifdef WITH_THREAD
1578 PyGILState_STATE gilstate = PyGILState_Ensure();
1579#endif
1580 m = PyList_New(num_matches);
1581 if (m == NULL)
1582 goto error;
1583 for (i = 0; i < num_matches; i++) {
1584 s = PyString_FromString(matches[i+1]);
1585 if (s == NULL)
1586 goto error;
1587 if (PyList_SetItem(m, i, s) == -1)
1588 goto error;
1589 }
1590
1591 r = PyObject_CallFunction(completion_display_matches_hook,
1592 "sOi", matches[0], m, max_length);
1593
1594 Py_DECREF(m); m=NULL;
1595
1596 if (r == NULL ||
1597 (r != Py_None && PyInt_AsLong(r) == -1 && PyErr_Occurred())) {
1598 goto error;
1599 }
1600 Py_XDECREF(r); r=NULL;
1601
1602 if (0) {
1603 error:
1604 PyErr_Clear();
1605 Py_XDECREF(m);
1606 Py_XDECREF(r);
1607 }
1608#ifdef WITH_THREAD
1609 PyGILState_Release(gilstate);
1610#endif
1611}
1612
1613#endif
1614
1615#ifdef HAVE_RL_RESIZE_TERMINAL
1616static volatile sig_atomic_t sigwinch_received;
1617static PyOS_sighandler_t sigwinch_ohandler;
1618
1619static void
1620readline_sigwinch_handler(int signum)
1621{
1622 sigwinch_received = 1;
1623 if (sigwinch_ohandler &&
1624 sigwinch_ohandler != SIG_IGN && sigwinch_ohandler != SIG_DFL)
1625 sigwinch_ohandler(signum);
1626}
1627#endif
1628
1629/* C function to call the Python completer. */
1630
1631static char *
1632on_completion(const char *text, int state)
1633{
1634 char *result = NULL;
1635 if (completer != NULL) {
1636 PyObject *r;
1637#ifdef WITH_THREAD
1638 PyGILState_STATE gilstate = PyGILState_Ensure();
1639#endif
1640 rl_attempted_completion_over = 1;
1641 r = PyObject_CallFunction(completer, "si", text, state);
1642 if (r == NULL)
1643 goto error;
1644 if (r == Py_None) {
1645 result = NULL;
1646 }
1647 else {
1648 char *s = PyString_AsString(r);
1649 if (s == NULL)
1650 goto error;
1651 result = strdup(s);
1652 }
1653 Py_DECREF(r);
1654 goto done;
1655 error:
1656 PyErr_Clear();
1657 Py_XDECREF(r);
1658 done:
1659#ifdef WITH_THREAD
1660 PyGILState_Release(gilstate);
1661#endif
1662 return result;
1663 }
1664 return result;
1665}
1666
1667
1668/* A more flexible constructor that saves the "begidx" and "endidx"
1669 * before calling the normal completer */
1670
1671static char **
1672flex_complete(const char *text, int start, int end)
1673{
1674#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1675 rl_completion_append_character ='\0';
1676#endif
1677#ifdef HAVE_RL_COMPLETION_SUPPRESS_APPEND
1678 rl_completion_suppress_append = 0;
1679#endif
1680 Py_XDECREF(begidx);
1681 Py_XDECREF(endidx);
1682 begidx = PyInt_FromLong((long) start);
1683 endidx = PyInt_FromLong((long) end);
1684 return completion_matches(text, *on_completion);
1685}
1686
1687
1688/* Helper to initialize GNU readline properly. */
1689
1690static void
1691setup_readline(void)
1692{
1693#ifdef SAVE_LOCALE
1694 char *saved_locale = strdup(setlocale(LC_CTYPE, NULL));
1695 if (!saved_locale)
1696 Py_FatalError("not enough memory to save locale");
1697#endif
1698
1699#ifdef __APPLE__
1700 /* the libedit readline emulation resets key bindings etc
1701 * when calling rl_initialize. So call it upfront
1702 */
1703 if (using_libedit_emulation)
1704 rl_initialize();
1705
1706 /* Detect if libedit's readline emulation uses 0-based
1707 * indexing or 1-based indexing.
1708 */
1709 add_history("1");
1710 if (history_get(1) == NULL) {
1711 libedit_history_start = 0;
1712 } else {
1713 libedit_history_start = 1;
1714 }
1715 clear_history();
1716#endif /* __APPLE__ */
1717
1718 using_history();
1719
1720 rl_readline_name = "oils";
1721#if defined(PYOS_OS2) && defined(PYCC_GCC)
1722 /* Allow $if term= in .inputrc to work */
1723 rl_terminal_name = getenv("TERM");
1724#endif
1725 /* Force rebind of TAB to insert-tab */
1726 rl_bind_key('\t', rl_insert);
1727 /* Bind both ESC-TAB and ESC-ESC to the completion function */
1728 rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
1729 rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
1730#ifdef HAVE_RL_RESIZE_TERMINAL
1731 /* Set up signal handler for window resize */
1732 sigwinch_ohandler = PyOS_setsig(SIGWINCH, readline_sigwinch_handler);
1733#endif
1734 /* Set our hook functions */
1735 rl_startup_hook = on_startup_hook;
1736#ifdef HAVE_RL_PRE_INPUT_HOOK
1737 rl_pre_input_hook = on_pre_input_hook;
1738#endif
1739 /* Set our completion function */
1740 rl_attempted_completion_function = flex_complete;
1741 /* Set Python word break characters */
1742 completer_word_break_characters =
1743 rl_completer_word_break_characters =
1744 strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?");
1745 /* All nonalphanums except '.' */
1746
1747 begidx = PyInt_FromLong(0L);
1748 endidx = PyInt_FromLong(0L);
1749
1750#ifdef __APPLE__
1751 if (!using_libedit_emulation)
1752#endif
1753 {
1754 if (!isatty(STDOUT_FILENO)) {
1755 /* Issue #19884: stdout is not a terminal. Disable meta modifier
1756 keys to not write the ANSI sequence "\033[1034h" into stdout. On
1757 terminals supporting 8 bit characters like TERM=xterm-256color
1758 (which is now the default Fedora since Fedora 18), the meta key is
1759 used to enable support of 8 bit characters (ANSI sequence
1760 "\033[1034h").
1761
1762 With libedit, this call makes readline() crash. */
1763 rl_variable_bind ("enable-meta-key", "off");
1764 }
1765 }
1766
1767 /* Initialize (allows .inputrc to override)
1768 *
1769 * XXX: A bug in the readline-2.2 library causes a memory leak
1770 * inside this function. Nothing we can do about it.
1771 */
1772#ifdef __APPLE__
1773 if (using_libedit_emulation)
1774 rl_read_init_file(NULL);
1775 else
1776#endif /* __APPLE__ */
1777 rl_initialize();
1778
1779 RESTORE_LOCALE(saved_locale)
1780}
1781
1782/* Wrapper around GNU readline that handles signals differently. */
1783
1784
1785#if defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT)
1786
1787static char *completed_input_string;
1788static void
1789rlhandler(char *text)
1790{
1791 completed_input_string = text;
1792 rl_callback_handler_remove();
1793}
1794
1795static char *
1796readline_until_enter_or_signal(char *prompt, int *signal)
1797{
1798 char * not_done_reading = "";
1799 fd_set selectset;
1800
1801 *signal = 0;
1802#ifdef HAVE_RL_CATCH_SIGNAL
1803 rl_catch_signals = 0;
1804#endif
1805 /* OVM_MAIN: Oil is handling SIGWINCH, so readline shouldn't handle it.
1806 * Without this line, strace reveals that GNU readline is constantly
1807 * turning it on and off.
1808 * */
1809 rl_catch_sigwinch = 0;
1810
1811 rl_callback_handler_install (prompt, rlhandler);
1812 FD_ZERO(&selectset);
1813
1814 completed_input_string = not_done_reading;
1815
1816 while (completed_input_string == not_done_reading) {
1817 int has_input = 0;
1818
1819 while (!has_input)
1820 { struct timeval timeout = {0, 100000}; /* 0.1 seconds */
1821
1822 /* [Bug #1552726] Only limit the pause if an input hook has been
1823 defined. */
1824 struct timeval *timeoutp = NULL;
1825 if (PyOS_InputHook)
1826 timeoutp = &timeout;
1827#ifdef HAVE_RL_RESIZE_TERMINAL
1828 /* Update readline's view of the window size after SIGWINCH */
1829 if (sigwinch_received) {
1830 sigwinch_received = 0;
1831 rl_resize_terminal();
1832 }
1833#endif
1834 FD_SET(fileno(rl_instream), &selectset);
1835 /* select resets selectset if no input was available */
1836 has_input = select(fileno(rl_instream) + 1, &selectset,
1837 NULL, NULL, timeoutp);
1838 if(PyOS_InputHook) PyOS_InputHook();
1839 }
1840
1841 if(has_input > 0) {
1842 rl_callback_read_char();
1843 }
1844 else if (errno == EINTR) {
1845 int s;
1846#ifdef WITH_THREAD
1847 PyEval_RestoreThread(_PyOS_ReadlineTState);
1848#endif
1849 s = PyErr_CheckSignals();
1850#ifdef WITH_THREAD
1851 PyEval_SaveThread();
1852#endif
1853 if (s < 0) {
1854 rl_free_line_state();
1855#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0700
1856 rl_callback_sigcleanup();
1857#endif
1858 rl_cleanup_after_signal();
1859 rl_callback_handler_remove();
1860 *signal = 1;
1861 completed_input_string = NULL;
1862 }
1863 }
1864 }
1865
1866 return completed_input_string;
1867}
1868
1869
1870#else
1871
1872/* Interrupt handler */
1873
1874static jmp_buf jbuf;
1875
1876/* ARGSUSED */
1877static void
1878onintr(int sig)
1879{
1880 longjmp(jbuf, 1);
1881}
1882
1883
1884static char *
1885readline_until_enter_or_signal(char *prompt, int *signal)
1886{
1887 PyOS_sighandler_t old_inthandler;
1888 char *p;
1889
1890 *signal = 0;
1891
1892 old_inthandler = PyOS_setsig(SIGINT, onintr);
1893 if (setjmp(jbuf)) {
1894#ifdef HAVE_SIGRELSE
1895 /* This seems necessary on SunOS 4.1 (Rasmus Hahn) */
1896 sigrelse(SIGINT);
1897#endif
1898 PyOS_setsig(SIGINT, old_inthandler);
1899 *signal = 1;
1900 return NULL;
1901 }
1902 rl_event_hook = PyOS_InputHook;
1903 p = readline(prompt);
1904 PyOS_setsig(SIGINT, old_inthandler);
1905
1906 return p;
1907}
1908#endif /*defined(HAVE_RL_CALLBACK) && defined(HAVE_SELECT) */
1909
1910
1911static char *
1912call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
1913{
1914 size_t n;
1915 char *p, *q;
1916 int signal;
1917
1918#ifdef SAVE_LOCALE
1919 char *saved_locale = strdup(setlocale(LC_CTYPE, NULL));
1920 if (!saved_locale)
1921 Py_FatalError("not enough memory to save locale");
1922 setlocale(LC_CTYPE, "");
1923#endif
1924
1925 if (sys_stdin != rl_instream || sys_stdout != rl_outstream) {
1926 rl_instream = sys_stdin;
1927 rl_outstream = sys_stdout;
1928#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1929 rl_prep_terminal (1);
1930#endif
1931 }
1932
1933 p = readline_until_enter_or_signal(prompt, &signal);
1934
1935 /* we got an interrupt signal */
1936 if (signal) {
1937 RESTORE_LOCALE(saved_locale)
1938 return NULL;
1939 }
1940
1941 /* We got an EOF, return an empty string. */
1942 if (p == NULL) {
1943 p = PyMem_Malloc(1);
1944 if (p != NULL)
1945 *p = '\0';
1946 RESTORE_LOCALE(saved_locale)
1947 return p;
1948 }
1949
1950 /* we have a valid line */
1951 n = strlen(p);
1952 /* Copy the malloc'ed buffer into a PyMem_Malloc'ed one and
1953 release the original. */
1954 q = p;
1955 p = PyMem_Malloc(n+2);
1956 if (p != NULL) {
1957 strncpy(p, q, n);
1958 p[n] = '\n';
1959 p[n+1] = '\0';
1960 }
1961 free(q);
1962 RESTORE_LOCALE(saved_locale)
1963 return p;
1964}
1965
1966
1967/* Initialize the module */
1968
1969PyDoc_STRVAR(doc_module,
1970"Importing this module enables command line editing using GNU readline.");
1971
1972#ifdef __APPLE__
1973PyDoc_STRVAR(doc_module_le,
1974"Importing this module enables command line editing using libedit readline.");
1975#endif /* __APPLE__ */
1976
1977PyMODINIT_FUNC
1978initline_input(void)
1979{
1980 PyObject *m;
1981
1982#ifdef __APPLE__
1983 if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
1984 using_libedit_emulation = 1;
1985 }
1986
1987 if (using_libedit_emulation)
1988 m = Py_InitModule4("line_input", readline_methods, doc_module_le,
1989 (PyObject *)NULL, PYTHON_API_VERSION);
1990 else
1991
1992#endif /* __APPLE__ */
1993
1994 m = Py_InitModule4("line_input", readline_methods, doc_module,
1995 (PyObject *)NULL, PYTHON_API_VERSION);
1996 if (m == NULL)
1997 return;
1998
1999 PyOS_ReadlineFunctionPointer = call_readline;
2000 setup_readline();
2001
2002 PyModule_AddIntConstant(m, "_READLINE_VERSION", RL_READLINE_VERSION);
2003 PyModule_AddIntConstant(m, "_READLINE_RUNTIME_VERSION", rl_readline_version);
2004}