home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / misc / file-complete.el < prev    next >
Encoding:
Text File  |  1993-03-03  |  9.6 KB  |  256 lines

  1. ;; FILE-COMPLETE.EL -- Display file name completions in mod-time order.
  2. ;; Copyright (c) 1989 Free Software Foundation, Inc.
  3. ;;
  4. ;; LCD Archive Entry:
  5. ;; file-complete|Ashwin Ram, Joe Wells|Ran-Ashwin@cs.yale.edu|
  6. ;; Display file name completions in mod-time order.|
  7. ;; 1992-10-13||~/misc/file-complete.el.Z|
  8. ;;
  9. ;; This file is not part of the GNU Emacs distribution (yet).
  10. ;;
  11. ;; This file is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  13. ;; accepts responsibility to anyone for the consequences of using it
  14. ;; or for whether it serves any particular purpose or works at all,
  15. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  16. ;; License for full details.
  17. ;;
  18. ;; Everyone is granted permission to copy, modify and redistribute
  19. ;; this file, but only under the conditions described in the
  20. ;; GNU Emacs General Public License.   A copy of this license is
  21. ;; supposed to have been given to you along with GNU Emacs so you
  22. ;; can know your rights and responsibilities.  It should be in a
  23. ;; file named COPYING.  Among other things, the copyright notice
  24. ;; and this notice must be preserved on all copies.
  25. ;;
  26. ;; Comments, corrections, and improvements should be sent to:
  27. ;;
  28. ;;     Ashwin Ram
  29. ;;
  30. ;;     ARPA:   Ram-Ashwin@cs.yale.edu
  31. ;;     UUCP:   {decvax,ucbvax,harvard,cmcl2,...}!yale!Ram-Ashwin
  32. ;;     BITNET: Ram@yalecs
  33. ;;
  34. ;;
  35. ;; MODIFICATION HISTORY:
  36. ;;
  37. ;; 03/13/89 Ashwin Ram <Ram-Ashwin@cs.yale.edu>
  38. ;;          Initial release.
  39. ;;
  40. ;; 03/18/89 Joe Wells <jbw%bucsf.bu.edu@bu-it.bu.edu>
  41. ;;          Optimized sort, did temp-minibuf-message, etc.
  42. ;;
  43. ;; 03/21/89 Joe Wells
  44. ;;          optimized sort even more by using sh -c "ls name*"
  45. ;;
  46. ;; 03/22/89 Joe Wells
  47. ;;          more sort optimization, very fast now
  48. ;;
  49. ;; Oct-13-1992 Joe Wells
  50. ;;          "fixed" temp-minibuf-message so it works with 18.57+
  51. ;;
  52. ;; DOCUMENTATION:
  53. ;;
  54. ;; Display file name completions in order of modification date instead
  55. ;; of alphabetically.
  56. ;;
  57. ;; For the curious, when doing a completing read for a filename,
  58. ;; minibuffer-completion-table is read-file-name-internal and
  59. ;; minibuffer-completion-predicate is the current-buffer's directory.
  60.  
  61.  
  62. (defun file-name-completion-help ()
  63.   "Display a list of possible completions of the current minibuffer
  64. contents.  If the minibuffer is completing filenames, print the list
  65. in file modification time order.  Should only be called from inside a
  66. completing read in the minibuffer."
  67.   (interactive)
  68.   ;; if not completing filenames, do normal behavior
  69.   (if (not (eq minibuffer-completion-table 'read-file-name-internal))
  70.       (minibuffer-completion-help)
  71.     (message "Making completion list...")
  72.     (let* ((buffer-string (buffer-string)) ; minibuffer contents
  73.        (string-dir                    ; directory part of minibuf contents
  74.         (file-name-directory
  75.          (substitute-in-file-name buffer-string)))
  76.        (real-dir                    ; directory for completion
  77.         (if string-dir
  78.         (expand-file-name
  79.          string-dir
  80.          minibuffer-completion-predicate)
  81.           minibuffer-completion-predicate))
  82.        (completions
  83.         (all-completions buffer-string
  84.                  minibuffer-completion-table
  85.                  minibuffer-completion-predicate)))
  86.       (cond (completions
  87.          (with-output-to-temp-buffer " *Completions*"
  88.            (display-completion-list
  89.         (sort-files-by-modtime completions real-dir)))
  90.          (temp-minibuf-message "")) ;clear message
  91.         (t
  92.          (ding)
  93.          (temp-minibuf-message " [No completions]"))))))
  94.  
  95. (defun minibuffer-completion-help-unsorted ()
  96.   "Display a list of possible completions of the current minibuffer
  97. contents.  Prints the list in the order that it is returned from
  98. all-completions (unsorted).  Should only be called from inside a
  99. completing read in the minibuffer."
  100.   (interactive)
  101.   (message "Making completion list...")
  102.   (let ((completions
  103.          (all-completions (buffer-string)
  104.                           minibuffer-completion-table
  105.                           minibuffer-completion-predicate)))
  106.     (cond (completions
  107.            (with-output-to-temp-buffer " *Completions*"
  108.              (display-completion-list completions))
  109.        (temp-minibuf-message ""))    ;clear message
  110.           (t
  111.            (ding)
  112.            (temp-minibuf-message " [No completions]")))))
  113.  
  114. (defun sort-files-by-modtime (files &optional dir)
  115.   "Sort a list of FILES by the files' modification times.  Optional
  116. argument DIR is the directory the files are located in, which defaults
  117. to the default-directory of the current buffer.  This is not an
  118. in-place sort.  Deletes any files named . or .. from the list.
  119. Returns the new head of the list.  Note the items returned are new
  120. strings.  None of the previous members of the list are returned."
  121.   (let* ((real-dir (file-name-as-directory
  122.             (expand-file-name (or dir default-directory))))
  123.      (buffer (get-buffer-create " *ls results*"))
  124.      (p files))
  125.     ;; remove trailing slashes and delete "." and ".."
  126.     (setq files nil)
  127.     (while (consp p)
  128.       (cond ((string-match "\\`\\.\\.?/\\'" (car p))) ;ignore . and ..
  129.         ((string-match "/\\'" (car p)) ;trailing backslashes
  130.          (setq files (cons (substring (car p) 0 -1) files)))
  131.         (t
  132.          (setq files (cons (car p) files))))
  133.       (setq p (cdr p)))
  134.     ;; we're going to collect the output of the ls -t command in a
  135.     ;; buffer and put that back into a list.
  136.     (save-excursion
  137.       (set-buffer buffer)
  138.       ;; run ls in correct directory
  139.       (if (not (file-directory-p real-dir))
  140.       (error "%s is not a directory" real-dir)
  141.     (setq default-directory real-dir))
  142.       (erase-buffer)
  143.       ;; ls options:
  144.       ;; 1 - one column
  145.       ;; d - list a directories name, not its contents
  146.       ;; t - sorted by time
  147.       ;; F - fancy listing (* for executable, / for directory, etc.)
  148.       ;; L - use stat not lstat
  149.       (apply 'call-process "/bin/ls" nil t nil "-1dtFL" files)
  150.       ;; grab the filenames from the ls output
  151.       (goto-char (point-min))
  152.       (setq files nil)
  153.       (while (not (eobp))
  154.     (skip-chars-forward "\n")
  155.     (let ((begin (point)))
  156.       (skip-chars-forward "^\n")
  157.       (setq files (cons (buffer-substring begin (point)) files)))
  158.     (skip-chars-forward "\n"))
  159.       ;; files are now in reverse order
  160.       (setq files (nreverse files))
  161.       ;; save memory
  162.       (erase-buffer)
  163.       files)))
  164.  
  165. ;; Too bad this isn't in src/minibuf.c:
  166. ;;
  167. ;; DEFUN ("temp-minibuf-message", Ftemp_minibuf_message, Stemp_minibuf_message,1, 1, 0,
  168. ;;   "Documentation.")
  169. ;;   (s)
  170. ;;      Lisp_Object s;
  171. ;; {
  172. ;;   CHECK_STRING (s);
  173. ;;   temp_minibuf_message (XSTRING(s)->data);
  174. ;;   return Qnil;
  175. ;; }
  176. ;;
  177. ;; defsubr (&Stemp_minibuf_message);
  178.  
  179. (defun temp-minibuf-message2 (m)
  180.   "Prints string MESSAGE in the current buffer to the right of all
  181. text in the buffer.  It is used mainly for putting messages in the
  182. minibuffer while also showing the minibuffer text."
  183.   (let ((osize (point-max))
  184.         (inhibit-quit t))
  185.     (save-excursion
  186.       (goto-char osize)
  187.       (insert m)
  188.       (goto-char osize)
  189.       ;; The next statement is a gross hack.
  190.       ;; The purpose is to set echo_area_contents = 0, so that the contents
  191.       ;; of the minibuffer will show.
  192.       ;; *** fix this so it doesn't assume RET exits minibuffer
  193.       (let ((unread-command-char ?\C-m))
  194.     (read-from-minibuffer "" nil nil nil))
  195.       ;; This sets prev_echo_area_contents = echo_area_contents (which is 0)
  196.       ;; *** fix this so it doesn't assume RET exits minibuffer
  197.       (let ((unread-command-char help-char)
  198.         (help-form '(setq unread-command-char ?\C-m)))
  199.     (read-key-sequence nil))
  200.       (sit-for 2)
  201.       (delete-region osize (point-max))
  202.       (if quit-flag
  203.       (setq quit-flag nil
  204.         unread-command-char ?\C-g)))))
  205.  
  206. ;; Check if temp-minibuf-message has been fixed in the C code.
  207. (or (and (fboundp 'temp-minibuf-message)
  208.      (subrp (symbol-function 'temp-minibuf-message)))
  209.     (fset 'temp-minibuf-message 'temp-minibuf-message2))
  210.  
  211. ;;(define-key minibuffer-local-completion-map "|" 'file-name-completion-help)
  212. ;;(define-key minibuffer-local-completion-map "=" 'minibuffer-completion-help-unsorted)
  213.  
  214. (provide 'file-complete)
  215.  
  216. ;; Avoid calling stat() more than once per file, at the expense of
  217. ;; some extra consing in file-attributes.  That's ok, because the
  218. ;; consing is O(n) and the stats were O(n lg n).  We grab the file
  219. ;; modtime and put it in the list with the filename.  Then we call
  220. ;; sort with a predicate that compares the modtimes.  The modtimes are
  221. ;; in this format: (HIGH LOW) where HIGH and LOW are 16 bit integers.
  222. ;; During the sort, the list is in this format: ((FILENAME HIGH LOW)
  223. ;; ...).  This sort occurs in place.
  224. ;; (defun sort-files-by-modtime (files &optional dir)
  225. ;;   "Sort a list of FILES by the files' modification times.  Optional
  226. ;; argument DIR is the directory the files are located in, which defaults
  227. ;; to the default-directory of the current buffer.  This is not an
  228. ;; in-place sort.  Deletes any files named . or .. from the list.
  229. ;; Returns the new head of the list."
  230. ;;   (let ((p files)
  231. ;;         time1 time2)
  232. ;;     (setq files nil)
  233. ;;     (while (consp p)
  234. ;;       (if (string-match "\\`\\.\\.?/\\'" (car p))
  235. ;;       nil
  236. ;;     (setq files (cons
  237. ;;              (cons (car p)
  238. ;;                (nth 5 (file-attributes
  239. ;;                    (expand-file-name (car p) dir))))
  240. ;;              files)))
  241. ;;       (setq p (cdr p)))
  242. ;;     (setq files
  243. ;;           (sort files
  244. ;;                 (function
  245. ;;                  (lambda (f1 f2)
  246. ;;                    (setq time1 (cdr f1)
  247. ;;                          time2 (cdr f2))
  248. ;;                    (or (> (car time1) (car time2))
  249. ;;                        (and (= (car time1) (car time2))
  250. ;;                             (> (car (cdr time1)) (car (cdr time2)))))))))
  251. ;;     (setq p files)
  252. ;;     (while (consp p)
  253. ;;       (setcar p (car (car p)))
  254. ;;       (setq p (cdr p))))
  255. ;;   files)
  256.