]> git.eshelyaron.com Git - emacs.git/commitdiff
(iswitchb-completion-help): Multiple TAB presses
authorKarl Heuer <kwzh@gnu.org>
Fri, 19 Dec 1997 14:58:42 +0000 (14:58 +0000)
committerKarl Heuer <kwzh@gnu.org>
Fri, 19 Dec 1997 14:58:42 +0000 (14:58 +0000)
scroll the completion window.
(iswitchb-read-buffer): New function to act as drop-in replacement
for read-buffer.

lisp/iswitchb.el

index 862d5ef30452c181c8cc094782fb3ed4ddf89f44..fb57ff69bad9b03980d8c612e109a11f7501aaaa 100644 (file)
 ;; Of course, where this function comes in really useful is when you
 ;; can specify the buffer using only a few keystrokes.  In the above
 ;; example, the quickest way to get to the "123456" buffer would be
-;; just to type 4 and then RET (assuming there isnt any newer buffer
+;; just to type 4 and then RET (assuming there isn't any newer buffer
 ;; with 4 in its name).
 
 ;; To see a full list of all matching buffers in a separate buffer,
 ;; hit ? or press TAB when there are no further completions to the
-;; substring.
+;; substring.  Repeated TAB presses will scroll you through this
+;; separate buffer.
 
 ;; The buffer at the head of the list can be killed by pressing C-k.
 ;; If the buffer needs saving, you will be queried before the buffer
 ;;       'iswitchb-my-keys)
 ;;
 ;;(defun iswitchb-my-keys ()
-;;  "Add my keybings for iswitchb."
+;;  "Add my keybindings for iswitchb."
 ;;  (define-key iswitchb-mode-map " " 'iswitchb-next-match)
 ;;  )
 ;;
 ;; this is too harsh, let me know.  Colouring of the matching buffer
 ;; name was suggested by Carsten Dominik (dominik@strw.leidenuniv.nl)
 
-;;; Comparison with iswitch-buffer
-
-;; This package is a rewrite of iswitch-buffer, using the minibuffer
-;; rather than the echo area.  The advantages of using the minibuffer
-;; are several:
-;; o minibuffer has more powerful editing facilities
-;; o doesnt interfere with other packages that use the echo area
-;; o *Messages* buffer doesnt get filled up with all of the messages that
-;;   go to the modeline
-;; o cursor is in the minibuffer, which somehow looks right.
-;; o minibuffer can be resized dynamically to show all the possible matching
-;;   buffers rather than just the first line's worth (using rsz-mini).
-;;
-;; Disadvantages:
-;; o cant change the prompt to indicate status of searching (eg whether
-;;   regexp searching is currently on).
 
+;; Replacement for read-buffer.
 
-;;; TODO
-;; Could this selection also be used for other buffer selection
-;; routines, such as append-to-buffer and kill-buffer?
+;; iswitchb-read-buffer has been written to be a drop in replacement
+;; for the normal buffer selection routine `read-buffer'.  To use
+;; iswitch for all buffer selections, add:
+;; (setq read-buffer-function 'iswitchb-read-buffer)
 
-;; Pressing Tab key twice (without completion) does not scroll the
-;; list of buffers.
+;;; TODO
 
 ;;; Acknowledgements
 
@@ -367,7 +353,7 @@ interfere with other minibuffer usage.")
   "Stores the users string as it is typed in.")
 
 (defvar iswitchb-matches nil
-  "List of buffers currenly matching `iswitchb-text'.")
+  "List of buffers currently matching `iswitchb-text'.")
 
 (defvar iswitchb-mode-map nil
   "Keymap for `iswitchb-buffer'.")
@@ -395,7 +381,7 @@ selected.")
   "Set up the keymap for `iswitchb-buffer'."
   (interactive)
   (let (map)
-    ;; generated every time so that it can inheret new functions.
+    ;; generated every time so that it can inherit new functions.
     ;;(or iswitchb-mode-map
 
     (setq map (copy-keymap minibuffer-local-map))
@@ -409,6 +395,7 @@ selected.")
     ;;(define-key map "\C-a" 'iswitchb-toggle-ignore)
     (define-key map "\C-c" 'iswitchb-toggle-case)
     (define-key map "\C-k" 'iswitchb-kill-buffer)
+    (define-key map "\C-m" 'iswitchb-exit-minibuffer)
     (setq iswitchb-mode-map map)
     (run-hooks 'iswitchb-define-mode-map-hook)
     ))
@@ -436,7 +423,7 @@ If no buffer is found, prompt for a new one.
 matches all buffers.  If there is only one match, select that buffer.
 If there is no common suffix, show a list of all matching buffers
 in a separate window.
-\\[iswitchb-toggle-regexp] Toggle rexep searching.
+\\[iswitchb-toggle-regexp] Toggle regexp searching.
 \\[iswitchb-toggle-case] Toggle case-sensitive searching of buffer names.
 \\[iswitchb-completion-help] Show list of matching buffers in separate window.
 \\[iswitchb-find-file] Exit iswitchb and drop into find-file.
@@ -444,69 +431,94 @@ in a separate window.
   ;;\\[iswitchb-toggle-ignore] Toggle ignoring certain buffers (see \
   ;;`iswitchb-buffer-ignore')
        
+  (let
+      (prompt buf)
+    
+    (setq prompt (format "iswitch "))
+
+    (setq buf (iswitchb-read-buffer prompt))
+
+
+    ;;(message "chosen text %s" iswitchb-final-text)
+    ;; Choose the buffer name: either the text typed in, or the head
+    ;; of the list of matches
+
+    (cond ( (eq iswitchb-exit 'findfile)
+           (call-interactively 'find-file))
+
+         (t
+          ;; View the buffer
+          (message "go to buf %s" buf)
+          ;; Check buf is non-nil.
+          (if buf
+              (if (get-buffer buf)
+                  ;; buffer exists, so view it and then exit
+                  (iswitchb-visit-buffer buf)
+                ;; else buffer doesn't exist
+                (iswitchb-possible-new-buffer buf)))
+          ))
+    
+    ))
+
+
+
+(defun iswitchb-read-buffer (prompt &optional default require-match)
+  "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."
   (let
       (
-       prompt
        buf-sel
        iswitchb-final-text
-       (minibuffer-confirm-incomplete nil) ;XEmacs todo: prevent `;confirm'
        (icomplete-mode nil) ;; prevent icomplete starting up
        ;; can only use fonts if they have been bound.
        (iswitchb-use-fonts (and iswitchb-use-fonts
                                (boundp 'font-lock-comment-face)
-                               (boundp 'font-lock-function-name-face)))
-       )
-    
+                               (boundp 'font-lock-function-name-face))))
+
     (iswitchb-define-mode-map)
     (setq iswitchb-exit nil)
     (setq iswitchb-rescan t)
     (setq iswitchb-text "")
+    (iswitchb-make-buflist default)
     (iswitchb-set-matches)
-    (setq prompt (format "iswitch "))
-    (iswitchb-make-buflist)
     (let 
-       ((minibuffer-local-completion-map iswitchb-mode-map))
+       ((minibuffer-local-completion-map iswitchb-mode-map)
+        (iswitchb-prepost-hooks t)
+        (iswitchb-require-match require-match) 
+        )
       ;; prompt the user for the buffer name
-      (setq iswitchb-final-text (completing-read prompt
-                                                ;;nil
-                                                '(("dummy".1))
-                                                ;;("2".2)  ("3".3))
-                                                nil nil
-                                                nil;init string
-                                                'iswitchb-history)))
-      
-    ;;(message "chosen text %s" iswitchb-final-text)
-    ;; Choose the buffer name: either the text typed in, or the head
-    ;; of the list of matches
+      (setq iswitchb-final-text (completing-read 
+                                prompt ;the prompt
+                                '(("dummy".1)) ;table
+                                nil    ;predicate
+                                nil    ;require-match [handled elsewhere]
+                                nil    ;initial-contents
+                                'iswitchb-history)))
+    ;; Handling the require-match must be done in a better way.
+    (if (and require-match (not (iswitchb-existing-buffer-p)))
+       (error "must specify valid buffer"))
+
+    (if (or 
+        (eq iswitchb-exit 'takeprompt)
+        (null iswitchb-matches))
+       (setq buf-sel iswitchb-final-text)
+      ;; else take head of list
+      (setq buf-sel (car iswitchb-matches)))
+    
+    ;; Or possibly choose the default buffer
+    (if  (equal iswitchb-final-text "")        
+       (setq buf-sel 
+             (car iswitchb-matches)))
 
-    (cond ( (eq iswitchb-exit 'findfile)
-           (call-interactively 'find-file))
+    buf-sel))
 
-         (t
-          (if (or 
-               (eq iswitchb-exit 'takeprompt)
-               (null iswitchb-matches))
-              (setq buf-sel iswitchb-final-text)
-            ;; else take head of list
-            (setq buf-sel (car iswitchb-matches)))
-    
-          ;; Or possibly choose the default buffer
-          (if  (equal iswitchb-final-text "")
-              (setq buf-sel (car iswitchb-matches)))
-    
-          ;; View the buffer
-          (message "go to buf %s" buf-sel)
-          ;; Check buf-sel is non-nil.
-          (if buf-sel
-              (if (get-buffer buf-sel)
-                  ;; buffer exists, so view it and then exit
-                  (iswitchb-visit-buffer buf-sel)
-                ;; else buffer doesnt exist
-                (iswitchb-possible-new-buffer buf-sel)))
-          ))
-    
-    ))
 
+(defun iswitchb-existing-buffer-p ()
+  "Return non-nil if there is a matching buffer."
+  (not (null iswitchb-matches)))
 
 ;;; COMPLETION CODE
 
@@ -534,7 +546,7 @@ The result is stored in `iswitchb-common-match-string'."
           (iswitchb-completion-help)
           )
          
-         ((eq 1 (length iswitchb-matches))
+         ((= 1 (length iswitchb-matches))
           ;; only one choice, so select it.
           (exit-minibuffer))
          
@@ -545,7 +557,7 @@ The result is stored in `iswitchb-common-match-string'."
                      iswitchb-matches iswitchb-text))
           (if (and (not (memq res '(t nil)))
                    (not (equal res iswitchb-text)))
-              ;; found something to complete, so put it in the minibuff.
+              ;; found something to complete, so put it in the minibuffer.
               (progn
                 (setq iswitchb-rescan nil)
                 (delete-region (point-min) (point))
@@ -592,6 +604,13 @@ The result is stored in `iswitchb-common-match-string'."
   (setq iswitchb-rescan t)
   )
 
+(defun iswitchb-exit-minibuffer ()
+  "Exit minibuffer, but make sure we have a match if one is needed."
+  (interactive)
+  (if (or (not iswitchb-require-match)
+          (iswitchb-existing-buffer-p))
+      (throw 'exit nil)
+    ))
 
 (defun iswitchb-select-buffer-text ()
   "Select the buffer named by the prompt.
@@ -648,12 +667,13 @@ If no buffer exactly matching the prompt exists, maybe create a new one."
 ;;; CREATE LIST OF ALL CURRENT BUFFERS
 
 
-(defun iswitchb-make-buflist ()
+(defun iswitchb-make-buflist (default)
   "Set `iswitchb-buflist' to the current list of buffers.
 Currently visible buffers are put at the end of the list.
 The hook `iswitchb-make-buflist-hook' is run after the list has been 
 created to allow the user to further modify the order of the buffer names
-in this list."
+in this list.  If DEFAULT is non-nil, and corresponds to an existing buffer,
+it is put to the start of the list."
   (setq iswitchb-buflist 
        (let* ((iswitchb-current-buffers (iswitchb-get-buffers-in-frames))
              (buflist 
@@ -669,7 +689,14 @@ in this list."
                      (buffer-list)))))
          (nconc buflist iswitchb-current-buffers)
          (run-hooks 'iswitchb-make-buflist-hook)
-         buflist)))
+         ;; Should this be after the hooks, or should the hooks be the
+         ;; final thing to be run?
+         (if default
+             (progn
+               (setq buflist (delete default buflist))
+               (setq buflist (cons default buflist))
+               ))
+           buflist)))
 
 (defun iswitchb-to-end (lst)
   "Move the elements from LST to the end of BUFLIST."
@@ -809,7 +836,7 @@ If `iswitchb-change-word-sub' cannot be found in WORD, return nil."
               subs
             (regexp-quote subs)))
     (setq res (mapcar 'iswitchb-word-matching-substring lis))
-    (setq res (delq nil res)) ;; remove any nil elements (shouldnt happen)
+    (setq res (delq nil res)) ;; remove any nil elements (shouldn't happen)
     (setq alist (mapcar 'iswitchb-makealist res)) ;; could use an  OBARRAY
 
     ;; try-completion returns t if there is an exact match.
@@ -847,30 +874,47 @@ Return the modified list with the last element prepended to it."
   (interactive)
   (setq iswitchb-rescan nil)
   (let ((completion-setup-hook nil)    ;disable fancy highlight/selection.
-       )
-    (with-output-to-temp-buffer "*Buffer Completions*"
-      (if iswitchb-xemacs 
-         
-         ;; XEmacs extents are put on by default, doesn't seem to be
-         ;; any way of switching them off.
-         (display-completion-list (if iswitchb-matches
-                                      iswitchb-matches
-                                    iswitchb-buflist)
-                                  :help-string "iswitchb "
+       (buf (current-buffer))
+       (temp-buf "*Buffer Completions*")
+       (win)
+       (again (eq last-command this-command)))
+
+    (if again
+       ;; scroll buffer
+       (progn
+         (set-buffer temp-buf)
+         (setq win (get-buffer-window temp-buf))
+         (if (pos-visible-in-window-p (point-max) win)
+             (set-window-start win (point-min))
+           (scroll-other-window))
+         (set-buffer buf)
+         )
+
+      
+      (with-output-to-temp-buffer temp-buf
+       (if iswitchb-xemacs 
+           
+           ;; XEmacs extents are put on by default, doesn't seem to be
+           ;; any way of switching them off.
+           (display-completion-list (if iswitchb-matches
+                                        iswitchb-matches
+                                      iswitchb-buflist)
+                                    :help-string "iswitchb "
                                   :activate-callback 
                                   '(lambda (x y z) 
-                                     (message "doesnt work yet, sorry!")))
-       ;; else running Emacs
-       (display-completion-list (if iswitchb-matches
+                                     (message "doesn't work yet, sorry!")))
+         ;; else running Emacs
+         (display-completion-list (if iswitchb-matches
                                     iswitchb-matches
-                                  iswitchb-buflist))
-       ))))
+                                    iswitchb-buflist))
+         )))))
+
 
 
 ;;; KILL CURRENT BUFFER
 
 (defun iswitchb-kill-buffer ()
-  "Kill the buffer at the head of `iswtichb-matches'."
+  "Kill the buffer at the head of `iswitchb-matches'."
   (interactive)
   (let ( (enable-recursive-minibuffers t)
         buf)
@@ -965,8 +1009,8 @@ If BUFFER is visible in the current frame, return nil."
     ;;If the buffer is visible in current frame, return nil
     (if (memq buffer blist)
        nil
-      ;;  maybe in other frame...
-      (get-buffer-window buffer 'visible)
+      ;;  maybe in other frame or icon
+      (get-buffer-window buffer 0) ; better than 'visible
       )))
 
 ;;;###autoload
@@ -991,7 +1035,7 @@ in another frame.
 For details of keybindings, do `\\[describe-function] iswitchb'."
   (interactive)
   (setq iswitchb-method iswitchb-default-method)
-  (iswitchb-entry))
+  (iswitchb))
 
 
 ;;;###autoload
@@ -1001,7 +1045,7 @@ The buffer name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] iswitchb'."
   (interactive)
   (setq iswitchb-method 'otherwindow)
-  (iswitchb-entry))
+  (iswitchb))
 
 
 
@@ -1012,7 +1056,7 @@ The buffer name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] iswitchb'."
   (interactive)
   (setq iswitchb-method 'display)
-  (iswitchb-entry))
+  (iswitchb))
 
 
 
@@ -1023,22 +1067,12 @@ The buffer name is selected interactively by typing a substring.
 For details of keybindings, do `\\[describe-function] iswitchb'."
   (interactive)
   (setq iswitchb-method 'otherframe)
-  (iswitchb-entry))
-
-
-
-(defun iswitchb-entry ()
-  "Simply fall into `iswitchb' -- the main function."
   (iswitchb))
 
-
-
-
-
 ;;; XEmacs hack for showing default buffer
 
 ;; The first time we enter the minibuffer, Emacs puts up the default
-;; buffer to switch to, but XEmacs doesnt -- presumably there is a
+;; buffer to switch to, but XEmacs doesn't -- presumably there is a
 ;; subtle difference in the two versions of post-command-hook.  The
 ;; default is shown for both whenever we delete all of our text
 ;; though, indicating its just a problem the first time we enter the
@@ -1061,7 +1095,7 @@ This is a hack for XEmacs, and should really be handled by `iswitchb-exhibit'."
 
 
 ;;; XEmacs / backspace key
-;; For some reason, if the backspace key is pressed in xemacs, the
+;; For some reason, if the backspace key is pressed in XEmacs, the
 ;; line gets confused, so I've added a simple key definition to make
 ;; backspace act like the normal delete key.  
 
@@ -1135,7 +1169,7 @@ Modified from `icomplete-completions'."
          (setq first (car comps))
          (setq first (format "%s" first))
          (put-text-property 0 (length first) 'face
-                            (if (eq (length comps) 1) 
+                            (if (= (length comps) 1) 
                                 'font-lock-comment-face
                               'font-lock-function-name-face)
                             first) 
@@ -1262,12 +1296,17 @@ Copied from `icomplete-tidy'."
 
 (defun iswitchb-entryfn-p ()
   "Return non-nil if `this-command' shows we are using `iswitchb-buffer'."
-  (and (symbolp this-command)          ; ignore lambda functions
-       (memq this-command
-            '(iswitchb-buffer
-              iswitchb-buffer-other-frame
-              iswitchb-display-buffer
-              iswitchb-buffer-other-window))))
+  (or (boundp 'iswitchb-prepost-hooks)
+      ;; I think the of this may be redundant, since the prepost hooks
+      ;; will always be set in the iswitchb defuns.
+      ;;(and (symbolp this-command)            ; ignore lambda functions
+      ;;(memq this-command
+      ;;        '(iswitchb-buffer
+      ;;          iswitchb-buffer-other-frame
+      ;;       iswitchb-display-buffer
+      ;;       iswitchb-buffer-other-window))))
+  ))
+