ITADN
migueldeicaza/SwiftTerm
migueldeicaza/SwiftTerm · 文件 下载 ZIP
文件最后提交记录最后更新时间
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

SwiftTerm

SwiftTerm 是一个用于 Swift 应用的 VT100/Xterm 终端模拟器库,可以 嵌入到 macOS、iOS 应用、基于文本的无头应用或其他 自定义场景中。它已被用于多个商业可用的 SSH 客户端,包括 Secure ShellfishLa TerminalCodeEdit

查看 API 文档

本仓库包含一个与 UI 无关的终端模拟器引擎,以及 针对 iOS(使用 UIKit)和 macOS(使用 AppKit)的该引擎的前端。 一个基于 curses 的 终端模拟器(用于在控制台应用中模拟 xterm)作为 TermKit 库的一部分提供。

示例代码TerminalApp 目录中有一些用于 Mac 和 iOS 的最小示例应用,展示了如何 使用该库。

  • 示例 Mac 应用具有 MacOS 的 Terminal.app 的大部分功能,但没有配置 UI。
  • 示例 iOS 应用使用 SSH 库连接到远程系统(因为 iOS 上没有原生 shell 可运行),并包含一个登录 UI 来配置连接。

配套应用

SwiftTermApp 构建 了一个实际使用此库的 iOS 应用,比本模块中的 测试应用更完整,并提供了适当的配置 UI。 它是你需要做什么的一个概念验证。

Pane 是一个终端 复用器,类似于 tmux。

历史

这是我最初作品的移植版本 XtermSharp,它本身 基于 xterm.js。 目前,我认为 SwiftTerm 比这两者都是更先进的终端模拟器(除了 选择/辅助功能),因为它对 UTF、Unicode 和字素簇的处理 优于它们,并且对终端模拟的覆盖更加全面。 XtermSharp 总体上一直在努力跟上,但已经落后了。

大量测试用例已从 xterm.js 和 Ghostty 中提取, 并且本作品还大量依赖 esctest 以确保兼容性。

功能

  • 相当出色的终端仿真,性能持平或优于 XtermSharp 和 xterm.js(在许多方面更为全面)
  • Unicode 渲染(包括 Emoji,以及组合字符和 emoji)
  • 遵循 terminal-wg BiDi 建议的双向文本(阿拉伯语、希伯来语),支持阿拉伯语上下文整形
  • 可复用且可插拔的引擎,允许在其之上构建多个用户界面:
    • 捆绑的 MacOS 和 iOS
    • 捆绑的 Headless 终端。
    • TermKit 包含一个终端之上的终端
    • Pane 实现了一个终端复用器
  • 选择引擎(在视图中支持 macOS)
  • 搜索支持,内置 macOS 查找栏和可编程搜索 API
  • 支持颜色(ANSI、256、TrueColor)
  • 支持文本属性,包括粗体、斜体、下划线、删除线和暗淡/微弱(SGR 2)
  • 支持鼠标事件
  • 支持终端调整大小操作(由远程主机控制,或本地控制)
  • 终端输出中的 Hyperlinks
  • 本地进程和 SSH 连接支持(后者需要一些组装)
  • 正确的 CoreText 渲染可以顺利通过强化的 Unicode 测试套件。
  • 图形支持:
    • Sixel(使用 img2sixel 进行测试)
    • iTerm2 风格的图形渲染(使用 imgcat 进行测试)
    • Kitty 图形(使用 kittyimg 进行测试)
  • 使用 termcast 进行终端会话录制和回放
  • 线程安全的 Terminal 实例
  • 经过模糊测试和滥用测试
  • 可选的通过 Metal 进行 GPU 加速渲染(macOS、iOS、visionOS)
  • 在我看来相当快

图像格式

SwiftTerm 支持以下图像数据格式:

  • Sixel 图像流。
  • 通过 iTerm2 和 Kitty 图形协议传输的 PNG 图像。
  • 通过 iTerm2 图形协议传输的 JPEG 图像。
  • 通过 Kitty 图形协议传输的 Raw RGB(24 位)和 RGBA(32 位)像素数据。

对于 iTerm2 图像,Apple 视图使用系统图像解码器。目标平台能够解码的其他图像格式也可以工作,但 PNG 和 JPEG 是经过测试的格式。

SwiftTerm 库

SwiftTerm 库本身包含引擎和前端两者的源代码。前端根据目标平台进行条件编译。

