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

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