]> code.delx.au - gnu-emacs-elpa/blobdiff - ivy.el
ivy.el (ivy-alt-done): Refactor
[gnu-emacs-elpa] / ivy.el
diff --git a/ivy.el b/ivy.el
index 0f62ab986084cac1dca6c38a1ec7e0e82e76c49c..f70c54f19a4fadafb017c7a5684b639982b859a5 100644 (file)
--- a/ivy.el
+++ b/ivy.el
@@ -285,7 +285,7 @@ When non-nil, it should contain one %d.")
   "Quit the minibuffer and call ACTION afterwards."
   (ivy-set-action
    `(lambda (x)
-      (funcall ,action x)
+      (funcall ',action x)
       (ivy-set-action ',(ivy-state-action ivy-last))))
   (setq ivy-exit 'done)
   (exit-minibuffer))
@@ -393,29 +393,69 @@ When ARG is t, exit with current text, ignoring the candidates."
   (let (dir)
     (cond (arg
            (ivy-immediate-done))
-          ((and ivy--directory
-                (equal ivy-text "/sudo::"))
-           (setq dir (concat ivy-text ivy--directory))
-           (ivy--cd dir)
-           (ivy--exhibit))
-          ((and ivy--directory
-                (or
-                 (and
-                  (not (equal ivy-text ""))
-                  (ignore-errors
-                    (file-directory-p
-                     (setq dir
-                           (file-name-as-directory
-                            (expand-file-name
-                             ivy-text ivy--directory))))))
-                 (and
-                  (not (string= ivy--current "./"))
-                  (cl-plusp ivy--length)
+          (ivy--directory
+           (cond
+             ((equal ivy-text "/sudo::")
+              (setq dir (concat ivy-text ivy--directory))
+              (ivy--cd dir)
+              (ivy--exhibit))
+             ((or
+               (and
+                (not (equal ivy-text ""))
+                (ignore-errors
                   (file-directory-p
-                   (setq dir (expand-file-name
-                              ivy--current ivy--directory))))))
-           (ivy--cd dir)
-           (ivy--exhibit))
+                   (setq dir
+                         (file-name-as-directory
+                          (expand-file-name
+                           ivy-text ivy--directory))))))
+               (and
+                (not (string= ivy--current "./"))
+                (cl-plusp ivy--length)
+                (ignore-errors
+                  (file-directory-p
+                   (setq dir (file-name-as-directory
+                              (expand-file-name
+                               ivy--current ivy--directory)))))))
+              (ivy--cd dir)
+              (ivy--exhibit))
+             ((or (and (equal ivy--directory "/")
+                       (string-match "\\`[^/]+:.*:.*\\'" ivy-text))
+                  (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
+              (ivy-done))
+             ((or (and (equal ivy--directory "/")
+                       (cond ((string-match
+                               "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+                               ivy-text))
+                             ((string-match
+                               "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+                               ivy--current)
+                              (setq ivy-text ivy--current))))
+                  (string-match
+                   "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
+                   ivy-text))
+              (let ((method (match-string 1 ivy-text))
+                    (user (match-string 2 ivy-text))
+                    (rest (match-string 3 ivy-text))
+                    res)
+                (require 'tramp)
+                (dolist (x (tramp-get-completion-function method))
+                  (setq res (append res (funcall (car x) (cadr x)))))
+                (setq res (delq nil res))
+                (when user
+                  (dolist (x res)
+                    (setcar x user)))
+                (setq res (cl-delete-duplicates res :test #'equal))
+                (let* ((old-ivy-last ivy-last)
+                       (enable-recursive-minibuffers t)
+                       (host (ivy-read "Find File: "
+                                       (mapcar #'ivy-build-tramp-name res)
+                                       :initial-input rest)))
+                  (setq ivy-last old-ivy-last)
+                  (when host
+                    (setq ivy--directory "/")
+                    (ivy--cd (concat "/" method ":" host ":"))))))
+             (t
+              (ivy-done))))
           ((eq (ivy-state-collection ivy-last) 'Info-read-node-name-1)
            (if (or (equal ivy--current "(./)")
                    (equal ivy--current "(../)"))
@@ -426,34 +466,6 @@ When ARG is t, exit with current text, ignoring the candidates."
                                      (expand-file-name x ivy--directory)
                                      "Top"))))
              (ivy-done)))
-          ((and ivy--directory
-                (string-match "\\`/[^/]+:.*:.*\\'" ivy-text))
-           (ivy-done))
-          ((and ivy--directory
-                (string-match
-                 "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'"
-                 ivy-text))
-           (let ((method (match-string 1 ivy-text))
-                 (user (match-string 2 ivy-text))
-                 (rest (match-string 3 ivy-text))
-                 res)
-             (require 'tramp)
-             (dolist (x (tramp-get-completion-function method))
-               (setq res (append res (funcall (car x) (cadr x)))))
-             (setq res (delq nil res))
-             (when user
-               (dolist (x res)
-                 (setcar x user)))
-             (setq res (cl-delete-duplicates res :test #'equal))
-             (let* ((old-ivy-last ivy-last)
-                    (enable-recursive-minibuffers t)
-                    (host (ivy-read "Find File: "
-                                    (mapcar #'ivy-build-tramp-name res)
-                                    :initial-input rest)))
-               (setq ivy-last old-ivy-last)
-               (when host
-                 (setq ivy--directory "/")
-                 (ivy--cd (concat "/" method ":" host ":"))))))
           (t
            (ivy-done)))))
 
@@ -466,13 +478,16 @@ When ARG is t, exit with current text, ignoring the candidates."
 If the text hasn't changed as a result, forward to `ivy-alt-done'."
   (interactive)
   (if (and (eq (ivy-state-collection ivy-last) #'read-file-name-internal)
-           (string-match "\\`/" ivy-text))
+           (or (and (equal ivy--directory "/")
+                    (string-match "\\`[^/]+:.*\\'" ivy-text))
+               (string-match "\\`/" ivy-text)))
       (let ((default-directory ivy--directory))
         (minibuffer-complete)
         (setq ivy-text (ivy--input))
-        (when (and (file-directory-p ivy-text)
-                   (= ivy--length 1))
-          (ivy--cd (expand-file-name ivy-text))))
+        (when (file-directory-p
+               (expand-file-name ivy-text ivy--directory))
+          (ivy--cd (file-name-as-directory
+                    (expand-file-name ivy-text ivy--directory)))))
     (or (ivy-partial)
         (when (or (eq this-command last-command)
                   (eq ivy--length 1))
@@ -736,12 +751,9 @@ If so, move to that directory, while keeping only the file name."
     (let ((input (ivy--input))
           url)
       (if (setq url (ffap-url-p input))
-          (progn
-            (ivy-set-action
-             (lambda (_)
-               (funcall ffap-url-fetcher url)))
-            (setq ivy-exit 'done)
-            (exit-minibuffer))
+          (ivy-exit-with-action
+           (lambda (_)
+             (funcall ffap-url-fetcher url)))
         (setq input (expand-file-name input))
         (let ((file (file-name-nondirectory input))
               (dir (expand-file-name (file-name-directory input))))
@@ -1238,6 +1250,12 @@ DEF is the default value.
 _INHERIT-INPUT-METHOD is ignored for now.
 
 The history, defaults and input-method arguments are ignored for now."
+  ;; See the doc of `completing-read'.
+  (when (consp history)
+    (when (numberp (cdr history))
+      (setq initial-input (nth (1- (cdr history))
+                               (symbol-value (car history)))))
+    (setq history (car history)))
   (ivy-read (replace-regexp-in-string "%" "%%" prompt)
             collection
             :predicate predicate
@@ -1293,13 +1311,15 @@ When MATCHER is non-nil it's used instead of `cl-remove-if-not'."
                  candidates))))
     (when matcher
       (setq candidates (funcall matcher "" candidates))))
-  (or (cl-position preselect candidates :test #'equal)
-      (and (stringp preselect)
-           (let ((re (regexp-quote preselect)))
-             (cl-position-if
-              (lambda (x)
-                (string-match re x))
-              candidates)))))
+  (cond ((integerp preselect)
+         preselect)
+        ((cl-position preselect candidates :test #'equal))
+        ((stringp preselect)
+         (let ((re (regexp-quote preselect)))
+           (cl-position-if
+            (lambda (x)
+              (string-match re x))
+            candidates)))))
 
 ;;* Implementation
 ;;** Regex
@@ -1726,6 +1746,15 @@ not matched collection functions.
 The alist VAL is a sorting function with the signature of
 `ivy--prefix-sort'.")
 
+(defun ivy--sort-files-by-date (_name candidates)
+  "Re-soft CANDIDATES according to file modification date."
+  (let ((default-directory ivy--directory))
+    (cl-sort (copy-sequence candidates)
+             (lambda (f1 f2)
+               (time-less-p
+                (nth 5 (file-attributes f2))
+                (nth 5 (file-attributes f1)))))))
+
 (defun ivy--sort (name candidates)
   "Re-sort CANDIDATES according to NAME.
 All CANDIDATES are assumed to match NAME."
@@ -1838,6 +1867,13 @@ Prefix matches to NAME are put ahead of the list."
   "Function to transform the list of candidates into a string.
 This string will be inserted into the minibuffer.")
 
+(defun ivy--truncate-string (str width)
+  "Truncate STR to WIDTH."
+  (if (> (string-width str) width)
+      (concat (substring str 0 (min (- width 3)
+                                    (- (length str) 3))) "...")
+    str))
+
 (defun ivy-format-function-default (cands)
   "Transform CANDS into a string for minibuffer."
   (if (bound-and-true-p truncate-lines)
@@ -1847,9 +1883,7 @@ This string will be inserted into the minibuffer.")
       (mapconcat
        (if truncate-lines
            (lambda (s)
-             (if (> (length s) ww)
-                 (concat (substring s 0 (- ww 3)) "...")
-               s))
+             (ivy--truncate-string s ww))
          #'identity)
        cands "\n"))))