]> git.donarmstrong.com Git - lib.git/blob - emacs_el/tiny-tools/tiny/tinycache.el
add tiny-tools
[lib.git] / emacs_el / tiny-tools / tiny / tinycache.el
1 ;;; tinycache.el --- Maintain a cache of visited files [compile,dired]
2
3 ;; This file is not part of Emacs
4
5 ;;{{{ Id
6
7 ;; Copyright (C)    1996-2007 Jari Aalto
8 ;; Keywords:        extensions
9 ;; Author:          Jari Aalto
10 ;; Maintainer:      Jari Aalto
11 ;;
12 ;; To get information on this program, call M-x tinycache-version.
13 ;; Look at the code with folding.el
14
15 ;; This program is free software; you can redistribute it and/or modify it
16 ;; under the terms of the GNU General Public License as published by the Free
17 ;; Software Foundation; either version 2 of the License, or (at your option)
18 ;; any later version.
19 ;;
20 ;; This program is distributed in the hope that it will be useful, but
21 ;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23 ;; for more details.
24 ;;
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with program; see the file COPYING. If not, write to the
27 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 ;; Boston, MA 02110-1301, USA.
29 ;;
30 ;; Visit <http://www.gnu.org/copyleft/gpl.html> for more information
31
32 ;;}}}
33 ;;{{{ Install
34
35 ;;   Put this file on your Emacs-Lisp load path, add following into
36 ;;   ~/.emacs startup file:
37 ;;
38 ;;       (add-hook tinycache-:load-hook 'tinycache-install-msb)
39 ;;       (require 'tinycache)
40 ;;
41 ;;   Or use quicker autoload:
42 ;;
43 ;;       (add-hook tinycache-:load-hook 'tinycache-install-msb)
44 ;;       (eval-after-load "compile" '(progn (require 'tinycache)))
45 ;;       (eval-after-load "dired"   '(progn (require 'tinycache)))
46 ;;
47 ;;   If you use *gnuserv.el*, be sure that to load the packages in order:
48 ;;   gnuserv, tinycache.
49 ;;
50 ;;   To disable this package:
51 ;;
52 ;;      M-x tinycache-uninstall
53 ;;
54 ;;   If you have any questions, use this function
55 ;;
56 ;;      M-x tinycache-submit-bug-report
57
58 ;;}}}
59 ;;{{{ Documentation
60
61 ;;; Commentary:
62
63 ;;  Preface, overview of features
64 ;;
65 ;;      This package is meant to be used with `dired' and compilation
66 ;;      buffers. When you load file from either one, the file is
67 ;;      "remembered". This way you can browse bunch of files easily and
68 ;;      when you have finished you can flush the cache and get rid of all
69 ;;      vieved files.
70 ;;
71 ;;  Dired description
72 ;;
73 ;;      When you load a file from dired with `dired-view-file', the
74 ;;      file is remembered. You can load several files for viewing and when you
75 ;;      have finished, call `tinycache-flush' (Defaults to `C-c' `k' in
76 ;;      dired) to remove all the remembered (cached) files from emacs.
77 ;;
78 ;;      This way you don't end up having files that you're not interested
79 ;;      in any more. Using the cache makes browsing bunch of files very
80 ;;      easy. Each dired buffer has it's own cache. The cache is also
81 ;;      flushed if you kill the dired buffer.
82 ;;
83 ;;  Compilation cache description
84 ;;
85 ;;      Maintain also a cache of buffers visiting files via the
86 ;;      `next-error' and `compile-goto-error' commands; each compile/grep
87 ;;      buffer has its own cache.  To kill the cached buffers manually, use
88 ;;      `C-c' `C-d' (compile-flush-cache) in the compile/grep buffer;
89 ;;      deleting the compile/grep buffer automatically kills the cached
90 ;;      buffers.  To disable the cache, set `compilation-find-file-cache'
91 ;;      to a non-list value (e.g. 'disable).
92 ;;
93 ;;      After loading this file, every file that is loaded by calling some
94 ;;      compile function, i.e. `compile-goto-error', is cached if it is not
95 ;;      in emacs already. I.e. when you fix some small errors in other
96 ;;      files, you may not want to keep those files in emacs after you've
97 ;;      done; remember, those got loaded during the calls to
98 ;;      compile-goto-error. The easiest way to get rid of these extra
99 ;;      files, that were not originally in emacs, is to:
100 ;;
101 ;;          A. kill compilation buffer, C-x k *compilation*
102 ;;          B. Call M-x tinycache-flush directly
103 ;;
104 ;;      See *igrep.el* also how you can browse (grep) files easily and when
105 ;;      you've done, you can call this package top get rid of those browsed
106 ;;      files.
107 ;;
108 ;;  Cache minor mode indication --  Controlling the cache flag
109 ;;
110 ;;      Mode line indication shows for loaded buffer
111 ;;
112 ;;          "+C"    if file is loaded as cached.
113 ;;          "+c"    If you have manually turned off the cache
114 ;;
115 ;;      And for root buffer where the file were loaded, normally
116 ;;      compilation or dired buffer, the mode line shows
117 ;;
118 ;;          "+CN"  where N is number of files currently in the cache
119 ;;
120 ;;      Sometimes you want to keep some file that belongs to the cache
121 ;;      and you don't want to loose it when you execute `M-x' `tinycache-flush'
122 ;;      or when you kill the root buffer.
123 ;;
124 ;;      For that purpose there is function `tinycache-mode' to turn
125 ;;      off the cache for current buffer. When the cache mark says
126 ;;      "+c" in the mode line, it tells you that the file will not be
127 ;;      killed when you `tinycache-flush' is called.
128 ;;
129 ;;      Note: the root buffer's xx count is not updated when you kill
130 ;;      buffer that was cached. So if the count says 10, and you kill 3
131 ;;      files that, the count will still still say 10. The count is
132 ;;      updated only when you load some *new* file from the root buffer.
133 ;;      At that time all the buffers cached are checked and the ones that
134 ;;      do not exist any more are removed.
135 ;;
136 ;;  Buffer list commands
137 ;;
138 ;;      There are some additional commands added to buffer list which
139 ;;      helps you to keep track of the cached files better. The "c"
140 ;;      prefix is chosen for (c)ache related commands.
141 ;;
142 ;;          C-c c m     mark all cached files
143 ;;          C-c c d     mark as deleted
144 ;;          C-c c u     unmark cached files.
145 ;;
146 ;;  Dired mode commands
147 ;;
148 ;;      Similar to buffer list, there is some dired commands too
149 ;;
150 ;;          C-c c k     tinycache-flush, remove all cached files from this dired
151 ;;          C-c c m     tinycache-dired-mark
152 ;;          C-c c u     tinycache-dired-unmark
153 ;;
154 ;;  Thanks
155 ;;
156 ;;      Kevin Rodgers, his *igrep.el* gave me an idea for this. The
157 ;;      original cache code from where this package evolved was
158 ;;      written by Kevin under name *compile-cache.el*
159
160 ;;; Change Log:
161
162 ;;}}}
163 ;;{{{ setup: require, variables
164
165 ;;; Code:
166
167 (eval-when-compile (require 'advice))
168 (require 'tinylibm)
169
170 (eval-and-compile
171   (autoload 'compilation-find-buffer    "compile"   "" t)
172   (autoload 'dired-view-file            "dired"     "" t)
173   (autoload 'dired-get-filename         "dired")
174   (autoload 'dired-mark                 "dired"     "" t)
175   (autoload 'dired-unmark               "dired"     "" t))
176
177 (ti::package-defgroup-tiny TinyCache tinycache-: extensions
178   "Maintain a cache of visited files [compile, dired].
179     overview of features
180
181         This package is meant to be used with dired and compilation
182         buffers. When you load file from either one, the file is
183         cached. This way you can view files easily and when you
184         have finished you can flush the cache and get rid of all
185         viewed files.")
186
187 ;;; ............................................. &emacs-compatibility ...
188 ;;;  We must install this for older emacs versions ( 19.30< )
189
190 (unless (boundp 'kill-buffer-hook)
191   ;; gnuserv.el
192   ;; - We have to do this now, because if user loads files in this order:
193   ;;
194   ;;        tinycache
195   ;;        gnuserv
196   ;;
197   ;;   The gnuserv won't see the real function, because tinycache
198   ;;   put advice around the function. And using the adviced function
199   ;;   as "real" causes infinite loop.
200   ;;
201   ;;   If user doesn't use gnuserv, this just defines one extra function,
202   ;;   which does no harm.
203   ;;
204   (or (fboundp 'server-real-kill-buffer)
205       (fset 'server-real-kill-buffer (symbol-function 'kill-buffer)))
206
207   (defvar kill-buffer-hook nil
208     "Defined in tinycache.el package. Hook run just before buffer
209      is killed.")
210
211   (defadvice kill-buffer (around tinycache act)
212     "Run kill-buffer-hook before buffer iss killed."
213     (run-hooks 'kill-buffer-hook)
214     ;; prevent accidents by setting this hook to nil
215     (let ((kill-buffer-hook nil))
216       ad-do-it)))
217
218 ;;; ........................................................ &v-public ...
219
220 (defcustom tinycache-:mode-on-string " +C"
221   "*Cache property on indicator. File can be flushed."
222   :type  'string
223   :group 'TinyCache)
224
225 (defcustom tinycache-:mode-off-string " +c"
226   "*Cache property off indicator. File will not be flushed."
227   :type  'string
228   :group 'TinyCache)
229
230 (defcustom tinycache-:load-hook nil
231   "*Hook run when file has been loaded.
232 Suggested function `tinycache-install-msb'."
233   :type  'hook
234   :group 'TinyCache)
235
236 (defcustom tinycache-:find-file-buffer-hook 'tinycache-maybe-view-mode
237   "*Hook run inside buffer which is loaded from compile output."
238   :type 'hook
239   :group 'TinyCache)
240
241 ;;; ....................................................... &v-private ...
242
243 (defvar tinycache-:mode-name tinycache-:mode-on-string
244   "String in the mode line to mark if that file is part the cache or not.
245 This is changed by program and not a user variable.")
246
247 (defvar tinycache-mode nil
248   "Mode on/off variable.")
249 (make-variable-buffer-local 'tinycache-mode)
250 (put 'tinycache-mode  'permanent-local t)
251
252 (defvar tinycache-:info nil
253   "Variable to keep information about the cache.
254 Contains the compile buffer pointer from where the file was loaded.")
255 (make-variable-buffer-local 'tinycache-:info)
256 (put 'tinycache-:info 'permanent-local t)
257
258 (defvar tinycache-:mode-user-flag nil
259   "If non-nil, user has touched the `tinycache-mode' flag in this buffer.")
260 (make-variable-buffer-local 'tinycache-:mode-user-flag)
261 (put 'tinycache-:mode-user-flag   'permanent-local t)
262
263 (defvar tinycache-:cache nil
264   "List of buffers created by `compilation-find-file'. Local to each buffer.
265 Format: (BUFFER-POINTER BP ..)")
266
267 ;; If user starts new compilation in *grep* buffer, it wipes the results
268 ;; but the cache must remain there, since he may have loaded files from
269 ;; previous compilation.
270
271 (put 'tinycache-:cache            'permanent-local t)
272
273 ;;; ....................................................... &v-version ...
274
275 ;;;###autoload (autoload 'tinycache-version "tinycache" "Display commentary." t)
276 (eval-and-compile
277   (ti::macrof-version-bug-report
278    "tinycache.el"
279    "tinycache"
280    tinycache-:version-id
281    "$Id: tinycache.el,v 2.45 2007/05/06 23:15:19 jaalto Exp $"
282    '(tinycache-:version-id
283      tinycache-:mode-on-string
284      tinycache-:mode-off-string
285      tinycache-:load-hook
286      tinycache-:find-file-buffer-hook
287      tinycache-:mode-name
288      tinycache-mode
289      tinycache-:info
290      tinycache-:mode-user-flag
291      tinycache-:cache)))
292
293 ;;}}}
294 ;;{{{ code: misc functions
295
296 ;;; ----------------------------------------------------------------------
297 ;;;
298 (defun tinycache-uninstall ()
299   "Deactivate package."
300   (tinycache-advice-control 'disable))
301
302 ;;; ----------------------------------------------------------------------
303 ;;;
304 (defun tinycache-advice-control (&optional disable)
305   "Turn advices on. Optionally DISABLE."
306   (interactive)
307   (ti::advice-control
308    '(compile-internal compilation-find-file) "^tinycache"  disable 'verb))
309
310 ;;; ----------------------------------------------------------------------
311 ;;;
312 (defun tinycache-install-mode ()
313   "Install `tinycache-mode'."
314   ;;  Make sure we can display string in mode line
315   (if (null (assq 'tinycache-mode minor-mode-alist))
316       (ti::keymap-add-minor-mode 'tinycache-mode
317                                  'tinycache-:mode-name
318                                  ;; No key map
319                                  (make-sparse-keymap))))
320
321 ;;; ----------------------------------------------------------------------
322 ;;;
323 (defun tinycache-install-msb ()
324   "Install new cache menu to msb.el if it is loaded."
325   (let* ((elt
326           '((and (boundp 'tinycache-mode)
327                  tinycache-mode)
328             1005
329             "Cached compile files (%d)"))
330          (sym  'msb-menu-cond)
331          menu)
332     (when (and (featurep 'msb)
333                ;;  Install only once.
334                ;;  symbol-value just silences byteComp
335                (setq menu (symbol-value sym))
336                (not (member menu elt)))
337       (push elt menu)
338       (set sym menu))))
339
340 ;;; ----------------------------------------------------------------------
341 ;;;
342 (defun tinycache-define-default-keys ()
343   "Define keys to `compilation-minor-mode-map'."
344   (interactive)
345   (let* (map)
346     ;;  Avoid byte compilation warnings this way....
347     ;;
348     (when (and (boundp  'compilation-minor-mode-map)
349                (setq map (symbol-value 'compilation-minor-mode-map))
350                (keymapp map))
351       (ti::use-prefix-key map "\C-cc")
352       (ti::define-key-if-free map "\C-cck" 'tinycache-flush))
353     (when (and (boundp  'compilation-minor-mode-map)
354                (setq map (symbol-value 'compilation-minor-mode-map))
355                (keymapp  map))
356       (ti::use-prefix-key map "\C-cc")
357       (ti::define-key-if-free map "\C-cck" 'tinycache-flush))
358     (when (and (boundp  'dired-mode-map)
359                (setq map (symbol-value 'dired-mode-map))
360                (keymapp  map))
361       (ti::use-prefix-key map "\C-cc")
362       (ti::define-key-if-free map "\C-cck" 'tinycache-flush)
363       (ti::define-key-if-free map "\C-ccm" 'tinycache-dired-mark)
364       (ti::define-key-if-free map "\C-ccu" 'tinycache-dired-unmark))))
365
366 ;;; ----------------------------------------------------------------------
367 ;;;
368 (defun tinycache-buffer-list-bindings-on ()
369   "Add default bindings to buffer list, \\[list-buffers]."
370   ;;  Choose "c" for cache commands
371   (ti::use-prefix-key Buffer-menu-mode-map "\C-cc")
372   ;;  With these you can see the cachec files
373   (ti::define-key-if-free Buffer-menu-mode-map "\C-ccd"
374                           'tinycache-buffer-list-mark-deleted)
375   (ti::define-key-if-free Buffer-menu-mode-map "\C-ccm"
376                           'tinycache-buffer-list-mark)
377   (ti::define-key-if-free Buffer-menu-mode-map "\C-ccu"
378                           'tinycache-buffer-list-unmark)
379   (ti::define-key-if-free Buffer-menu-mode-map "\C-ccf"
380                           'tinycache-buffer-list-mark-cache-off)
381   ;;  Bye, bye. No need to call us again. Installation already done.
382   (remove-hook 'buffer-menu-mode-hook 'tinycache-define-default-keys))
383
384 ;;; ----------------------------------------------------------------------
385 ;;;  - The following says that "Load view-(minor)mode in Emacs 19.30, but
386 ;;;    for other (X)Emacs load mview-mode if it exists."
387 ;;;  - The view-mode is minor mode in new Emacs releases, older
388 ;;;    versions are encouraged to get mview.el minor mode
389 ;;;
390 ;;;            mview.el
391 ;;;            Mike Williams
392 ;;;
393 (defun tinycache-maybe-view-mode ()
394   "Turen on view (minor) mode if needed."
395   (interactive)
396   (let* ((zip-re ;; arc-mode's zip file prompt
397           ;; M Filemode      Length  Date         Time      File
398           ;; - ----------  --------  -----------  --------  ---------
399           ;; -rw-r--r--      9695  10-Sep-1993  17:53:46  Makefile
400           ;; -rw-r--r--      7441   8-Sep-1993  14:21:20  README
401           ;;
402           ".*Filemode[ \t]+Length[ \t]+Date[ \t]+Time[ \t]+File[ \t]*$")
403          func)
404     ;;  Now; if you load from dired a .zip or .tar file; you don't
405     ;;  want view mode on, check buffer file name.
406     (cond
407      ((and (not (ti::emacs-p "21"))
408            (ti::emacs-p)
409            (< emacs-minor-version 30)
410            (require 'mview nil 'noerr)
411            ;;
412            ;; Not loaded from dired-view-file, but from compile buffer?
413            ;;
414            (not (eq major-mode 'view-mode)))
415       (when (fboundp 'view-mode)        ;Turn off this mode.
416         (ti::funcall 'view-mode 0)) ;in 19.28 won't work, but try anyway
417       ;; Use minor mode instead
418       (setq func 'mview-mode))
419      ((fboundp 'view-mode)
420       (setq func 'view-mode)))
421     (cond
422      ((save-excursion
423         (ti::pmin)
424         (and (looking-at zip-re)
425              (fboundp 'archive-mode)))
426       (ti::funcall 'archive-mode))
427      (func
428       (funcall func)))))
429
430 ;;}}}
431 ;;{{{ code: Buffer list control
432
433 ;;; ----------------------------------------------------------------------
434 ;;;
435 (defmacro tinycache-:mode-on-string-p ()
436   "Check if `tinycache-mode' is on."
437   (` (memq tinycache-mode '(t on))))
438
439 ;;; ----------------------------------------------------------------------
440 ;;;
441 (put 'tinycache-map-over-buffers 'lisp-indent-function 1)
442 (defmacro tinycache-map-over-buffers (off &rest body)
443   "Map over all cached buffers.
444 If OFF is non-nil, maps over buffers whose `tinycache-:cache' is off
445 and do BODY.
446
447 In macro you can refer to these variables. The names are mangled
448 so that they don't clash with the toplevel definitions.
449
450     'BuffeR'    as current buffer
451     'NamE'      buffers's name
452     'LisT'      current list of buffers to loop over.
453
454 Setting 'list' to nil terminates this macro."
455   (`
456    (let* (NamE)
457      (dolist (BuffeR (tinycache-cached-file-list (, off)) )
458        (setq NamE (buffer-name BuffeR))
459        (if (null NamE)
460            (setq NamE nil))             ;NoOp, Silence ButeComp
461        (,@ body)))))
462
463 ;;; ----------------------------------------------------------------------
464 ;;;
465 (put 'tinycache-buffer-list-map-over-buffers 'lisp-indent-function 0)
466 (defmacro tinycache-buffer-list-map-over-buffers (&rest body)
467   "Special Buffer list macro to execute BODY at found buffer line."
468   (`
469    (tinycache-map-over-buffers nil
470                                (setq NamE (regexp-quote NamE))
471                                (ti::pmin)
472                                (when (re-search-forward NamE nil t)
473                                  (beginning-of-line)
474                                  (,@ body)))))
475
476 ;;; ----------------------------------------------------------------------
477 ;;;
478 (put 'tinycache-buffer-list-map-over-off-buffers 'lisp-indent-function 0)
479 (defmacro tinycache-buffer-list-map-over-off-buffers (&rest body)
480   "Special Buffer list macro to execute BODY at found buffer line."
481   (`
482    (tinycache-map-over-buffers 'off
483                                (setq NamE (regexp-quote NamE))
484                                (ti::pmin)
485                                (when (re-search-forward NamE nil t)
486                                  (beginning-of-line)
487                                  (,@ body)))))
488
489 ;;; ----------------------------------------------------------------------
490 ;;;
491 ;;;###autoload
492 (defun tinycache-buffer-list-mark ()
493   "Mark Cached files in buffer list."
494   (interactive)
495   (tinycache-buffer-list-map-over-buffers (Buffer-menu-mark)))
496
497 ;;; ----------------------------------------------------------------------
498 ;;;
499 ;;;###autoload
500 (defun tinycache-buffer-list-unmark ()
501   "Mark Cached files in buffer list."
502   (interactive)
503   (tinycache-buffer-list-map-over-buffers (Buffer-menu-unmark)))
504
505 ;;; ----------------------------------------------------------------------
506 ;;;
507 ;;;###autoload
508 (defun tinycache-buffer-list-mark-deleted ()
509   "Mark Cached files in buffer list."
510   (interactive)
511   (tinycache-buffer-list-map-over-buffers (Buffer-menu-delete)))
512
513 ;;; ----------------------------------------------------------------------
514 ;;;
515 ;;;###autoload
516 (defun tinycache-buffer-list-mark-cache-off ()
517   "Mark files whose cache property has been turned off."
518   (interactive)
519   (tinycache-buffer-list-map-over-off-buffers (Buffer-menu-mark)))
520
521 ;;}}}
522 ;;{{{ Dired buffer
523
524 ;;; ----------------------------------------------------------------------
525 ;;;
526 (defun tinycache-dired-mark (&optional unmark verb)
527   "Mark cached files. Optionally UNMARK. VERB."
528   (interactive)
529   (let* ((i 0)
530          file)
531     (ti::verb)
532     (ti::save-line-column-macro nil nil
533       (dolist (elt tinycache-:cache)
534         (setq file (buffer-name elt))
535         (ti::pmin)
536         (when (re-search-forward (format "%s$" file))
537           (cond
538            (unmark
539             (beginning-of-line)
540             (when (eq (following-char)
541                       (symbol-value 'dired-marker-char))
542               (incf  i)
543               (dired-unmark 1)))
544            (t
545             (incf  i)
546             (dired-mark 1))))))
547     (if verb
548         (message "%d cached files %smarked" i
549                  (if unmark "un" "") ))))
550
551 ;;; ----------------------------------------------------------------------
552 ;;;
553 (defun tinycache-dired-unmark (&optional verb)
554   "Unmark cached files. VERB."
555   (interactive)
556   (ti::verb)
557   (tinycache-dired-mark 'unmark verb))
558
559 ;;}}}
560 ;;{{{ code: cache control
561
562 ;;; ----------------------------------------------------------------------
563 ;;;
564 (defun tinycache-add-local-hook ()
565   "Make `kill-buffer-hook' local to this buffer. And add `tinycache-flush' to it.
566 When you kill the dired buffer, cached buffers loaded from this
567 buffer are also killed."
568   (let* (buffer)
569     ;; Make sure this hook does not contain tinycache-flush outside
570     ;; the compilation buffer
571     (remove-hook 'kill-buffer-hook 'tinycache-flush)
572     (save-excursion
573       ;;   Select right buffer where to localize the hook
574       (cond
575        ((eq major-mode 'dired-mode))
576        ((and (boundp 'compilation-last-buffer)
577              (setq buffer (symbol-value 'compilation-last-buffer))
578              (buffer-live-p (get-buffer buffer)))
579         (set-buffer buffer))
580        (t
581         (error "improper use of tinycache-add-local-hook: no dired/compilation")))
582       ;;  force the hook local to buffer
583       (make-local-hook 'kill-buffer-hook)
584       ;;  Make sure there are no constants in the hook.
585       (setq kill-buffer-hook (delq nil (delq t kill-buffer-hook)))
586       (add-hook 'kill-buffer-hook 'tinycache-flush))))
587
588 ;;; ----------------------------------------------------------------------
589 ;;;
590 (defun tinycache-activate (this-buffer buffer)
591   "THIS-BUFFER is the root buffer (dired,compile) and put BUFFER to cache."
592   (interactive)
593   (let (new-list)
594     ;;  update cache list
595     (with-current-buffer this-buffer
596       (make-local-variable 'tinycache-:cache)
597       (dolist (elt tinycache-:cache) ;Remove buffers that do not exist
598         (if (buffer-live-p (get-buffer elt))
599             (push elt new-list)))
600       (setq tinycache-:cache new-list)
601       (if (not (memq buffer tinycache-:cache))
602           (push buffer tinycache-:cache))
603       (tinycache-mode-root-buffer))
604     ;;  Turn on cache mode
605     (with-current-buffer buffer
606       (setq tinycache-:info this-buffer)
607       ;;  - We don't touch the tinycache-mode if user has taken control
608       ;;  - If the flag shows untouched buffer, mark the buffer
609       ;;    to cache.
610       (unless tinycache-:mode-user-flag
611         (setq tinycache-mode 'on)
612         (setq tinycache-:mode-name tinycache-:mode-on-string)
613         (ti::compat-modeline-update))
614       (run-hooks 'tinycache-:find-file-buffer-hook))))
615
616 ;;; ----------------------------------------------------------------------
617 ;;;
618 (defun tinycache-cached-file-list (&optional off)
619   "Return all cached files by looking at every compilation buffer.
620 This excludes files that user has manually instructed not to be in
621 cache (tinycache-mode is off for buffer)
622
623 if optional OFF is non-nil, then return buffers whose `tinycache-:cache'
624 has been turned manually off."
625   (let* ((modes '(compilation-mode compilation-minor-mode dired-mode))
626          buffers
627          blist2)
628     (dolist (elt (buffer-list))
629       (with-current-buffer elt
630         (when (and (memq major-mode modes)
631                    tinycache-:cache)
632           ;;  Read the value of cache and loop over it
633           (setq blist2 tinycache-:cache)
634           ;;  Check the `tinycache-mode' for every cached file.
635           (dolist (elt2 blist2)
636             (with-current-buffer elt2
637               (cond
638                ((null off)
639                 (if (tinycache-:mode-on-string-p)
640                     (push elt2 buffers)))
641                (t
642                 (if (null (tinycache-:mode-on-string-p))
643                     (push elt2 buffers))))))  ))) ;; dolist1 - 2
644     buffers))
645
646 ;;; ----------------------------------------------------------------------
647 ;;;
648 (defun tinycache-mode-root-buffer (&optional remove)
649   "Update root buffer's `tinycache-mode' flag. Optionally REMOVE from cache.
650 This is the buffer where `tinycache-:cache' resides."
651   (make-variable-buffer-local 'tinycache-:mode-name)
652   (cond
653    (remove
654     (setq tinycache-mode nil))
655    (t
656     (setq tinycache-mode 'on)
657     (setq tinycache-:mode-name
658           (format "%s%d" tinycache-:mode-on-string (length tinycache-:cache))))))
659 ;;; ----------------------------------------------------------------------
660 ;;; - This function must be called by user only!
661 ;;;
662 ;;;###autoload
663 (defun tinycache-mode (&optional arg)
664   "Toggle cache flag for this buffer with ARG.
665 If the file does not belong to compile cache, calling this function
666 does nothing. If the file is in the cache, the mode line displays mode name.
667
668 Removing the file from cache means that the file is not killed when
669 the cache is flushed with \\[tinycache-flush]."
670   (interactive)
671   (unless tinycache-:info
672     (message "Can't find tinycache-:info, Buffer is not part of the cache?")
673     (sleep-for 1))
674   (if (null tinycache-mode)
675       (message "This buffer is not in cache controlled.")
676     (setq tinycache-:mode-user-flag t)
677     (cond
678      ((memq arg '(0 -1))
679       (setq tinycache-mode 'off))
680      ((eq arg nil)
681       (if (tinycache-:mode-on-string-p)
682           (setq tinycache-mode 'off)
683         (setq tinycache-mode 'on)))
684      (t
685       (setq tinycache-mode 'on)))
686     (message
687      (format "Buffer is %s in cache control"
688              (if (tinycache-:mode-on-string-p)
689                  (progn
690                    (setq tinycache-:mode-name tinycache-:mode-on-string)
691                    "now")
692                (setq tinycache-:mode-name tinycache-:mode-off-string)
693                "no more")))
694     (ti::compat-modeline-update)))
695
696 ;;}}}
697 ;;{{{ code: flush
698
699 ;;; ----------------------------------------------------------------------
700 ;;;
701 ;;;###autoload
702 (defun tinycache-flush-all-compilation (&optional verb)
703   "Kill all cached files by stepping through all compilation buffers. VERB."
704   (interactive)
705   (let* ((count  0)
706          (verb   (or verb (interactive-p))))
707     (tinycache-map-over-buffers nil
708                                 (when (buffer-live-p  (get-buffer BuffeR))
709                                   (kill-buffer BuffeR)
710                                   (incf  count)))
711     (if verb
712         (message (format "Flushed %d buffers." count)))))
713
714 ;;; ----------------------------------------------------------------------
715 ;;;
716 ;;;###autoload
717 (defun tinycache-flush (&optional verb)
718   "Kill buffers listed in `tinycache-:cache'. VERB.
719 You must be in the Compilation/Dired buffer to execute this command.
720
721 If you're not in dired buffer, function tries to find compilation
722 buffer and kill compilation cached files."
723   (interactive)
724   (let* ((cache-buffer  (current-buffer))
725          count
726          do-it)
727     (ti::verb)
728     (unless (eq major-mode 'dired-mode)
729       ;;  This calls error if no compile buffer found...
730       (setq cache-buffer (ignore-errors (compilation-find-buffer))))
731     (when cache-buffer                  ;if there is buffer for us
732       (with-current-buffer cache-buffer
733         (tinycache-mode-root-buffer 'remove)
734         ;;  This variable is local to buffer
735         (setq count   (length tinycache-:cache))
736         (dolist (buffer tinycache-:cache)
737           (setq do-it nil)
738           (if (not (buffer-live-p  (get-buffer buffer)))
739               (setq do-it t)
740             (with-current-buffer buffer
741               ;;  kill-buffer-hook is local to each buffer.
742               ;;  prevent alias loop
743               (let ((kill-buffer-hook kill-buffer-hook))
744                 (remove-hook 'kill-buffer-hook 'tinycache-flush)
745                 (when (tinycache-:mode-on-string-p) ;it's allowed to kill
746                   (kill-buffer buffer)
747                   (setq do-it t)))))
748           (if do-it
749               (setq tinycache-:cache (delq buffer tinycache-:cache))))))
750     (if verb
751         (message (format "Cache flushed [%s] files. " count)))))
752
753 ;;}}}
754 ;;{{{ code: advice
755
756 ;;; ----------------------------------------------------------------------
757 ;;;
758 (defadvice compilation-find-file (around tinycache activate)
759   "Cache newly visited files in `tinycache-:cache';
760 use `\\[tinycache-flush]' in compilation buffer,
761 to kill these loaded files."
762   (let ((this-buffer    (current-buffer))
763         (file           filename)       ;ADVICE variable
764         buffer)
765     (tinycache-install-mode)
766     ;;  Already in emacs ?
767     (setq buffer (get-file-buffer file))
768     (prog1
769         ad-do-it
770       (unless buffer                    ;Loaded new file
771         (if (setq buffer ad-return-value)
772             (tinycache-activate this-buffer buffer))))))
773
774 ;;; ----------------------------------------------------------------------
775 ;;;
776 (defadvice compile-internal (after tinycache activate)
777   "Automatically kill the buffers listed in `tinycache-:cache'.
778 `kill-buffer-hook' when the `compile' buffer is killed."
779   (tinycache-add-local-hook))
780
781 ;;; ----------------------------------------------------------------------
782 ;;;
783 (defadvice dired-view-file (around tinycache act)
784   "Cache newly visited files in `tinycache-:cache';
785 Kill the dired buffer to kill cached files."
786   (let ((this-buffer    (current-buffer))
787         (file           (dired-get-filename))
788         buffer)
789     (tinycache-install-mode)
790     (cond
791      ((file-directory-p file)
792       (setq buffer t))                  ;skip this one
793      ((get-file-buffer file)            ;Already in emacs ?
794       (setq buffer t))
795      (t
796       (setq buffer (get-file-buffer file))))
797     (prog1
798         ad-do-it
799       (when (and (null buffer)          ;Loaded new file
800                  (setq buffer (get-file-buffer file)))
801         (tinycache-activate this-buffer buffer)))))
802
803 ;;}}}
804
805 ;;   delayed install
806
807 (add-hook 'buffer-menu-mode-hook 'tinycache-buffer-list-bindings-on)
808 (add-hook 'compilation-mode-hook 'tinycache-define-default-keys)
809 (add-hook 'dired-mode-hook       'tinycache-add-local-hook)
810 (add-hook 'dired-mode-hook       'tinycache-define-default-keys)
811
812 (provide   'tinycache)
813 (run-hooks 'tinycache-:load-hook)
814
815 ;; tinycache.el ends here