Michael Albinus <[email protected]> writes:
Hi,
> I hope to have a first version of tramp-rename-remote-files ready this
> week, for playing. I would post a patch here, on top of Tramp 2.4.2.4.
I have implemented a very first shot, see appended patch. It is pretty
much alpha, it needs more careful testing, and it represents just where
I stand now. Improvements welcome, but stabilization first. Proper
documentation is also missing.
You can apply this patch on top of Tramp 2.4.2.4 from GNU ELPA. I guess
it would work also on top og Tramp 2.3, but I haven't tested yet.
The scenario I have tested so far is:
- I have some open buffers with files located in /ssh:bad:/tmp. I
believe this connection is broken, so I call "M-x tramp-rename-remote-files"
- "Enter old connection: /ssh:"
I complete this via TAB, until I have the remote connection "/ssh:bad:"
- Now, the next TAB gives me the longest common path of all buffers
connected to /ssh:bad: - this is "/ssh:bad:/tmp/".
- After RET, I get the prompt "Enter new Tramp connection: /ssh:". The
Tramp method of the old connection is offered as initial completion.
- Via usual minibuffer completion, I have "/ssh:good:/var/tmp/". I
confirm this with RET
- Now, the command goes through all buffers. Buffers which have a
buffer-file-name starting with the old name, "/ssh:bad:/tmp/", are
presented to me, plus the prompt "Set visited file name:
/ssh:good:/var/tmp/". Confirming this with RET, sets the new
name. This is editable, of course.
Well, that's it. The buffer file names are renamed, the buffers are
marked modified. Now you can save them (or not :-)
Happy testing! Any feedback is more than welcome.
>> Best,
>>
>> JD
Best regards, Michael.
diff --git a/lisp/tramp-cmds.el b/lisp/tramp-cmds.el
index 35bb85b8..333eb06d 100644
--- a/lisp/tramp-cmds.el
+++ b/lisp/tramp-cmds.el
@@ -195,6 +195,93 @@ This includes password cache, file cache, connection cache, buffers."
(dolist (name (tramp-list-remote-buffers))
(when (bufferp (get-buffer name)) (kill-buffer name))))
+;;;###tramp-autoload
+(defun tramp-rename-remote-files (source target &optional keep-connection)
+ "Replace in all buffers `buffer-file-name's SOURCE by TARGET.
+SOURCE is a remote directory name, which could contain also a
+localname part. TARGET is the directory name SOURCE is replaced
+with. Often, TARGET is also a remote file name on another
+machine, but it can also be a local file name.
+
+On all buffers, which have a `buffer-file-name' matching SOURCE,
+this name is modified by replacing SOURCE with TARGET. This is
+applied by calling `set-visited-file-name'. The buffers are
+marked modified, and must be saved explicitly.
+
+The remote connection identified by SOURCE is flushed by
+`tramp-cleanup-connection' unless there still exists buffers with
+a `buffer-file-name' pointing to this remote connection, or unless
+KEEP-CONNECTION is non-nil. Interactively, KEEP-CONNECTION is
+set to the prefix argument."
+ (interactive
+ (let ((connections
+ (mapcar #'tramp-make-tramp-file-name (tramp-list-connections)))
+ source target)
+ (if (null connections)
+ (tramp-user-error nil "There are no remote connections.")
+ (setq source
+ ;; Likely, the source remote connection is broken. So we
+ ;; shall avoid any action on it.
+ (let (non-essential)
+ (completing-read
+ "Enter old Tramp connection: "
+ ;; Completion function.
+ (completion-table-dynamic
+ (lambda (string)
+ (cond
+ ;; Initially, show existing remote connections.
+ ((not (tramp-tramp-file-p string))
+ (all-completions string connections))
+ ;; There is a selected remote connection. Show
+ ;; its longest common directory path of respective
+ ;; buffers.
+ (t (mapcar
+ (lambda (buffer)
+ (let ((bfn (buffer-file-name buffer)))
+ (and (buffer-live-p buffer)
+ (tramp-equal-remote string bfn)
+ (stringp bfn) (file-name-directory bfn))))
+ (tramp-list-remote-buffers))))))
+ #'tramp-tramp-file-p t
+ ;; If the current buffer is a remote one, it is likely
+ ;; that this connection is meant. So we offer it as
+ ;; initial value. Otherwise, use the longest remote
+ ;; connection path as initial value.
+ (or (file-remote-p default-directory nil t)
+ (try-completion "" connections))))
+
+ target
+ (read-file-name
+ "Enter new Tramp connection: "
+ ;; We use just the method name as initial value.
+ (substring
+ (tramp-make-tramp-file-name (file-remote-p source 'method t))
+ nil -1))))
+
+ (list source target current-prefix-arg)))
+
+ (unless (tramp-tramp-file-p source)
+ (tramp-user-error nil "Source %s must be remote." source))
+ (when (tramp-equal-remote source target)
+ (tramp-user-error nil "Source and target must have different remote."))
+
+ (let ((current-buffer (current-buffer)))
+ (dolist (buffer (tramp-list-remote-buffers))
+ (with-current-buffer buffer
+ (let ((bfn (buffer-file-name)))
+ (when (and (buffer-live-p buffer) (stringp bfn)
+ (file-in-directory-p bfn source))
+ (switch-to-buffer buffer)
+ (setq buffer-file-name
+ (replace-regexp-in-string
+ (regexp-quote source) target bfn)
+ default-directory
+ (replace-regexp-in-string
+ (regexp-quote source) target default-directory))
+ (call-interactively
+ 'set-visited-file-name)))))
+ (switch-to-buffer current-buffer)))
+
;; Tramp version is useful in a number of situations.
;;;###tramp-autoload