2017-05-26 25 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調用我的代碼,完全忘了這一點。