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

3
我正在使用Swift构建命令行工具,并想知道是否有办法在运行应用程序时确定视口的当前宽度,以便将屏幕上的文本限制为适合而不换行的内容。
我知道在“真正的”命令行应用程序中可以实现这一点,因为像pico、man、pine等都是基于窗口大小呈现其文本界面的,但我似乎找不到关于它们如何实现的任何信息。
事实上,您甚至可以在它们运行时调整窗口大小,它们会自动刷新。有人知道这是如何实现的吗?是否可以向使用Swift编写的命令行工具添加此功能支持?

在Bash shell中,LINESCOLUMNS环境变量提供了屏幕大小。但是,在Mac上使用Swift命令行工具时,这些变量在ProcessInfo.processInfo.environment中并不会出现。 - rmaddy
你关心Xcode调试窗口还是只关心终端?正如@Martin R所说,你可以使用ioctl在终端中获取宽度和高度,但这在XCode的调试窗口中不起作用[即使你将“行为”更改为在新选项卡中启动调试控制台]。 - rustyMagnet
1个回答

8

这段来自获取终端宽度的C代码可轻松翻译为Swift:

import Darwin

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

由于某些原因,在Xcode调试器控制台中无法正常工作,您需要在终端窗口中调用可执行文件。
另外,您也可以使用ncurses库(参考链接:获取C语言中的终端宽度?)。
import Darwin.ncurses

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

为了追踪窗口调整大小事件,您需要处理SIGWINCH信号,可参考在Swift命令行应用程序中捕获信号
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()

1
太棒了!如果可以的话,我会给你买一杯啤酒。谢谢马丁! - devios1
1
@devios1:如果我有机会去加拿大,我会给你打电话的 :) - Martin R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接