我有以下代码:
def test_callback_interface
with_temp_stdio do |stdin, stdout|
stdin.write("hello\n")
stdin.close
stdout.flush
line = nil
replace_stdio(stdin.path, stdout.path) {
Readline.handler_install("> ", true) { |l| line = l }
6.times { Readline.read_char }
Readline.handler_remove
}
assert_equal("hello", line) <------ FAIL here
assert_equal(true, line.tainted?)
stdout.rewind
assert_equal("> ", stdout.read(2))
assert_equal(1, Readline::HISTORY.length)
assert_equal("hello", Readline::HISTORY[0])
end
assert_equal(true, false)
end
它在assert_equal("hello", line)
行上失败,说line
是nil
。但是,我确信调用了回调(我通过将raise
放在那里来验证它)。所以我必须在这里遗漏一些关于范围的基本信息。有人可以告诉我如何将l
的值赋予line
变量吗?
由于
编辑:
如何在handler_install / read_char中调用回调?
static VALUE readline_callback_ensure(VALUE val) {
free(readline_callback_line);
readline_callback_line = NULL;
return Qnil;
}
static VALUE readline_callback_call(VALUE line) {
VALUE proc = rb_attr_get(mReadline, read_char_cb_proc);
rb_funcall(proc, id_call, 1, line);
return Qnil;
}
static void readline_callback_callback(char * line) {
if (readline_callback_add_history && line) {
add_history(line);
}
readline_callback_line = line;
rb_ensure(
readline_callback_call, line ? rb_str_new_cstr(line) : Qnil,
readline_callback_ensure, Qnil
);
}
static VALUE readline_callback_handler_install(int argc, VALUE * argv, VALUE self) {
VALUE tmp, add_hist, block;
char * prompt = NULL;
rb_need_block();
if (rb_scan_args(argc, argv, "02&", &tmp, &add_hist, &block) > 0) {
prompt = RSTRING_PTR(tmp);
}
if (RTEST(add_hist)) {
readline_callback_add_history = true;
} else {
readline_callback_add_history = false;
}
rb_ivar_set(mReadline, read_char_cb_proc, block);
rl_callback_handler_install(prompt, readline_callback_callback);
return Qnil;
}
static VALUE readline_callback_read_char(VALUE self) {
VALUE proc = rb_attr_get(mReadline, read_char_cb_proc);
if (NIL_P(proc)) {
rb_raise(rb_eRuntimeError, "No handler installed.");
}
rl_callback_read_char();
return Qnil;
}
所以基本上read_char
调用rl_callback_read_char
(gnu readline函数),它在检测完整行时调用我安装的处理程序readline_callback_callback
,它调用了用户提供的存储块。
答案 0 :(得分:0)
解决,而不是范围问题。 GNU Readline在EOF上再次使用NULL调用我的代码,完全忘记了这一点。