emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master 28e88ab 025/399: Allow to mark/unmark candidates with "m",


From: Oleh Krehel
Subject: [elpa] master 28e88ab 025/399: Allow to mark/unmark candidates with "m", "u", "DEL", "t"
Date: Sat, 20 Jul 2019 14:56:41 -0400 (EDT)

branch: master
commit 28e88ab23a191420a93a4f920ca076674ee53f94
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>

    Allow to mark/unmark candidates with "m", "u", "DEL", "t"
    
    These key bindings are now available in the "C-o" hydra.
    
    * ivy.el (ivy-marked-candidates):
    (ivy-mark-prefix): New defvar.
    (ivy-call): Use `ivy-marked-candidates' when non-nil.
    (ivy-read): Reset `ivy-marked-candidates' to nil.
    (ivy-mark):
    (ivy-unmark):
    (ivy-unmark-backward):
    (ivy-toggle-marks): New command.
    
    Fixes #561
---
 ivy-hydra.el | 16 +++++++----
 ivy.el       | 94 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 89 insertions(+), 21 deletions(-)

diff --git a/ivy-hydra.el b/ivy-hydra.el
index 5b0054e..89d8b81 100644
--- a/ivy-hydra.el
+++ b/ivy-hydra.el
@@ -46,8 +46,8 @@
   "
 ^ ^ ^ ^ ^ ^ | ^Call^      ^ ^  | ^Cancel^ | ^Options^ | Action _w_/_s_/_a_: 
%-14s(ivy-action-name)
 
^-^-^-^-^-^-+-^-^---------^-^--+-^-^------+-^-^-------+-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------
-^ ^ _k_ ^ ^ | _f_ollow occ_u_r | _i_nsert | _c_: calling %-5s(if ivy-calling 
\"on\" \"off\") _C_ase-fold: %-10`ivy-case-fold-search
-_h_ ^+^ _l_ | _d_one      ^ ^  | _o_ops   | _m_: matcher 
%-5s(ivy--matcher-desc)^^^^^^^^^^^^ _t_runcate: %-11`truncate-lines
+^ ^ _k_ ^ ^ | _f_ollow occ_U_r | _i_nsert | _c_: calling %-5s(if ivy-calling 
\"on\" \"off\") _C_ase-fold: %-10`ivy-case-fold-search
+_h_ ^+^ _l_ | _d_one      ^ ^  | _o_ops   | _M_: matcher 
%-5s(ivy--matcher-desc)^^^^^^^^^^^^ _T_runcate: %-11`truncate-lines
 ^ ^ _j_ ^ ^ | _g_o        ^ ^  | ^ ^      | _<_/_>_: 
shrink/grow^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _D_efinition of this menu
 "
   ;; arrows
@@ -55,8 +55,14 @@ _h_ ^+^ _l_ | _d_one      ^ ^  | _o_ops   | _m_: matcher 
%-5s(ivy--matcher-desc)
   ("j" ivy-next-line)
   ("k" ivy-previous-line)
   ("l" ivy-end-of-buffer)
+  ;; mark
+  ("m" ivy-mark)
+  ("u" ivy-unmark)
+  ("DEL" ivy-unmark-backward)
+  ("t" ivy-toggle-marks)
   ;; actions
   ("o" keyboard-escape-quit :exit t)
+  ("r" ivy-dispatching-done-hydra :exit t)
   ("C-g" keyboard-escape-quit :exit t)
   ("i" nil)
   ("C-o" nil)
@@ -66,15 +72,15 @@ _h_ ^+^ _l_ | _d_one      ^ ^  | _o_ops   | _m_: matcher 
%-5s(ivy--matcher-desc)
   ("g" ivy-call)
   ("C-m" ivy-done :exit t)
   ("c" ivy-toggle-calling)
-  ("m" ivy-rotate-preferred-builders)
+  ("M" ivy-rotate-preferred-builders)
   (">" ivy-minibuffer-grow)
   ("<" ivy-minibuffer-shrink)
   ("w" ivy-prev-action)
   ("s" ivy-next-action)
   ("a" ivy-read-action)
-  ("t" (setq truncate-lines (not truncate-lines)))
+  ("T" (setq truncate-lines (not truncate-lines)))
   ("C" ivy-toggle-case-fold)
-  ("u" ivy-occur :exit t)
+  ("U" ivy-occur :exit t)
   ("D" (ivy-exit-with-action
         (lambda (_) (find-function 'hydra-ivy/body)))
        :exit t))
diff --git a/ivy.el b/ivy.el
index 184acf4..f7a997f 100644
--- a/ivy.el
+++ b/ivy.el
@@ -1265,6 +1265,16 @@ See variable `ivy-recursive-restore' for further 
information."
              (not (eq ivy-last ivy-recursive-last)))
     (ivy--reset-state (setq ivy-last ivy-recursive-last))))
 
+(defvar ivy-marked-candidates nil
+  "List of marked candidates.
+Use `ivy-mark' to populate this.
+
+When this list is non-nil at the end of the session, the action
+will be called for each element of this list.")
+
+(defvar ivy-mark-prefix ">"
+  "Prefix used by `ivy-mark'.")
+
 (defun ivy-call ()
   "Call the current action without exiting completion."
   (interactive)
@@ -1281,26 +1291,30 @@ See variable `ivy-recursive-restore' for further 
information."
       (let* ((collection (ivy-state-collection ivy-last))
              (current (ivy-state-current ivy-last))
              (x (cond
-                 ;; Alist type.
-                 ((and (consp (car-safe collection))
-                       ;; Previously, the cdr of the selected
-                       ;; candidate would be returned.  Now, the
-                       ;; whole candidate is returned.
-                       (let ((idx (get-text-property 0 'idx current)))
-                         (if idx
-                             (nth idx collection)
-                           (assoc current collection)))))
-                 (ivy--directory
-                  (expand-file-name current ivy--directory))
-                 ((equal current "")
-                  ivy-text)
-                 (t
-                  current))))
+                  ;; Alist type.
+                  ((and (consp (car-safe collection))
+                        ;; Previously, the cdr of the selected
+                        ;; candidate would be returned.  Now, the
+                        ;; whole candidate is returned.
+                        (let ((idx (get-text-property 0 'idx current)))
+                          (if idx
+                              (nth idx collection)
+                            (assoc current collection)))))
+                  (ivy--directory
+                   (expand-file-name current ivy--directory))
+                  ((equal current "")
+                   ivy-text)
+                  (t
+                   current))))
         (if (eq action #'identity)
             (funcall action x)
           (select-window (ivy--get-window ivy-last))
           (set-buffer (ivy-state-buffer ivy-last))
-          (prog1 (unwind-protect (funcall action x)
+          (prog1 (unwind-protect
+                      (if ivy-marked-candidates
+                          (dolist (c ivy-marked-candidates)
+                            (funcall action (substring c (length 
ivy-mark-prefix))))
+                        (funcall action x))
                    (ivy-recursive-restore))
             (unless (or (eq ivy-exit 'done)
                         (minibuffer-window-active-p (selected-window))
@@ -1828,6 +1842,7 @@ customizations apply to the current completion session."
                      ,@extra-actions))
                   (t
                    (delete-dups (append action extra-actions)))))))
+  (setq ivy-marked-candidates nil)
   (unless caller
     (setq caller this-command))
   (let ((extra-sources (plist-get ivy--sources-list caller)))
@@ -4441,6 +4456,53 @@ EVENT gives the mouse position."
   (ivy-occur-press)
   (select-window (ivy--get-window ivy-occur-last)))
 
+(defun ivy--marked-p ()
+  (member (ivy-state-current ivy-last) ivy-marked-candidates))
+
+(defun ivy--unmark (cand)
+  (setcar (member cand ivy--all-candidates)
+          (setcar (member cand ivy--old-cands)
+                  (substring cand (length ivy-mark-prefix))))
+  (setq ivy-marked-candidates
+        (delete cand ivy-marked-candidates)))
+
+(defun ivy--mark (cand)
+  (let ((marked-cand (concat ivy-mark-prefix cand)))
+    (setcar (member cand ivy--all-candidates)
+            (setcar (member cand ivy--old-cands) marked-cand))
+    (setq ivy-marked-candidates
+          (append ivy-marked-candidates (list marked-cand)))))
+
+(defun ivy-mark ()
+  "Mark the selected candidate and move to the next one."
+  (interactive)
+  (unless (ivy--marked-p)
+    (ivy--mark (ivy-state-current ivy-last)))
+  (ivy-next-line))
+
+(defun ivy-unmark ()
+  "Unmark the selected candidate and move to the next one."
+  (interactive)
+  (when (ivy--marked-p)
+    (ivy--unmark (ivy-state-current ivy-last)))
+  (ivy-next-line))
+
+(defun ivy-unmark-backward ()
+  "Move to the previous candidate and unmark it."
+  (interactive)
+  (ivy-previous-line)
+  (ivy--exhibit)
+  (when (ivy--marked-p)
+    (ivy--unmark (ivy-state-current ivy-last))))
+
+(defun ivy-toggle-marks ()
+  "Toggle mark for all narrowed candidates."
+  (interactive)
+  (dolist (cand ivy--old-cands)
+    (if (member cand ivy-marked-candidates)
+        (ivy--unmark cand)
+      (ivy--mark cand))))
+
 (defconst ivy-help-file (let ((default-directory
                                (if load-file-name
                                    (file-name-directory load-file-name)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]