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>
47static 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"
60static 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"
63static ID quoting_detection_proc;
65#if USE_INSERT_IGNORE_ESCAPE
66static ID id_orig_prompt, id_last_prompt;
68#if defined(HAVE_RL_PRE_INPUT_HOOK)
69static ID id_pre_input_hook;
71#if defined(HAVE_RL_SPECIAL_PREFIXES)
72static 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
87static int (*history_get_offset_func)(
int);
88static int (*history_replace_offset_func)(
int);
89#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
90static int readline_completion_append_character;
93static 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());\
135static VALUE readline_instream;
136static VALUE readline_outstream;
137static FILE *readline_rl_instream;
138static FILE *readline_rl_outstream;
141mustbe_callable(
VALUE proc)
147#if defined HAVE_RL_GETC_FUNCTION
150#define rl_getc(f) EOF
161getc_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;
207getc_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
253static int readline_event(
void);
266#if USE_INSERT_IGNORE_ESCAPE
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 ==
';')) {
342readline_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);
351clear_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;
363clear_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;
375prepare_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;
588readline_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);
655readline_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)
692int rl_delete_text(
int,
int);
694str_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
838readline_s_set_completion_proc(
VALUE self,
VALUE proc)
840 mustbe_callable(proc);
841 return rb_ivar_set(mReadline, completion_proc, proc);
851readline_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
908readline_s_set_completion_case_fold(
VALUE self,
VALUE val)
910 return rb_ivar_set(mReadline, completion_case_fold, val);
928readline_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
1003readline_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
1078readline_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
1151int 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
1190int 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
1675int rl_refresh_line(
int,
int);
1686 rl_refresh_line(0, 0);
1690#define readline_s_refresh_line rb_f_notimplement
1694hist_to_s(
VALUE self)
1700history_get_offset_history_base(
int offset)
1702 return history_base + offset;
1706history_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
1776rb_remove_history(
int index)
1778#ifdef HAVE_REMOVE_HISTORY
1782 entry = remove_history(
index);
1785 free((
void *) entry->line);
1800 if (history_length > 0) {
1801 return rb_remove_history(history_length - 1);
1808hist_shift(
VALUE self)
1810 if (history_length > 0) {
1811 return rb_remove_history(0);
1818hist_each(
VALUE self)
1825 for (
i = 0;
i < history_length;
i++) {
1826 entry = history_get(history_get_offset_func(
i));
1835hist_length(
VALUE self)
1837 return INT2NUM(history_length);
1841hist_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
1922int 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
unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len_p, rb_encoding *enc)
rb_encoding * rb_enc_check(VALUE str1, VALUE str2)
rb_encoding * rb_locale_encoding(void)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
VALUE rb_enc_str_new_static(const char *, long, rb_encoding *)
long rb_enc_strlen(const char *, const char *, rb_encoding *)
char str[HTML_ESCAPE_MAX_LEN+1]
void rb_extend_object(VALUE, VALUE)
Extend the object with the module.
VALUE rb_define_module(const char *)
VALUE rb_cObject
Object class.
void rb_notimplement(void)
void rb_syserr_fail(int e, const char *mesg)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_bug(const char *fmt,...)
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
void rb_sys_fail(const char *mesg)
VALUE rb_obj_reveal(VALUE obj, VALUE klass)
Make a hidden object visible again.
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_Array(VALUE)
Equivalent to Kernel#Array in Ruby.
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
VALUE rb_io_taint_check(VALUE)
#define GetOpenFile(obj, fp)
void rb_io_check_initialized(rb_io_t *)
#define readline_s_get_completion_quote_character
#define readline_s_refresh_line
#define readline_s_vi_editing_mode_p
#define OutputStringValue(str)
#define readline_s_set_screen_size
#define readline_s_vi_editing_mode
#define readline_s_set_basic_word_break_characters
#define readline_s_get_screen_size
#define readline_s_get_special_prefixes
#define readline_s_set_point
#define readline_s_delete_text
#define readline_s_set_pre_input_hook
#define readline_s_set_completion_append_character
#define readline_s_set_basic_quote_characters
#define readline_s_set_completer_word_break_characters
#define readline_s_set_filename_quote_characters
#define readline_s_get_quoting_detection_proc
#define readline_s_set_quoting_detection_proc
#define readline_s_emacs_editing_mode
#define rl_completion_matches
#define readline_s_get_basic_quote_characters
#define readline_s_get_pre_input_hook
#define rl_filename_completion_function
#define readline_s_get_filename_quote_characters
#define readline_s_set_special_prefixes
#define COMPLETION_CASE_FOLD
#define readline_s_redisplay
#define readline_s_get_line_buffer
#define readline_s_get_completer_quote_characters
#define readline_s_get_point
#define rl_username_completion_function
#define readline_s_insert_text
#define readline_s_get_completer_word_break_characters
#define readline_s_set_completer_quote_characters
#define EDIT_LINE_LIBRARY_VERSION
#define readline_s_get_completion_append_character
#define readline_s_emacs_editing_mode_p
#define readline_s_get_basic_word_break_characters
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
int rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout)