# I/O I/O 动词是编译进每个 Deft 运行时的裸标准库函数—— `deft` 脚本二进制与各 TUI 宿主皆然。它们操作通道(channel): `open` 返回不透明的 `%Chan` 句柄,`puts` / `gets` 通过它读写。整文件与路径辅助函数见 文件系统, 调用形式见 语法与风格。 ## 函数 | 函数 | 用途 | |---|---| | `echo $args...` | 将值打印到 stdout,后跟一个换行 | | `puts ?target $value` | 向通道写入一行(默认 `:stdout`);字符串原样输出,其他值按 `echo` 的方式格式化 | | `gets ?target` | 从通道读取一行(默认 `:stdin`);EOF 时返回 nil | | `open "path" ?mode` | 以不透明的 `%Chan` 打开文件(`"r"`/`"w"`/`"a"`/`"rw"`);失败时返回 `%Err` | | `close $chan` | 关闭通道;本次调用将其关闭则返回 true,已关闭则返回 false | | `log $args...` | 将值追加到 `<tmp>/deft.log`(绕过捕获) | 通道目标是来自 `open` 的 `%Chan` 句柄,或 `:stdin` / `:stdout` / `:stderr` 关键字——原始文件描述符从来不是值。描述符是进程全局的、 可复用的,且无法被 GC 回收,因此将裸 fd 编号传给 `puts`、`gets` 或 `close` 会被拒绝。通道用 `close` 显式关闭, 或在被丢弃的句柄被 GC 回收时自动关闭;标准流关键字本身不能关闭 (传入会引发错误)。 ### 说明 - `echo` 始终写入 stdout,每次调用一行。字符串原样输出; 其他值格式化后用于显示。 - `puts` 将 `$value` 和换行写入目标通道。字符串原样输出; 其他值的格式化方式与 `echo` 完全相同。 - `gets` 返回不含末尾换行的行,文件结束时返回 `nil` (最后一行没有换行也仍会返回)。它会阻塞直到有行到达—— 在托管 TUI 应用的 TTY 上,这会卡住面板。 - `open` 的模式有 `"r"` 读取(默认)、`"w"` 写入(截断)、`"a"` 追加和 `"rw"` 读写。未知模式会引发错误;无法打开路径 会返回 `%Err{:message}`,因此使用句柄前先用 `err?` 检查。 - `close` 是幂等的:第一次调用返回 `true`,之后的调用 返回 `false`。关闭标准流会引发错误。 - `log` 是裸磁盘日志器:它将格式化、空格分隔的值和换行 追加到 `<tmp-dir>/deft.log`,绕过 TUI 重定向和 echo 捕获缓冲区——它在每种宿主中都写入磁盘。要获得由 `DEFT_LOG_LEVEL` 控制的分级输出,请使用 日志 中的 `log/debug`、`log/info`、`log/warn` 和 `log/error`。 ## 示例 ### 写入并读取文件
set path "/tmp/deft-io.txt"

set out [open $path "w"]
puts $out "first line"
puts $out "second line"
close $out

set in [open $path]                    # mode defaults to "r"
while true {
    set line [gets $in]
    if [nil? $line] { break }
    echo "read:" $line
}
close $in
### 流与磁盘日志
echo "to stdout"
puts :stderr "diagnostic to stderr"

set out [open "/tmp/deft-io.txt" "a"]  # append
puts $out "appended entry"
close $out

log "checkpoint reached:" 17
不带目标的 `puts` 会写入 `:stdout`,因此 `puts $value` 等价于 `puts :stdout $value`。 ## 另见 - 文件系统 - 日志 - 实用工具 - 语法与风格