引擎位于此目录中,而 macOS 的代码位于 Mac 下,iOS 的代码位于 iOS 下。鉴于这两者共享许多共同特性,共享代码位于 Apple 下。

使用 SwiftTerm

SwiftTerm 使用 Swift Package Manager 进行构建,您可以通过使用此项目的 url 或其 fork 来将库添加到您的项目中。

MacOS NSView

macOS AppKit NSView 实现 TerminalView 是一个可重用的 NSView 控件,可以通过实现 TerminalViewDelegate 连接到任何源。
我预计一个常见场景是 托管本地 Unix 命令,因此我包含了 LocalProcessTerminalView 这是一个将 TerminalView 连接到 Unix 伪终端并在其中运行命令的实现。

iOS UIView

存在一个等效的 UIKit UIView 实现,用于 TerminalView 它与其 NSView 对应物一样,是一个可嵌入且可复用的视图, 可以通过实现相同的 TerminalViewDelegate 将其连接到您的应用程序。 与在 Mac 上运行的 NSView 情况不同, 在 Mac 上,一个常见场景是运行本地命令,鉴于 iOS 不提供对进程的访问,最常见的场景将是 将此终端连接到远程主机。 而连接 到远程系统的最安全方式是使用 SSH。

MacOS 和 iOS 之间的共享代码

iOS 和 UIKit 代码共享大量代码,这些代码位于 Apple 目录下。

Apple 视图中的链接报告

AppKit 和 UIKit TerminalView 都暴露了 linkReporting

  • .none 禁用链接跟踪。
  • .explicit 仅跟踪显式的 OSC 8 超链接。
  • .implicit(默认)首先跟踪显式链接,然后回退到从终端文本中检测隐式 URL。

linkReporting 控制链接发现/跟踪。链接激活还受 linkHighlightMode 的额外控制。

当用户激活链接时,TerminalView 调用 TerminalViewDelegate.requestOpenLink(source:link:params:)。 对于显式的 OSC 8 超链接,params 包含解析后的键值元数据(如果提供);隐式链接使用空的 params。 在 macOS 上,默认委托实现通过 NSWorkspace 打开链接。在 iOS/visionOS 上,请在您的委托中处理 requestOpenLink

  • 在 macOS 上,跟踪基于悬停。默认高亮模式为 .hoverWithModifier,因此 Command 悬停和 Command 点击是默认的链接交互方式。
  • 在 iOS/visionOS 上,跟踪由指针/悬停交互驱动(UIPointerInteraction / UIHoverGestureRecognizer),而点击激活取决于活动的 linkHighlightMode(包括基于修饰键模式的修饰键要求)。

使用 SSH

核心库目前不提供连接 SSH 的便捷方式,纯粹 是为了避免额外的依赖。iOS 示例应用演示了如何使用现代 SSH 技术栈集成 SSH ,使用 swift-nio-ssh。参见 UIKitSshTerminalViewSSHLoginView ,了解将 iOS 的 TerminalView 连接到 SSH 连接的示例。

Termcast - 终端录制与回放

SwiftTerm 包含一个 termcast 命令行工具,可以录制和回放 asciinema .cast 格式的终端会话。该工具使用 SwiftTerm 的 LocalProcess 功能构建。

录制会话

要录制终端会话:

swift run termcast record output.cast

选项:

  • --command / -c: 指定要运行的命令(默认使用您的 shell)
  • --timeout / -t: 设置自动超时时间(秒)

示例:

# Record an interactive shell session
swift run termcast record my-session.cast

# Record a specific command
swift run termcast record -c "ls -la && echo 'Done'" command-demo.cast

# Record with a 30-second timeout
swift run termcast record --timeout 30 timed-session.cast

回放会话

要回放已录制的会话:

swift run termcast playback my-session.cast

播放将显示录制的终端会话,并保留正确的时序,包括录制过程中发生的输入和输出。

功能

  • 完整的输入/输出捕获:以精确的时序记录用户输入和程序输出
  • 原始终端模式:正确处理终端控制序列和特殊按键
  • asciinema 兼容性:使用标准 .cast 格式以实现互操作性
  • 实时显示:在录制时实时显示会话
  • 正确的终端处理:保持正确的行尾和终端状态

在 SwiftTerm 上工作

如果你使用 Xcode,有两个顶级项目,一个用于 Mac, 一个用于 iOS,位于 TerminalApp 目录中,一个名为 "iOSTerminal.xcodeproj", 另一个名为 "MacTerminal.xcodeproj"。

