Mercurial > emacs
diff lisp/ls-lisp.el @ 88155:d7ddb3e565de
sync with trunk
author | Henrik Enberg <henrik.enberg@telia.com> |
---|---|
date | Mon, 16 Jan 2006 00:03:54 +0000 |
parents | 850f7b918635 |
children |
line wrap: on
line diff
--- a/lisp/ls-lisp.el Sun Jan 15 23:02:10 2006 +0000 +++ b/lisp/ls-lisp.el Mon Jan 16 00:03:54 2006 +0000 @@ -1,6 +1,7 @@ ;;; ls-lisp.el --- emulate insert-directory completely in Emacs Lisp -;; Copyright (C) 1992, 1994, 2000 Free Software Foundation, Inc. +;; Copyright (C) 1992, 1994, 2000, 2002, 2003, 2004, +;; 2005 Free Software Foundation, Inc. ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de> ;; Modified by: Francis J. Wright <F.J.Wright@maths.qmw.ac.uk> @@ -21,8 +22,8 @@ ;; 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., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. ;;; Commentary: @@ -44,8 +45,6 @@ ;; * A few obscure ls switches are still ignored: see the docstring of ;; `insert-directory'. -;; * Generally only numeric uid/gid. - ;; TO DO ============================================================= ;; Complete handling of F switch (if/when possible). @@ -60,11 +59,13 @@ ;; Revised by Andrew Innes and Geoff Volker (and maybe others). ;; Modified by Francis J. Wright <F.J.Wright@maths.qmw.ac.uk>, mainly -;; to support many more ls options, "platform emulation", hooks for -;; external symbolic link support and more robust sorting. +;; to support many more ls options, "platform emulation" and more +;; robust sorting. ;;; Code: +(eval-when-compile (require 'cl)) + (defgroup ls-lisp nil "Emulate the ls program completely in Emacs Lisp." :version "21.1" @@ -172,14 +173,6 @@ (or (featurep 'ls-lisp) ; FJW: unless this file is being reloaded! (setq original-insert-directory (symbol-function 'insert-directory))) -;; This stub is to allow ls-lisp to parse symbolic links via another -;; library such as w32-symlinks.el from -;; http://centaur.maths.qmw.ac.uk/Emacs/: -(defun ls-lisp-parse-symlink (file-name) - "This stub may be redefined to parse FILE-NAME as a symlink. -It should return nil or the link target as a string." - nil) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -210,22 +203,35 @@ file switches wildcard full-directory-p) ;; We need the directory in order to find the right handler. (let ((handler (find-file-name-handler (expand-file-name file) - 'insert-directory))) + 'insert-directory)) + wildcard-regexp) (if handler (funcall handler 'insert-directory file switches wildcard full-directory-p) + ;; Remove --dired switch + (if (string-match "--dired " switches) + (setq switches (replace-match "" nil nil switches))) ;; Convert SWITCHES to a list of characters. (setq switches (delete ?- (append switches nil))) + ;; Sometimes we get ".../foo*/" as FILE. While the shell and + ;; `ls' don't mind, we certainly do, because it makes us think + ;; there is no wildcard, only a directory name. + (if (and ls-lisp-support-shell-wildcards + (string-match "[[?*]" file)) + (progn + (or (not (eq (aref file (1- (length file))) ?/)) + (setq file (substring file 0 (1- (length file))))) + (setq wildcard t))) (if wildcard - (setq wildcard + (setq wildcard-regexp (if ls-lisp-support-shell-wildcards (wildcard-to-regexp (file-name-nondirectory file)) (file-name-nondirectory file)) file (file-name-directory file)) - (if (memq ?B switches) (setq wildcard "[^~]\\'"))) + (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'"))) (ls-lisp-insert-directory file switches (ls-lisp-time-index switches) - wildcard full-directory-p) + wildcard-regexp full-directory-p) ;; Try to insert the amount of free space. (save-excursion (goto-char (point-min)) @@ -239,29 +245,20 @@ (insert " available " available))))))))) (defun ls-lisp-insert-directory - (file switches time-index wildcard full-directory-p) + (file switches time-index wildcard-regexp full-directory-p) "Insert directory listing for FILE, formatted according to SWITCHES. Leaves point after the inserted text. This is an internal function optionally called by the `ls-lisp.el' version of `insert-directory'. It is called recursively if the -R switch is used. SWITCHES is a *list* of characters. TIME-INDEX is the time index into -file-attributes according to SWITCHES. WILDCARD is nil or an *Emacs +file-attributes according to SWITCHES. WILDCARD-REGEXP is nil or an *Emacs regexp*. FULL-DIRECTORY-P means file is a directory and SWITCHES does not contain `d', so that a full listing is expected." - ;; Sometimes we get ".../foo*/" as FILE. While the shell and - ;; `ls' don't mind, we certainly do, because it makes us think - ;; there is no wildcard, only a directory name. - (if (and ls-lisp-support-shell-wildcards - (string-match "[[?*]" file)) - (progn - (or (not (eq (aref file (1- (length file))) ?/)) - (setq file (substring file 0 (1- (length file))))) - (setq wildcard t))) - (if (or wildcard full-directory-p) + (if (or wildcard-regexp full-directory-p) (let* ((dir (file-name-as-directory file)) (default-directory dir) ; so that file-attributes works (file-alist - (directory-files-and-attributes dir nil wildcard t)) + (directory-files-and-attributes dir nil wildcard-regexp t 'string)) (now (current-time)) (sum 0) ;; do all bindings here for speed @@ -317,13 +314,13 @@ (setq elt (expand-file-name (car elt) dir)) (insert "\n" elt ":\n") (ls-lisp-insert-directory - elt switches time-index wildcard full-directory-p))))) + elt switches time-index wildcard-regexp full-directory-p))))) ;; If not full-directory-p, FILE *must not* end in /, as ;; file-attributes will not recognize a symlink to a directory, ;; so must make it a relative filename as ls does: (if (eq (aref file (1- (length file))) ?/) (setq file (substring file 0 -1))) - (let ((fattr (file-attributes file))) + (let ((fattr (file-attributes file 'string))) (if fattr (insert (ls-lisp-format file fattr (nth 7 fattr) switches time-index (current-time))) @@ -422,7 +419,9 @@ ;; symbolic link, or nil. (let (el dirs files) (while file-alist - (if (eq (cadr (setq el (car file-alist))) t) ; directory + (if (or (eq (cadr (setq el (car file-alist))) t) ; directory + (and (stringp (cadr el)) + (file-directory-p (cadr el)))) ; symlink to a directory (setq dirs (cons el dirs)) (setq files (cons el files))) (setq file-alist (cdr file-alist))) @@ -445,15 +444,14 @@ Also, for regular files that are executable, append `*'. The file type indicators are `/' for directories, `@' for symbolic links, `|' for FIFOs, `=' for sockets, and nothing for regular files. -\[But FIFOs and sockets are not recognised.] +\[But FIFOs and sockets are not recognized.] FILEDATA has the form (filename . `file-attributes'). Its `cadr' is t for directory, string (name linked to) for symbolic link, or nil." - (let ((dir (cadr filedata)) (file-name (car filedata))) - (cond ((or dir - ;; Parsing .lnk files here is perhaps overkill! - (setq dir (ls-lisp-parse-symlink file-name))) + (let ((file-name (car filedata)) + (type (cadr filedata))) + (cond (type (cons - (concat file-name (if (eq dir t) "/" "@")) + (concat file-name (if (eq type t) "/" "@")) (cdr filedata))) ((string-match "x" (nth 9 filedata)) (cons @@ -499,10 +497,6 @@ ;; t for directory, string (name linked to) ;; for symbolic link, or nil. (drwxrwxrwx (nth 8 file-attr))) ; attribute string ("drwxrwxrwx") - (and (null file-type) - ;; Maybe no kernel support for symlinks, so... - (setq file-type (ls-lisp-parse-symlink file-name)) - (aset drwxrwxrwx 0 ?l)) ; symbolic link - update attribute string (concat (if (memq ?i switches) ; inode number (format " %6d" (nth 10 file-attr))) ;; nil is treated like "" in concat @@ -516,28 +510,19 @@ ;; They tend to be bogus on non-UNIX platforms anyway so ;; optionally hide them. (if (memq 'uid ls-lisp-verbosity) - ;; (user-login-name uid) works on Windows NT but not - ;; on 9x and maybe not on some other platforms, so... + ;; uid can be a sting or an integer (let ((uid (nth 2 file-attr))) - (if (= uid (user-uid)) - (format " %-8s" (user-login-name)) - (format " %-8d" uid)))) + (format (if (stringp uid) " %-8s" " %-8d") uid))) (if (not (memq ?G switches)) ; GNU ls -- shows group by default (if (or (memq ?g switches) ; UNIX ls -- no group by default (memq 'gid ls-lisp-verbosity)) - (if (memq system-type '(macos windows-nt ms-dos)) - ;; No useful concept of group... - " root" - (let* ((gid (nth 3 file-attr)) - (group (user-login-name gid))) - (if group - (format " %-8s" group) - (format " %-8d" gid)))))) - (format (if (floatp file-size) " %8.0f" " %8d") file-size) + (let ((gid (nth 3 file-attr))) + (format (if (stringp gid) " %-8s" " %-8d") gid)))) + (ls-lisp-format-file-size file-size (memq ?h switches)) " " (ls-lisp-format-time file-attr time-index now) " " - file-name + (propertize file-name 'dired-filename t) (if (stringp file-type) ; is a symbolic link (concat " -> " file-type)) "\n" @@ -587,6 +572,16 @@ time)) (error "Unk 0 0000")))) +(defun ls-lisp-format-file-size (file-size human-readable) + (if (or (not human-readable) + (< file-size 1024)) + (format (if (floatp file-size) " %9.0f" " %9d") file-size) + (do ((file-size (/ file-size 1024.0) (/ file-size 1024.0)) + ;; kilo, mega, giga, tera, peta, exa + (post-fixes (list "k" "M" "G" "T" "P" "E") (cdr post-fixes))) + ((< file-size 1024) (format " %8.0f%s" file-size (car post-fixes)))))) + (provide 'ls-lisp) +;;; arch-tag: e55f399b-05ec-425c-a6d5-f5e349c35ab4 ;;; ls-lisp.el ends here