branch: externals/ivy
commit 11649c347107cba5f7ef8fd67ad8e77bc3b2472c
Author: Basil L. Contovounesios <[email protected]>
Commit: Basil L. Contovounesios <[email protected]>

    Fix counsel-M-x regression with amx/smex
    
    Historically counsel-M-x transformed the amx and smex collections
    into something that could be manipulated uniformly with the default
    obarray candidates.
    
    Recently this was refactored and opened up via the user option
    counsel-M-x-collection to arbitrary completion tables.
    
    The counsel-M-x :predicate was adapted accordingly, but I forgot to
    check other relevant actions and key bindings.
    
    This patch tries to introduce a bit more uniformity in action
    argument handling, at least as is relevant to counsel-M-x.
    
    * ivy.el (ivy--action-cand-to-str): New convenience function.
    (ivy--action-insert, ivy--action-copy):
    * counsel.el (counsel--info-lookup-symbol, counsel--find-symbol):
    Use it to handle symbol-keyed alists.
    (counsel--action-cand-to-interned): New convenience function,
    similar in spirit but opposite to ivy--action-cand-to-str.
    (counsel--describe-function): Use it to handle alists.
    (counsel-M-x-action): Handle alists (#3078) and as yet unknown atoms
    for flexibility.
    (counsel-descbinds-action-find): Simplify now that
    counsel--find-symbol takes symbols.
    (counsel-descbinds-action-info): Simplify;
    counsel-info-lookup-symbol takes both symbols and strings.
    
    Fixes #3078.
---
 counsel.el | 36 +++++++++++++++++++++++++++---------
 ivy.el     | 27 +++++++++++++++++----------
 2 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/counsel.el b/counsel.el
index 2d59eee1ae..5ce692ceba 100644
--- a/counsel.el
+++ b/counsel.el
@@ -477,7 +477,9 @@ Used by commands `counsel-describe-symbol',
 (defun counsel--info-lookup-symbol ()
   "Lookup the current symbol in the info docs."
   (interactive)
-  (ivy-exit-with-action #'counsel-info-lookup-symbol))
+  (ivy-exit-with-action
+   (lambda (x)
+     (counsel-info-lookup-symbol (ivy--action-cand-to-str x)))))
 (ivy--no-M-x #'counsel--info-lookup-symbol #'ivy--minibuffer-p)
 
 (defun counsel--push-xref-marker (&optional m)
@@ -497,10 +499,11 @@ Used by commands `counsel-describe-symbol',
     (ring-insert find-tag-marker-ring (or m (point-marker)))))
 
 (defun counsel--find-symbol (x)
-  "Find symbol definition that corresponds to string X."
+  "Find symbol definition that corresponds to action candidate X."
   (with-ivy-window
     (counsel--push-xref-marker)
-    (let ((full-name (get-text-property 0 'full-name x)))
+    (let* ((x (ivy--action-cand-to-str x))
+           (full-name (get-text-property 0 'full-name x)))
       (if full-name
           (find-library full-name)
         (let ((sym (read x)))
@@ -586,9 +589,16 @@ Variables declared using `defcustom' are highlighted 
according to
           (function-item ivy-thing-at-point)
           (function-item ivy-function-called-at-point)))
 
+;; FIXME: Use this more in place of `intern'.
+(defun counsel--action-cand-to-interned (x)
+  "Try to return Ivy action argument X as an existing symbol.
+Not quite the dual of `ivy--action-cand-to-str'."
+  (intern-soft (if (consp x) (car x) x)))
+
 (defun counsel--describe-function (candidate)
   "Pass string CANDIDATE to `counsel-describe-function-function'."
-  (funcall counsel-describe-function-function (intern candidate)))
+  (funcall counsel-describe-function-function
+           (counsel--action-cand-to-interned candidate)))
 
 ;;;###autoload
 (defun counsel-describe-function ()
@@ -995,9 +1005,17 @@ that returns a completion table suitable for `ivy-read'."
   "History for `counsel-M-x'.")
 
 (defun counsel-M-x-action (cmd)
-  "Execute CMD."
-  (setq cmd (intern
-             (subst-char-in-string ?\s ?- (string-remove-prefix "^" cmd))))
+  "Execute CMD from `counsel-M-x'."
+  ;; Currently CMD is a string either following `ivy-immediate-done',
+  ;; or for all collection types but alist, where CMD is the original
+  ;; cons.  There is no harm in allowing other atoms through.
+  (setq cmd (cond ((stringp cmd)
+                   ;; For the benefit of `ivy-immediate-done'.
+                   ;; FIXME: Check `intern-soft'?
+                   (intern (subst-char-in-string
+                            ?\s ?- (string-remove-prefix "^" cmd))))
+                  ((atom cmd) cmd)
+                  ((intern-soft (car cmd)))))
   (counsel--M-x-extern-rank cmd)
   ;; As per `execute-extended-command'.
   (setq this-command cmd)
@@ -1237,13 +1255,13 @@ See `execute-extended-command' for further information."
   "Find symbol definition of candidate X.
 See `counsel--find-symbol' for further information."
   (let ((cmd (cddr x)))
-    (counsel--find-symbol (symbol-name cmd))))
+    (counsel--find-symbol cmd)))
 
 (defun counsel-descbinds-action-info (x)
   "Display symbol definition of candidate X, as found in the relevant manual.
 See `info-lookup-symbol' for further information."
   (let ((cmd (cddr x)))
-    (counsel-info-lookup-symbol (symbol-name cmd))))
+    (counsel-info-lookup-symbol cmd)))
 
 ;;;###autoload
 (defun counsel-descbinds (&optional prefix buffer)
diff --git a/ivy.el b/ivy.el
index 47b3a36529..a6aca7a2af 100644
--- a/ivy.el
+++ b/ivy.el
@@ -4796,25 +4796,32 @@ Otherwise, forward to `ivy-kill-line'."
 
 (ivy-set-actions
  t
- '(("i" ivy--action-insert "insert")
-   ("w" ivy--action-copy "copy")))
+ `(("i" ,#'ivy--action-insert "insert")
+   ("w" ,#'ivy--action-copy "copy")))
 
 (defun ivy--trim-grep-line-number (x)
   (if (string-match ":[0-9]+:" x)
       (substring x (match-end 0))
     x))
 
+(defun ivy--action-cand-to-str (x)
+  "Try to return Ivy action argument X as a string."
+  (let ((x (if (consp x) (car x) x)))
+    (if (symbolp x) (symbol-name x) x)))
+
 (defun ivy--action-insert (x)
-  (insert
-   (if (stringp x)
-       (ivy--trim-grep-line-number x)
-     (car x))))
+  "Insert completion candidate X into current buffer at point."
+  (insert (funcall (if (stringp x)
+                       #'ivy--trim-grep-line-number
+                     #'ivy--action-cand-to-str)
+                   x)))
 
 (defun ivy--action-copy (x)
-  (kill-new
-   (if (stringp x)
-       (ivy--trim-grep-line-number x)
-     (car x))))
+  "Add completion candidate X to the kill ring."
+  (kill-new (funcall (if (stringp x)
+                         #'ivy--trim-grep-line-number
+                       #'ivy--action-cand-to-str)
+                     x)))
 
 (defun ivy--switch-buffer-matcher (regexp candidates)
   "Return REGEXP matching CANDIDATES.

Reply via email to