Initial Commit
[packages] / xemacs-packages / tramp / lisp / tramp-efs.el
1 ;;; tramp-efs.el --- Make EFS a foreign method in Tramp
2
3 ;; Copyright (C) 2003-2015 Free Software Foundation, Inc.
4
5 ;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
6 ;; Keywords: comm, processes
7 ;; Package: tramp
8
9 ;; This file is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
21
22 ;;; Commentary:
23
24 ;; This file provides glue between Tramp and EFS.  EFS is hooked into
25 ;; Tramp as a foreign method.  Most of this file has been snarfed from
26 ;; tramp-ftp.el, which does the same for Tramp and Ange-FTP.
27
28 ;;; Code:
29
30 (require 'tramp)
31
32 ;; Pacify byte-compiler.
33 (defvar efs-path-format-string)
34 (defvar efs-path-format-without-user)
35 (defvar efs-path-host-format)
36 (defvar efs-path-regexp)
37 (defvar efs-path-root-regexp)
38 (defvar efs-path-user-at-host-format)
39 (defvar package-get-download-sites)
40
41 ;;;###tramp-autoload
42 (defconst tramp-efs-method "ftp"
43   "Name of the method invoking EFS.")
44
45 ;; The EFS name format is somewhat restricted.  EFS assumes that the
46 ;; first pair of parentheses is the user and the second is the host.
47 ;; It assumes that there is one character after the host name, and
48 ;; then the localname part follows.  See function `efs-ftp-path' for
49 ;; the code.  If the first pair of parentheses doesn't match anything,
50 ;; then it assumes that the user is not given.  Therefore, we need to
51 ;; be quite careful with the \(...\) constructs we use in our regexes.
52
53 (defvar tramp-efs-method-given nil
54   "Method tag is given in filename.
55 To be set in `tramp-efs-file-name-handler'.")
56
57 (defvar tramp-efs-method-regexp
58   (concat tramp-prefix-regexp
59           (regexp-quote tramp-efs-method)
60           tramp-postfix-method-regexp)
61   "Regexp indicating method tag.")
62
63 (defun tramp-efs-path-regexp ()
64   "Tramp uses this value for `efs-path-regexp'."
65   (concat tramp-prefix-regexp
66           (when tramp-efs-method-given
67             (concat
68              (regexp-quote tramp-efs-method)
69              tramp-postfix-method-regexp))
70           "\\(" tramp-user-regexp tramp-postfix-user-regexp "\\)?"
71           "\\(" tramp-host-with-port-regexp "\\)"
72           tramp-postfix-host-regexp
73           "\\(" tramp-localname-regexp "\\)"))
74
75 (defun tramp-efs-path-format-string ()
76   "Tramp uses this value for `efs-path-format-string'."
77   (concat tramp-prefix-format
78           (when tramp-efs-method-given
79             (concat tramp-efs-method tramp-postfix-method-format))
80           "%s" tramp-postfix-user-format
81           "%s" tramp-postfix-host-format
82           "%s"))
83
84 (defun tramp-efs-path-format-without-user ()
85   "Tramp uses this value for `efs-path-format-without-user'."
86   (concat tramp-prefix-format
87           (when tramp-efs-method-given
88             (concat tramp-efs-method tramp-postfix-method-format))
89           "%s" tramp-postfix-host-format
90           "%s"))
91
92 (defun tramp-efs-path-user-at-host-format ()
93   "Tramp uses this value for `efs-path-user-at-host-format'."
94   (concat "%s" tramp-postfix-user-format
95           "%s" tramp-postfix-host-format))
96
97 (defun tramp-efs-path-host-format ()
98   "Tramp uses this value for `efs-path-host-format'."
99   (concat "%s" tramp-postfix-host-format))
100
101 (defun tramp-efs-path-root-regexp ()
102   "Tramp uses this value for `efs-path-root-regexp'."
103   (concat tramp-prefix-regexp
104           (when tramp-efs-method-given
105             (concat
106              (regexp-quote tramp-efs-method)
107              tramp-postfix-method-regexp))
108           "\\(" tramp-user-regexp tramp-postfix-user-regexp "\\)?"
109           "\\(" tramp-host-with-port-regexp "\\)"
110           tramp-postfix-host-regexp))
111
112 ;; Still need to do `efs-path-root-short-circuit-regexp'.
113
114 ;; Disable EFS from file-name-handler-alist.
115
116 ;; There is still an entry for efs-sifn-handler-function
117 ;; in file-name-handler-alist that I don't know how to deal with.
118
119 (defun tramp-disable-efs ()
120   "Turn EFS off.
121 This is useful for unified remoting.  See
122 `tramp-file-name-structure' for details.  Requests suitable for
123 EFS will be forwarded to EFS.  Also see the variables
124 `tramp-efs-method', `tramp-default-method', and
125 `tramp-default-method-alist'.
126
127 This function is not needed in Emacsen which include Tramp, but is
128 present for backward compatibility."
129   (let ((a1 (rassq 'efs-file-handler-function
130                    file-name-handler-alist))
131         (a2 (rassq 'efs-root-handler-function
132                    file-name-handler-alist))
133         (a3 (rassq 'remote-path-file-handler-function
134                    file-name-handler-alist)))
135     (setq file-name-handler-alist
136           (delete a1 (delete a2 (delete a3 file-name-handler-alist))))))
137
138 (tramp-disable-efs)
139
140 (eval-after-load "efs" '(tramp-disable-efs))
141 (eval-after-load "efs-fnh" '(tramp-disable-efs))
142
143 ;;;###tramp-autoload
144 (when (featurep 'xemacs)
145   ;; Add EFS method to the method list.
146   (add-to-list 'tramp-methods (cons tramp-efs-method nil))
147
148   ;; Add some defaults for `tramp-default-method-alist'.
149   (add-to-list 'tramp-default-method-alist
150                (list "\\`ftp\\." nil tramp-efs-method))
151   (add-to-list 'tramp-default-method-alist
152                (list nil "\\`\\(anonymous\\|ftp\\)\\'" tramp-efs-method)))
153
154 (when (featurep 'xemacs)
155   ;; Add all XEmacs download sites to `tramp-default-method-alist'.
156   ;; The settings above should be sufficient, but it's better to make
157   ;; it explicitly.
158   (when (listp package-get-download-sites)
159     (mapc (lambda (x)
160             (when (listp x)
161               (add-to-list
162                'tramp-default-method-alist
163                (list (concat "\\`" (nth 1 x) "\\'")
164                      "\\`anonymous\\'" tramp-efs-method))))
165           package-get-download-sites)))
166
167 ;; Add completion function for FTP method.
168 ;;;###tramp-autoload
169 (eval-after-load 'tramp
170   '(tramp-set-completion-function
171     tramp-efs-method
172     '((tramp-parse-netrc "~/.netrc"))))
173
174 ;;;###tramp-autoload
175 (defun tramp-efs-file-name-handler (operation &rest args)
176   "Invoke the EFS handler for OPERATION.
177 First arg specifies the OPERATION, second args is a list of arguments to
178 pass to the OPERATION."
179   (save-match-data
180     (or (boundp 'efs-path-regexp)
181         (require 'efs-cu))
182
183     ;; Check whether the method is given in a filename.
184     (setq tramp-efs-method-given nil)
185     (mapc (lambda (x)
186             (and (stringp x)
187                  (string-match tramp-efs-method-regexp x)
188                  (setq tramp-efs-method-given t)))
189           args)
190
191     (let ((efs-path-regexp              (tramp-efs-path-regexp))
192           (efs-path-format-string       (tramp-efs-path-format-string))
193           (efs-path-format-without-user (tramp-efs-path-format-without-user))
194           (efs-path-user-at-host-format (tramp-efs-path-user-at-host-format))
195           (efs-path-host-format         (tramp-efs-path-host-format))
196           (efs-path-root-regexp         (tramp-efs-path-root-regexp)))
197       (cond
198        ;; If argument is a symlink, `file-directory-p' and
199        ;; `file-exists-p' call the traversed file recursively.  So we
200        ;; cannot disable the file-name-handler this case.
201        ((memq operation '(file-directory-p file-exists-p))
202         (apply 'efs-file-handler-function operation args))
203         ;; Normally, the handlers must be discarded
204         (t (let* ((inhibit-file-name-handlers
205                    (list 'tramp-file-name-handler
206                          'tramp-completion-file-name-handler
207                          (and (eq inhibit-file-name-operation operation)
208                               inhibit-file-name-handlers)))
209                   (inhibit-file-name-operation operation))
210              (apply 'efs-file-handler-function operation args)))))))
211
212 ;; This function is called even in case the filename doesn't fit Tramp
213 ;; syntax (see defadvice of `efs-dired-before-readin' and
214 ;; `efs-set-buffer-mode').  So a syntax check must be performed first;
215 ;; otherwise `tramp-dissect-file-name' returns with an error.
216 ;; It must be a `defsubst' in order to push the whole code into
217 ;; tramp-loaddefs.el.  Otherwise, there would be recursive autoloading.
218 ;;;###tramp-autoload
219 (defsubst tramp-efs-file-name-p (filename)
220   "Check if it's a filename that should be forwarded to EFS."
221   (when (string-match (nth 0 tramp-file-name-structure) filename)
222     (string= (tramp-file-name-method (tramp-dissect-file-name filename))
223              tramp-efs-method)))
224
225 ;;;###tramp-autoload
226 (when (featurep 'xemacs)
227   (add-to-list 'tramp-foreign-file-name-handler-alist
228                (cons 'tramp-efs-file-name-p 'tramp-efs-file-name-handler)))
229
230 ;; Deal with other EFS hooks.
231 ;; * dired-before-readin-hook contains efs-dired-before-readin
232 ;; * find-file-hooks contains efs-set-buffer-mode
233
234 (defadvice efs-dired-before-readin (around tramp-efs activate)
235   "Do nothing for non-EFS names."
236   (when (tramp-efs-file-name-p default-directory)
237     ad-do-it))
238
239 (defadvice efs-set-buffer-mode (around tramp-efs activate)
240   "Do nothing for non-EFS names."
241   (when (tramp-efs-file-name-p buffer-file-name)
242     ad-do-it))
243
244 (add-hook 'tramp-unload-hook
245           (lambda ()
246             (unload-feature 'tramp-efs 'force)))
247
248 (provide 'tramp-efs)
249 ;;; tramp-efs.el ends here
250
251 ;; Local Variables:
252 ;; mode: Emacs-Lisp
253 ;; coding: utf-8
254 ;; End: