(defun tramp-adb-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
(file-name-as-directory f)
f))
(with-current-buffer (tramp-get-buffer v)
- (delete-dups
- (append
- ;; On some file systems like "sdcard", "." and ".." are
- ;; not included. We fix this by `delete-dups'.
- '("." "..")
- (delq
- nil
- (mapcar
- (lambda (l)
- (and (not (string-match-p (rx bol (* blank) eol) l)) l))
- (split-string (buffer-string) "\n"))))))))))))
+ (append
+ ;; On some file systems like "sdcard", "." and ".." are
+ ;; not included.
+ '("." "..")
+ (mapcar
+ (lambda (l)
+ (and (not (string-match-p (rx bol (* blank) eol) l)) l))
+ (split-string (buffer-string) "\n" 'omit))))))))))
(defun tramp-adb-handle-file-local-copy (filename)
"Like `file-local-copy' for Tramp files."
(defun tramp-crypt-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(let* (completion-regexp-list
(defun tramp-fuse-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (tramp-fuse-remove-hidden-files
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
+ (tramp-fuse-remove-hidden-files
(all-completions
filename
- (delete-dups
- (append
- (file-name-all-completions
- filename (tramp-fuse-local-file-name directory))
- ;; Some storage systems do not return "." and "..".
- (let (result)
- (dolist (item '(".." ".") result)
- (when (string-prefix-p filename item)
- (catch 'match
- (dolist (elt completion-regexp-list)
- (unless (string-match-p elt item) (throw 'match nil)))
- (setq result (cons (concat item "/") result))))))))))))
+ (append
+ (file-name-all-completions
+ filename (tramp-fuse-local-file-name directory))
+ ;; Some storage systems do not return "." and "..".
+ (let (result)
+ (dolist (item '(".." ".") result)
+ (when (string-prefix-p filename item)
+ (catch 'match
+ (dolist (elt completion-regexp-list)
+ (unless (string-match-p elt item) (throw 'match nil)))
+ (setq result (cons (concat item "/") result)))))))))))
;; This function isn't used.
(defun tramp-fuse-handle-insert-directory
(defun tramp-gvfs-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (unless (tramp-compat-string-search "/" filename)
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
+ (unless (tramp-compat-string-search "/" filename)
(all-completions
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
;; files.
(defun tramp-sh-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (with-parsed-tramp-file-name (expand-file-name directory) nil
- (when (and (not (tramp-compat-string-search "/" filename))
- (tramp-connectable-p v))
- (unless (tramp-compat-string-search "/" filename)
- (ignore-error file-missing
- (all-completions
- filename
- (with-tramp-file-property v localname "file-name-all-completions"
- (let (result)
- ;; Get a list of directories and files, including
- ;; reliably tagging the directories with a trailing "/".
- ;; Because I rock. --daniel@danann.net
- (if (tramp-get-remote-perl v)
- (progn
- (tramp-maybe-send-script
- v tramp-perl-file-name-all-completions
- "tramp_perl_file_name_all_completions")
- (setq result
- (tramp-send-command-and-read
- v (format "tramp_perl_file_name_all_completions %s"
- (tramp-shell-quote-argument localname))
- 'noerror))
- ;; Cached values.
- (dolist (elt result)
- (tramp-set-file-property
- v (cadr elt) "file-directory-p" (nth 2 elt))
- (tramp-set-file-property
- v (cadr elt) "file-exists-p" (nth 3 elt))
- (tramp-set-file-property
- v (cadr elt) "file-readable-p" (nth 4 elt)))
- ;; Result.
- (mapcar #'car result))
-
- ;; Do it with ls.
- (when (tramp-send-command-and-check
- v (format (concat
- "cd %s 2>&1 && %s -a 2>%s"
- " | while IFS= read f; do"
- " if %s -d \"$f\" 2>%s;"
- " then echo \"$f/\"; else echo \"$f\"; fi;"
- " done")
- (tramp-shell-quote-argument localname)
- (tramp-get-ls-command v)
- (tramp-get-remote-null-device v)
- (tramp-get-test-command v)
- (tramp-get-remote-null-device v)))
-
- ;; Now grab the output.
- (with-current-buffer (tramp-get-buffer v)
- (goto-char (point-max))
- (while (zerop (forward-line -1))
- (push
- (buffer-substring (point) (line-end-position)) result)))
- result))))))))))
+ (tramp-skeleton-file-name-all-completions filename directory
+ (with-parsed-tramp-file-name (expand-file-name directory) nil
+ (when (and (not (tramp-compat-string-search "/" filename))
+ (tramp-connectable-p v))
+ (unless (tramp-compat-string-search "/" filename)
+ (all-completions
+ filename
+ (with-tramp-file-property v localname "file-name-all-completions"
+ (let (result)
+ ;; Get a list of directories and files, including
+ ;; reliably tagging the directories with a trailing "/".
+ ;; Because I rock. --daniel@danann.net
+ (if (tramp-get-remote-perl v)
+ (progn
+ (tramp-maybe-send-script
+ v tramp-perl-file-name-all-completions
+ "tramp_perl_file_name_all_completions")
+ (setq result
+ (tramp-send-command-and-read
+ v (format "tramp_perl_file_name_all_completions %s"
+ (tramp-shell-quote-argument localname))
+ 'noerror))
+ ;; Cached values.
+ (dolist (elt result)
+ (tramp-set-file-property
+ v (cadr elt) "file-directory-p" (nth 2 elt))
+ (tramp-set-file-property
+ v (cadr elt) "file-exists-p" (nth 3 elt))
+ (tramp-set-file-property
+ v (cadr elt) "file-readable-p" (nth 4 elt)))
+ ;; Result.
+ (mapcar #'car result))
+
+ ;; Do it with ls.
+ (when (tramp-send-command-and-check
+ v (format (concat
+ "cd %s 2>&1 && %s -a 2>%s"
+ " | while IFS= read f; do"
+ " if %s -d \"$f\" 2>%s;"
+ " then echo \"$f/\"; else echo \"$f\"; fi;"
+ " done")
+ (tramp-shell-quote-argument localname)
+ (tramp-get-ls-command v)
+ (tramp-get-remote-null-device v)
+ (tramp-get-test-command v)
+ (tramp-get-remote-null-device v)))
+
+ ;; Now grab the output.
+ (with-current-buffer (tramp-get-buffer v)
+ (goto-char (point-max))
+ (while (zerop (forward-line -1))
+ (push
+ (buffer-substring (point) (line-end-position)) result)))
+ result))))))))))
;; cp, mv and ln
;; files.
(defun tramp-smb-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(when (file-directory-p directory)
(with-parsed-tramp-file-name (expand-file-name directory) nil
(with-tramp-file-property v localname "file-name-all-completions"
- (delete-dups
- (mapcar
- (lambda (x)
- (list
- (if (tramp-compat-string-search "d" (nth 1 x))
- (file-name-as-directory (nth 0 x))
- (nth 0 x))))
- (tramp-smb-get-file-entries directory)))))))))
+ (mapcar
+ (lambda (x)
+ (list
+ (if (tramp-compat-string-search "d" (nth 1 x))
+ (file-name-as-directory (nth 0 x))
+ (nth 0 x))))
+ (tramp-smb-get-file-entries directory))))))))
(defun tramp-smb-handle-file-system-info (filename)
"Like `file-system-info' for Tramp files."
(defun tramp-sudoedit-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
(if (ignore-errors (file-directory-p (expand-file-name f directory)))
(file-name-as-directory f)
f))
- (delq
- nil
- (mapcar
- (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
- (split-string
- (tramp-get-buffer-string (tramp-get-connection-buffer v))
- "\n" 'omit)))))))))
+ (mapcar
+ (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
+ (split-string
+ (tramp-get-buffer-string (tramp-get-connection-buffer v))
+ "\n" 'omit))))))))
(defun tramp-sudoedit-handle-file-readable-p (filename)
"Like `file-readable-p' for Tramp files."
(tramp-run-real-handler #'file-exists-p (list filename))))
+(defmacro tramp-skeleton-file-name-all-completions
+ (_filename _directory &rest body)
+ "Skeleton for `tramp-*-handle-filename-all-completions'.
+BODY is the backend specific code."
+ (declare (indent 2) (debug t))
+ `(ignore-error file-missing
+ (delete-dups (delq nil
+ (let* ((case-fold-search read-file-name-completion-ignore-case)
+ (regexp (mapconcat #'identity completion-regexp-list "\\|"))
+ (result ,@body))
+ (if (consp completion-regexp-list)
+ ;; Discriminate over `completion-regexp-list'.
+ (mapcar
+ (lambda (x) (and (stringp x) (string-match-p regexp x) x))
+ result)
+ result))))))
+
(defvar tramp--last-hop-directory nil
"Tracks the directory from which to run login programs.")
;; completions.
(defun tramp-completion-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for partial Tramp files."
- (let ((fullname
- (tramp-drop-volume-letter (expand-file-name filename directory)))
- (directory (tramp-drop-volume-letter directory))
- tramp--last-hop-directory hop result result1)
-
- ;; Suppress hop from completion.
- (when (string-match
- (rx
- (regexp tramp-prefix-regexp)
- (group (+ (regexp tramp-remote-file-name-spec-regexp)
- (regexp tramp-postfix-hop-regexp))))
- fullname)
- (setq hop (match-string 1 fullname)
- fullname (replace-match "" nil nil fullname 1)
- tramp--last-hop-directory
- (tramp-make-tramp-file-name (tramp-dissect-hop-name hop))))
-
- (let (;; When `tramp-syntax' is `simplified', we need a default method.
- (tramp-default-method
- (and (string-empty-p tramp-postfix-method-format)
- tramp-default-method))
- (tramp-default-method-alist
- (and (string-empty-p tramp-postfix-method-format)
- tramp-default-method-alist))
- tramp-default-user tramp-default-user-alist
- tramp-default-host tramp-default-host-alist)
-
- ;; Possible completion structures.
- (dolist (elt (tramp-completion-dissect-file-name fullname))
- (let* ((method (tramp-file-name-method elt))
- (user (tramp-file-name-user elt))
- (host (tramp-file-name-host elt))
- (localname (tramp-file-name-localname elt))
- (m (tramp-find-method method user host))
- all-user-hosts)
-
- (unless localname ;; Nothing to complete.
-
- (if (or user host)
-
- ;; Method dependent user / host combinations.
- (progn
- (mapc
- (lambda (x)
- (setq all-user-hosts
- (append all-user-hosts
- (funcall (nth 0 x) (nth 1 x)))))
- (tramp-get-completion-function m))
-
- (setq result
- (append result
- (mapcar
- (lambda (x)
- (tramp-get-completion-user-host
- method user host (nth 0 x) (nth 1 x)))
- (delq nil all-user-hosts)))))
-
- ;; Possible methods.
- (setq result
- (append result (tramp-get-completion-methods m hop)))))))
-
- ;; Unify list, add hop, remove nil elements.
- (dolist (elt result)
- (when elt
- (setq elt (replace-regexp-in-string
- tramp-prefix-regexp (concat tramp-prefix-format hop) elt))
- (push (substring elt (length directory)) result1)))
-
- ;; Complete local parts.
- (delete-dups
- (append
- result1
- (ignore-errors
- (tramp-run-real-handler
- #'file-name-all-completions (list filename directory))))))))
+ (tramp-skeleton-file-name-all-completions filename directory
+ (let ((fullname
+ (tramp-drop-volume-letter (expand-file-name filename directory)))
+ (directory (tramp-drop-volume-letter directory))
+ tramp--last-hop-directory hop result result1)
+
+ ;; Suppress hop from completion.
+ (when (string-match
+ (rx
+ (regexp tramp-prefix-regexp)
+ (group (+ (regexp tramp-remote-file-name-spec-regexp)
+ (regexp tramp-postfix-hop-regexp))))
+ fullname)
+ (setq hop (match-string 1 fullname)
+ fullname (replace-match "" nil nil fullname 1)
+ tramp--last-hop-directory
+ (tramp-make-tramp-file-name (tramp-dissect-hop-name hop))))
+
+ (let (;; When `tramp-syntax' is `simplified', we need a default method.
+ (tramp-default-method
+ (and (string-empty-p tramp-postfix-method-format)
+ tramp-default-method))
+ (tramp-default-method-alist
+ (and (string-empty-p tramp-postfix-method-format)
+ tramp-default-method-alist))
+ tramp-default-user tramp-default-user-alist
+ tramp-default-host tramp-default-host-alist)
+
+ ;; Possible completion structures.
+ (dolist (elt (tramp-completion-dissect-file-name fullname))
+ (let* ((method (tramp-file-name-method elt))
+ (user (tramp-file-name-user elt))
+ (host (tramp-file-name-host elt))
+ (localname (tramp-file-name-localname elt))
+ (m (tramp-find-method method user host))
+ all-user-hosts)
+
+ (unless localname ;; Nothing to complete.
+ (if (or user host)
+ ;; Method dependent user / host combinations.
+ (progn
+ (mapc
+ (lambda (x)
+ (setq all-user-hosts
+ (append all-user-hosts
+ (funcall (nth 0 x) (nth 1 x)))))
+ (tramp-get-completion-function m))
+
+ (setq result
+ (append result
+ (mapcar
+ (lambda (x)
+ (tramp-get-completion-user-host
+ method user host (nth 0 x) (nth 1 x)))
+ all-user-hosts))))
+
+ ;; Possible methods.
+ (setq result
+ (append result (tramp-get-completion-methods m hop)))))))
+
+ ;; Add hop.
+ (dolist (elt result)
+ (when elt
+ (setq elt (replace-regexp-in-string
+ tramp-prefix-regexp (concat tramp-prefix-format hop) elt))
+ (push (substring elt (length directory)) result1)))
+
+ ;; Complete local parts.
+ (append
+ result1
+ (ignore-errors
+ (tramp-run-real-handler
+ #'file-name-all-completions (list filename directory))))))))
;; Method, host name and user name completion for a file.
(defun tramp-completion-handle-file-name-completion