]> code.delx.au - gnu-emacs/blobdiff - lisp/ls-lisp.el
.
[gnu-emacs] / lisp / ls-lisp.el
index d8f52df45ea8366d2cb5f6b757b43c5e6a1223dd..9f6de6753c668bc471c79bb89961c9767951cd61 100644 (file)
@@ -2,10 +2,10 @@
 
 ;; Copyright (C) 1992, 1994, 2000 Free Software Foundation, Inc.
 
-;; Author:             Sebastian Kremer <sk@thp.uni-koeln.de>
-;; Modified by:                Francis J. Wright <F.J.Wright@maths.qmw.ac.uk>
-;; Maintainer:         FSF
-;; Keywords:           unix, dired
+;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
+;; Modified by: Francis J. Wright <F.J.Wright@maths.qmw.ac.uk>
+;; Maintainer: FSF
+;; Keywords: unix, dired
 
 ;; This file is part of GNU Emacs.
 
@@ -65,7 +65,6 @@
 
 ;;; Code:
 
-;;;###autoload
 (defgroup ls-lisp nil
   "Emulate the ls program completely in Emacs Lisp."
   :version "21.1"
@@ -113,7 +112,7 @@ option will have no effect until you restart Emacs."
        (t '(links uid gid)))           ; GNU ls
   "*A list of optional file attributes that ls-lisp should display.
 It should contain none or more of the symbols: links, uid, gid.
-Nil (or an empty list) means display none of them.
+nil (or an empty list) means display none of them.
 
 Concepts come from UNIX: `links' means count of names associated with
 the file\; `uid' means user (owner) identifier\; `gid' means group
@@ -144,13 +143,35 @@ Otherwise they are treated as Emacs regexps (for backward compatibility)."
   :type 'boolean
   :group 'ls-lisp)
 
+(defcustom ls-lisp-format-time-list
+  '("%b %e %H:%M"
+    "%b %e  %Y")
+  "*List of `format-time-string' specs to display file time stamps.
+They are used whenever a locale is not specified to use instead.
+
+Syntax:  (EARLY-TIME-FORMAT OLD-TIME-FORMAT)
+
+The EARLY-TIME-FORMAT is used if file has been modified within the
+current year. The OLD-TIME-FORMAT is used for older files.  To use ISO
+8601 dates, you could set:
+
+\(setq ls-lisp-format-time-list
+       '(\"%Y-%m-%d %H:%M\"
+         \"%Y-%m-%d      \"))"
+  :type '(list (string :tag "Early time format")
+              (string :tag "Old time format"))
+  :group 'ls-lisp)
+
+(defvar original-insert-directory nil
+  "This holds the original function definition of `insert-directory'.")
+
 ;; Remember the original insert-directory function
 (or (featurep 'ls-lisp)  ; FJW: unless this file is being reloaded!
-    (fset 'original-insert-directory (symbol-function 'insert-directory)))
+    (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.qmw.ac.uk/Emacs/:
+;; 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."
@@ -182,7 +203,8 @@ is non-nil; otherwise, it interprets wildcards as regular expressions
 to match file names.  It does not support all `ls' switches -- those
 that work are: A a c i r S s t u U X g G B C R and F partly."
   (if ls-lisp-use-insert-directory-program
-      (original-insert-directory file switches wildcard full-directory-p)
+      (funcall original-insert-directory
+              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)))
@@ -200,7 +222,18 @@ that work are: A a c i r S s t u U X g G B C R and F partly."
          (if (memq ?B switches) (setq wildcard "[^~]\\'")))
        (ls-lisp-insert-directory
         file switches (ls-lisp-time-index switches)
-        wildcard full-directory-p)))))
+        wildcard full-directory-p)
+       ;; Try to insert the amount of free space.
+       (save-excursion
+         (goto-char (point-min))
+         ;; First find the line to put it on.
+         (when (re-search-forward "^total" nil t)
+           (let ((available (get-free-disk-space ".")))
+             (when available
+               ;; Replace "total" with "total used", to avoid confusion.
+               (replace-match "total used in directory")
+               (end-of-line)
+               (insert " available " available)))))))))
 
 (defun ls-lisp-insert-directory
   (file switches time-index wildcard full-directory-p)
@@ -515,26 +548,40 @@ Return nil if no time switch found."
        ((memq ?t switches) 5)          ; last modtime
        ((memq ?u switches) 4)))        ; last access
 
+(defun ls-lisp-time-to-seconds (time)
+  "Convert TIME to a floating point number."
+  (+ (* (car time) 65536.0)
+     (cadr time)
+     (/ (or (nth 2 time) 0) 1000000.0)))
+
 (defun ls-lisp-format-time (file-attr time-index now)
   "Format time for file with attributes FILE-ATTR according to TIME-INDEX.
 Use the same method as ls to decide whether to show time-of-day or year,
 depending on distance between file date and NOW.
 All ls time options, namely c, t and u, are handled."
   (let* ((time (nth (or time-index 5) file-attr)) ; default is last modtime
-        (diff16 (- (car time) (car now)))
-        (diff (+ (ash diff16 16) (- (car (cdr time)) (car (cdr now)))))
-        (past-cutoff (- (* 6 30 24 60 60)))    ; 6 30-day months
-        (future-cutoff (* 60 60)))             ; 1 hour
+        (diff (- (ls-lisp-time-to-seconds time)
+                 (ls-lisp-time-to-seconds now)))
+        ;; Consider a time to be recent if it is within the past six
+        ;; months.  A Gregorian year has 365.2425 * 24 * 60 * 60 ==
+        ;; 31556952 seconds on the average, and half of that is 15778476.
+        ;; Write the constant explicitly to avoid roundoff error.
+        (past-cutoff -15778476)) ; half a Gregorian year
     (condition-case nil
-       (format-time-string
-        (if (and
-             (<= past-cutoff diff) (<= diff future-cutoff)
-             ;; Sanity check in case `diff' computation overflowed.
-             (<= (1- (ash past-cutoff -16)) diff16)
-             (<= diff16 (1+ (ash future-cutoff -16))))
-            "%b %e %H:%M"
-          "%b %e  %Y")
-        time)
+       ;; Use traditional time format in the C or POSIX locale,
+       ;; ISO-style time format otherwise, so columns line up.
+       (let ((locale system-time-locale))
+         (if (not locale)
+             (let ((vars '("LC_ALL" "LC_TIME" "LANG")))
+               (while (and vars (not (setq locale (getenv (car vars)))))
+                 (setq vars (cdr vars)))))
+         (if (member locale '("C" "POSIX"))
+             (setq locale nil))
+         (format-time-string
+          (if (and (<= past-cutoff diff) (<= diff 0))
+              (if locale "%m-%d %H:%M" (nth 0 ls-lisp-format-time-list))
+            (if locale "%Y-%m-%d " (nth 1 ls-lisp-format-time-list)))
+          time))
       (error "Unk  0  0000"))))
 
 (provide 'ls-lisp)