Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lisp/ghostel.el
Original file line number Diff line number Diff line change
Expand Up @@ -5197,7 +5197,8 @@ spawn after initialization."
DISPLAY-ACTION, when non-nil, is passed to `pop-to-buffer' before
terminal creation so size detection observes the window that will
display the terminal. Optional ROWS and COLS are passed through to
`ghostel--init-buffer'."
`ghostel--init-buffer'. If initialization is interrupted by an error
or quit, the partially created buffer is killed before re-signaling."
(let ((buffer (generate-new-buffer name)))
(condition-case err
(progn
Expand All @@ -5209,7 +5210,7 @@ display the terminal. Optional ROWS and COLS are passed through to
(pop-to-buffer buffer display-action))
(ghostel--init-buffer buffer rows cols)
buffer)
(error
((error quit)
(when (buffer-live-p buffer)
(kill-buffer buffer))
(signal (car err) (cdr err))))))
Expand Down
17 changes: 17 additions & 0 deletions test/ghostel-project-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,23 @@ same name must get separate buffers."
(when (buffer-live-p buf)
(kill-buffer buf)))))

(ert-deftest ghostel-test-create-kills-buffer-on-quit ()
"`ghostel--create' kills the partially created buffer on quit.
A keyboard quit can arrive during initialization, e.g. at a dir-locals
prompt in `ghostel-mode'. Uses `condition-case' directly since
`should-error' only traps `error', not `quit'."
(cl-letf (((symbol-function 'ghostel--init-buffer)
(lambda (&rest _) (signal 'quit nil))))
(unwind-protect
(progn
(should (eq 'quit
(condition-case err
(progn (ghostel--create " *ghostel-test-quit*") nil)
(quit (car err)))))
(should-not (get-buffer " *ghostel-test-quit*")))
(when-let* ((leftover (get-buffer " *ghostel-test-quit*")))
(kill-buffer leftover)))))

(ert-deftest ghostel-test-returns-buffer ()
"`ghostel' returns the (live) Ghostel buffer."
(let ((created (generate-new-buffer "*ghostel-return-test*"))
Expand Down
25 changes: 15 additions & 10 deletions test/ghostel-shell-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ newest-first list aligns with the buffer-order regions."
;; Send a real command before testing line editing. The initial
;; output may be a terminal query or startup redraw; waiting for
;; command output proves fish's reader is accepting input. Private
;; mode keeps history/autosuggestions from repainting `abc' after
;; it has been backspaced to `ab'.
;; mode keeps history/autosuggestions from repainting `wxyz' after
;; it has been backspaced to `wxy'.
(ghostel--write-pty ghostel--term
"printf '%s%s\\n' GHOSTEL_FISH _READY\n")
(ghostel-test--wait-until
Expand All @@ -129,25 +129,30 @@ newest-first list aligns with the buffer-order regions."
(ghostel-test--rendered-terminal-text)))
proc 10)

;; Type "abc" then backspace.
(ghostel--write-pty ghostel--term "abc")
;; Type "wxyz" then backspace. The typed text must
;; contain letters outside [0-9a-f]: fish's default
;; prompt shows the checkout's VCS state, and on a
;; detached HEAD (as in CI) that is the short commit
;; sha, so a hex-only marker can appear verbatim in
;; the prompt and never leave the screen.
(ghostel--write-pty ghostel--term "wxyz")
(ghostel-test--wait-until
(lambda ()
(string-match-p "abc" (ghostel-test--rendered-terminal-text)))
(string-match-p "wxyz" (ghostel-test--rendered-terminal-text)))
proc 5)
(should (string-match-p "abc" (ghostel-test--rendered-terminal-text)))
(should (string-match-p "wxyz" (ghostel-test--rendered-terminal-text)))

;; Send backspace (\x7f) and verify it works.
(ghostel--write-pty ghostel--term "\x7f")
(ghostel-test--wait-until
(lambda ()
(let ((state (ghostel-test--rendered-terminal-text)))
(and (string-match-p "ab" state)
(not (string-match-p "abc" state)))))
(and (string-match-p "wxy" state)
(not (string-match-p "wxyz" state)))))
proc 5)
(let ((state (ghostel-test--rendered-terminal-text)))
(should (string-match-p "ab" state))
(should-not (string-match-p "abc" state)))))))
(should (string-match-p "wxy" state))
(should-not (string-match-p "wxyz" state)))))))

(ert-deftest ghostel-test-fish-auto-inject-loads-integration ()
"Fish auto-inject shim chains to ghostel.fish and cleans XDG_DATA_DIRS."
Expand Down
Loading