- Bump a terminal epoch when the deferred WASM setup finishes so the session sync effect re-runs against the live terminal even when no session field changed during the load, completing the exited-at-mount handling - Read config.ghostty as an alternate config file name and merge the XDG and macOS Application Support configs in Ghostty's load order instead of stopping at the first existing file
Unified · Split
| @@ -207,13 +207,25 @@ export const loadGhosttyTerminalStyle: Effect.Effect< · 206 unmodified lines | |||
| 207 | return undefined; | 207 | return undefined; |
| 208 | }); | 208 | }); |
| 209 | 209 | ||
| 210 | const configSource = yield* readFirstExisting([ | 210 | // Ghostty reads the XDG config first and the macOS Application Support |
| 211 | path.join(xdgConfigHome, "ghostty", "config"), | 211 | // config after it, so later files override earlier values. It also accepts |
| 212 | path.join(home, "Library", "Application Support", "com.mitchellh.ghostty", "config"), | 212 | // config.ghostty as the file name. Merge every location that exists instead |
| 213 | ]); | 213 | // of stopping at the first match. |
| 214 | if (configSource === undefined) return undefined; | 214 | const configDirs = [ |
| 215 | path.join(xdgConfigHome, "ghostty"), | ||
| 216 | path.join(home, "Library", "Application Support", "com.mitchellh.ghostty"), | ||
| 217 | ]; | ||
| 218 | const configSources: Array<string> = []; | ||
| 219 | for (const dir of configDirs) { | ||
| 220 | const source = yield* readFirstExisting([ | ||
| 221 | path.join(dir, "config"), | ||
| 222 | path.join(dir, "config.ghostty"), | ||
| 223 | ]); | ||
| 224 | if (source !== undefined) configSources.push(source); | ||
| 225 | } | ||
| 226 | if (configSources.length === 0) return undefined; | ||
| 215 | 227 | ||
| 216 | const config = parseGhosttyConfig(configSource); | 228 | const config = parseGhosttyConfig(configSources.join("\n")); |
| 217 | 229 | ||
| 218 | const loadThemeColors = (themeName: string) => | 230 | const loadThemeColors = (themeName: string) => |
| 219 | Effect.gen(function* () { | 231 | Effect.gen(function* () { |
| @@ -434,6 +434,10 @@ export function TerminalViewport({ · 433 unmodified lines | |||
| 434 | reportFailure: false, | 434 | reportFailure: false, |
| 435 | }); | 435 | }); |
| 436 | const hasHandledExitRef = useRef(false); | 436 | const hasHandledExitRef = useRef(false); |
| 437 | // Bumped when the async WASM gate finishes creating a terminal, so the | ||
| 438 | // session sync effect re-runs against the live terminal even when no | ||
| 439 | // session field changed while the WASM module was loading. | ||
| 440 | const [terminalEpoch, setTerminalEpoch] = useState(0); | ||
| 437 | const selectionPointerRef = useRef<{ x: number; y: number } | null>(null); | 441 | const selectionPointerRef = useRef<{ x: number; y: number } | null>(null); |
| 438 | const selectionGestureActiveRef = useRef(false); | 442 | const selectionGestureActiveRef = useRef(false); |
| 439 | const selectionActionRequestIdRef = useRef(0); | 443 | const selectionActionRequestIdRef = useRef(0); |
| @@ -549,6 +553,7 @@ export function TerminalViewport({ · 109 unmodified lines | |||
| 549 | status: "closed", | 553 | status: "closed", |
| 550 | version: 0, | 554 | version: 0, |
| 551 | }; | 555 | }; |
| 556 | setTerminalEpoch((value) => value + 1); | ||
| 552 | 557 | ||
| 553 | const clearSelectionAction = () => { | 558 | const clearSelectionAction = () => { |
| 554 | selectionActionRequestIdRef.current += 1; | 559 | selectionActionRequestIdRef.current += 1; |
| @@ -970,7 +975,7 @@ export function TerminalViewport({ · 415 unmodified lines | |||
| 970 | }); | 975 | }); |
| 971 | } | 976 | } |
| 972 | previousSessionRef.current = current; | 977 | previousSessionRef.current = current; |
| 973 | }, [autoFocus, terminalBuffer, terminalError, terminalStatus, terminalVersion]); | 978 | }, [autoFocus, terminalBuffer, terminalEpoch, terminalError, terminalStatus, terminalVersion]); |
| 974 | 979 | ||
| 975 | useEffect(() => { | 980 | useEffect(() => { |
| 976 | if (!autoFocus) return; | 981 | if (!autoFocus) return; |