19 #include RUBY_EXTCONF_H
22 #include "ruby/config.h"
26 #ifdef HAVE_READLINE_READLINE_H
27 #include <readline/readline.h>
29 #ifdef HAVE_READLINE_HISTORY_H
30 #include <readline/history.h>
32 #ifdef HAVE_EDITLINE_READLINE_H
33 #include <editline/readline.h>
43 #ifdef HAVE_SYS_STAT_H
47 static VALUE mReadline;
49 #define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper"
50 #ifndef USE_INSERT_IGNORE_ESCAPE
51 # if !defined(HAVE_EDITLINE_READLINE_H) && defined(RL_PROMPT_START_IGNORE) && defined(RL_PROMPT_END_IGNORE)
52 # define USE_INSERT_IGNORE_ESCAPE 1
54 # define USE_INSERT_IGNORE_ESCAPE 0
58 #define COMPLETION_PROC "completion_proc"
59 #define COMPLETION_CASE_FOLD "completion_case_fold"
60 static ID id_call, completion_proc, completion_case_fold;
61 #if defined HAVE_RL_CHAR_IS_QUOTED_P
62 #define QUOTING_DETECTION_PROC "quoting_detection_proc"
63 static ID quoting_detection_proc;
65 #if USE_INSERT_IGNORE_ESCAPE
66 static ID id_orig_prompt, id_last_prompt;
68 #if defined(HAVE_RL_PRE_INPUT_HOOK)
69 static ID id_pre_input_hook;
71 #if defined(HAVE_RL_SPECIAL_PREFIXES)
72 static ID id_special_prefixes;
75 #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
76 # define rl_filename_completion_function filename_completion_function
78 #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
79 # define rl_username_completion_function username_completion_function
83 #ifndef HAVE_RL_COMPLETION_MATCHES
84 # define rl_completion_matches completion_matches
87 static int (*history_get_offset_func)(
int);
88 static int (*history_replace_offset_func)(
int);
89 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
90 static int readline_completion_append_character;
93 static char **readline_attempted_completion_function(
const char *text,
96 #define OutputStringValue(str) do {\
97 StringValueCStr(str);\
98 (str) = rb_str_conv_enc((str), rb_enc_get(str), rb_locale_encoding());\
135 static VALUE readline_instream;
136 static VALUE readline_outstream;
137 static FILE *readline_rl_instream;
138 static FILE *readline_rl_outstream;
141 mustbe_callable(
VALUE proc)
147 #if defined HAVE_RL_GETC_FUNCTION
150 #define rl_getc(f) EOF
161 getc_body(
struct getc_struct *p)
170 static int prior_key =
'0';
173 if (prior_key > 0xff) {
174 prior_key = rl_getc(p->input);
177 h = (HANDLE)_get_osfhandle(p->fd);
178 if (PeekConsoleInput(
h, &ir, 1, &
n)) {
180 if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
181 prior_key = rl_getc(p->input);
184 ReadConsoleInput(
h, &ir, 1, &
n);
196 ss =
read(p->fd, &ch, 1);
203 return (
unsigned char)ch;
207 getc_func(
void *data1)
209 struct getc_struct *p = data1;
211 p->ret = getc_body(p);
219 struct getc_struct data;
228 if (data.ret ==
EOF) {
232 if (data.err ==
EINTR) {
239 rb_bug(
"readline_getc: input closed unexpectedly or memory corrupted");
250 #elif defined HAVE_RL_EVENT_HOOK
253 static int readline_event(
void);
266 #if USE_INSERT_IGNORE_ESCAPE
268 insert_ignore_escape(
VALUE self,
VALUE prompt)
272 const char *s0, *s, *e;
274 static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE};
278 if (orig_prompt == prompt)
return last_prompt;
280 if (
NIL_P(last_prompt)) {
287 while (s < e && *s) {
289 case RL_PROMPT_START_IGNORE:
294 case RL_PROMPT_END_IGNORE:
300 if (++s < e && *s ==
'[') {
303 while (++s < e && *s) {
304 if (
ISALPHA(*(
unsigned char *)s)) {
313 else if (!((
'0' <= *s && *s <=
'9') || *s ==
';')) {
342 readline_get(
VALUE prompt)
344 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
345 readline_completion_append_character = rl_completion_append_character;
347 return (
VALUE)readline((
char *)prompt);
351 clear_rl_instream(
void)
353 if (readline_rl_instream) {
354 fclose(readline_rl_instream);
355 if (rl_instream == readline_rl_instream)
357 readline_rl_instream =
NULL;
359 readline_instream =
Qfalse;
363 clear_rl_outstream(
void)
365 if (readline_rl_outstream) {
366 fclose(readline_rl_outstream);
367 if (rl_outstream == readline_rl_outstream)
369 readline_rl_outstream =
NULL;
371 readline_outstream =
Qfalse;
375 prepare_readline(
void)
377 static int initialized = 0;
383 if (readline_instream) {
392 if (readline_outstream) {
396 clear_rl_outstream();
489 VALUE tmp, add_hist, result;
496 #if USE_INSERT_IGNORE_ESCAPE
497 tmp = insert_ignore_escape(
self, tmp);
509 #if USE_INSERT_IGNORE_ESCAPE
515 #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
517 #if defined HAVE_RL_FREE_LINE_STATE
518 rl_free_line_state();
520 rl_cleanup_after_signal();
521 #elif defined HAVE_RL_DEPREP_TERM_FUNCTION
523 if (rl_deprep_term_function !=
NULL)
524 (*rl_deprep_term_function)();
527 rl_deprep_terminal();
532 if (
RTEST(add_hist) && buff) {
540 if (buff)
free(buff);
570 int save_errno =
errno;
574 rl_instream = readline_rl_instream =
f;
575 readline_instream =
input;
588 readline_s_set_output(
VALUE self,
VALUE output)
595 clear_rl_outstream();
600 clear_rl_outstream();
606 int save_errno =
errno;
610 rl_outstream = readline_rl_outstream =
f;
611 readline_outstream = output;
616 #if defined(HAVE_RL_PRE_INPUT_HOOK)
634 mustbe_callable(proc);
635 return rb_ivar_set(mReadline, id_pre_input_hook, proc);
655 readline_pre_input_hook(
void)
665 #define readline_s_set_pre_input_hook rb_f_notimplement
666 #define readline_s_get_pre_input_hook rb_f_notimplement
669 #if defined(HAVE_RL_INSERT_TEXT)
688 #define readline_s_insert_text rb_f_notimplement
691 #if defined(HAVE_RL_DELETE_TEXT)
692 int rl_delete_text(
int,
int);
694 str_subpos(
const char *
ptr,
const char *end,
long beg,
long *sublen,
rb_encoding *enc)
719 if (rl_line_buffer) {
720 const char *p, *
ptr = rl_line_buffer;
722 const char *end =
ptr +
len;
728 p = str_subpos(
ptr, end, beg, &
len, enc);
732 else if (
argc == 1) {
744 #define readline_s_delete_text rb_f_notimplement
747 #if defined(HAVE_RL_REDISPLAY)
766 #define readline_s_redisplay rb_f_notimplement
838 readline_s_set_completion_proc(
VALUE self,
VALUE proc)
840 mustbe_callable(proc);
841 return rb_ivar_set(mReadline, completion_proc, proc);
851 readline_s_get_completion_proc(
VALUE self)
856 #ifdef HAVE_RL_CHAR_IS_QUOTED_P
881 mustbe_callable(proc);
882 return rb_ivar_set(mReadline, quoting_detection_proc, proc);
894 return rb_attr_get(mReadline, quoting_detection_proc);
897 #define readline_s_set_quoting_detection_proc rb_f_notimplement
898 #define readline_s_get_quoting_detection_proc rb_f_notimplement
908 readline_s_set_completion_case_fold(
VALUE self,
VALUE val)
910 return rb_ivar_set(mReadline, completion_case_fold, val);
928 readline_s_get_completion_case_fold(
VALUE self)
930 return rb_attr_get(mReadline, completion_case_fold);
933 #ifdef HAVE_RL_LINE_BUFFER
950 if (rl_line_buffer ==
NULL)
955 #define readline_s_get_line_buffer rb_f_notimplement
998 #define readline_s_get_point rb_f_notimplement
999 #define readline_s_set_point rb_f_notimplement
1003 readline_attempted_completion_function(
const char *text,
int start,
int end)
1005 VALUE proc, ary, temp;
1015 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1016 rl_completion_append_character = readline_completion_append_character;
1018 #ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
1019 rl_attempted_completion_over = 1;
1026 if (matches == 0)
return NULL;
1027 result = (
char**)
malloc((matches + 2)*
sizeof(
char*));
1031 for (
i = 0;
i < matches;
i++) {
1039 result[matches + 1] =
NULL;
1042 result[0] =
strdup(result[1]);
1045 const char *result1 = result[1];
1046 long low =
strlen(result1);
1048 for (
i = 1;
i < matches; ++
i) {
1049 register int c1, c2;
1052 const char *p2 = result[
i + 1];
1055 for (i1 = i2 = 0; i1 < low && i2 < l2; i1 += n1, i2 += n2) {
1059 c1 = rb_tolower(c1);
1060 c2 = rb_tolower(c2);
1062 if (c1 != c2)
break;
1067 result[0] = (
char*)
malloc(low + 1);
1069 strncpy(result[0], result[1], low);
1070 result[0][low] =
'\0';
1076 #ifdef HAVE_RL_CHAR_IS_QUOTED_P
1078 readline_char_is_quoted(
char *text,
int byte_index)
1084 proc =
rb_attr_get(mReadline, quoting_detection_proc);
1090 if (byte_index < 0 ||
len < (
size_t)byte_index) {
1098 return RTEST(result);
1102 #ifdef HAVE_RL_SET_SCREEN_SIZE
1120 #define readline_s_set_screen_size rb_f_notimplement
1123 #ifdef HAVE_RL_GET_SCREEN_SIZE
1140 rl_get_screen_size(&rows, &columns);
1147 #define readline_s_get_screen_size rb_f_notimplement
1150 #ifdef HAVE_RL_VI_EDITING_MODE
1151 int rl_vi_editing_mode(
int,
int);
1164 rl_vi_editing_mode(1,0);
1168 #define readline_s_vi_editing_mode rb_f_notimplement
1171 #ifdef HAVE_RL_EDITING_MODE
1186 #define readline_s_vi_editing_mode_p rb_f_notimplement
1189 #ifdef HAVE_RL_EMACS_EDITING_MODE
1190 int rl_emacs_editing_mode(
int,
int);
1203 rl_emacs_editing_mode(1,0);
1207 #define readline_s_emacs_editing_mode rb_f_notimplement
1210 #ifdef HAVE_RL_EDITING_MODE
1225 #define readline_s_emacs_editing_mode_p rb_f_notimplement
1228 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1269 rl_completion_append_character =
'\0';
1274 rl_completion_append_character =
'\0';
1282 #define readline_s_set_completion_append_character rb_f_notimplement
1285 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1300 if (rl_completion_append_character ==
'\0')
1303 buf[0] = (
char) rl_completion_append_character;
1307 #define readline_s_get_completion_append_character rb_f_notimplement
1310 #ifdef HAVE_RL_COMPLETION_QUOTE_CHARACTER
1329 if (rl_completion_quote_character ==
'\0')
1332 buf[0] = (
char) rl_completion_quote_character;
1336 #define readline_s_get_completion_quote_character rb_f_notimplement
1339 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
1353 static char *basic_word_break_characters =
NULL;
1356 if (basic_word_break_characters ==
NULL) {
1357 basic_word_break_characters =
1363 strncpy(basic_word_break_characters,
1366 rl_basic_word_break_characters = basic_word_break_characters;
1370 #define readline_s_set_basic_word_break_characters rb_f_notimplement
1373 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
1386 if (rl_basic_word_break_characters ==
NULL)
1391 #define readline_s_get_basic_word_break_characters rb_f_notimplement
1394 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
1408 static char *completer_word_break_characters =
NULL;
1411 if (completer_word_break_characters ==
NULL) {
1412 completer_word_break_characters =
1418 strncpy(completer_word_break_characters,
1421 rl_completer_word_break_characters = completer_word_break_characters;
1425 #define readline_s_set_completer_word_break_characters rb_f_notimplement
1428 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
1441 if (rl_completer_word_break_characters ==
NULL)
1446 #define readline_s_get_completer_word_break_characters rb_f_notimplement
1449 #if defined(HAVE_RL_SPECIAL_PREFIXES)
1474 rl_special_prefixes =
NULL;
1498 if (rl_special_prefixes ==
NULL)
return Qnil;
1507 #define readline_s_set_special_prefixes rb_f_notimplement
1508 #define readline_s_get_special_prefixes rb_f_notimplement
1511 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
1523 static char *basic_quote_characters =
NULL;
1526 if (basic_quote_characters ==
NULL) {
1527 basic_quote_characters =
1533 strncpy(basic_quote_characters,
1536 rl_basic_quote_characters = basic_quote_characters;
1541 #define readline_s_set_basic_quote_characters rb_f_notimplement
1544 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
1556 if (rl_basic_quote_characters ==
NULL)
1561 #define readline_s_get_basic_quote_characters rb_f_notimplement
1564 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
1579 static char *completer_quote_characters =
NULL;
1582 if (completer_quote_characters ==
NULL) {
1583 completer_quote_characters =
1591 rl_completer_quote_characters = completer_quote_characters;
1596 #define readline_s_set_completer_quote_characters rb_f_notimplement
1599 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
1612 if (rl_completer_quote_characters ==
NULL)
1617 #define readline_s_get_completer_quote_characters rb_f_notimplement
1620 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1633 static char *filename_quote_characters =
NULL;
1636 if (filename_quote_characters ==
NULL) {
1637 filename_quote_characters =
1645 rl_filename_quote_characters = filename_quote_characters;
1650 #define readline_s_set_filename_quote_characters rb_f_notimplement
1653 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1666 if (rl_filename_quote_characters ==
NULL)
1671 #define readline_s_get_filename_quote_characters rb_f_notimplement
1674 #ifdef HAVE_RL_REFRESH_LINE
1675 int rl_refresh_line(
int,
int);
1686 rl_refresh_line(0, 0);
1690 #define readline_s_refresh_line rb_f_notimplement
1694 hist_to_s(
VALUE self)
1700 history_get_offset_history_base(
int offset)
1702 return history_base + offset;
1706 history_get_offset_0(
int offset)
1714 HIST_ENTRY *entry =
NULL;
1719 i += history_length;
1722 entry = history_get(history_get_offset_func(
i));
1724 if (entry ==
NULL) {
1730 #ifdef HAVE_REPLACE_HISTORY_ENTRY
1734 HIST_ENTRY *entry =
NULL;
1740 i += history_length;
1745 if (entry ==
NULL) {
1751 #define hist_set rb_f_notimplement
1776 rb_remove_history(
int index)
1778 #ifdef HAVE_REMOVE_HISTORY
1782 entry = remove_history(
index);
1785 free((
void *) entry->line);
1798 hist_pop(
VALUE self)
1800 if (history_length > 0) {
1801 return rb_remove_history(history_length - 1);
1808 hist_shift(
VALUE self)
1810 if (history_length > 0) {
1811 return rb_remove_history(0);
1818 hist_each(
VALUE self)
1825 for (
i = 0;
i < history_length;
i++) {
1826 entry = history_get(history_get_offset_func(
i));
1835 hist_length(
VALUE self)
1837 return INT2NUM(history_length);
1841 hist_empty_p(
VALUE self)
1853 i += history_length;
1854 if (i < 0 || i > history_length - 1) {
1857 return rb_remove_history(
i);
1860 #ifdef HAVE_CLEAR_HISTORY
1868 #define hist_clear rb_f_notimplement
1882 for (
i = 0; matches[
i];
i++) {
1907 for (
i = 0; matches[
i];
i++) {
1921 #ifdef HAVE_RL_CLEAR_SIGNALS
1922 int rl_clear_signals(
void);
1929 VALUE history, fcomp, ucomp, version;
1932 rl_readline_name = (
char *)
"Ruby";
1934 #if defined HAVE_RL_GETC_FUNCTION
1938 rl_getc_function = readline_getc;
1939 #elif defined HAVE_RL_EVENT_HOOK
1940 rl_event_hook = readline_event;
1948 #if defined(HAVE_RL_PRE_INPUT_HOOK)
1949 id_pre_input_hook =
rb_intern(
"pre_input_hook");
1951 #if defined(HAVE_RL_SPECIAL_PREFIXES)
1952 id_special_prefixes =
rb_intern(
"special_prefixes");
1954 #if defined HAVE_RL_CHAR_IS_QUOTED_P
1955 quoting_detection_proc =
rb_intern(QUOTING_DETECTION_PROC);
1960 readline_readline, -1);
1962 readline_s_set_input, 1);
1964 readline_s_set_output, 1);
1966 readline_s_set_completion_proc, 1);
1968 readline_s_get_completion_proc, 0);
1974 readline_s_set_completion_case_fold, 1);
1976 readline_s_get_completion_case_fold, 0);
2038 #if USE_INSERT_IGNORE_ESCAPE
2039 id_orig_prompt =
rb_intern(
"orig_prompt");
2040 id_last_prompt =
rb_intern(
"last_prompt");
2069 filename_completion_proc_call, 1);
2078 username_completion_proc_call, 1);
2084 history_get_offset_func = history_get_offset_history_base;
2085 history_replace_offset_func = history_get_offset_0;
2086 #if defined HAVE_RL_LIBRARY_VERSION
2088 #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY
2092 if (history_get(history_get_offset_func(0)) ==
NULL) {
2093 history_get_offset_func = history_get_offset_0;
2095 #ifdef HAVE_REPLACE_HISTORY_ENTRY
2096 if (replace_history_entry(0,
"a",
NULL) ==
NULL) {
2097 history_replace_offset_func = history_get_offset_history_base;
2100 #ifdef HAVE_CLEAR_HISTORY
2104 HIST_ENTRY *entry = remove_history(0);
2106 free((
char *)entry->line);
2119 rl_attempted_completion_function = readline_attempted_completion_function;
2120 #if defined(HAVE_RL_PRE_INPUT_HOOK)
2121 rl_pre_input_hook = (rl_hook_func_t *)readline_pre_input_hook;
2123 #if defined HAVE_RL_CHAR_IS_QUOTED_P
2124 rl_char_is_quoted_p = &readline_char_is_quoted;
2126 #ifdef HAVE_RL_CATCH_SIGNALS
2127 rl_catch_signals = 0;
2129 #ifdef HAVE_RL_CLEAR_SIGNALS