2017-05-26 24 views
1

我有以下代码:从块内部的块外部设置变量?

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 

失败上说,linenilassert_equal("hello", line)。不过,我确定该回调被称为(我通过将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其中调用存储由用户提供的块。

+1

你能告诉我们,你如何在'handler_install'中调用回调? – fangxing

+0

我不相信这是一个范围问题。尝试改变块'{| l | line = l}'到'{| l |放置“l =#{l}”; line = l}'。 –

+0

@fangxing我修改了我的问题以提供更多详细信息 – Paladin

回答

0

解决,不是一个范围问题。 GNU Readline在EOF上再次用NULL调用我的代码,完全忘了这一点。