From 6c79f37b98b45fb0fd1721ea5d5d9b6752ad64e2 Mon Sep 17 00:00:00 2001 From: shipmints Date: Tue, 25 Feb 2025 11:34:49 +0100 Subject: [PATCH] Add tramp-cleanup-bufferless-connections (bug#76417) * doc/misc/tramp.texi (Cleanup remote connections): Add 'tramp-cleanup-bufferless-connections'. * etc/NEWS: Announce 'tramp-cleanup-bufferless-connections'. * lisp/net/tramp-cmds.el: (tramp-list-remote-buffer-connections): New function. (tramp-cleanup-bufferless-connections): New command. (tramp-list-remote-buffers): Account for 'buffer-file-name'. (cherry picked from commit bea00a07990ebfbe420636363f8d3514571ae79d) --- doc/misc/tramp.texi | 17 ++++++++++++++-- lisp/net/tramp-cmds.el | 45 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 247bbdf1262..bfbe96ca665 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -4773,13 +4773,13 @@ proxy definitions (@pxref{Ad-hoc multi-hops}). @deffn Command tramp-cleanup-all-buffers Just as for @code{tramp-cleanup-all-connections}, all remote -connections and ad-hoc proxy definition are cleaned up in addition to +connections and ad-hoc proxy definitions are cleaned up in addition to killing all buffers related to remote connections. @end deffn @deffn Command tramp-cleanup-some-buffers Similar to @code{tramp-cleanup-all-buffers}, where all remote -connections and ad-hoc proxy definition are cleaned up. However, +connections and ad-hoc proxy definitions are cleaned up. However, additional buffers are killed only if one of the functions in @code{tramp-cleanup-some-buffers-hook} returns @code{t}. @end deffn @@ -4791,6 +4791,19 @@ remote buffers which are linked to a remote file, remote @code{dired} buffers, and buffers related to a remote process are cleaned up. @end defopt +@deffn Command tramp-cleanup-bufferless-connections + +Similar to @code{tramp-cleanup-all-connections}, remote connections and +ad-hoc proxy definitions are flushed, but limited to those connections +for which no associated buffers exist (except for Tramp internal +buffers). + +This command is helpful to prune connections after you close remote-file +buffers without having to either cherry pick via +@code{tramp-cleanup-connection} or clear them all via +@code{tramp-cleanup-all-connections}. +@end deffn + @node Renaming remote files @section Renaming remote files diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 7d88fcefb34..c5e2bf1b3c3 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -99,12 +99,35 @@ SYNTAX can be one of the symbols `default' (default), ;; Use `match-buffers' starting with Emacs 29.1. ;;;###tramp-autoload (defun tramp-list-remote-buffers () - "Return a list of all buffers with remote `default-directory'." + "Return a list of remote buffers, excluding internal tramp buffers. +A buffer is considered remote if either its `default-directory' or its +buffer file name is a remote file name." (tramp-compat-seq-keep - (lambda (x) - (when (tramp-tramp-file-p (tramp-get-default-directory x)) x)) + (lambda (buffer) + (when (tramp-tramp-file-p + (or (buffer-file-name buffer) + (tramp-get-default-directory buffer))) + buffer)) (buffer-list))) +;;;###tramp-autoload +(defun tramp-list-remote-buffer-connections () + "Return a list of all remote buffer connections. +A buffer is considered remote if either its `default-directory' or the +function `buffer-file-name' is a remote file name." + (seq-uniq + (mapcar (lambda (buffer) + (or + (when (buffer-file-name buffer) + (file-remote-p (buffer-file-name buffer))) + (when (tramp-get-default-directory buffer) + (file-remote-p (tramp-get-default-directory buffer))))) + ;; Eliminate false positives from internal tramp buffers + (seq-remove + (lambda (buffer) + (member (buffer-name buffer) (tramp-list-tramp-buffers))) + (tramp-list-remote-buffers))))) + ;;; Cleanup ;;;###tramp-autoload @@ -319,6 +342,22 @@ non-nil." (let ((tramp-cleanup-some-buffers-hook '(always))) (tramp-cleanup-some-buffers))) +;;;###tramp-autoload +(defun tramp-cleanup-bufferless-connections () + "Flush connection-related objects for which no buffer exists. +A bufferless connection is one for which no live buffer's +`buffer-file-name' or `default-directory' is associated with that +connection, except for Tramp internal buffers. +Display a message of cleaned-up connections." + (interactive) + (when-let* ((bufferless-connections + (seq-difference + (mapcar #'tramp-make-tramp-file-name (tramp-list-connections)) + (tramp-list-remote-buffer-connections)))) + (message "Cleaning up %s" (mapconcat #'identity bufferless-connections ", ")) + (dolist (connection bufferless-connections) + (tramp-cleanup-connection (tramp-dissect-file-name connection 'noexpand))))) + ;;; Rename (defcustom tramp-default-rename-alist nil -- 2.39.5