reddit / emacs

vterm: do not query on exit flag if there is no subprocess running

richardvandesorge · 2022-05-26 13:19
I don't know if there are other solutions around to achieve this, but I use vterm rather often and was annoyed by the query-on-exit whenever I tried to kill Emacs. The behavior I want is to be asked for confirmation when trying to kill Emacs while a vterm process is running some subprocess, otherwise not being bothered (the same as with regular terminal emulators). Here is the code I wrote: (defun my/process-has-subprocesses (process &optional print-message) "Determine if PROCESS has a subprocess. Display message in the echo area if PRINT-MESSAGE is true. If used interactively, PROCESS is the process from the current buffer." (interactive (list (get-buffer-process (current-buffer)) t)) (if process (let ((pstree-out (shell-command-to-string (format "pstree %d" (process-id process))))) (if (string-match-p (regexp-quote "-") pstree-out) (progn (when print-message (message "t")) t) (when print-message (message "nil")) nil)) (when print-message (message "No process")) nil) ) (define-advice save-buffers-kill-emacs (:around (orig-foo &rest args) my/unset-process-query-on-exit-flag-if-no-subprocesses) ;; Set process-query-on-exit-flag to nil for each ;; vterm process which does not currently have any ;; subprocess running. (interactive "P") (let ((changed-procs) (orig-flags)) (when (boundp 'multi-vterm-buffer-list) (dolist (buffer multi-vterm-buffer-list) (let ((proc (get-buffer-process buffer))) (when (and (processp proc) (not (my/process-has-subprocesses proc))) ;; Store original flags and respective processes to be restored in case Emacs is not killed (push proc changed-procs) (push (process-query-on-exit-flag proc) orig-flags) (set-process-query-on-exit-flag proc nil))))) (let ((res (apply orig-foo args))) ;; If Emacs was not killed, restore original flags (when (not res) (let ((changed-procs-orig-flags (-zip changed-procs orig-flags))) (dolist (proc-and-flag changed-procs-orig-flags) (set-process-query-on-exit-flag (car proc-and-flag) (cdr proc-and-flag)))))))) I implemented a similar solution for dealing with the same issue when using `kill-buffer` . Also, my elisp is not great and at present I only learn on the go whenever I feel the need to change my init.el, so in case you see something which can be rewritten in a better way, I will appreciate all the suggestions.
_viz_ · 2022-05-28 06:53
(defun vz/shell-inside-p (&optional buffer) "Return t if the current \"active\" process is a shell. If BUFFER is nil, the current buffer is used instead." (let ((it (process-running-child-p (get-buffer-process (or buffer (current-buffer)))))) (or (null it) (equal (alist-get 'comm (process-attributes it)) (file-name-base explicit-shell-file-name))))) I use this function to check if there are no subprocesses running in a *shell* buffer. The second condition is needed to check if the subprocess is not another shell instance (in my case, it would be due to nix-shell).
richardvandesorge · 2022-05-28 07:41
Nice! `process-running-child-p` completely slipped under my radar when I did my googling on how to get that info, that's why I had resorted to using a shell command. Thanks for sharing it.