diff options
| author | Michael Albinus | 2019-11-20 13:45:30 +0100 |
|---|---|---|
| committer | Michael Albinus | 2019-11-20 13:45:30 +0100 |
| commit | 035931777bd89b939436fd1d8a2b8d5a80ede095 (patch) | |
| tree | b0ce714884bc106eaa95415754e807cb40c761e6 | |
| parent | 5c5c1b559313d06aab6516ff1b1acf1da3a01c7d (diff) | |
| download | emacs-035931777bd89b939436fd1d8a2b8d5a80ede095.tar.gz emacs-035931777bd89b939436fd1d8a2b8d5a80ede095.zip | |
Add renaming of remote buffer file names to Tramp
* doc/misc/tramp.texi (Default User): Fix typo.
(Cleanup remote connections): Adapt arguments of
`tramp-cleanup-connection'.
(Renaming remote files): New node.
(Frequently Asked Questions): New item "How to save files when a
remote host isn't reachable anymore?".
* etc/NEWS: Add `tramp-rename-files' and `tramp-rename-these-files'.
* lisp/net/tramp-cmds.el (tramp-default-rename-alist)
(tramp-confirm-rename-file-names): New defcustoms.
(tramp-rename-read-file-name-dir)
(tramp-rename-read-file-name-init): New defsubsts.
(tramp-default-rename-file, tramp-rename-files)
(tramp-rename-these-files): New defuns.
* lisp/net/tramp-integration.el (ido, ivy): Integrate with them.
| -rw-r--r-- | doc/misc/tramp.texi | 140 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/net/tramp-cmds.el | 267 | ||||
| -rw-r--r-- | lisp/net/tramp-integration.el | 16 |
4 files changed, 416 insertions, 12 deletions
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 67472a87a32..dd1378a8da7 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi | |||
| @@ -153,6 +153,7 @@ Using @value{tramp} | |||
| 153 | * Ad-hoc multi-hops:: Declaring multiple hops in the file name. | 153 | * Ad-hoc multi-hops:: Declaring multiple hops in the file name. |
| 154 | * Remote processes:: Integration with other Emacs packages. | 154 | * Remote processes:: Integration with other Emacs packages. |
| 155 | * Cleanup remote connections:: Cleanup remote connections. | 155 | * Cleanup remote connections:: Cleanup remote connections. |
| 156 | * Renaming remote files:: Renaming remote files. | ||
| 156 | * Archive file names:: Access to files in file archives. | 157 | * Archive file names:: Access to files in file archives. |
| 157 | 158 | ||
| 158 | How file names, directories and localnames are mangled and managed | 159 | How file names, directories and localnames are mangled and managed |
| @@ -1409,7 +1410,7 @@ use the @samp{john} as the default user for the domain | |||
| 1409 | A Caution: @value{tramp} will override any default user specified in | 1410 | A Caution: @value{tramp} will override any default user specified in |
| 1410 | the configuration files outside Emacs, such as @file{~/.ssh/config}. | 1411 | the configuration files outside Emacs, such as @file{~/.ssh/config}. |
| 1411 | To stop @value{tramp} from applying the default value, set the | 1412 | To stop @value{tramp} from applying the default value, set the |
| 1412 | corresponding alist entry to nil: | 1413 | corresponding alist entry to @code{nil}: |
| 1413 | 1414 | ||
| 1414 | @lisp | 1415 | @lisp |
| 1415 | @group | 1416 | @group |
| @@ -2710,6 +2711,7 @@ is a feature of Emacs that may cause missed prompts when using | |||
| 2710 | * Ad-hoc multi-hops:: Declaring multiple hops in the file name. | 2711 | * Ad-hoc multi-hops:: Declaring multiple hops in the file name. |
| 2711 | * Remote processes:: Integration with other Emacs packages. | 2712 | * Remote processes:: Integration with other Emacs packages. |
| 2712 | * Cleanup remote connections:: Cleanup remote connections. | 2713 | * Cleanup remote connections:: Cleanup remote connections. |
| 2714 | * Renaming remote files:: Renaming remote files. | ||
| 2713 | * Archive file names:: Access to files in file archives. | 2715 | * Archive file names:: Access to files in file archives. |
| 2714 | @end menu | 2716 | @end menu |
| 2715 | 2717 | ||
| @@ -3371,9 +3373,9 @@ To open @command{powershell} as a remote shell, use this: | |||
| 3371 | 3373 | ||
| 3372 | @value{tramp} provides several ways to flush remote connections. | 3374 | @value{tramp} provides several ways to flush remote connections. |
| 3373 | 3375 | ||
| 3374 | @deffn Command tramp-cleanup-connection vec | 3376 | @deffn Command tramp-cleanup-connection vec &optional keep-debug keep-password |
| 3375 | This command flushes all connection related objects. @option{vec} is | 3377 | This command flushes all connection related objects. @var{vec} is the |
| 3376 | the internal representation of a remote connection. When called | 3378 | internal representation of a remote connection. When called |
| 3377 | interactively, this command lists active remote connections in the | 3379 | interactively, this command lists active remote connections in the |
| 3378 | minibuffer. Each connection is of the format | 3380 | minibuffer. Each connection is of the format |
| 3379 | @file{@trampfn{method,user@@host,}}. | 3381 | @file{@trampfn{method,user@@host,}}. |
| @@ -3383,11 +3385,14 @@ Flushing remote connections also cleans the password cache | |||
| 3383 | (@pxref{Connection caching}), and recentf cache (@pxref{File | 3385 | (@pxref{Connection caching}), and recentf cache (@pxref{File |
| 3384 | Conveniences, , , emacs}). It also deletes session timers | 3386 | Conveniences, , , emacs}). It also deletes session timers |
| 3385 | (@pxref{Predefined connection information}) and connection buffers. | 3387 | (@pxref{Predefined connection information}) and connection buffers. |
| 3388 | |||
| 3389 | If @var{keep-debug} is non-@code{nil}, the debug buffer is kept. A | ||
| 3390 | non-@code{nil} @var{keep-password} preserves the password cache. | ||
| 3386 | @end deffn | 3391 | @end deffn |
| 3387 | 3392 | ||
| 3388 | @deffn Command tramp-cleanup-this-connection | 3393 | @deffn Command tramp-cleanup-this-connection |
| 3389 | Flushes only the current buffer's remote connection objects, the same | 3394 | Flushes the current buffer's remote connection objects, the same as in |
| 3390 | as in @code{tramp-cleanup-connection}. | 3395 | @code{tramp-cleanup-connection}. |
| 3391 | @end deffn | 3396 | @end deffn |
| 3392 | 3397 | ||
| 3393 | @deffn Command tramp-cleanup-all-connections | 3398 | @deffn Command tramp-cleanup-all-connections |
| @@ -3404,6 +3409,112 @@ killing all buffers related to remote connections. | |||
| 3404 | @end deffn | 3409 | @end deffn |
| 3405 | 3410 | ||
| 3406 | 3411 | ||
| 3412 | @node Renaming remote files | ||
| 3413 | @section Renaming remote files | ||
| 3414 | @cindex save remote files | ||
| 3415 | |||
| 3416 | Sometimes, it is desirable to safe file contents of buffers visiting a | ||
| 3417 | given remote host. This could happen for example, if the local host | ||
| 3418 | changes its network integration, and the remote host is not reachable | ||
| 3419 | anymore. | ||
| 3420 | |||
| 3421 | @deffn Command tramp-rename-files source target | ||
| 3422 | Replace in all buffers the visiting file name from @var{source} to | ||
| 3423 | @var{target}. @var{source} is a remote directory name, which could | ||
| 3424 | contain also a localname part. @var{target} is the directory name | ||
| 3425 | @var{source} is replaced with. Often, @var{target} is a remote | ||
| 3426 | directory name on another host, but it can also be a local directory | ||
| 3427 | name. If @var{target} has no local part, the local part from | ||
| 3428 | @var{source} is used. | ||
| 3429 | |||
| 3430 | If @var{target} is @code{nil}, it is selected according to the first | ||
| 3431 | match in @code{tramp-default-rename-alist}. If called interactively, | ||
| 3432 | this match is offered as initial value for selection. | ||
| 3433 | |||
| 3434 | On all buffers, which have a @code{buffer-file-name} matching | ||
| 3435 | @var{source}, this name is modified by replacing @var{source} with | ||
| 3436 | @var{target}. This is applied by calling | ||
| 3437 | @code{set-visited-file-name}. The new @code{buffer-file-name} is | ||
| 3438 | prompted for modification in the minibuffer. The buffers are marked | ||
| 3439 | modified, and must be saved explicitly. | ||
| 3440 | |||
| 3441 | If user option @code{tramp-confirm-rename-file-names} is nil, changing | ||
| 3442 | the file name happens without confirmation. This requires a | ||
| 3443 | matching entry in @code{tramp-default-rename-alist}. | ||
| 3444 | |||
| 3445 | Remote buffers related to the remote connection identified by | ||
| 3446 | @var{source}, which are not visiting files, or which are visiting | ||
| 3447 | files not matching @var{source}, are not modified. | ||
| 3448 | |||
| 3449 | Interactively, @var{target} is selected from | ||
| 3450 | @code{tramp-default-rename-alist} without confirmation if the prefix | ||
| 3451 | argument is non-@code{nil}. | ||
| 3452 | |||
| 3453 | The remote connection identified by @var{source} is flushed by | ||
| 3454 | @code{tramp-cleanup-connection}. | ||
| 3455 | @end deffn | ||
| 3456 | |||
| 3457 | @deffn Command tramp-rename-these-files target | ||
| 3458 | Replace visiting file names to @var{target}. The current buffer must | ||
| 3459 | be related to a remote connection. In all buffers, which are visiting | ||
| 3460 | a file with the same directory name, the buffer file name is changed. | ||
| 3461 | |||
| 3462 | Interactively, @var{target} is selected from | ||
| 3463 | @code{tramp-default-rename-alist} without confirmation if the prefix | ||
| 3464 | argument is non-@code{nil}. | ||
| 3465 | @end deffn | ||
| 3466 | |||
| 3467 | @defopt tramp-default-rename-alist | ||
| 3468 | The default target for renaming remote buffer file names. This is an | ||
| 3469 | alist of cons cells @code{(source . target)}. The first matching item | ||
| 3470 | specifies the target to be applied for renaming buffer file names from | ||
| 3471 | source via @code{tramp-rename-files}. @code{source} is a regular | ||
| 3472 | expressions, which matches a remote file name. @code{target} must be | ||
| 3473 | a directory name, which could be remote (including remote directories | ||
| 3474 | Tramp infers by default, such as @samp{@trampfn{method,user@@host,}}). | ||
| 3475 | |||
| 3476 | @code{target} can contain the patterns @code{%m}, @code{%u} or | ||
| 3477 | @code{%h}, which are replaced by the method name, user name or host | ||
| 3478 | name of @code{source} when calling @code{tramp-rename-files}. | ||
| 3479 | |||
| 3480 | @code{source} could also be a Lisp form, which will be evaluated. The | ||
| 3481 | result must be a string or nil, which is interpreted as a regular | ||
| 3482 | expression which always matches. | ||
| 3483 | |||
| 3484 | Example entries: | ||
| 3485 | |||
| 3486 | @lisp | ||
| 3487 | @group | ||
| 3488 | ("@trampfn{ssh,badhost,/path/to/dir/}" | ||
| 3489 | . "@trampfn{ssh,goodhost,/path/to/another/dir/}") | ||
| 3490 | @end group | ||
| 3491 | @end lisp | ||
| 3492 | |||
| 3493 | would trigger renaming of buffer file names on @samp{badhost} to | ||
| 3494 | @samp{goodhost}, including changing the directory name. | ||
| 3495 | |||
| 3496 | @lisp | ||
| 3497 | ("@trampfn{ssh,.+\\\\.company\\\\.org,}" . "@value{prefix}ssh@value{postfixhop}multi.hop|ssh@value{postfixhop}%h@value{postfix}") | ||
| 3498 | @end lisp | ||
| 3499 | |||
| 3500 | routes all connections to a host in @samp{company.org} via | ||
| 3501 | @samp{@trampfn{ssh,multi.hop,}}, which might be useful when using | ||
| 3502 | Emacs outside the company network. | ||
| 3503 | |||
| 3504 | @lisp | ||
| 3505 | (nil . "~/saved-files/%m:%u@@%h/") | ||
| 3506 | @end lisp | ||
| 3507 | |||
| 3508 | saves all remote files locally, with a directory name including method | ||
| 3509 | name, user name and host name of the remote connection. | ||
| 3510 | @end defopt | ||
| 3511 | |||
| 3512 | @defopt tramp-confirm-rename-file-names | ||
| 3513 | Whether renaming a buffer file name by @code{tramp-rename-files} or | ||
| 3514 | @code{tramp-rename-these-files} must be confirmed. | ||
| 3515 | @end defopt | ||
| 3516 | |||
| 3517 | |||
| 3407 | @node Archive file names | 3518 | @node Archive file names |
| 3408 | @section Archive file names | 3519 | @section Archive file names |
| 3409 | @cindex file archives | 3520 | @cindex file archives |
| @@ -3412,7 +3523,7 @@ killing all buffers related to remote connections. | |||
| 3412 | @cindex archive method | 3523 | @cindex archive method |
| 3413 | 3524 | ||
| 3414 | @value{tramp} offers also transparent access to files inside file | 3525 | @value{tramp} offers also transparent access to files inside file |
| 3415 | archives. This is possible only on machines which have installed | 3526 | archives. This is possible only on hosts which have installed |
| 3416 | @acronym{GVFS, the GNOME Virtual File System}, @ref{GVFS-based | 3527 | @acronym{GVFS, the GNOME Virtual File System}, @ref{GVFS-based |
| 3417 | methods}. Internally, file archives are mounted via the | 3528 | methods}. Internally, file archives are mounted via the |
| 3418 | @acronym{GVFS} @option{archive} method. | 3529 | @acronym{GVFS} @option{archive} method. |
| @@ -4440,6 +4551,21 @@ the buffer is remote. See the optional arguments of | |||
| 4440 | 4551 | ||
| 4441 | 4552 | ||
| 4442 | @item | 4553 | @item |
| 4554 | How to save files when a remote host isn't reachable anymore? | ||
| 4555 | |||
| 4556 | If the local machine Emacs is running on changes its network | ||
| 4557 | integration, remote hosts could become unreachable. This happens for | ||
| 4558 | example, if the local machine is moved between your office and your | ||
| 4559 | home without restarting Emacs. | ||
| 4560 | |||
| 4561 | In such cases, the command @code{tramp-rename-files} can be used to | ||
| 4562 | alter remote buffers’ method, host, and/or directory names. This | ||
| 4563 | permits saving their contents in the same location via another network | ||
| 4564 | path, or somewhere else entirely (including locally). @pxref{Renaming | ||
| 4565 | remote files}. | ||
| 4566 | |||
| 4567 | |||
| 4568 | @item | ||
| 4443 | How to disable other packages from calling @value{tramp}? | 4569 | How to disable other packages from calling @value{tramp}? |
| 4444 | 4570 | ||
| 4445 | There are packages that call @value{tramp} without the user ever | 4571 | There are packages that call @value{tramp} without the user ever |
| @@ -1837,6 +1837,11 @@ possible to configure the remote login shell. This avoids problems | |||
| 1837 | with remote hosts, where "/bin/sh" is a link to a shell which | 1837 | with remote hosts, where "/bin/sh" is a link to a shell which |
| 1838 | cooperates badly with Tramp. | 1838 | cooperates badly with Tramp. |
| 1839 | 1839 | ||
| 1840 | +++ | ||
| 1841 | *** New commands 'tramp-rename-files' and 'tramp-rename-these-files'. | ||
| 1842 | They allow to save remote files somewhere else when the corresponding | ||
| 1843 | host is not reachable anymore. | ||
| 1844 | |||
| 1840 | ** Rcirc | 1845 | ** Rcirc |
| 1841 | 1846 | ||
| 1842 | --- | 1847 | --- |
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 56ccf738070..96b11c7f524 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el | |||
| @@ -195,6 +195,268 @@ This includes password cache, file cache, connection cache, buffers." | |||
| 195 | (dolist (name (tramp-list-remote-buffers)) | 195 | (dolist (name (tramp-list-remote-buffers)) |
| 196 | (when (bufferp (get-buffer name)) (kill-buffer name)))) | 196 | (when (bufferp (get-buffer name)) (kill-buffer name)))) |
| 197 | 197 | ||
| 198 | ;;;###tramp-autoload | ||
| 199 | (defcustom tramp-default-rename-alist nil | ||
| 200 | "Default target for renaming remote buffer file names. | ||
| 201 | This is an alist of cons cells (SOURCE . TARGET). The first | ||
| 202 | matching item specifies the target to be applied for renaming | ||
| 203 | buffer file names from source via `tramp-rename-files'. SOURCE | ||
| 204 | is a regular expressions, which matches a remote file name. | ||
| 205 | TARGET must be a directory name, which could be remote (including | ||
| 206 | remote directories Tramp infers by default, such as | ||
| 207 | \"/method:user@host:\"). | ||
| 208 | |||
| 209 | TARGET can contain the patterns %m, %u or %h, which are replaced | ||
| 210 | by the method name, user name or host name of SOURCE when calling | ||
| 211 | `tramp-rename-files'. | ||
| 212 | |||
| 213 | SOURCE could also be a Lisp form, which will be evaluated. The | ||
| 214 | result must be a string or nil, which is interpreted as a regular | ||
| 215 | expression which always matches." | ||
| 216 | :group 'tramp | ||
| 217 | :version "27.1" | ||
| 218 | :type '(repeat (cons (choice :tag "Source regexp" regexp sexp) | ||
| 219 | (choice :tag "Target name" string (const nil))))) | ||
| 220 | |||
| 221 | ;;;###tramp-autoload | ||
| 222 | (defcustom tramp-confirm-rename-file-names t | ||
| 223 | "Whether renaming a buffer file name must be confirmed." | ||
| 224 | :group 'tramp | ||
| 225 | :version "27.1" | ||
| 226 | :type 'boolean) | ||
| 227 | |||
| 228 | (defun tramp-default-rename-file (string) | ||
| 229 | "Determine default file name for renaming according to STRING. | ||
| 230 | The user option `tramp-default-rename-alist' is consulted, | ||
| 231 | finding the default mapping. If there is no matching entry, the | ||
| 232 | function returns nil" | ||
| 233 | (when (tramp-tramp-file-p string) | ||
| 234 | (let ((tdra tramp-default-rename-alist) | ||
| 235 | (method (or (file-remote-p string 'method) "")) | ||
| 236 | (user (or (file-remote-p string 'user) "")) | ||
| 237 | (host (or (file-remote-p string 'host) "")) | ||
| 238 | item result) | ||
| 239 | (while (setq item (pop tdra)) | ||
| 240 | (when (string-match-p (or (eval (car item)) "") string) | ||
| 241 | (setq tdra nil | ||
| 242 | result | ||
| 243 | (format-spec | ||
| 244 | (cdr item) (format-spec-make ?m method ?u user ?h host))))) | ||
| 245 | result))) | ||
| 246 | |||
| 247 | (defsubst tramp-rename-read-file-name-dir (string) | ||
| 248 | "Return the DIR entry to be applied in `read-file-name', based on STRING." | ||
| 249 | (when (tramp-tramp-file-p string) | ||
| 250 | (substring (file-remote-p string) 0 -1))) | ||
| 251 | |||
| 252 | (defsubst tramp-rename-read-file-name-init (string) | ||
| 253 | "Return the INIT entry to be applied in `read-file-name', based on STRING." | ||
| 254 | (when (tramp-tramp-file-p string) | ||
| 255 | (string-remove-prefix (tramp-rename-read-file-name-dir string) string))) | ||
| 256 | |||
| 257 | ;;;###tramp-autoload | ||
| 258 | (defun tramp-rename-files (source target) | ||
| 259 | "Replace in all buffers the visiting file name from SOURCE to TARGET. | ||
| 260 | SOURCE is a remote directory name, which could contain also a | ||
| 261 | localname part. TARGET is the directory name SOURCE is replaced | ||
| 262 | with. Often, TARGET is a remote directory name on another host, | ||
| 263 | but it can also be a local directory name. If TARGET has no | ||
| 264 | local part, the local part from SOURCE is used. | ||
| 265 | |||
| 266 | If TARGET is nil, it is selected according to the first match in | ||
| 267 | `tramp-default-rename-alist'. If called interactively, this | ||
| 268 | match is offered as initial value for selection. | ||
| 269 | |||
| 270 | On all buffers, which have a `buffer-file-name' matching SOURCE, | ||
| 271 | this name is modified by replacing SOURCE with TARGET. This is | ||
| 272 | applied by calling `set-visited-file-name'. The new | ||
| 273 | `buffer-file-name' is prompted for modification in the | ||
| 274 | minibuffer. The buffers are marked modified, and must be saved | ||
| 275 | explicitly. | ||
| 276 | |||
| 277 | If user option `tramp-confirm-rename-file-names' is nil, changing | ||
| 278 | the file name happens without confirmation. This requires a | ||
| 279 | matching entry in `tramp-default-rename-alist'. | ||
| 280 | |||
| 281 | Remote buffers related to the remote connection identified by | ||
| 282 | SOURCE, which are not visiting files, or which are visiting files | ||
| 283 | not matching SOURCE, are not modified. | ||
| 284 | |||
| 285 | Interactively, TARGET is selected from `tramp-default-rename-alist' | ||
| 286 | without confirmation if the prefix argument is non-nil. | ||
| 287 | |||
| 288 | The remote connection identified by SOURCE is flushed by | ||
| 289 | `tramp-cleanup-connection'." | ||
| 290 | (interactive | ||
| 291 | (let ((connections | ||
| 292 | (mapcar #'tramp-make-tramp-file-name (tramp-list-connections))) | ||
| 293 | ;; Completion packages do their voodoo in `completing-read' | ||
| 294 | ;; and `read-file-name', which is often incompatible with | ||
| 295 | ;; Tramp. Ignore them. | ||
| 296 | (completing-read-function #'completing-read-default) | ||
| 297 | (read-file-name-function #'read-file-name-default) | ||
| 298 | source target) | ||
| 299 | (if (null connections) | ||
| 300 | (tramp-user-error nil "There are no remote connections.") | ||
| 301 | (setq source | ||
| 302 | ;; Likely, the source remote connection is broken. So we | ||
| 303 | ;; shall avoid any action on it. | ||
| 304 | (let (non-essential) | ||
| 305 | (completing-read-default | ||
| 306 | "Enter old Tramp connection: " | ||
| 307 | ;; Completion function. | ||
| 308 | (completion-table-dynamic | ||
| 309 | (lambda (string) | ||
| 310 | (cond | ||
| 311 | ;; Initially, show existing remote connections. | ||
| 312 | ((not (tramp-tramp-file-p string)) | ||
| 313 | (all-completions string connections)) | ||
| 314 | ;; There is a selected remote connection. Show | ||
| 315 | ;; its longest common directory path of respective | ||
| 316 | ;; buffers. | ||
| 317 | (t (mapcar | ||
| 318 | (lambda (buffer) | ||
| 319 | (let ((bfn (buffer-file-name buffer))) | ||
| 320 | (and (buffer-live-p buffer) | ||
| 321 | (tramp-equal-remote string bfn) | ||
| 322 | (stringp bfn) (file-name-directory bfn)))) | ||
| 323 | (tramp-list-remote-buffers)))))) | ||
| 324 | #'tramp-tramp-file-p t | ||
| 325 | ;; If the current buffer is a remote one, it is likely | ||
| 326 | ;; that this connection is meant. So we offer it as | ||
| 327 | ;; initial value. Otherwise, use the longest remote | ||
| 328 | ;; connection path as initial value. | ||
| 329 | (or (file-remote-p default-directory) | ||
| 330 | (try-completion "" connections)))) | ||
| 331 | |||
| 332 | target | ||
| 333 | (when (null current-prefix-arg) | ||
| 334 | ;; The source remote connection shall not trigger any action. | ||
| 335 | ;; FIXME: Better error prompt when trying to access source host. | ||
| 336 | (let* ((default (or (tramp-default-rename-file source) source)) | ||
| 337 | (dir (tramp-rename-read-file-name-dir default)) | ||
| 338 | (init (tramp-rename-read-file-name-init default)) | ||
| 339 | (tramp-ignored-file-name-regexp | ||
| 340 | (regexp-quote (file-remote-p source)))) | ||
| 341 | (read-file-name-default | ||
| 342 | "Enter new Tramp connection: " | ||
| 343 | dir default 'confirm init #'file-directory-p))))) | ||
| 344 | |||
| 345 | (list source target))) | ||
| 346 | |||
| 347 | (unless (tramp-tramp-file-p source) | ||
| 348 | (tramp-user-error nil "Source %s must be remote." source)) | ||
| 349 | (when (null target) | ||
| 350 | (or (setq target (tramp-default-rename-file source)) | ||
| 351 | (tramp-user-error | ||
| 352 | nil | ||
| 353 | (eval-when-compile | ||
| 354 | (concat "There is no target specified. " | ||
| 355 | "Check `tramp-default-rename-alist' for a proper entry."))))) | ||
| 356 | (when (tramp-equal-remote source target) | ||
| 357 | (tramp-user-error nil "Source and target must have different remote.")) | ||
| 358 | |||
| 359 | ;; Append local file name if none is specified. | ||
| 360 | (when (string-equal (file-remote-p target) target) | ||
| 361 | (setq target (concat target (file-remote-p source 'localname)))) | ||
| 362 | ;; Make them directoy names. | ||
| 363 | (setq source (directory-file-name source) | ||
| 364 | target (directory-file-name target)) | ||
| 365 | |||
| 366 | ;; Rename visited file names of source buffers. | ||
| 367 | (save-window-excursion | ||
| 368 | (save-current-buffer | ||
| 369 | (let ((help-form "\ | ||
| 370 | Type SPC or `y' to set visited file name, | ||
| 371 | DEL or `n' to skip to next, | ||
| 372 | `e' to edit the visited file name, | ||
| 373 | ESC or `q' to quit without changing further buffers, | ||
| 374 | `!' to change all remaining buffers with no more questions.") | ||
| 375 | (query-choices '(?y ?\s ?n ?\177 ?! ?e ?q ?\e)) | ||
| 376 | (query (unless tramp-confirm-rename-file-names ?!)) | ||
| 377 | changed-buffers) | ||
| 378 | (dolist (buffer (tramp-list-remote-buffers)) | ||
| 379 | (switch-to-buffer buffer) | ||
| 380 | (let* ((bfn (buffer-file-name)) | ||
| 381 | (new-bfn (and (stringp bfn) | ||
| 382 | (replace-regexp-in-string | ||
| 383 | (regexp-quote source) target bfn))) | ||
| 384 | (prompt (format-message | ||
| 385 | "Set visited file name to `%s' [Type yn!eq or %s] " | ||
| 386 | new-bfn (key-description (vector help-char))))) | ||
| 387 | (when (and (buffer-live-p buffer) (stringp bfn) | ||
| 388 | (string-prefix-p source bfn) | ||
| 389 | ;; Skip, and don't ask again. | ||
| 390 | (not (memq query '(?q ?\e)))) | ||
| 391 | ;; Read prompt. | ||
| 392 | (unless (eq query ?!) | ||
| 393 | (setq query (read-char-choice prompt query-choices))) | ||
| 394 | ;; Edit the new buffer file name. | ||
| 395 | (when (eq query ?e) | ||
| 396 | (setq new-bfn | ||
| 397 | (read-file-name | ||
| 398 | "New visited file name: " | ||
| 399 | (file-name-directory new-bfn) new-bfn))) | ||
| 400 | ;; Set buffer file name. Remember the change. | ||
| 401 | (when (memq query '(?y ?\s ?! ?e)) | ||
| 402 | (setq changed-buffers | ||
| 403 | (cons (list buffer bfn (buffer-modified-p)) | ||
| 404 | changed-buffers)) | ||
| 405 | (set-visited-file-name new-bfn)) | ||
| 406 | ;; Quit. Revert changes if prompted by user. | ||
| 407 | (when (and (memq query '(?q ?\e)) changed-buffers | ||
| 408 | (y-or-n-p "Do you want to revert applied changes?")) | ||
| 409 | (dolist (item changed-buffers) | ||
| 410 | (with-current-buffer (car item) | ||
| 411 | (set-visited-file-name (nth 1 item)) | ||
| 412 | (set-buffer-modified-p (nth 2 item))))) | ||
| 413 | ;; Cleanup echo area. | ||
| 414 | (message nil))))))) | ||
| 415 | |||
| 416 | ;; Cleanup. | ||
| 417 | (tramp-cleanup-connection (tramp-dissect-file-name source))) | ||
| 418 | |||
| 419 | ;;;###tramp-autoload | ||
| 420 | (defun tramp-rename-these-files (target) | ||
| 421 | "Replace visiting file names to TARGET. | ||
| 422 | The current buffer must be related to a remote connection. In | ||
| 423 | all buffers, which are visiting a file with the same directory | ||
| 424 | name, the buffer file name is changed. | ||
| 425 | |||
| 426 | Interactively, TARGET is selected from `tramp-default-rename-alist' | ||
| 427 | without confirmation if the prefix argument is non-nil. | ||
| 428 | |||
| 429 | For details, see `tramp-rename-files'." | ||
| 430 | (interactive | ||
| 431 | (let ((source default-directory) | ||
| 432 | target | ||
| 433 | ;; Completion packages do their voodoo in `completing-read' | ||
| 434 | ;; and `read-file-name', which is often incompatible with | ||
| 435 | ;; Tramp. Ignore them. | ||
| 436 | (completing-read-function #'completing-read-default) | ||
| 437 | (read-file-name-function #'read-file-name-default)) | ||
| 438 | (if (not (tramp-tramp-file-p source)) | ||
| 439 | (tramp-user-error | ||
| 440 | nil | ||
| 441 | (substitute-command-keys | ||
| 442 | (concat "Current buffer is not remote. " | ||
| 443 | "Consider `\\[tramp-rename-files]' instead."))) | ||
| 444 | (setq target | ||
| 445 | (when (null current-prefix-arg) | ||
| 446 | ;; The source remote connection shall not trigger any action. | ||
| 447 | ;; FIXME: Better error prompt when trying to access source host. | ||
| 448 | (let* ((default (or (tramp-default-rename-file source) source)) | ||
| 449 | (dir (tramp-rename-read-file-name-dir default)) | ||
| 450 | (init (tramp-rename-read-file-name-init default)) | ||
| 451 | (tramp-ignored-file-name-regexp | ||
| 452 | (regexp-quote (file-remote-p source)))) | ||
| 453 | (read-file-name-default | ||
| 454 | (format "Change Tramp connection `%s': " source) | ||
| 455 | dir default 'confirm init #'file-directory-p))))) | ||
| 456 | (list target))) | ||
| 457 | |||
| 458 | (tramp-rename-files default-directory target)) | ||
| 459 | |||
| 198 | ;; Tramp version is useful in a number of situations. | 460 | ;; Tramp version is useful in a number of situations. |
| 199 | 461 | ||
| 200 | ;;;###tramp-autoload | 462 | ;;;###tramp-autoload |
| @@ -424,11 +686,6 @@ please ensure that the buffers are attached to your email.\n\n")) | |||
| 424 | 686 | ||
| 425 | ;; * Clean up unused *tramp/foo* buffers after a while. (Pete Forman) | 687 | ;; * Clean up unused *tramp/foo* buffers after a while. (Pete Forman) |
| 426 | ;; | 688 | ;; |
| 427 | ;; * WIBNI there was an interactive command prompting for Tramp | ||
| 428 | ;; method, hostname, username and filename and translates the user | ||
| 429 | ;; input into the correct filename syntax (depending on the Emacs | ||
| 430 | ;; flavor) (Reiner Steib) | ||
| 431 | ;; | ||
| 432 | ;; * Let the user edit the connection properties interactively. | 689 | ;; * Let the user edit the connection properties interactively. |
| 433 | ;; Something like `gnus-server-edit-server' in Gnus' *Server* buffer. | 690 | ;; Something like `gnus-server-edit-server' in Gnus' *Server* buffer. |
| 434 | 691 | ||
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index 0bb19ed9c4d..0c3107603fb 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el | |||
| @@ -36,6 +36,8 @@ | |||
| 36 | (declare-function tramp-file-name-equal-p "tramp") | 36 | (declare-function tramp-file-name-equal-p "tramp") |
| 37 | (declare-function tramp-tramp-file-p "tramp") | 37 | (declare-function tramp-tramp-file-p "tramp") |
| 38 | (defvar eshell-path-env) | 38 | (defvar eshell-path-env) |
| 39 | (defvar ido-read-file-name-non-ido) | ||
| 40 | (defvar ivy-completing-read-handlers-alist) | ||
| 39 | (defvar recentf-exclude) | 41 | (defvar recentf-exclude) |
| 40 | (defvar tramp-current-connection) | 42 | (defvar tramp-current-connection) |
| 41 | (defvar tramp-postfix-host-format) | 43 | (defvar tramp-postfix-host-format) |
| @@ -170,6 +172,20 @@ NAME must be equal to `tramp-current-connection'." | |||
| 170 | (remove-hook 'tramp-cleanup-all-connections-hook | 172 | (remove-hook 'tramp-cleanup-all-connections-hook |
| 171 | #'tramp-recentf-cleanup-all)))) | 173 | #'tramp-recentf-cleanup-all)))) |
| 172 | 174 | ||
| 175 | ;;; Integration of ido.el: | ||
| 176 | |||
| 177 | (with-eval-after-load 'ido | ||
| 178 | (add-to-list 'ido-read-file-name-non-ido 'tramp-rename-files) | ||
| 179 | (add-to-list 'ido-read-file-name-non-ido 'tramp-these-rename-files)) | ||
| 180 | |||
| 181 | ;;; Integration of ivy.el: | ||
| 182 | |||
| 183 | (with-eval-after-load 'ivy | ||
| 184 | (add-to-list 'ivy-completing-read-handlers-alist | ||
| 185 | '(tramp-rename-files . completing-read-default)) | ||
| 186 | (add-to-list 'ivy-completing-read-handlers-alist | ||
| 187 | '(tramp-these-rename-files . completing-read-default))) | ||
| 188 | |||
| 173 | ;;; Default connection-local variables for Tramp: | 189 | ;;; Default connection-local variables for Tramp: |
| 174 | 190 | ||
| 175 | (defconst tramp-connection-local-default-profile | 191 | (defconst tramp-connection-local-default-profile |