初始提交:terminalX 可运行态(M0/M1/M1.5 已真机验证)
- M0: libghostty SSH 终端(渲染/输入/连接)+ 白屏修复(OutputGate) + 会话状态机/自动重连 - M1: tsnet 用户态组网 + SSH-over-tsnet(fd 桥),shell 级真机验证;R5(Go+gvisor+C+++Swift 同进程) retire - M1.5: tmux -CC 原生 tab(MVP) - 结构: packages/(TXCore·TXTransport), apps/TerminalX, vendor/(libghostty-spm/libssh2/mbedtls/tsnet-bridge), artifacts/ - 文档: CLAUDE.md + docs/HANDOFF.md(新会话入口) - 环境: 认证代理→依赖 vendor 本地化;Go 在 ~/.local/go;仅模拟器/未签名 - 待续: M2 mosh, tmux 多 pane, M4 安全(host key/SE) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
94
vendor/libghostty-spm/docs/guide/in-memory.html
vendored
Normal file
94
vendor/libghostty-spm/docs/guide/in-memory.html
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · Host-managed I/O</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>Host-managed I/O</h1>
|
||||
<nav class="on-this-page" aria-label="On this page">
|
||||
<strong>On this page:</strong>
|
||||
<a href="#session">Session</a>
|
||||
<a href="#output">Output</a>
|
||||
<a href="#viewport">Viewport</a>
|
||||
<a href="#exit">Exit</a>
|
||||
</nav>
|
||||
|
||||
<p><code>InMemoryTerminalSession</code> connects Ghostty’s host-managed backend to your own process, emulator, or command engine. The host supplies output with <code>receive</code>, and Ghostty sends user input through the <code>write</code> closure.</p>
|
||||
|
||||
<h2 id="session">Create a session</h2>
|
||||
<pre><code class="language-swift">let session = InMemoryTerminalSession(
|
||||
write: { data in
|
||||
backend.handleInput(data)
|
||||
},
|
||||
resize: { viewport in
|
||||
backend.resize(columns: viewport.columns, rows: viewport.rows)
|
||||
}
|
||||
)
|
||||
|
||||
terminal.configuration = TerminalSurfaceOptions(
|
||||
backend: .inMemory(session)
|
||||
)
|
||||
</code></pre>
|
||||
|
||||
<h2 id="output">Send host output</h2>
|
||||
<p>Use UTF-8 strings for simple demos and <code>Data</code> for exact byte streams.</p>
|
||||
<pre><code class="language-swift">session.receive("hello from host\r\n")
|
||||
session.receive(Data([0x1B, 0x5B, 0x32, 0x4A])) // ESC [ 2 J
|
||||
</code></pre>
|
||||
|
||||
<h2 id="viewport">Read viewport text</h2>
|
||||
<p><code>readViewportText()</code> returns the visible grid as a UTF-8 string. It reads viewport rows and separates them with <code>\n</code>.</p>
|
||||
<pre><code class="language-swift">if let text = session.readViewportText() {
|
||||
print(text)
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="exit">Finish a process</h2>
|
||||
<p>Tell Ghostty that the host-managed process has exited so lifecycle delegates and shell integration receive the close event.</p>
|
||||
<pre><code class="language-swift">session.finish(exitCode: 0, runtimeMilliseconds: 1234)
|
||||
</code></pre>
|
||||
|
||||
<nav class="pager" aria-label="Sibling pages">
|
||||
<a class="prev" href="uikit-appkit.html">UIKit & AppKit</a>
|
||||
<a class="parent" href="index.html">↑ Guide</a>
|
||||
<a class="next" href="themes.html">Themes</a>
|
||||
</nav>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"
|
||||
integrity="sha384-GdEWAbCjn+ghjX0gLx7/N1hyTVmPAjdC2OvoAA0RyNcAOhqwtT8qnbCxWle2+uJX"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/swift.min.js"
|
||||
integrity="sha384-TfALNLT6HJzZieazgsVvFM0DzFWQsgl0d7mdwPLyg1yg7XE4QwLY4jqmJRNnI1S4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</body>
|
||||
</html>
|
||||
66
vendor/libghostty-spm/docs/guide/index.html
vendored
Normal file
66
vendor/libghostty-spm/docs/guide/index.html
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · Guide</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>Guide</h1>
|
||||
<p class="lede">Task-oriented integration notes for embedding GhosttyKit in Apple apps. Each page maps directly to a product or workflow.</p>
|
||||
|
||||
<ul class="hub-list">
|
||||
<li>
|
||||
<a href="swiftui.html">SwiftUI</a>
|
||||
<span class="summary"><code>TerminalViewState</code>, <code>TerminalSurfaceView</code>, lifecycle state, and sending input.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="uikit-appkit.html">UIKit & AppKit</a>
|
||||
<span class="summary">Create <code>TerminalView</code>, assign a controller, attach delegates, and configure native input.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="in-memory.html">Host-managed I/O</a>
|
||||
<span class="summary"><code>InMemoryTerminalSession</code> bridges terminal bytes to a sandbox-safe host backend.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="themes.html">Themes</a>
|
||||
<span class="summary">Use <code>GhosttyThemeCatalog</code>, convert themes to terminal config, and switch light/dark variants.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="text-selection.html">Text selection</a>
|
||||
<span class="summary">Long-press requests, viewport snapshots, UTF-16 ranges, and host presentation.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="shellcraft.html">ShellCraftKit</a>
|
||||
<span class="summary">Build a sandboxed command surface backed by <code>ShellDefinition</code> and <code>ShellSession</code>.</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
93
vendor/libghostty-spm/docs/guide/shellcraft.html
vendored
Normal file
93
vendor/libghostty-spm/docs/guide/shellcraft.html
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · ShellCraftKit</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>ShellCraftKit</h1>
|
||||
<nav class="on-this-page" aria-label="On this page">
|
||||
<strong>On this page:</strong>
|
||||
<a href="#shell">Shell</a>
|
||||
<a href="#commands">Commands</a>
|
||||
<a href="#attach">Attach</a>
|
||||
</nav>
|
||||
|
||||
<p><code>ShellCraftKit</code> is a small command engine for demos and sandboxed tools. It feeds a Ghostty terminal through <code>InMemoryTerminalSession</code> and executes Swift closures for commands.</p>
|
||||
|
||||
<h2 id="shell">Define a shell</h2>
|
||||
<pre><code class="language-swift">import ShellCraftKit
|
||||
|
||||
let shell = ShellDefinition(
|
||||
prompt: "demo$ ",
|
||||
welcomeMessage: "\r\nGhosttyKit demo\r\n\r\n"
|
||||
) {
|
||||
ShellCommand("date", summary: "Print the current date") { _ in
|
||||
.output(Date().description + "\r\n")
|
||||
}
|
||||
|
||||
ShellCommand("clear", summary: "Clear the screen") { _ in
|
||||
.clear
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="commands">Command result</h2>
|
||||
<p>A command returns one of three results: output, clear, or exit. <code>CommandContext</code> gives the parsed command name, arguments, username, and current terminal size.</p>
|
||||
<pre><code class="language-swift">ShellCommand("size", summary: "Print terminal size") { context in
|
||||
.output("\(context.terminalSize.columns)x\(context.terminalSize.rows)\r\n")
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="attach">Attach to Ghostty</h2>
|
||||
<pre><code class="language-swift">let shellSession = ShellSession(shell: shell)
|
||||
shellSession.start()
|
||||
|
||||
terminal.configuration = TerminalSurfaceOptions(
|
||||
backend: .inMemory(shellSession.terminalSession)
|
||||
)
|
||||
</code></pre>
|
||||
|
||||
<nav class="pager" aria-label="Sibling pages">
|
||||
<a class="prev" href="text-selection.html">Text selection</a>
|
||||
<a class="parent" href="index.html">↑ Guide</a>
|
||||
<a class="next" href="../api/index.html">API</a>
|
||||
</nav>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"
|
||||
integrity="sha384-GdEWAbCjn+ghjX0gLx7/N1hyTVmPAjdC2OvoAA0RyNcAOhqwtT8qnbCxWle2+uJX"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/swift.min.js"
|
||||
integrity="sha384-TfALNLT6HJzZieazgsVvFM0DzFWQsgl0d7mdwPLyg1yg7XE4QwLY4jqmJRNnI1S4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</body>
|
||||
</html>
|
||||
109
vendor/libghostty-spm/docs/guide/swiftui.html
vendored
Normal file
109
vendor/libghostty-spm/docs/guide/swiftui.html
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · SwiftUI</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>SwiftUI</h1>
|
||||
<nav class="on-this-page" aria-label="On this page">
|
||||
<strong>On this page:</strong>
|
||||
<a href="#state">State</a>
|
||||
<a href="#view">View</a>
|
||||
<a href="#input">Input</a>
|
||||
<a href="#configuration">Configuration</a>
|
||||
</nav>
|
||||
|
||||
<p>SwiftUI integration starts with <code>TerminalViewState</code>. It owns the controller, exposes observable terminal state, and tracks the current <code>TerminalSurface</code> after a platform view attaches.</p>
|
||||
|
||||
<h2 id="state">State</h2>
|
||||
<pre><code class="language-swift">import SwiftUI
|
||||
import GhosttyTerminal
|
||||
|
||||
struct TerminalScreen: View {
|
||||
@StateObject private var terminal = TerminalViewState()
|
||||
|
||||
var body: some View {
|
||||
TerminalSurfaceView(context: terminal)
|
||||
.navigationTitle(terminal.title)
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p>Observable properties include <code>title</code>, <code>surfaceSize</code>, <code>isFocused</code>, <code>bellCount</code>, <code>lastBellAt</code>, desktop notification metadata, <code>workingDirectory</code>, and command-finished metadata.</p>
|
||||
|
||||
<h2 id="view">View</h2>
|
||||
<p><code>TerminalSurfaceView</code> embeds the platform terminal view and adopts the current SwiftUI color scheme. iOS 15, macOS 13, and Mac Catalyst 15 are the SwiftUI floor for this wrapper.</p>
|
||||
<pre><code class="language-swift">TerminalSurfaceView(context: terminal)
|
||||
.onAppear {
|
||||
terminal.configuration = TerminalSurfaceOptions(
|
||||
backend: .inMemory(session),
|
||||
fontSize: 13,
|
||||
workingDirectory: "/"
|
||||
)
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="input">Input</h2>
|
||||
<p>Call <code>send(_:)</code> after the surface attaches. The method returns <code>true</code> when Ghostty accepts the text.</p>
|
||||
<pre><code class="language-swift">@discardableResult
|
||||
func sendCommand(_ command: String) -> Bool {
|
||||
terminal.send(command + "\r")
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="configuration">Configuration</h2>
|
||||
<p>Use fluent configuration for common Ghostty settings, and <code>custom(_:_:)</code> for additional Ghostty config keys.</p>
|
||||
<pre><code class="language-swift">let config = TerminalConfiguration.default
|
||||
.fontFamily("SF Mono")
|
||||
.fontSize(13)
|
||||
.windowPaddingX(8)
|
||||
.windowPaddingY(6)
|
||||
.custom("shell-integration", "detect")
|
||||
|
||||
terminal.setTerminalConfiguration(config)
|
||||
</code></pre>
|
||||
|
||||
<nav class="pager" aria-label="Sibling pages">
|
||||
<a class="prev" href="index.html">Guide</a>
|
||||
<a class="parent" href="index.html">↑ Guide</a>
|
||||
<a class="next" href="uikit-appkit.html">UIKit & AppKit</a>
|
||||
</nav>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"
|
||||
integrity="sha384-GdEWAbCjn+ghjX0gLx7/N1hyTVmPAjdC2OvoAA0RyNcAOhqwtT8qnbCxWle2+uJX"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/swift.min.js"
|
||||
integrity="sha384-TfALNLT6HJzZieazgsVvFM0DzFWQsgl0d7mdwPLyg1yg7XE4QwLY4jqmJRNnI1S4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</body>
|
||||
</html>
|
||||
89
vendor/libghostty-spm/docs/guide/text-selection.html
vendored
Normal file
89
vendor/libghostty-spm/docs/guide/text-selection.html
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · Text selection</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>Text selection</h1>
|
||||
<nav class="on-this-page" aria-label="On this page">
|
||||
<strong>On this page:</strong>
|
||||
<a href="#flow">Flow</a>
|
||||
<a href="#delegate">Delegate</a>
|
||||
<a href="#range">Ranges</a>
|
||||
</nav>
|
||||
|
||||
<p>On iOS, a single-finger long press requests host text selection. GhosttyKit sends a viewport snapshot, a suggested UTF-16 range, and the source point for anchoring UI.</p>
|
||||
|
||||
<h2 id="flow">Flow</h2>
|
||||
<ol>
|
||||
<li>The user long-presses the terminal view for 0.5 seconds.</li>
|
||||
<li>The view asks Ghostty for a viewport text snapshot and a quicklook word anchor.</li>
|
||||
<li><code>TerminalTextSelectionRequest</code> arrives at the delegate.</li>
|
||||
<li>The host presents its own UI, commonly a <code>UITextView</code> sheet or popover.</li>
|
||||
</ol>
|
||||
|
||||
<h2 id="delegate">Delegate</h2>
|
||||
<pre><code class="language-swift">final class SelectionCoordinator: TerminalSurfaceTextSelectionRequestDelegate {
|
||||
func terminalDidRequestTextSelection(_ request: TerminalTextSelectionRequest) {
|
||||
let textView = UITextView()
|
||||
textView.text = request.text
|
||||
|
||||
if let range = request.anchorRange {
|
||||
textView.selectedRange = range
|
||||
} else {
|
||||
textView.selectAll(nil)
|
||||
}
|
||||
|
||||
presentSelectionUI(textView, sourcePoint: request.sourcePoint)
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="range">Ranges</h2>
|
||||
<p><code>anchorRange</code> uses UTF-16 units so it can be assigned directly to <code>UITextView.selectedRange</code>. Duplicate words on the same row are disambiguated with the long-press x coordinate and Ghostty cell metrics.</p>
|
||||
<p class="muted">The MVP targets the in-memory backend and viewport text. Full scrollback selection belongs in a host selection surface.</p>
|
||||
|
||||
<nav class="pager" aria-label="Sibling pages">
|
||||
<a class="prev" href="themes.html">Themes</a>
|
||||
<a class="parent" href="index.html">↑ Guide</a>
|
||||
<a class="next" href="shellcraft.html">ShellCraftKit</a>
|
||||
</nav>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"
|
||||
integrity="sha384-GdEWAbCjn+ghjX0gLx7/N1hyTVmPAjdC2OvoAA0RyNcAOhqwtT8qnbCxWle2+uJX"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/swift.min.js"
|
||||
integrity="sha384-TfALNLT6HJzZieazgsVvFM0DzFWQsgl0d7mdwPLyg1yg7XE4QwLY4jqmJRNnI1S4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</body>
|
||||
</html>
|
||||
98
vendor/libghostty-spm/docs/guide/themes.html
vendored
Normal file
98
vendor/libghostty-spm/docs/guide/themes.html
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · Themes</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>Themes</h1>
|
||||
<nav class="on-this-page" aria-label="On this page">
|
||||
<strong>On this page:</strong>
|
||||
<a href="#catalog">Catalog</a>
|
||||
<a href="#apply">Apply</a>
|
||||
<a href="#custom">Custom</a>
|
||||
</nav>
|
||||
|
||||
<p><code>GhosttyTheme</code> ships 485 terminal color themes from iTerm2-Color-Schemes. Each theme can render directly into <code>TerminalConfiguration</code> and participate in light/dark switching.</p>
|
||||
|
||||
<h2 id="catalog">Catalog lookup</h2>
|
||||
<pre><code class="language-swift">import GhosttyTheme
|
||||
|
||||
let theme = GhosttyThemeCatalog.theme(named: "Dracula")
|
||||
let matches = GhosttyThemeCatalog.search("solarized")
|
||||
let all = GhosttyThemeCatalog.allThemes
|
||||
</code></pre>
|
||||
|
||||
<h2 id="apply">Apply to a terminal</h2>
|
||||
<p>Wrap one or two definitions in <code>TerminalTheme</code>, then assign it to the controller or state container.</p>
|
||||
<pre><code class="language-swift">import GhosttyTerminal
|
||||
import GhosttyTheme
|
||||
|
||||
let dark = GhosttyThemeCatalog.theme(named: "Dracula")!
|
||||
let light = GhosttyThemeCatalog.theme(named: "Solarized Light")!
|
||||
|
||||
let theme = TerminalTheme(
|
||||
light: light.toTerminalConfiguration(),
|
||||
dark: dark.toTerminalConfiguration()
|
||||
)
|
||||
|
||||
terminal.setTheme(theme)
|
||||
</code></pre>
|
||||
|
||||
<p><code>TerminalSurfaceView</code> follows the SwiftUI color scheme and asks <code>TerminalController</code> to resolve the effective config for the active appearance.</p>
|
||||
|
||||
<h2 id="custom">Custom colors</h2>
|
||||
<pre><code class="language-swift">let config = TerminalConfiguration.default
|
||||
.background("#101010")
|
||||
.foreground("#f0f0f0")
|
||||
.cursorColor("#ffd866")
|
||||
.selectionBackground("#334455")
|
||||
.palette(0, color: "#1b1d23")
|
||||
.palette(1, color: "#ef6155")
|
||||
|
||||
terminal.setTerminalConfiguration(config)
|
||||
</code></pre>
|
||||
|
||||
<nav class="pager" aria-label="Sibling pages">
|
||||
<a class="prev" href="in-memory.html">Host-managed I/O</a>
|
||||
<a class="parent" href="index.html">↑ Guide</a>
|
||||
<a class="next" href="text-selection.html">Text selection</a>
|
||||
</nav>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"
|
||||
integrity="sha384-GdEWAbCjn+ghjX0gLx7/N1hyTVmPAjdC2OvoAA0RyNcAOhqwtT8qnbCxWle2+uJX"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/swift.min.js"
|
||||
integrity="sha384-TfALNLT6HJzZieazgsVvFM0DzFWQsgl0d7mdwPLyg1yg7XE4QwLY4jqmJRNnI1S4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</body>
|
||||
</html>
|
||||
124
vendor/libghostty-spm/docs/guide/uikit-appkit.html
vendored
Normal file
124
vendor/libghostty-spm/docs/guide/uikit-appkit.html
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<title>GhosttyKit · UIKit & AppKit</title>
|
||||
<link rel="stylesheet" href="../styles.css">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github.min.css"
|
||||
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/styles/github-dark.min.css"
|
||||
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH"
|
||||
crossorigin="anonymous"
|
||||
media="(prefers-color-scheme: dark)">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="topbar" aria-label="Primary">
|
||||
<a class="home" href="../index.html">GhosttyKit</a>
|
||||
<a href="../index.html">Overview</a>
|
||||
<a href="index.html" aria-current="page">Guide</a>
|
||||
<a href="../api/index.html">API</a>
|
||||
<a href="../architecture.html">Architecture</a>
|
||||
<a href="../build.html">Build</a>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<h1>UIKit & AppKit</h1>
|
||||
<nav class="on-this-page" aria-label="On this page">
|
||||
<strong>On this page:</strong>
|
||||
<a href="#view">View</a>
|
||||
<a href="#delegate">Delegate</a>
|
||||
<a href="#ios-input">iOS input</a>
|
||||
</nav>
|
||||
|
||||
<p><code>TerminalView</code> resolves to <code>UITerminalView</code> on UIKit and <code>AppTerminalView</code> on AppKit. Catalyst follows UIKit.</p>
|
||||
|
||||
<h2 id="view">View setup</h2>
|
||||
<pre><code class="language-swift">import GhosttyTerminal
|
||||
|
||||
let terminalView = TerminalView(frame: .zero)
|
||||
let controller = TerminalController(configuration: .default)
|
||||
|
||||
terminalView.controller = controller
|
||||
terminalView.configuration = TerminalSurfaceOptions(
|
||||
backend: .inMemory(session)
|
||||
)
|
||||
terminalView.delegate = coordinator
|
||||
</code></pre>
|
||||
|
||||
<p>The view owns the native input layer and the Metal-backed surface. <code>TerminalController</code> owns Ghostty app lifecycle, configuration resolution, themes, and surface creation.</p>
|
||||
|
||||
<h2 id="delegate">Delegate callbacks</h2>
|
||||
<p>Adopt the delegate protocols that match your host UI. A single coordinator object can implement multiple protocols.</p>
|
||||
<pre><code class="language-swift">final class Coordinator:
|
||||
TerminalSurfaceTitleDelegate,
|
||||
TerminalSurfaceGridResizeDelegate,
|
||||
TerminalSurfaceBellDelegate,
|
||||
TerminalSurfaceLifecycleDelegate
|
||||
{
|
||||
func terminalDidChangeTitle(_ title: String) {}
|
||||
func terminalDidResize(_ size: TerminalGridMetrics) {}
|
||||
func terminalDidRingBell() {}
|
||||
func terminalDidAttachSurface(_ surface: TerminalSurface) {}
|
||||
func terminalDidDetachSurface() {}
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<h2 id="ios-input">iOS input</h2>
|
||||
<p><code>UITerminalView</code> conforms to <code>UITextInput</code>. Hardware keys enter through <code>pressesBegan</code>, software keyboard text enters through <code>insertText</code>, and marked text flows through the shared IME handler.</p>
|
||||
<p>On iOS, the input accessory bar provides Esc, Tab, arrows, symbols, Paste, and sticky Ctrl/Alt/Cmd modifiers. Configure colors through <code>inputAccessoryStyle</code>.</p>
|
||||
<pre><code class="language-swift">#if canImport(UIKit)
|
||||
terminalView.inputAccessoryStyle = .init(
|
||||
regularBackground: .secondarySystemBackground,
|
||||
regularForeground: .label,
|
||||
activeBackground: .label,
|
||||
activeForeground: .systemBackground
|
||||
)
|
||||
#endif
|
||||
</code></pre>
|
||||
<p>Hosts with a custom keyboard bar can hide the bundled accessory and drive sticky modifiers through the public sticky APIs.</p>
|
||||
<pre><code class="language-swift">#if canImport(UIKit)
|
||||
terminalView.inputAccessoryItems = []
|
||||
#endif
|
||||
</code></pre>
|
||||
<p>The default button list is available as <code>TerminalInputAccessoryItem.defaultItems</code>. Hosts can provide a smaller list while keeping the bundled bar styling and key dispatch behavior.</p>
|
||||
<pre><code class="language-swift">#if canImport(UIKit)
|
||||
terminalView.inputAccessoryItems = [
|
||||
.esc,
|
||||
.ctrl,
|
||||
.alt,
|
||||
.command,
|
||||
.divider,
|
||||
.tab,
|
||||
.arrowLeft,
|
||||
.arrowRight,
|
||||
.paste,
|
||||
]
|
||||
#endif
|
||||
</code></pre>
|
||||
|
||||
<nav class="pager" aria-label="Sibling pages">
|
||||
<a class="prev" href="swiftui.html">SwiftUI</a>
|
||||
<a class="parent" href="index.html">↑ Guide</a>
|
||||
<a class="next" href="in-memory.html">Host-managed I/O</a>
|
||||
</nav>
|
||||
|
||||
<footer>
|
||||
GhosttyKit · <a href="https://github.com/Lakr233/libghostty-spm">github.com/Lakr233/libghostty-spm</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js"
|
||||
integrity="sha384-GdEWAbCjn+ghjX0gLx7/N1hyTVmPAjdC2OvoAA0RyNcAOhqwtT8qnbCxWle2+uJX"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/languages/swift.min.js"
|
||||
integrity="sha384-TfALNLT6HJzZieazgsVvFM0DzFWQsgl0d7mdwPLyg1yg7XE4QwLY4jqmJRNnI1S4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script>hljs.highlightAll();</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user