这是必要的,因为如果项目中包含 Mac 项目,Xcode 不会为 iOS 提供代码补全。 所以我不得不将它们分开。 两个 项目都引用同一个 SwiftTerm 包。

在处理这些项目时,如果你选择终端应用程序, 它将运行这个应用程序。 要运行测试套件,请选择 'SwiftTerm' 目标 而不是其他,你可以使用 'SwiftTermFuzz' 来运行模糊测试器。

你可以使用 swift build 来构建包,并使用 swift test 来 运行测试套件。 为了获得更好的测试覆盖率,克隆 esctest 仓库,其中包含全面的终端模拟器测试:

make clone-esctest
swift test

此操作会克隆 esctest 仓库(Python 3 分支)并启用完整的终端合规性 测试套件以运行。

如果使用 Xcode,您可以选择 "SwiftTerm" 项目,然后使用 Command-U 来运行测试套件。

双向文本 (BiDi)

SwiftTerm 实现了 terminal-wg BiDi 建议,用于 在 Apple 视图(CoreGraphics 和 Metal 渲染器)上处理 从右到左和混合方向的文本:

  • 缓冲区保持逻辑顺序;每个段落都在渲染 时通过 Unicode 双向算法重新排序,并支持阿拉伯语上下文 整形、lam-alef 连字和括号镜像。
  • 支持建议中的所有六种呈现模式: 隐式/显式、固定 LTR/RTL,以及从第一个强 字符进行自动检测。默认设置(隐式 + 自动检测 + LTR 回退)开箱即可正确渲染 RTL 文本,并保持 LTR 输出不变。
  • 终端应用程序使用标准序列控制行为: BDSM (CSI 8 h/l)、SCP (CSI Ps SP k) 以及 DEC 私有模式 2501 (自动检测)、2500(制表符镜像)和 1243(箭头键 交换),包括 DECRQM 查询和 XTSAVE/XTRESTORE。
  • 嵌入者可以通过 TerminalOptionsinitialBidiStateinitialBidiArrowKeySwapmaximumBidiParagraphRows)设置初始状态, 通过 Terminal.currentBidiState 检查状态,并使用 TerminalView.bidiHostPolicy = .legacyLeftToRight 完全 禁用某个视图。

详细信息请参阅 BiDi 文档

BiDi 视觉测试框架

SwiftTerm BiDi 测试框架 是一个用于可视化 BiDi 测试的 AppKit 应用。 它在 WebKit 参考实现旁边显示 SwiftTerm。其场景涵盖段落重排、终端模式、重置行为、 方框镜像、组合字符、选择、光标移动和回滚缓冲区。

从仓库根目录运行它:

Tools/BidiHarness/Scripts/run-harness.sh --artifacts /tmp/bidi-artifacts

使用应用中的控件来选择场景、遍历其步骤、调整终端大小、滚动、更改渲染器并保存捕获。该应用还具有一个本地控制套接字,用于可重复的测试运行。有关控制命令、Xcode 说明、工件路径以及 Metal 窗口捕获所需的 macOS 权限,请参阅 harness README。

截图

24 位颜色

24 bit color

Midnight Commander

Screen Shot 2020-04-12 at 12 17 49 AM

完善的 UTF-8 支持,出色的渲染效果: Screen Shot 2020-04-22 at 11 25 30 PM

Screen Shot 2020-04-22 at 11 25 24 PM

支持由现代应用发出的超链接:

image

iOS 支持:

image

Sixel 支持:

image image

Resources

Additional and useful documents:

Test suites:

  • VTTest - 较旧,但仍然很好
  • EscTest - 非常出色:iTerm 的作者 George Nachman 创建了此测试套件,它已成为 FreeDesktop 标准。 此后,xterm 维护者以及许多文本应用维护者 Thomas E. Dickey 也为此工作做出了贡献。

Authors

  • 感谢 xterm.js 开发者,他们最初编写了一个终端模拟器, 该模拟器采用允许最大程度复用的许可证。
  • Marcin Krzyzanowski 他出色地改进并优化了基于 AppKit/CoreText 的渲染引擎,使其成为如今卓越的渲染器——并感谢他对渲染引擎的贡献
  • Greg Munn 他在 XtermSharp 中做了大量工作,以支持 Visual Studio for Mac 的需求
  • Anders Borum 他贡献了可靠性修复、sixel 解析器以及将 SwiftTerm 投入生产环境所需的更改。
  • Miguel de Icaza -我- 一直在寻找一个编写一些 Swift 代码的借口。