модуль Readline
Модуль Readline предоставляет интерфейс для GNU Readline. Этот модуль определяет ряд методов для облегчения автодополнения и доступа к истории ввода из интерпретатора Ruby. Этот модуль также поддерживает Edit Line (libedit). libedit совместим с GNU Readline.
- GNU Readline
- libedit
Считывает одну строку ввода с редактированием строк с помощью метода ::readline. В данный момент, можно использовать автодополнение и сочетания клавиш, как в Emacs, так же как и в GNU Readline.
require "readline"
while buf = Readline.readline("> ", true)
p buf
end
Содержание, введённое пользователем, может быть записано в историю. Доступ к истории осуществляется через константу Readline::HISTORY.
require "readline"
while buf = Readline.readline("> ", true)
p Readline::HISTORY.to_a
print("-> ", buf, "\n")
end
Документировано Кодзи Такао <kouji dot takao at gmail dot com>.
Константы
- FILENAME_COMPLETION_PROC
-
Объект с методом вызова, который является автодополнением для имён файлов. Он устанавливается методом ::completion_proc=.
- HISTORY
-
Буфер истории. Он расширяет модуль Enumerable, поэтому ведет себя как массив. Например, получить пятое содержимое введённое пользователем с помощью HISTORY.
- USERNAME_COMPLETION_PROC
-
Объект с методом вызова, который является автодополнением для имён пользователей. Он устанавливается методом ::completion_proc=.
- VERSION
-
Строка версии GNU Readline или libedit.
Публичные методы класса
static VALUE
readline_s_get_basic_quote_characters(VALUE self, VALUE str)
{
if (rl_basic_quote_characters == NULL)
return Qnil;
return rb_locale_str_new_cstr(rl_basic_quote_characters);
} Возвращает список символов кавычек, которые могут вызвать разрыв слова.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_set_basic_quote_characters(VALUE self, VALUE str)
{
static char *basic_quote_characters = NULL;
OutputStringValue(str);
if (basic_quote_characters == NULL) {
basic_quote_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
}
else {
REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1);
}
strncpy(basic_quote_characters,
RSTRING_PTR(str), RSTRING_LEN(str));
basic_quote_characters[RSTRING_LEN(str)] = '\0';
rl_basic_quote_characters = basic_quote_characters;
return self;
} Устанавливает список символов кавычек, которые могут вызвать разрыв слова.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_get_basic_word_break_characters(VALUE self, VALUE str)
{
if (rl_basic_word_break_characters == NULL)
return Qnil;
return rb_locale_str_new_cstr(rl_basic_word_break_characters);
} Возвращает базовый список символов, которые сигнализируют о разрыве между словами для процедуры автодополнения.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_set_basic_word_break_characters(VALUE self, VALUE str)
{
static char *basic_word_break_characters = NULL;
OutputStringValue(str);
if (basic_word_break_characters == NULL) {
basic_word_break_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
}
else {
REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1);
}
strncpy(basic_word_break_characters,
RSTRING_PTR(str), RSTRING_LEN(str));
basic_word_break_characters[RSTRING_LEN(str)] = '\0';
rl_basic_word_break_characters = basic_word_break_characters;
return self;
} Устанавливает базовый список символов, которые сигнализируют о разрыве между словами для процедуры автодополнения. По умолчанию это символы, которые разрывают слова для автодополнения в Bash: “ tn"\'`@$><=;|&{(”.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_get_completer_quote_characters(VALUE self, VALUE str)
{
if (rl_completer_quote_characters == NULL)
return Qnil;
return rb_locale_str_new_cstr(rl_completer_quote_characters);
} Возвращает список символов, которые могут использоваться для цитирования подстроки строки.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_set_completer_quote_characters(VALUE self, VALUE str)
{
static char *completer_quote_characters = NULL;
OutputStringValue(str);
if (completer_quote_characters == NULL) {
completer_quote_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
}
else {
REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1);
}
strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
completer_quote_characters[RSTRING_LEN(str)] = '\0';
rl_completer_quote_characters = completer_quote_characters;
return self;
} Устанавливает список символов, которые могут использоваться для цитирования подстроки строки. Автодополнение происходит по всей подстроке, и внутри подстроки ::completer_word_break_characters рассматриваются как любые другие символы, если они также не присутствуют в этом списке.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_get_completer_word_break_characters(VALUE self, VALUE str)
{
if (rl_completer_word_break_characters == NULL)
return Qnil;
return rb_locale_str_new_cstr(rl_completer_word_break_characters);
} Возвращает базовый список символов, которые сигнализируют о разрыве между словами для rl_complete_internal().
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_set_completer_word_break_characters(VALUE self, VALUE str)
{
static char *completer_word_break_characters = NULL;
OutputStringValue(str);
if (completer_word_break_characters == NULL) {
completer_word_break_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
}
else {
REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1);
}
strncpy(completer_word_break_characters,
RSTRING_PTR(str), RSTRING_LEN(str));
completer_word_break_characters[RSTRING_LEN(str)] = '\0';
rl_completer_word_break_characters = completer_word_break_characters;
return self;
} Устанавливает базовый список символов, которые сигнализируют о разрыве между словами для rl_complete_internal(). По умолчанию используется значение ::basic_word_break_characters.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_get_completion_append_character(VALUE self)
{
char buf[1];
if (rl_completion_append_character == '\0')
return Qnil;
buf[0] = (char) rl_completion_append_character;
return rb_locale_str_new(buf, 1);
} Возвращает строку, содержащую символ, который будет добавлен при автодополнении. По умолчанию это пробел (“ ”).
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_set_completion_append_character(VALUE self, VALUE str)
{
if (NIL_P(str)) {
rl_completion_append_character = '\0';
}
else {
OutputStringValue(str);
if (RSTRING_LEN(str) == 0) {
rl_completion_append_character = '\0';
} else {
rl_completion_append_character = RSTRING_PTR(str)[0];
}
}
return self;
} Указывает символ, который будет добавлен при автодополнении. Ничего не будет добавлено, если указана пустая строка (“”) или nil.
Например:
require "readline"
Readline.readline("> ", true)
Readline.completion_append_character = " "
Результат:
> Input "/var/li". > /var/li Press TAB key. > /var/lib Completes "b" and appends " ". So, you can continuously input "/usr". > /var/lib /usr
ПРИМЕЧАНИЕ: Может быть указан только один символ. Если указана “строка”, устанавливается только “с”, то есть первый символ.
require "readline" Readline.completion_append_character = "string" p Readline.completion_append_character # => "s"
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_get_completion_case_fold(VALUE self)
{
return rb_attr_get(mReadline, completion_case_fold);
} Возвращает true, если автодополнение игнорирует регистр. В противном случае возвращает false.
ПРИМЕЧАНИЕ: Возвращает тот же объект, который указан методом ::completion_case_fold=.
require "readline" Readline.completion_case_fold = "This is a String." p Readline.completion_case_fold # => "This is a String."
static VALUE
readline_s_set_completion_case_fold(VALUE self, VALUE val)
{
return rb_ivar_set(mReadline, completion_case_fold, val);
} Устанавливает, следует ли игнорировать регистр при автодополнении.
static VALUE
readline_s_get_completion_proc(VALUE self)
{
return rb_attr_get(mReadline, completion_proc);
} Возвращает объект Proc автодополнения.
static VALUE
readline_s_set_completion_proc(VALUE self, VALUE proc)
{
if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call")))
rb_raise(rb_eArgError, "argument must respond to `call'");
return rb_ivar_set(mReadline, completion_proc, proc);
} Указывает объект Proc proc для определения поведения автодополнения. Он должен принимать входную строку и возвращать массив кандидатов для автодополнения.
Используется автодополнение по умолчанию, если proc равно nil.
Строка, передаваемая в Proc, зависит от свойства ::completer_word_break_characters. По умолчанию в Proc передаётся слово под курсором. Например, если входные данные — “foo bar”, то в процедуру автодополнения будет передано только “bar”.
После успешного автодополнения ::completion_append_character будет добавлен ко входу, чтобы пользователь мог начать работу со своим следующим аргументом.
Примеры
Автодополнение для статического списка
require 'readline'
LIST = [
'search', 'download', 'open',
'help', 'history', 'quit',
'url', 'next', 'clear',
'prev', 'past'
].sort
comp = proc { |s| LIST.grep(/^#{Regexp.escape(s)}/) }
Readline.completion_append_character = " "
Readline.completion_proc = comp
while line = Readline.readline('> ', true)
p line
end
Автодополнение для содержимого каталога
require 'readline'
Readline.completion_append_character = " "
Readline.completion_proc = Proc.new do |str|
Dir[str+'*'].grep(/^#{Regexp.escape(str)}/)
end
while line = Readline.readline('> ', true)
p line
end
Стратегии автодополнения
При работе с автодополнением существуют некоторые эффективные стратегии. Для получения идей можно посмотреть файл completion.rb для irb.
Распространённая стратегия заключается в том, чтобы взять список возможных вариантов автодополнения и отфильтровать его до тех вариантов, которые начинаются с пользовательского ввода. В примерах выше используется Enumerable#grep. Входные данные экранируются, чтобы предотвратить вмешательство специальных символов Regexp в сопоставление.
Также может быть полезно использовать библиотеку Abbrev для генерации вариантов автодополнения.
Вызывает ArgumentError, если proc не отвечает на вызов метода.
static VALUE
readline_s_delete_text(int argc, VALUE *argv, VALUE self)
{
rb_check_arity(argc, 0, 2);
if (rl_line_buffer) {
char *p, *ptr = rl_line_buffer;
long beg = 0, len = strlen(rl_line_buffer);
struct RString fakestr;
VALUE str = rb_setup_fake_str(&fakestr, ptr, len, rb_locale_encoding());
OBJ_FREEZE(str);
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
num_pos:
p = rb_str_subpos(str, beg, &len);
if (!p) rb_raise(rb_eArgError, "invalid index");
beg = p - ptr;
}
else if (argc == 1) {
len = rb_str_strlen(str);
if (!rb_range_beg_len(argv[0], &beg, &len, len, 1)) {
beg = NUM2LONG(argv[0]);
goto num_pos;
}
}
rl_delete_text(rb_long2int(beg), rb_long2int(beg + len));
}
return self;
} Удаляет текст между start и end в текущей строке.
См. функцию rl_delete_text в GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает данную функцию.
static VALUE
readline_s_emacs_editing_mode(VALUE self)
{
rl_emacs_editing_mode(1,0);
return Qnil;
} Задает режим редактирования Emacs. По умолчанию используется этот режим. Подробности о режиме редактирования Emacs см. в руководстве по GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_emacs_editing_mode_p(VALUE self)
{
return rl_editing_mode == 1 ? Qtrue : Qfalse;
} Возвращает true, если режим emacs активен. Возвращает false, если нет.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_get_filename_quote_characters(VALUE self, VALUE str)
{
if (rl_filename_quote_characters == NULL)
return Qnil;
return rb_locale_str_new_cstr(rl_filename_quote_characters);
} Получает список символов, которые приводят к тому, что имя файла заключается в кавычки средством автодополнения, когда они появляются в завершенном имени файла.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_set_filename_quote_characters(VALUE self, VALUE str)
{
static char *filename_quote_characters = NULL;
OutputStringValue(str);
if (filename_quote_characters == NULL) {
filename_quote_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
}
else {
REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1);
}
strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
filename_quote_characters[RSTRING_LEN(str)] = '\0';
rl_filename_quote_characters = filename_quote_characters;
return self;
} Устанавливает список символов, которые приводят к тому, что имя файла заключается в кавычки средством автодополнения, когда они появляются в завершенном имени файла. Значение по умолчанию — nil.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_get_screen_size(VALUE self)
{
int rows, columns;
VALUE res;
rl_get_screen_size(&rows, &columns);
res = rb_ary_new();
rb_ary_push(res, INT2NUM(rows));
rb_ary_push(res, INT2NUM(columns));
return res;
} Возвращает количество строк и столбцов терминала.
См. функцию rl_get_screen_size в GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_set_input(VALUE self, VALUE input)
{
rb_io_t *ifp;
int fd;
FILE *f;
if (NIL_P(input)) {
clear_rl_instream();
}
else {
Check_Type(input, T_FILE);
GetOpenFile(input, ifp);
clear_rl_instream();
fd = rb_cloexec_dup(ifp->fd);
if (fd == -1)
rb_sys_fail("dup");
f = fdopen(fd, "r");
if (f == NULL) {
int save_errno = errno;
close(fd);
errno = save_errno;
rb_sys_fail("fdopen");
}
rl_instream = readline_rl_instream = f;
readline_instream = input;
}
return input;
} Указывает объект File input который является входным потоком для метода ::readline.
static VALUE
readline_s_insert_text(VALUE self, VALUE str)
{
OutputStringValue(str);
rl_insert_text(RSTRING_PTR(str));
return self;
} Вставляет текст в строку в текущую позицию курсора.
См. функцию rl_insert_text в GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_get_line_buffer(VALUE self)
{
if (rl_line_buffer == NULL)
return Qnil;
return rb_locale_str_new_cstr(rl_line_buffer);
} Возвращает полную строку, которая редактируется. Это полезно изнутри complete_proc для определения контекста запроса на автодополнение.
Длина Readline.line_buffer и rl_end в GNU Readline совпадают.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_set_output(VALUE self, VALUE output)
{
rb_io_t *ofp;
int fd;
FILE *f;
if (NIL_P(output)) {
clear_rl_outstream();
}
else {
Check_Type(output, T_FILE);
GetOpenFile(output, ofp);
clear_rl_outstream();
fd = rb_cloexec_dup(ofp->fd);
if (fd == -1)
rb_sys_fail("dup");
f = fdopen(fd, "w");
if (f == NULL) {
int save_errno = errno;
close(fd);
errno = save_errno;
rb_sys_fail("fdopen");
}
rl_outstream = readline_rl_outstream = f;
readline_outstream = output;
}
return output;
} Указывает объект File output который является выходным потоком для метода ::readline.
static VALUE
readline_s_get_point(VALUE self)
{
return INT2NUM(rl_point);
} Возвращает индекс текущей позиции курсора в Readline.line_buffer.
Индекс в Readline.line_buffer, который соответствует началу входной строки, переданной в ::completion_proc, вычисляется путем вычитания длины входной строки из Readline.point.
start = (the length of input-string) - Readline.point
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_set_point(VALUE self, VALUE pos)
{
rl_point = NUM2INT(pos);
return pos;
} Устанавливает индекс текущей позиции курсора в Readline.line_buffer.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
См. Readline.point.
static VALUE
readline_s_get_pre_input_hook(VALUE self)
{
return rb_attr_get(mReadline, id_pre_input_hook);
} Возвращает объект Proc proc для вызова после того, как первый приглашение будет напечатано и непосредственно перед тем, как readline начнет считывать входные символы. Значение по умолчанию — nil.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_set_pre_input_hook(VALUE self, VALUE proc)
{
if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call")))
rb_raise(rb_eArgError, "argument must respond to `call'");
return rb_ivar_set(mReadline, id_pre_input_hook, proc);
} Указывает объект Proc proc для вызова после того, как первый приглашение будет напечатано и непосредственно перед тем, как readline начнет считывать входные символы.
См. переменную rl_pre_input_hook в GNU Readline.
Вызывает ArgumentError, если proc не отвечает на вызов метода.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_readline(int argc, VALUE *argv, VALUE self)
{
VALUE tmp, add_hist, result;
char *prompt = NULL;
char *buff;
int status;
if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
OutputStringValue(tmp);
#if USE_INSERT_IGNORE_ESCAPE
tmp = insert_ignore_escape(self, tmp);
rb_str_locktmp(tmp);
#endif
prompt = RSTRING_PTR(tmp);
}
prepare_readline();
#ifdef _WIN32
rl_prep_terminal(1);
#endif
buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status);
#if USE_INSERT_IGNORE_ESCAPE
if (prompt) {
rb_str_unlocktmp(tmp);
}
#endif
if (status) {
#if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
/* restore terminal mode and signal handler*/
#if defined HAVE_RL_FREE_LINE_STATE
rl_free_line_state();
#endif
rl_cleanup_after_signal();
#elif defined HAVE_RL_DEPREP_TERM_FUNCTION
/* restore terminal mode */
if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */
(*rl_deprep_term_function)();
else
#else
rl_deprep_terminal();
#endif
rb_jump_tag(status);
}
if (RTEST(add_hist) && buff) {
add_history(buff);
}
if (buff) {
result = rb_locale_str_new_cstr(buff);
}
else
result = Qnil;
if (buff) free(buff);
return result;
} Показывает prompt и считывает введенную строку с редактированием строки. Введенная строка добавляется в историю, если add_hist истинно.
Возвращает nil, когда введенная строка пуста, и пользователь вводит EOF (нажимает ^D в UNIX).
Вызывает исключение IOError, если выполняется одно из следующих условий.
-
stdin был закрыт.
-
stdout был закрыт.
Этот метод поддерживает потоки. Переключает контекст потока при ожидании ввода строки.
Поддерживает редактирование строки при вводе строки. Предоставляет режимы редактирования VI и Emacs. По умолчанию используется режим редактирования Emacs.
ПРИМЕЧАНИЕ: завершает интерпретатор ruby и не возвращает состояние терминала после того, как пользователь нажал '^C' при ожидании ввода строки. Приведите 3 примера, чтобы избежать этого.
-
Перехватывает исключение Interrupt после нажатия ^C после возврата состояния терминала:
require "readline" stty_save = `stty -g`.chomp begin while buf = Readline.readline p buf end rescue Interrupt system("stty", stty_save) exit end end end -
Перехватывает сигнал INT после нажатия ^C после возврата состояния терминала:
require "readline" stty_save = %x`stty -g`.chomp trap("INT") { system "stty", stty_save; exit } while buf = Readline.readline p buf end -
Игнорирует нажатие ^C:
require "readline" trap("INT", "SIG_IGN") while buf = Readline.readline p buf end
Можно сделать следующим образом с константой Readline::HISTORY. Он не записывает в историю, если введенная строка пуста или совпадает с последней.
require "readline"
while buf = Readline.readline("> ", true)
# p Readline::HISTORY.to_a
Readline::HISTORY.pop if /^\s*$/ =~ buf
begin
if Readline::HISTORY[Readline::HISTORY.length-2] == buf
Readline::HISTORY.pop
end
rescue IndexError
end
# p Readline::HISTORY.to_a
print "-> ", buf, "\n"
end
static VALUE
readline_s_redisplay(VALUE self)
{
rl_redisplay();
return self;
} Изменяет то, что отображается на экране, чтобы отразить текущее содержимое.
См. функцию rl_redisplay в GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_refresh_line(VALUE self)
{
prepare_readline();
rl_refresh_line(0, 0);
return Qnil;
} Очищает текущую строку ввода.
static VALUE
readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns)
{
rl_set_screen_size(NUM2INT(rows), NUM2INT(columns));
return self;
} Устанавливает размер терминала на rows и columns.
См. функцию rl_set_screen_size в GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_get_special_prefixes(VALUE self)
{
VALUE str;
if (rl_special_prefixes == NULL) return Qnil;
str = rb_ivar_get(mReadline, id_special_prefixes);
if (!NIL_P(str)) {
str = rb_str_dup_frozen(str);
rb_obj_reveal(str, rb_cString);
}
return str;
} Получает список символов, которые являются разделителями слов, но должны оставаться в тексте, когда он передаётся функции дополнения.
См. переменную rl_special_prefixes GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_set_special_prefixes(VALUE self, VALUE str)
{
if (!NIL_P(str)) {
OutputStringValue(str);
str = rb_str_dup_frozen(str);
rb_obj_hide(str);
}
rb_ivar_set(mReadline, id_special_prefixes, str);
if (NIL_P(str)) {
rl_special_prefixes = NULL;
}
else {
rl_special_prefixes = RSTRING_PTR(str);
}
return self;
} Устанавливает список символов, которые являются разделителями слов, но должны оставаться в тексте при передаче функции дополнения. Программы могут использовать это, чтобы определить какой тип дополнения выполнять. Например, Bash устанавливает эту переменную в «$@», чтобы можно было дополнять оболочковые переменные и имена хостов.
См. переменную rl_special_prefixes GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_vi_editing_mode(VALUE self)
{
rl_vi_editing_mode(1,0);
return Qnil;
} Указывает режим редактирования VI. Подробности о режиме редактирования VI см. в руководстве по GNU Readline.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
static VALUE
readline_s_vi_editing_mode_p(VALUE self)
{
return rl_editing_mode == 0 ? Qtrue : Qfalse;
} Возвращает true, если активен режим vi. Возвращает false, если нет.
Вызывает NotImplementedError, если используемая библиотека readline не поддерживает.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.