1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-05 11:45:45 +00:00
emacs/lisp/net/tramp-integration.el
Shuguang Sun 67b50770c0 Fix recent change in Tramp
* lisp/net/tramp-adb.el:
* lisp/net/tramp-archive.el:
* lisp/net/tramp-integration.el: Remove superfluous `progn' in
`with-eval-after-load'.
2019-06-29 12:18:59 +02:00

197 lines
6.9 KiB
EmacsLisp

;;; tramp-integration.el --- Tramp integration into other packages -*- lexical-binding:t -*-
;; Copyright (C) 2019 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
;; Package: tramp
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; This assembles all integration of Tramp with other packages.
;;; Code:
(require 'tramp-compat)
;; Pacify byte-compiler.
(require 'cl-lib)
(declare-function recentf-cleanup "recentf")
(declare-function tramp-dissect-file-name "tramp")
(declare-function tramp-file-name-equal-p "tramp")
(declare-function tramp-tramp-file-p "tramp")
(defvar eshell-path-env)
(defvar recentf-exclude)
(defvar tramp-current-connection)
(defvar tramp-postfix-host-format)
;;; Fontification of `read-file-name':
(defvar tramp-rfn-eshadow-overlay)
(make-variable-buffer-local 'tramp-rfn-eshadow-overlay)
(defun tramp-rfn-eshadow-setup-minibuffer ()
"Set up a minibuffer for `file-name-shadow-mode'.
Adds another overlay hiding filename parts according to Tramp's
special handling of `substitute-in-file-name'."
(when minibuffer-completing-file-name
(setq tramp-rfn-eshadow-overlay
(make-overlay (minibuffer-prompt-end) (minibuffer-prompt-end)))
;; Copy rfn-eshadow-overlay properties.
(let ((props (overlay-properties rfn-eshadow-overlay)))
(while props
;; The `field' property prevents correct minibuffer
;; completion; we exclude it.
(if (not (eq (car props) 'field))
(overlay-put tramp-rfn-eshadow-overlay (pop props) (pop props))
(pop props) (pop props))))))
(add-hook 'rfn-eshadow-setup-minibuffer-hook
#'tramp-rfn-eshadow-setup-minibuffer)
(add-hook 'tramp-unload-hook
(lambda ()
(remove-hook 'rfn-eshadow-setup-minibuffer-hook
#'tramp-rfn-eshadow-setup-minibuffer)))
(defun tramp-rfn-eshadow-update-overlay-regexp ()
(format "[^%s/~]*\\(/\\|~\\)" tramp-postfix-host-format))
;; Package rfn-eshadow is preloaded in Emacs, but for some reason,
;; it only did (defvar rfn-eshadow-overlay) without giving it a global
;; value, so it was only declared as dynamically-scoped within the
;; rfn-eshadow.el file. This is now fixed in Emacs>26.1 but we still need
;; this defvar here for older releases.
(defvar rfn-eshadow-overlay)
(defun tramp-rfn-eshadow-update-overlay ()
"Update `rfn-eshadow-overlay' to cover shadowed part of minibuffer input.
This is intended to be used as a minibuffer `post-command-hook' for
`file-name-shadow-mode'; the minibuffer should have already
been set up by `rfn-eshadow-setup-minibuffer'."
;; In remote files name, there is a shadowing just for the local part.
(ignore-errors
(let ((end (or (overlay-end rfn-eshadow-overlay)
(minibuffer-prompt-end)))
;; We do not want to send any remote command.
(non-essential t))
(when (tramp-tramp-file-p (buffer-substring end (point-max)))
(save-excursion
(save-restriction
(narrow-to-region
(1+ (or (string-match-p
(tramp-rfn-eshadow-update-overlay-regexp)
(buffer-string) end)
end))
(point-max))
(let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay)
(rfn-eshadow-update-overlay-hook nil)
file-name-handler-alist)
(move-overlay rfn-eshadow-overlay (point-max) (point-max))
(rfn-eshadow-update-overlay))))))))
(add-hook 'rfn-eshadow-update-overlay-hook
#'tramp-rfn-eshadow-update-overlay)
(add-hook 'tramp-unload-hook
(lambda ()
(remove-hook 'rfn-eshadow-update-overlay-hook
#'tramp-rfn-eshadow-update-overlay)))
;;; Integration of eshell.el:
;; eshell.el keeps the path in `eshell-path-env'. We must change it
;; when `default-directory' points to another host.
(defun tramp-eshell-directory-change ()
"Set `eshell-path-env' to $PATH of the host related to `default-directory'."
;; Remove last element of `(exec-path)', which is `exec-directory'.
;; Use `path-separator' as it does eshell.
(setq eshell-path-env
(mapconcat
#'identity (butlast (tramp-compat-exec-path)) path-separator)))
(with-eval-after-load 'esh-util
(add-hook 'eshell-mode-hook
#'tramp-eshell-directory-change)
(add-hook 'eshell-directory-change-hook
#'tramp-eshell-directory-change)
(add-hook 'tramp-integration-unload-hook
(lambda ()
(remove-hook 'eshell-mode-hook
#'tramp-eshell-directory-change)
(remove-hook 'eshell-directory-change-hook
#'tramp-eshell-directory-change))))
;;; Integration of recentf.el:
(defun tramp-recentf-exclude-predicate (name)
"Predicate to exclude a remote file name from recentf.
NAME must be equal to `tramp-current-connection'."
(when (file-remote-p name)
(tramp-file-name-equal-p
(tramp-dissect-file-name name) (car tramp-current-connection))))
(defun tramp-recentf-cleanup (vec)
"Remove all file names related to VEC from recentf."
(when (bound-and-true-p recentf-list)
(let ((tramp-current-connection `(,vec))
(recentf-exclude '(tramp-recentf-exclude-predicate)))
(recentf-cleanup))))
(defun tramp-recentf-cleanup-all ()
"Remove all remote file names from recentf."
(when (bound-and-true-p recentf-list)
(let ((recentf-exclude '(file-remote-p)))
(recentf-cleanup))))
(with-eval-after-load 'recentf
(add-hook 'tramp-cleanup-connection-hook
#'tramp-recentf-cleanup)
(add-hook 'tramp-cleanup-all-connections-hook
#'tramp-recentf-cleanup-all)
(add-hook 'tramp-integration-unload-hook
(lambda ()
(remove-hook 'tramp-cleanup-connection-hook
#'tramp-recentf-cleanup)
(remove-hook 'tramp-cleanup-all-connections-hook
#'tramp-recentf-cleanup-all))))
;;; Default connection-local variables for Tramp:
(defconst tramp-connection-local-default-profile
'((shell-file-name . "/bin/sh")
(shell-command-switch . "-c"))
"Default connection-local variables for remote connections.")
;; `connection-local-set-profile-variables' and
;; `connection-local-set-profiles' exists since Emacs 26.1.
(with-eval-after-load 'shell
(tramp-compat-funcall
'connection-local-set-profile-variables
'tramp-connection-local-default-profile
tramp-connection-local-default-profile)
(tramp-compat-funcall
'connection-local-set-profiles
`(:application tramp)
'tramp-connection-local-default-profile))
(add-hook 'tramp-unload-hook
(lambda () (unload-feature 'tramp-integration 'force)))
(provide 'tramp-integration)
;;; tramp-integration.el ends here