Subject: RE: bug#13322: 24.3.50; `completion-all-sorted-completions': sorting and duplicate deletion

From: "Drew Adams" <[email-masked]>
Date: Thu, 3 Jan 2013 09:39:45 -0800

> Since the completion-all-sorted-completions function just returns the
> value of the completion-all-sorted-completions cache when 
> that cache is populated, it clearly can't take arguments since they'd
> not always be obeyed.

They would be obeyed whenever the function does not simply return the cached
value.  That's the point.

Code can call `completion--flush-all-sorted-completions' when it wants
`completion-all-sorted-completions' to update the cache.  That function
(`c--f-a-s-c') should not be "internal", BTW, IMHO.

(It might also be helpful for `completion-all-sorted-completions' itself to be
able to decide whether to reuse the cached value - other than testing its mere
presence.  It could do so based on another optional argument or on a(nother)
global variable value.)

FWIW, as an example, in `icomplete+.el' I use this version, which is essentially
what I sent here before, but this also handles `completion-ignored-extensions'
and an alist COLLECTION arg of absolute file names (for Icicles).  (See also bug
#12939, which has gotten no reply, about handling
`completion-ignored-extensions'.)

(defun icompletep-completion-all-sorted-completions
         (&optional sort-function dont-remove-dups)
  "Like `completion-all-sorted-completions', but with added optional args.
If SORT-FUNCTION is nil, sort per `completion-all-sorted-completions':
 * per property `cycle-sort-function', if defined
 * else by shorter length, then by recent use."
  (or completion-all-sorted-completions
      (let* ((start      (field-beginning))
             (end        (field-end))
             (string     (buffer-substring start end))
             (md         (completion--field-metadata start))
             (all        (completion-all-completions
                          string  minibuffer-completion-table
                          minibuffer-completion-predicate
                          (- (point) start)  md))
             (last       (last all))
             (base-size  (or (cdr last)  0))
             (all-md     (completion--metadata
                          (buffer-substring-no-properties start (point))
                          base-size md minibuffer-completion-table
                          minibuffer-completion-predicate))
             (sort-fun   (or sort-function
                             (completion-metadata-get
                               all-md 'cycle-sort-function))))
        (when last
          (setcdr last ())
          ;; Exclude files for `completion-ignored-extensions'.
          (when (or minibuffer-completing-file-name
                    (and (boundp 'icicle-abs-file-candidates)
                         icicle-abs-file-candidates))
            (setq all  (delete-if
                        (lambda (fl)
                          (string-match-p
                            (regexp-opt
                              completion-ignored-extensions)
                            fl))
                        all)))
          (unless dont-remove-dups (setq all  (delete-dups all)))
          (setq last  (last all)
                all   (if sort-fun
                          (funcall sort-fun all)
                        (sort all (lambda (c1 c2)
                                    (< (length c1)
                                       (length c2))))))
          (when (and (minibufferp)  (not sort-fun))
            (let ((hist  (symbol-value minibuffer-history-variable)))
              (setq all  (sort all (lambda (c1 c2)
                                     (> (length (member c1 hist))
                                        (length (member c2 hist))))))))
          (completion--cache-all-sorted-completions
            (nconc all base-size))))))

I call `completion--flush-all-sorted-completions' from Icicles when a user hits
`C-,' in the minibuffer, which cycles to the next Icicles candidate sort order.
This cache flushing makes Icomplete re-order the candidates, so the order in
Icomplete reflects the new current (Icicles) sort order.