Ruby 2.4

Readline

module Readline

Readline模块为GNU Readline提供接口。这个模块定义了许多方法来促进完成,并从Ruby解释器访问输入历史记录。该模块也支持编辑行(libedit)。libedit与GNU Readline兼容。

通过:: 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

常量

FILENAME_COMPLETION_PROC

带有调用方法的Object是文件名的完成。这由:: completion_proc = method设置。

历史

历史缓冲区。它扩展了Enumerable模块,所以它的行为就像一个数组。例如,获取用户通过HISTORY输入的第五个内容。

USERNAME_COMPLETION_PROC

带有调用方法的对象,即用户名完成。这由:: completion_proc = method设置。

公共类方法

basic_quote_characters → string Show source

获取可能导致分词的引号字符列表。

如果使用readline库不支持,则引发NotImplementedError。

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 }

basic_quote_characters = string Show source

设置可能导致分词的引号字符列表。

如果使用readline库不支持,则引发NotImplementedError。

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; }

basic_word_break_characters → string Show source

获取完成程序例程中用于表示单词间断的基本字符列表。

如果使用readline库不支持,则引发NotImplementedError。

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 }

basic_word_break_characters = string Show source

设置完成程序例程中表示单词间断的基本字符列表。缺省值是在Bash中完成单词的字符:“tn”\'`@ $> <=; |&{(“。

如果使用readline库不支持,则引发NotImplementedError。

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; }

completer_quote_characters → string Show source

获取可用于引用该行的子字符串的字符列表。

如果使用readline库不支持,则引发NotImplementedError。

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 }

completer_quote_characters = string Show source

设置可用于引用该行的子字符串的字符列表。完成发生在整个子字符串上,并且在substring :: completer_word_break_characters内​​被视为任何其他字符,除非它们也出现在此列表中。

如果使用readline库不支持,则引发NotImplementedError。

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 → string Show source

获取rl_complete_internal()的单词间基本信息列表。

如果使用readline库不支持,则引发NotImplementedError。

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 }

completer_word_break_characters = string Show source

设置用于rl_complete_internal()的单词之间中断的基本字符列表。默认值是:: basic_word_break_characters的值。

如果使用readline库不支持,则引发NotImplementedError。

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; }

completion_append_character → char Show source

返回一个字符串,其中包含要在完成时添加的字符。默认值是一个空格(“”)。

如果使用readline库不支持,则引发NotImplementedError。

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 }

completion_append_character = char Show source

指定完成时添加的字符。如果指定了空字符串(“”)或零,则不会附加任何内容。

例如:

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

注意:只能指定一个字符。当指定“字符串”时,只设置“s”,即第一个。

require "readline" Readline.completion_append_character = "string" p Readline.completion_append_character # => "s"

如果使用readline库不支持,则引发NotImplementedError。

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; }

completion_case_fold → bool Show source

如果完成忽略大小写,则返回true。如果不是,则返回false。

注:返回由:: completion_case_fold = method指定的相同对象。

require "readline" Readline.completion_case_fold = "This is a String." p Readline.completion_case_fold # => "This is a String."

