在 Swift 中从命令行应用程序确定视口大小(以字符为单位)?

Determine viewport size (in characters) from command line app in Swift?

我正在 Swift 中构建一个命令行工具,我想知道是否有任何方法可以在 运行 应用程序时确定视口的当前宽度,以限制文本筛选适合不包裹的内容。

我知道这在 "real" 命令行应用程序中是可能的,因为 pico、man、pine 等都基于 window 大小呈现它们的文本界面,但我可以似乎找不到关于他们如何做的任何信息。

事实上,您甚至可以在 window 处于 运行 时调整它们的大小,它们会刷新。有谁知道这是如何工作的,以及是否可以向用 Swift 编写的命令行工具添加支持?

来自 Getting terminal width in C? 的 C 代码很容易翻译成 Swift:

import Darwin

var w = winsize()
if ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0 {
    print("rows:", w.ws_row, "cols", w.ws_col)
}

(出于某种原因,这在 Xcode 调试器控制台中不起作用, 您必须在终端 window 中调用可执行文件。)

或者,使用 ncurses 库(来自 Getting terminal width in C?):

import Darwin.ncurses

initscr()
let s = "rows: \(LINES), cols: \(COLS)"
mvaddstr(1, 1, s);
refresh();
getch()
endwin()

要跟踪 window 调整大小事件,您必须处理 SIGWINCH 信号,比较 :

import Darwin
import Dispatch

var w = winsize()
if ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0 {
    print("rows:", w.ws_row, "cols", w.ws_col)
}

let sigwinchSrc = DispatchSource.makeSignalSource(signal: SIGWINCH, queue: .main)
sigwinchSrc.setEventHandler {
    if ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0 {
        print("rows:", w.ws_row, "cols", w.ws_col)
    }
}
sigwinchSrc.resume()

dispatchMain()