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_buffer
GNU 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
将终端大小设置为rows
和columns
。
请参阅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;
}