mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-26 10:49:33 +00:00
Added better remote directory support to Eshell, as well as a few bug
fixes. See the ChangeLog.
This commit is contained in:
parent
e2c06b17a9
commit
8c6b1d8311
@ -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>
|
||||
|
||||
* image-file.el (image-file-name-extensions)
|
||||
@ -347,6 +426,8 @@
|
||||
* files.el (set-auto-mode): Ignore unknown -*- mode -*- rather than
|
||||
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.
|
||||
Don't use `update-menu-bindings' any more.
|
||||
Get rid of assumptions about keymap representation.
|
||||
@ -1362,9 +1443,6 @@
|
||||
|
||||
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
|
||||
read-only, since they aren't under VC now.
|
||||
|
||||
|
@ -243,7 +243,7 @@ resulting regular expression."
|
||||
|
||||
(INCLUDE-REGEXP EXCLUDE-REGEXP (PRED-FUNC-LIST) (MOD-FUNC-LIST))"
|
||||
(let ((paths (eshell-split-path glob))
|
||||
matches message-shown)
|
||||
matches message-shown ange-cache)
|
||||
(unwind-protect
|
||||
(if (and (cdr paths)
|
||||
(file-name-absolute-p (car paths)))
|
||||
|
@ -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.
|
||||
This is really just for efficiency, to avoid having to stat the file
|
||||
yet again."
|
||||
`(if (= (user-uid) (nth 2 ,attrs))
|
||||
(not (eq (aref (nth 8 ,attrs) ,index) ?-))
|
||||
(,(eval func) ,file)))
|
||||
`(if (numberp (nth 2 ,attrs))
|
||||
(if (= (user-uid) (nth 2 ,attrs))
|
||||
(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
|
||||
"*This alist correlates test functions to color.
|
||||
@ -265,7 +271,8 @@ instead."
|
||||
(defvar show-all)
|
||||
(defvar show-recursive)
|
||||
(defvar show-size)
|
||||
(defvar sort-method))
|
||||
(defvar sort-method)
|
||||
(defvar ange-cache))
|
||||
|
||||
(defun eshell-do-ls (&rest args)
|
||||
"Implementation of \"ls\" in Lisp, passing ARGS."
|
||||
@ -328,7 +335,7 @@ Sort entries alphabetically across.")
|
||||
(setq listing-style 'by-columns))
|
||||
(unless args
|
||||
(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
|
||||
(unless (eshell-using-module 'eshell-glob)
|
||||
(error (concat "-I option requires that `eshell-glob'"
|
||||
@ -347,7 +354,7 @@ Sort entries alphabetically across.")
|
||||
(file-name-absolute-p arg))
|
||||
(expand-file-name arg)
|
||||
arg)
|
||||
(file-attributes arg)))) args)
|
||||
(eshell-file-attributes arg)))) args)
|
||||
t (expand-file-name default-directory)))
|
||||
(funcall flush-func)))
|
||||
|
||||
@ -379,7 +386,7 @@ name should be displayed as, etc. Think of it as cooking a FILEINFO."
|
||||
(file-name-directory
|
||||
(expand-file-name (car fileinfo))))))
|
||||
(setq attr
|
||||
(file-attributes
|
||||
(eshell-file-attributes
|
||||
(let ((target (if dir
|
||||
(expand-file-name (cadr fileinfo) dir)
|
||||
(cadr fileinfo))))
|
||||
@ -425,16 +432,22 @@ whose cdr is the list of file attributes."
|
||||
"%s%4d %-8s %-8s "
|
||||
(or (nth 8 attrs) "??????????")
|
||||
(or (nth 1 attrs) 0)
|
||||
(or (and (not numeric-uid-gid)
|
||||
(nth 2 attrs)
|
||||
(eshell-substring
|
||||
(user-login-name (nth 2 attrs)) 8))
|
||||
(or (let ((user (nth 2 attrs)))
|
||||
(and (not numeric-uid-gid)
|
||||
user
|
||||
(eshell-substring
|
||||
(if (numberp user)
|
||||
(user-login-name user)
|
||||
user) 8)))
|
||||
(nth 2 attrs)
|
||||
"")
|
||||
(or (and (not numeric-uid-gid)
|
||||
(nth 3 attrs)
|
||||
(eshell-substring
|
||||
(eshell-group-name (nth 3 attrs)) 8))
|
||||
(or (let ((group (nth 3 attrs)))
|
||||
(and (not numeric-uid-gid)
|
||||
group
|
||||
(eshell-substring
|
||||
(if (numberp group)
|
||||
(eshell-group-name group)
|
||||
group) 8)))
|
||||
(nth 3 attrs)
|
||||
""))
|
||||
(let* ((str (eshell-ls-printable-size (nth 7 attrs)))
|
||||
|
@ -464,7 +464,7 @@ that 'ls -l' will show in the first column of its display. "
|
||||
(forward-char)
|
||||
(setq type ?%)))
|
||||
`(lambda (file)
|
||||
(let ((attrs (file-attributes (directory-file-name file))))
|
||||
(let ((attrs (eshell-file-attributes (directory-file-name file))))
|
||||
(if attrs
|
||||
(memq (aref (nth 8 attrs) 0)
|
||||
,(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)))
|
||||
(goto-char (match-end 0))
|
||||
`(lambda (file)
|
||||
(let ((attrs (file-attributes file)))
|
||||
(let ((attrs (eshell-file-attributes file)))
|
||||
(if attrs
|
||||
(,(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))
|
||||
(goto-char (match-end 0))
|
||||
`(lambda (file)
|
||||
(let ((attrs (file-attributes file)))
|
||||
(let ((attrs (eshell-file-attributes file)))
|
||||
(if attrs
|
||||
(,(if (eq qual ?-)
|
||||
'<
|
||||
|
@ -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
|
||||
input."
|
||||
(interactive "p")
|
||||
(let ((proc (get-buffer-process (current-buffer))))
|
||||
(let ((proc (eshell-interactive-process)))
|
||||
(if (eobp)
|
||||
(cond
|
||||
((/= (point) eshell-last-output-end)
|
||||
|
@ -122,6 +122,12 @@ Otherwise, `rmdir' is required."
|
||||
:type 'boolean
|
||||
: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)
|
||||
|
||||
;;; Functions:
|
||||
@ -296,7 +302,7 @@ Remove the DIRECTORY(ies), if they are empty.")
|
||||
"Shuffle around some filesystem entries, using FUNC to do the work."
|
||||
(if (null target)
|
||||
(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)
|
||||
(and preview (not eshell-warn-dot-directories))))
|
||||
attr)
|
||||
@ -315,8 +321,10 @@ Remove the DIRECTORY(ies), if they are empty.")
|
||||
((and attr-target
|
||||
(or (not (eshell-under-windows-p))
|
||||
(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 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"
|
||||
command (car files) target)))
|
||||
@ -339,10 +347,10 @@ Remove the DIRECTORY(ies), if they are empty.")
|
||||
(let (eshell-warn-dot-directories)
|
||||
(if (and (not deep)
|
||||
(eq func 'rename-file)
|
||||
(= (nth 11 (file-attributes
|
||||
(= (nth 11 (eshell-file-attributes
|
||||
(file-name-directory
|
||||
(expand-file-name source))))
|
||||
(nth 11 (file-attributes
|
||||
(nth 11 (eshell-file-attributes
|
||||
(file-name-directory
|
||||
(expand-file-name target))))))
|
||||
(apply 'eshell-funcalln func source target args)
|
||||
@ -415,7 +423,7 @@ Remove the DIRECTORY(ies), if they are empty.")
|
||||
(or (not no-dereference)
|
||||
(not (file-symlink-p (car args)))))))
|
||||
(eshell-shorthand-tar-command ,command args)
|
||||
(let (target)
|
||||
(let (target ange-cache)
|
||||
(if (> (length args) 1)
|
||||
(progn
|
||||
(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
|
||||
in DIRECTORY to each TARGET. Create hard links by default, symbolic links
|
||||
with '--symbolic'. When creating hard links, each TARGET must exist.")
|
||||
(let (target no-dereference)
|
||||
(let (target no-dereference ange-cache)
|
||||
(if (> (length args) 1)
|
||||
(progn
|
||||
(setq target (car (last args)))
|
||||
@ -525,10 +533,24 @@ with '--symbolic'. When creating hard links, each TARGET must exist.")
|
||||
nil))
|
||||
|
||||
(defun eshell/cat (&rest args)
|
||||
"Implementation of cat in Lisp."
|
||||
(if eshell-in-pipeline-p
|
||||
(throw 'eshell-replace-command
|
||||
(eshell-parse-command "*cat" (eshell-flatten-list args)))
|
||||
"Implementation of cat in Lisp.
|
||||
If in a pipeline, or the file is not a regular file, directory or
|
||||
symlink, then revert to the system's definition of cat."
|
||||
(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-eval-using-options
|
||||
"cat" args
|
||||
@ -772,61 +794,69 @@ external command."
|
||||
|
||||
(defun eshell/du (&rest args)
|
||||
"Implementation of \"du\" in Lisp, passing ARGS."
|
||||
(if (eshell-search-path "du")
|
||||
(throw 'eshell-replace-command
|
||||
(eshell-parse-command "*du" (eshell-flatten-list args)))
|
||||
(eshell-eval-using-options
|
||||
"du" args
|
||||
'((?a "all" nil show-all
|
||||
"write counts for all files, not just directories")
|
||||
(nil "block-size" t block-size
|
||||
"use SIZE-byte blocks (i.e., --block-size SIZE)")
|
||||
(?b "bytes" nil by-bytes
|
||||
"print size in bytes")
|
||||
(?c "total" nil grand-total
|
||||
"produce a grand total")
|
||||
(?d "max-depth" t max-depth
|
||||
"display data only this many levels of data")
|
||||
(?h "human-readable" 1024 human-readable
|
||||
"print sizes in human readable format")
|
||||
(?H "is" 1000 human-readable
|
||||
"likewise, but use powers of 1000 not 1024")
|
||||
(?k "kilobytes" 1024 block-size
|
||||
"like --block-size 1024")
|
||||
(?L "dereference" nil dereference-links
|
||||
"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...
|
||||
(setq args (if args
|
||||
(eshell-flatten-list args)
|
||||
'(".")))
|
||||
(let ((ext-du (eshell-search-path "du")))
|
||||
(if (and ext-du
|
||||
(not (catch 'have-ange-path
|
||||
(eshell-for arg args
|
||||
(if (eq (find-file-name-handler (expand-file-name arg)
|
||||
'directory-files)
|
||||
'ange-ftp-hook-function)
|
||||
(throw 'have-ange-path t))))))
|
||||
(throw 'eshell-replace-command
|
||||
(eshell-parse-command ext-du args))
|
||||
(eshell-eval-using-options
|
||||
"du" args
|
||||
'((?a "all" nil show-all
|
||||
"write counts for all files, not just directories")
|
||||
(nil "block-size" t block-size
|
||||
"use SIZE-byte blocks (i.e., --block-size SIZE)")
|
||||
(?b "bytes" nil by-bytes
|
||||
"print size in bytes")
|
||||
(?c "total" nil grand-total
|
||||
"produce a grand total")
|
||||
(?d "max-depth" t max-depth
|
||||
"display data only this many levels of data")
|
||||
(?h "human-readable" 1024 human-readable
|
||||
"print sizes in human readable format")
|
||||
(?H "is" 1000 human-readable
|
||||
"likewise, but use powers of 1000 not 1024")
|
||||
(?k "kilobytes" 1024 block-size
|
||||
"like --block-size 1024")
|
||||
(?L "dereference" nil dereference-links
|
||||
"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.")
|
||||
(unless by-bytes
|
||||
(setq block-size (or block-size 1024)))
|
||||
(if (and max-depth (stringp max-depth))
|
||||
(setq max-depth (string-to-int max-depth)))
|
||||
;; filesystem support means nothing under Windows
|
||||
(if (eshell-under-windows-p)
|
||||
(setq only-one-filesystem nil))
|
||||
(unless args
|
||||
(setq args '(".")))
|
||||
(let ((size 0.0))
|
||||
(while args
|
||||
(if only-one-filesystem
|
||||
(setq only-one-filesystem
|
||||
(nth 11 (file-attributes
|
||||
(file-name-as-directory (car args))))))
|
||||
(setq size (+ size (eshell-du-sum-directory
|
||||
(directory-file-name (car args)) 0)))
|
||||
(setq args (cdr args)))
|
||||
(if grand-total
|
||||
(eshell-print (concat (eshell-du-size-string size)
|
||||
"total\n")))))))
|
||||
(unless by-bytes
|
||||
(setq block-size (or block-size 1024)))
|
||||
(if (and max-depth (stringp max-depth))
|
||||
(setq max-depth (string-to-int max-depth)))
|
||||
;; filesystem support means nothing under Windows
|
||||
(if (eshell-under-windows-p)
|
||||
(setq only-one-filesystem nil))
|
||||
(let ((size 0.0) ange-cache)
|
||||
(while args
|
||||
(if only-one-filesystem
|
||||
(setq only-one-filesystem
|
||||
(nth 11 (eshell-file-attributes
|
||||
(file-name-as-directory (car args))))))
|
||||
(setq size (+ size (eshell-du-sum-directory
|
||||
(directory-file-name (car args)) 0)))
|
||||
(setq args (cdr args)))
|
||||
(if grand-total
|
||||
(eshell-print (concat (eshell-du-size-string size)
|
||||
"total\n"))))))))
|
||||
|
||||
(defvar eshell-time-start nil)
|
||||
|
||||
|
@ -328,13 +328,13 @@ special character that is not itself a backslash."
|
||||
(defun eshell-parse-double-quote ()
|
||||
"Parse a double quoted string, which allows for variable interpolation."
|
||||
(when (eq (char-after) ?\")
|
||||
(forward-char)
|
||||
(let* ((end (eshell-find-delimiter ?\" ?\" nil nil t))
|
||||
(eshell-current-quoted t))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\")
|
||||
(prog1
|
||||
(save-restriction
|
||||
(forward-char)
|
||||
(narrow-to-region (point) end)
|
||||
(list 'eshell-escape-arg
|
||||
(eshell-parse-argument)))
|
||||
|
@ -524,8 +524,9 @@ sessions, such as when using `eshell-command'.")
|
||||
(interactive)
|
||||
(require 'etags)
|
||||
(let ((inhibit-read-only t)
|
||||
(no-default (eobp)))
|
||||
(setq tagname (find-tag-interactive "Find tag: " no-default))
|
||||
(no-default (eobp))
|
||||
(find-tag-default-function 'ignore))
|
||||
(setq tagname (car (find-tag-interactive "Find tag: ")))
|
||||
(find-tag tagname next-p regexp-p)))
|
||||
|
||||
(defun eshell-move-argument (limit func property arg)
|
||||
|
@ -86,6 +86,15 @@ function `string-to-number'."
|
||||
:type 'regexp
|
||||
: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:
|
||||
|
||||
(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)
|
||||
(defun directory-files-and-attributes (dir &optional full match nosort)
|
||||
(documentation 'directory-files)
|
||||
(let* ((dir (expand-file-name dir))
|
||||
(default-directory dir))
|
||||
(let ((dir (expand-file-name dir)) ange-cache)
|
||||
(mapcar
|
||||
(function
|
||||
(lambda (file)
|
||||
(cons file (file-attributes file))))
|
||||
(cons file (eshell-file-attributes (expand-file-name file dir)))))
|
||||
(directory-files dir full match nosort)))))
|
||||
|
||||
(eval-when-compile
|
||||
(defvar ange-cache))
|
||||
|
||||
(defun eshell-directory-files-and-attributes (dir &optional full match nosort)
|
||||
"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)
|
||||
(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))
|
||||
(default-directory (expand-file-name dir)))
|
||||
(let ((files (funcall dfh 'directory-files dir full match nosort))
|
||||
(fah (find-file-name-handler dir 'file-attributes)))
|
||||
(mapcar
|
||||
(function
|
||||
(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)))))
|
||||
|
||||
(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)
|
||||
"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."
|
||||
|
Loading…
Reference in New Issue
Block a user