;;; esh-util.el --- general utilities
-;; Copyright (C) 1999, 2000, 2001 Free Software Foundation
+;; 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
;;; 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)))
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))
(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))
;; "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."
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
(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)
(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))
(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
(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)
(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)
; (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