master 5081ab07952: icomplete.el (icomplete-fido-kill): Make it extensible (bug#72210)

Stefan Monnier via Mailing list for Emacs changes <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 5081ab0795291f990e6c774d844ac8c4a1707a1d
Author: Stefan Monnier <[email protected]>
Commit: Stefan Monnier <[email protected]>

    icomplete.el (icomplete-fido-kill): Make it extensible (bug#72210)
    
    * lisp/icomplete.el (icomplete-kill-candidate): New generic function.
    (icomplete-fido-kill): Use it instead of hardcoding support for
    files and buffers.
---
 lisp/icomplete.el | 49 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 33 insertions(+), 16 deletions(-)

diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 8902cb2354e..d6a326ba88c 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -387,6 +387,32 @@ Return non-nil if something was stepped."
 
 ;;;_* Helpers for `fido-mode' (or `ido-mode' emulation)
 
+(cl-defgeneric icomplete-kill-candidate (category _candidate)
+  "\"Kill\" CANDIDATE, assuming it is of kind CATEGORY.
+CANDIDATE is a string denoting a completion candidate,
+CATEGORY should be a completion category, as specified
+in `completion-metadata'.
+\"Kill\" here means to actually delete the underlying object, such
+as a file, buffer, ...
+Return non-nil if the operation was successful."
+  (error "Don't know how to kill things for category `%s'" category))
+
+(cl-defmethod icomplete-kill-candidate ((_ (eql 'buffer)) thing)
+  (kill-buffer thing))
+
+(cl-defmethod icomplete-kill-candidate ((_ (eql 'file)) thing)
+  ;; FIXME: This makes assumptions about completion style: e.g. with
+  ;; partial-completion, `/usr/s/d/ema' can result in DIR being
+  ;; `/usr/s/d/' and THING being `share/doc/emacs', in which case DIR
+  ;; isn't the right base directory to pass to `expand-file-name'!
+  (let* ((dir (file-name-directory (icomplete--field-string)))
+         (file (expand-file-name thing dir)))
+    (delete-file file)
+    t))
+
+(cl-defmethod icomplete-kill-candidate ((_ (eql 'project-file)) thing)
+  (icomplete-kill-candidate 'file thing))
+
 (defun icomplete-fido-kill ()
   "Kill line or current completion, like `ido-mode'.
 If killing to the end of line make sense, call `kill-line',
@@ -401,26 +427,15 @@ require user confirmation."
         (call-interactively 'kill-line)
       (let* ((all (completion-all-sorted-completions))
              (thing (car all))
-             (cat (icomplete--category))
-             (action
-              (cl-case cat
-                (buffer
-                 (lambda ()
-                   (when (yes-or-no-p (concat "Kill buffer " thing "? "))
-                     (kill-buffer thing))))
-                ((project-file file)
-                 (lambda ()
-                   (let* ((dir (file-name-directory (icomplete--field-string)))
-                          (path (expand-file-name thing dir)))
-                     (when (yes-or-no-p (concat "Delete file " path "? "))
-                       (delete-file path) t))))
-                (t
-                 (error "Sorry, don't know how to kill things for `%s'" cat)))))
+             (cat (icomplete--category)))
         (when (let (;; Allow `yes-or-no-p' to work and don't let it
                     ;; `icomplete-exhibit' anything.
                     (enable-recursive-minibuffers t)
                     (icomplete-mode nil))
-                (funcall action))
+                ;; FIXME: For some categories (like `multi-category'), this
+                ;; results in a poor prompt.
+                (when (yes-or-no-p (format "Kill %s %s? " cat thing))
+                  (icomplete-kill-candidate cat thing)))
           (completion--cache-all-sorted-completions
            (icomplete--field-beg)
            (icomplete--field-end)
@@ -443,6 +458,8 @@ require user confirmation."
                    (file-name-directory (icomplete--field-string))))
          (current (car completion-all-sorted-completions))
          (probe (and dir current
+                     ;; FIXME: Same problem as in
+                     ;; `icomplete-kill-candidate<file>' above.
                      (expand-file-name (directory-file-name current)
                                        (substitute-env-vars dir)))))
     (cond ((and probe (file-directory-p probe) (not (string= current "./")))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.