mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
115 lines
3.0 KiB
Swift
115 lines
3.0 KiB
Swift
import AppKit
|
|
import AppIntents
|
|
import SwiftUI
|
|
|
|
struct TerminalEntity: AppEntity {
|
|
let id: UUID
|
|
|
|
@Property(title: "Title")
|
|
var title: String
|
|
|
|
@Property(title: "Working Directory")
|
|
var workingDirectory: String?
|
|
|
|
@MainActor
|
|
@DeferredProperty(title: "Full Contents")
|
|
@available(macOS 26.0, *)
|
|
var screenContents: String? {
|
|
get async {
|
|
guard let surfaceView else { return nil }
|
|
return surfaceView.cachedScreenContents.get()
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
@DeferredProperty(title: "Visible Contents")
|
|
@available(macOS 26.0, *)
|
|
var visibleContents: String? {
|
|
get async {
|
|
guard let surfaceView else { return nil }
|
|
return surfaceView.cachedVisibleContents.get()
|
|
}
|
|
}
|
|
|
|
var screenshot: Image?
|
|
|
|
static var typeDisplayRepresentation: TypeDisplayRepresentation {
|
|
TypeDisplayRepresentation(name: "Terminal")
|
|
}
|
|
|
|
@MainActor
|
|
var displayRepresentation: DisplayRepresentation {
|
|
var rep = DisplayRepresentation(title: "\(title)")
|
|
if let screenshot,
|
|
let nsImage = ImageRenderer(content: screenshot).nsImage,
|
|
let data = nsImage.tiffRepresentation {
|
|
rep.image = .init(data: data)
|
|
}
|
|
|
|
return rep
|
|
}
|
|
|
|
/// Returns the view associated with this entity. This may no longer exist.
|
|
@MainActor
|
|
var surfaceView: Ghostty.SurfaceView? {
|
|
Self.defaultQuery.all.first { $0.uuid == self.id }
|
|
}
|
|
|
|
@MainActor
|
|
var surfaceModel: Ghostty.Surface? {
|
|
surfaceView?.surfaceModel
|
|
}
|
|
|
|
static var defaultQuery = TerminalQuery()
|
|
|
|
init(_ view: Ghostty.SurfaceView) {
|
|
self.id = view.uuid
|
|
self.title = view.title
|
|
self.workingDirectory = view.pwd
|
|
self.screenshot = view.screenshot()
|
|
}
|
|
}
|
|
|
|
struct TerminalQuery: EntityStringQuery, EnumerableEntityQuery {
|
|
@MainActor
|
|
func entities(for identifiers: [TerminalEntity.ID]) async throws -> [TerminalEntity] {
|
|
return all.filter {
|
|
identifiers.contains($0.uuid)
|
|
}.map {
|
|
TerminalEntity($0)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
func entities(matching string: String) async throws -> [TerminalEntity] {
|
|
return all.filter {
|
|
$0.title.localizedCaseInsensitiveContains(string)
|
|
}.map {
|
|
TerminalEntity($0)
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
func allEntities() async throws -> [TerminalEntity] {
|
|
return all.map { TerminalEntity($0) }
|
|
}
|
|
|
|
@MainActor
|
|
func suggestedEntities() async throws -> [TerminalEntity] {
|
|
return try await allEntities()
|
|
}
|
|
|
|
@MainActor
|
|
var all: [Ghostty.SurfaceView] {
|
|
// Find all of our terminal windows (includes quick terminal)
|
|
let controllers = NSApp.windows.compactMap {
|
|
$0.windowController as? BaseTerminalController
|
|
}
|
|
|
|
// Get all our surfaces
|
|
return controllers.reduce([]) { result, c in
|
|
result + (c.surfaceTree.root?.leaves() ?? [])
|
|
}
|
|
}
|
|
}
|