Subject: bug#34070: 27.0.50; icomplete-mode candidate cycling broken for C-x C-f

From: João Távora <[email-masked]>
Date: Thu, 17 Jan 2019 14:20:38 +0000

tag 34070 patch

Drew Adams <[email-masked]> writes:

>> > I'd like to push the fix before that maybe, any objections?
>> 
>> Please wait for Drew to respond, before you do.
>
> I took a look at the bug description, reproduced it, and took a look
> at the proposed patch.  It looks OK to me.  Thx.

I've already pushed the proposed patch to master, but there's a much
less intrusive way using a new patch attached after my sig.

Significantly, while still honouring the original intention of Drew's
change:

   65797b1d7 "Make icomplete respect `completion-ignored-extensions'"

the new patch does two things:

   1. Still fixes the candidate cycling (i.e. this bug)
   
   2. Leaves the current directory as a candidate, i.e. "./" is *not*
      filtered from the prospects list (but "../" is).

Number 2 can be seen as "new" behaviour, but then Drew's patch also
silently introduced new behaviour by filtering out "./" and "../", which
are *not* in completion-ignored-extensions.  Reading bug#12939
(https://debbugs.gnu.org/12939) this seems to have gone unnoticed.

If someone thinks this is a problem we can make this configurable
(though I think the default should be what I suggest, since it makes C-x
C-f'ing directories much easier).

João

>From 99c712809fca46648a02451c4eaa8196e915207b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= <[email-masked]>
Date: Tue, 15 Jan 2019 12:10:23 +0000
Subject: [PATCH 2/5] Simplify ignored extensions filtering in Icomplete
 (bug#34070)

* lisp/icomplete.el: Use lexical binding.
(icomplete--filtered-completions): Remove.
(icomplete-forward-completions, icomplete-backward-completions):
Revert last change.
(icomplete-completions): Use minibuffer-completion-predicate
to filter out completion-ignored-extensions.
---
 lisp/icomplete.el | 45 ++++++++++++++++++++++++---------------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 82e2728487..6d77c0649a 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -1,4 +1,4 @@
-;;; icomplete.el --- minibuffer completion incremental feedback
+;;; icomplete.el --- minibuffer completion incremental feedback -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1992-1994, 1997, 1999, 2001-2019 Free Software
 ;; Foundation, Inc.
@@ -162,9 +162,6 @@ icomplete-force-complete-and-exit
       (minibuffer-force-complete-and-exit)
     (minibuffer-complete-and-exit)))
 
-(defvar icomplete--filtered-completions nil
-  "If non-nil completions as filtered by `icomplete-completions'")
-
 (defun icomplete-forward-completions ()
   "Step forward completions by one entry.
 Second entry becomes the first and can be selected with
@@ -172,8 +169,7 @@ icomplete-forward-completions
   (interactive)
   (let* ((beg (icomplete--field-beg))
          (end (icomplete--field-end))
-         (comps (or icomplete--filtered-completions
-                    (completion-all-sorted-completions beg end)))
+         (comps (completion-all-sorted-completions beg end))
 	 (last (last comps)))
     (when comps
       (setcdr last (cons (car comps) (cdr last)))
@@ -186,8 +182,7 @@ icomplete-backward-completions
   (interactive)
   (let* ((beg (icomplete--field-beg))
          (end (icomplete--field-end))
-         (comps (or icomplete--filtered-completions
-                    (completion-all-sorted-completions beg end)))
+         (comps (completion-all-sorted-completions beg end))
 	 (last-but-one (last comps 2))
 	 (last (cdr last-but-one)))
     (when (consp last)		      ; At least two elements in comps
@@ -373,8 +368,21 @@ icomplete-completions
 The displays for unambiguous matches have ` [Matched]' appended
 \(whether complete or not), or ` [No matches]', if no eligible
 matches exist."
-  (let* ((minibuffer-completion-table candidates)
-	 (minibuffer-completion-predicate predicate)
+  (let* ((ignored-extension-re
+          (and minibuffer-completing-file-name
+               icomplete-with-completion-tables
+               completion-ignored-extensions
+               (concat "\\(?:\\`\\.\\./\\|"
+                       (regexp-opt completion-ignored-extensions)
+                       "\\)\\'")))
+         (minibuffer-completion-table candidates)
+	 (minibuffer-completion-predicate
+          (if ignored-extension-re
+              (lambda (cand)
+                (and (not (string-match ignored-extension-re cand))
+                     (or (null predicate)
+                         (funcall predicate cand))))
+            predicate))
 	 (md (completion--field-metadata (icomplete--field-beg)))
 	 (comps (completion-all-sorted-completions
                  (icomplete--field-beg) (icomplete--field-end)))
@@ -385,13 +393,8 @@ icomplete-completions
     ;; `concat'/`mapconcat' is the slow part.
     (if (not (consp comps))
 	(progn ;;(debug (format "Candidates=%S field=%S" candidates name))
-	       (format " %sNo matches%s" open-bracket close-bracket))
+	  (format " %sNo matches%s" open-bracket close-bracket))
       (if last (setcdr last nil))
-      (if (and minibuffer-completing-file-name
-               icomplete-with-completion-tables)
-          (setq comps (completion-pcm--filename-try-filter comps)
-                icomplete--filtered-completions comps)
-        (setq icomplete--filtered-completions nil))
       (let* ((most-try
               (if (and base-size (> base-size 0))
                   (completion-try-completion
@@ -477,11 +480,11 @@ icomplete-completions
 		  (if prefix-len (substring (car comps) prefix-len) (car comps))
 		  comps (cdr comps))
 	    (setq prospects-len
-                           (+ (string-width comp)
-			      (string-width icomplete-separator)
-			      prospects-len))
-		     (if (< prospects-len prospects-max)
-			 (push comp prospects)
+                  (+ (string-width comp)
+		     (string-width icomplete-separator)
+		     prospects-len))
+	    (if (< prospects-len prospects-max)
+		(push comp prospects)
 	      (setq limit t))))
 	(setq prospects (nreverse prospects))
 	;; Decorate first of the prospects.
-- 
2.19.2