emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Patch for "virtual buffers" in iswitchb


From: John Wiegley
Subject: Re: Patch for "virtual buffers" in iswitchb
Date: Fri, 30 Apr 2004 04:41:53 -0700
User-agent: Gnus/5.110002 (No Gnus v0.2) Emacs/21.3.50 (darwin)

I just mailed off the general assignment papers, so soon I can check
the following patch in.  But I wanted to post this new version anyway,
since it runs many, many times faster than the previous patch, and
also represents what I hope is the final state of the code to be
checked in.

I've been relying heavily on this feature since writing it, so I
believe it can be quite useful to current iswitchb users.

John

Index: iswitchb.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/iswitchb.el,v
retrieving revision 1.51
diff -w -U3 -r1.51 iswitchb.el
--- iswitchb.el 21 Apr 2004 09:47:11 -0000      1.51
+++ iswitchb.el 30 Apr 2004 11:38:10 -0000
@@ -307,6 +307,20 @@
   :type '(choice (const :tag "Show all" nil) integer)
   :group 'iswitchb)
 
+(defcustom iswitchb-use-virtual-buffers nil
+  "*If non-nil, refer to past buffers when none match.
+This feature relies upon the `recentf' package, which will be
+enabled if this variable is configured to a non-nil value."
+  :type 'boolean
+  :require 'recentf
+  :set (function
+       (lambda (sym value)
+         (recentf-mode value)
+         (set sym value)))
+  :group 'iswitchb)
+
+(defvar iswitchb-virtual-buffers nil)
+
 (defcustom iswitchb-cannot-complete-hook 'iswitchb-completion-help
   "*Hook run when `iswitchb-complete' can't complete any more.
 The most useful values are `iswitchb-completion-help', which pops up a
@@ -572,12 +586,18 @@
           ))))
 
 ;;;###autoload
-(defun iswitchb-read-buffer (prompt &optional default require-match)
+(defun iswitchb-read-buffer (prompt &optional default require-match
+                                   start matches-set)
   "Replacement for the built-in `read-buffer'.
 Return the name of a buffer selected.
-PROMPT is the prompt to give to the user.  DEFAULT if given is the default
-buffer to be selected, which will go to the front of the list.
-If REQUIRE-MATCH is non-nil, an existing-buffer must be selected."
+PROMPT is the prompt to give to the user.
+DEFAULT if given is the default buffer to be selected, which will
+go to the front of the list.
+If REQUIRE-MATCH is non-nil, an existing-buffer must be selected.
+If START is a string, the selection process is started with that
+string.
+If MATCHES-SET is non-nil, the buflist is not updated before
+the selection process begins.  Used by isearchb.el."
   (let
       (
        buf-sel
@@ -590,14 +610,15 @@
 
     (iswitchb-define-mode-map)
     (setq iswitchb-exit nil)
-    (setq iswitchb-rescan t)
-    (setq iswitchb-text "")
     (setq iswitchb-default
          (if (bufferp default)
              (buffer-name default)
            default))
+    (setq iswitchb-text (or start ""))
+    (unless matches-set
+      (setq iswitchb-rescan t)
     (iswitchb-make-buflist iswitchb-default)
-    (iswitchb-set-matches)
+      (iswitchb-set-matches))
     (let
        ((minibuffer-local-completion-map iswitchb-mode-map)
         ;; Record the minibuffer depth that we expect to find once
@@ -610,19 +631,29 @@
                                 '(("dummy" . 1)) ;table
                                 nil    ;predicate
                                 nil    ;require-match [handled elsewhere]
-                                nil    ;initial-contents
+                                start  ;initial-contents
                                 'iswitchb-history)))
     (if (and (not (eq iswitchb-exit 'usefirst))
             (get-buffer iswitchb-final-text))
        ;; This happens for example if the buffer was chosen with the mouse.
-       (setq iswitchb-matches (list iswitchb-final-text)))
+       (setq iswitchb-matches (list iswitchb-final-text)
+             iswitchb-virtual-buffers nil))
+
+    ;; If no buffer matched, but a virtual buffer was selected, visit
+    ;; that file now and act as though that buffer had been selected.
+    (if (and iswitchb-virtual-buffers
+            (not (iswitchb-existing-buffer-p)))
+       (let ((virt (car iswitchb-virtual-buffers)))
+         (find-file-noselect (cdr virt))
+         (setq iswitchb-matches (list (car virt))
+               iswitchb-virtual-buffers nil)))
 
     ;; Handling the require-match must be done in a better way.
-    (if (and require-match (not (iswitchb-existing-buffer-p)))
+    (if (and require-match
+            (not (iswitchb-existing-buffer-p)))
        (error "Must specify valid buffer"))
 
-    (if (or
-        (eq iswitchb-exit 'takeprompt)
+    (if (or (eq iswitchb-exit 'takeprompt)
         (null iswitchb-matches))
        (setq buf-sel iswitchb-final-text)
       ;; else take head of list
@@ -732,18 +762,29 @@
   (setq iswitchb-exit 'findfile)
   (exit-minibuffer))
 
+(eval-when-compile
+  (defvar recentf-list))
+
 (defun iswitchb-next-match ()
   "Put first element of `iswitchb-matches' at the end of the list."
   (interactive)
   (let ((next  (cadr iswitchb-matches)))
-    (setq iswitchb-buflist (iswitchb-chop iswitchb-buflist next))
+    (if (and (null next) iswitchb-virtual-buffers)
+       (setq recentf-list
+             (iswitchb-chop recentf-list
+                            (cdr (cadr iswitchb-virtual-buffers))))
+      (setq iswitchb-buflist (iswitchb-chop iswitchb-buflist next)))
     (setq iswitchb-rescan t)))
 
 (defun iswitchb-prev-match ()
   "Put last element of `iswitchb-matches' at the front of the list."
   (interactive)
   (let ((prev  (car (last iswitchb-matches))))
-    (setq iswitchb-buflist (iswitchb-chop iswitchb-buflist prev))
+    (if (and (null prev) iswitchb-virtual-buffers)
+       (setq recentf-list
+             (iswitchb-chop recentf-list
+                            (cdr (car (last iswitchb-virtual-buffers)))))
+      (setq iswitchb-buflist (iswitchb-chop iswitchb-buflist prev)))
     (setq iswitchb-rescan t)))
 
 (defun iswitchb-chop (list elem)
@@ -835,7 +876,8 @@
       (setq iswitchb-matches
            (let* ((buflist iswitchb-buflist))
              (iswitchb-get-matched-buffers iswitchb-text iswitchb-regexp
-                                           buflist)))))
+                                           buflist))
+           iswitchb-virtual-buffers nil)))
 
 (defun iswitchb-get-matched-buffers (regexp
                                     &optional string-format buffer-list)
@@ -1227,6 +1273,35 @@
                             first)
          (setq comps  (cons first (cdr comps)))))
 
+    ;; If no buffers matched, and virtual buffers are being used, then
+    ;; consult the list of past visited files, to see if we can find
+    ;; the file which the user might thought was still open.
+    (when (and iswitchb-use-virtual-buffers (null comps)
+              recentf-list)
+      (setq iswitchb-virtual-buffers nil)
+      (let ((head recentf-list) name)
+       (while head
+         (if (and (setq name (file-name-nondirectory (car head)))
+                  (string-match (if iswitchb-regexp
+                                    iswitchb-text
+                                  (regexp-quote iswitchb-text)) name)
+                  (null (get-file-buffer (car head)))
+                  (not (assoc name iswitchb-virtual-buffers))
+                  (not (iswitchb-ignore-buffername-p name))
+                  (file-exists-p (car head)))
+             (setq iswitchb-virtual-buffers
+                   (cons (cons name (car head))
+                         iswitchb-virtual-buffers)))
+         (setq head (cdr head)))
+       (setq iswitchb-virtual-buffers (nreverse iswitchb-virtual-buffers)
+             comps (mapcar 'car iswitchb-virtual-buffers))
+       (let ((comp comps))
+         (while comp
+           (put-text-property 0 (length (car comp))
+                              'face 'font-lock-builtin-face
+                              (car comp))
+           (setq comp (cdr comp))))))
+
     (cond ((null comps) (format " %sNo match%s"
                                open-bracket-determined
                                close-bracket-determined))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]