You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raku中start加{}导致NCurses终端resize异常的原因解析

Raku中start { loop { ... } }与start loop { ... }的行为差异原因分析

原始正常程序

这个Raku NCurses程序会在终端调整大小时打印尺寸,按ESC键退出:

#!/bin/env raku
use NCurses;
initscr;
loop {
    given getch() {
        when 27 { last } # exit when pressing esc
        when KEY_RESIZE {
            mvprintw 0, 0, "{LINES}x{COLS}";
            nc_refresh
        }
    }
}

endwin;

异常写法(带外层大括号)

给loop加上await start { ... }包裹后,程序运行异常:终端调整大小时无输出,按下任意键才会打印尺寸,但ESC键退出功能正常。

await start { loop {
    given getch() {
        when 27 { last }
        when KEY_RESIZE {
            mvprintw 0, 0, "{LINES}x{COLS}";
            nc_refresh
        }
    }
} }

恢复正常的写法(去掉外层大括号)

去掉大括号写成await start loop ...时,程序恢复正常运行:

await start loop {
    given getch() {
        when 27 { last }
        when KEY_RESIZE {
            mvprintw 0, 0, "{LINES}x{COLS}";
            nc_refresh
        }
    }
}

原因分析

核心差异源于Raku中start的调用方式与NCurses事件处理的交互:

  • start loop { ... }是将循环块直接作为参数传递给start,异步线程启动后会立刻进入循环执行getch(),此时getch()能持续监听终端的输入事件与KEY_RESIZE信号,终端调整尺寸时会被及时捕获并处理。
  • start { loop { ... } }传递的是一个嵌套块,异步线程先执行外层块,再进入内部循环。NCurses的getch()依赖当前线程的终端上下文,外层块的存在会导致异步线程的终端上下文初始化出现延迟,使得KEY_RESIZE事件无法被实时响应——这类终端事件会被缓存,直到有按键输入触发getch()唤醒,才会一次性处理之前的KEY_RESIZE事件,因此出现“按任意键才打印尺寸”的现象。
  • ESC键功能不受影响是因为它属于直接按键输入,会直接触发getch()返回,无需依赖终端事件的主动推送,所以两种写法都能正常捕获。

内容的提问来源于stack exchange,提问作者fingolfin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 10:41:17