home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / functions / live-find-file.el < prev    next >
Encoding:
Text File  |  1991-07-03  |  7.2 KB  |  203 lines

  1. ; Path: dg-rtp!rock!mcnc!stanford.edu!agate!spool.mu.edu!caen!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!csvax.cs.caltech.edu!daveg
  2. ; From: daveg@csvax.cs.caltech.edu (David Gillespie)
  3. ; Newsgroups: gnu.emacs.sources
  4. ; Subject: A live-find-file command
  5. ; Date: 29 Jun 91 11:25:57 GMT
  6. ; Organization: Source only  Discussion and requests in gnu.emacs.help.
  7. ; This file defines a simple command for monitoring files that grow, such as
  8. ; log files.  Type M-x live-find-file RET and enter the file name; the result
  9. ; will be a read-only buffer with a Unix "tail -f" command living in it that
  10. ; keeps the buffer up-to-date as the file grows.
  11. ; If you switch away from the buffer and new input arrives, Emacs notifies you
  12. ; of this in the echo area.  The `n' key selects a few other notification modes.
  13. ; When you are done with the buffer, just kill it with `q' or `C-x k' and the
  14. ; "tail -f" command will go away.
  15. ; Enjoy,
  16. ;                                 -- Dave
  17. ;; View a file with "live" updates as the file grows on disk.
  18. ;; Copyright (C) 1991 Dave Gillespie
  19.  
  20. ;; LCD Archive Entry:
  21. ;; live-find-file|David Gillespie|daveg@csvax.cs.caltech.edu
  22. ;; |View a file with "live" updates as the file grows on disk
  23. ;; |91-06-29||~/functions/live-find-file.el.Z
  24.  
  25. ;; This file is part of GNU Emacs.
  26.  
  27. ;; GNU Emacs is distributed in the hope that it will be useful,
  28. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  29. ;; accepts responsibility to anyone for the consequences of using it
  30. ;; or for whether it serves any particular purpose or works at all,
  31. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  32. ;; License for full details.
  33.  
  34. ;; Everyone is granted permission to copy, modify and redistribute
  35. ;; GNU Emacs, but only under the conditions described in the
  36. ;; GNU Emacs General Public License.   A copy of this license is
  37. ;; supposed to have been given to you along with GNU Emacs so you
  38. ;; can know your rights and responsibilities.  It should be in a
  39. ;; file named COPYING.  Among other things, the copyright notice
  40. ;; and this notice must be preserved on all copies.
  41.  
  42. ;; Usage:
  43. ;;   (autoload 'live-find-file "live" "View a file with \"tail -f\"" t)
  44. ;;   M-x live-find-file RET filename RET
  45.  
  46.  
  47. (defvar live-file-notify t
  48.   "*Non-nil to display a message in the echo area if data comes in on a
  49. live file buffer which is not currently displayed.
  50. If Non-nil and not \"t\", actually display the buffer if new data comes in.")
  51.  
  52. (defvar live-file-mask (concat "^\000\001\002\003\004\005\006\007\010\011"
  53.                    "\013\015\016\017\020\021\022\023\024\025"
  54.                    "\026\027\030\031\032\033\034\035\036\037\177")
  55.   "*A string of characters to retain in a live file buffer;
  56. all others are discarded.  If it begins with \"^\", it is a list of
  57. characters which *should* be discarded.
  58. Default is to discard all control characters except new-line and form-feed.")
  59.  
  60.  
  61.  
  62. (defun live-find-file (filename)
  63.   "Read in and display a file with \"live\" updates as the file grows on disk.
  64. This is accomplished using the Unix \"tail -f\" command.
  65. The buffer will remain live until you kill it with \\[kill-buffer].
  66. The buffer is made read-only, and should probably be left that way.
  67. Inside the buffer, hit n to change notification mode, r to re-read, q to kill."
  68.   (interactive "fLive find file: ")
  69.   (setq filename (expand-file-name filename))
  70.   (if (file-directory-p filename)
  71.       (error "%s is a directory." filename))
  72.   (let ((buf (create-file-buffer filename))
  73.     size)
  74.     (switch-to-buffer buf)
  75.     (fundamental-mode)
  76.     (setq major-mode 'live-find-file)
  77.     (setq mode-name "Live-Find-File")
  78.     (use-local-map (make-sparse-keymap))   ; should set up a real major mode!
  79.     (local-set-key "q" "\C-xk\r")
  80.     (local-set-key "n" 'Live-file-notify)
  81.     (local-set-key "r" 'Live-file-reread)
  82.     (local-set-key " " 'scroll-up)
  83.     (local-set-key "\177" 'scroll-down)
  84.     (local-set-key "?" 'Live-file-help)
  85.     (local-set-key "h" 'Live-file-help)
  86.     (erase-buffer)
  87.     (insert-file-contents filename t)
  88.     (setq size (buffer-size))
  89.     (live-file-clean-region (point-min) (point-max))
  90.     (set-buffer-modified-p nil)
  91.     (setq buffer-read-only t)
  92.     (goto-char (point-max))
  93.     (setq default-directory (file-name-directory filename))
  94.     (let* ((process-connection-type nil)
  95.        (proc (start-process
  96.           "tail" (current-buffer) "tail"
  97.           (format "+%dcf" (1+ size))
  98.           filename)))
  99.       (process-kill-without-query proc)
  100.       (set-process-filter proc 'live-file-filter)))
  101. )
  102.  
  103. (defun Live-file-help ()
  104.   (interactive)
  105.   (message "Live mode:  n=change notification method, q=quit, r=reread")
  106. )
  107.  
  108. (defun Live-file-notify (flag)
  109.   "Control whether to notify on input from live files not visible in a window.
  110. This applies to files created by \\[live-find-file].
  111. Cycles among three options:  Notify in echo area, notify by creating a new
  112. window, or don't notify.
  113. Notification mode applies if input arrives for a live file that is not
  114. currently visible.  If input arrives for a live file that is visible but
  115. that has been scrolled so that the end is not visible, new input always
  116. notifies in the echo area."
  117.   (interactive "P")
  118.   (setq live-file-notify
  119.     (cond ((null flag)
  120.            (or (not live-file-notify)
  121.            (and (eq live-file-notify t)
  122.             'show)))
  123.           ((not (integerp flag)) 'show)
  124.           ((> flag 0) t)))
  125.   (message (cond ((eq live-file-notify t) "Notifying in echo area.")
  126.          (live-file-notify "Notifying in a new window.")
  127.          (t "Not notifying.")))
  128. )
  129.  
  130. (defun Live-file-reread ()
  131.   "Re-read the contents of the current live file from disk.
  132. Live-find-file only checks for new text being appended at the end.  This
  133. command re-reads the whole of the file to see if any of it has changed."
  134.   (interactive)
  135.   (let ((name (buffer-file-name)))
  136.     (or name
  137.     (error "Buffer is not visiting a file."))
  138.     (or (file-readable-p name)
  139.     (error "File %s no longer exists." name))
  140.     (message "Re-reading %s..." name)
  141.     (kill-buffer (current-buffer))
  142.     (live-find-file name)
  143.     (message "Re-reading %s...done" name))
  144. )
  145.  
  146. (defun live-file-filter (proc str)
  147.   (let* ((oldbuf (current-buffer))
  148.      (buf (process-buffer proc))
  149.      (win (get-buffer-window buf))
  150.      (changed nil))
  151.     (unwind-protect
  152.     (progn
  153.       (set-buffer buf)
  154.       (clear-visited-file-modtime)
  155.       (let ((pt (point-max))
  156.         (opt (and (< (point) (point-max)) (point)))
  157.         (mod (buffer-modified-p)))
  158.         (goto-char pt)
  159.         (let ((buffer-read-only nil))
  160.           (insert str)
  161.           (live-file-clean-region pt (point-max)))
  162.         (setq changed (/= pt (point-max)))
  163.         (and changed
  164.          (or (not win)
  165.              (not (pos-visible-in-window-p pt win)))
  166.          (or win (eq live-file-notify t))
  167.          (= (minibuffer-depth) 0)
  168.          (message "From %s: %s"
  169.               (file-name-nondirectory
  170.                (buffer-file-name buf))
  171.               str))
  172.         (or mod
  173.         (set-buffer-modified-p nil))
  174.         (or opt (setq opt (point-max)))
  175.         (goto-char opt)
  176.         (and win (set-window-point win opt))))
  177.       (set-buffer oldbuf))
  178.     (and changed
  179.      live-file-notify 
  180.      (not (eq live-file-notify t))
  181.      (not (get-buffer-window buf))
  182.      (set-window-point (display-buffer buf t)
  183.                (save-excursion (set-buffer buf)
  184.                        (goto-char (point-max))
  185.                        (point)))))
  186. )
  187.  
  188. (defun live-file-clean-region (start end)
  189.   (and live-file-mask
  190.        (save-excursion
  191.      (goto-char end)
  192.      (while (progn
  193.           (skip-chars-backward live-file-mask start)
  194.           (> (point) start))
  195.        (delete-backward-char 1))))
  196. )
  197.