Merge from mainline.
[bpt/emacs.git] / lisp / eshell / esh-util.el
index c05f6ab..1a4c5e1 100644 (file)
@@ -1,16 +1,16 @@
 ;;; esh-util.el --- general utilities
 
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+;;   2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Author: John Wiegley <johnw@gnu.org>
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; 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 2, or (at your option)
-;; any later version.
+;; 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
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
-(provide 'esh-util)
+;;; Commentary:
 
-(eval-when-compile (require 'esh-maint))
+;;; Code:
 
 (defgroup eshell-util nil
   "This is general utility code, meant for use by Eshell itself."
   :tag "General utilities"
   :group 'eshell)
 
-;;; Commentary:
-
-(require 'pp)
-
 ;;; User Variables:
 
 (defcustom eshell-stringify-t t
@@ -139,10 +133,6 @@ function `string-to-number'."
 
 ;;; Functions:
 
-(defsubst eshell-under-xemacs-p ()
-  "Return non-nil if we are running under XEmacs."
-  (boundp 'xemacs-logo))
-
 (defsubst eshell-under-windows-p ()
   "Return non-nil if we are running under MS-DOS/Windows."
   (memq system-type '(ms-dos windows-nt)))
@@ -247,6 +237,21 @@ If N or M is nil, it means the end of the list."
            a (last a)))
     a))
 
+(defvar eshell-path-env (getenv "PATH")
+  "Content of $PATH.
+It might be different from \(getenv \"PATH\"\), when
+`default-directory' points to a remote host.")
+
+(defun eshell-parse-colon-path (path-env)
+  "Split string with `parse-colon-path'.
+Prepend remote identification of `default-directory', if any."
+  (let ((remote (file-remote-p default-directory)))
+    (if remote
+       (mapcar
+        (lambda (x) (concat remote x))
+        (parse-colon-path path-env))
+      (parse-colon-path path-env))))
+
 (defun eshell-split-path (path)
   "Split a path into multiple subparts."
   (let ((len (length path))
@@ -280,6 +285,7 @@ If N or M is nil, it means the end of the list."
       (setq text (replace-match " " t t text)))
     text))
 
+;; FIXME this is just dolist.
 (defmacro eshell-for (for-var for-list &rest forms)
   "Iterate through a list"
   `(let ((list-iter ,for-list))
@@ -433,7 +439,9 @@ list."
   ;; "args out of range" error in `sit-for', if this function
   ;; runs while point is in the minibuffer and the users attempt
   ;; to use completion.  Don't ask me.
-  (ignore-errors (sit-for 0 0)))
+  (condition-case nil
+      (sit-for 0 0)
+    (error nil)))
 
 (defun eshell-read-passwd-file (file)
   "Return an alist correlating gids to group names in FILE."
@@ -586,7 +594,7 @@ Unless optional argument INPLACE is non-nil, return a new string."
        string)))
 
 (unless (fboundp 'directory-files-and-attributes)
-  (defun directory-files-and-attributes (directory &optional full match nosort)
+  (defun directory-files-and-attributes (directory &optional full match nosort id-format)
     "Return a list of names of files and their attributes in DIRECTORY.
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
@@ -601,25 +609,18 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
          (cons file (eshell-file-attributes (expand-file-name file directory)))))
        (directory-files directory full match nosort)))))
 
-(eval-when-compile
-  (defvar ange-cache))
+(defvar ange-cache)
 
-(defun eshell-directory-files-and-attributes (dir &optional full match nosort)
+(defun eshell-directory-files-and-attributes (dir &optional full match nosort id-format)
   "Make sure to use the handler for `directory-file-and-attributes'."
-  (let* ((dir (expand-file-name dir))
-        (dfh (find-file-name-handler dir 'directory-files)))
-    (if (not dfh)
-       (directory-files-and-attributes dir full match nosort)
-      (let ((files (funcall dfh 'directory-files dir full match nosort))
-           (fah (find-file-name-handler dir 'file-attributes)))
-       (mapcar
-        (function
-         (lambda (file)
-           (cons file (if fah
-                          (eshell-file-attributes
-                           (expand-file-name file dir))
-                        (file-attributes (expand-file-name file dir))))))
-        files)))))
+  (let* ((dir (expand-file-name dir)))
+    (if (string-equal (file-remote-p dir 'method) "ftp")
+       (let ((files (directory-files dir full match nosort)))
+         (mapcar
+          (lambda (file)
+            (cons file (eshell-file-attributes (expand-file-name file dir))))
+          files))
+      (directory-files-and-attributes dir full match nosort id-format))))
 
 (defun eshell-current-ange-uids ()
   (if (string-match "/\\([^@]+\\)@\\([^:]+\\):" default-directory)
@@ -636,10 +637,23 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
     (autoload 'parse-time-string "parse-time"))
 
 (eval-when-compile
-  (load "ange-ftp" t))
+  (require 'ange-ftp nil t)
+  (require 'tramp nil t))
 
 (defun eshell-parse-ange-ls (dir)
-  (let (entry)
+  (let ((ange-ftp-name-format
+        (list (nth 0 tramp-file-name-structure)
+              (nth 3 tramp-file-name-structure)
+              (nth 2 tramp-file-name-structure)
+              (nth 4 tramp-file-name-structure)))
+       ;; ange-ftp uses `ange-ftp-ftp-name-arg' and `ange-ftp-ftp-name-res'
+       ;; for optimization in `ange-ftp-ftp-name'. If Tramp wasn't active,
+       ;; there could be incorrect values from previous calls in case the
+       ;; "ftp" method is used in the Tramp file name. So we unset
+       ;; those values.
+       (ange-ftp-ftp-name-arg "")
+       (ange-ftp-ftp-name-res nil)
+       entry)
     (with-temp-buffer
       (insert (ange-ftp-ls dir "-la" nil))
       (goto-char (point-min))
@@ -658,6 +672,7 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
               (user (match-string 3))
               (group (match-string 4))
               (size (string-to-number (match-string 5)))
+              (name (ange-ftp-parse-filename))
               (mtime
                (if (fboundp 'parse-time-string)
                    (let ((moment (parse-time-string
@@ -670,7 +685,6 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
                        (setcar (nthcdr 2 moment) 0))
                      (apply 'encode-time moment))
                  (ange-ftp-file-modtime (expand-file-name name dir))))
-              (name (ange-ftp-parse-filename))
               symlink)
          (if (string-match "\\(.+\\) -> \\(.+\\)" name)
              (setq symlink (match-string 2 name)
@@ -687,32 +701,32 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
        (forward-line)))
     entry))
 
-(defun eshell-file-attributes (file)
-  "Return the attributes of FILE, playing tricks if it's over ange-ftp."
+(defun eshell-file-attributes (file &optional id-format)
+  "Return the attributes of FILE, playing tricks if it's over ange-ftp.
+The optional argument ID-FORMAT specifies the preferred uid and
+gid format.  Valid values are 'string and 'integer, defaulting to
+'integer.  See `file-attributes'."
   (let* ((file (expand-file-name file))
-        (handler (find-file-name-handler file 'file-attributes))
         entry)
-    (if (not handler)
-       (file-attributes file)
-      (if (eq (find-file-name-handler (file-name-directory file)
-                                     'directory-files)
-             'ange-ftp-hook-function)
-         (let ((base (file-name-nondirectory file))
-               (dir (file-name-directory file)))
+    (if (string-equal (file-remote-p file 'method) "ftp")
+       (let ((base (file-name-nondirectory file))
+             (dir (file-name-directory file)))
+         (if (string-equal "" base) (setq base "."))
+         (if (boundp 'ange-cache)
+             (setq entry (cdr (assoc base (cdr (assoc dir ange-cache))))))
+         (unless entry
+           (setq entry (eshell-parse-ange-ls dir))
            (if (boundp 'ange-cache)
-               (setq entry (cdr (assoc base (cdr (assoc dir ange-cache))))))
-           (unless entry
-             (setq entry (eshell-parse-ange-ls dir))
-             (if (boundp 'ange-cache)
-                 (setq ange-cache
-                       (cons (cons dir entry)
-                             ange-cache)))
-             (if entry
-                 (let ((fentry (assoc base (cdr entry))))
-                   (if fentry
-                       (setq entry (cdr fentry))
-                     (setq entry nil)))))))
-      (or entry (funcall handler 'file-attributes file)))))
+               (setq ange-cache
+                     (cons (cons dir entry)
+                           ange-cache)))
+           (if entry
+               (let ((fentry (assoc base (cdr entry))))
+                 (if fentry
+                     (setq entry (cdr fentry))
+                   (setq entry nil)))))
+         entry)
+      (file-attributes file id-format))))
 
 (defalias 'eshell-copy-tree 'copy-tree)
 
@@ -785,7 +799,7 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
 ;     (or result
 ;      (file-attributes filename))))
 
-;;; Code:
+(provide 'esh-util)
 
-;;; arch-tag: 70159778-5c7a-480a-bae4-3ad332fca19d
+;; arch-tag: 70159778-5c7a-480a-bae4-3ad332fca19d
 ;;; esh-util.el ends here