mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-05-24 13:50:11 +00:00
macOS: check abnormal-command-exit-runtime when process exits (#12393)
<img width="849" height="434" alt="image" src="https://github.com/user-attachments/assets/81c89d8d-6f0a-4bb9-b942-6734ff616bf9" />
This commit is contained in:
@@ -1649,7 +1649,8 @@ extension Ghostty {
|
||||
// We handle this when the window is visible and timetime_ms is greater than 0,
|
||||
// which will rule out exit codes on launch
|
||||
guard surfaceView.window != nil, v.timetime_ms > 0 else { return false }
|
||||
surfaceView.setChildExitedMessage(.init(v))
|
||||
guard let config = (NSApplication.shared.delegate as? AppDelegate)?.ghostty.config else { return false }
|
||||
surfaceView.setChildExitedMessage(.init(v, threshold: config.abnormalCommandExitRuntime))
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -10,14 +10,32 @@ extension Ghostty {
|
||||
let text: String
|
||||
let level: Level
|
||||
|
||||
init(_ message: ghostty_surface_message_childexited_s) {
|
||||
init(_ message: ghostty_surface_message_childexited_s, threshold abnormalCommandExitRuntime: Duration) {
|
||||
var level: Level
|
||||
switch Int(message.exit_code) {
|
||||
case Int(EXIT_SUCCESS):
|
||||
level = .success
|
||||
default:
|
||||
level = .error
|
||||
}
|
||||
text = "Process exited. Press any key to close the terminal."
|
||||
// See: Surface.zig/childExited
|
||||
// If our runtime was below some threshold then we assume that this
|
||||
// was an abnormal exit and we show an error message.
|
||||
if abnormalCommandExitRuntime >= .milliseconds(message.timetime_ms) {
|
||||
level = .error
|
||||
let measure = Measurement.init(value: Double(message.timetime_ms), unit: UnitDuration.milliseconds)
|
||||
let formatter = MeasurementFormatter()
|
||||
if message.timetime_ms > 1000 {
|
||||
formatter.unitOptions = .naturalScale
|
||||
} else {
|
||||
formatter.unitOptions = .providedUnit
|
||||
}
|
||||
formatter.locale = .init(identifier: "en_US")
|
||||
text = "Process exited after **`\(formatter.string(from: measure))`**. Press any key to close the terminal."
|
||||
} else {
|
||||
text = "Process exited. Press any key to close the terminal."
|
||||
}
|
||||
self.level = level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,6 +709,16 @@ extension Ghostty {
|
||||
return MacShortcuts(rawValue: str) ?? defaultValue
|
||||
}
|
||||
|
||||
var abnormalCommandExitRuntime: Duration {
|
||||
let defaultValue: Duration = .milliseconds(250)
|
||||
guard let config = self.config else { return defaultValue }
|
||||
var v: UInt32?
|
||||
let key = "abnormal-command-exit-runtime"
|
||||
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
|
||||
guard let v else { return defaultValue }
|
||||
return .milliseconds(v)
|
||||
}
|
||||
|
||||
var scrollbar: Scrollbar {
|
||||
let defaultValue = Scrollbar.system
|
||||
guard let config = self.config else { return defaultValue }
|
||||
|
||||
@@ -6,8 +6,7 @@ struct ChildExitedMessageBar: View {
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 6) {
|
||||
Text(msg.text)
|
||||
.fontWeight(.medium)
|
||||
Text(message)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
@@ -28,6 +27,10 @@ struct ChildExitedMessageBar: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var message: AttributedString {
|
||||
(try? AttributedString(markdown: msg.text)) ?? AttributedString(msg.text)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Ghostty.ChildExitedMessage.Level {
|
||||
|
||||
Reference in New Issue
Block a user