mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-05 19:08:17 +00:00
macos: new terminal intent
This commit is contained in:
@@ -120,6 +120,8 @@
|
||||
A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E112942AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift */; };
|
||||
A5E112972AF7401B00C6E0C2 /* ClipboardConfirmationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E112962AF7401B00C6E0C2 /* ClipboardConfirmationView.swift */; };
|
||||
A5E4082A2E022E9E0035FEAC /* TabGroupCloseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408292E022E9B0035FEAC /* TabGroupCloseCoordinator.swift */; };
|
||||
A5E4082E2E0237460035FEAC /* NewTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E4082D2E0237410035FEAC /* NewTerminalIntent.swift */; };
|
||||
A5E408302E0271320035FEAC /* GhosttyIntentError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */; };
|
||||
A5FEB3002ABB69450068369E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FEB2FF2ABB69450068369E /* main.swift */; };
|
||||
AEE8B3452B9AA39600260C5E /* NSPasteboard+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */; };
|
||||
C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; };
|
||||
@@ -240,6 +242,8 @@
|
||||
A5E112942AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardConfirmationController.swift; sourceTree = "<group>"; };
|
||||
A5E112962AF7401B00C6E0C2 /* ClipboardConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardConfirmationView.swift; sourceTree = "<group>"; };
|
||||
A5E408292E022E9B0035FEAC /* TabGroupCloseCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabGroupCloseCoordinator.swift; sourceTree = "<group>"; };
|
||||
A5E4082D2E0237410035FEAC /* NewTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewTerminalIntent.swift; sourceTree = "<group>"; };
|
||||
A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyIntentError.swift; sourceTree = "<group>"; };
|
||||
A5FEB2FF2ABB69450068369E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSPasteboard+Extension.swift"; sourceTree = "<group>"; };
|
||||
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = "<group>"; };
|
||||
@@ -299,6 +303,7 @@
|
||||
A56D58872ACDE6BE00508D2C /* Services */,
|
||||
A59630982AEE1C4400D64628 /* Terminal */,
|
||||
A5CBD05A2CA0C5910017A1AE /* QuickTerminal */,
|
||||
A5E4082C2E0237270035FEAC /* App Intents */,
|
||||
A5E112912AF73E4D00C6E0C2 /* ClipboardConfirmation */,
|
||||
A57D79252C9C8782001D522E /* Secure Input */,
|
||||
A58636622DEF955100E04A10 /* Splits */,
|
||||
@@ -598,6 +603,15 @@
|
||||
path = ClipboardConfirmation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A5E4082C2E0237270035FEAC /* App Intents */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A5E4082D2E0237410035FEAC /* NewTerminalIntent.swift */,
|
||||
A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */,
|
||||
);
|
||||
path = "App Intents";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -777,8 +791,10 @@
|
||||
A56D58862ACDDB4100508D2C /* Ghostty.Shell.swift in Sources */,
|
||||
A5985CD72C320C4500C57AD3 /* String+Extension.swift in Sources */,
|
||||
A5A2A3CC2D444ABB0033CF96 /* NSApplication+Extension.swift in Sources */,
|
||||
A5E408302E0271320035FEAC /* GhosttyIntentError.swift in Sources */,
|
||||
A5FEB3002ABB69450068369E /* main.swift in Sources */,
|
||||
A53A297F2DB4480F00B6E02C /* EventModifiers+Extension.swift in Sources */,
|
||||
A5E4082E2E0237460035FEAC /* NewTerminalIntent.swift in Sources */,
|
||||
A53A297B2DB2E49700B6E02C /* CommandPalette.swift in Sources */,
|
||||
A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */,
|
||||
A51B78472AF4B58B00F3EDB9 /* TitlebarTabsVenturaTerminalWindow.swift in Sources */,
|
||||
|
@@ -167,7 +167,7 @@ class AppDelegate: NSObject,
|
||||
|
||||
// This registers the Ghostty => Services menu to exist.
|
||||
NSApp.servicesMenu = menuServices
|
||||
|
||||
|
||||
// Setup a local event monitor for app-level keyboard shortcuts. See
|
||||
// localEventHandler for more info why.
|
||||
_ = NSEvent.addLocalMonitorForEvents(
|
||||
|
@@ -0,0 +1,9 @@
|
||||
enum GhosttyIntentError: Error, CustomLocalizedStringResourceConvertible {
|
||||
case appUnavailable
|
||||
|
||||
var localizedStringResource: LocalizedStringResource {
|
||||
switch self {
|
||||
case .appUnavailable: return "The Ghostty app isn't properly initialized."
|
||||
}
|
||||
}
|
||||
}
|
81
macos/Sources/Features/App Intents/NewTerminalIntent.swift
Normal file
81
macos/Sources/Features/App Intents/NewTerminalIntent.swift
Normal file
@@ -0,0 +1,81 @@
|
||||
import AppKit
|
||||
import AppIntents
|
||||
|
||||
/// App intent that allows creating a new terminal window or tab.
|
||||
///
|
||||
/// This requires macOS 15 or greater because we use features of macOS 15 here.
|
||||
@available(macOS 15.0, *)
|
||||
struct NewTerminalIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "New Terminal"
|
||||
static var description = IntentDescription("Create a new terminal.")
|
||||
|
||||
@Parameter(
|
||||
title: "Location",
|
||||
description: "The location that the terminal should be created.",
|
||||
default: .window
|
||||
)
|
||||
var location: NewTerminalLocation
|
||||
|
||||
@Parameter(
|
||||
title: "Working Directory",
|
||||
description: "The working directory to open in the terminal.",
|
||||
supportedContentTypes: [.folder]
|
||||
)
|
||||
var workingDirectory: IntentFile?
|
||||
|
||||
@available(macOS 26.0, *)
|
||||
static var supportedModes: IntentModes = .foreground(.immediate)
|
||||
|
||||
@available(macOS, obsoleted: 26.0, message: "Replaced by supportedModes")
|
||||
static var openAppWhenRun = true
|
||||
|
||||
static var parameterSummary: some ParameterSummary {
|
||||
Summary("New Terminal \(\.$location)")
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func perform() async throws -> some IntentResult {
|
||||
guard let appDelegate = NSApp.delegate as? AppDelegate else {
|
||||
throw GhosttyIntentError.appUnavailable
|
||||
}
|
||||
|
||||
var config = Ghostty.SurfaceConfiguration()
|
||||
|
||||
// If we were given a working directory then open that directory
|
||||
if let url = workingDirectory?.fileURL {
|
||||
let dir = url.hasDirectoryPath ? url : url.deletingLastPathComponent()
|
||||
config.workingDirectory = dir.path(percentEncoded: false)
|
||||
}
|
||||
|
||||
switch location {
|
||||
case .window:
|
||||
_ = TerminalController.newWindow(
|
||||
appDelegate.ghostty,
|
||||
withBaseConfig: config)
|
||||
|
||||
case .tab:
|
||||
_ = TerminalController.newTab(
|
||||
appDelegate.ghostty,
|
||||
from: TerminalController.preferredParent?.window,
|
||||
withBaseConfig: config)
|
||||
}
|
||||
|
||||
return .result()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: NewTerminalLocation
|
||||
|
||||
enum NewTerminalLocation: String {
|
||||
case tab
|
||||
case window
|
||||
}
|
||||
|
||||
extension NewTerminalLocation: AppEnum {
|
||||
static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Terminal Location")
|
||||
|
||||
static var caseDisplayRepresentations: [Self: DisplayRepresentation] = [
|
||||
.tab: .init(title: "Tab"),
|
||||
.window: .init(title: "Window"),
|
||||
]
|
||||
}
|
@@ -169,7 +169,7 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr
|
||||
private static var lastCascadePoint = NSPoint(x: 0, y: 0)
|
||||
|
||||
// The preferred parent terminal controller.
|
||||
private static var preferredParent: TerminalController? {
|
||||
static var preferredParent: TerminalController? {
|
||||
all.first {
|
||||
$0.window?.isMainWindow ?? false
|
||||
} ?? all.last
|
||||
|
Reference in New Issue
Block a user