static VALUE readline_s_get_completion_case_fold(VALUE self) { return rb_attr_get(mReadline, completion_case_fold }

completion_case_fold = bool Show source

设置是否在完成时忽略大小写。

static VALUE readline_s_set_completion_case_fold(VALUE self, VALUE val) { return rb_ivar_set(mReadline, completion_case_fold, val }

completion_proc → proc Show source

返回完成Proc对象。

static VALUE readline_s_get_completion_proc(VALUE self) { return rb_attr_get(mReadline, completion_proc }

completion_proc = proc Show source

指定一个Proc对象proc来确定完成行为。它应该输入字符串并返回一个完成候选数组。

如果proc为零,则使用缺省完成。

传递给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

自动完成策略

When working with auto-complete there are some strategies that work well. To get some ideas you can take a look at the completion.rb file for irb.

常见的策略是获取可能的完成列表并将其过滤到以用户输入开始的完成。在上面的例子中,使用了Enumerable#grep。输入被转义以防止Regexp特殊字符干扰匹配。

使用Abbrev库生成完成也可能有所帮助。

如果proc不响应呼叫方法,则引发ArgumentError 。

static VALUE readline_s_set_completion_proc(VALUE self, VALUE proc) { mustbe_callable(proc return rb_ivar_set(mReadline, completion_proc, proc }

delete_text([start, length]) → self Show source

delete_text(start..end) → self

delete_text() → self

在当前行中删除开始和结束之间的文本。

请参阅GNU Readline的rl_delete_text函数。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_delete_text(int argc, VALUE *argv, VALUE self) { rb_check_arity(argc, 0, 2 if (rl_line_buffer) { const char *p, *ptr = rl_line_buffer; long beg = 0, len = strlen(ptr const char *end = ptr + len; rb_encoding *enc = rb_locale_encoding( if (argc == 2) { beg = NUM2LONG(argv[0] len = NUM2LONG(argv[1] num_pos: p = str_subpos(ptr, end, beg, &len, enc if (!p) rb_raise(rb_eArgError, "invalid index" beg = p - ptr; } else if (argc == 1) { len = rb_enc_strlen(ptr, ptr + len, enc 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; }

emacs_editing_mode → nil Show source

指定Emacs编辑模式。默认是这种模式。有关Emacs编辑模式的详细信息,请参阅GNU Readline手册。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_emacs_editing_mode(VALUE self) { rl_emacs_editing_mode(1,0 return Qnil; }

emacs_editing_mode? → bool Show source

如果emacs模式处于活动状态,则返回true。如果不是,则返回false。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_emacs_editing_mode_p(VALUE self) { return rl_editing_mode == 1 ? Qtrue : Qfalse; }

filename_quote_characters → string Show source

获取一个字符列表,当完成者出现在完整的文件名中时,这些字符会导致文件名被引用。

如果使用readline库不支持,则引发NotImplementedError。

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 }

filename_quote_characters = string Show source

设置一个字符列表,当完成者出现在完整的文件名中时,这些字符会导致文件名被引用。默认值是零。

如果使用readline库不支持,则引发NotImplementedError。

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; }

get_screen_size → rows, columns()

返回终端的行和列。

请参阅GNU Readline的rl_get_screen_size函数。

如果使用readline库不支持,则引发NotImplementedError。

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; }

input = input Show source

指定一个File对象input,它是:: 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 rb_syserr_fail(save_errno, "fdopen" } rl_instream = readline_rl_instream = f; readline_instream = input; } return input; }

insert_text(string) → self Show source

Insert text into the line at the current cursor position.

See GNU Readline's rl_insert_text function.

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_insert_text(VALUE self, VALUE str) { OutputStringValue(str rl_insert_text(RSTRING_PTR(str) return self; }

line_buffer → string Show source

返回正在编辑的完整行。这在complete_proc中用于确定完成请求的上下文很有用。

Readline.line_bufferGNU Readline的rl_end 的长度是相同的。

如果使用readline库不支持,则引发NotImplementedError。

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 }

output = output Show source

指定一个File对象output,它是:: 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 rb_syserr_fail(save_errno, "fdopen" } rl_outstream = readline_rl_outstream = f; readline_outstream = output; } return output; }

point → int Show source

返回当前光标位置的索引Readline.line_buffer

Readline.line_buffer与传递到:: completion_proc的输入字符串的开始匹配的索引是通过从中减去输入字符串的长度来计算的Readline.point

start = (the length of input-string) - Readline.point

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_get_point(VALUE self) { return INT2NUM(rl_point }

point = int Show source

设置当前光标位置的索引Readline.line_buffer

如果使用readline库不支持,则引发NotImplementedError。

Readline.point

static VALUE readline_s_set_point(VALUE self, VALUE pos) { rl_point = NUM2INT(pos return pos; }

pre_input_hook → proc Show source

proc在第一个提示已经打印并且在readline开始读取输入字符之前,返回要调用的Proc对象。默认值是零。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_get_pre_input_hook(VALUE self) { return rb_attr_get(mReadline, id_pre_input_hook }

pre_input_hook = proc Show source

指定一个Proc对象proc,在第一个提示已经打印并且在readline开始读取输入字符之前调用。

请参阅GNU Readline的rl_pre_input_hook变量。

如果proc不响应呼叫方法,则引发ArgumentError 。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_set_pre_input_hook(VALUE self, VALUE proc) { mustbe_callable(proc return rb_ivar_set(mReadline, id_pre_input_hook, proc }

quoting_detection_proc → proc Show source

返回引用检测Proc对象。

static VALUE readline_s_get_quoting_detection_proc(VALUE self) { return rb_attr_get(mReadline, quoting_detection_proc }

quoting_detection_proc = proc Show source

指定Proc对象proc以确定用户输入中的字符是否已转义。它应该将用户的输入和问题字符的索引作为输入,并返回一个布尔值(如果指定的字符被转义,则返回true)。

Readline只会使用指定的字符来调用该proc completer_quote_characters,以发现它们是否指示引用参数的结尾或指定的字符completer_word_break_characters,以发现它们是否指示参数之间的中断。

如果completer_quote_characters没有设置,或者如果用户输入不包含其中一个completer_quote_characters或一个++字符,则Readline将不会尝试使用该过程。

如果proc不响应呼叫方法,则引发ArgumentError 。

static VALUE readline_s_set_quoting_detection_proc(VALUE self, VALUE proc) { mustbe_callable(proc return rb_ivar_set(mReadline, quoting_detection_proc, proc }

readline(prompt = "", add_hist = false) → string or nil Show source

prompt用行编辑显示并读取输入的行。输入的行如果add_hist为真,则添加到历史记录中。

当输入的行为空并且用户输入EOF时,返回nil(在UNIX上按下^ D)。

如果满足以下条件之一,则引发IOError异常。

  • stdin被关闭。

  • 标准输出已关闭。

此方法支持线程。在等待输入行时切换线程上下文。

输入行时支持行编辑。提供VI和Emacs编辑模式。默认是Emacs编辑模式。

注意:终止ruby解释器并且在等待输入线路时用户按'^ C'后不会返回终端状态。给出3个避免它的例子。

  • 通过在返回终端状态后按下^ C来捕获中断异常:require“readline”stty_save = stty -g.chomp begin while buf = Readline.readline p buf结束救援中断系统(“stty”,stty_save)退出结束结束结束

  • 返回终端状态后按^ C捕捉INT信号:

需要“readline”stty_save =%x stty -g.chomp trap(“INT”){system“stty”,stty_save; 退出}而buf = Readline.readline p buf结束

  • 忽略按^ C:

需要“readline”陷阱(“INT”,“SIG_IGN”)而buf = Readline.readline p buf结束

可以使用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_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; }

redisplay → self Show source

更改屏幕上显示的内容以反映当前内容。

请参阅GNU Readline的rl_redisplay函数。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_redisplay(VALUE self) { rl_redisplay( return self; }

refresh_line → nil Show source

清除当前输入行。

static VALUE readline_s_refresh_line(VALUE self) { prepare_readline( rl_refresh_line(0, 0 return Qnil; }

set_screen_size(rows, columns) → self Show source

将终端大小设置为rowscolumns

请参阅GNU Readline的rl_set_screen_size函数。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_set_screen_size(VALUE self, VALUE rows, VALUE columns) { rl_set_screen_size(NUM2INT(rows), NUM2INT(columns) return self; }

special_prefixes → string Show source

获取作为分词符的字符列表,但在传递到完成函数时应保留为文本。

请参阅GNU Readline的rl_special_prefixes变量。

如果使用readline库不支持,则引发NotImplementedError。

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; }

special_prefixes = string Show source

设置作为分词符的字符列表,但在传递到完成功能时应保留为文本。程序可以使用它来帮助确定完成什么样的操作。例如,Bash将此变量设置为“$ @”,以便它可以完成shell变量和主机名。

请参阅GNU Readline的rl_special_prefixes变量。

如果使用readline库不支持,则引发NotImplementedError。

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; }

vi_editing_mode → nil Show source

指定VI编辑模式。有关VI编辑模式的详细信息,请参阅GNU Readline手册。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_vi_editing_mode(VALUE self) { rl_vi_editing_mode(1,0 return Qnil; }

vi_editing_mode? → bool Show source

vi模式处于活动状态时返回true。如果不是,则返回false。

如果使用readline库不支持,则引发NotImplementedError。

static VALUE readline_s_vi_editing_mode_p(VALUE self) { return rl_editing_mode == 0 ? Qtrue : Qfalse; }