Subject: 23.1; [missing feature] `minibuffer-force-completion' does not cycle through completions
From: Bruno Barbier <[email-masked]>
To: [email-masked]
Date: Mon, 21 Sep 2009 16:20:16 +0200

* Problem

The function `minibuffer-force-complete' does not cycle
through completions; it just steps through the completion list once.

* Step to reproduce:

  1. In a shell
        emacs -Q --eval "(progn                                        \
                           (define-key minibuffer-local-completion-map \
                               (kbd \"M-<tab>\" )                      \
                               #'minibuffer-force-complete)            \
                           (setq unread-command-events                 \
                                (append '(?\M-x ?s ?e ?t ?- ?v)        \
                                        '(tab M-tab M-tab)             \
                                        unread-command-events ))       \
                           ) \
                          "  
  2. Hit M-<tab>

* Result

   M-<tab> offers only "set-visited-file-name" as the sole completion.

* Expected result

   M-<tab> should allow cycling through the choices:

           set-variable
           set-visited-file-name

* Proposed solution

See attached patch against today CVS version ([2009-09-21 Mon]).

* Proposed ChangeLog item if needed.

2009-09-21    <[email-masked]> or whoever commits it

	* minibuffer.el: The function `minibuffer-force-complete' now cycles
	through the completion choices (it was just stepping through the
	completion list once).

*** emacs/lisp/minibuffer.el	Wed Sep  2 05:09:19 2009
--- patched-emacs/lisp/minibuffer.el	Mon Sep 21 15:40:24 2009
***************
*** 528,536 ****
            (setq completion-all-sorted-completions
                  (nconc all base-size))))))
  
  (defun minibuffer-force-complete ()
    "Complete the minibuffer to an exact match.
! Repeated uses step through the possible completions."
    (interactive)
    ;; FIXME: Need to deal with the extra-size issue here as well.
    (let* ((start (field-beginning))
--- 528,576 ----
            (setq completion-all-sorted-completions
                  (nconc all base-size))))))
  
+ (defun minibuffer--rotate-completions (l)
+   "Rotate the list of completions L.
+ 
+ The first element becomes the last one.	 More precisely:
+        (minibuffer--rotate-completions '(c1 c2 .. c_{n-1} cn . basesize))
+   ==>
+        (cn c1 c2 .. c_{n-1} . basesize)"
+   (if (not l) l
+     (let* ( ;; The first pair of the final result. We will set its elements
+ 	   ;; when we meet them.
+ 	   (result (cons nil nil))
+ 	   ;; The current pair we are building.
+ 	   (now	   result)
+ 	   ;; The tail of the completions we want to rotate.
+ 	   (tail   (cdr l))
+ 	   )
+       ;; We copy until the last pair.
+       (while (consp tail)
+ 	(let ((next (cons (car l) nil))
+ 	      )
+ 	  ;; make `now' points to next and shift to next.
+ 	  (setcdr now next)
+ 	  (setq now next)
+ 	  ;; update what we want to rotate on.
+ 	  (setq l tail)
+ 	  (setq tail (cdr l))
+ 	  ))
+       ;; Tail is the final element: it is basesize or nil,
+       ;; l is the last pair and its car is the last completion item.
+       (setcar result (car l))
+       (setcdr now (cdr l))
+       result)
+     ))
+ ;; @TEST with basesize: (minibuffer--rotate-completions '(1 2 3 . 4))
+ ;;	   ==> (3 1 2 . 4)
+ ;; @TEST no basesize: (minibuffer--rotate-completions '(1 2 3 4))
+ ;;	   ==> (4 1 2 3)
+ ;; @TEST limit case: (minibuffer--rotate-completions '())
+ ;;	   ==> nil
+ 
  (defun minibuffer-force-complete ()
    "Complete the minibuffer to an exact match.
! Repeated uses cycle through the possible completions."
    (interactive)
    ;; FIXME: Need to deal with the extra-size issue here as well.
    (let* ((start (field-beginning))
***************
*** 546,552 ****
        ;; completion-all-sorted-completions to nil, but we prefer not to,
        ;; so that repeated calls minibuffer-force-complete still cycle
        ;; through the previous possible completions.
!       (setq completion-all-sorted-completions (cdr all)))))
  
  (defvar minibuffer-confirm-exit-commands
    '(minibuffer-complete minibuffer-complete-word PC-complete PC-complete-word)
--- 586,594 ----
        ;; completion-all-sorted-completions to nil, but we prefer not to,
        ;; so that repeated calls minibuffer-force-complete still cycle
        ;; through the previous possible completions.
!       (setq completion-all-sorted-completions
!             (minibuffer--rotate-completions all))
!       )))
  
  (defvar minibuffer-confirm-exit-commands
    '(minibuffer-complete minibuffer-complete-word PC-complete PC-complete-word)