1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-27 10:54:40 +00:00

Added better remote directory support to Eshell, as well as a few bug

fixes.  See the ChangeLog.
This commit is contained in:
John Wiegley 2000-10-13 09:02:39 +00:00
parent e2c06b17a9
commit 8c6b1d8311
9 changed files with 324 additions and 98 deletions

View File

@ -1,3 +1,82 @@
2000-10-13 John Wiegley <johnw@gnu.org>
* eshell/esh-util.el: Added a global form which declares an
autoload for `parse-time-string', if that function is not already
defined, and if parse-time.el is available on the user's system.
* eshell/em-ls.el (eshell-ls-applicable): Extended this function
to be aware of ange-ftp user info.
(eshell-do-ls): Bind `ange-cache'. Also, use
`eshell-file-attributes'.
(eshell-ls-annotate): Use `eshell-file-attributes'.
(eshell-ls-file): Made the user-id printing code a bit smarter.
* eshell/esh-util.el (eshell-ange-ls-uids): Added variable, to
allow identification of alias user ids in remote directories.
It's manual, but there's no other way to know when the current
user on the local machine, is also the owning user on the remote
machine.
(fboundp): Bind `ange-cache'.
(eshell-directory-files-and-attributes): Re-organized the logic a
bit to use `eshell-file-attributes' instead of `file-attributes'.
The former is more sensitive to directories that are read via FTP,
and knows how to use ange-ftp to determine full attribute
information, instead of just the name and last modtime.
(eshell-current-ange-uids): Return the current user id when in a
remote directory.
(eshell-parse-ange-ls): Parse a full directory listing that has
been returned by ange-ftp.
(eshell-file-attributes): This beefed up version of
`file-attributes' is only special if the user is currently in a
remote directory, in which case it does a lot of work to find out
what the real attributes of a file are, as they appear on the
remote machine. This makes usage of remote directories (i.e.,
ange-ftp pathnames) much more useful. You can now use Eshell as a
full-fledged FTP client, with much more manipulation ability than
most other clients.
* eshell/em-unix.el (eshell-du-prefer-over-ange): Added a new
variable, which means that Eshell's du should always be preferred
in remote directories.
(eshell-shuffle-files): Use `eshell-file-attributes', rather than
just `file-attributes'.
(eshell-mvcp-template): Bind `ange-cache', to improve performance
when reading remote directories. This is an Eshell-specific
variable (not part of ange-ftp).
(eshell/ln): Bind `ange-cache'.
(eshell/du): Added some extra logic for determining when to use
Eshell's du (which is slow), and when to use the external version
(which may or may not exist).
* eshell/em-rebind.el (eshell-delchar-or-maybe-eof): Call
`eshell-interactive-process', rather than using
`get-buffer-process', since backgrounded processes don't count in
the context of this function's logic.
* eshell/esh-arg.el (eshell-parse-double-quote): Moved a call to
`forward-char', so that null strings are parsed correctly.
2000-09-10 John Wiegley <johnw@gnu.org>
* eshell/em-pred.el (eshell-pred-file-type,
eshell-pred-file-links, eshell-pred-file-size): Use
`eshell-file-attributes'. This is more correct over ange-ftp.
* eshell/em-glob.el (eshell-extended-glob): Bind `ange-cache', so
that remote file globbing is more efficient.
* eshell/em-ls.el (eshell-ls-dir): Use `expand-file-name' when
gathering the files and attributes within a directory.
* eshell/em-unix.el (eshell/cat): If any of the files passed on
the command line is a special file (not a regular file, directory
or symlink), always attempt to call the external version of cat.
2000-09-06 John Wiegley <johnw@gnu.org>
* eshell/esh-mode.el (eshell-find-tag): Corrections to the
Eshell-friendly version of find-tag.
2000-10-13 Miles Bader <miles@lsi.nec.co.jp> 2000-10-13 Miles Bader <miles@lsi.nec.co.jp>
* image-file.el (image-file-name-extensions) * image-file.el (image-file-name-extensions)
@ -347,6 +426,8 @@
* files.el (set-auto-mode): Ignore unknown -*- mode -*- rather than * files.el (set-auto-mode): Ignore unknown -*- mode -*- rather than
raise an error. This way it can still default to a sane value. raise an error. This way it can still default to a sane value.
2000-10-06 Stefan Monnier <monnier@cs.yale.edu>
* startup.el (fancy-splash-screens): Use local rather than global map. * startup.el (fancy-splash-screens): Use local rather than global map.
Don't use `update-menu-bindings' any more. Don't use `update-menu-bindings' any more.
Get rid of assumptions about keymap representation. Get rid of assumptions about keymap representation.
@ -1362,9 +1443,6 @@
2000-09-16 Andrew Innes <andrewi@gnu.org> 2000-09-16 Andrew Innes <andrewi@gnu.org>
* makefile.nt (compile-files): No need to make .elc files
read-only, since they aren't under VC now.
* makefile.w32-in (compile-files-CMD): No need to make .elc files * makefile.w32-in (compile-files-CMD): No need to make .elc files
read-only, since they aren't under VC now. read-only, since they aren't under VC now.

View File

@ -243,7 +243,7 @@ resulting regular expression."
(INCLUDE-REGEXP EXCLUDE-REGEXP (PRED-FUNC-LIST) (MOD-FUNC-LIST))" (INCLUDE-REGEXP EXCLUDE-REGEXP (PRED-FUNC-LIST) (MOD-FUNC-LIST))"
(let ((paths (eshell-split-path glob)) (let ((paths (eshell-split-path glob))
matches message-shown) matches message-shown ange-cache)
(unwind-protect (unwind-protect
(if (and (cdr paths) (if (and (cdr paths)
(file-name-absolute-p (car paths))) (file-name-absolute-p (car paths)))

View File

@ -192,9 +192,15 @@ really need to stick around for very long."
"Test whether, for ATTRS, the user UID can do what corresponds to INDEX. "Test whether, for ATTRS, the user UID can do what corresponds to INDEX.
This is really just for efficiency, to avoid having to stat the file This is really just for efficiency, to avoid having to stat the file
yet again." yet again."
`(if (= (user-uid) (nth 2 ,attrs)) `(if (numberp (nth 2 ,attrs))
(not (eq (aref (nth 8 ,attrs) ,index) ?-)) (if (= (user-uid) (nth 2 ,attrs))
(,(eval func) ,file))) (not (eq (aref (nth 8 ,attrs) ,index) ?-))
(,(eval func) ,file))
(not (eq (aref (nth 8 ,attrs)
(+ ,index (if (member (nth 2 ,attrs)
(eshell-current-ange-uids))
0 6)))
?-))))
(defcustom eshell-ls-highlight-alist nil (defcustom eshell-ls-highlight-alist nil
"*This alist correlates test functions to color. "*This alist correlates test functions to color.
@ -265,7 +271,8 @@ instead."
(defvar show-all) (defvar show-all)
(defvar show-recursive) (defvar show-recursive)
(defvar show-size) (defvar show-size)
(defvar sort-method)) (defvar sort-method)
(defvar ange-cache))
(defun eshell-do-ls (&rest args) (defun eshell-do-ls (&rest args)
"Implementation of \"ls\" in Lisp, passing ARGS." "Implementation of \"ls\" in Lisp, passing ARGS."
@ -328,7 +335,7 @@ Sort entries alphabetically across.")
(setq listing-style 'by-columns)) (setq listing-style 'by-columns))
(unless args (unless args
(setq args (list "."))) (setq args (list ".")))
(let ((eshell-ls-exclude-regexp eshell-ls-exclude-regexp)) (let ((eshell-ls-exclude-regexp eshell-ls-exclude-regexp) ange-cache)
(when ignore-pattern (when ignore-pattern
(unless (eshell-using-module 'eshell-glob) (unless (eshell-using-module 'eshell-glob)
(error (concat "-I option requires that `eshell-glob'" (error (concat "-I option requires that `eshell-glob'"
@ -347,7 +354,7 @@ Sort entries alphabetically across.")
(file-name-absolute-p arg)) (file-name-absolute-p arg))
(expand-file-name arg) (expand-file-name arg)
arg) arg)
(file-attributes arg)))) args) (eshell-file-attributes arg)))) args)
t (expand-file-name default-directory))) t (expand-file-name default-directory)))
(funcall flush-func))) (funcall flush-func)))
@ -379,7 +386,7 @@ name should be displayed as, etc. Think of it as cooking a FILEINFO."
(file-name-directory (file-name-directory
(expand-file-name (car fileinfo)))))) (expand-file-name (car fileinfo))))))
(setq attr (setq attr
(file-attributes (eshell-file-attributes
(let ((target (if dir (let ((target (if dir
(expand-file-name (cadr fileinfo) dir) (expand-file-name (cadr fileinfo) dir)
(cadr fileinfo)))) (cadr fileinfo))))
@ -425,16 +432,22 @@ whose cdr is the list of file attributes."
"%s%4d %-8s %-8s " "%s%4d %-8s %-8s "
(or (nth 8 attrs) "??????????") (or (nth 8 attrs) "??????????")
(or (nth 1 attrs) 0) (or (nth 1 attrs) 0)
(or (and (not numeric-uid-gid) (or (let ((user (nth 2 attrs)))
(nth 2 attrs) (and (not numeric-uid-gid)
(eshell-substring user
(user-login-name (nth 2 attrs)) 8)) (eshell-substring
(if (numberp user)
(user-login-name user)
user) 8)))
(nth 2 attrs) (nth 2 attrs)
"") "")
(or (and (not numeric-uid-gid) (or (let ((group (nth 3 attrs)))
(nth 3 attrs) (and (not numeric-uid-gid)
(eshell-substring group
(eshell-group-name (nth 3 attrs)) 8)) (eshell-substring
(if (numberp group)
(eshell-group-name group)
group) 8)))
(nth 3 attrs) (nth 3 attrs)
"")) ""))
(let* ((str (eshell-ls-printable-size (nth 7 attrs))) (let* ((str (eshell-ls-printable-size (nth 7 attrs)))

View File

@ -464,7 +464,7 @@ that 'ls -l' will show in the first column of its display. "
(forward-char) (forward-char)
(setq type ?%))) (setq type ?%)))
`(lambda (file) `(lambda (file)
(let ((attrs (file-attributes (directory-file-name file)))) (let ((attrs (eshell-file-attributes (directory-file-name file))))
(if attrs (if attrs
(memq (aref (nth 8 attrs) 0) (memq (aref (nth 8 attrs) 0)
,(if (eq type ?%) ,(if (eq type ?%)
@ -489,7 +489,7 @@ that 'ls -l' will show in the first column of its display. "
(setq amount (string-to-number (match-string 0))) (setq amount (string-to-number (match-string 0)))
(goto-char (match-end 0)) (goto-char (match-end 0))
`(lambda (file) `(lambda (file)
(let ((attrs (file-attributes file))) (let ((attrs (eshell-file-attributes file)))
(if attrs (if attrs
(,(if (eq qual ?-) (,(if (eq qual ?-)
'< '<
@ -518,7 +518,7 @@ that 'ls -l' will show in the first column of its display. "
(setq amount (* (string-to-number (match-string 0)) quantum)) (setq amount (* (string-to-number (match-string 0)) quantum))
(goto-char (match-end 0)) (goto-char (match-end 0))
`(lambda (file) `(lambda (file)
(let ((attrs (file-attributes file))) (let ((attrs (eshell-file-attributes file)))
(if attrs (if attrs
(,(if (eq qual ?-) (,(if (eq qual ?-)
'< '<

View File

@ -232,7 +232,7 @@ lock it at that."
Sends an EOF only if point is at the end of the buffer and there is no Sends an EOF only if point is at the end of the buffer and there is no
input." input."
(interactive "p") (interactive "p")
(let ((proc (get-buffer-process (current-buffer)))) (let ((proc (eshell-interactive-process)))
(if (eobp) (if (eobp)
(cond (cond
((/= (point) eshell-last-output-end) ((/= (point) eshell-last-output-end)

View File

@ -122,6 +122,12 @@ Otherwise, `rmdir' is required."
:type 'boolean :type 'boolean
:group 'eshell-unix) :group 'eshell-unix)
(defcustom eshell-du-prefer-over-ange nil
"*Use Eshell's du in ange-ftp remote directories.
Otherwise, Emacs will attempt to use rsh to invoke du the machine."
:type 'boolean
:group 'eshell-unix)
(require 'esh-opt) (require 'esh-opt)
;;; Functions: ;;; Functions:
@ -296,7 +302,7 @@ Remove the DIRECTORY(ies), if they are empty.")
"Shuffle around some filesystem entries, using FUNC to do the work." "Shuffle around some filesystem entries, using FUNC to do the work."
(if (null target) (if (null target)
(error "%s: missing destination file" command)) (error "%s: missing destination file" command))
(let ((attr-target (file-attributes target)) (let ((attr-target (eshell-file-attributes target))
(is-dir (or (file-directory-p target) (is-dir (or (file-directory-p target)
(and preview (not eshell-warn-dot-directories)))) (and preview (not eshell-warn-dot-directories))))
attr) attr)
@ -315,8 +321,10 @@ Remove the DIRECTORY(ies), if they are empty.")
((and attr-target ((and attr-target
(or (not (eshell-under-windows-p)) (or (not (eshell-under-windows-p))
(eq system-type 'ms-dos)) (eq system-type 'ms-dos))
(setq attr (file-attributes (car files))) (setq attr (eshell-file-attributes (car files)))
(nth 10 attr-target) (nth 10 attr)
(= (nth 10 attr-target) (nth 10 attr)) (= (nth 10 attr-target) (nth 10 attr))
(nth 11 attr-target) (nth 11 attr)
(= (nth 11 attr-target) (nth 11 attr))) (= (nth 11 attr-target) (nth 11 attr)))
(eshell-error (format "%s: `%s' and `%s' are the same file\n" (eshell-error (format "%s: `%s' and `%s' are the same file\n"
command (car files) target))) command (car files) target)))
@ -339,10 +347,10 @@ Remove the DIRECTORY(ies), if they are empty.")
(let (eshell-warn-dot-directories) (let (eshell-warn-dot-directories)
(if (and (not deep) (if (and (not deep)
(eq func 'rename-file) (eq func 'rename-file)
(= (nth 11 (file-attributes (= (nth 11 (eshell-file-attributes
(file-name-directory (file-name-directory
(expand-file-name source)))) (expand-file-name source))))
(nth 11 (file-attributes (nth 11 (eshell-file-attributes
(file-name-directory (file-name-directory
(expand-file-name target)))))) (expand-file-name target))))))
(apply 'eshell-funcalln func source target args) (apply 'eshell-funcalln func source target args)
@ -415,7 +423,7 @@ Remove the DIRECTORY(ies), if they are empty.")
(or (not no-dereference) (or (not no-dereference)
(not (file-symlink-p (car args))))))) (not (file-symlink-p (car args)))))))
(eshell-shorthand-tar-command ,command args) (eshell-shorthand-tar-command ,command args)
(let (target) (let (target ange-cache)
(if (> (length args) 1) (if (> (length args) 1)
(progn (progn
(setq target (car (last args))) (setq target (car (last args)))
@ -508,7 +516,7 @@ Create a link to the specified TARGET with optional LINK_NAME. If there is
more than one TARGET, the last argument must be a directory; create links more than one TARGET, the last argument must be a directory; create links
in DIRECTORY to each TARGET. Create hard links by default, symbolic links in DIRECTORY to each TARGET. Create hard links by default, symbolic links
with '--symbolic'. When creating hard links, each TARGET must exist.") with '--symbolic'. When creating hard links, each TARGET must exist.")
(let (target no-dereference) (let (target no-dereference ange-cache)
(if (> (length args) 1) (if (> (length args) 1)
(progn (progn
(setq target (car (last args))) (setq target (car (last args)))
@ -525,10 +533,24 @@ with '--symbolic'. When creating hard links, each TARGET must exist.")
nil)) nil))
(defun eshell/cat (&rest args) (defun eshell/cat (&rest args)
"Implementation of cat in Lisp." "Implementation of cat in Lisp.
(if eshell-in-pipeline-p If in a pipeline, or the file is not a regular file, directory or
(throw 'eshell-replace-command symlink, then revert to the system's definition of cat."
(eshell-parse-command "*cat" (eshell-flatten-list args))) (setq args (eshell-flatten-list args))
(if (or eshell-in-pipeline-p
(catch 'special
(eshell-for arg args
(unless (let ((attrs (eshell-file-attributes arg)))
(and attrs (memq (aref (nth 8 attrs) 0)
'(?d ?l ?-))))
(throw 'special t)))))
(let ((ext-cat (eshell-search-path "cat")))
(if ext-cat
(throw 'eshell-replace-command
(eshell-parse-command ext-cat args))
(if eshell-in-pipeline-p
(error "Eshell's `cat' does not work in pipelines")
(error "Eshell's `cat' cannot display one of the files given"))))
(eshell-init-print-buffer) (eshell-init-print-buffer)
(eshell-eval-using-options (eshell-eval-using-options
"cat" args "cat" args
@ -772,61 +794,69 @@ external command."
(defun eshell/du (&rest args) (defun eshell/du (&rest args)
"Implementation of \"du\" in Lisp, passing ARGS." "Implementation of \"du\" in Lisp, passing ARGS."
(if (eshell-search-path "du") (setq args (if args
(throw 'eshell-replace-command (eshell-flatten-list args)
(eshell-parse-command "*du" (eshell-flatten-list args))) '(".")))
(eshell-eval-using-options (let ((ext-du (eshell-search-path "du")))
"du" args (if (and ext-du
'((?a "all" nil show-all (not (catch 'have-ange-path
"write counts for all files, not just directories") (eshell-for arg args
(nil "block-size" t block-size (if (eq (find-file-name-handler (expand-file-name arg)
"use SIZE-byte blocks (i.e., --block-size SIZE)") 'directory-files)
(?b "bytes" nil by-bytes 'ange-ftp-hook-function)
"print size in bytes") (throw 'have-ange-path t))))))
(?c "total" nil grand-total (throw 'eshell-replace-command
"produce a grand total") (eshell-parse-command ext-du args))
(?d "max-depth" t max-depth (eshell-eval-using-options
"display data only this many levels of data") "du" args
(?h "human-readable" 1024 human-readable '((?a "all" nil show-all
"print sizes in human readable format") "write counts for all files, not just directories")
(?H "is" 1000 human-readable (nil "block-size" t block-size
"likewise, but use powers of 1000 not 1024") "use SIZE-byte blocks (i.e., --block-size SIZE)")
(?k "kilobytes" 1024 block-size (?b "bytes" nil by-bytes
"like --block-size 1024") "print size in bytes")
(?L "dereference" nil dereference-links (?c "total" nil grand-total
"dereference all symbolic links") "produce a grand total")
(?m "megabytes" 1048576 block-size (?d "max-depth" t max-depth
"like --block-size 1048576") "display data only this many levels of data")
(?s "summarize" 0 max-depth (?h "human-readable" 1024 human-readable
"display only a total for each argument") "print sizes in human readable format")
(?x "one-file-system" nil only-one-filesystem (?H "is" 1000 human-readable
"skip directories on different filesystems") "likewise, but use powers of 1000 not 1024")
(nil "help" nil nil (?k "kilobytes" 1024 block-size
"show this usage screen") "like --block-size 1024")
:external "du" (?L "dereference" nil dereference-links
:usage "[OPTION]... FILE... "dereference all symbolic links")
(?m "megabytes" 1048576 block-size
"like --block-size 1048576")
(?s "summarize" 0 max-depth
"display only a total for each argument")
(?x "one-file-system" nil only-one-filesystem
"skip directories on different filesystems")
(nil "help" nil nil
"show this usage screen")
:external "du"
:usage "[OPTION]... FILE...
Summarize disk usage of each FILE, recursively for directories.") Summarize disk usage of each FILE, recursively for directories.")
(unless by-bytes (unless by-bytes
(setq block-size (or block-size 1024))) (setq block-size (or block-size 1024)))
(if (and max-depth (stringp max-depth)) (if (and max-depth (stringp max-depth))
(setq max-depth (string-to-int max-depth))) (setq max-depth (string-to-int max-depth)))
;; filesystem support means nothing under Windows ;; filesystem support means nothing under Windows
(if (eshell-under-windows-p) (if (eshell-under-windows-p)
(setq only-one-filesystem nil)) (setq only-one-filesystem nil))
(unless args (let ((size 0.0) ange-cache)
(setq args '("."))) (while args
(let ((size 0.0)) (if only-one-filesystem
(while args (setq only-one-filesystem
(if only-one-filesystem (nth 11 (eshell-file-attributes
(setq only-one-filesystem (file-name-as-directory (car args))))))
(nth 11 (file-attributes (setq size (+ size (eshell-du-sum-directory
(file-name-as-directory (car args)))))) (directory-file-name (car args)) 0)))
(setq size (+ size (eshell-du-sum-directory (setq args (cdr args)))
(directory-file-name (car args)) 0))) (if grand-total
(setq args (cdr args))) (eshell-print (concat (eshell-du-size-string size)
(if grand-total "total\n"))))))))
(eshell-print (concat (eshell-du-size-string size)
"total\n")))))))
(defvar eshell-time-start nil) (defvar eshell-time-start nil)

View File

@ -328,13 +328,13 @@ special character that is not itself a backslash."
(defun eshell-parse-double-quote () (defun eshell-parse-double-quote ()
"Parse a double quoted string, which allows for variable interpolation." "Parse a double quoted string, which allows for variable interpolation."
(when (eq (char-after) ?\") (when (eq (char-after) ?\")
(forward-char)
(let* ((end (eshell-find-delimiter ?\" ?\" nil nil t)) (let* ((end (eshell-find-delimiter ?\" ?\" nil nil t))
(eshell-current-quoted t)) (eshell-current-quoted t))
(if (not end) (if (not end)
(throw 'eshell-incomplete ?\") (throw 'eshell-incomplete ?\")
(prog1 (prog1
(save-restriction (save-restriction
(forward-char)
(narrow-to-region (point) end) (narrow-to-region (point) end)
(list 'eshell-escape-arg (list 'eshell-escape-arg
(eshell-parse-argument))) (eshell-parse-argument)))

View File

@ -524,8 +524,9 @@ sessions, such as when using `eshell-command'.")
(interactive) (interactive)
(require 'etags) (require 'etags)
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(no-default (eobp))) (no-default (eobp))
(setq tagname (find-tag-interactive "Find tag: " no-default)) (find-tag-default-function 'ignore))
(setq tagname (car (find-tag-interactive "Find tag: ")))
(find-tag tagname next-p regexp-p))) (find-tag tagname next-p regexp-p)))
(defun eshell-move-argument (limit func property arg) (defun eshell-move-argument (limit func property arg)

View File

@ -86,6 +86,15 @@ function `string-to-number'."
:type 'regexp :type 'regexp
:group 'eshell-util) :group 'eshell-util)
(defcustom eshell-ange-ls-uids nil
"*List of user/host/id strings, used to determine remote ownership."
:type '(list (cons :tag "Host/User Pair"
(string :tag "Hostname")
(repeat (cons :tag "User/UID List"
(string :tag "Username")
(repeat :tag "UIDs" string)))))
:group 'eshell-util)
;;; Internal Variables: ;;; Internal Variables:
(defvar eshell-group-names nil (defvar eshell-group-names nil
@ -558,28 +567,123 @@ Unless optional argument INPLACE is non-nil, return a new string."
(unless (fboundp 'directory-files-and-attributes) (unless (fboundp 'directory-files-and-attributes)
(defun directory-files-and-attributes (dir &optional full match nosort) (defun directory-files-and-attributes (dir &optional full match nosort)
(documentation 'directory-files) (documentation 'directory-files)
(let* ((dir (expand-file-name dir)) (let ((dir (expand-file-name dir)) ange-cache)
(default-directory dir))
(mapcar (mapcar
(function (function
(lambda (file) (lambda (file)
(cons file (file-attributes file)))) (cons file (eshell-file-attributes (expand-file-name file dir)))))
(directory-files dir full match nosort))))) (directory-files dir full match nosort)))))
(eval-when-compile
(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)
"Make sure to use the handler for `directory-file-and-attributes'." "Make sure to use the handler for `directory-file-and-attributes'."
(let ((dfh (find-file-name-handler dir 'directory-files))) (let* ((dir (expand-file-name dir))
(dfh (find-file-name-handler dir 'directory-files)))
(if (not dfh) (if (not dfh)
(directory-files-and-attributes dir full match nosort) (directory-files-and-attributes dir full match nosort)
(let* ((files (funcall dfh 'directory-files dir full match nosort)) (let ((files (funcall dfh 'directory-files dir full match nosort))
(fah (find-file-name-handler dir 'file-attributes)) (fah (find-file-name-handler dir 'file-attributes)))
(default-directory (expand-file-name dir)))
(mapcar (mapcar
(function (function
(lambda (file) (lambda (file)
(cons file (funcall fah 'file-attributes file)))) (cons file (if fah
(eshell-file-attributes
(expand-file-name file dir))
(file-attributes (expand-file-name file dir))))))
files))))) files)))))
(defun eshell-current-ange-uids ()
(if (string-match "/\\([^@]+\\)@\\([^:]+\\):" default-directory)
(let* ((host (match-string 2 default-directory))
(user (match-string 1 default-directory))
(host-users (assoc host eshell-ange-ls-uids)))
(when host-users
(setq host-users (cdr host-users))
(cdr (assoc user host-users))))))
;; Add an autoload for parse-time-string
(if (and (not (fboundp 'parse-time-string))
(locate-library "parse-time"))
(autoload 'parse-time-string "parse-time"))
(defun eshell-parse-ange-ls (dir)
(let (entry)
(with-temp-buffer
(insert (ange-ftp-ls dir "-la" nil))
(goto-char (point-min))
(if (looking-at "^total [0-9]+$")
(forward-line 1))
;; Some systems put in a blank line here.
(if (eolp) (forward-line 1))
(while (looking-at
`,(concat "\\([dlscb-][rwxst-]+\\)"
"\\s-*" "\\([0-9]+\\)" "\\s-+"
"\\(\\S-+\\)" "\\s-+"
"\\(\\S-+\\)" "\\s-+"
"\\([0-9]+\\)" "\\s-+" "\\(.*\\)"))
(let* ((perms (match-string 1))
(links (string-to-number (match-string 2)))
(user (match-string 3))
(group (match-string 4))
(size (string-to-number (match-string 5)))
(mtime
(if (fboundp 'parse-time-string)
(let ((moment (parse-time-string
(match-string 6))))
(if (nth 0 moment)
(setcar (nthcdr 5 moment)
(nth 5 (decode-time (current-time))))
(setcar (nthcdr 0 moment) 0)
(setcar (nthcdr 1 moment) 0)
(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)
name (match-string 1 name)))
(setq entry
(cons
(cons name
(list (if (eq (aref perms 0) ?d)
t
symlink)
links user group
nil mtime nil
size perms nil nil)) entry)))
(forward-line)))
entry))
(defun eshell-file-attributes (file)
"Return the attributes of FILE, playing tricks if it's over ange-ftp."
(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 (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)))))
(defun eshell-copy-list (list) (defun eshell-copy-list (list)
"Return a copy of a list, which may be a dotted list. "Return a copy of a list, which may be a dotted list.
The elements of the list are not copied, just the list structure itself." The elements of the list are not copied, just the list structure itself."