diff -Nru emacs-ivy-0.12.0+dfsg/counsel.el emacs-ivy-0.13.0/counsel.el --- emacs-ivy-0.12.0+dfsg/counsel.el 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/counsel.el 2019-10-16 16:57:42.000000000 +0000 @@ -4,8 +4,8 @@ ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/swiper -;; Version: 0.12.0 -;; Package-Requires: ((emacs "24.3") (swiper "0.12.0")) +;; Version: 0.13.0 +;; Package-Requires: ((emacs "24.5") (swiper "0.13.0")) ;; Keywords: convenience, matching, tools ;; This file is part of GNU Emacs. @@ -30,11 +30,11 @@ ;; ;; Currently available: ;; - Symbol completion for Elisp, Common Lisp, Python, Clojure, C, C++. -;; - Describe fuctions for Elisp: function, variable, library, command, +;; - Describe functions for Elisp: function, variable, library, command, ;; bindings, theme. ;; - Navigation functions: imenu, ace-line, semantic, outline. ;; - Git utilities: git-files, git-grep, git-log, git-stash, git-checkout. -;; - Grep utitilies: grep, ag, pt, recoll, ack, rg. +;; - Grep utilities: grep, ag, pt, recoll, ack, rg. ;; - System utilities: process list, rhythmbox, linux-app. ;; - Many more. @@ -50,10 +50,6 @@ :prefix "counsel-") ;;* Utility -(define-obsolete-variable-alias 'counsel-more-chars-alist 'ivy-more-chars-alist "0.10.0") - -(define-obsolete-function-alias 'counsel-more-chars 'ivy-more-chars "0.10.0") - (defun counsel--elisp-to-pcre (regex &optional look-around) "Convert REGEX from Elisp format to PCRE format, on best-effort basis. REGEX may be of any format returned by an Ivy regex function, @@ -115,7 +111,7 @@ str)) (defun counsel-require-program (cmd) - "Check system for program used in CMD, printing error if unfound. + "Check system for program used in CMD, printing error if not found. CMD is either a string or a list of strings. To skip the `executable-find' check, start the string with a space." (unless (and (stringp cmd) (string-match-p "^ " cmd)) @@ -127,11 +123,6 @@ (executable-find program)) (user-error "Required program \"%s\" not found in your path" program))))) -(defun counsel-prompt-function-default () - "Return prompt appended with a semicolon." - (declare (obsolete ivy-set-prompt "0.10.0")) - (ivy-add-prompt-count (concat (ivy-state-prompt ivy-last) ": "))) - (declare-function eshell-split-path "esh-util") (defun counsel-prompt-function-dir () @@ -162,6 +153,9 @@ This plist maps commands to a plist mapping their exit codes to descriptions.") +(defvar counsel--async-last-error-string nil + "When the process returned non-0, store the output here.") + (defun counsel-set-async-exit-code (cmd number str) "For CMD, associate NUMBER exit code with STR." (let ((plist (plist-get counsel--async-exit-code-plist cmd))) @@ -170,21 +164,15 @@ cmd (plist-put plist number str))))) -(defvar counsel-async-split-string-re "\n" - "Store the regexp for splitting shell command output.") -(make-obsolete-variable - 'counsel-async-split-string-re 'counsel-async-split-string-re-alist "<2019-07-16 Tue>") - (defvar counsel-async-split-string-re-alist '((t . "\n")) "Store the regexp for splitting shell command output.") -(defvar counsel-async-ignore-re nil - "Regexp matching candidates to ignore in `counsel--async-filter'.") -(make-obsolete-variable 'counsel-async-ignore-re 'counsel-async-ignore-re-alist "<2019-07-16 Tue>") - (defvar counsel-async-ignore-re-alist nil "An alist of regexp matching candidates to ignore in `counsel--async-filter'.") +(defvar counsel--async-last-command nil + "Store the last command ran by `counsel--async-command'.") + (defun counsel--async-command (cmd &optional sentinel filter name) "Start and return new counsel process by calling CMD. CMD can be either a shell command as a string, or a list of the @@ -198,6 +186,7 @@ (setq name (or name " *counsel*")) (when (get-buffer name) (kill-buffer name)) + (setq counsel--async-last-command cmd) (let* ((buf (get-buffer-create name)) (proc (if (listp cmd) (apply #'start-file-process name buf cmd) @@ -208,8 +197,6 @@ (set-process-filter proc (or filter #'counsel--async-filter)) proc)) -(defvar counsel-grep-last-line nil) - (defun counsel--split-string (&optional str) (split-string (or str (buffer-string)) @@ -225,7 +212,6 @@ (ivy--sort-maybe (with-current-buffer (process-buffer process) (counsel--split-string)))) - (setq counsel-grep-last-line nil) (when counsel--async-start (setq counsel--async-duration (time-to-seconds (time-since counsel--async-start)))) @@ -243,6 +229,8 @@ (if ivy--all-candidates (ivy--exhibit) (ivy--insert-minibuffer ""))) + (setq counsel--async-last-error-string + (with-current-buffer (process-buffer process) (buffer-string))) (setq ivy--all-candidates (let ((status (process-exit-status process)) (plist (plist-get counsel--async-exit-code-plist @@ -307,16 +295,16 @@ (if (string= str "") (mapatoms (lambda (x) - (when (symbolp x) + (when (and (symbolp x) (funcall pred x)) (push (symbol-name x) symbol-names)))) (setq symbol-names (all-completions str obarray pred))) (ivy-read "Symbol name: " symbol-names - :caller 'counsel-el - :predicate pred :initial-input str - :action #'ivy-completion-in-region-action))) + :action #'ivy-completion-in-region-action + :caller 'counsel-el))) -(add-to-list 'ivy-height-alist '(counsel-el . 7)) +(ivy-configure 'counsel-el + :height 7) ;;** `counsel-cl' (declare-function slime-symbol-start-pos "ext:slime") @@ -362,11 +350,7 @@ ivy-completion-end)) (setq ivy-completion-beg (point)) (insert symbol-name) - (setq ivy-completion-end (point)) - (when (equal (get-text-property 0 'symbol symbol-name) "f") - (insert "()") - (setq ivy-completion-end (point)) - (backward-char))))) + (setq ivy-completion-end (point))))) ;;** `counsel-clj' (declare-function cider-sync-request:complete "ext:cider-client") @@ -385,7 +369,8 @@ (delete-region (car bnd) (cdr bnd))) (insert res)))) -(add-to-list 'ivy-height-alist '(counsel--generic . 7)) +(ivy-configure 'counsel--generic + :height 7) ;;;###autoload (defun counsel-clj () @@ -421,9 +406,11 @@ (setq ivy-completion-end (point)) (ivy-read "Candidate: " company-candidates :action #'ivy-completion-in-region-action - :unwind #'company-abort :caller 'counsel-company)))) +(ivy-configure 'counsel-company + :unwind-fn #'company-abort) + ;;** `counsel-irony' (declare-function irony-completion-candidates-async "ext:irony-completion") (declare-function irony-completion-symbol-bounds "ext:irony-completion") @@ -479,6 +466,7 @@ "Jump to the definition of the current symbol." (interactive) (ivy-exit-with-action #'counsel--find-symbol)) +(put 'counsel-find-symbol 'no-counsel-M-x t) (defun counsel--info-lookup-symbol () "Lookup the current symbol in the info docs." @@ -521,9 +509,6 @@ (error "Couldn't find definition of %s" sym)))))))) -(define-obsolete-function-alias 'counsel-symbol-at-point - 'ivy-thing-at-point "0.7.0") - (defun counsel--variable-p (symbol) "Return non-nil if SYMBOL is a bound or documented variable." (or (and (boundp symbol) @@ -540,9 +525,6 @@ (ivy-append-face var 'ivy-highlight-face) var)) -(ivy-set-display-transformer - 'counsel-describe-variable 'counsel-describe-variable-transformer) - ;;;###autoload (defun counsel-describe-variable () "Forward to `describe-variable'. @@ -557,11 +539,15 @@ :history 'counsel-describe-symbol-history :keymap counsel-describe-map :preselect (ivy-thing-at-point) - :sort t :action (lambda (x) (funcall counsel-describe-variable-function (intern x))) :caller 'counsel-describe-variable))) +(ivy-configure 'counsel-describe-variable + :initial-input "^" + :display-transformer-fn #'counsel-describe-variable-transformer + :sort-fn #'ivy-string<) + ;;** `counsel-describe-function' (ivy-set-actions 'counsel-describe-function @@ -578,9 +564,6 @@ (ivy-append-face function-name 'ivy-highlight-face) function-name)) -(ivy-set-display-transformer - 'counsel-describe-function 'counsel-describe-function-transformer) - (defun ivy-function-called-at-point () (let ((f (function-called-at-point))) (and f (symbol-name f)))) @@ -607,11 +590,15 @@ :history 'counsel-describe-symbol-history :keymap counsel-describe-map :preselect (funcall counsel-describe-function-preselect) - :sort t :action (lambda (x) (funcall counsel-describe-function-function (intern x))) :caller 'counsel-describe-function))) +(ivy-configure 'counsel-describe-function + :initial-input "^" + :display-transformer-fn #'counsel-describe-function-transformer + :sort-fn #'ivy-string<) + ;;** `counsel-set-variable' (defvar counsel-set-variable-history nil "Store history for `counsel-set-variable'.") @@ -739,7 +726,6 @@ (symbol-plist sym))) :history 'counsel-apropos-history :preselect (ivy-thing-at-point) - :sort t :action (lambda (pattern) (when (string= pattern "") (user-error "Please specify a pattern")) @@ -754,6 +740,9 @@ (apropos (concat "\\`" pattern "\\'")))) :caller 'counsel-apropos)) +(ivy-configure 'counsel-apropos + :sort-fn #'ivy-string<) + ;;** `counsel-info-lookup-symbol' (defvar info-lookup-mode) (declare-function info-lookup-guess-default "info-look") @@ -782,17 +771,24 @@ (list (ivy-read "Describe symbol: " (info-lookup->completions topic mode) :history 'info-lookup-history :preselect (info-lookup-guess-default topic mode) - :sort t :caller 'counsel-info-lookup-symbol) mode)))) (info-lookup-symbol symbol mode)) +(ivy-configure 'counsel-info-lookup-symbol + :sort-fn #'ivy-string<) + ;;** `counsel-M-x' (defface counsel-key-binding '((t :inherit font-lock-keyword-face)) "Face used by `counsel-M-x' for key bindings." :group 'ivy-faces) +(defface counsel-active-mode + '((t :inherit font-lock-builtin-face)) + "Face used by `counsel-M-x' for activated modes." + :group 'ivy-faces) + (defcustom counsel-alias-expand t "When non-nil, show the expansion of aliases in `counsel-M-x'." :type 'boolean @@ -800,8 +796,15 @@ (defun counsel-M-x-transformer (cmd) "Return CMD annotated with its active key binding, if any." - (let ((alias (symbol-function (intern cmd))) - (key (where-is-internal (intern cmd) nil t))) + (let* ((sym (intern cmd)) + (alias (symbol-function sym)) + (key (where-is-internal sym nil t))) + (when (or (eq sym major-mode) + (and + (memq sym minor-mode-list) + (boundp sym) + (buffer-local-value sym (ivy-state-buffer ivy-last)))) + (setq cmd (propertize cmd 'face 'counsel-active-mode))) (concat cmd (when (and (symbolp alias) counsel-alias-expand) (format " (%s)" alias)) @@ -867,6 +870,18 @@ (defvar counsel-M-x-history nil "History for `counsel-M-x'.") +(defun counsel-M-x-action (cmd) + "Execute CMD." + (setq cmd (intern cmd)) + (cond ((bound-and-true-p amx-initialized) + (amx-rank cmd)) + ((bound-and-true-p smex-initialized-p) + (smex-rank cmd))) + (setq prefix-arg current-prefix-arg) + (setq this-command cmd) + (setq real-this-command cmd) + (command-execute cmd 'record)) + ;;;###autoload (defun counsel-M-x (&optional initial-input) "Ivy version of `execute-extended-command'. @@ -881,35 +896,28 @@ (setq real-this-command real-last-command) (let ((externs (counsel--M-x-externs))) (ivy-read (counsel--M-x-prompt) (or externs obarray) - :predicate (and (not externs) - (lambda (sym) - (and (commandp sym) - (not (get sym 'byte-obsolete-info))))) + :predicate (if externs + (lambda (x) + (not (get (intern x) 'no-counsel-M-x))) + (lambda (sym) + (and (commandp sym) + (not (get sym 'byte-obsolete-info)) + (not (get sym 'no-counsel-M-x))))) :require-match t :history 'counsel-M-x-history - :action (lambda (cmd) - (setq cmd (intern cmd)) - (cond ((bound-and-true-p amx-initialized) - (amx-rank cmd)) - ((bound-and-true-p smex-initialized-p) - (smex-rank cmd))) - (setq prefix-arg current-prefix-arg) - (setq this-command cmd) - (setq real-this-command cmd) - (command-execute cmd 'record)) - :sort (not externs) + :action #'counsel-M-x-action :keymap counsel-describe-map :initial-input initial-input :caller 'counsel-M-x))) +(ivy-configure 'counsel-M-x + :initial-input "^" + :display-transformer-fn #'counsel-M-x-transformer) + (ivy-set-actions 'counsel-M-x `(("d" counsel--find-symbol "definition") - ("h" ,(lambda (x) (describe-function (intern x))) "help"))) - -(ivy-set-display-transformer - 'counsel-M-x - 'counsel-M-x-transformer) + ("h" ,(lambda (x) (funcall counsel-describe-function-function (intern x))) "help"))) ;;** `counsel-command-history' (defun counsel-command-history-action-eval (cmd) @@ -1151,10 +1159,12 @@ :require-match t :history 'face-name-history :preselect (counsel--face-at-point) - :sort t :action counsel-describe-face-function :caller 'counsel-describe-face)) +(ivy-configure 'counsel-describe-face + :sort-fn #'ivy-string<) + (defun counsel-customize-face (name) "Customize face with NAME." (customize-face (intern name))) @@ -1172,8 +1182,7 @@ (defvar counsel--faces-format "%-40s %s") (defun counsel--faces-format-function (names) - "Customize `ivy-format-functions-alist' for `counsel-faces'. -Each candidate is formatted based on the given FORMAT string." + "Format NAMES according to `counsel--faces-format'." (let ((formatter (lambda (name) (format counsel--faces-format name @@ -1198,11 +1207,12 @@ :require-match t :history 'face-name-history :preselect (counsel--face-at-point) - :sort t :action counsel-describe-face-function :caller 'counsel-faces))) -(add-to-list 'ivy-format-functions-alist '(counsel-faces . counsel--faces-format-function)) +(ivy-configure 'counsel-faces + :sort-fn #'ivy-string< + :format-fn #'counsel--faces-format-function) (ivy-set-actions 'counsel-faces @@ -1250,13 +1260,16 @@ :action #'counsel-git-action :caller 'counsel-git))) +(ivy-configure 'counsel-git + :occur #'counsel-git-occur) + (defun counsel-git-action (x) "Find file X in current Git repository." (with-ivy-window (let ((default-directory (ivy-state-directory ivy-last))) (find-file x)))) -(defun counsel-git-occur () +(defun counsel-git-occur (&optional _cands) "Occur function for `counsel-git' using `counsel-cmd-to-dired'." (cd (ivy-state-directory ivy-last)) (counsel-cmd-to-dired @@ -1294,19 +1307,15 @@ (forward-line 2) (dired-move-to-filename))))))) -(ivy-set-occur 'counsel-git 'counsel-git-occur) - ;;** `counsel-git-grep' (defvar counsel-git-grep-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-l") 'ivy-call-and-recenter) (define-key map (kbd "M-q") 'counsel-git-grep-query-replace) (define-key map (kbd "C-c C-m") 'counsel-git-grep-switch-cmd) + (define-key map (kbd "C-x C-d") 'counsel-cd) map)) -(ivy-set-occur 'counsel-git-grep 'counsel-git-grep-occur) -(ivy-set-display-transformer 'counsel-git-grep 'counsel-git-grep-transformer) - (defvar counsel-git-grep-cmd-default "git --no-pager grep --full-name -n --no-color -i -I -e \"%s\"" "Initial command for `counsel-git-grep'.") @@ -1334,7 +1343,11 @@ (defun counsel-git-grep-cmd-function-default (str) (format counsel-git-grep-cmd - (setq ivy--old-re (ivy--regex str t)))) + (setq ivy--old-re + (if (eq ivy--regex-function #'ivy--regex-fuzzy) + (replace-regexp-in-string + "\n" "" (ivy--regex-fuzzy str)) + (ivy--regex str t))))) (defun counsel-git-grep-cmd-function-ignore-order (str) (setq ivy--old-re (ivy--regex str t)) @@ -1362,7 +1375,9 @@ (ivy-state-directory ivy-last))) (goto-char (point-min)) (forward-line (1- (string-to-number line-number))) - (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) + (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) + (when swiper-goto-start-of-match + (goto-char (match-beginning 0)))) (swiper--ensure-visible) (run-hooks 'counsel-grep-post-action-hook) (unless (eq ivy-exit 'done) @@ -1390,7 +1405,7 @@ proj) (cond ((stringp cmd)) - (cmd + (current-prefix-arg (if (setq proj (cl-find-if (lambda (x) @@ -1407,13 +1422,12 @@ (setq cmd counsel-git-grep-cmd-default))) (cons proj cmd))) -(define-obsolete-function-alias 'counsel--call 'counsel--command "0.11.0") - -(defun counsel--command (&rest command) +(defun counsel--call (command &optional result-fn) "Synchronously call COMMAND and return its output as a string. COMMAND comprises the program name followed by its arguments, as in `make-process'. Signal `file-error' and emit a warning if -COMMAND fails. Obey file handlers based on `default-directory'." +COMMAND fails. Obey file handlers based on `default-directory'. +On success, RESULT-FN is called in output buffer with no arguments." (let ((stderr (make-temp-file "counsel-call-stderr-")) status) (unwind-protect @@ -1421,12 +1435,14 @@ (setq status (apply #'process-file (car command) nil (list t stderr) nil (cdr command))) (if (eq status 0) - ;; Return all output except trailing newline. - (buffer-substring (point-min) - (- (point) - (if (eq (bobp) (bolp)) - 0 - 1))) + (if result-fn + (funcall result-fn) + ;; Return all output except trailing newline. + (buffer-substring (point-min) + (- (point) + (if (eq (bobp) (bolp)) + 0 + 1)))) ;; Convert process status into error list. (setq status (list 'file-error (mapconcat #'identity `(,@command "failed") " ") @@ -1444,13 +1460,22 @@ (signal (car status) (cdr status)))) (delete-file stderr)))) +(defun counsel--command (&rest command) + "Forward COMMAND to `counsel--call'." + (counsel--call command)) + +(defun counsel--grep-unwind () + (counsel-delete-process) + (swiper--cleanup)) + ;;;###autoload -(defun counsel-git-grep (&optional cmd initial-input) +(defun counsel-git-grep (&optional initial-input initial-directory cmd) "Grep for a string in the current Git repository. +INITIAL-INPUT can be given as the initial minibuffer input. +INITIAL-DIRECTORY, if non-nil, is used as the root directory for search. When CMD is a string, use it as a \"git grep\" command. -When CMD is non-nil, prompt for a specific \"git grep\" command. -INITIAL-INPUT can be given as the initial minibuffer input." - (interactive "P") +When CMD is non-nil, prompt for a specific \"git grep\" command." + (interactive) (let ((proj-and-cmd (counsel--git-grep-cmd-and-proj cmd)) proj) (setq proj (car proj-and-cmd)) @@ -1460,22 +1485,25 @@ (if proj #'counsel-git-grep-proj-function #'counsel-git-grep-function)) - (unwind-function - (lambda () - (counsel-delete-process) - (swiper--cleanup))) - (default-directory (if proj - (car proj) - (counsel-locate-git-root)))) + (default-directory (or initial-directory + (if proj + (car proj) + (counsel-locate-git-root))))) (ivy-read "git grep: " collection-function :initial-input initial-input :dynamic-collection t :keymap counsel-git-grep-map :action #'counsel-git-grep-action - :unwind unwind-function :history 'counsel-git-grep-history :caller 'counsel-git-grep)))) -(cl-pushnew 'counsel-git-grep ivy-highlight-grep-commands) + +(ivy-configure 'counsel-git-grep + :occur #'counsel-git-grep-occur + :unwind-fn #'counsel--grep-unwind + :index-fn #'ivy-recompute-index-swiper-async + :display-transformer-fn #'counsel-git-grep-transformer + :grep-p t + :exit-codes '(1 "No matches found")) (defun counsel-git-grep-proj-function (str) "Grep for STR in the current Git repository." @@ -1510,16 +1538,11 @@ (setq str (replace-match "" t t str 1)))) str) -(defun counsel-git-grep-occur () - "Generate a custom occur buffer for `counsel-git-grep'. -When REVERT is non-nil, regenerate the current *ivy-occur* buffer." - (unless (eq major-mode 'ivy-occur-grep-mode) - (ivy-occur-grep-mode) - (setq default-directory (ivy-state-directory ivy-last))) - (setq ivy-text - (and (string-match "\"\\(.*\\)\"" (buffer-name)) - (match-string 1 (buffer-name)))) - (let* ((regex (funcall ivy--regex-function ivy-text)) +(defun counsel--git-grep-occur-cmd (input) + (let* ((regex (funcall ivy--regex-function input)) + (regex (if (eq ivy--regex-function #'ivy--regex-fuzzy) + (replace-regexp-in-string "\n" "" regex) + regex)) (positive-pattern (replace-regexp-in-string ;; git-grep can't handle .*? "\\.\\*\\?" ".*" @@ -1530,16 +1553,12 @@ (and (null (cdr x)) (format "| grep -v %s" (car x)))) regex - " "))) - (cmd (concat (format counsel-git-grep-cmd positive-pattern) negative-patterns)) - cands) - (setq cands (counsel--split-string (shell-command-to-string cmd))) - ;; Need precise number of header lines for `wgrep' to work. - (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n" - default-directory)) - (insert (format "%d candidates:\n" (length cands))) - (ivy--occur-insert-lines - (mapcar #'counsel--normalize-grep-match cands)))) + " ")))) + (concat (format counsel-git-grep-cmd positive-pattern) negative-patterns))) + +(defun counsel-git-grep-occur (&optional _cands) + "Generate a custom occur buffer for `counsel-git-grep'." + (counsel-grep-like-occur #'counsel--git-grep-occur-cmd)) (defun counsel-git-grep-query-replace () "Start `query-replace' with string to replace from last search string." @@ -1591,11 +1610,6 @@ (defvar counsel-git-log-cmd "GIT_PAGER=cat git log --grep '%s'" "Command used for \"git log\".") -(defvar counsel-git-log-split-string-re "^commit " - "The `split-string' separates when split output of `counsel-git-log-cmd'.") -(make-obsolete-variable - 'counsel-git-log-split-string-re 'counsel-async-split-string-re-alist "<2019-07-16 Tue>") - (defun counsel-git-log-function (str) "Search for STR in git log." (or @@ -1718,11 +1732,13 @@ (ivy-read "Grep log: " #'counsel-git-log-function :dynamic-collection t :action #'counsel-git-log-action - :unwind #'counsel-delete-process :caller 'counsel-git-log)) -(add-to-list 'ivy-format-functions-alist '(counsel-git-log . counsel--git-log-format-function)) -(add-to-list 'ivy-height-alist '(counsel-git-log . 4)) +(ivy-configure 'counsel-git-log + :height 4 + :unwind-fn #'counsel-delete-process + :format-fn #'counsel--git-log-format-function) + (add-to-list 'counsel-async-split-string-re-alist '(counsel-git-log . "^commit ")) (add-to-list 'counsel-async-ignore-re-alist '(counsel-git-log . "^[ \n]*$")) @@ -1735,9 +1751,6 @@ (define-key map (kbd "`") (ivy-make-magic-action 'counsel-find-file "b")) map)) -(define-obsolete-function-alias 'counsel-yank-directory 'ivy-insert-current-full - "<2019-06-13 Thu>") - (when (executable-find "git") (add-to-list 'ivy-ffap-url-functions 'counsel-github-url-p) (add-to-list 'ivy-ffap-url-functions 'counsel-emacs-url-p)) @@ -1819,12 +1832,12 @@ 'counsel-find-file-move)) (defun counsel-find-file-mkdir-action (_x) - "Create a directory from `ivy-text'." + "Create a directory and any nonexistent parent dirs from `ivy-text'." (let ((dir (file-name-as-directory (expand-file-name ivy-text ivy--directory))) (win (and (not (eq ivy-exit 'done)) (active-minibuffer-window)))) - (make-directory dir) + (make-directory dir t) (when win (with-selected-window win (ivy--cd dir))))) (ivy-set-actions @@ -1834,6 +1847,7 @@ ("b" counsel-find-file-cd-bookmark-action "cd bookmark") ("x" counsel-find-file-extern "open externally") ("r" counsel-find-file-as-root "open as root") + ("R" find-file-read-only "read only") ("k" counsel-find-file-delete "delete") ("c" counsel-find-file-copy "copy file") ("m" counsel-find-file-move "move or rename") @@ -1866,6 +1880,9 @@ ,(regexp-opt completion-ignored-extensions)) (regexp :tag "Regex"))) +(defvar counsel--find-file-predicate nil + "When non-nil, `counsel--find-file-matcher' will use this predicate.") + (defun counsel--find-file-matcher (regexp candidates) "Return REGEXP matching CANDIDATES. Skip some dotfiles unless `ivy-text' requires them." @@ -1875,6 +1892,9 @@ (lambda (re-str) (lambda (x) (string-match re-str (directory-file-name x))))))) + (when counsel--find-file-predicate + (let ((default-directory ivy--directory)) + (setq res (cl-remove-if-not counsel--find-file-predicate res)))) (if (or (null ivy-use-ignore) (null counsel-find-file-ignore-regexp) (string-match-p "\\`\\." ivy-text)) @@ -1910,7 +1930,7 @@ (defun counsel--preselect-file () "Return candidate to preselect during filename completion. -The preselect behaviour can be customized via user options +The preselect behavior can be customized via user options `counsel-find-file-at-point' and `counsel-preselect-current-file', which see." (or @@ -1923,15 +1943,19 @@ (file-name-nondirectory buffer-file-name)))) (defun counsel--find-file-1 (prompt initial-input action caller) - (ivy-read prompt #'read-file-name-internal - :matcher #'counsel--find-file-matcher - :initial-input initial-input - :action action - :preselect (counsel--preselect-file) - :require-match 'confirm-after-completion - :history 'file-name-history - :keymap counsel-find-file-map - :caller caller)) + (let ((default-directory + (if (eq major-mode 'dired-mode) + (dired-current-directory) + default-directory))) + (ivy-read prompt #'read-file-name-internal + :matcher #'counsel--find-file-matcher + :initial-input initial-input + :action action + :preselect (counsel--preselect-file) + :require-match 'confirm-after-completion + :history 'file-name-history + :keymap counsel-find-file-map + :caller caller))) ;;;###autoload (defun counsel-find-file (&optional initial-input) @@ -1943,7 +1967,9 @@ #'counsel-find-file-action 'counsel-find-file)) -(ivy-set-occur 'counsel-find-file 'counsel-find-file-occur) +(ivy-configure 'counsel-find-file + :occur #'counsel-find-file-occur + :display-transformer-fn #'ivy-read-file-transformer) (defvar counsel-find-file-occur-cmd "ls -a | %s | xargs -d '\\n' ls -d --group-directories-first" "Format string for `counsel-find-file-occur'.") @@ -1970,29 +1996,31 @@ "Return a command that filters a file list to match ivy candidates. If USE-IGNORE is non-nil, try to generate a command that respects `counsel-find-file-ignore-regexp'." - (let ((regex ivy--old-re) - (filter-cmd (cl-find-if - (lambda (x) - (executable-find - (car (split-string (car x))))) - counsel-file-name-filter-alist)) - cmd) - (when (and use-ignore ivy-use-ignore - counsel-find-file-ignore-regexp - (cdr filter-cmd) - (not (string-match-p "\\`\\." ivy-text)) - (not (string-match-p counsel-find-file-ignore-regexp - (or (car ivy--old-cands) "")))) - (let ((ignore-re (list (counsel--elisp-to-pcre - counsel-find-file-ignore-regexp)))) - (setq regex (if (stringp regex) - (list ignore-re (cons regex t)) - (cons ignore-re regex))))) - (setq cmd (format (car filter-cmd) - (counsel--elisp-to-pcre regex (cdr filter-cmd)))) - (if (string-match-p "csh\\'" shell-file-name) - (replace-regexp-in-string "\\?!" "?\\\\!" cmd) - cmd))) + (let ((regex ivy--old-re)) + (if (= 0 (length regex)) + "cat" + (let ((filter-cmd (cl-find-if + (lambda (x) + (executable-find + (car (split-string (car x))))) + counsel-file-name-filter-alist)) + cmd) + (when (and use-ignore ivy-use-ignore + counsel-find-file-ignore-regexp + (cdr filter-cmd) + (not (string-match-p "\\`\\." ivy-text)) + (not (string-match-p counsel-find-file-ignore-regexp + (or (car ivy--old-cands) "")))) + (let ((ignore-re (list (counsel--elisp-to-pcre + counsel-find-file-ignore-regexp)))) + (setq regex (if (stringp regex) + (list ignore-re (cons regex t)) + (cons ignore-re regex))))) + (setq cmd (format (car filter-cmd) + (counsel--elisp-to-pcre regex (cdr filter-cmd)))) + (if (string-match-p "csh\\'" shell-file-name) + (replace-regexp-in-string "\\?!" "?\\\\!" cmd) + cmd))))) (defun counsel--occur-cmd-find () (let ((cmd (format @@ -2012,7 +2040,7 @@ " | grep" (concat " -type " type exclude-dots " | grep") cmd))) -(defun counsel-find-file-occur () +(defun counsel-find-file-occur (&optional _cands) (require 'find-dired) (cd ivy--directory) (if counsel-find-file-occur-use-find @@ -2074,7 +2102,7 @@ "When point is at an issue in a Git-versioned file, return the issue string." (and (looking-at "#[0-9]+") (or (eq (vc-backend buffer-file-name) 'Git) - (eq major-mode 'magit-commit-mode) + (memq major-mode '(magit-commit-mode vc-git-log-view-mode)) (bound-and-true-p magit-commit-mode)) (match-string-no-properties 0))) @@ -2161,10 +2189,14 @@ "Forward to `dired'. When INITIAL-INPUT is non-nil, use it in the minibuffer during completion." (interactive) - (counsel--find-file-1 - "Dired (directory): " initial-input - (lambda (d) (dired (expand-file-name d))) - 'counsel-dired)) + (let ((counsel--find-file-predicate #'file-directory-p)) + (counsel--find-file-1 + "Dired (directory): " initial-input + (lambda (d) (dired (expand-file-name d))) + 'counsel-dired))) + +(ivy-configure 'counsel-dired + :display-transformer-fn #'ivy-read-file-transformer) ;;** `counsel-recentf' (defvar recentf-list) @@ -2188,6 +2220,49 @@ ("f" find-file-other-frame "other frame") ("x" counsel-find-file-extern "open externally"))) +(defun counsel-buffer-or-recentf-candidates () + "Return candidates for `counsel-buffer-or-recentf'." + (require 'recentf) + (recentf-mode) + (let ((buffers + (delq nil + (mapcar (lambda (b) + (when (buffer-file-name b) + (buffer-file-name b))) + (buffer-list))))) + (append + buffers + (cl-remove-if (lambda (f) (member f buffers)) + (mapcar #'substring-no-properties recentf-list))))) + +;;;###autoload +(defun counsel-buffer-or-recentf () + "Find a buffer visiting a file or file on `recentf-list'." + (interactive) + (ivy-read "Buffer File or Recentf: " (counsel-buffer-or-recentf-candidates) + :action (lambda (s) + (with-ivy-window + (if (bufferp s) + (switch-to-buffer s) + (find-file s)))) + :require-match t + :caller 'counsel-buffer-or-recentf)) + +(ivy-configure 'counsel-buffer-or-recentf + :display-transformer-fn #'counsel-buffer-or-recentf-transformer) + +(ivy-set-actions + 'counsel-buffer-or-recentf + '(("j" find-file-other-window "other window") + ("f" find-file-other-frame "other frame") + ("x" counsel-find-file-extern "open externally"))) + +(defun counsel-buffer-or-recentf-transformer (var) + "Propertize VAR if it's a buffer visiting a file." + (if (member var (mapcar #'buffer-file-name (buffer-list))) + (ivy-append-face var 'ivy-highlight-face) + var)) + ;;** `counsel-bookmark' (defcustom counsel-bookmark-avoid-dired nil "If non-nil, open directory bookmarks with `counsel-find-file'. @@ -2223,7 +2298,7 @@ :caller 'counsel-bookmark)) (defun counsel--apply-bookmark-fn (fn) - "Return a function applyinig FN to a bookmark's location." + "Return a function applying FN to a bookmark's location." (lambda (bookmark) (funcall fn (bookmark-location bookmark)))) @@ -2279,7 +2354,7 @@ (interactive) (ivy-read "File Register: " ;; Use the `register-alist' variable to filter out file - ;; registers. Each entry for a file registar will have the + ;; registers. Each entry for a file register will have the ;; following layout: ;; ;; (NUMBER 'file . "string/path/to/file") @@ -2291,13 +2366,15 @@ (if (eq 'file (cadr register-alist-entry)) (cddr register-alist-entry))) register-alist) - :sort t :require-match t :history 'counsel-file-register :caller 'counsel-file-register :action (lambda (register-file) (with-ivy-window (find-file register-file))))) +(ivy-configure 'counsel-file-register + :sort-fn #'ivy-string<) + (ivy-set-actions 'counsel-file-register '(("j" find-file-other-window "other window"))) @@ -2326,8 +2403,6 @@ ("r" counsel-find-file-as-root "open as root") ("d" counsel-locate-action-dired "dired"))) -(counsel-set-async-exit-code 'counsel-locate 1 "Nothing found") - (defvar counsel-locate-history nil "History for `counsel-locate'.") @@ -2371,12 +2446,22 @@ (counsel-require-program "mdfind") (format "mdfind -name '%s'" input)) +(defvar w32-ansi-code-page) + (defun counsel-locate-cmd-es (input) "Return a shell command based on INPUT." (counsel-require-program "es.exe") - (format "es.exe -i -r -p %s" - (counsel--elisp-to-pcre - (ivy--regex input t)))) + (let ((raw-string (format "es.exe -i -r -p %s" + (counsel--elisp-to-pcre + (ivy--regex input t))))) + ;; W32 don't use Unicode by default, so we encode search command + ;; to local codepage to support searching filename contains non-ASCII + ;; characters. + (if (and (eq system-type 'windows-nt) + (boundp 'w32-ansi-code-page)) + (encode-coding-string raw-string + (intern (format "cp%d" w32-ansi-code-page))) + raw-string))) (defun counsel-locate-function (input) "Call the \"locate\" shell command with INPUT." @@ -2391,16 +2476,20 @@ "Location where to put the locatedb in case your home folder is encrypted." :type 'file) +(defun counsel-file-stale-p (fname seconds) + "Return non-nil if FNAME was modified more than SECONDS ago." + (> (time-to-seconds + (time-subtract + (current-time) + (nth 5 (file-attributes fname)))) + seconds)) + (defun counsel--locate-updatedb () (when (file-exists-p "~/.Private") (let ((db-fname (expand-file-name counsel-locate-db-path))) (setenv "LOCATE_PATH" db-fname) (when (or (not (file-exists-p db-fname)) - (> (time-to-seconds - (time-subtract - (current-time) - (nth 5 (file-attributes db-fname)))) - 60)) + (counsel-file-stale-p db-fname 60)) (message "Updating %s..." db-fname) (counsel--command "updatedb" "-l" "0" "-o" db-fname "-U" (expand-file-name "~")))))) @@ -2420,9 +2509,12 @@ (with-ivy-window (find-file (concat (file-remote-p default-directory) file))))) - :unwind #'counsel-delete-process :caller 'counsel-locate)) +(ivy-configure 'counsel-locate + :unwind-fn #'counsel-delete-process + :exit-codes '(1 "Nothing found")) + ;;** `counsel-fzf' (defvar counsel-fzf-cmd "fzf -f \"%s\"" "Command for `counsel-fzf'.") @@ -2458,9 +2550,9 @@ (let ((fzf-basename (car (split-string counsel-fzf-cmd)))) (list nil (when current-prefix-arg - (read-directory-name (concat - fzf-basename - " in directory: ")))))) + (counsel-read-directory-name (concat + fzf-basename + " in directory: ")))))) (counsel-require-program counsel-fzf-cmd) (setq counsel--fzf-dir (or initial-directory @@ -2471,16 +2563,20 @@ :re-builder #'ivy--regex-fuzzy :dynamic-collection t :action #'counsel-fzf-action - :unwind #'counsel-delete-process :caller 'counsel-fzf)) +(ivy-configure 'counsel-fzf + :occur #'counsel-fzf-occur + :unwind-fn #'counsel-delete-process + :exit-codes '(1 "Nothing found")) + (defun counsel-fzf-action (x) "Find file X in current fzf directory." (with-ivy-window (let ((default-directory counsel--fzf-dir)) (find-file x)))) -(defun counsel-fzf-occur () +(defun counsel-fzf-occur (&optional _cands) "Occur function for `counsel-fzf' using `counsel-cmd-to-dired'." (cd counsel--fzf-dir) (counsel-cmd-to-dired @@ -2489,15 +2585,11 @@ "%s --print0 | xargs -0 ls" (format counsel-fzf-cmd ivy-text))))) -(ivy-set-occur 'counsel-fzf 'counsel-fzf-occur) - (ivy-set-actions 'counsel-fzf '(("x" counsel-locate-action-extern "xdg-open") ("d" counsel-locate-action-dired "dired"))) -(counsel-set-async-exit-code 'counsel-fzf 1 "Nothing found") - ;;** `counsel-dpkg' ;;;###autoload (defun counsel-dpkg () @@ -2540,28 +2632,40 @@ (message (cdr x))) :caller 'counsel-rpm))) -(defcustom counsel-file-jump-args ". -name '.git' -prune -o -type f -print | cut -c 3-" +(defun counsel--find-return-list (args) + (unless (listp args) + (user-error "`counsel-file-jump-args' is a list now, please customize accordingly.")) + (counsel--call + (cons find-program args) + (lambda () + (let (files) + (goto-char (point-min)) + (while (< (point) (point-max)) + (when (looking-at "\\./") + (goto-char (match-end 0))) + (push (buffer-substring (point) (line-end-position)) files) + (beginning-of-line 2)) + (nreverse files))))) + +(defcustom counsel-file-jump-args (split-string ". -name .git -prune -o -type f -print") "Arguments for the `find-command' when using `counsel-file-jump'." - :type 'string) + :type '(repeat string)) ;;** `counsel-file-jump' ;;;###autoload (defun counsel-file-jump (&optional initial-input initial-directory) "Jump to a file below the current directory. -List all files within the current directory or any of its subdirectories. +List all files within the current directory or any of its sub-directories. INITIAL-INPUT can be given as the initial minibuffer input. INITIAL-DIRECTORY, if non-nil, is used as the root directory for search." (interactive (list nil (when current-prefix-arg - (read-directory-name "From directory: ")))) + (counsel-read-directory-name "From directory: ")))) (counsel-require-program find-program) (let ((default-directory (or initial-directory default-directory))) (ivy-read "Find file: " - (split-string - (shell-command-to-string - (concat find-program " " counsel-file-jump-args)) - "\n" t) + (counsel--find-return-list counsel-file-jump-args) :matcher #'counsel--find-file-matcher :initial-input initial-input :action #'find-file @@ -2577,28 +2681,26 @@ (dired (or (file-name-directory x) default-directory))) "open in dired"))) -(defcustom counsel-dired-jump-args ". -name '.git' -prune -o -type d -print | cut -c 3-" +(defcustom counsel-dired-jump-args (split-string ". -name .git -prune -o -type d -print") "Arguments for the `find-command' when using `counsel-dired-jump'." - :type 'string) + :type '(repeat string)) ;;** `counsel-dired-jump' ;;;###autoload (defun counsel-dired-jump (&optional initial-input initial-directory) "Jump to a directory (see `dired-jump') below the current directory. -List all subdirectories within the current directory. +List all sub-directories within the current directory. INITIAL-INPUT can be given as the initial minibuffer input. INITIAL-DIRECTORY, if non-nil, is used as the root directory for search." (interactive (list nil (when current-prefix-arg - (read-directory-name "From directory: ")))) + (counsel-read-directory-name "From directory: ")))) (counsel-require-program find-program) (let ((default-directory (or initial-directory default-directory))) (ivy-read "Find directory: " - (split-string - (shell-command-to-string - (concat find-program " " counsel-dired-jump-args)) - "\n" t) + (cdr + (counsel--find-return-list counsel-dired-jump-args)) :matcher #'counsel--find-file-matcher :initial-input initial-input :action (lambda (d) (dired-jump nil (expand-file-name d))) @@ -2651,10 +2753,6 @@ (defvar counsel--regex-look-around nil) -(counsel-set-async-exit-code 'counsel-ag 1 "No matches found") -(ivy-set-occur 'counsel-ag 'counsel-ag-occur) -(ivy-set-display-transformer 'counsel-ag 'counsel-git-grep-transformer) - (defconst counsel--command-args-separator "-- ") (defun counsel--split-command-args (arguments) @@ -2725,9 +2823,9 @@ (when current-prefix-arg (setq initial-directory (or initial-directory - (read-directory-name (concat - (car (split-string counsel-ag-command)) - " in directory: ")))) + (counsel-read-directory-name (concat + (car (split-string counsel-ag-command)) + " in directory: ")))) (setq extra-ag-args (or extra-ag-args (read-from-minibuffer (format @@ -2745,21 +2843,36 @@ :keymap counsel-ag-map :history 'counsel-git-grep-history :action #'counsel-git-grep-action - :unwind (lambda () - (counsel-delete-process) - (swiper--cleanup)) :caller (or caller 'counsel-ag)))) +(ivy-configure 'counsel-ag + :occur #'counsel-ag-occur + :unwind-fn #'counsel--grep-unwind + :display-transformer-fn #'counsel-git-grep-transformer + :grep-p t + :exit-codes '(1 "No matches found")) + +(defun counsel-read-directory-name (prompt) + "Read a directory name from user, a (partial) replacement of `read-directory-name'." + (let ((counsel--find-file-predicate #'file-directory-p)) + (ivy-read prompt + #'read-file-name-internal + :matcher #'counsel--find-file-matcher + :history 'file-name-history + :keymap counsel-find-file-map + :caller 'counsel-read-directory-name))) + +(ivy-configure 'counsel-read-directory-name + :display-transformer-fn #'ivy-read-file-transformer) + (defun counsel-cd () - "Change the directory for the currently running Ivy command." + "Change the directory for the currently running Ivy grep-like command. +Works for `counsel-git-grep', `counsel-ag', etc." (interactive) (let ((input ivy-text) - (new-dir (read-directory-name "cd: "))) + (new-dir (counsel-read-directory-name "cd: "))) (ivy-quit-and-run - (let ((default-directory new-dir)) - (funcall (ivy-state-caller ivy-last) input))))) - -(cl-pushnew 'counsel-ag ivy-highlight-grep-commands) + (funcall (ivy-state-caller ivy-last) input new-dir)))) (defun counsel-grep-like-occur (cmd-template) (unless (eq major-mode 'ivy-occur-grep-mode) @@ -2768,23 +2881,21 @@ (setq ivy-text (and (string-match "\"\\(.*\\)\"" (buffer-name)) (match-string 1 (buffer-name)))) - (let* ((command-args (counsel--split-command-args ivy-text)) - (regex (counsel--grep-regex (cdr command-args))) - (switches (concat (car command-args) - (counsel--ag-extra-switches regex))) - (cmd (format cmd-template + (let* ((cmd + (if (functionp cmd-template) + (funcall cmd-template ivy-text) + (let* ((command-args (counsel--split-command-args ivy-text)) + (regex (counsel--grep-regex (cdr command-args))) + (switches (concat (car command-args) + (counsel--ag-extra-switches regex)))) + (format cmd-template (concat switches - (shell-quote-argument regex)))) + (shell-quote-argument regex)))))) (cands (counsel--split-string (shell-command-to-string cmd)))) - ;; Need precise number of header lines for `wgrep' to work. - (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n" - default-directory)) - (insert (format "%d candidates:\n" (length cands))) - (ivy--occur-insert-lines - (mapcar #'counsel--normalize-grep-match cands)))) + (swiper--occur-insert-lines (mapcar #'counsel--normalize-grep-match cands)))) -(defun counsel-ag-occur () +(defun counsel-ag-occur (&optional _cands) "Generate a custom occur buffer for `counsel-ag'." (counsel-grep-like-occur counsel-ag-command)) @@ -2804,7 +2915,11 @@ (let ((counsel-ag-base-command counsel-pt-base-command) (counsel--grep-tool-look-around nil)) (counsel-ag initial-input :caller 'counsel-pt))) -(cl-pushnew 'counsel-pt ivy-highlight-grep-commands) + +(ivy-configure 'counsel-pt + :unwind-fn #'counsel--grep-unwind + :display-transformer-fn #'counsel-git-grep-transformer + :grep-p t) ;;** `counsel-ack' (defcustom counsel-ack-base-command @@ -2828,15 +2943,31 @@ ;;** `counsel-rg' -(defcustom counsel-rg-base-command "rg -S --no-heading --line-number --color never %s ." +(defcustom counsel-rg-base-command + (if (memq system-type '(ms-dos windows-nt)) + "rg --with-filename --no-heading --line-number --path-separator / --color never %s ." + "rg --with-filename --no-heading --line-number --color never %s") "Alternative to `counsel-ag-base-command' using ripgrep. Note: don't use single quotes for the regex." :type 'string) -(counsel-set-async-exit-code 'counsel-rg 1 "No matches found") -(ivy-set-occur 'counsel-rg 'counsel-ag-occur) -(ivy-set-display-transformer 'counsel-rg 'counsel-git-grep-transformer) +(defun counsel--rg-targets () + "Return a list of files to operate on, based on `dired-mode' marks." + (if (eq major-mode 'dired-mode) + (let ((files + (dired-get-marked-files 'no-dir nil nil t))) + (if (and (null (cdr files)) + (not (when (string-match-p "\\*ivy-occur" (buffer-name)) + (dired-toggle-marks) + (setq files (dired-get-marked-files 'no-dir)) + (dired-toggle-marks) + t))) + "" + (concat + " " + (mapconcat #'shell-quote-argument (delq t files) " ")))) + "")) ;;;###autoload (defun counsel-rg (&optional initial-input initial-directory extra-rg-args rg-prompt) @@ -2849,7 +2980,8 @@ Example input with inclusion and exclusion file patterns: -g*.py -g!*test* -- ..." (interactive) - (let ((counsel-ag-base-command counsel-rg-base-command) + (let ((counsel-ag-base-command + (concat counsel-rg-base-command (counsel--rg-targets))) (counsel--grep-tool-look-around (let ((rg (car (split-string counsel-rg-base-command))) (switch "--pcre2")) @@ -2857,7 +2989,13 @@ switch)))) (counsel-ag initial-input initial-directory extra-rg-args rg-prompt :caller 'counsel-rg))) -(cl-pushnew 'counsel-rg ivy-highlight-grep-commands) + +(ivy-configure 'counsel-rg + :occur #'counsel-ag-occur + :unwind-fn #'counsel--grep-unwind + :display-transformer-fn #'counsel-git-grep-transformer + :grep-p t + :exit-codes '(1 "No matches found")) ;;** `counsel-grep' (defvar counsel-grep-map @@ -2887,6 +3025,12 @@ (format counsel-grep-command (shell-quote-argument regex))) nil))) +(defvar counsel--grep-last-pos nil + "Store the last point and line that `counsel-grep-action' scrolled to. +This speeds up scrolling: instead of going to `point-min' and +`forward-line' with a huge arg (e.g. to scroll 50K lines), scroll +relative to the last position stored here.") + (defun counsel-grep-action (x) "Go to candidate X." (with-ivy-window @@ -2907,12 +3051,14 @@ (with-current-buffer (or (get-file-buffer file-name) (find-file file-name)) (setq line-number (string-to-number line-number)) - (if counsel-grep-last-line - (forward-line (- line-number counsel-grep-last-line)) + (if (and counsel--grep-last-pos (= (point) (car counsel--grep-last-pos))) + (forward-line (- line-number (cdr counsel--grep-last-pos))) (goto-char (point-min)) (forward-line (1- line-number))) - (setq counsel-grep-last-line line-number) - (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) + (setq counsel--grep-last-pos (cons (point) line-number)) + (when (re-search-forward (ivy--regex ivy-text t) (line-end-position) t) + (when swiper-goto-start-of-match + (goto-char (match-beginning 0)))) (run-hooks 'counsel-grep-post-action-hook) (if (eq ivy-exit 'done) (swiper--ensure-visible) @@ -2920,7 +3066,7 @@ (line-end-position)) (swiper--add-overlays (ivy--regex ivy-text)))))))) -(defun counsel-grep-occur () +(defun counsel-grep-occur (&optional _cands) "Generate a custom occur buffer for `counsel-grep'." (counsel-grep-like-occur (format @@ -2930,9 +3076,6 @@ (buffer-file-name (ivy-state-buffer ivy-last))))))) -(ivy-set-occur 'counsel-grep 'counsel-grep-occur) -(counsel-set-async-exit-code 'counsel-grep 1 "") - (defvar counsel-grep-history nil "History for `counsel-grep'.") @@ -2944,7 +3087,6 @@ (unless buffer-file-name (user-error "Current buffer is not visiting a file")) (counsel-require-program counsel-grep-base-command) - (setq counsel-grep-last-line nil) (setq counsel-grep-command (format counsel-grep-base-command "%s" (shell-quote-argument @@ -2954,9 +3096,10 @@ (init-point (point)) res) (unwind-protect - (setq res (ivy-read "grep: " 'counsel-grep-function + (setq res (ivy-read "grep: " #'counsel-grep-function :initial-input initial-input :dynamic-collection t + :require-match t :preselect (when (< (- (line-end-position) (line-beginning-position)) 300) (format "%d:%s" @@ -2965,19 +3108,23 @@ (buffer-substring-no-properties (line-beginning-position) (line-end-position))))) - :keymap counsel-grep-map :history 'counsel-grep-history - :update-fn 'auto :re-builder #'ivy--regex :action #'counsel-grep-action - :unwind (lambda () - (counsel-delete-process) - (swiper--cleanup)) :caller 'counsel-grep)) (unless res (goto-char init-point))))) +(ivy-configure 'counsel-grep + :update-fn 'auto + :unwind-fn #'counsel--grep-unwind + :index-fn #'ivy-recompute-index-swiper-async + :occur #'counsel-grep-occur + :more-chars 2 + :grep-p t + :exit-codes '(1 "")) + ;;;###autoload (defun counsel-grep-backward (&optional initial-input) "Grep for a string in the file visited by the current buffer going @@ -3072,9 +3219,11 @@ (find-file file-name) (unless (string-match "pdf$" x) (swiper ivy-text))))) - :unwind #'counsel-delete-process :caller 'counsel-recoll)) +(ivy-configure 'counsel-recoll + :unwind-fn #'counsel-delete-process) + ;;* Org ;;** `counsel-org-tag' (defvar counsel-org-tags nil @@ -3255,16 +3404,10 @@ #'counsel-org-tag)) (org-agenda-set-tags))) -(define-obsolete-variable-alias 'counsel-org-goto-display-tags - 'counsel-org-headline-display-tags "0.10.0") - (defcustom counsel-org-headline-display-tags nil "If non-nil, display tags in matched `org-mode' headlines." :type 'boolean) -(define-obsolete-variable-alias 'counsel-org-goto-display-todo - 'counsel-org-headline-display-todo "0.10.0") - (defcustom counsel-org-headline-display-todo nil "If non-nil, display todo keywords in matched `org-mode' headlines." :type 'boolean) @@ -3317,7 +3460,7 @@ instead of the default settings. The following settings are recognized: -- `:outline-regexp' is a regexp to match the beggining of an +- `:outline-regexp' is a regexp to match the beginning of an outline heading. It is only checked at the start of a line and so need not start with \"^\". Defaults to the value of the variable `outline-regexp'. @@ -3346,7 +3489,7 @@ eponymous `ivy-read' keyword, as used by `counsel-outline'. Defaults to the symbol `counsel-outline-history'. -- `:caller' is a symbol to uniquely idendify the caller to +- `:caller' is a symbol to uniquely identify the caller to `ivy-read'. It corresponds directly to its eponymous `ivy-read' keyword, as used by `counsel-outline'. Defaults to the symbol `counsel-outline'. @@ -3496,6 +3639,9 @@ (org-capture nil (car (split-string x)))) :caller 'counsel-org-capture)) +(ivy-configure 'counsel-org-capture + :initial-input "^") + (ivy-set-actions 'counsel-org-capture `(("t" ,(lambda (x) @@ -3532,11 +3678,6 @@ (defvar counsel-org-agenda-headlines-history nil "History for `counsel-org-agenda-headlines'.") -(define-obsolete-variable-alias 'counsel-org-goto-display-style - 'counsel-outline-display-style "0.10.0") -(define-obsolete-variable-alias 'counsel-org-headline-display-style - 'counsel-outline-display-style "0.10.0") - (defcustom counsel-outline-display-style 'path "The style used when displaying matched outline headings. @@ -3558,11 +3699,6 @@ (const :tag "Headline" headline) (const :tag "Path" path))) -(define-obsolete-variable-alias 'counsel-org-goto-separator - 'counsel-outline-path-separator "0.10.0") -(define-obsolete-variable-alias 'counsel-org-headline-path-separator - 'counsel-outline-path-separator "0.10.0") - (defcustom counsel-outline-path-separator "/" "String separating path entries in matched outline headings. This variable has no effect unless @@ -3628,20 +3764,20 @@ "Face for current `counsel-mark-ring' line." :group 'ivy-faces) -(defvar counsel--mark-ring-overray nil - "Intarnal overray to highlight line by candidate of `counsel-mark-ring'.") +(defvar counsel--mark-ring-overlay nil + "Internal overlay to highlight line by candidate of `counsel-mark-ring'.") (defun counsel--mark-ring-add-highlight () "Add highlight to current line." - (setq counsel--mark-ring-overray + (setq counsel--mark-ring-overlay (make-overlay (line-beginning-position) (1+ (line-end-position)))) (with-ivy-window - (overlay-put counsel--mark-ring-overray 'face + (overlay-put counsel--mark-ring-overlay 'face 'counsel--mark-ring-highlight))) (defun counsel--mark-ring-delete-highlight () "If `counsel-mark-ring' have highlight, delete highlight." - (if counsel--mark-ring-overray (delete-overlay counsel--mark-ring-overray))) + (if counsel--mark-ring-overlay (delete-overlay counsel--mark-ring-overlay))) (defvar counsel--mark-ring-calling-point 0 "Internal variable to remember calling position.") @@ -3653,41 +3789,46 @@ (defun counsel--mark-ring-update-fn () "Show preview by candidate." - (let ((linenum (string-to-number (ivy-state-current ivy-last)))) + (let ((pos (get-text-property 0 'point (ivy-state-current ivy-last)))) (counsel--mark-ring-delete-highlight) - (unless (= linenum 0) - (with-ivy-window - (forward-line (- linenum (line-number-at-pos))))))) + (with-ivy-window + (goto-char pos) + (counsel--mark-ring-add-highlight)))) ;;;###autoload (defun counsel-mark-ring () "Browse `mark-ring' interactively. Obeys `widen-automatically', which see." (interactive) - (let ((counsel--mark-ring-calling-point (point)) - (cands - (save-excursion - (save-restriction - ;; Widen, both to save `line-number-at-pos' the trouble - ;; and for `buffer-substring' to work. - (widen) - (let ((fmt (format "%%%dd %%s" - (length (number-to-string - (line-number-at-pos (point-max))))))) - (mapcar (lambda (mark) - (goto-char (marker-position mark)) - (let ((linum (line-number-at-pos)) - (line (buffer-substring - (line-beginning-position) - (line-end-position)))) - (cons (format fmt linum line) (point)))) - (sort (delete-dups (copy-sequence mark-ring)) #'<))))))) + (let* ((counsel--mark-ring-calling-point (point)) + (width (length (number-to-string (line-number-at-pos (point-max))))) + (fmt (format "%%%dd %%s" width)) + (make-candidate + (lambda (mark) + (goto-char (marker-position mark)) + (let ((linum (line-number-at-pos)) + (line (buffer-substring + (line-beginning-position) (line-end-position)))) + (propertize (format fmt linum line) 'point (point))))) + (marks (copy-sequence mark-ring)) + (marks (delete-dups marks)) + (marks + ;; mark-marker is empty? + (if (equal (mark-marker) (make-marker)) + marks + (cons (copy-marker (mark-marker)) marks))) + (cands + ;; Widen, both to save `line-number-at-pos' the trouble + ;; and for `buffer-substring' to work. + (save-excursion + (save-restriction + (widen) + (mapcar make-candidate marks))))) (if cands (ivy-read "Mark: " cands :require-match t - :update-fn #'counsel--mark-ring-update-fn :action (lambda (cand) - (let ((pos (cdr-safe cand))) + (let ((pos (get-text-property 0 'point cand))) (when pos (unless (<= (point-min) pos (point-max)) (if widen-automatically @@ -3695,14 +3836,20 @@ (error "\ Position of selected mark outside accessible part of buffer"))) (goto-char pos)))) - :unwind #'counsel--mark-ring-unwind :caller 'counsel-mark-ring) (message "Mark ring is empty")))) +(ivy-configure 'counsel-mark-ring + :update-fn #'counsel--mark-ring-update-fn + :unwind-fn #'counsel--mark-ring-unwind + :sort-fn #'ivy-string<) + ;;** `counsel-package' (defvar package--initialized) (defvar package-alist) (defvar package-archive-contents) +(defvar package-archives) +(defvar package-user-dir) (declare-function package-installed-p "package") (declare-function package-delete "package") (declare-function package-desc-extras "package") @@ -3714,8 +3861,16 @@ "Return completion alist for `counsel-package'." (unless package--initialized (package-initialize t)) - (unless package-archive-contents - (package-refresh-contents)) + (if (or (not package-archive-contents) + (cl-find-if (lambda (package-archive) + (let ((fname + (format + "%s/archives/%s/archive-contents" + package-user-dir (car package-archive)))) + (or (not (file-exists-p fname)) + (counsel-file-stale-p fname (* 4 60 60))))) + package-archives)) + (package-refresh-contents)) (sort (mapcar (lambda (entry) (cons (let ((pkg (car entry))) (concat (if (package-installed-p pkg) "-" "+") @@ -3795,8 +3950,7 @@ (map-keymap (lambda (k v) (tmm-get-keymap (cons k v))) menu) (setq tmm-km-list (nreverse tmm-km-list)) (setq out (ivy-read "Menu bar: " (tmm--completion-table tmm-km-list) - :require-match t - :sort nil)) + :require-match t)) (setq choice (cdr (assoc out tmm-km-list))) (setq chosen-string (car choice)) (setq choice (cdr choice)) @@ -3810,7 +3964,7 @@ ;;;###autoload (defun counsel-tmm () - "Text-mode emulation of looking and choosing from a menubar." + "Text-mode emulation of looking and choosing from a menu bar." (interactive) (require 'tmm) (run-hooks 'menu-bar-update-hook) @@ -3854,9 +4008,6 @@ (const :tag "Dashes" "\n----\n") string)) -(define-obsolete-variable-alias 'counsel-yank-pop-height - 'ivy-height-alist "0.11.0") - (defun counsel--yank-pop-format-function (cand-pairs) "Transform CAND-PAIRS into a string for `counsel-yank-pop'." (ivy--format-function-generic @@ -3899,7 +4050,7 @@ (defun counsel--yank-pop-kills () "Return filtered `kill-ring' for `counsel-yank-pop' completion. Both `kill-ring' and `kill-ring-yank-pointer' may be -destructively modifed to eliminate duplicates under +destructively modified to eliminate duplicates under `equal-including-properties', satisfy `counsel-yank-pop-filter', and incorporate `interprogram-paste-function'." ;; Protect against `kill-ring' and result of @@ -4010,8 +4161,10 @@ :preselect preselect :action #'counsel-yank-pop-action :caller 'counsel-yank-pop))) -(add-to-list 'ivy-format-functions-alist '(counsel-yank-pop . counsel--yank-pop-format-function)) -(add-to-list 'ivy-height-alist '(counsel-yank-pop . 5)) + +(ivy-configure 'counsel-yank-pop + :height 5 + :format-fn #'counsel--yank-pop-format-function) (ivy-set-actions 'counsel-yank-pop @@ -4065,16 +4218,14 @@ (list s)))) register-alist) :require-match t - :sort t :history 'counsel-register-history :action #'counsel-register-action :caller 'counsel-register)) -;;** `counsel-evil-registers' -(defcustom counsel-evil-registers-height 5 - "The `ivy-height' of `counsel-evil-registers'." - :type 'integer) +(ivy-configure 'counsel-register + :sort-fn #'ivy-string<) +;;** `counsel-evil-registers' ;;;###autoload (defun counsel-evil-registers () "Ivy replacement for `evil-show-registers'." @@ -4087,8 +4238,9 @@ :action #'counsel-evil-registers-action :caller 'counsel-evil-registers) (user-error "Required feature `evil' not installed."))) -(add-to-list 'ivy-format-functions-alist '(counsel-evil-registers . counsel--yank-pop-format-function)) -(add-to-list 'ivy-height-alist '(counsel-evil-registers . 5)) +(ivy-configure 'counsel-evil-registers + :height 5 + :format-fn #'counsel--yank-pop-format-function) (defun counsel-evil-registers-action (s) "Paste contents of S, trimming the register part. @@ -4104,28 +4256,40 @@ (declare-function imenu--subalist-p "imenu") (declare-function imenu--make-index-alist "imenu") +(defun counsel--imenu-candidates () + (unless (featurep 'imenu) + (require 'imenu nil t)) + (let* ((imenu-auto-rescan t) + (imenu-auto-rescan-maxout (if current-prefix-arg + (buffer-size) + imenu-auto-rescan-maxout)) + (items (imenu--make-index-alist t)) + (items (delete (assoc "*Rescan*" items) items)) + (items (counsel-imenu-categorize-functions items))) + (counsel-imenu-get-candidates-from items))) + (defun counsel-imenu-get-candidates-from (alist &optional prefix) "Create a list of (key . value) from ALIST. PREFIX is used to create the key." - (cl-mapcan (lambda (elm) - (if (imenu--subalist-p elm) - (counsel-imenu-get-candidates-from - (cl-loop for (e . v) in (cdr elm) collect - (cons e (if (integerp v) (copy-marker v) v))) - ;; pass the prefix to next recursive call - (concat prefix (if prefix ".") (car elm))) - (let ((key (concat - (when prefix - (concat - (propertize prefix 'face 'ivy-grep-info) - ": ")) - (car elm)))) - (list (cons key - ;; create a imenu candidate here - (cons key (if (overlayp (cdr elm)) - (overlay-start (cdr elm)) - (cdr elm)))))))) - alist)) + (cl-mapcan + (lambda (elm) + (if (imenu--subalist-p elm) + (counsel-imenu-get-candidates-from + (cl-loop for (e . v) in (cdr elm) collect + (cons e (if (integerp v) (copy-marker v) v))) + ;; pass the prefix to next recursive call + (concat prefix (if prefix ".") (car elm))) + (let ((key (concat + (when prefix + (concat + (propertize prefix 'face 'ivy-grep-info) + ": ")) + (car elm)))) + (list (cons key + (cons key (if (overlayp (cdr elm)) + (overlay-start (cdr elm)) + (cdr elm)))))))) + alist)) (defvar counsel-imenu-map (let ((map (make-sparse-keymap))) @@ -4140,29 +4304,20 @@ `(("Functions" ,@fns))) items))) +(defun counsel-imenu-action (x) + (with-ivy-window + (imenu (cdr x)))) + ;;;###autoload (defun counsel-imenu () "Jump to a buffer position indexed by imenu." (interactive) - (unless (featurep 'imenu) - (require 'imenu nil t)) - (let* ((imenu-auto-rescan t) - (imenu-auto-rescan-maxout (if current-prefix-arg - (buffer-size) - imenu-auto-rescan-maxout)) - (items (imenu--make-index-alist t)) - (items (delete (assoc "*Rescan*" items) items)) - (items (counsel-imenu-categorize-functions items))) - (ivy-read "imenu items: " (counsel-imenu-get-candidates-from items) - :preselect (thing-at-point 'symbol) - :require-match t - :action (lambda (candidate) - (with-ivy-window - ;; In org-mode, (imenu candidate) will expand child node - ;; after jump to the candidate position - (imenu (cdr candidate)))) - :keymap counsel-imenu-map - :caller 'counsel-imenu))) + (ivy-read "imenu items: " (counsel--imenu-candidates) + :preselect (thing-at-point 'symbol) + :require-match t + :action #'counsel-imenu-action + :keymap counsel-imenu-map + :caller 'counsel-imenu)) ;;** `counsel-list-processes' (defun counsel-list-processes-action-delete (x) @@ -4265,6 +4420,15 @@ (require 'comint) (counsel--browse-history comint-input-ring)) +(defvar slime-repl-input-history) + +;;;###autoload +(defun counsel-slime-repl-history () + "Browse Slime REPL history." + (interactive) + (require 'slime-repl) + (counsel--browse-history slime-repl-input-history)) + ;;** `counsel-hydra-heads' (defvar hydra-curr-body-fn) (declare-function hydra-keyboard-quit "ext:hydra") @@ -4368,9 +4532,6 @@ (counsel-imenu))) ;;** `counsel-outline' -(define-obsolete-variable-alias 'counsel-org-goto-face-style - 'counsel-outline-face-style "0.10.0") - (defcustom counsel-outline-face-style nil "Determines how to style outline headings during completion. @@ -4409,9 +4570,6 @@ (const :tag "Custom" custom) (const :tag "No style" nil))) -(define-obsolete-variable-alias 'counsel-org-goto-custom-faces - 'counsel-outline-custom-faces "0.10.0") - (defcustom counsel-outline-custom-faces nil "List of faces for custom display of outline headings. @@ -4477,7 +4635,7 @@ (funcall outline-level))) (defvar counsel-outline--preselect 0 - "Index of the presected candidate in `counsel-outline'.") + "Index of the preselected candidate in `counsel-outline'.") (defun counsel-outline-candidates (&optional settings prefix) "Return an alist of outline heading completion candidates. @@ -4711,7 +4869,6 @@ (setq ivy-completion-end (point)) (ivy-read "Unicode name: " counsel--unicode-table :history 'counsel-unicode-char-history - :sort t :action (lambda (name) (with-ivy-window (delete-region ivy-completion-beg ivy-completion-end) @@ -4720,6 +4877,9 @@ (setq ivy-completion-end (point)))) :caller 'counsel-unicode-char)) +(ivy-configure 'counsel-unicode-char + :sort-fn #'ivy-string<) + (defun counsel-unicode-copy (name) "Ivy action to copy the unicode from NAME to the kill ring." (kill-new (char-to-string (get-text-property 0 'code name)))) @@ -4819,7 +4979,8 @@ :history 'counsel-colors-emacs-history :action #'insert :caller 'counsel-colors-emacs))) -(add-to-list 'ivy-format-functions-alist '(counsel-colors-emacs . counsel--colors-emacs-format-function)) +(ivy-configure 'counsel-colors-emacs + :format-fn #'counsel--colors-emacs-format-function) (ivy-set-actions 'counsel-colors-emacs @@ -4830,7 +4991,7 @@ (defvar shr-color-html-colors-alist) (defun counsel-colors--web-alist () - "Return list of CSS colours for `counsel-colors-web'." + "Return list of CSS colors for `counsel-colors-web'." (require 'shr-color) (let* ((alist (copy-alist shr-color-html-colors-alist)) (mp (assoc "MediumPurple" alist)) @@ -4863,16 +5024,34 @@ (ivy-read "Web color: " colors :require-match t :history 'counsel-colors-web-history - :sort t :action #'insert :caller 'counsel-colors-web))) -(add-to-list 'ivy-format-functions-alist '(counsel-colors-web . counsel--colors-web-format-function)) +(ivy-configure 'counsel-colors-web + :sort-fn #'ivy-string< + :format-fn #'counsel--colors-web-format-function) + (ivy-set-actions 'counsel-colors-web '(("h" counsel-colors-action-insert-hex "insert hexadecimal value") ("H" counsel-colors-action-kill-hex "kill hexadecimal value"))) +;;** `counsel-fonts' +(defvar counsel-fonts-history () + "History for `counsel-fonts'.") + +;;;###autoload +(defun counsel-fonts () + "Show a list of all supported font families for a particular frame. + +You can insert or kill the name of the selected font." + (interactive) + (ivy-read "Font: " (delete-dups (font-family-list)) + :require-match t + :history 'counsel-fonts-history + :action #'insert + :caller 'counsel-fonts)) + ;;* Misc. OS ;;** `counsel-rhythmbox' (declare-function dbus-call-method "dbus") @@ -5331,14 +5510,11 @@ Display a preview of the selected ivy completion candidate buffer in the current window." (interactive) - (ivy-read "Switch to buffer: " 'internal-complete-buffer - :preselect (buffer-name (other-buffer (current-buffer))) - :keymap ivy-switch-buffer-map - :action #'ivy--switch-buffer-action - :matcher #'ivy--switch-buffer-matcher - :caller 'counsel-switch-buffer - :unwind #'counsel--switch-buffer-unwind - :update-fn 'counsel--switch-buffer-update-fn)) + (let ((ivy-update-fns-alist + '((ivy-switch-buffer . counsel--switch-buffer-update-fn))) + (ivy-unwind-fns-alist + '((ivy-switch-buffer . counsel--switch-buffer-unwind)))) + (ivy-switch-buffer))) ;;;###autoload (defun counsel-switch-buffer-other-window () @@ -5346,13 +5522,11 @@ Display a preview of the selected ivy completion candidate buffer in the current window." (interactive) - (ivy-read "Switch to buffer in other window: " 'internal-complete-buffer - :preselect (buffer-name (other-buffer (current-buffer))) - :action #'ivy--switch-buffer-other-window-action - :matcher #'ivy--switch-buffer-matcher - :caller 'counsel-switch-buffer-other-window - :unwind #'counsel--switch-buffer-unwind - :update-fn 'counsel--switch-buffer-update-fn)) + (let ((ivy-update-fns-alist + '((ivy-switch-buffer-other-window . counsel--switch-buffer-update-fn))) + (ivy-unwind-fns-alist + '((ivy-switch-buffer-other-window . counsel--switch-buffer-unwind)))) + (ivy-switch-buffer-other-window))) (defun counsel-open-buffer-file-externally (buffer) "Open the file associated with BUFFER with an external program." @@ -5370,6 +5544,11 @@ 'ivy-switch-buffer '(("x" counsel-open-buffer-file-externally "open externally"))) +(ivy-set-actions + 'counsel-switch-buffer + '(("x" counsel-open-buffer-file-externally "open externally") + ("j" ivy--switch-buffer-other-window-action "other window"))) + ;;** `counsel-compile' (defvar counsel-compile-history nil "History for `counsel-compile'. @@ -5436,7 +5615,7 @@ "Additional compile invocations to feed into `counsel-compile'. This can either be a list of compile invocation strings or -functions that will provide such a list. You should customise +functions that will provide such a list. You should customize this if you want to provide specific non-standard build types to `counsel-compile'. The default helpers are set up to handle common build environments.") @@ -5457,7 +5636,7 @@ "History for `counsel-compile-env'.") (defvar counsel-compile-env-pattern - "[_[:digit:][:upper:]]+=[/[:album:]]*" + "[_[:digit:][:upper:]]+=[/[:alnum:]]*" "Pattern to match valid environment variables.") (defcustom counsel-compile-make-pattern "\\`\\(?:GNUm\\|[Mm]\\)akefile\\'" @@ -5530,7 +5709,7 @@ "Have a look in the root directory for any build control files. The optional BLDDIR is useful for other helpers that have found -subdirectories that builds may be invoked in." +sub-directories that builds may be invoked in." (let ((srcdir (counsel--compile-root))) (when (directory-files (or blddir srcdir) nil counsel-compile-make-pattern t) @@ -5652,9 +5831,11 @@ (defun counsel-compile (&optional dir) "Call `compile' completing with smart suggestions, optionally for DIR." (interactive) - (setq counsel-compile--current-build-dir (or dir default-directory)) + (setq counsel-compile--current-build-dir (or dir + (counsel--compile-root) + default-directory)) (ivy-read "Compile command: " - (counsel--get-compile-candidates dir) + (delete-dups (counsel--get-compile-candidates dir)) :action #'counsel-compile--action :caller 'counsel-compile)) @@ -5695,7 +5876,9 @@ cand)) :history 'counsel-compile-env-history :caller 'counsel-compile-env)) -(add-to-list 'ivy-format-functions-alist '(counsel-compile-env . counsel-compile-env--format-hint)) + +(ivy-configure 'counsel-compile-env + :format-fn #'counsel-compile-env--format-hint) ;;** `counsel-minor' (defvar counsel-minor-history nil @@ -5742,17 +5925,65 @@ (counsel--minor-candidates) :require-match t :history 'counsel-minor-history - :sort t :action (lambda (x) (call-interactively (cdr x))))) -(cl-pushnew '(counsel-minor . "^+") ivy-initial-inputs-alist :key #'car) +(ivy-configure 'counsel-minor + :initial-input "^+" + :sort-fn #'ivy-string<) (ivy-set-actions 'counsel-minor `(("d" ,(lambda (x) (find-function (cdr x))) "definition") ("h" ,(lambda (x) (describe-function (cdr x))) "help"))) +;;;###autoload +(defun counsel-major () + (interactive) + (ivy-read "Major modes: " obarray + :predicate (lambda (f) + (and (commandp f) (string-match "-mode$" (symbol-name f)) + (or (and (autoloadp (symbol-function f)) + (let ((doc-split (help-split-fundoc (documentation f) f))) + ;; major mode starters have no arguments + (and doc-split (null (cdr (read (car doc-split))))))) + (null (help-function-arglist f))))) + :action #'counsel-M-x-action + :caller 'counsel-major)) + +;;* `counsel-google' +(declare-function request "ext:request") +(defun counsel-google-function (input) + "Create a request to Google with INPUT. +Return 0 tells `ivy--exhibit' not to update the minibuffer. +We update it in the callback with `ivy-update-candidates'." + (or + (ivy-more-chars) + (progn + (require 'request) + (require 'json) + (request + "http://suggestqueries.google.com/complete/search" + :type "GET" + :params (list + (cons "client" "firefox") + (cons "q" input)) + :parser 'json-read + :success (cl-function + (lambda (&key data &allow-other-keys) + (ivy-update-candidates + (mapcar #'identity (aref data 1)))))) + 0))) + +(defun counsel-google () + "Ivy interface for Google." + (interactive) + (ivy-read "search: " #'counsel-google-function + :action (lambda (x) + (browse-url (concat "https://www.google.com/search?q=" x))) + :dynamic-collection t + :caller 'counsel-google)) + ;;* `counsel-mode' (defvar counsel-mode-map (let ((map (make-sparse-keymap))) diff -Nru emacs-ivy-0.12.0+dfsg/debian/changelog emacs-ivy-0.13.0/debian/changelog --- emacs-ivy-0.12.0+dfsg/debian/changelog 2019-08-25 23:26:25.000000000 +0000 +++ emacs-ivy-0.13.0/debian/changelog 2020-07-24 23:12:20.000000000 +0000 @@ -1,3 +1,30 @@ +emacs-ivy (0.13.0-1) unstable; urgency=medium + + * New upstream version, now with DFSG-free documentation. + * Drop 0001-Skip-3-tests-that-are-unsuitable-for-buildd-or-DebCI.patch + because these tests no longer exist upstream. + * copyright: No longer exclude doc/ivy.org and doc/ivy.texi. + * copyright: Add GDFL-1.3+NIV license info for these two files. + * control: Add texinfo as a build dep when 'nodoc' isn't active. + * rules: Add override_dh_installinfo to convert upstream ivy.org to + ivy.texi, and to then run makeinfo. + * rules: Override dh_clean to restore upstream-provided ivy.texi + * Create debian/elpa-ivy.info to install the new info page. + * Add elpa-smex to elpa-counsel's Recommends. The way it presents one's + recently and most frequently used commands at the top of the + candidates list is a wonderful productivity-enhancing feature. See + the docs to learn how to use Counsel to enable this for the M-x + interface. + * Add elpa-wgrep as a build-dep. (Closes: #944991) + * Cherry pick 0001-ivy-test.el-ivy-with-Don-t-use-counsel-locate-git-ro.patch + from upstream to fix failing self-tests. + * Add 0002-Skip-ert-deftest-ivy-lazy-load-ffap-ffap-url-p.patch to skip + another failing test. + * debian/control: Add "Rules-Requires-Root: no". + * Declare Standards-Version 4.5.0 (no changes required). + + -- Nicholas D Steeves Fri, 24 Jul 2020 19:12:20 -0400 + emacs-ivy (0.12.0+dfsg-1) unstable; urgency=medium * New upstream version. diff -Nru emacs-ivy-0.12.0+dfsg/debian/control emacs-ivy-0.13.0/debian/control --- emacs-ivy-0.12.0+dfsg/debian/control 2019-08-25 23:26:25.000000000 +0000 +++ emacs-ivy-0.13.0/debian/control 2020-07-24 23:12:20.000000000 +0000 @@ -5,7 +5,10 @@ Uploaders: Nicholas D Steeves Build-Depends: debhelper-compat (= 12) , dh-elpa -Standards-Version: 4.4.0 + , elpa-wgrep + , texinfo +Rules-Requires-Root: no +Standards-Version: 4.5.0 Vcs-Browser: https://salsa.debian.org/emacsen-team/emacs-ivy Vcs-Git: https://salsa.debian.org/emacsen-team/emacs-ivy.git Homepage: https://github.com/abo-abo/swiper @@ -57,8 +60,8 @@ Depends: ${elpa:Depends} , ${misc:Depends} , elpa-swiper +Recommends: elpa-smex Enhances: emacs - , elpa-smex , elpa-ivy , elpa-swiper , git diff -Nru emacs-ivy-0.12.0+dfsg/debian/copyright emacs-ivy-0.13.0/debian/copyright --- emacs-ivy-0.12.0+dfsg/debian/copyright 2019-08-25 23:26:25.000000000 +0000 +++ emacs-ivy-0.13.0/debian/copyright 2020-07-24 23:12:20.000000000 +0000 @@ -2,12 +2,24 @@ Upstream-Name: swiper Upstream-Contact: Oleh Krehel Source: https://github.com/abo-abo/swiper -Files-Excluded: doc/ivy.org doc/ivy.texi Files: * Copyright: 2015-2019 Free Software Foundation, Inc. License: GPL-3+ +Files: doc/ivy.org doc/ivy.texi +Copyright: 2015-2019 Free Software Foundation, Inc. +License: GDFL-1.3+NIV + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + . + On Debian systems, the complete text of the GNU Free Documentation + License version 1.3 can be found in `/usr/share/common-licenses/GFDL-1.3' + Files: debian/* Copyright: 2017-2019 Nicholas D Steeves License: GPL-3+ diff -Nru emacs-ivy-0.12.0+dfsg/debian/elpa-ivy.info emacs-ivy-0.13.0/debian/elpa-ivy.info --- emacs-ivy-0.12.0+dfsg/debian/elpa-ivy.info 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/debian/elpa-ivy.info 2020-07-24 23:12:20.000000000 +0000 @@ -0,0 +1 @@ +ivy.info diff -Nru emacs-ivy-0.12.0+dfsg/debian/patches/0001-ivy-test.el-ivy-with-Don-t-use-counsel-locate-git-ro.patch emacs-ivy-0.13.0/debian/patches/0001-ivy-test.el-ivy-with-Don-t-use-counsel-locate-git-ro.patch --- emacs-ivy-0.12.0+dfsg/debian/patches/0001-ivy-test.el-ivy-with-Don-t-use-counsel-locate-git-ro.patch 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/debian/patches/0001-ivy-test.el-ivy-with-Don-t-use-counsel-locate-git-ro.patch 2020-07-24 23:12:20.000000000 +0000 @@ -0,0 +1,26 @@ +From: Oleh Krehel +Date: Thu, 11 Jun 2020 20:24:32 +0200 +Subject: ivy-test.el (ivy-with): Don't use counsel-locate-git-root +Origin: upstream, https://github.com/abo-abo/swiper/commit/db5a8940cf2a4324a1512c8f2a0e91475d1ac26f +Bug: https://github.com/abo-abo/swiper/issues/2608 + +Assume `default-directory' matches it anyway + +Re #2608 +--- + ivy-test.el | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ivy-test.el b/ivy-test.el +index c15cf2f..10ab9eb 100644 +--- a/ivy-test.el ++++ b/ivy-test.el +@@ -80,7 +80,7 @@ Since `execute-kbd-macro' doesn't pick up a let-bound `default-directory'.") + (unwind-protect + (progn + (when dir +- (setq dir (expand-file-name dir (counsel-locate-git-root)))) ++ (setq dir (expand-file-name dir))) + (setq ivy-eval-dir dir) + (execute-kbd-macro + (vconcat (kbd "C-c e") diff -Nru emacs-ivy-0.12.0+dfsg/debian/patches/0001-Skip-3-tests-that-are-unsuitable-for-buildd-or-DebCI.patch emacs-ivy-0.13.0/debian/patches/0001-Skip-3-tests-that-are-unsuitable-for-buildd-or-DebCI.patch --- emacs-ivy-0.12.0+dfsg/debian/patches/0001-Skip-3-tests-that-are-unsuitable-for-buildd-or-DebCI.patch 2019-08-25 23:26:25.000000000 +0000 +++ emacs-ivy-0.13.0/debian/patches/0001-Skip-3-tests-that-are-unsuitable-for-buildd-or-DebCI.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -From: Nicholas D Steeves -Date: Wed, 7 Aug 2019 21:32:30 -0400 -Subject: Skip 3 tests that are unsuitable for buildd or DebCI (and that fail) -Forwarded: https://github.com/abo-abo/swiper/issues/2187 - -These 3 tests depend on this function: - -counsel--setup-test-files () - (unless (file-exists-p "tests/") - (shell-command - "git clone -b test --single-branch https://github.com/abo-abo/swiper/ tests")) - (let ((default-directory (expand-file-name "tests/")) - (version "066ec1d")) - (shell-command - (format "git checkout %s || git fetch && git checkout %s" version version)))) ---- - ivy-test.el | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/ivy-test.el b/ivy-test.el -index 386fe9c..02dbb3c 100644 ---- a/ivy-test.el -+++ b/ivy-test.el -@@ -1262,6 +1262,7 @@ a buffer visiting a file." - (format "git checkout %s || git fetch && git checkout %s" version version)))) - - (ert-deftest counsel-find-file-with-dollars () -+ (ert-skip "Test unsuitable for buildds or DebCI") - (counsel--setup-test-files) - (should (string= - (file-relative-name -@@ -1270,6 +1271,7 @@ a buffer visiting a file." - "tests/find-file/files-with-dollar/foo$"))) - - (ert-deftest counsel-find-file-with-dotfiles () -+ (ert-skip "Test unsuitable for buildds or DebCI") - (counsel--setup-test-files) - (should (string= - (file-relative-name -@@ -1283,6 +1285,7 @@ a buffer visiting a file." - "tests/find-file/dotfiles/.foobar1"))) - - (ert-deftest counsel-find-file-with-spaces () -+ (ert-skip "Test unsuitable for buildds or DebCI") - (counsel--setup-test-files) - (let ((ivy-extra-directories nil)) - (should (string= diff -Nru emacs-ivy-0.12.0+dfsg/debian/patches/0002-Skip-ert-deftest-ivy-lazy-load-ffap-ffap-url-p.patch emacs-ivy-0.13.0/debian/patches/0002-Skip-ert-deftest-ivy-lazy-load-ffap-ffap-url-p.patch --- emacs-ivy-0.12.0+dfsg/debian/patches/0002-Skip-ert-deftest-ivy-lazy-load-ffap-ffap-url-p.patch 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/debian/patches/0002-Skip-ert-deftest-ivy-lazy-load-ffap-ffap-url-p.patch 2020-07-24 23:12:20.000000000 +0000 @@ -0,0 +1,30 @@ +From: Nicholas D Steeves +Date: Sat, 20 Jun 2020 05:43:08 -0400 +Subject: Skip ert-deftest ivy--lazy-load-ffap--ffap-url-p +Origin: upstream, https://github.com/abo-abo/swiper/issues/2608#issuecomment-643200262 +Bug: https://github.com/abo-abo/swiper/issues/2608 + +This test fails on a local system, and will certainly fail on buildd. +Basil-conto writes that parts of it "assume too much about the +environment and have nothing to do with Ivy" and "checking whether Ivy +causes another package to be loaded is not something suitable for +Emacs regression tests or even that useful/practical" thus it seems +reasonable to skip this test for now. If upstream resolves the issue +then this patch should be dropped. + +--- + ivy-test.el | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ivy-test.el b/ivy-test.el +index 10ab9eb..2186973 100644 +--- a/ivy-test.el ++++ b/ivy-test.el +@@ -44,6 +44,7 @@ + (message "%s" (emacs-version)) + + (ert-deftest ivy--lazy-load-ffap--ffap-url-p () ++ (ert-skip "Skipping ivy--lazy-load-ffap--ffap-url-p") + (should (not (memq 'ffap require-features))) + (should (not (fboundp 'ffap-url-p))) + (should (string= (ivy-ffap-url-p "https://foo.org") diff -Nru emacs-ivy-0.12.0+dfsg/debian/patches/series emacs-ivy-0.13.0/debian/patches/series --- emacs-ivy-0.12.0+dfsg/debian/patches/series 2019-08-25 23:26:25.000000000 +0000 +++ emacs-ivy-0.13.0/debian/patches/series 2020-07-24 23:12:20.000000000 +0000 @@ -1 +1,2 @@ -0001-Skip-3-tests-that-are-unsuitable-for-buildd-or-DebCI.patch +0001-ivy-test.el-ivy-with-Don-t-use-counsel-locate-git-ro.patch +0002-Skip-ert-deftest-ivy-lazy-load-ffap-ffap-url-p.patch diff -Nru emacs-ivy-0.12.0+dfsg/debian/rules emacs-ivy-0.13.0/debian/rules --- emacs-ivy-0.12.0+dfsg/debian/rules 2019-08-25 23:26:25.000000000 +0000 +++ emacs-ivy-0.13.0/debian/rules 2020-07-24 23:12:20.000000000 +0000 @@ -6,7 +6,19 @@ override_dh_auto_build: @echo Using dh-elpa for build/install instead of upstream Makefile. +override_dh_clean: + dh_clean + mv -f doc/ivy.texi~ doc/ivy.texi || true + override_dh_installchangelogs: mkdir -p debian/tmp cat doc/Changelog.org debian/local-var-snippet >> debian/tmp/changelog dh_installchangelogs debian/tmp/changelog + +override_dh_installinfo: + @echo Generating info page. + cd doc \ + && emacs -batch -l ivy-ox.el -l scripts.el \ + --eval "(org-to-texi \"ivy.org\")" + makeinfo --no-split doc/ivy.texi -o debian/tmp/ivy.info + dh_installinfo diff -Nru emacs-ivy-0.12.0+dfsg/doc/Changelog.org emacs-ivy-0.13.0/doc/Changelog.org --- emacs-ivy-0.12.0+dfsg/doc/Changelog.org 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/doc/Changelog.org 2019-10-16 16:57:42.000000000 +0000 @@ -1,6 +1,6 @@ #+TITLE: Ivy CHANGELOG #+OPTIONS: H:4 num:nil toc:3 -#+SETUPFILE: ~/git/org-html-themes/setup/theme-readtheorg.setup +#+SETUPFILE: ~/git/Emacs/org-html-themes/setup/theme-readtheorg.setup #+HTML_HEAD: * 0.6.0 @@ -4581,7 +4581,7 @@ :PROPERTIES: :CUSTOM_ID: 0-12-0-fx-counsel-org-file :END: -Handle ATTACH_DIR property. Re-use el:org-attach-dir. See [[https://github.com/abo-abo/swiper/issues/2042][#2042]]. +Handle =ATTACH_DIR= property. Re-use el:org-attach-dir. See [[https://github.com/abo-abo/swiper/issues/2042][#2042]]. ----- *** counsel-org-goto-all :PROPERTIES: @@ -5193,3 +5193,507 @@ :END: See [[https://github.com/abo-abo/swiper/issues/2125][#2125]]. ----- +* 0.13.0 +:PROPERTIES: +:CUSTOM_ID: 0.13.0 +:END: +----- +** Fixes +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fixes +:END: +----- +*** counsel--async-last-command +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel--async-last-command +:END: +New variable. Store the last command ran by el:counsel--async-command. +----- +*** counsel--async-last-error-string +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel--async-last-error-string +:END: +New variable. If a command that relies on el:counsel--async-command returns non-0, store +the output here. See [[https://github.com/abo-abo/swiper/issues/2160][#2160]]. +----- +*** counsel-cd +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-cd +:END: +Fix for el:counsel-ag. See [[https://github.com/abo-abo/swiper/issues/2261][#2261]]. +----- +*** counsel-compile +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-compile +:END: +Delete duplicates. Favor project root over el:default-directory. See [[https://github.com/abo-abo/swiper/issues/2253][#2253]]. +----- +*** counsel-compile-env-pattern +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-compile-env-pattern +:END: +Fix regex typo. See [[https://github.com/abo-abo/swiper/issues/2193][#2193]]. +----- +*** counsel-file-jump +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-file-jump +:END: +Use temp buffer instead of el:split-string. See [[https://github.com/abo-abo/swiper/issues/2120][#2120]]. + +Make el:counsel--find-return-list work with or without the "./" prefix. See [[https://github.com/abo-abo/swiper/issues/2196][#2196]]. +----- +*** counsel-git-grep-action +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-git-grep-action +:END: +Check the result of el:re-search-forward. See [[https://github.com/abo-abo/swiper/issues/2209][#2209]]. +----- +*** counsel-imenu +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-imenu +:END: +Work with =:update-fn 'auto=. See [[https://github.com/abo-abo/swiper/issues/2188][#2188]]. +----- +*** counsel-locate-cmd-es +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-locate-cmd-es +:END: +Encode the command to local codepage. See [[https://github.com/abo-abo/swiper/issues/2278][#2278]]. +----- +*** counsel-mark-ring +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-mark-ring +:END: +Refactor. See [[https://github.com/abo-abo/swiper/issues/2237][#2237]]. + +Add the latest mark to selection. See [[https://github.com/abo-abo/swiper/issues/2252][#2252]]. + +Go to actual point instead of line. See [[https://github.com/abo-abo/swiper/issues/2254][#2254]]. + +Fix highlight line. See [[https://github.com/abo-abo/swiper/issues/2255][#2255]]. + +Handle read-only strings. See [[https://github.com/abo-abo/swiper/issues/2258][#2258]], [[https://github.com/abo-abo/swiper/issues/2262][#2262]]. +----- +*** counsel-M-x +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-m-x +:END: +Respect el:counsel-describe-function-function. See [[https://github.com/abo-abo/swiper/issues/2251][#2251]]. +----- +*** counsel--py-action +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel--py-action +:END: +Don't auto-insert parens. See [[https://github.com/abo-abo/swiper/issues/2229][#2229]]. +----- +*** counsel-rg-base-command +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-counsel-rg-base-command +:END: +Don't include directory on non-Windows. See [[https://github.com/abo-abo/swiper/issues/795][#795]], [[https://github.com/abo-abo/swiper/issues/2180][#2180]]. + +Ensure =/= is the path-separator on Windows. See [[https://github.com/abo-abo/swiper/issues/2279][#2279]]. +----- +*** Documentation +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-documentation +:END: +=ivy.info= is not installed from GNU ELPA. See [[https://github.com/abo-abo/swiper/issues/697][#697]]. + +Fix typo. See [[https://github.com/abo-abo/swiper/issues/2170][#2170]]. + +Fix el:ivy-read docstring. See [[https://github.com/abo-abo/swiper/issues/2201][#2201]]. + +Add full text of licences. See [[https://github.com/abo-abo/swiper/issues/2206][#2206]]. + +Document the marking feature. See [[https://github.com/abo-abo/swiper/issues/2214][#2214]]. + +Update GFDL licence. See [[https://github.com/abo-abo/swiper/issues/2187][#2187]]. + +Ivy now requires at least Emacs-24.5 (released on 2015-04-10). Up from Emacs-24.1 +(released 2012-06-10). +----- +*** hydra-ivy +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-hydra-ivy +:END: +Use el:ivy-read-action-by-key. See [[https://github.com/abo-abo/swiper/issues/2239][#2239]], [[https://github.com/abo-abo/swiper/issues/2250][#2250]]. +----- +*** ivy +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy +:END: +Lazy load el:ffap. See [[https://github.com/abo-abo/swiper/issues/2215][#2215]]. +----- +*** ivy-completion-in-region +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-completion-in-region +:END: +Add workaround for el:package-menu-filter. See [[https://github.com/abo-abo/swiper/issues/2244][#2244]]. +----- +*** ivy--directory-done +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy--directory-done +:END: +Handle ~/ C-j~ on remote. See [[https://github.com/abo-abo/swiper/issues/2205][#2205]]. +----- +*** ivy-dispatching-done-hydra +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-dispatching-done-hydra +:END: +Fix for el:ivy-resume. Modify the action list non-desctructively. See [[https://github.com/abo-abo/swiper/issues/2195][#2195]]. +----- +*** ivy--done +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy--done +:END: +Check if given a string. See [[https://github.com/abo-abo/swiper/issues/2200][#2200]]. +----- +*** ivy-immediate-done +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-immediate-done +:END: +Add el:copy-sequence to fix el:read-directory-name. See [[https://github.com/abo-abo/swiper/issues/1170][#1170]], [[https://github.com/abo-abo/swiper/issues/2149][#2149]], [[https://github.com/abo-abo/swiper/issues/2165][#2165]]. + +Fix for when ~C-j~ changed cwd. See [[https://github.com/abo-abo/swiper/issues/2165][#2165]]. + +Fix parent dirs for el:read-directory-name. See [[https://github.com/abo-abo/swiper/issues/2165][#2165]], [[https://github.com/abo-abo/swiper/issues/2198][#2198]]. +----- +*** ivy--input +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy--input +:END: +Fix point moving in TRAMP sessions sometimes. See [[https://github.com/abo-abo/swiper/issues/2160][#2160]]. + +Fix for el:ediff. See [[https://github.com/abo-abo/swiper/issues/2175][#2175]]. +----- +*** ivy--magic-file-slash +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy--magic-file-slash +:END: +Make less aggressive. Check that the prompt is not selected before performing the +ivy-magic-slash-non-match-cd-selected action. See [[https://github.com/abo-abo/swiper/issues/2240][#2240]]. +----- +*** ivy-occur +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-occur +:END: +Set up for el:next-error. See [[https://github.com/abo-abo/swiper/issues/1354][#1354]], [[https://github.com/abo-abo/swiper/issues/2257][#2257]]. +----- +*** ivy-occur-revert-buffer +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-occur-revert-buffer +:END: +Don't error if the el:swiper buffer was killed. +----- +*** ivy-overlay-show-after +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-overlay-show-after +:END: +Check window height better. See [[https://github.com/abo-abo/swiper/issues/2161][#2161]]. +----- +*** ivy-partial +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-partial +:END: +Fix trailing space issue. See [[https://github.com/abo-abo/swiper/issues/2103][#2103]]. + +Use el:ivy--filter in place of el:all-completions. See [[https://github.com/abo-abo/swiper/issues/2199][#2199]]. +----- +*** ivy-read +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-read +:END: +Fix conflict with an existing el:read-key session. See [[https://github.com/abo-abo/swiper/issues/2230][#2230]]. +----- +*** ivy-resume +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-resume +:END: +Restore use-ignore setting. See [[https://github.com/abo-abo/swiper/issues/2179][#2179]]. +----- +*** ivy-yank-word +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-ivy-yank-word +:END: +Handle case fold. See [[https://github.com/abo-abo/swiper/issues/2194][#2194]]. +----- +*** swiper +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper +:END: +Fix overlay faces using el:ivy--regex-ignore-order. See [[https://github.com/abo-abo/swiper/issues/2162][#2162]]. + +Fix symbol bounds with el:char-fold-to-regexp. See [[https://github.com/abo-abo/swiper/issues/2177][#2177]]. +----- +*** swiper-isearch +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper-isearch +:END: +Improve matching. See [[https://github.com/abo-abo/swiper/issues/2154][#2154]]. + +Fix for el:ivy-resume. See [[https://github.com/abo-abo/swiper/issues/2153][#2153]], 2154. + +Make el:swiper-isearch-function work with el:ivy--regex-ignore-order. See [[https://github.com/abo-abo/swiper/issues/2155][#2155]]. + +Fix return value. See [[https://github.com/abo-abo/swiper/issues/2163][#2163]]. + +Fix regexes for el:ivy--regex-ignore-order. See [[https://github.com/abo-abo/swiper/issues/2164][#2164]]. + +Fix scroll on ~RET~. See [[https://github.com/abo-abo/swiper/issues/2159][#2159]]. + +Set el:case-fold-search. See [[https://github.com/abo-abo/swiper/issues/2226][#2226]]. +----- +*** swiper-isearch-action +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper-isearch-action +:END: +Make el:ivy-previous-line-or-history work. See [[https://github.com/abo-abo/swiper/issues/2158][#2158]]. +----- +*** swiper-occur +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper-occur +:END: +Fix for el:wgrep. See [[https://github.com/abo-abo/swiper/issues/2156][#2156]]. +----- +*** swiper-query-replace +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper-query-replace +:END: +For for "^$" search term. See [[https://github.com/abo-abo/swiper/issues/2232][#2232]]. +----- +*** swiper-recenter-top-bottom +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper-recenter-top-bottom +:END: +Now works for el:swiper-isearch. +----- +*** swiper-thing-at-point +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-swiper-thing-at-point +:END: +Fix for el:swiper-isearch. See [[https://github.com/abo-abo/swiper/issues/2157][#2157]]. +----- +*** Tests +:PROPERTIES: +:CUSTOM_ID: 0.13.0-fx-tests +:END: +Keep the test files in worktree instead of in a =test= branch. See [[https://github.com/abo-abo/swiper/issues/2187][#2187]]. + +Fix tests using file names on Windows. See [[https://github.com/abo-abo/swiper/issues/2217][#2217]]. +----- +** New Features +:PROPERTIES: +:CUSTOM_ID: 0.13.0-new-features +:END: +----- +*** counsel-dired +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-dired +:END: +Filter to directories only. See [[https://github.com/abo-abo/swiper/issues/2275][#2275]]. +----- +*** counsel-dired-jump-args +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-dired-jump-args +:END: +The variable is now a list. See [[https://github.com/abo-abo/swiper/issues/2120][#2120]]. +----- +*** counsel-file-jump-args +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-file-jump-args +:END: +The variable is now a list. See [[https://github.com/abo-abo/swiper/issues/2120][#2120]]. +----- +*** counsel-find-file +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-find-file +:END: +Use =~~= to move to the local home directory from remote. Using =/ RET ~= is still an option, +but more cumbersome. This also works for =/sudo::=. See [[https://github.com/abo-abo/swiper/issues/2276][#2276]]. + +Use el:file-name-at-point-functions. See [[https://github.com/abo-abo/swiper/issues/1446][#1446]], [[https://github.com/abo-abo/swiper/issues/2181][#2181]], [[https://github.com/abo-abo/swiper/issues/2184][#2184]]. + +Use el:dired-current-directory if in el:dired. See [[https://github.com/abo-abo/swiper/issues/2274][#2274]]. + +Bind ~M-o R~ to el:find-file-read-only. See [[https://github.com/abo-abo/swiper/issues/2236][#2236]]. +----- +*** counsel-find-file-mkdir-action +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-find-file-mkdir-action +:END: +Make parents too. See [[https://github.com/abo-abo/swiper/issues/2178][#2178]]. +----- +*** counsel-git-grep +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-git-grep +:END: +Use ~C-x C-d~ to switch current directory. See [[https://github.com/abo-abo/swiper/issues/2259][#2259]]. + +Works with el:ivy--regex-fuzzy. el:ivy-occur works as well. See [[https://github.com/abo-abo/swiper/issues/2243][#2243]]. + +Nicer message when no match was found. See [[https://github.com/abo-abo/swiper/issues/2265][#2265]]. +----- +*** counsel-M-x +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-m-x +:END: +Propertize names of active modes with el:counsel-active-mode. See [[https://github.com/abo-abo/swiper/issues/2189][#2189]], [[https://github.com/abo-abo/swiper/issues/2258][#2258]]. + +Some commands are intended to be called only via their key binding. Make them disappear +from el:counsel-M-x like this: +#+begin_src elisp +(put 'counsel-find-symbol 'no-counsel-M-x t) +#+end_src +See [[https://github.com/abo-abo/swiper/issues/2270][#2270]]. +----- +*** counsel-package +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-package +:END: +Refresh contents automatically. +----- +*** counsel-rg +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-rg +:END: +Ivy will add "-i" appropriately, based on el:ivy-case-fold-search-default. +You should remove the "-S" flag from el:counsel-rg-base-command if you customized it. + +When in el:dired, operate on marked files. This also applies to ivy-occur buffers of +el:counsel-find-file and el:counsel-git. +----- +*** counsel-switch-buffer +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-counsel-switch-buffer +:END: +Add actions. See [[https://github.com/abo-abo/swiper/issues/2233][#2233]]. +----- +*** ivy-configure +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-configure +:END: +New function to configure many things at once. Example: +#+begin_src elisp +(ivy-configure 'counsel-find-file + :occur #'counsel-find-file-occur + :display-transformer-fn #'ivy-read-file-transformer) +#+end_src +Instead of configuring many alists separately using the =:caller= key of el:ivy-read, +configure everything together. +----- +*** ivy-ffap-url-functions +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-ffap-url-functions +:END: +Add el:vc-git-log-view-mode. +----- +*** ivy-partial +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-partial +:END: +Obey el:completion-cycle-threshold. See [[https://github.com/abo-abo/swiper/issues/2225][#2225]]. +----- +*** ivy-partial-or-done +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-partial-or-done +:END: +Work with el:completion-cycle-threshold. See [[https://github.com/abo-abo/swiper/issues/2225][#2225]]. +If you set this to an integer, and the amount of candidates is less than that number, +pressing ~TAB~ will cycle to the next candidate. +----- +*** ivy-pre-prompt-function +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-pre-prompt-function +:END: +When non-nil, add strings before the el:ivy-read prompt. See [[https://github.com/abo-abo/swiper/issues/2185][#2185]]. +----- +*** ivy-read +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-read +:END: +New API for asynchronous calls. See [[https://github.com/abo-abo/swiper/issues/2263][#2263]]. + +To use it, pass to el:ivy-read: =:dynamic-collection t=, and a collection function that +takes a user input string, starts some asynchronous process based on that input, and +returns 0. The 0 return result tells Ivy that no candidates were returned; instead, +el:ivy-update-candidates is used in the async callback. + +See el:counsel-google for a reference implementation. +----- +*** ivy-read-action-function +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-read-action-function +:END: +New defcustom that allows you to read the action via: key, or Ivy, or Hydra. See [[https://github.com/abo-abo/swiper/issues/2176][#2176]]. +----- +*** ivy-restrict-to-matches +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-restrict-to-matches +:END: +Work for dynamic collection. See [[https://github.com/abo-abo/swiper/issues/2168][#2168]]. +----- +*** ivy-update-fns-alist +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-update-fns-alist +:END: +Allow to customize =:update-fn=. See [[https://github.com/abo-abo/swiper/issues/2188][#2188]]. +Example: +#+begin_src elisp +(ivy-configure 'counsel-imenu + :update-fn 'auto) +#+end_src +----- +*** ivy-use-virtual-buffers +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-ivy-use-virtual-buffers +:END: +Allow to choose beween: recent files, or bookmarks, or both, or none. See [[https://github.com/abo-abo/swiper/issues/2169][#2169]], [[https://github.com/abo-abo/swiper/issues/2172][#2172]]. +----- +*** swiper-goto-start-of-match +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-swiper-goto-start-of-match +:END: +Also works for el:counsel-grep and el:counsel-git-grep. See [[https://github.com/abo-abo/swiper/issues/2209][#2209]]. +----- +*** swiper-isearch +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nf-swiper-isearch +:END: +Bind ~M-o w~ to copy the current line. +----- +** New Commands +:PROPERTIES: +:CUSTOM_ID: 0.13.0-new-commands +:END: +----- +*** counsel-buffer-or-recentf +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nc-counsel-buffer-or-recentf +:END: +Lists buffers visiting files (highlighted) then the recentf file list. See [[https://github.com/abo-abo/swiper/issues/2182][#2182]]. +----- +*** counsel-fonts +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nc-counsel-fonts +:END: +Show a list of all supported font families for a particular frame. See [[https://github.com/abo-abo/swiper/issues/2220][#2220]]. +----- +*** counsel-google +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nc-counsel-google +:END: +Asynchronously query the Google predictive search API. +----- +*** counsel-major +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nc-counsel-major +:END: +Switch el:major-mode. See [[https://github.com/abo-abo/swiper/issues/378][#378]]. +----- +*** counsel-slime-repl-history +:PROPERTIES: +:CUSTOM_ID: 0.13.0-nc-counsel-slime-repl-history +:END: +Browse Slime REPL history. See [[https://github.com/abo-abo/swiper/issues/2234][#2234]]. +----- diff -Nru emacs-ivy-0.12.0+dfsg/doc/fdl-1.3.txt emacs-ivy-0.13.0/doc/fdl-1.3.txt --- emacs-ivy-0.12.0+dfsg/doc/fdl-1.3.txt 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/doc/fdl-1.3.txt 2019-10-16 16:57:42.000000000 +0000 @@ -0,0 +1,451 @@ + + GNU Free Documentation License + Version 1.3, 3 November 2008 + + + Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +functional and useful document "free" in the sense of freedom: to +assure everyone the effective freedom to copy and redistribute it, +with or without modifying it, either commercially or noncommercially. +Secondarily, this License preserves for the author and publisher a way +to get credit for their work, while not being considered responsible +for modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work, in any medium, that +contains a notice placed by the copyright holder saying it can be +distributed under the terms of this License. Such a notice grants a +world-wide, royalty-free license, unlimited in duration, to use that +work under the conditions stated herein. The "Document", below, +refers to any such manual or work. Any member of the public is a +licensee, and is addressed as "you". You accept the license if you +copy, modify or distribute the work in a way requiring permission +under copyright law. + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall +subject (or to related matters) and contains nothing that could fall +directly within that overall subject. (Thus, if the Document is in +part a textbook of mathematics, a Secondary Section may not explain +any mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. If a +section does not fit the above definition of Secondary then it is not +allowed to be designated as Invariant. The Document may contain zero +Invariant Sections. If the Document does not identify any Invariant +Sections then there are none. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. A Front-Cover Text may +be at most 5 words, and a Back-Cover Text may be at most 25 words. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, that is suitable for revising the document +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup, or absence of markup, has been arranged to thwart +or discourage subsequent modification by readers is not Transparent. +An image format is not Transparent if used for any substantial amount +of text. A copy that is not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML, PostScript or PDF designed for human modification. Examples of +transparent image formats include PNG, XCF and JPG. Opaque formats +include proprietary formats that can be read and edited only by +proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML, PostScript or PDF produced by some word +processors for output purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +The "publisher" means any person or entity that distributes copies of +the Document to the public. + +A section "Entitled XYZ" means a named subunit of the Document whose +title either is precisely XYZ or contains XYZ in parentheses following +text that translates XYZ in another language. (Here XYZ stands for a +specific section name mentioned below, such as "Acknowledgements", +"Dedications", "Endorsements", or "History".) To "Preserve the Title" +of such a section when you modify the Document means that it remains a +section "Entitled XYZ" according to this definition. + +The Document may include Warranty Disclaimers next to the notice which +states that this License applies to the Document. These Warranty +Disclaimers are considered to be included by reference in this +License, but only as regards disclaiming warranties: any other +implication that these Warranty Disclaimers may have is void and has +no effect on the meaning of this License. + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no +other conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies (or copies in media that commonly have +printed covers) of the Document, numbering more than 100, and the +Document's license notice requires Cover Texts, you must enclose the +copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a computer-network location from which the general network-using +public has access to download using public-standard network protocols +a complete Transparent copy of the Document, free of added material. +If you use the latter option, you must take reasonably prudent steps, +when you begin distribution of Opaque copies in quantity, to ensure +that this Transparent copy will remain thus accessible at the stated +location until at least one year after the last time you distribute an +Opaque copy (directly or through your agents or retailers) of that +edition to the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to +give them a chance to provide you with an updated version of the +Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has fewer than five), + unless they release you from this requirement. +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section Entitled "History", Preserve its Title, and add + to it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section Entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. For any section Entitled "Acknowledgements" or "Dedications", + Preserve the Title of the section, and preserve in the section all + the substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section Entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section to be Entitled "Endorsements" + or to conflict in title with any Invariant Section. +O. Preserve any Warranty Disclaimers. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section Entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice, and that you preserve all their Warranty Disclaimers. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections Entitled "History" +in the various original documents, forming one section Entitled +"History"; likewise combine any sections Entitled "Acknowledgements", +and any sections Entitled "Dedications". You must delete all sections +Entitled "Endorsements". + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other +documents released under this License, and replace the individual +copies of this License in the various documents with a single copy +that is included in the collection, provided that you follow the rules +of this License for verbatim copying of each of the documents in all +other respects. + +You may extract a single document from such a collection, and +distribute it individually under this License, provided you insert a +copy of this License into the extracted document, and follow this +License in all other respects regarding verbatim copying of that +document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, is called an "aggregate" if the copyright +resulting from the compilation is not used to limit the legal rights +of the compilation's users beyond what the individual works permit. +When the Document is included in an aggregate, this License does not +apply to the other works in the aggregate which are not themselves +derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one half of +the entire aggregate, the Document's Cover Texts may be placed on +covers that bracket the Document within the aggregate, or the +electronic equivalent of covers if the Document is in electronic form. +Otherwise they must appear on printed covers that bracket the whole +aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License, and all the license notices in the +Document, and any Warranty Disclaimers, provided that you also include +the original English version of this License and the original versions +of those notices and disclaimers. In case of a disagreement between +the translation and the original version of this License or a notice +or disclaimer, the original version will prevail. + +If a section in the Document is Entitled "Acknowledgements", +"Dedications", or "History", the requirement (section 4) to Preserve +its Title (section 1) will typically require changing the actual +title. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense, or distribute it is void, and +will automatically terminate your rights under this License. + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, receipt of a copy of some or all of the same material does +not give you any rights to use it. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions of the +GNU Free Documentation License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in +detail to address new problems or concerns. See +https://www.gnu.org/licenses/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. If the Document +specifies that a proxy can decide which future versions of this +License can be used, that proxy's public statement of acceptance of a +version permanently authorizes you to choose that version for the +Document. + +11. RELICENSING + +"Massive Multiauthor Collaboration Site" (or "MMC Site") means any +World Wide Web server that publishes copyrightable works and also +provides prominent facilities for anybody to edit those works. A +public wiki that anybody can edit is an example of such a server. A +"Massive Multiauthor Collaboration" (or "MMC") contained in the site +means any set of copyrightable works thus published on the MMC site. + +"CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 +license published by Creative Commons Corporation, a not-for-profit +corporation with a principal place of business in San Francisco, +California, as well as future copyleft versions of that license +published by that same organization. + +"Incorporate" means to publish or republish a Document, in whole or in +part, as part of another Document. + +An MMC is "eligible for relicensing" if it is licensed under this +License, and if all works that were first published under this License +somewhere other than this MMC, and subsequently incorporated in whole or +in part into the MMC, (1) had no cover texts or invariant sections, and +(2) were thus incorporated prior to November 1, 2008. + +The operator of an MMC Site may republish an MMC contained in the site +under CC-BY-SA on the same site at any time before August 1, 2009, +provided the MMC is eligible for relicensing. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, +replace the "with...Texts." line with this: + + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + +If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff -Nru emacs-ivy-0.12.0+dfsg/doc/gpl-3.0.txt emacs-ivy-0.13.0/doc/gpl-3.0.txt --- emacs-ivy-0.12.0+dfsg/doc/gpl-3.0.txt 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/doc/gpl-3.0.txt 2019-10-16 16:57:42.000000000 +0000 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff -Nru emacs-ivy-0.12.0+dfsg/doc/ivy.org emacs-ivy-0.13.0/doc/ivy.org --- emacs-ivy-0.12.0+dfsg/doc/ivy.org 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/doc/ivy.org 2019-10-16 16:57:42.000000000 +0000 @@ -0,0 +1,1389 @@ +#+TITLE: Ivy User Manual +#+AUTHOR: Oleh Krehel +#+EMAIL: ohwoeowho@gmail.com +#+LANGUAGE: en + +#+TEXINFO_DIR_CATEGORY: Emacs +#+TEXINFO_DIR_TITLE: Ivy: (ivy). +#+TEXINFO_DIR_DESC: Using Ivy for completion. + +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+OPTIONS: H:6 num:6 toc:4 +#+STARTUP: indent +* Setup :noexport: +#+BEGIN_SRC elisp :exports results :results silent +(add-to-list 'load-path default-directory) +(require 'ivy-ox) +#+END_SRC +* Writing this manual :noexport: +To highlight a section without introducing a new subheading use +definition lists. The definition list "owns" the subsequent text if +the text is indented by 5 spaces. Use ~C-q~ to indent the +paragraphs. Start new paragraphs with 5 spaces indented. To separate +definition lists from regular lists, use two newlines. + +A typical definition list: +#+BEGIN_EXAMPLE +- ~C-M-j~ (=ivy-immediate-done=) :: +#+END_EXAMPLE +The code and kbd part is recognized and added as =@vindex= and +=@kindex= respectively. + +Use definition lists to declare a =@defopt= section for =defcustom= +or =defvar=. For proper Texinfo export, use this form: + +#+BEGIN_EXAMPLE +User Option =ivy-wrap= :: +#+END_EXAMPLE + +Set =CUSTOM_ID= property to name each heading. For example, =worf='s +~C-u L~. This will result in consistent HTML node names. + +Keep one empty line before each source block for proper Texinfo +exports. + +** Exporting to texinfo + +ivy.texi is generated from ivy.org. To update the .texi file, eval +ivy-ox.el then ~C-c C-e i t~ in the ivy.org buffer. +* Copying +:PROPERTIES: +:COPYING: t +:CUSTOM_ID: copying +:END: +#+TEXINFO: @ifnottex +Ivy manual, version 0.13.0 + +Ivy is an interactive interface for completion in Emacs. Emacs uses +completion mechanism in a variety of contexts: code, menus, commands, +variables, functions, etc. Completion entails listing, sorting, +filtering, previewing, and applying actions on selected items. When +active, =ivy-mode= completes the selection process by narrowing +available choices while previewing in the minibuffer. Selecting the +final candidate is either through simple keyboard character inputs or +through powerful regular expressions. +#+TEXINFO: @end ifnottex + +Copyright (C) 2015-2019 Free Software Foundation, Inc. + +#+BEGIN_QUOTE +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is included in the section entitled "GNU +Free Documentation License". +#+END_QUOTE + +#+HTML: This manual source +* Introduction +:PROPERTIES: +:CUSTOM_ID: introduction +:END: +Ivy is for quick and easy selection from a list. When Emacs prompts +for a string from a list of several possible choices, Ivy springs into +action to assist in narrowing and picking the right string from a vast +number of choices. + +Ivy strives for minimalism, simplicity, customizability and +discoverability. + +- Minimalism :: + Uncluttered minibuffer is minimalism. Ivy shows the completion + defaults, the number of matches, and 10 candidate matches below + the input line. Customize =ivy-height= to adjust the number of + candidate matches displayed in the minibuffer. + +- Simplicity :: + Simplicity is about Ivy's behavior in the minibuffer. It is also + about the code interface to extend Ivy's functionality. The + minibuffer area behaves as close to =fundamental-mode= as + possible. ~SPC~ inserts a space, for example, instead of being + bound to the more complex =minibuffer-complete-word=. Ivy's code + uses easy-to-examine global variables; avoids needless + complications with branch-introducing custom macros. + +- Customizability :: + Customizability is about being able to use different methods and + interfaces of completion to tailor the selection process. For + example, adding a custom display function that points to a + selected candidate with =>=, instead of highlighting the selected + candidate with the =ivy-current-match= face (see + =ivy-format-functions-alist=). Or take the customization of actions, say + after the candidate function is selected. ~RET~ uses + =counsel-describe-function= to describe the function, whereas + ~M-o d~ jumps to that function's definition in the code. The + ~M-o~ prefix can be uniformly used with characters like ~d~ to + group similar actions. + +- Discoverability :: + Ivy displays easily discoverable commands through the hydra + facility. ~C-o~ in the minibuffer displays a hydra menu. It + opens up within an expanded minibuffer area. Each menu item comes + with short documentation strings and highlighted one-key + completions. So discovering even seldom used keys is simply a + matter of ~C-o~ in the minibuffer while in the midst of the Ivy + interaction. This discoverability minimizes exiting Ivy interface + for documentation look-ups. + +* Installation +:PROPERTIES: +:CUSTOM_ID: installation +:END: + +Install Ivy automatically through Emacs's package manager, or manually +from Ivy's development repository. + +Emacs 24.3 is the oldest version to run Ivy. Emacs 24.4 is the oldest +version that runs Ivy with fancy faces display. + +** Installing from Emacs Package Manager +:PROPERTIES: +:CUSTOM_ID: installing-from-emacs-package-manager +:END: + +~M-x~ =package-install= ~RET~ =ivy= ~RET~ + +Ivy is installed as part of =ivy= package, which is available from two +different package archives, GNU ELPA and MELPA. For the latest stable +version, use the GNU ELPA archives using the above M-x command. + +For current hourly builds, use the MELPA archives. In MELPA, Ivy is +split into three packages: =ivy=, =swiper= and =counsel=; you can simply +install =counsel= which will bring in the other two as dependencies. +See the code below for adding MELPA to the list of package archives: + +#+begin_src elisp +(require 'package) +(add-to-list 'package-archives + '("melpa" . "https://melpa.org/packages/")) +#+end_src + +After this do ~M-x~ =package-refresh-contents= ~RET~, followed by ~M-x~ +=package-install= ~RET~ =counsel= ~RET~. + +For package manager details, see [[info:emacs#Packages]]. + +** Installing from the Git repository +:PROPERTIES: +:CUSTOM_ID: installing-from-the-git-repository +:END: + +- Why install from Git? :: + + - No need to wait for MELPA's hourly builds + - Easy to revert to previous versions + - Contribute to Ivy's development; send patches; pull requests + + +- Configuration steps :: + First clone the Swiper repository with: + + #+begin_src sh + cd ~/git && git clone https://github.com/abo-abo/swiper + cd swiper && make compile + #+end_src + + Second, add these lines to the Emacs init file: + + #+begin_src elisp + (add-to-list 'load-path "~/git/swiper/") + (require 'ivy) + #+end_src + + Then, update the code with: + + #+begin_src sh + git pull + make + #+end_src + +* Getting started +:PROPERTIES: +:CUSTOM_ID: getting-started +:END: +First enable Ivy completion everywhere: + +#+begin_src elisp +(ivy-mode 1) +#+end_src + +Note: =ivy-mode= can be toggled on and off with ~M-x~ =ivy-mode=. +** Basic customization +:PROPERTIES: +:CUSTOM_ID: basic-customization +:END: +Here are some basic settings particularly useful for new Ivy users: + +#+begin_src elisp +(setq ivy-use-virtual-buffers t) +(setq ivy-count-format "(%d/%d) ") +#+end_src + +If you want, you can go without any customizations at all. The above +settings are the most bang for the buck in terms of customization. So +users that typically don't like customize a lot are advised to look at +these settings first. + +For more advanced customizations, refer to =M-x describe-variable= +documentation. + +* Key bindings +:PROPERTIES: +:CUSTOM_ID: key-bindings +:END: +** Global key bindings +:PROPERTIES: +:CUSTOM_ID: global-key-bindings +:END: +Here is a list of commands that are useful to be bound globally, along +with some sample bindings: + +- Ivy-based interface to standard commands :: + + #+begin_src elisp + (global-set-key (kbd "C-s") 'swiper-isearch) + (global-set-key (kbd "M-x") 'counsel-M-x) + (global-set-key (kbd "C-x C-f") 'counsel-find-file) + (global-set-key (kbd "M-y") 'counsel-yank-pop) + (global-set-key (kbd " f") 'counsel-describe-function) + (global-set-key (kbd " v") 'counsel-describe-variable) + (global-set-key (kbd " l") 'counsel-find-library) + (global-set-key (kbd " i") 'counsel-info-lookup-symbol) + (global-set-key (kbd " u") 'counsel-unicode-char) + (global-set-key (kbd " j") 'counsel-set-variable) + (global-set-key (kbd "C-x b") 'ivy-switch-buffer) + (global-set-key (kbd "C-c v") 'ivy-push-view) + (global-set-key (kbd "C-c V") 'ivy-pop-view) + #+end_src + +- Ivy-based interface to shell and system tools :: + + #+begin_src elisp + (global-set-key (kbd "C-c c") 'counsel-compile) + (global-set-key (kbd "C-c g") 'counsel-git) + (global-set-key (kbd "C-c j") 'counsel-git-grep) + (global-set-key (kbd "C-c L") 'counsel-git-log) + (global-set-key (kbd "C-c k") 'counsel-rg) + (global-set-key (kbd "C-c m") 'counsel-linux-app) + (global-set-key (kbd "C-c n") 'counsel-fzf) + (global-set-key (kbd "C-x l") 'counsel-locate) + (global-set-key (kbd "C-c J") 'counsel-file-jump) + (global-set-key (kbd "C-S-o") 'counsel-rhythmbox) + (global-set-key (kbd "C-c w") 'counsel-wmctrl) + #+end_src + +- Ivy-resume and other commands :: + + =ivy-resume= resumes the last Ivy-based completion. + + #+begin_src elisp + (global-set-key (kbd "C-c C-r") 'ivy-resume) + (global-set-key (kbd "C-c b") 'counsel-bookmark) + (global-set-key (kbd "C-c d") 'counsel-descbinds) + (global-set-key (kbd "C-c g") 'counsel-git) + (global-set-key (kbd "C-c o") 'counsel-outline) + (global-set-key (kbd "C-c t") 'counsel-load-theme) + (global-set-key (kbd "C-c F") 'counsel-org-file) + #+end_src + +You can also enable =counsel-mode= to make some global key binding remapping for you. + +** Minibuffer key bindings +:PROPERTIES: +:CUSTOM_ID: minibuffer-key-bindings +:END: + +#+VINDEX: ivy-minibuffer-map +Ivy includes several minibuffer bindings, which are defined in the +=ivy-minibuffer-map= keymap variable. The most frequently used ones +are described here. + +=swiper= or =counsel-M-x= add more key bindings through the =keymap= +argument to =ivy-read=. These keys, also active in the minibuffer, are +described under their respective commands. + +A key feature of =ivy-minibuffer-map= is its full editing capability +where the familiar ~C-a~, ~C-f~, ~M-d~, ~M-DEL~, ~M-b~, ~M-w~, ~C-k~, +~C-y~ key bindings work the same as in =fundamental-mode=. + +*** Key bindings for navigation +:PROPERTIES: +:CUSTOM_ID: key-bindings-for-navigation +:END: + +- ~C-n~ (=ivy-next-line=) selects the next candidate +- ~C-p~ (=ivy-previous-line=) selects the previous candidate +- ~M-<~ (=ivy-beginning-of-buffer=) selects the first candidate +- ~M->~ (=ivy-end-of-buffer=) selects the last candidate +- ~C-v~ (=ivy-scroll-up-command=) scrolls up by =ivy-height= lines +- ~M-v~ (=ivy-scroll-down-command=) scrolls down by =ivy-height= lines + + +- User Option =ivy-wrap= :: + Specifies the wrap-around behavior for ~C-n~ and ~C-p~. When + =ivy-wrap= is set to =t=, =ivy-next-line= and =ivy-previous-line= + will cycle past the last and the first candidates respectively. + + Wrap-around behavior is off by default. + +- User Option =ivy-height= :: + Use this option to adjust the minibuffer height, which also + affects scroll size when using ~C-v~ and ~M-v~ key bindings. + + =ivy-height= is 10 lines by default. + +*** Key bindings for single selection, action, then exit minibuffer +:PROPERTIES: +:CUSTOM_ID: key-bindings-for-single-selection-action-then-exit-minibuffer +:END: + +Ivy can offer several actions from which to choose which action to +run. This "calling an action" operates on the selected candidate. For +example, when viewing a list of files, one action could open it for +editing, one to view it, another to invoke a special function, and so +on. Custom actions can be added to this interface. The precise action +to call on the selected candidate can be delayed until after the +narrowing is completed. No need to exit the interface if unsure which +action to run. This delayed flexibility and customization of actions +extends usability of lists in Emacs. + +- ~C-m~ or ~RET~ (=ivy-done=) :: + Calls the default action and then exits the minibuffer. + +- ~M-o~ (=ivy-dispatching-done=) :: + Presents valid actions from which to choose. When only one action + is available, there is no difference between ~M-o~ and ~C-m~. + +- ~C-j~ (=ivy-alt-done=) :: + When completing file names, selects the current directory + candidate and starts a new completion session there. Otherwise, + it is the same as =ivy-done=. + +- ~TAB~ (=ivy-partial-or-done=) :: + Attempts partial completion, extending current input as much as + possible. ~TAB TAB~ is the same as ~C-j~ (=ivy-alt-done=). + + Example ERT test: + + #+begin_src elisp + (should + (equal (ivy-with + '(progn + (ivy-read "Test: " '("can do" "can't, sorry" "other")) + ivy-text) + "c ") + "can")) + #+end_src + +- ~C-M-j~ (=ivy-immediate-done=) :: + Exits with /the current input/ instead of /the current candidate/ + (like other commands). + + This is useful e.g. when you call =find-file= to create a new + file, but the desired name matches an existing file. In that + case, using ~C-j~ would select that existing file, which isn't + what you want - use this command instead. + +- ~C-'~ (=ivy-avy=) :: + Uses avy to select one of the candidates on the current candidate + page. This can often be faster than multiple ~C-n~ or ~C-p~ + keystrokes followed by ~C-m~. + +*** Key bindings for multiple selections and actions, keep minibuffer open +:PROPERTIES: +:CUSTOM_ID: key-bindings-for-multiple-selections-and-actions-keep-minibuffer-open +:END: + +For repeatedly applying multiple actions or acting on multiple +candidates, Ivy does not close the minibuffer between commands. It +keeps the minibuffer open for applying subsequent actions. + +Adding an extra meta key to the normal key chord invokes the special +version of the regular commands that enables applying multiple +actions. + +- ~C-M-m~ (=ivy-call=) :: + Is the non-exiting version of ~C-m~ (=ivy-done=). + + Instead of closing the minibuffer, ~C-M-m~ allows selecting + another candidate or another action. For example, ~C-M-m~ on + functions list invokes =describe-function=. When combined with + ~C-n~, function descriptions can be invoked quickly in + succession. + +- ~C-M-o~ (=ivy-dispatching-call=) :: + Is the non-exiting version of ~M-o~ (=ivy-dispatching-done=). + + For example, during the =counsel-rhythmbox= completion, press + ~C-M-o e~ to en-queue the selected candidate, followed by ~C-n + C-m~ to play the next candidate - the current action reverts to + the default one after ~C-M-o~. + +- ~C-M-n~ (=ivy-next-line-and-call=) :: + Combines ~C-n~ and ~C-M-m~. Moves to next line and applies an action. + + Comes in handy when opening multiple files from + =counsel-find-file=, =counsel-git-grep=, =counsel-ag=, =counsel-rg=, or + =counsel-locate= lists. Just hold ~C-M-n~ for rapid-fire default + action on each successive element of the list. + +- ~C-M-p~ (=ivy-previous-line-and-call=) :: + Combines ~C-p~ and ~C-M-m~. + + Similar to the above except it moves through the list in the + other direction. + +- =ivy-resume= :: + Recalls the state of the completion session just before its last + exit. + + Useful after an accidental ~C-m~ (=ivy-done=). + +*** Key bindings that alter the minibuffer input +:PROPERTIES: +:CUSTOM_ID: key-bindings-that-alter-the-minibuffer-input +:END: + +- ~M-n~ (=ivy-next-history-element=) :: + Cycles forward through the Ivy command history. + + Ivy updates an internal history list after each action. When this + history list is empty, ~M-n~ inserts symbol (or URL) at point + into the minibuffer. + +- ~M-p~ (=ivy-previous-history-element=) :: + Cycles forward through the Ivy command history. + +- ~M-i~ (=ivy-insert-current=) :: + Inserts the current candidate into the minibuffer. + + Useful for copying and renaming files, for example: ~M-i~ to + insert the original file name string, edit it, and then ~C-m~ to + complete the renaming. + +- ~M-j~ (=ivy-yank-word=) :: + Inserts the sub-word at point into the minibuffer. + + This is similar to ~C-s C-w~ with =isearch=. Ivy reserves ~C-w~ + for =kill-region=. See also =ivy-yank-symbol= and + =ivy-yank-char=. + +- ~S-SPC~ (=ivy-restrict-to-matches=) :: + Deletes the current input, and resets the candidates list to the + currently restricted matches. + + This is how Ivy provides narrowing in successive tiers. + +- ~C-r~ (=ivy-reverse-i-search=) :: + Starts a recursive completion session through the command's + history. + + This works just like ~C-r~ at the bash command prompt, where the + completion candidates are the history items. Upon completion, the + selected candidate string is inserted into the minibuffer. + +*** Other key bindings +:PROPERTIES: +:CUSTOM_ID: other-key-bindings +:END: + +- ~M-w~ (=ivy-kill-ring-save=) :: + Copies selected candidates to the kill ring. + + Copies the region if the region is active. + +*** Hydra in the minibuffer +:PROPERTIES: +:CUSTOM_ID: hydra-in-the-minibuffer +:END: + +- ~C-o~ (=hydra-ivy/body=) :: + Invokes the hydra menu with short key bindings. + +When Hydra is active, minibuffer editing is disabled and menus +display short aliases: + +| Short | Normal | Command name | +|-------+---------+-------------------------| +| ~o~ | ~C-g~ | =keyboard-escape-quit= | +| ~j~ | ~C-n~ | =ivy-next-line= | +| ~k~ | ~C-p~ | =ivy-previous-line= | +| ~h~ | ~M-<~ | =ivy-beginning-of-buffer= | +| ~l~ | ~M->~ | =ivy-end-of-buffer= | +| ~d~ | ~C-m~ | =ivy-done= | +| ~f~ | ~C-j~ | =ivy-alt-done= | +| ~g~ | ~C-M-m~ | =ivy-call= | +| ~u~ | ~C-c C-o~ | =ivy-occur= | + +Hydra reduces key strokes, for example: ~C-n C-n C-n C-n~ is ~C-o +jjjj~ in Hydra. + +Hydra menu offers these additional bindings: + +- ~c~ (=ivy-toggle-calling=) :: + Toggle calling the action after each candidate change. It + modifies ~j~ to ~jg~, ~k~ to ~kg~ etc. + +- ~m~ (=ivy-rotate-preferred-builders=) :: + Rotate the current regexp matcher. + +- ~>~ (=ivy-minibuffer-grow=) :: + Increase =ivy-height= for the current minibuffer. + +- ~<~ (=ivy-minibuffer-shrink=) :: + Decrease =ivy-height= for the current minibuffer. + +- ~w~ (=ivy-prev-action=) :: + Select the previous action. + +- ~s~ (=ivy-next-action=) :: + Select the next action. + +- ~a~ (=ivy-read-action=) :: + Use a menu to select an action. + +- ~C~ (=ivy-toggle-case-fold=) :: + Toggle case folding (match both upper and lower case + characters for lower case input). + +Hydra menu also offers bindings for marking multiple candidates: + +| Key | Command name | +|-----+---------------------| +| ~m~ | =ivy-mark= | +| ~u~ | =ivy-unmark= | +| ~DEL~ | =ivy-unmark-backward= | +| ~t~ | =ivy-toggle-marks= | + +The action is called on each marked candidate one by one. + +*** Saving the current completion session to a buffer +:PROPERTIES: +:CUSTOM_ID: saving-the-current-completion-session-to-a-buffer +:END: + +- ~C-c C-o~ (=ivy-occur=) :: + Saves the current candidates to a new buffer and exits + completion. + +The new buffer is read-only and has a few useful bindings defined. + +- ~RET~ or ~f~ (=ivy-occur-press=) :: + Call the current action on the selected candidate. + +- ~mouse-1~ (=ivy-occur-click=) :: + Call the current action on the selected candidate. + +- ~j~ (=next-line=) :: + Move to next line. + +- ~k~ (=previous-line=) :: + Move to previous line. + +- ~a~ (=ivy-occur-read-action=) :: + Read an action and make it current for this buffer. + +- ~o~ (=ivy-occur-dispatch=) :: + Read an action and call it on the selected candidate. + +- ~q~ (=quit-window=) :: + Bury the current buffer. + + +Ivy has no limit on the number of active buffers like these. + +Ivy takes care of naming buffers uniquely by constructing descriptive +names. For example: =*ivy-occur counsel-describe-variable +"function$*=. + +* Completion Styles +:PROPERTIES: +:CUSTOM_ID: completion-styles +:END: + +Ivy's completion functions rely on a regex builder - a function that +transforms a string input to a string regex. All current candidates +simply have to match this regex. Each collection can be assigned its +own regex builder by customizing =ivy-re-builders-alist=. + +The keys of this alist are collection names, and the values are one of +the following: +- =ivy--regex= +- =ivy--regex-plus= +- =ivy--regex-ignore-order= +- =ivy--regex-fuzzy= +- =regexp-quote= + +A catch-all key, =t=, applies to all collections that don't have their +own key. + +The default is: + +#+begin_src elisp +(setq ivy-re-builders-alist + '((t . ivy--regex-plus))) +#+end_src + +This example shows a custom regex builder assigned to file name +completion: + +#+begin_src elisp +(setq ivy-re-builders-alist + '((read-file-name-internal . ivy--regex-fuzzy) + (t . ivy--regex-plus))) +#+end_src + +Here, =read-file-name-internal= is a function that is passed as the +second argument to =completing-read= for file name completion. + +The regex builder resolves as follows (in order of priority): +1. =re-builder= argument passed to =ivy-read=. +2. =collection= argument passed to =ivy-read= is a function and has an + entry on =ivy-re-builders-alist=. +3. =caller= argument passed to =ivy-read= has an entry on + =ivy-re-builders-alist=. +4. =this-command= has an entry on =ivy-re-builders-alist=. +5. =t= has an entry on =ivy-re-builders-alist=. +6. =ivy--regex=. + +** ivy--regex-plus +:PROPERTIES: +:CUSTOM_ID: ivy--regex-plus +:END: + +=ivy--regex-plus= is Ivy's default completion method. + +=ivy--regex-plus= matches by splitting the input by spaces and +rebuilding it into a regex. + +As the search string is typed in Ivy's minibuffer, it is transformed +into valid regex syntax. If the string is ="for example"=, it is +transformed into + +#+begin_src elisp +"\\(for\\).*\\(example\\)" +#+end_src + +which in regex terminology matches ="for"= followed by a wild card and +then ="example"=. Note how Ivy uses the space character to build wild +cards. To match a literal white space, use an extra space. So to match +one space type two spaces, to match two spaces type three spaces, and +so on. + +As Ivy transforms typed characters into regex strings, it provides an +intuitive feedback through font highlights. + +Ivy supports regexp negation with ="!"=. +For example, ="define key ! ivy quit"= first selects everything +matching ="define.*key"=, then removes everything matching ="ivy"=, +and finally removes everything matching ="quit"=. What remains is the +final result set of the negation regexp. + +Since Ivy treats minibuffer input as a regexp, the standard regexp +identifiers work: ="^"=, ="$"=, ="\b"= or ="[a-z]"=. The exceptions +are spaces, which translate to =".*"=, and ="!"= that signal the +beginning of a negation group. + +** ivy--regex-ignore-order +:PROPERTIES: +:CUSTOM_ID: ivy--regex-ignore-order +:END: + +=ivy--regex-ignore-order= ignores the order of regexp tokens when +searching for matching candidates. For instance, the input +="for example"= will match ="example test for"=. + +** ivy--regex-fuzzy +:PROPERTIES: +:CUSTOM_ID: ivy--regex-fuzzy +:END: + +=ivy--regex-fuzzy= splits each character with a wild card. Searching +for ="for"= returns all ="f.*o.*r"= matches, resulting in a large +number of hits. Yet some searches need these extra hits. Ivy sorts +such large lists using =flx= package's scoring mechanism, if it's +installed. + +~C-o m~ toggles the current regexp builder. + +* Customization +:PROPERTIES: +:CUSTOM_ID: customization +:END: +** Faces +:PROPERTIES: +:CUSTOM_ID: faces +:END: +- =ivy-current-match= :: + Highlights the currently selected candidate. +- =ivy-minibuffer-match-face-1= :: + Highlights the background of the match. +- =ivy-minibuffer-match-face-2= :: + Highlights the first (modulo 3) matched group. +- =ivy-minibuffer-match-face-3= :: + Highlights the second (modulo 3) matched group. +- =ivy-minibuffer-match-face-4= :: + Highlights the third (modulo 3) matched group. +- =ivy-confirm-face= :: + Highlights the "(confirm)" part of the prompt. + + When =confirm-nonexistent-file-or-buffer= set to =t=, then + confirming non-existent files in =ivy-mode= requires an + additional ~RET~. + + The confirmation prompt will use this face. + + For example: + + #+begin_src elisp + (setq confirm-nonexistent-file-or-buffer t) + #+end_src + + Then call =find-file=, enter "eldorado" and press ~RET~ - the + prompt will be appended with "(confirm)". Press ~RET~ once more + to confirm, or any key to continue the completion. +- =ivy-match-required-face= :: + Highlights the "(match required)" part of the prompt. + + When completions have to match available candidates and cannot + take random input, the "(match required)" prompt signals this + constraint. + + For example, call =describe-variable=, enter "waldo" and press + ~RET~ - "(match required)" is prompted. + Press any key for the prompt to disappear. +- =ivy-subdir= :: + Highlights directories when completing file names. +- =ivy-remote= :: + Highlights remote files when completing file names. +- =ivy-virtual= :: + Highlights virtual buffers when completing buffer names. + + Virtual buffers correspond to bookmarks and recent files list, + =recentf=. + + Enable virtual buffers with: + + #+begin_src elisp + (setq ivy-use-virtual-buffers t) + #+end_src + +- =ivy-modified-buffer= :: + Highlights modified buffers when switching buffer. +- =ivy-modified-outside-buffer= :: + Highlights buffers modified outside Emacs when switching buffer. + + This takes precedence over =ivy-modified-buffer=. + +** Defcustoms +:PROPERTIES: +:CUSTOM_ID: defcustoms +:END: +- User Option =ivy-count-format= :: + A string that specifies display of number of candidates and + current candidate, if one exists. + + The number of matching candidates by default is shown as a right- + padded integer value. + + To disable showing the number of candidates: + + #+begin_src elisp + (setq ivy-count-format "") + #+end_src + + To also display the current candidate: + + #+begin_src elisp + (setq ivy-count-format "(%d/%d) ") + #+end_src + + The =format=-style switches this variable uses are described + in the =format= documentation. + +- User Option =ivy-display-style= :: + Specifies highlighting candidates in the minibuffer. + + The default setting is ='fancy= in Emacs versions 24.4 or newer. + + Set =ivy-display-style= to =nil= for a plain minibuffer. + +- User Option =ivy-on-del-error-function= :: + Specifies what to do when ~DEL~ (=ivy-backward-delete-char=) fails. + + This is usually the case when there is no text left to delete, + i.e., when ~DEL~ is typed at the beginning of the minibuffer. + + The default behavior is to quit the completion after ~DEL~ -- a + handy key to invoke after mistakenly triggering a completion. + +** Actions +:PROPERTIES: +:CUSTOM_ID: actions +:END: +*** What are actions? +:PROPERTIES: +:CUSTOM_ID: what-are-actions +:END: +An action is a function that is called after you select a candidate +during completion. This function takes a single string argument, which +is the selected candidate. + +- Window context when calling an action :: + Currently, the action is executed in the minibuffer window + context. This means e.g. that if you call =insert= the text will + be inserted into the minibuffer. + + If you want to execute the action in the initial window from + which the completion started, use the =with-ivy-window= wrapper + macro. + + #+begin_src elisp + (defun ivy-insert-action (x) + (with-ivy-window + (insert x))) + #+end_src + +*** How can different actions be called? +:PROPERTIES: +:CUSTOM_ID: how-can-different-actions-be-called +:END: +- ~C-m~ (=ivy-done=) calls the current action. +- ~M-o~ (=ivy-dispatching-done=) presents available actions for + selection, calls it after selection, and then exits. +- ~C-M-o~ (=ivy-dispatching-call=) presents available actions for + selection, calls it after selection, and then does not exit. + +*** How to modify the actions list? +:PROPERTIES: +:CUSTOM_ID: how-to-modify-the-actions-list +:END: +Currently, you can append any amount of your own actions to the +default list of actions. This can be done either for a specific +command, or for all commands at once. + +Usually, the command has only one default action. The convention is to +use single letters when selecting a command, and the letter ~o~ is +designated for the default command. This way, ~M-o o~ should be always +equivalent to ~C-m~. + +*** Example - add two actions to each command +:PROPERTIES: +:CUSTOM_ID: example---add-two-actions-to-each-command +:END: +The first action inserts the current candidate into the Ivy window - +the window from which =ivy-read= was called. + +The second action copies the current candidate to the kill ring. + +#+begin_src elisp +(defun ivy-yank-action (x) + (kill-new x)) + +(defun ivy-copy-to-buffer-action (x) + (with-ivy-window + (insert x))) + +(ivy-set-actions + t + '(("i" ivy-copy-to-buffer-action "insert") + ("y" ivy-yank-action "yank"))) +#+end_src + +Then in any completion session, ~M-o y~ invokes =ivy-yank-action=, and +~M-o i~ invokes =ivy-copy-to-buffer-action=. + +**** How to undo adding the two actions +:PROPERTIES: +:CUSTOM_ID: how-to-undo-adding-the-two-actions +:END: +Since =ivy-set-actions= modifies the internal dictionary with new +data, set the extra actions list to =nil= by assigning =nil= value to +the =t= key as follows: + +#+begin_src elisp +(ivy-set-actions t nil) +#+end_src + +**** How to add actions to a specific command +:PROPERTIES: +:CUSTOM_ID: how-to-add-actions-to-a-specific-command +:END: +Use the command name as the key: + +#+begin_src elisp +(ivy-set-actions + 'swiper + '(("i" ivy-copy-to-buffer-action "insert") + ("y" ivy-yank-action "yank"))) +#+end_src + +*** Example - define a new command with several actions +:PROPERTIES: +:CUSTOM_ID: example---define-a-new-command-with-several-actions +:END: +#+begin_src elisp +(defun my-action-1 (x) + (message "action-1: %s" x)) + +(defun my-action-2 (x) + (message "action-2: %s" x)) + +(defun my-action-3 (x) + (message "action-3: %s" x)) + +(defun my-command-with-3-actions () + (interactive) + (ivy-read "test: " '("foo" "bar" "baz") + :action '(1 + ("o" my-action-1 "action 1") + ("j" my-action-2 "action 2") + ("k" my-action-3 "action 3")))) +#+end_src + +The number 1 above is the index of the default action. Each +action has its own string description for easy selection. + +**** Test the above function with =ivy-occur= +:PROPERTIES: +:CUSTOM_ID: test-the-above-function-with-ivy-occur +:END: +To examine each action with each candidate in a key-efficient way, try: + +- Call =my-command-with-3-actions= +- Press ~C-c C-o~ to close the completion window and move to an + ivy-occur buffer +- Press ~kkk~ to move to the first candidate, since the point is most + likely at the end of the buffer +- Press ~oo~ to call the first action +- Press ~oj~ and ~ok~ to call the second and the third actions +- Press ~j~ to move to the next candidate +- Press ~oo~, ~oj~, ~ok~ +- Press ~j~ to move to the next candidate +- and so on... + +** Packages +:PROPERTIES: +:CUSTOM_ID: packages +:END: +- =org-mode= :: + =org-mode= versions 8.3.3 or later obey + =completing-read-function= (which =ivy-mode= sets). Try refiling + headings with similar names to appreciate =ivy-mode=. +- =magit= :: + Uses ivy by default if Ivy is installed. +- =find-file-in-project= :: + Uses ivy by default if Ivy is installed. +- =projectile= :: + Projectile requires this setting for ivy completion: + + #+begin_src elisp + (setq projectile-completion-system 'ivy) + #+end_src +- =helm-make= :: + Helm-make requires this setting for ivy completion. + + #+begin_src elisp + (setq helm-make-completion-method 'ivy) + #+end_src + +- automatically integrated packages :: + Ivy re-uses the following packages if they are installed: + =avy=, =amx= or =smex=, =flx=, and =wgrep=. + +* Commands +:PROPERTIES: +:CUSTOM_ID: commands +:END: +** File Name Completion +:PROPERTIES: +:CUSTOM_ID: file-name-completion +:END: +Since file name completion is ubiquitous, Ivy provides extra +bindings that work here: + + +- ~C-j~ (=ivy-alt-done=) :: + On a directory, restarts completion from that directory. + + On a file or =./=, exit completion with the selected candidate. +- ~DEL~ (=ivy-backward-delete-char=) :: + Restart the completion in the parent directory if current input + is empty. +- ~//~ (=self-insert-command=) :: + Switch to the root directory. +- ~~~ (=self-insert-command=) :: + Switch to the home directory. +- ~/~ (=self-insert-command=) :: + If the current input matches an existing directory name exactly, + switch the completion to that directory. +- ~M-r~ (=ivy-toggle-regexp-quote=) :: + Toggle between input as regexp or not. + + Switch to matching literally since file names include =.=, which + is for matching any char in regexp mode. + +- User Option =ivy-extra-directories= :: + Decide if you want to see =../= and =./= during file name + completion. + + Reason to remove: =../= is the same as ~DEL~. + + Reason not to remove: navigate anywhere with only ~C-n~, ~C-p~ + and ~C-j~. + + Likewise, =./= can be removed. + +- History :: + File history works the same with ~M-p~, ~M-n~, and ~C-r~, but + uses a custom code for file name completion that cycles through + files previously opened. It also works with TRAMP files. + +*** Using TRAMP +:PROPERTIES: +:CUSTOM_ID: using-tramp +:END: +- ~~~ (tilde) :: + Move to the home directory. Either the local or the remote one, depending on the + current directory. The boolean option =ivy-magic-tilde= decides whether the binding to + do this is ~~~ or ~~/~. + +- ~//~ (double slash) :: + Move to the root directory. Either the local or the remote one, depending on the + current directory. Here, you can also select a TRAMP connection method, such as =ssh= + or =scpx=. + +- ~/ C-j~ :: + Move the the local root directory. + +- ~~~~ :: + Move to the local home directory. + + +From any directory, with the empty input, inputting =/ssh:= and pressing +~C-j~ (or ~RET~, which is the same thing) completes for host and user +names. + +For =/ssh:user@= input, completes the domain name. + +~C-i~ works in a similar way to the default completion. + +You can also get sudo access for the current directory by inputting +=/sudo::= ~RET~. Using =/sudo:= (i.e. single colon instead of double) will +result in a completion session for the desired user. + +Multi-hopping is possible, although a bit complex. + +- Example : connect to a remote host =cloud= and open a file with =sudo= there :: + - ~C-x C-f~ =/ssh:cloud|sudo:root:/=. + +** Buffer Name Completion +:PROPERTIES: +:CUSTOM_ID: buffer-name-completion +:END: +- User Option =ivy-use-virtual-buffers= :: + When non-nil, add =recentf-mode= and bookmarks to + =ivy-switch-buffer= completion candidates. + + Adding this to Emacs init file: + + #+begin_src elisp + (setq ivy-use-virtual-buffers t) + #+end_src + will add additional virtual buffers to the buffers list for recent + files. Selecting such virtual buffers, which are highlighted with + =ivy-virtual= face, will open the corresponding file. + +** Counsel commands +:PROPERTIES: +:CUSTOM_ID: counsel-commands +:END: +The main advantages of =counsel-= functions over their basic +equivalents in =ivy-mode= are: + +1. Multi-actions and non-exiting actions work. +2. =ivy-resume= can resume the last completion session. +3. Customize =ivy-set-actions=, =ivy-re-builders-alist=. +4. Customize individual keymaps, such as =counsel-describe-map=, + =counsel-git-grep-map=, or =counsel-find-file-map=, instead of + customizing =ivy-minibuffer-map= that applies to all completion + sessions. +* API +:PROPERTIES: +:CUSTOM_ID: api +:END: +The main (and only) entry point is the =ivy-read= function. It takes +two required arguments and many optional arguments that can be passed +by a key. The optional =:action= argument is highly recommended for +features such as multi-actions, non-exiting actions, =ivy-occur= and +=ivy-resume=. + +** Required arguments for =ivy-read= +:PROPERTIES: +:CUSTOM_ID: required-arguments-for-ivy-read +:END: +- =prompt= :: + A prompt string normally ending in a colon and a space. + =ivy-count-format= is prepended to it during completion. + +- =collection= :: + Either a list of strings, a function, an alist or a hash table. + + If a function, then it has to be compatible with + =all-completions=. + +** Optional arguments for =ivy-read= +:PROPERTIES: +:CUSTOM_ID: optional-arguments-for-ivy-read +:END: +- =predicate= :: + Is a function to filter the initial collection. It has to be + compatible with =all-completions=. Tip: most of the time, it's + simpler to just apply this filter to the =collection= argument + itself, e.g. =(cl-remove-if-not predicate collection)=. +- =require-match= :: + When set to a non-nil value, input must match one of the + candidates. Custom input is not accepted. +- =initial-input= :: + This string argument is included for compatibility with + =completing-read=, which inserts it into the minibuffer. + + It's recommended to use the =preselect= argument instead of this. +- =history= :: + Name of the symbol to store history. See =completing-read=. +- =preselect= :: + Determines which one of the candidates to initially select. + + When set to an integer value, select the candidate with that + index value. + + When set to any other non-nil value, select the first candidate + matching this value. Comparison is first done with =equal=. + If this fails, and when applicable, match =preselect= as a + regular expression. + + Every time the input becomes empty, the item corresponding to + =preselect= is selected. +- =keymap= :: + A keymap to be composed with =ivy-minibuffer-map=. This keymap + has priority over =ivy-minibuffer-map= and can be modified at any + later stage. +- =update-fn= :: + Is the function called each time the current candidate changes. + This function takes no arguments and is called in the + minibuffer's =post-command-hook=. See =swiper= for an example + usage. +- =sort= :: + When non-nil, use =ivy-sort-functions-alist= to sort the + collection as long as the collection is not larger than + =ivy-sort-max-size=. +- =action= :: + Is the function to call after selection. It takes a string + argument. +- =unwind= :: + Is the function to call before exiting completion. It takes no + arguments. This function is called even if the completion is + interrupted with ~C-g~. See =swiper= for an example usage. +- =re-builder= :: + Is a function that takes a string and returns a valid regex. See + =Completion Styles= for details. +- =matcher= :: + Is a function that takes a regex string and a list of strings and + returns a list of strings matching the regex. Any ordinary Emacs + matching function will suffice, yet finely tuned matching + functions can be used. See =counsel-find-file= for an example + usage. +- =dynamic-collection= :: + When non-nil, =collection= will be used to dynamically generate + the candidates each time the input changes, instead of being used + once statically with =all-completions= to generate a list of + strings. See =counsel-locate= for an example usage. +- =caller= :: + Is a symbol that uniquely identifies the function that called + =ivy-read=, which may be useful for further customizations. +** Example - =counsel-describe-function= +:PROPERTIES: +:CUSTOM_ID: example---counsel-describe-function +:END: +This is a typical example of a function with a non-async collection, +which is a collection where all the strings in the collection are +known prior to any input from the user. + +Only the first two arguments (along with =action=) are essential - the +rest of the arguments are for fine-tuning, and could be omitted. + +The =action= argument could also be omitted - but then =ivy-read= +would do nothing except returning the string result, which you could +later use yourself. However, it's recommended that you use the +=action= argument. + +#+begin_src elisp +(defun counsel-describe-function () + "Forward to `describe-function'." + (interactive) + (ivy-read "Describe function: " + (let (cands) + (mapatoms + (lambda (x) + (when (fboundp x) + (push (symbol-name x) cands)))) + cands) + :keymap counsel-describe-map + :preselect (ivy-thing-at-point) + :history 'counsel-describe-symbol-history + :require-match t + :action (lambda (x) + (describe-function + (intern x))) + :caller 'counsel-describe-function)) +#+end_src + +Here are the interesting features of the above function, in the order that they appear: + +- The =prompt= argument is a simple string ending in ": ". +- The =collection= argument evaluates to a (large) list of strings. +- The =keymap= argument is for a custom keymap to supplement =ivy-minibuffer-map=. +- The =preselect= is provided by =ivy-thing-at-point=, which + returns a symbol near the point. Ivy then selects the first + candidate from the collection that matches this symbol. To select + this pre-selected candidate, a ~RET~ will suffice. No further user + input is necessary. +- The =history= argument is for keeping the history of this command + separate from the common history in =ivy-history=. +- The =require-match= is set to =t= since it doesn't make sense to + call =describe-function= on an un-interned symbol. +- The =action= argument calls =describe-function= on the interned + selected candidate. +- The =caller= argument identifies this completion session. This is + important, since with the collection being a list of strings and not + a function name, the only other way for =ivy-read= to identify + "who's calling" and to apply the appropriate customizations is to + examine =this-command=. But =this-command= would be modified if + another command called =counsel-describe-function=. +** Example - =counsel-locate= +:PROPERTIES: +:CUSTOM_ID: example---counsel-locate +:END: +This is a typical example of a function with an async collection. +Since the collection function cannot pre-compute all the locatable +files in memory within reasonable limits (time or memory), it relies +on user input to filter the universe of possible candidates to a +manageable size while also continuing to search asynchronously for +possible candidates. Both the filtering and searching continues with +each character change of the input with rapid updates to the +collection presented without idle waiting times. This live update will +continue as long as there are likely candidates. Eventually updates to +the minibuffer will stop after user input, filtering, and searching +have exhausted looking for possible candidates. + +Async collections suit long-running shell commands, such as =locate=. +With each new input, a new process starts while the old process is +killed. The collection is refreshed anew with each new process. +Meanwhile the user can provide more input characters (for further +narrowing) or select a candidate from the visible collection. + +#+begin_src elisp +(defun counsel-locate-function (str) + (or + (ivy-more-chars) + (progn + (counsel--async-command + (format "locate %s '%s'" + (mapconcat #'identity counsel-locate-options " ") + (counsel--elisp-to-pcre + (ivy--regex str)))) + '("" "working...")))) + +;;;###autoload +(defun counsel-locate (&optional initial-input) + "Call the \"locate\" shell command. +INITIAL-INPUT can be given as the initial minibuffer input." + (interactive) + (ivy-read "Locate: " #'counsel-locate-function + :initial-input initial-input + :dynamic-collection t + :history 'counsel-locate-history + :action (lambda (file) + (with-ivy-window + (when file + (find-file file)))) + :unwind #'counsel-delete-process + :caller 'counsel-locate)) +#+end_src + +Here are the interesting features of the above functions, in the order +that they appear: + +- =counsel-locate-function= takes a string argument and returns a list + of strings. Note that it's not compatible with =all-completions=, + but since we're not using that here, might as well use one argument + instead of three. +- =ivy-more-chars= is a simple function that returns e.g. + ='("2 chars more")= asking the user for more input. +- =counsel--async-command= is a very easy API simplification that + takes a single string argument suitable for + =shell-command-to-string=. So you could prototype your function as + non-async using =shell-command-to-string= and =split-string= to + produce a collection, then decide that you want async and simply swap in + =counsel--async-command=. +- =counsel-locate= is an interactive function with an optional =initial-input=. +- =#'counsel-locate-function= is passed as the =collection= argument. +- =dynamic-collection= is set to t, since this is an async collection. +- =action= argument uses =with-ivy-window= wrapper, since we want to open the + selected file in the same window from which =counsel-locate= was + called. +- =unwind= argument is set to =#'counsel-delete-process=: when we press ~C-g~ + we want to kill the running process created by + =counsel--async-command=. +- =caller= argument identifies this command for easier customization. +** Example - =ivy-read-with-extra-properties= +:PROPERTIES: +:CUSTOM_ID: example---ivy-read-with-extra-properties +:END: +This is another example to show how to associate additional values to each +displayed strings. + +#+BEGIN_SRC elisp +(defun find-candidates-function (str pred _) + (let ((props '(1 2)) + (strs '("foo" "foo2"))) + (cl-mapcar (lambda (s p) (propertize s 'property p)) + strs + props))) + +(defun find-candidates () + (interactive) + (ivy-read "Find symbols: " + #'find-candidates-function + :action (lambda (x) + (message "Value: %s" (get-text-property 0 'property x) + )))) +#+END_SRC + +Here are the interesting features of the above function: + +- =find-candidates-function= builds up a list of strings and associates "foo" with + the value 1 and "foo2" with 2. +- =find-candidates= is an interactive function. +- =#'find-candidates= is passed as the =collection= argument. +- =action= gets passed the selected string with the associated value. It + then retrieves that value and displays it. + +* Variable Index +:PROPERTIES: +:INDEX: vr +:CUSTOM_ID: variable-index +:END: + +* Keystroke Index +:PROPERTIES: +:CUSTOM_ID: key-index +:INDEX: ky +:END: diff -Nru emacs-ivy-0.12.0+dfsg/doc/ivy.texi emacs-ivy-0.13.0/doc/ivy.texi --- emacs-ivy-0.12.0+dfsg/doc/ivy.texi 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/doc/ivy.texi 2019-10-16 16:57:42.000000000 +0000 @@ -0,0 +1,1813 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setfilename ivy.info +@settitle Ivy User Manual +@documentencoding UTF-8 +@documentlanguage en +@c %**end of header + +@copying +@ifnottex +Ivy manual, version 0.13.0 + +Ivy is an interactive interface for completion in Emacs. Emacs uses +completion mechanism in a variety of contexts: code, menus, commands, +variables, functions, etc. Completion entails listing, sorting, +filtering, previewing, and applying actions on selected items. When +active, @code{ivy-mode} completes the selection process by narrowing +available choices while previewing in the minibuffer. Selecting the +final candidate is either through simple keyboard character inputs or +through powerful regular expressions. +@end ifnottex + +Copyright (C) 2015-2019 Free Software Foundation, Inc. + +@quotation +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is included in the section entitled "GNU +Free Documentation License". +@end quotation +@end copying + +@dircategory Emacs +@direntry +* Ivy: (ivy). Using Ivy for completion. +@end direntry + +@finalout +@titlepage +@title Ivy User Manual +@author Oleh Krehel +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@ifnottex +@node Top +@top Ivy User Manual +@end ifnottex + +@menu +* Introduction:: +* Installation:: +* Getting started:: +* Key bindings:: +* Completion Styles:: +* Customization:: +* Commands:: +* API:: +* Variable Index:: +* Keystroke Index:: + +@detailmenu +--- The Detailed Node Listing --- + +Installation + +* Installing from Emacs Package Manager:: +* Installing from the Git repository:: + +Getting started + +* Basic customization:: + +Key bindings + +* Global key bindings:: +* Minibuffer key bindings:: + +Minibuffer key bindings + +* Key bindings for navigation:: +* Key bindings for single selection, action, then exit minibuffer: Key bindings for single selection action then exit minibuffer. +* Key bindings for multiple selections and actions, keep minibuffer open: Key bindings for multiple selections and actions keep minibuffer open. +* Key bindings that alter the minibuffer input:: +* Other key bindings:: +* Hydra in the minibuffer:: +* Saving the current completion session to a buffer:: + +Completion Styles + +* ivy--regex-plus:: +* ivy--regex-ignore-order:: +* ivy--regex-fuzzy:: + +Customization + +* Faces:: +* Defcustoms:: +* Actions:: +* Packages:: + +Actions + +* What are actions?:: +* How can different actions be called?:: +* How to modify the actions list?:: +* Example - add two actions to each command:: +* Example - define a new command with several actions:: + +Example - add two actions to each command + +* How to undo adding the two actions:: +* How to add actions to a specific command:: + +Example - define a new command with several actions + +* Test the above function with @code{ivy-occur}:: + +Commands + +* File Name Completion:: +* Buffer Name Completion:: +* Counsel commands:: + +File Name Completion + +* Using TRAMP:: + +API + +* Required arguments for @code{ivy-read}:: +* Optional arguments for @code{ivy-read}:: +* Example - @code{counsel-describe-function}:: +* Example - @code{counsel-locate}:: +* Example - @code{ivy-read-with-extra-properties}:: + +@end detailmenu +@end menu + +@node Introduction +@chapter Introduction + +Ivy is for quick and easy selection from a list. When Emacs prompts +for a string from a list of several possible choices, Ivy springs into +action to assist in narrowing and picking the right string from a vast +number of choices. + +Ivy strives for minimalism, simplicity, customizability and +discoverability. + +@subsubheading Minimalism +@indentedblock +Uncluttered minibuffer is minimalism. Ivy shows the completion +defaults, the number of matches, and 10 candidate matches below +the input line. Customize @code{ivy-height} to adjust the number of +candidate matches displayed in the minibuffer. +@end indentedblock +@subsubheading Simplicity +@indentedblock +Simplicity is about Ivy's behavior in the minibuffer. It is also +about the code interface to extend Ivy's functionality. The +minibuffer area behaves as close to @code{fundamental-mode} as +possible. @kbd{SPC} inserts a space, for example, instead of being +bound to the more complex @code{minibuffer-complete-word}. Ivy's code +uses easy-to-examine global variables; avoids needless +complications with branch-introducing custom macros. +@end indentedblock +@subsubheading Customizability +@indentedblock +Customizability is about being able to use different methods and +interfaces of completion to tailor the selection process. For +example, adding a custom display function that points to a +selected candidate with @code{>}, instead of highlighting the selected +candidate with the @code{ivy-current-match} face (see +@code{ivy-format-functions-alist}). Or take the customization of actions, say +after the candidate function is selected. @kbd{RET} uses +@code{counsel-describe-function} to describe the function, whereas +@kbd{M-o d} jumps to that function's definition in the code. The +@kbd{M-o} prefix can be uniformly used with characters like @kbd{d} to +group similar actions. +@end indentedblock +@subsubheading Discoverability +@indentedblock +Ivy displays easily discoverable commands through the hydra +facility. @kbd{C-o} in the minibuffer displays a hydra menu. It +opens up within an expanded minibuffer area. Each menu item comes +with short documentation strings and highlighted one-key +completions. So discovering even seldom used keys is simply a +matter of @kbd{C-o} in the minibuffer while in the midst of the Ivy +interaction. This discoverability minimizes exiting Ivy interface +for documentation look-ups. +@end indentedblock + +@node Installation +@chapter Installation + +Install Ivy automatically through Emacs's package manager, or manually +from Ivy's development repository. + +Emacs 24.3 is the oldest version to run Ivy. Emacs 24.4 is the oldest +version that runs Ivy with fancy faces display. + +@menu +* Installing from Emacs Package Manager:: +* Installing from the Git repository:: +@end menu + +@node Installing from Emacs Package Manager +@section Installing from Emacs Package Manager + +@kbd{M-x} @code{package-install} @kbd{RET} @code{ivy} @kbd{RET} + +Ivy is installed as part of @code{ivy} package, which is available from two +different package archives, GNU ELPA and MELPA. For the latest stable +version, use the GNU ELPA archives using the above M-x command. + +For current hourly builds, use the MELPA archives. In MELPA, Ivy is +split into three packages: @code{ivy}, @code{swiper} and @code{counsel}; you can simply +install @code{counsel} which will bring in the other two as dependencies. +See the code below for adding MELPA to the list of package archives: + +@lisp +(require 'package) +(add-to-list 'package-archives + '("melpa" . "https://melpa.org/packages/")) +@end lisp + +After this do @kbd{M-x} @code{package-refresh-contents} @kbd{RET}, followed by @kbd{M-x} +@code{package-install} @kbd{RET} @code{counsel} @kbd{RET}. + +For package manager details, see @ref{Packages,,,emacs,}. + +@node Installing from the Git repository +@section Installing from the Git repository + +@subsubheading Why install from Git? +@indentedblock +@itemize +@item +No need to wait for MELPA's hourly builds +@item +Easy to revert to previous versions +@item +Contribute to Ivy's development; send patches; pull requests +@end itemize +@end indentedblock + + +@subsubheading Configuration steps +@indentedblock +First clone the Swiper repository with: + +@example +cd ~/git && git clone https://github.com/abo-abo/swiper +cd swiper && make compile +@end example + +Second, add these lines to the Emacs init file: + +@lisp +(add-to-list 'load-path "~/git/swiper/") +(require 'ivy) +@end lisp + +Then, update the code with: + +@example +git pull +make +@end example +@end indentedblock + +@node Getting started +@chapter Getting started + +First enable Ivy completion everywhere: + +@lisp +(ivy-mode 1) +@end lisp + +Note: @code{ivy-mode} can be toggled on and off with @kbd{M-x} @code{ivy-mode}. + +@menu +* Basic customization:: +@end menu + +@node Basic customization +@section Basic customization + +Here are some basic settings particularly useful for new Ivy users: + +@lisp +(setq ivy-use-virtual-buffers t) +(setq ivy-count-format "(%d/%d) ") +@end lisp + +If you want, you can go without any customizations at all. The above +settings are the most bang for the buck in terms of customization. So +users that typically don't like customize a lot are advised to look at +these settings first. + +For more advanced customizations, refer to @code{M-x describe-variable} +documentation. + +@node Key bindings +@chapter Key bindings + +@menu +* Global key bindings:: +* Minibuffer key bindings:: +@end menu + +@node Global key bindings +@section Global key bindings + +Here is a list of commands that are useful to be bound globally, along +with some sample bindings: + +@subsubheading Ivy-based interface to standard commands +@indentedblock +@lisp +(global-set-key (kbd "C-s") 'swiper-isearch) +(global-set-key (kbd "M-x") 'counsel-M-x) +(global-set-key (kbd "C-x C-f") 'counsel-find-file) +(global-set-key (kbd "M-y") 'counsel-yank-pop) +(global-set-key (kbd " f") 'counsel-describe-function) +(global-set-key (kbd " v") 'counsel-describe-variable) +(global-set-key (kbd " l") 'counsel-find-library) +(global-set-key (kbd " i") 'counsel-info-lookup-symbol) +(global-set-key (kbd " u") 'counsel-unicode-char) +(global-set-key (kbd " j") 'counsel-set-variable) +(global-set-key (kbd "C-x b") 'ivy-switch-buffer) +(global-set-key (kbd "C-c v") 'ivy-push-view) +(global-set-key (kbd "C-c V") 'ivy-pop-view) +@end lisp +@end indentedblock +@subsubheading Ivy-based interface to shell and system tools +@indentedblock +@lisp +(global-set-key (kbd "C-c c") 'counsel-compile) +(global-set-key (kbd "C-c g") 'counsel-git) +(global-set-key (kbd "C-c j") 'counsel-git-grep) +(global-set-key (kbd "C-c L") 'counsel-git-log) +(global-set-key (kbd "C-c k") 'counsel-rg) +(global-set-key (kbd "C-c m") 'counsel-linux-app) +(global-set-key (kbd "C-c n") 'counsel-fzf) +(global-set-key (kbd "C-x l") 'counsel-locate) +(global-set-key (kbd "C-c J") 'counsel-file-jump) +(global-set-key (kbd "C-S-o") 'counsel-rhythmbox) +(global-set-key (kbd "C-c w") 'counsel-wmctrl) +@end lisp +@end indentedblock +@subsubheading Ivy-resume and other commands +@indentedblock +@code{ivy-resume} resumes the last Ivy-based completion. + +@lisp +(global-set-key (kbd "C-c C-r") 'ivy-resume) +(global-set-key (kbd "C-c b") 'counsel-bookmark) +(global-set-key (kbd "C-c d") 'counsel-descbinds) +(global-set-key (kbd "C-c g") 'counsel-git) +(global-set-key (kbd "C-c o") 'counsel-outline) +(global-set-key (kbd "C-c t") 'counsel-load-theme) +(global-set-key (kbd "C-c F") 'counsel-org-file) +@end lisp +@end indentedblock + +You can also enable @code{counsel-mode} to make some global key binding remapping for you. + +@node Minibuffer key bindings +@section Minibuffer key bindings + +@vindex ivy-minibuffer-map +Ivy includes several minibuffer bindings, which are defined in the +@code{ivy-minibuffer-map} keymap variable. The most frequently used ones +are described here. + +@code{swiper} or @code{counsel-M-x} add more key bindings through the @code{keymap} +argument to @code{ivy-read}. These keys, also active in the minibuffer, are +described under their respective commands. + +A key feature of @code{ivy-minibuffer-map} is its full editing capability +where the familiar @kbd{C-a}, @kbd{C-f}, @kbd{M-d}, @kbd{M-DEL}, @kbd{M-b}, @kbd{M-w}, @kbd{C-k}, +@kbd{C-y} key bindings work the same as in @code{fundamental-mode}. + +@menu +* Key bindings for navigation:: +* Key bindings for single selection, action, then exit minibuffer: Key bindings for single selection action then exit minibuffer. +* Key bindings for multiple selections and actions, keep minibuffer open: Key bindings for multiple selections and actions keep minibuffer open. +* Key bindings that alter the minibuffer input:: +* Other key bindings:: +* Hydra in the minibuffer:: +* Saving the current completion session to a buffer:: +@end menu + +@node Key bindings for navigation +@subsection Key bindings for navigation + +@itemize +@item +@kbd{C-n} (@code{ivy-next-line}) selects the next candidate +@item +@kbd{C-p} (@code{ivy-previous-line}) selects the previous candidate +@item +@kbd{M-<} (@code{ivy-beginning-of-buffer}) selects the first candidate +@item +@kbd{M->} (@code{ivy-end-of-buffer}) selects the last candidate +@item +@kbd{C-v} (@code{ivy-scroll-up-command}) scrolls up by @code{ivy-height} lines +@item +@kbd{M-v} (@code{ivy-scroll-down-command}) scrolls down by @code{ivy-height} lines +@end itemize + + +@defopt ivy-wrap +Specifies the wrap-around behavior for @kbd{C-n} and @kbd{C-p}. When +@code{ivy-wrap} is set to @code{t}, @code{ivy-next-line} and @code{ivy-previous-line} +will cycle past the last and the first candidates respectively. + +Wrap-around behavior is off by default. +@end defopt + +@defopt ivy-height +Use this option to adjust the minibuffer height, which also +affects scroll size when using @kbd{C-v} and @kbd{M-v} key bindings. + +@code{ivy-height} is 10 lines by default. +@end defopt + +@node Key bindings for single selection action then exit minibuffer +@subsection Key bindings for single selection, action, then exit minibuffer + +Ivy can offer several actions from which to choose which action to +run. This "calling an action" operates on the selected candidate. For +example, when viewing a list of files, one action could open it for +editing, one to view it, another to invoke a special function, and so +on. Custom actions can be added to this interface. The precise action +to call on the selected candidate can be delayed until after the +narrowing is completed. No need to exit the interface if unsure which +action to run. This delayed flexibility and customization of actions +extends usability of lists in Emacs. + +@subsubheading @kbd{C-m} or @kbd{RET} (@code{ivy-done}) +@vindex ivy-done +@kindex C-m +@kindex RET +@indentedblock +Calls the default action and then exits the minibuffer. +@end indentedblock +@subsubheading @kbd{M-o} (@code{ivy-dispatching-done}) +@vindex ivy-dispatching-done +@kindex M-o +@indentedblock +Presents valid actions from which to choose. When only one action +is available, there is no difference between @kbd{M-o} and @kbd{C-m}. +@end indentedblock +@subsubheading @kbd{C-j} (@code{ivy-alt-done}) +@vindex ivy-alt-done +@kindex C-j +@indentedblock +When completing file names, selects the current directory +candidate and starts a new completion session there. Otherwise, +it is the same as @code{ivy-done}. +@end indentedblock +@subsubheading @kbd{TAB} (@code{ivy-partial-or-done}) +@vindex ivy-partial-or-done +@kindex TAB +@indentedblock +Attempts partial completion, extending current input as much as +possible. @kbd{TAB TAB} is the same as @kbd{C-j} (@code{ivy-alt-done}). + +Example ERT test: + +@lisp +(should + (equal (ivy-with + '(progn + (ivy-read "Test: " '("can do" "can't, sorry" "other")) + ivy-text) + "c ") + "can")) +@end lisp +@end indentedblock +@subsubheading @kbd{C-M-j} (@code{ivy-immediate-done}) +@vindex ivy-immediate-done +@kindex C-M-j +@indentedblock +Exits with @emph{the current input} instead of @emph{the current candidate} +(like other commands). + +This is useful e.g. when you call @code{find-file} to create a new +file, but the desired name matches an existing file. In that +case, using @kbd{C-j} would select that existing file, which isn't +what you want - use this command instead. +@end indentedblock +@subsubheading @kbd{C-'} (@code{ivy-avy}) +@vindex ivy-avy +@kindex C-' +@indentedblock +Uses avy to select one of the candidates on the current candidate +page. This can often be faster than multiple @kbd{C-n} or @kbd{C-p} +keystrokes followed by @kbd{C-m}. +@end indentedblock + +@node Key bindings for multiple selections and actions keep minibuffer open +@subsection Key bindings for multiple selections and actions, keep minibuffer open + +For repeatedly applying multiple actions or acting on multiple +candidates, Ivy does not close the minibuffer between commands. It +keeps the minibuffer open for applying subsequent actions. + +Adding an extra meta key to the normal key chord invokes the special +version of the regular commands that enables applying multiple +actions. + +@subsubheading @kbd{C-M-m} (@code{ivy-call}) +@vindex ivy-call +@kindex C-M-m +@indentedblock +Is the non-exiting version of @kbd{C-m} (@code{ivy-done}). + +Instead of closing the minibuffer, @kbd{C-M-m} allows selecting +another candidate or another action. For example, @kbd{C-M-m} on +functions list invokes @code{describe-function}. When combined with +@kbd{C-n}, function descriptions can be invoked quickly in +succession. +@end indentedblock +@subsubheading @kbd{C-M-o} (@code{ivy-dispatching-call}) +@vindex ivy-dispatching-call +@kindex C-M-o +@indentedblock +Is the non-exiting version of @kbd{M-o} (@code{ivy-dispatching-done}). + +For example, during the @code{counsel-rhythmbox} completion, press +@kbd{C-M-o e} to en-queue the selected candidate, followed by @kbd{C-n + C-m} to play the next candidate - the current action reverts to +the default one after @kbd{C-M-o}. +@end indentedblock +@subsubheading @kbd{C-M-n} (@code{ivy-next-line-and-call}) +@vindex ivy-next-line-and-call +@kindex C-M-n +@indentedblock +Combines @kbd{C-n} and @kbd{C-M-m}. Moves to next line and applies an action. + +Comes in handy when opening multiple files from +@code{counsel-find-file}, @code{counsel-git-grep}, @code{counsel-ag}, @code{counsel-rg}, or +@code{counsel-locate} lists. Just hold @kbd{C-M-n} for rapid-fire default +action on each successive element of the list. +@end indentedblock +@subsubheading @kbd{C-M-p} (@code{ivy-previous-line-and-call}) +@vindex ivy-previous-line-and-call +@kindex C-M-p +@indentedblock +Combines @kbd{C-p} and @kbd{C-M-m}. + +Similar to the above except it moves through the list in the +other direction. +@end indentedblock +@subsubheading @code{ivy-resume} +@vindex ivy-resume +@indentedblock +Recalls the state of the completion session just before its last +exit. + +Useful after an accidental @kbd{C-m} (@code{ivy-done}). +@end indentedblock + +@node Key bindings that alter the minibuffer input +@subsection Key bindings that alter the minibuffer input + +@subsubheading @kbd{M-n} (@code{ivy-next-history-element}) +@vindex ivy-next-history-element +@kindex M-n +@indentedblock +Cycles forward through the Ivy command history. + +Ivy updates an internal history list after each action. When this +history list is empty, @kbd{M-n} inserts symbol (or URL) at point +into the minibuffer. +@end indentedblock +@subsubheading @kbd{M-p} (@code{ivy-previous-history-element}) +@vindex ivy-previous-history-element +@kindex M-p +@indentedblock +Cycles forward through the Ivy command history. +@end indentedblock +@subsubheading @kbd{M-i} (@code{ivy-insert-current}) +@vindex ivy-insert-current +@kindex M-i +@indentedblock +Inserts the current candidate into the minibuffer. + +Useful for copying and renaming files, for example: @kbd{M-i} to +insert the original file name string, edit it, and then @kbd{C-m} to +complete the renaming. +@end indentedblock +@subsubheading @kbd{M-j} (@code{ivy-yank-word}) +@vindex ivy-yank-word +@kindex M-j +@indentedblock +Inserts the sub-word at point into the minibuffer. + +This is similar to @kbd{C-s C-w} with @code{isearch}. Ivy reserves @kbd{C-w} +for @code{kill-region}. See also @code{ivy-yank-symbol} and +@code{ivy-yank-char}. +@end indentedblock +@subsubheading @kbd{S-SPC} (@code{ivy-restrict-to-matches}) +@vindex ivy-restrict-to-matches +@kindex S-SPC +@indentedblock +Deletes the current input, and resets the candidates list to the +currently restricted matches. + +This is how Ivy provides narrowing in successive tiers. +@end indentedblock +@subsubheading @kbd{C-r} (@code{ivy-reverse-i-search}) +@vindex ivy-reverse-i-search +@kindex C-r +@indentedblock +Starts a recursive completion session through the command's +history. + +This works just like @kbd{C-r} at the bash command prompt, where the +completion candidates are the history items. Upon completion, the +selected candidate string is inserted into the minibuffer. +@end indentedblock + +@node Other key bindings +@subsection Other key bindings + +@subsubheading @kbd{M-w} (@code{ivy-kill-ring-save}) +@vindex ivy-kill-ring-save +@kindex M-w +@indentedblock +Copies selected candidates to the kill ring. + +Copies the region if the region is active. +@end indentedblock + +@node Hydra in the minibuffer +@subsection Hydra in the minibuffer + +@subsubheading @kbd{C-o} (@code{hydra-ivy/body}) +@kindex C-o +@indentedblock +Invokes the hydra menu with short key bindings. +@end indentedblock + +When Hydra is active, minibuffer editing is disabled and menus +display short aliases: + +@multitable {aaaaa} {aaaaaaaaa} {aaaaaaaaaaaaaaaaaaaaaaaaa} +@headitem Short +@tab Normal +@tab Command name +@item @kbd{o} +@tab @kbd{C-g} +@tab @code{keyboard-escape-quit} +@item @kbd{j} +@tab @kbd{C-n} +@tab @code{ivy-next-line} +@item @kbd{k} +@tab @kbd{C-p} +@tab @code{ivy-previous-line} +@item @kbd{h} +@tab @kbd{M-<} +@tab @code{ivy-beginning-of-buffer} +@item @kbd{l} +@tab @kbd{M->} +@tab @code{ivy-end-of-buffer} +@item @kbd{d} +@tab @kbd{C-m} +@tab @code{ivy-done} +@item @kbd{f} +@tab @kbd{C-j} +@tab @code{ivy-alt-done} +@item @kbd{g} +@tab @kbd{C-M-m} +@tab @code{ivy-call} +@item @kbd{u} +@tab @kbd{C-c C-o} +@tab @code{ivy-occur} +@end multitable + +Hydra reduces key strokes, for example: @kbd{C-n C-n C-n C-n} is @kbd{C-o +jjjj} in Hydra. + +Hydra menu offers these additional bindings: + +@subsubheading @kbd{c} (@code{ivy-toggle-calling}) +@vindex ivy-toggle-calling +@kindex c +@indentedblock +Toggle calling the action after each candidate change. It +modifies @kbd{j} to @kbd{jg}, @kbd{k} to @kbd{kg} etc. +@end indentedblock +@subsubheading @kbd{m} (@code{ivy-rotate-preferred-builders}) +@vindex ivy-rotate-preferred-builders +@kindex m +@indentedblock +Rotate the current regexp matcher. +@end indentedblock +@subsubheading @kbd{>} (@code{ivy-minibuffer-grow}) +@vindex ivy-minibuffer-grow +@kindex > +@indentedblock +Increase @code{ivy-height} for the current minibuffer. +@end indentedblock +@subsubheading @kbd{<} (@code{ivy-minibuffer-shrink}) +@vindex ivy-minibuffer-shrink +@kindex < +@indentedblock +Decrease @code{ivy-height} for the current minibuffer. +@end indentedblock +@subsubheading @kbd{w} (@code{ivy-prev-action}) +@vindex ivy-prev-action +@kindex w +@indentedblock +Select the previous action. +@end indentedblock +@subsubheading @kbd{s} (@code{ivy-next-action}) +@vindex ivy-next-action +@kindex s +@indentedblock +Select the next action. +@end indentedblock +@subsubheading @kbd{a} (@code{ivy-read-action}) +@vindex ivy-read-action +@kindex a +@indentedblock +Use a menu to select an action. +@end indentedblock +@subsubheading @kbd{C} (@code{ivy-toggle-case-fold}) +@vindex ivy-toggle-case-fold +@kindex C +@indentedblock +Toggle case folding (match both upper and lower case +characters for lower case input). +@end indentedblock + +Hydra menu also offers bindings for marking multiple candidates: + +@multitable {aaaaa} {aaaaaaaaaaaaaaaaaaaaa} +@headitem Key +@tab Command name +@item @kbd{m} +@tab @code{ivy-mark} +@item @kbd{u} +@tab @code{ivy-unmark} +@item @kbd{DEL} +@tab @code{ivy-unmark-backward} +@item @kbd{t} +@tab @code{ivy-toggle-marks} +@end multitable + +The action is called on each marked candidate one by one. + +@node Saving the current completion session to a buffer +@subsection Saving the current completion session to a buffer + +@subsubheading @kbd{C-c C-o} (@code{ivy-occur}) +@vindex ivy-occur +@kindex C-c C-o +@indentedblock +Saves the current candidates to a new buffer and exits +completion. +@end indentedblock + +The new buffer is read-only and has a few useful bindings defined. + +@subsubheading @kbd{RET} or @kbd{f} (@code{ivy-occur-press}) +@vindex ivy-occur-press +@kindex RET +@kindex f +@indentedblock +Call the current action on the selected candidate. +@end indentedblock +@subsubheading @kbd{mouse-1} (@code{ivy-occur-click}) +@vindex ivy-occur-click +@kindex mouse-1 +@indentedblock +Call the current action on the selected candidate. +@end indentedblock +@subsubheading @kbd{j} (@code{next-line}) +@kindex j +@indentedblock +Move to next line. +@end indentedblock +@subsubheading @kbd{k} (@code{previous-line}) +@kindex k +@indentedblock +Move to previous line. +@end indentedblock +@subsubheading @kbd{a} (@code{ivy-occur-read-action}) +@vindex ivy-occur-read-action +@kindex a +@indentedblock +Read an action and make it current for this buffer. +@end indentedblock +@subsubheading @kbd{o} (@code{ivy-occur-dispatch}) +@vindex ivy-occur-dispatch +@kindex o +@indentedblock +Read an action and call it on the selected candidate. +@end indentedblock +@subsubheading @kbd{q} (@code{quit-window}) +@kindex q +@indentedblock +Bury the current buffer. +@end indentedblock + + +Ivy has no limit on the number of active buffers like these. + +Ivy takes care of naming buffers uniquely by constructing descriptive +names. For example: @code{*ivy-occur counsel-describe-variable +"function$*}. + +@node Completion Styles +@chapter Completion Styles + +Ivy's completion functions rely on a regex builder - a function that +transforms a string input to a string regex. All current candidates +simply have to match this regex. Each collection can be assigned its +own regex builder by customizing @code{ivy-re-builders-alist}. + +The keys of this alist are collection names, and the values are one of +the following: +@itemize +@item +@code{ivy--regex} +@item +@code{ivy--regex-plus} +@item +@code{ivy--regex-ignore-order} +@item +@code{ivy--regex-fuzzy} +@item +@code{regexp-quote} +@end itemize + +A catch-all key, @code{t}, applies to all collections that don't have their +own key. + +The default is: + +@lisp +(setq ivy-re-builders-alist + '((t . ivy--regex-plus))) +@end lisp + +This example shows a custom regex builder assigned to file name +completion: + +@lisp +(setq ivy-re-builders-alist + '((read-file-name-internal . ivy--regex-fuzzy) + (t . ivy--regex-plus))) +@end lisp + +Here, @code{read-file-name-internal} is a function that is passed as the +second argument to @code{completing-read} for file name completion. + +The regex builder resolves as follows (in order of priority): +@enumerate +@item +@code{re-builder} argument passed to @code{ivy-read}. +@item +@code{collection} argument passed to @code{ivy-read} is a function and has an +entry on @code{ivy-re-builders-alist}. +@item +@code{caller} argument passed to @code{ivy-read} has an entry on +@code{ivy-re-builders-alist}. +@item +@code{this-command} has an entry on @code{ivy-re-builders-alist}. +@item +@code{t} has an entry on @code{ivy-re-builders-alist}. +@item +@code{ivy--regex}. +@end enumerate + +@menu +* ivy--regex-plus:: +* ivy--regex-ignore-order:: +* ivy--regex-fuzzy:: +@end menu + +@node ivy--regex-plus +@section ivy--regex-plus + +@code{ivy--regex-plus} is Ivy's default completion method. + +@code{ivy--regex-plus} matches by splitting the input by spaces and +rebuilding it into a regex. + +As the search string is typed in Ivy's minibuffer, it is transformed +into valid regex syntax. If the string is @code{"for example"}, it is +transformed into + +@lisp +"\\(for\\).*\\(example\\)" +@end lisp + +which in regex terminology matches @code{"for"} followed by a wild card and +then @code{"example"}. Note how Ivy uses the space character to build wild +cards. To match a literal white space, use an extra space. So to match +one space type two spaces, to match two spaces type three spaces, and +so on. + +As Ivy transforms typed characters into regex strings, it provides an +intuitive feedback through font highlights. + +Ivy supports regexp negation with @code{"!"}. +For example, @code{"define key ! ivy quit"} first selects everything +matching @code{"define.*key"}, then removes everything matching @code{"ivy"}, +and finally removes everything matching @code{"quit"}. What remains is the +final result set of the negation regexp. + +Since Ivy treats minibuffer input as a regexp, the standard regexp +identifiers work: @code{"^"}, @code{"$"}, @code{"\b"} or @code{"[a-z]"}. The exceptions +are spaces, which translate to @code{".*"}, and @code{"!"} that signal the +beginning of a negation group. + +@node ivy--regex-ignore-order +@section ivy--regex-ignore-order + +@code{ivy--regex-ignore-order} ignores the order of regexp tokens when +searching for matching candidates. For instance, the input +@code{"for example"} will match @code{"example test for"}. + +@node ivy--regex-fuzzy +@section ivy--regex-fuzzy + +@code{ivy--regex-fuzzy} splits each character with a wild card. Searching +for @code{"for"} returns all @code{"f.*o.*r"} matches, resulting in a large +number of hits. Yet some searches need these extra hits. Ivy sorts +such large lists using @code{flx} package's scoring mechanism, if it's +installed. + +@kbd{C-o m} toggles the current regexp builder. + +@node Customization +@chapter Customization + +@menu +* Faces:: +* Defcustoms:: +* Actions:: +* Packages:: +@end menu + +@node Faces +@section Faces + +@subsubheading @code{ivy-current-match} +@vindex ivy-current-match +@indentedblock +Highlights the currently selected candidate. +@end indentedblock +@subsubheading @code{ivy-minibuffer-match-face-1} +@vindex ivy-minibuffer-match-face-1 +@indentedblock +Highlights the background of the match. +@end indentedblock +@subsubheading @code{ivy-minibuffer-match-face-2} +@vindex ivy-minibuffer-match-face-2 +@indentedblock +Highlights the first (modulo 3) matched group. +@end indentedblock +@subsubheading @code{ivy-minibuffer-match-face-3} +@vindex ivy-minibuffer-match-face-3 +@indentedblock +Highlights the second (modulo 3) matched group. +@end indentedblock +@subsubheading @code{ivy-minibuffer-match-face-4} +@vindex ivy-minibuffer-match-face-4 +@indentedblock +Highlights the third (modulo 3) matched group. +@end indentedblock +@subsubheading @code{ivy-confirm-face} +@vindex ivy-confirm-face +@indentedblock +Highlights the "(confirm)" part of the prompt. + +When @code{confirm-nonexistent-file-or-buffer} set to @code{t}, then +confirming non-existent files in @code{ivy-mode} requires an +additional @kbd{RET}. + +The confirmation prompt will use this face. + +For example: + +@lisp +(setq confirm-nonexistent-file-or-buffer t) +@end lisp + +Then call @code{find-file}, enter "eldorado" and press @kbd{RET} - the +prompt will be appended with "(confirm)". Press @kbd{RET} once more +to confirm, or any key to continue the completion. +@end indentedblock +@subsubheading @code{ivy-match-required-face} +@vindex ivy-match-required-face +@indentedblock +Highlights the "(match required)" part of the prompt. + +When completions have to match available candidates and cannot +take random input, the "(match required)" prompt signals this +constraint. + +For example, call @code{describe-variable}, enter "waldo" and press +@kbd{RET} - "(match required)" is prompted. +Press any key for the prompt to disappear. +@end indentedblock +@subsubheading @code{ivy-subdir} +@vindex ivy-subdir +@indentedblock +Highlights directories when completing file names. +@end indentedblock +@subsubheading @code{ivy-remote} +@vindex ivy-remote +@indentedblock +Highlights remote files when completing file names. +@end indentedblock +@subsubheading @code{ivy-virtual} +@vindex ivy-virtual +@indentedblock +Highlights virtual buffers when completing buffer names. + +Virtual buffers correspond to bookmarks and recent files list, +@code{recentf}. + +Enable virtual buffers with: + +@lisp +(setq ivy-use-virtual-buffers t) +@end lisp +@end indentedblock +@subsubheading @code{ivy-modified-buffer} +@vindex ivy-modified-buffer +@indentedblock +Highlights modified buffers when switching buffer. +@end indentedblock +@subsubheading @code{ivy-modified-outside-buffer} +@vindex ivy-modified-outside-buffer +@indentedblock +Highlights buffers modified outside Emacs when switching buffer. + +This takes precedence over @code{ivy-modified-buffer}. +@end indentedblock + +@node Defcustoms +@section Defcustoms + +@defopt ivy-count-format +A string that specifies display of number of candidates and +current candidate, if one exists. + +The number of matching candidates by default is shown as a right- +padded integer value. + +To disable showing the number of candidates: + +@lisp +(setq ivy-count-format "") +@end lisp + +To also display the current candidate: + +@lisp +(setq ivy-count-format "(%d/%d) ") +@end lisp + +The @code{format}-style switches this variable uses are described +in the @code{format} documentation. +@end defopt + +@defopt ivy-display-style +Specifies highlighting candidates in the minibuffer. + +The default setting is @code{'fancy} in Emacs versions 24.4 or newer. + +Set @code{ivy-display-style} to @code{nil} for a plain minibuffer. +@end defopt + +@defopt ivy-on-del-error-function +Specifies what to do when @kbd{DEL} (@code{ivy-backward-delete-char}) fails. + +This is usually the case when there is no text left to delete, +i.e., when @kbd{DEL} is typed at the beginning of the minibuffer. + +The default behavior is to quit the completion after @kbd{DEL} -- a +handy key to invoke after mistakenly triggering a completion. +@end defopt + +@node Actions +@section Actions + +@menu +* What are actions?:: +* How can different actions be called?:: +* How to modify the actions list?:: +* Example - add two actions to each command:: +* Example - define a new command with several actions:: +@end menu + +@node What are actions? +@subsection What are actions? + +An action is a function that is called after you select a candidate +during completion. This function takes a single string argument, which +is the selected candidate. + +@subsubheading Window context when calling an action +@indentedblock +Currently, the action is executed in the minibuffer window +context. This means e.g. that if you call @code{insert} the text will +be inserted into the minibuffer. + +If you want to execute the action in the initial window from +which the completion started, use the @code{with-ivy-window} wrapper +macro. + +@lisp +(defun ivy-insert-action (x) + (with-ivy-window + (insert x))) +@end lisp +@end indentedblock + +@node How can different actions be called? +@subsection How can different actions be called? + +@itemize +@item +@kbd{C-m} (@code{ivy-done}) calls the current action. +@item +@kbd{M-o} (@code{ivy-dispatching-done}) presents available actions for +selection, calls it after selection, and then exits. +@item +@kbd{C-M-o} (@code{ivy-dispatching-call}) presents available actions for +selection, calls it after selection, and then does not exit. +@end itemize + +@node How to modify the actions list? +@subsection How to modify the actions list? + +Currently, you can append any amount of your own actions to the +default list of actions. This can be done either for a specific +command, or for all commands at once. + +Usually, the command has only one default action. The convention is to +use single letters when selecting a command, and the letter @kbd{o} is +designated for the default command. This way, @kbd{M-o o} should be always +equivalent to @kbd{C-m}. + +@node Example - add two actions to each command +@subsection Example - add two actions to each command + +The first action inserts the current candidate into the Ivy window - +the window from which @code{ivy-read} was called. + +The second action copies the current candidate to the kill ring. + +@lisp +(defun ivy-yank-action (x) + (kill-new x)) + +(defun ivy-copy-to-buffer-action (x) + (with-ivy-window + (insert x))) + +(ivy-set-actions + t + '(("i" ivy-copy-to-buffer-action "insert") + ("y" ivy-yank-action "yank"))) +@end lisp + +Then in any completion session, @kbd{M-o y} invokes @code{ivy-yank-action}, and +@kbd{M-o i} invokes @code{ivy-copy-to-buffer-action}. + +@menu +* How to undo adding the two actions:: +* How to add actions to a specific command:: +@end menu + +@node How to undo adding the two actions +@subsubsection How to undo adding the two actions + +Since @code{ivy-set-actions} modifies the internal dictionary with new +data, set the extra actions list to @code{nil} by assigning @code{nil} value to +the @code{t} key as follows: + +@lisp +(ivy-set-actions t nil) +@end lisp + +@node How to add actions to a specific command +@subsubsection How to add actions to a specific command + +Use the command name as the key: + +@lisp +(ivy-set-actions + 'swiper + '(("i" ivy-copy-to-buffer-action "insert") + ("y" ivy-yank-action "yank"))) +@end lisp + +@node Example - define a new command with several actions +@subsection Example - define a new command with several actions + +@lisp +(defun my-action-1 (x) + (message "action-1: %s" x)) + +(defun my-action-2 (x) + (message "action-2: %s" x)) + +(defun my-action-3 (x) + (message "action-3: %s" x)) + +(defun my-command-with-3-actions () + (interactive) + (ivy-read "test: " '("foo" "bar" "baz") + :action '(1 + ("o" my-action-1 "action 1") + ("j" my-action-2 "action 2") + ("k" my-action-3 "action 3")))) +@end lisp + +The number 1 above is the index of the default action. Each +action has its own string description for easy selection. + +@menu +* Test the above function with @code{ivy-occur}:: +@end menu + +@node Test the above function with @code{ivy-occur} +@subsubsection Test the above function with @code{ivy-occur} + +To examine each action with each candidate in a key-efficient way, try: + +@itemize +@item +Call @code{my-command-with-3-actions} +@item +Press @kbd{C-c C-o} to close the completion window and move to an +ivy-occur buffer +@item +Press @kbd{kkk} to move to the first candidate, since the point is most +likely at the end of the buffer +@item +Press @kbd{oo} to call the first action +@item +Press @kbd{oj} and @kbd{ok} to call the second and the third actions +@item +Press @kbd{j} to move to the next candidate +@item +Press @kbd{oo}, @kbd{oj}, @kbd{ok} +@item +Press @kbd{j} to move to the next candidate +@item +and so on@dots{} +@end itemize + +@node Packages +@section Packages + +@subsubheading @code{org-mode} +@indentedblock +@code{org-mode} versions 8.3.3 or later obey +@code{completing-read-function} (which @code{ivy-mode} sets). Try refiling +headings with similar names to appreciate @code{ivy-mode}. +@end indentedblock +@subsubheading @code{magit} +@indentedblock +Uses ivy by default if Ivy is installed. +@end indentedblock +@subsubheading @code{find-file-in-project} +@indentedblock +Uses ivy by default if Ivy is installed. +@end indentedblock +@subsubheading @code{projectile} +@indentedblock +Projectile requires this setting for ivy completion: + +@lisp +(setq projectile-completion-system 'ivy) +@end lisp +@end indentedblock +@subsubheading @code{helm-make} +@indentedblock +Helm-make requires this setting for ivy completion. + +@lisp +(setq helm-make-completion-method 'ivy) +@end lisp +@end indentedblock +@subsubheading automatically integrated packages +@indentedblock +Ivy re-uses the following packages if they are installed: +@code{avy}, @code{amx} or @code{smex}, @code{flx}, and @code{wgrep}. +@end indentedblock + +@node Commands +@chapter Commands + +@menu +* File Name Completion:: +* Buffer Name Completion:: +* Counsel commands:: +@end menu + +@node File Name Completion +@section File Name Completion + +Since file name completion is ubiquitous, Ivy provides extra +bindings that work here: + + +@subsubheading @kbd{C-j} (@code{ivy-alt-done}) +@vindex ivy-alt-done +@kindex C-j +@indentedblock +On a directory, restarts completion from that directory. + +On a file or @code{./}, exit completion with the selected candidate. +@end indentedblock +@subsubheading @kbd{DEL} (@code{ivy-backward-delete-char}) +@vindex ivy-backward-delete-char +@kindex DEL +@indentedblock +Restart the completion in the parent directory if current input +is empty. +@end indentedblock +@subsubheading @kbd{//} (@code{self-insert-command}) +@kindex // +@indentedblock +Switch to the root directory. +@end indentedblock +@subsubheading @kbd{~} (@code{self-insert-command}) +@kindex ~ +@indentedblock +Switch to the home directory. +@end indentedblock +@subsubheading @kbd{/} (@code{self-insert-command}) +@kindex / +@indentedblock +If the current input matches an existing directory name exactly, +switch the completion to that directory. +@end indentedblock +@subsubheading @kbd{M-r} (@code{ivy-toggle-regexp-quote}) +@vindex ivy-toggle-regexp-quote +@kindex M-r +@indentedblock +Toggle between input as regexp or not. + +Switch to matching literally since file names include @code{.}, which +is for matching any char in regexp mode. +@end indentedblock +@defopt ivy-extra-directories +Decide if you want to see @code{../} and @code{./} during file name +completion. + +Reason to remove: @code{../} is the same as @kbd{DEL}. + +Reason not to remove: navigate anywhere with only @kbd{C-n}, @kbd{C-p} +and @kbd{C-j}. + +Likewise, @code{./} can be removed. +@end defopt + +@subsubheading History +@indentedblock +File history works the same with @kbd{M-p}, @kbd{M-n}, and @kbd{C-r}, but +uses a custom code for file name completion that cycles through +files previously opened. It also works with TRAMP files. +@end indentedblock + +@menu +* Using TRAMP:: +@end menu + +@node Using TRAMP +@subsection Using TRAMP + +@subsubheading @kbd{~} (tilde) +@kindex ~ +@indentedblock +Move to the home directory. Either the local or the remote one, depending on the +current directory. The boolean option @code{ivy-magic-tilde} decides whether the binding to +do this is @kbd{~} or @kbd{~/}. +@end indentedblock +@subsubheading @kbd{//} (double slash) +@kindex // +@indentedblock +Move to the root directory. Either the local or the remote one, depending on the +current directory. Here, you can also select a TRAMP connection method, such as @code{ssh} +or @code{scpx}. +@end indentedblock +@subsubheading @kbd{/ C-j} +@kindex / C-j +@indentedblock +Move the the local root directory. +@end indentedblock +@subsubheading @kbd{~~} +@kindex ~~ +@indentedblock +Move to the local home directory. +@end indentedblock + + +From any directory, with the empty input, inputting @code{/ssh:} and pressing +@kbd{C-j} (or @kbd{RET}, which is the same thing) completes for host and user +names. + +For @code{/ssh:user@@} input, completes the domain name. + +@kbd{C-i} works in a similar way to the default completion. + +You can also get sudo access for the current directory by inputting +@code{/sudo::} @kbd{RET}. Using @code{/sudo:} (i.e. single colon instead of double) will +result in a completion session for the desired user. + +Multi-hopping is possible, although a bit complex. + +@subsubheading Example : connect to a remote host @code{cloud} and open a file with @code{sudo} there +@indentedblock +@itemize +@item +@kbd{C-x C-f} @code{/ssh:cloud|sudo:root:/}. +@end itemize +@end indentedblock + +@node Buffer Name Completion +@section Buffer Name Completion + +@defopt ivy-use-virtual-buffers +When non-nil, add @code{recentf-mode} and bookmarks to +@code{ivy-switch-buffer} completion candidates. + +Adding this to Emacs init file: + +@lisp +(setq ivy-use-virtual-buffers t) +@end lisp +will add additional virtual buffers to the buffers list for recent +files. Selecting such virtual buffers, which are highlighted with +@code{ivy-virtual} face, will open the corresponding file. +@end defopt + +@node Counsel commands +@section Counsel commands + +The main advantages of @code{counsel-} functions over their basic +equivalents in @code{ivy-mode} are: + +@enumerate +@item +Multi-actions and non-exiting actions work. +@item +@code{ivy-resume} can resume the last completion session. +@item +Customize @code{ivy-set-actions}, @code{ivy-re-builders-alist}. +@item +Customize individual keymaps, such as @code{counsel-describe-map}, +@code{counsel-git-grep-map}, or @code{counsel-find-file-map}, instead of +customizing @code{ivy-minibuffer-map} that applies to all completion +sessions. +@end enumerate + +@node API +@chapter API + +The main (and only) entry point is the @code{ivy-read} function. It takes +two required arguments and many optional arguments that can be passed +by a key. The optional @code{:action} argument is highly recommended for +features such as multi-actions, non-exiting actions, @code{ivy-occur} and +@code{ivy-resume}. + +@menu +* Required arguments for @code{ivy-read}:: +* Optional arguments for @code{ivy-read}:: +* Example - @code{counsel-describe-function}:: +* Example - @code{counsel-locate}:: +* Example - @code{ivy-read-with-extra-properties}:: +@end menu + +@node Required arguments for @code{ivy-read} +@section Required arguments for @code{ivy-read} + +@subsubheading @code{prompt} +@indentedblock +A prompt string normally ending in a colon and a space. +@code{ivy-count-format} is prepended to it during completion. +@end indentedblock +@subsubheading @code{collection} +@indentedblock +Either a list of strings, a function, an alist or a hash table. + +If a function, then it has to be compatible with +@code{all-completions}. +@end indentedblock + +@node Optional arguments for @code{ivy-read} +@section Optional arguments for @code{ivy-read} + +@subsubheading @code{predicate} +@indentedblock +Is a function to filter the initial collection. It has to be +compatible with @code{all-completions}. Tip: most of the time, it's +simpler to just apply this filter to the @code{collection} argument +itself, e.g. @code{(cl-remove-if-not predicate collection)}. +@end indentedblock +@subsubheading @code{require-match} +@indentedblock +When set to a non-nil value, input must match one of the +candidates. Custom input is not accepted. +@end indentedblock +@subsubheading @code{initial-input} +@indentedblock +This string argument is included for compatibility with +@code{completing-read}, which inserts it into the minibuffer. + +It's recommended to use the @code{preselect} argument instead of this. +@end indentedblock +@subsubheading @code{history} +@indentedblock +Name of the symbol to store history. See @code{completing-read}. +@end indentedblock +@subsubheading @code{preselect} +@indentedblock +Determines which one of the candidates to initially select. + +When set to an integer value, select the candidate with that +index value. + +When set to any other non-nil value, select the first candidate +matching this value. Comparison is first done with @code{equal}. +If this fails, and when applicable, match @code{preselect} as a +regular expression. + +Every time the input becomes empty, the item corresponding to +@code{preselect} is selected. +@end indentedblock +@subsubheading @code{keymap} +@indentedblock +A keymap to be composed with @code{ivy-minibuffer-map}. This keymap +has priority over @code{ivy-minibuffer-map} and can be modified at any +later stage. +@end indentedblock +@subsubheading @code{update-fn} +@indentedblock +Is the function called each time the current candidate changes. +This function takes no arguments and is called in the +minibuffer's @code{post-command-hook}. See @code{swiper} for an example +usage. +@end indentedblock +@subsubheading @code{sort} +@indentedblock +When non-nil, use @code{ivy-sort-functions-alist} to sort the +collection as long as the collection is not larger than +@code{ivy-sort-max-size}. +@end indentedblock +@subsubheading @code{action} +@indentedblock +Is the function to call after selection. It takes a string +argument. +@end indentedblock +@subsubheading @code{unwind} +@indentedblock +Is the function to call before exiting completion. It takes no +arguments. This function is called even if the completion is +interrupted with @kbd{C-g}. See @code{swiper} for an example usage. +@end indentedblock +@subsubheading @code{re-builder} +@indentedblock +Is a function that takes a string and returns a valid regex. See +@code{Completion Styles} for details. +@end indentedblock +@subsubheading @code{matcher} +@indentedblock +Is a function that takes a regex string and a list of strings and +returns a list of strings matching the regex. Any ordinary Emacs +matching function will suffice, yet finely tuned matching +functions can be used. See @code{counsel-find-file} for an example +usage. +@end indentedblock +@subsubheading @code{dynamic-collection} +@indentedblock +When non-nil, @code{collection} will be used to dynamically generate +the candidates each time the input changes, instead of being used +once statically with @code{all-completions} to generate a list of +strings. See @code{counsel-locate} for an example usage. +@end indentedblock +@subsubheading @code{caller} +@indentedblock +Is a symbol that uniquely identifies the function that called +@code{ivy-read}, which may be useful for further customizations. +@end indentedblock + +@node Example - @code{counsel-describe-function} +@section Example - @code{counsel-describe-function} + +This is a typical example of a function with a non-async collection, +which is a collection where all the strings in the collection are +known prior to any input from the user. + +Only the first two arguments (along with @code{action}) are essential - the +rest of the arguments are for fine-tuning, and could be omitted. + +The @code{action} argument could also be omitted - but then @code{ivy-read} +would do nothing except returning the string result, which you could +later use yourself. However, it's recommended that you use the +@code{action} argument. + +@lisp +(defun counsel-describe-function () + "Forward to `describe-function'." + (interactive) + (ivy-read "Describe function: " + (let (cands) + (mapatoms + (lambda (x) + (when (fboundp x) + (push (symbol-name x) cands)))) + cands) + :keymap counsel-describe-map + :preselect (ivy-thing-at-point) + :history 'counsel-describe-symbol-history + :require-match t + :action (lambda (x) + (describe-function + (intern x))) + :caller 'counsel-describe-function)) +@end lisp + +Here are the interesting features of the above function, in the order that they appear: + +@itemize +@item +The @code{prompt} argument is a simple string ending in ": ". +@item +The @code{collection} argument evaluates to a (large) list of strings. +@item +The @code{keymap} argument is for a custom keymap to supplement @code{ivy-minibuffer-map}. +@item +The @code{preselect} is provided by @code{ivy-thing-at-point}, which +returns a symbol near the point. Ivy then selects the first +candidate from the collection that matches this symbol. To select +this pre-selected candidate, a @kbd{RET} will suffice. No further user +input is necessary. +@item +The @code{history} argument is for keeping the history of this command +separate from the common history in @code{ivy-history}. +@item +The @code{require-match} is set to @code{t} since it doesn't make sense to +call @code{describe-function} on an un-interned symbol. +@item +The @code{action} argument calls @code{describe-function} on the interned +selected candidate. +@item +The @code{caller} argument identifies this completion session. This is +important, since with the collection being a list of strings and not +a function name, the only other way for @code{ivy-read} to identify +"who's calling" and to apply the appropriate customizations is to +examine @code{this-command}. But @code{this-command} would be modified if +another command called @code{counsel-describe-function}. +@end itemize + +@node Example - @code{counsel-locate} +@section Example - @code{counsel-locate} + +This is a typical example of a function with an async collection. +Since the collection function cannot pre-compute all the locatable +files in memory within reasonable limits (time or memory), it relies +on user input to filter the universe of possible candidates to a +manageable size while also continuing to search asynchronously for +possible candidates. Both the filtering and searching continues with +each character change of the input with rapid updates to the +collection presented without idle waiting times. This live update will +continue as long as there are likely candidates. Eventually updates to +the minibuffer will stop after user input, filtering, and searching +have exhausted looking for possible candidates. + +Async collections suit long-running shell commands, such as @code{locate}. +With each new input, a new process starts while the old process is +killed. The collection is refreshed anew with each new process. +Meanwhile the user can provide more input characters (for further +narrowing) or select a candidate from the visible collection. + +@lisp +(defun counsel-locate-function (str) + (or + (ivy-more-chars) + (progn + (counsel--async-command + (format "locate %s '%s'" + (mapconcat #'identity counsel-locate-options " ") + (counsel--elisp-to-pcre + (ivy--regex str)))) + '("" "working...")))) + +;;;###autoload +(defun counsel-locate (&optional initial-input) + "Call the \"locate\" shell command. +INITIAL-INPUT can be given as the initial minibuffer input." + (interactive) + (ivy-read "Locate: " #'counsel-locate-function + :initial-input initial-input + :dynamic-collection t + :history 'counsel-locate-history + :action (lambda (file) + (with-ivy-window + (when file + (find-file file)))) + :unwind #'counsel-delete-process + :caller 'counsel-locate)) +@end lisp + +Here are the interesting features of the above functions, in the order +that they appear: + +@itemize +@item +@code{counsel-locate-function} takes a string argument and returns a list +of strings. Note that it's not compatible with @code{all-completions}, +but since we're not using that here, might as well use one argument +instead of three. +@item +@code{ivy-more-chars} is a simple function that returns e.g. +@code{'("2 chars more")} asking the user for more input. +@item +@code{counsel--async-command} is a very easy API simplification that +takes a single string argument suitable for +@code{shell-command-to-string}. So you could prototype your function as +non-async using @code{shell-command-to-string} and @code{split-string} to +produce a collection, then decide that you want async and simply swap in +@code{counsel--async-command}. +@item +@code{counsel-locate} is an interactive function with an optional @code{initial-input}. +@item +@code{#'counsel-locate-function} is passed as the @code{collection} argument. +@item +@code{dynamic-collection} is set to t, since this is an async collection. +@item +@code{action} argument uses @code{with-ivy-window} wrapper, since we want to open the +selected file in the same window from which @code{counsel-locate} was +called. +@item +@code{unwind} argument is set to @code{#'counsel-delete-process}: when we press @kbd{C-g} +we want to kill the running process created by +@code{counsel--async-command}. +@item +@code{caller} argument identifies this command for easier customization. +@end itemize + +@node Example - @code{ivy-read-with-extra-properties} +@section Example - @code{ivy-read-with-extra-properties} + +This is another example to show how to associate additional values to each +displayed strings. + +@lisp +(defun find-candidates-function (str pred _) + (let ((props '(1 2)) + (strs '("foo" "foo2"))) + (cl-mapcar (lambda (s p) (propertize s 'property p)) + strs + props))) + +(defun find-candidates () + (interactive) + (ivy-read "Find symbols: " + #'find-candidates-function + :action (lambda (x) + (message "Value: %s" (get-text-property 0 'property x) + )))) +@end lisp + +Here are the interesting features of the above function: + +@itemize +@item +@code{find-candidates-function} builds up a list of strings and associates "foo" with +the value 1 and "foo2" with 2. +@item +@code{find-candidates} is an interactive function. +@item +@code{#'find-candidates} is passed as the @code{collection} argument. +@item +@code{action} gets passed the selected string with the associated value. It +then retrieves that value and displays it. +@end itemize + +@node Variable Index +@unnumbered Variable Index + +@printindex vr + +@node Keystroke Index +@unnumbered Keystroke Index + +@printindex ky + +@bye \ No newline at end of file diff -Nru emacs-ivy-0.12.0+dfsg/doc/Makefile emacs-ivy-0.13.0/doc/Makefile --- emacs-ivy-0.12.0+dfsg/doc/Makefile 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/doc/Makefile 2019-10-16 16:57:42.000000000 +0000 @@ -1,2 +1,11 @@ +INFO_INSTALL_DIR="${HOME}/git/gnu-elpa/packages/ivy" + ivy.texi: ivy.org emacs -batch -l ivy-ox.el -l scripts.el --eval "(org-to-texi \"ivy.org\")" + +ivy.info: ivy.texi + makeinfo --no-split $^ + +install: ivy.info + cp $^ $(INFO_INSTALL_DIR) + install-info --info-dir=$(INFO_INSTALL_DIR) --info-file=$^ diff -Nru emacs-ivy-0.12.0+dfsg/.github/FUNDING.yml emacs-ivy-0.13.0/.github/FUNDING.yml --- emacs-ivy-0.12.0+dfsg/.github/FUNDING.yml 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/.github/FUNDING.yml 2019-10-16 16:57:42.000000000 +0000 @@ -1,2 +1,3 @@ +github: abo-abo liberapay: abo-abo patreon: abo_abo diff -Nru emacs-ivy-0.12.0+dfsg/ivy.el emacs-ivy-0.13.0/ivy.el --- emacs-ivy-0.12.0+dfsg/ivy.el 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/ivy.el 2019-10-16 16:57:42.000000000 +0000 @@ -4,8 +4,8 @@ ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/swiper -;; Version: 0.12.0 -;; Package-Requires: ((emacs "24.1")) +;; Version: 0.13.0 +;; Package-Requires: ((emacs "24.5")) ;; Keywords: matching ;; This file is part of GNU Emacs. @@ -39,7 +39,6 @@ ;;; Code: (require 'cl-lib) -(require 'ffap) (require 'ivy-overlay) (require 'colir) (require 'ring) @@ -179,6 +178,12 @@ (const :tag "Count matches and show current match" "(%d/%d) ") string)) +(defcustom ivy-pre-prompt-function nil + "When non-nil, add strings before the `ivy-read' prompt." + :type '(choice + (const :tag "Do nothing" nil) + (function :tag "Custom function"))) + (defcustom ivy-add-newline-after-prompt nil "When non-nil, add a newline after the `ivy-read' prompt." :type 'boolean) @@ -222,24 +227,15 @@ (const :tag "Current Directory" "./")))) (defcustom ivy-use-virtual-buffers nil - "When non-nil, add recent files and bookmarks to `ivy-switch-buffer'." - :type 'boolean) - -(defvar ivy-display-function nil - "Determine where to display candidates. -When nil (the default), candidates are shown in the minibuffer. -Otherwise, this can be set to a function which takes a string -argument comprising the current matching candidates and displays -it somewhere. - -This user option acts as a global default for Ivy-based -completion commands. You can customize the display function on a -per-command basis via `ivy-display-functions-alist', which see. -See also URL -`https://github.com/abo-abo/swiper/wiki/ivy-display-function'.") - -(make-obsolete-variable - 'ivy-display-function 'ivy-display-functions-alist "<2019-12-05 Mon>") + "When non-nil, add recent files and/or bookmarks to `ivy-switch-buffer'. +The value `recentf' includes only recent files to the virtual +buffers list, whereas the value `bookmarks' does the same for +bookmarks. Any other non-nil value includes both." + :type '(choice + (const :tag "Don't use virtual buffers" nil) + (const :tag "Recent files" recentf) + (const :tag "Bookmarks" bookmarks) + (const :tag "All virtual buffers" t))) (defvar ivy--display-function nil "The display-function is used in current.") @@ -252,14 +248,14 @@ (defcustom ivy-display-functions-alist '((ivy-completion-in-region . ivy-display-function-overlay) (t . nil)) - "An alist for customizing display-function. + "An alist for customizing where to display the candidates. -display-function determine where to display candidates. it takes -a string argument comprising the current matching candidates and -displays it somewhere. +Each key is a caller symbol. When the value is nil (the default), +the candidates are shown in the minibuffer. Otherwise, the value +is a function which takes a string argument comprising the +current matching candidates and displays it somewhere. -When display-function is nil, candidates are shown in the -minibuffer." +See also `https://github.com/abo-abo/swiper/wiki/ivy-display-function'." :type '(alist :key-type symbol :value-type (choice @@ -303,7 +299,7 @@ act as if `ivy-completing-read-handlers-alist' is empty.") (defvar ivy-highlight-grep-commands nil - "List of counsel grep-like commands.") + "List of grep-like commands.") (defvar ivy--actions-list nil "A list of extra actions per command.") @@ -501,7 +497,9 @@ caller current def - multi-action) + ignore + multi-action + extra-props) (defvar ivy-last (make-ivy-state) "The last parameters passed to `ivy-read'. @@ -534,8 +532,7 @@ ((thing-at-point 'url)) ((and (eq (ivy-state-collection ivy-last) #'read-file-name-internal) (let ((inhibit-message t)) - (ignore-errors - (ffap-file-at-point))))) + (run-hook-with-args-until-success 'file-name-at-point-functions)))) ((let ((s (thing-at-point 'symbol))) (and (stringp s) (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s) @@ -665,8 +662,7 @@ "Store the current overriding `case-fold-search'.") (defvar ivy-more-chars-alist - '((counsel-grep . 2) - (t . 3)) + '((t . 3)) "Map commands to their minimum required input length. That is the number of characters prompted for before fetching candidates. The special key t is used as a fallback.") @@ -733,12 +729,13 @@ "Insert TEXT and exit minibuffer." (if (member (ivy-state-prompt ivy-last) '("Create directory: " "Make directory: ")) (ivy-immediate-done) - (insert - (setf (ivy-state-current ivy-last) - (if (and ivy--directory - (not (eq (ivy-state-history ivy-last) 'grep-files-history))) - (expand-file-name text ivy--directory) - text))) + (if (stringp text) + (insert + (setf (ivy-state-current ivy-last) + (if (and ivy--directory + (not (eq (ivy-state-history ivy-last) 'grep-files-history))) + (expand-file-name text ivy--directory) + text)))) (setq ivy-exit 'done) (exit-minibuffer))) @@ -866,6 +863,13 @@ actions "\n"))) +(defcustom ivy-read-action-function #'ivy-read-action-by-key + "Function used to read an action." + :type '(radio + (function-item ivy-read-action-by-key) + (function-item ivy-read-action-ivy) + (function-item ivy-read-action-hydra))) + (defun ivy-read-action () "Change the action to one of the available ones. @@ -875,26 +879,44 @@ (let ((actions (ivy-state-action ivy-last))) (if (not (ivy--actionp actions)) t - (let* ((hint (funcall ivy-read-action-format-function (cdr actions))) - (resize-mini-windows t) - (key "") - action-idx) - (while (and (setq action-idx (cl-position-if - (lambda (x) - (string-prefix-p key (car x))) - (cdr actions))) - (not (string= key (car (nth action-idx (cdr actions)))))) - (setq key (concat key (string (read-key hint))))) - (ivy-shrink-after-dispatching) - (cond ((member key '("" "")) - nil) - ((null action-idx) - (message "%s is not bound" key) - nil) - (t - (message "") - (setcar actions (1+ action-idx)) - (ivy-set-action actions))))))) + (funcall ivy-read-action-function actions)))) + +(defun ivy-read-action-by-key (actions) + (let* ((hint (funcall ivy-read-action-format-function (cdr actions))) + (resize-mini-windows t) + (key "") + action-idx) + (while (and (setq action-idx (cl-position-if + (lambda (x) + (string-prefix-p key (car x))) + (cdr actions))) + (not (string= key (car (nth action-idx (cdr actions)))))) + (setq key (concat key (string (read-key hint))))) + (ivy-shrink-after-dispatching) + (cond ((member key '("" "")) + nil) + ((null action-idx) + (message "%s is not bound" key) + nil) + (t + (message "") + (setcar actions (1+ action-idx)) + (ivy-set-action actions))))) + +(defun ivy-read-action-ivy (actions) + "Select an action from ACTIONS using Ivy." + (let ((enable-recursive-minibuffers t)) + (if (and (> (minibuffer-depth) 1) + (eq (ivy-state-caller ivy-last) 'ivy-read-action-ivy)) + (minibuffer-keyboard-quit) + (ivy-read (format "action (%s): " (ivy-state-current ivy-last)) + (cl-mapcar + (lambda (a i) (cons (format "[%s] %s" (nth 0 a) (nth 2 a)) i)) + (cdr actions) (number-sequence 1 (length (cdr actions)))) + :action (lambda (a) + (setcar actions (cdr a)) + (ivy-set-action actions)) + :caller 'ivy-read-action-ivy)))) (defun ivy-shrink-after-dispatching () "Shrink the window after dispatching when action list is too large." @@ -971,14 +993,20 @@ (ivy--cd dir) (ivy--exhibit)))) +(defun ivy--handle-directory (input) + "Detect the next directory based on special values of INPUT." + (cond ((string= input "/") + "/") + ((string= input "/sudo::") + (concat input ivy--directory)))) + (defun ivy--directory-done () "Handle exit from the minibuffer when completing file names." - (let (dir) + (let ((dir (ivy--handle-directory ivy-text))) (cond - ((equal ivy-text "/sudo::") - (setq dir (concat ivy-text (expand-file-name ivy--directory))) - (ivy--cd dir) - (ivy--exhibit)) + (dir + (let ((inhibit-message t)) + (ivy--cd dir))) ((ivy--directory-enter)) ((unless (string= ivy-text "") (let ((file (expand-file-name @@ -1049,20 +1077,25 @@ "Complete the minibuffer text as much as possible. 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) - (or (and (equal ivy--directory "/") - (string-match-p "\\`[^/]+:.*\\'" ivy-text)) - (= (string-to-char ivy-text) ?/))) - (let ((default-directory ivy--directory) - dir) - (minibuffer-complete) - (setq ivy-text (ivy--input)) - (when (setq dir (ivy-expand-file-if-directory ivy-text)) - (ivy--cd dir))) - (or (ivy-partial) - (when (or (eq this-command last-command) - (eq ivy--length 1)) - (ivy-alt-done))))) + (cond + ((and completion-cycle-threshold (< (length ivy--all-candidates) completion-cycle-threshold)) + (let ((ivy-wrap t)) + (ivy-next-line))) + ((and (eq (ivy-state-collection ivy-last) #'read-file-name-internal) + (or (and (equal ivy--directory "/") + (string-match-p "\\`[^/]+:.*\\'" ivy-text)) + (= (string-to-char ivy-text) ?/))) + (let ((default-directory ivy--directory) + dir) + (minibuffer-complete) + (setq ivy-text (ivy--input)) + (when (setq dir (ivy-expand-file-if-directory ivy-text)) + (ivy--cd dir)))) + (t + (or (ivy-partial) + (when (or (eq this-command last-command) + (eq ivy--length 1)) + (ivy-alt-done)))))) (defun ivy--remove-prefix (prefix string) "Compatibility shim for `string-remove-prefix'." @@ -1070,10 +1103,20 @@ (substring string (length prefix)) string)) +(defun ivy--partial-cd-for-single-directory () + (when (and + (eq (ivy-state-collection ivy-last) #'read-file-name-internal) + (= 1 (length + (ivy--re-filter + (funcall ivy--regex-function ivy-text) ivy--all-candidates))) + (let ((default-directory ivy--directory)) + (file-directory-p (ivy-state-current ivy-last)))) + (ivy--directory-done))) + (defun ivy-partial () "Complete the minibuffer text as much as possible." (interactive) - (let* ((parts (or (split-string ivy-text " " t) (list ""))) + (let* ((parts (or (ivy--split-spaces ivy-text) (list ""))) (tail (last parts)) (postfix (car tail)) (case-fold-search (ivy--case-fold-p ivy-text)) @@ -1087,7 +1130,7 @@ ivy--old-cands))))) (cond ((eq new t) nil) ((string= new ivy-text) nil) - ((string= (car tail) new) nil) + ((string= (car tail) (car (ivy--split-spaces new))) nil) (new (delete-region (minibuffer-prompt-end) (point-max)) (setcar tail @@ -1099,13 +1142,7 @@ (concat (mapconcat #'identity parts " ") (and ivy-tab-space (not (= (length ivy--old-cands) 1)) " ")))) - (when (and - (eq (ivy-state-collection ivy-last) #'read-file-name-internal) - (= 1 (length - (all-completions ivy-text ivy--all-candidates))) - (let ((default-directory ivy--directory)) - (file-directory-p (ivy-state-current ivy-last)))) - (ivy--directory-done)) + (ivy--partial-cd-for-single-directory) t)))) (defvar ivy-completion-beg nil @@ -1125,8 +1162,14 @@ ((and (string= ivy-text "") (eq (ivy-state-collection ivy-last) #'read-file-name-internal)) - (or (ivy-state-def ivy-last) - ivy--directory)) + (if (ivy-state-def ivy-last) + (if (and + (file-exists-p (ivy-state-def ivy-last)) + (/= (length ivy--directory) + (1+ (length (expand-file-name (ivy-state-def ivy-last)))))) + ivy--directory + (copy-sequence (ivy-state-def ivy-last))) + ivy--directory)) (t (expand-file-name ivy-text ivy--directory)))) (insert (ivy-state-current ivy-last)) @@ -1140,10 +1183,12 @@ (interactive) (if (null (ivy-state-action ivy-last)) (user-error "The last session isn't compatible with `ivy-resume'") - (when (eq (ivy-state-caller ivy-last) 'swiper) + (when (memq (ivy-state-caller ivy-last) + '(swiper swiper-isearch swiper-backward swiper-isearch-backward)) (switch-to-buffer (ivy-state-buffer ivy-last))) (with-current-buffer (ivy-state-buffer ivy-last) - (let ((default-directory (ivy-state-directory ivy-last))) + (let ((default-directory (ivy-state-directory ivy-last)) + (ivy-use-ignore-default (ivy-state-ignore ivy-last))) (ivy-read (ivy-state-prompt ivy-last) (ivy-state-collection ivy-last) @@ -1160,6 +1205,7 @@ :re-builder (ivy-state-re-builder ivy-last) :matcher (ivy-state-matcher ivy-last) :dynamic-collection (ivy-state-dynamic-collection ivy-last) + :extra-props (ivy-state-extra-props ivy-last) :caller (ivy-state-caller ivy-last)))))) (defvar-local ivy-calling nil @@ -1260,6 +1306,7 @@ (if ivy-use-ignore nil (or ivy-use-ignore-default t))) + (setf (ivy-state-ignore ivy-last) ivy-use-ignore) ;; invalidate cache (setq ivy--old-cands nil)) @@ -1326,8 +1373,8 @@ Example use: (let* ((ivy-inhibit-action t) - (str (counsel-locate \"lispy.el\"))) - ;; do whatever with str - the corresponding file will not be opened + (str (ivy-switch-buffer))) + ;; do whatever with str - the corresponding buffer will not be opened )") (defun ivy-recursive-restore () @@ -1423,7 +1470,7 @@ (ivy-call)) (defun ivy-previous-line-and-call (&optional arg) - "Move cursor vertically down ARG candidates. + "Move cursor vertically up ARG candidates. Call the permanent action if possible." (interactive "p") (ivy-previous-line arg) @@ -1457,7 +1504,7 @@ (when (and (with-ivy-window (derived-mode-p 'prog-mode)) (eq (ivy-state-caller ivy-last) 'swiper) (not (file-exists-p ivy--default)) - (not (ffap-url-p ivy--default)) + (not (ivy-ffap-url-p ivy--default)) (not (ivy-state-dynamic-collection ivy-last)) (> (point) (minibuffer-prompt-end))) (ivy--insert-symbol-boundaries))) @@ -1475,7 +1522,7 @@ (when ivy--directory (let ((input (ivy--input)) url) - (if (setq url (or (ffap-url-p input) + (if (setq url (or (ivy-ffap-url-p input) (with-ivy-window (cl-reduce (lambda (a b) @@ -1484,7 +1531,7 @@ :initial-value nil)))) (ivy-exit-with-action (lambda (_) - (funcall ffap-url-fetcher url))) + (ivy-ffap-url-fetcher url))) (setq input (expand-file-name input)) (let ((file (file-name-nondirectory input)) (dir (expand-file-name (file-name-directory input)))) @@ -1621,13 +1668,6 @@ (const :tag "Full line" ivy-format-function-line) (function :tag "Custom function")))) -(defvar ivy-format-function #'ivy-format-function-default - "Function to transform the list of candidates into a string. -This string is inserted into the minibuffer.") - -(make-obsolete-variable - 'ivy-format-function 'ivy-format-functions-alist "<2019-06-03 Mon>") - (eval-after-load 'avy '(add-to-list 'avy-styles-alist '(ivy-avy . pre))) @@ -1701,30 +1741,16 @@ nil (string< x y)))) -(declare-function ido-file-extension-lessp "ido") - -(defun ivy-sort-file-function-using-ido (x y) - "Compare two files X and Y using `ido-file-extensions-order'. - -This function is suitable as a replacement for -`ivy-sort-file-function-default' in `ivy-sort-functions-alist'." - (if (and (bound-and-true-p ido-file-extensions-order)) - (ido-file-extension-lessp x y) - (ivy-sort-file-function-default x y))) - (defun ivy-string< (x y) "Like `string<', but operate on CARs when given cons cells." (string< (if (consp x) (car x) x) (if (consp y) (car y) y))) +(define-obsolete-function-alias 'ivy-sort-file-function-using-ido + 'ido-file-extension-lessp "<2019-10-12 Sat>") + (defcustom ivy-sort-functions-alist - '((read-file-name-internal . ivy-sort-file-function-default) - (internal-complete-buffer . nil) - (ivy-completion-in-region . nil) - (counsel-git-grep-function . nil) - (Man-goto-section . nil) - (org-refile . nil) - (t . ivy-string<)) + '((t . ivy-string<)) "An alist of sorting functions for each collection function. Interactive functions that call completion fit in here as well. @@ -1747,6 +1773,7 @@ :value-type (choice (const :tag "Plain sort" string-lessp) (const :tag "File sort" ivy-sort-file-function-default) + (const :tag "File sort using Ido" ido-file-extension-lessp) (const :tag "No sort" nil) (function :tag "Custom function") (repeat (function :tag "Custom function"))))) @@ -1773,11 +1800,7 @@ (ivy--reset-state ivy-last)))) (defvar ivy-index-functions-alist - '((swiper . ivy-recompute-index-swiper) - (swiper-multi . ivy-recompute-index-swiper) - (counsel-git-grep . ivy-recompute-index-swiper) - (counsel-grep . ivy-recompute-index-swiper-async) - (t . ivy-recompute-index-zero)) + '((t . ivy-recompute-index-zero)) "An alist of index recomputing functions for each collection function. When the input changes, the appropriate function returns an integer - the index of the matched candidate that should be @@ -1810,24 +1833,21 @@ '((ivy--regex-ignore-order . ivy--highlight-ignore-order) (ivy--regex-fuzzy . ivy--highlight-fuzzy) (ivy--regex-plus . ivy--highlight-default)) - "An alist of highlighting functions for each regex buidler function.") + "An alist of highlighting functions for each regex builder function.") (defcustom ivy-initial-inputs-alist '((org-refile . "^") (org-agenda-refile . "^") (org-capture-refile . "^") - (counsel-M-x . "^") - (counsel-describe-function . "^") - (counsel-describe-variable . "^") - (counsel-org-capture . "^") (Man-completion-table . "^") (woman . "^")) "An alist associating commands with their initial input. Each cdr is either a string or a function called in the context of a call to `ivy-read'." - :type '(alist :key-type (symbol) - :value-type (choice (string) (function)))) + :type '(alist + :key-type (symbol) + :value-type (choice (string) (function)))) (defcustom ivy-hooks-alist nil "An alist associating commands to setup functions. @@ -1835,6 +1855,79 @@ May supersede `ivy-initial-inputs-alist'." :type '(alist :key-type symbol :value-type function)) +(defvar ivy--occurs-list nil + "A list of custom occur generators per command.") + +(defun ivy-set-occur (cmd occur) + "Assign CMD a custom OCCUR function." + (setq ivy--occurs-list + (plist-put ivy--occurs-list cmd occur))) + +(defcustom ivy-update-fns-alist nil + "An alist associating commands to their :update-fn values." + :type '(alist + :key-type symbol + :value-type + (radio + (const :tag "Off" nil) + (const :tag "Call action on change" auto)))) + +(defvar ivy-unwind-fns-alist nil + "An alist associating commands to their :unwind values.") + +(defun ivy--alist-set (alist-sym key val) + (let ((cell (assoc key (symbol-value alist-sym)))) + (if cell + (setcdr cell val) + (set alist-sym (cons (cons key val) + (symbol-value alist-sym)))))) + +(declare-function counsel-set-async-exit-code "counsel") + +(cl-defun ivy-configure (caller + &key + initial-input + height + occur + update-fn + unwind-fn + index-fn + sort-fn + format-fn + display-transformer-fn + more-chars + grep-p + exit-codes) + "Configure `ivy-read' params for CALLER." + (declare (indent 1)) + (when initial-input + (ivy--alist-set 'ivy-initial-inputs-alist caller initial-input)) + (when height + (ivy--alist-set 'ivy-height-alist caller height)) + (when occur + (ivy-set-occur caller occur)) + (when update-fn + (ivy--alist-set 'ivy-update-fns-alist caller update-fn)) + (when unwind-fn + (ivy--alist-set 'ivy-unwind-fns-alist caller unwind-fn)) + (when index-fn + (ivy--alist-set 'ivy-index-functions-alist caller index-fn)) + (when sort-fn + (ivy--alist-set 'ivy-sort-functions-alist caller sort-fn)) + (when format-fn + (ivy--alist-set 'ivy-format-functions-alist caller format-fn)) + (when display-transformer-fn + (ivy-set-display-transformer caller display-transformer-fn)) + (when more-chars + (ivy--alist-set 'ivy-more-chars-alist caller more-chars)) + (when grep-p + (cl-pushnew caller ivy-highlight-grep-commands)) + (when exit-codes + (let (code msg) + (while (and (setq code (pop exit-codes)) + (setq msg (pop exit-codes))) + (counsel-set-async-exit-code caller code msg))))) + (defcustom ivy-sort-max-size 30000 "Sorting won't be done for collections larger than this." :type 'integer) @@ -1902,7 +1995,9 @@ history preselect def keymap update-fn sort action multi-action unwind re-builder matcher - dynamic-collection caller) + dynamic-collection + extra-props + caller) "Read a string in the minibuffer, with completion. PROMPT is a string, normally ending in a colon and a space. @@ -1935,13 +2030,14 @@ DEF is for compatibility with `completing-read'. -UPDATE-FN is called each time the candidate list is redisplayed. +UPDATE-FN is called each time the candidate list is re-displayed. When SORT is non-nil, `ivy-sort-functions-alist' determines how to sort candidates before displaying them. ACTION is a function to call after selecting a candidate. -It takes the candidate, which is a string, as its only argument. +It takes one argument, the selected candidate. If COLLECTION is +an alist, the argument is a cons cell, otherwise it's a string. MULTI-ACTION, when non-nil, is called instead of ACTION when there are marked candidates. It takes the list of candidates as @@ -1960,9 +2056,15 @@ DYNAMIC-COLLECTION is a boolean specifying whether the list of candidates is updated after each input by calling COLLECTION. +EXTRA-PROPS can be used to store collection-specific +session-specific data. + CALLER is a symbol to uniquely identify the caller to `ivy-read'. It is used, along with COLLECTION, to determine which customizations apply to the current completion session." + ;; get un-stuck from an existing `read-key' overriding minibuffer keys + (when (equal overriding-local-map '(keymap)) + (keyboard-quit)) (setq caller (or caller this-command)) (let* ((ivy-recursive-last (and (active-minibuffer-window) ivy-last)) (ivy--display-function @@ -1970,6 +2072,8 @@ (not (window-minibuffer-p))) (ivy-alist-setting ivy-display-functions-alist caller))) result) + (setq update-fn (or update-fn (ivy-alist-setting ivy-update-fns-alist caller))) + (setq unwind (or unwind (ivy-alist-setting ivy-unwind-fns-alist caller))) (setq ivy-last (make-ivy-state :prompt prompt @@ -1982,8 +2086,13 @@ :keymap keymap :update-fn (if (eq update-fn 'auto) (lambda () - (funcall (ivy--get-action ivy-last) - (ivy-state-current ivy-last))) + (with-ivy-window + (funcall + (ivy--get-action ivy-last) + (if (consp (car-safe (ivy-state-collection ivy-last))) + (assoc (ivy-state-current ivy-last) + (ivy-state-collection ivy-last)) + (ivy-state-current ivy-last))))) update-fn) :sort sort :action (ivy--compute-extra-actions action caller) @@ -1997,6 +2106,7 @@ :dynamic-collection dynamic-collection :display-transformer-fn (plist-get ivy--display-transformers-list caller) :directory default-directory + :extra-props extra-props :caller caller :def def)) (ivy--reset-state ivy-last) @@ -2017,10 +2127,10 @@ (car ivy--all-candidates)) (setq ivy-exit 'done)) (read-from-minibuffer - prompt - (ivy-state-initial-input ivy-last) - (make-composed-keymap keymap ivy-minibuffer-map) - nil + prompt + (ivy-state-initial-input ivy-last) + (make-composed-keymap keymap ivy-minibuffer-map) + nil hist)) (when (eq ivy-exit 'done) (let ((item (if ivy--directory @@ -2099,6 +2209,7 @@ (setq ivy--index 0) (setq ivy-calling nil) (setq ivy-use-ignore ivy-use-ignore-default) + (setf (ivy-state-ignore state) ivy-use-ignore) (setq ivy--highlight-function (or (cdr (assq ivy--regex-function ivy-highlight-functions-alist)) #'ivy--highlight-default)) @@ -2170,7 +2281,7 @@ counsel-switch-buffer))) predicate))) (dynamic-collection - (setq coll (funcall collection ivy-text))) + (setq coll (funcall collection (or initial-input "")))) ((consp (car-safe collection)) (setq collection (cl-remove-if-not predicate collection)) (when (and sort (setq sort-fn (ivy--sort-function caller))) @@ -2315,7 +2426,6 @@ :def def :history history :keymap nil - :sort t :dynamic-collection ivy-completing-read-dynamic-collection :caller (if (and collection (symbolp collection)) collection @@ -2341,13 +2451,15 @@ prompt collection predicate require-match initial-input history (or def "") inherit-input-method)) +(declare-function mc/all-fake-cursors "ext:multiple-cursors-core") + (defun ivy-completion-in-region-action (str) "Insert STR, erasing the previous one. The previous string is between `ivy-completion-beg' and `ivy-completion-end'." (when (consp str) (setq str (cdr str))) (when (stringp str) - (let ((fake-cursors (and (fboundp 'mc/all-fake-cursors) + (let ((fake-cursors (and (require 'multiple-cursors-core nil t) (mc/all-fake-cursors))) (pt (point)) (beg ivy-completion-beg) @@ -2406,6 +2518,8 @@ (string= str (car comps)))) (message "Sole match")) (t + (when (eq collection 'crm--collection-fn) + (setq comps (delete-dups comps))) (let* ((len (ivy-completion-common-length (car comps))) (initial (cond ((= len 0) "") @@ -2435,7 +2549,6 @@ ;; `completion-all-completions'. :predicate nil :initial-input initial - :sort t :action #'ivy-completion-in-region-action :unwind (lambda () (unless (eq ivy-exit 'done) @@ -2484,7 +2597,9 @@ (defun ivy--preselect-index (preselect candidates) "Return the index of PRESELECT in CANDIDATES." (cond ((integerp preselect) - preselect) + (if (integerp (car candidates)) + (cl-position preselect candidates) + preselect)) ((cl-position preselect candidates :test #'equal)) ((ivy--regex-p preselect) (cl-position preselect candidates :test #'string-match-p)))) @@ -2560,6 +2675,13 @@ (push s res))) (mapcar #'ivy--regex-or-literal (nreverse res)))) +(defun ivy--trim-trailing-re (regex) + "Trim incomplete REGEX. +If REGEX ends with \\|, trim it, since then it matches an empty string." + (if (string-match "\\`\\(.*\\)[\\]|\\'" regex) + (match-string 1 regex) + regex)) + (defun ivy--regex (str &optional greedy) "Re-build regex pattern from STR in case it has a space. When GREEDY is non-nil, join words in a greedy way." @@ -2571,6 +2693,7 @@ (cdr hashed)) (when (string-match-p "\\(?:[^\\]\\|^\\)\\\\\\'" str) (setq str (substring str 0 -1))) + (setq str (ivy--trim-trailing-re str)) (cdr (puthash str (let ((subs (ivy--split str))) (if (= (length subs) 1) @@ -2602,7 +2725,7 @@ "Split STR into text before and after ! delimiter. Do not split if the delimiter is escaped as \\!. -Assumes there is at most one unescaped delimiter and discards +Assumes there is at most one un-escaped delimiter and discards text after delimiter if it is empty. Modifies match data." (unless (string= str "") (let ((delim "\\(?:\\`\\|[^\\]\\)\\(!\\)")) @@ -2610,7 +2733,7 @@ ;; Store "\!" as "!". (replace-regexp-in-string "\\\\!" "!" split t t)) (if (string-match delim str) - ;; Ignore everything past first unescaped ! rather than + ;; Ignore everything past first un-escaped ! rather than ;; crashing. We can't warn or error because the minibuffer is ;; already active. (let* ((i (match-beginning 1)) @@ -2624,7 +2747,7 @@ (defun ivy--split-spaces (str) "Split STR on spaces, unless they're preceded by \\. -No unescaped spaces are left in the output. Any substring not +No un-escaped spaces are left in the output. Any substring not constituting a valid regexp is passed to `regexp-quote'." (when str (let ((i 0) ; End of last search. @@ -2633,7 +2756,7 @@ (while (string-match "\\(\\\\ \\)\\| +" str i) (setq i (match-end 0)) (if (not (match-beginning 1)) - ;; Unescaped space(s). + ;; Un-escaped space(s). (let ((delim (match-beginning 0))) (when (< j delim) (push (substring str j delim) parts)) @@ -2656,10 +2779,11 @@ foo[a-z] -> matches \"foo[a-z]\" Escaping examples: -foo\!bar -> matches \"foo!bar\" -foo\ bar -> matches \"foo bar\" +foo\\!bar -> matches \"foo!bar\" +foo\\ bar -> matches \"foo bar\" Returns a list suitable for `ivy-re-match'." + (setq str (ivy--trim-trailing-re str)) (let* (regex-parts (raw-parts (ivy--split-negation str))) (dolist (part (ivy--split-spaces (car raw-parts))) @@ -2692,6 +2816,7 @@ (defun ivy--regex-fuzzy (str) "Build a regex sequence from STR. Insert .* between each char." + (setq str (ivy--trim-trailing-re str)) (if (string-match "\\`\\(\\^?\\)\\(.*?\\)\\(\\$?\\)\\'" str) (prog1 (concat (match-string 1 str) @@ -2745,9 +2870,12 @@ (defun ivy--input () "Return the current minibuffer input." ;; assume one-line minibuffer input - (buffer-substring-no-properties - (minibuffer-prompt-end) - (line-end-position))) + (save-excursion + (goto-char (minibuffer-prompt-end)) + (let ((inhibit-field-text-motion t)) + (buffer-substring-no-properties + (point) + (line-end-position))))) (defun ivy--minibuffer-cleanup () "Delete the displayed completion candidates." @@ -2848,6 +2976,8 @@ (concat n-str d-str "\n")) (t (concat n-str d-str))))) + (when ivy-pre-prompt-function + (setq n-str (concat (funcall ivy-pre-prompt-function) n-str))) (when ivy-add-newline-after-prompt (setq n-str (concat n-str "\n"))) (let ((regex (format "\\([^\n]\\{%d\\}\\)[^\n]" (window-width)))) @@ -2938,6 +3068,7 @@ (and (or (> ivy--index 0) (= ivy--length 1) magic) + (not (ivy--prompt-selected-p)) (not (equal (ivy-state-current ivy-last) "")) (file-directory-p (ivy-state-current ivy-last)) (or (eq ivy-magic-slash-non-match-action @@ -3019,14 +3150,22 @@ 'ivy--exhibit))) (ivy--exhibit))) -(defun ivy--magic-tilde-directory () - "Return an appropriate directory for when ~ or ~/ are entered." +(defun ivy--magic-tilde-directory (dir) + "Return an appropriate home for DIR for when ~ or ~/ are entered." (expand-file-name (let (remote) - (if (setq remote (file-remote-p ivy--directory)) + (if (and (setq remote (file-remote-p dir)) + (let ((local (file-local-name dir))) + (not (or (string= "/root/" local) + (string-match-p "/home/\\([^/]+\\)/\\'" local))))) (concat remote "~/") "~/")))) +(defun ivy-update-candidates (cands) + (ivy--insert-minibuffer + (ivy--format + (setq ivy--all-candidates cands)))) + (defun ivy--exhibit () "Insert Ivy completions display. Should be run via minibuffer `post-command-hook'." @@ -3037,15 +3176,24 @@ (if (ivy-state-dynamic-collection ivy-last) ;; while-no-input would cause annoying ;; "Waiting for process to die...done" message interruptions - (let ((inhibit-message t)) + (let ((inhibit-message t) + coll in-progress) (unless (equal ivy--old-text ivy-text) (while-no-input - (setq ivy--all-candidates - (ivy--sort-maybe - (funcall (ivy-state-collection ivy-last) ivy-text))) + (setq coll (funcall (ivy-state-collection ivy-last) ivy-text)) + (when (eq coll 0) + (setq coll nil) + (setq ivy--old-re nil) + (setq in-progress t)) + (setq ivy--all-candidates (ivy--sort-maybe coll)) (setq ivy--old-text ivy-text))) + (when (eq ivy--all-candidates 0) + (setq ivy--all-candidates nil) + (setq ivy--old-re nil) + (setq in-progress t)) (when (or ivy--all-candidates - (not (get-process " *counsel*"))) + (and (not (get-process " *counsel*")) + (not in-progress))) (ivy--set-index-dynamic-collection) (ivy--insert-minibuffer (ivy--format ivy--all-candidates)))) @@ -3053,7 +3201,7 @@ (cond ((or (string= "~/" ivy-text) (and (string= "~" ivy-text) ivy-magic-tilde)) - (ivy--cd (ivy--magic-tilde-directory))) + (ivy--cd (ivy--magic-tilde-directory ivy--directory))) ((string-match "/\\'" ivy-text) (ivy--magic-file-slash)))) ((eq (ivy-state-collection ivy-last) #'internal-complete-buffer) @@ -3313,9 +3461,6 @@ (defvar ivy--virtual-buffers nil "Store the virtual buffers alist.") -(define-obsolete-function-alias 'ivy-generic-regex-to-str - 'ivy-re-to-str "0.10.0") - (defun ivy-re-to-str (re) "Transform RE to a string. @@ -3439,7 +3584,7 @@ (res 0) (i 0)) (dolist (c cands) - (when (eq n (read (get-text-property 0 'swiper-line-number c))) + (when (eq n (get-text-property 0 'swiper-line-number c)) (setq res i)) (cl-incf i)) res)))) @@ -3450,7 +3595,7 @@ CANDS are the current candidates." (let ((idx (ivy-recompute-index-swiper re-str cands))) (if (or (= idx -1) - (<= (read (get-text-property 0 'swiper-line-number (nth idx cands))) + (<= (get-text-property 0 'swiper-line-number (nth idx cands)) (line-number-at-pos))) idx (- idx 1)))) @@ -3706,7 +3851,7 @@ (str (if (eq ivy-display-style 'fancy) (if (memq (ivy-state-caller ivy-last) ivy-highlight-grep-commands) - (let* ((start (if (string-match "\\`[^:]+:[^:]+:" str) + (let* ((start (if (string-match "\\`[^:]+:\\(?:[^:]+:\\)?" str) (match-end 0) 0)) (file (substring str 0 start)) (match (substring str start))) @@ -3732,13 +3877,6 @@ olen (length str) 'ivy-completions-annotations str)) str)) -(ivy-set-display-transformer - 'counsel-find-file 'ivy-read-file-transformer) -(ivy-set-display-transformer - 'counsel-dired 'ivy-read-file-transformer) -(ivy-set-display-transformer - 'read-file-name-internal 'ivy-read-file-transformer) - (defun ivy-read-file-transformer (str) "Transform candidate STR when reading files." (if (ivy--dirname-p str) @@ -3755,7 +3893,7 @@ (defun ivy--format (cands) "Return a string for CANDS suitable for display in the minibuffer. -CANDS is a list of strings." +CANDS is a list of candidates that :display-transformer can turn into strings." (setq ivy--length (length cands)) (when (>= ivy--index ivy--length) (ivy-set-index (max (1- ivy--length) 0))) @@ -3768,6 +3906,7 @@ (let* ((bnd (ivy--minibuffer-index-bounds ivy--index ivy--length ivy-height)) (wnd-cands (cl-subseq cands (car bnd) (cadr bnd))) + (case-fold-search (ivy--case-fold-p ivy-text)) transformer-fn) (setq ivy--window-index (nth 2 bnd)) (when (setq transformer-fn (ivy-state-display-transformer-fn ivy-last)) @@ -3806,12 +3945,19 @@ (require 'bookmark) (unless recentf-mode (recentf-mode 1)) - (let (virtual-buffers) - (bookmark-maybe-load-default-file) - (dolist (head (append recentf-list - (delete " - no file -" - (delq nil (mapcar #'bookmark-get-filename - bookmark-alist))))) + (bookmark-maybe-load-default-file) + (let* ((vb-bkm (delete " - no file -" + (delq nil (mapcar #'bookmark-get-filename + bookmark-alist)))) + (vb-list (cond ((eq ivy-use-virtual-buffers 'recentf) + recentf-list) + ((eq ivy-use-virtual-buffers 'bookmarks) + vb-bkm) + (ivy-use-virtual-buffers + (append recentf-list vb-bkm)) + (t nil))) + virtual-buffers) + (dolist (head vb-list) (let* ((file-name (if (stringp head) head (cdr head))) @@ -3934,7 +4080,7 @@ When ARG is non-nil, replace a selected item on `ivy-views'. -Currently, the split configuration (i.e. horizonal or vertical) +Currently, the split configuration (i.e. horizontal or vertical) and point positions are saved, but the split positions aren't. Use `ivy-pop-view' to delete any item from `ivy-views'." (interactive "P") @@ -4167,11 +4313,6 @@ (and (eq ivy-use-ignore t) res))))) -(ivy-set-display-transformer - 'ivy-switch-buffer 'ivy-switch-buffer-transformer) -(ivy-set-display-transformer - 'internal-complete-buffer 'ivy-switch-buffer-transformer) - (defun ivy-append-face (str face) "Append to STR the property FACE." (setq str (copy-sequence str)) @@ -4191,21 +4332,23 @@ (t str)) str))) -(defun ivy-switch-buffer-occur () - "Occur function for `ivy-switch-buffer' using `ibuffer'." +(defun ivy-switch-buffer-occur (cands) + "Occur function for `ivy-switch-buffer' using `ibuffer'. +CANDS are the candidates to be displayed." + (unless cands + (setq cands (all-completions ivy-text #'internal-complete-buffer))) (ibuffer nil (buffer-name) `((or ,@(cl-mapcan (lambda (cand) (unless (eq (get-text-property 0 'face cand) 'ivy-virtual) `((name . ,(format "\\_<%s\\_>" (regexp-quote cand)))))) - ivy--old-cands))))) + cands))))) ;;;###autoload (defun ivy-switch-buffer () "Switch to another buffer." (interactive) - (setq this-command #'ivy-switch-buffer) (ivy-read "Switch to buffer: " #'internal-complete-buffer :keymap ivy-switch-buffer-map :preselect (buffer-name (other-buffer (current-buffer))) @@ -4213,6 +4356,10 @@ :matcher #'ivy--switch-buffer-matcher :caller 'ivy-switch-buffer)) +(ivy-configure 'ivy-switch-buffer + :occur #'ivy-switch-buffer-occur + :display-transformer-fn #'ivy-switch-buffer-transformer) + ;;;###autoload (defun ivy-switch-view () "Switch to one of the window views stored by `ivy-push-view'." @@ -4232,7 +4379,14 @@ :keymap ivy-switch-buffer-map :caller 'ivy-switch-buffer-other-window)) -(define-obsolete-function-alias 'ivy-recentf 'counsel-recentf "0.8.0") +(ivy-configure 'ivy-switch-buffer-other-window + :occur #'ivy-switch-buffer-occur) + +(defun ivy--yank-handle-case-fold (text) + (if (and (> (length ivy-text) 0) + (string= (downcase ivy-text) ivy-text)) + (downcase text) + text)) (defun ivy--yank-by (fn &rest args) "Pull buffer text from current line into search string. @@ -4252,7 +4406,10 @@ (unless text (goto-char beg))))) (when text - (insert (replace-regexp-in-string " +" " " text t t))))) + (insert (replace-regexp-in-string + " +" " " + (ivy--yank-handle-case-fold text) + t t))))) (defun ivy-yank-word (&optional arg) "Pull next word from buffer into search string. @@ -4349,9 +4506,6 @@ (interactive) (insert ivy--directory)) -(define-obsolete-variable-alias 'ivy--preferred-re-builders - 'ivy-preferred-re-builders "0.10.0") - (defcustom ivy-preferred-re-builders '((ivy--regex-plus . "ivy") (ivy--regex-ignore-order . "order") @@ -4401,20 +4555,23 @@ (define-key map (kbd "C-k") 'ivy-reverse-i-search-kill) map)) -(defun ivy-history-contents (sym-or-ring) - "Copy contents of SYM-OR-RING. +(defun ivy-history-contents (history) + "Copy contents of HISTORY. A copy is necessary so that we don't clobber any string attributes. -Also set `ivy--reverse-i-search-symbol' to SYM-OR-RING." - (setq ivy--reverse-i-search-symbol sym-or-ring) - (cond ((symbolp sym-or-ring) +Also set `ivy--reverse-i-search-symbol' to HISTORY." + (setq ivy--reverse-i-search-symbol history) + (cond ((symbolp history) + (delete-dups + (copy-sequence (symbol-value history)))) + ((ring-p history) (delete-dups - (copy-sequence (symbol-value sym-or-ring)))) - ((ring-p sym-or-ring) + (when (> (ring-size history) 0) + (ring-elements history)))) + ((sequencep history) (delete-dups - (when (> (ring-size sym-or-ring) 0) - (ring-elements sym-or-ring)))) + (copy-sequence history))) (t - (error "Expected a symbol or a ring: %S" sym-or-ring)))) + (error "Expected a symbol, ring, or sequence: %S" history)))) (defun ivy-reverse-i-search () "Enter a recursive `ivy-read' session using the current history. @@ -4447,8 +4604,13 @@ "Restrict candidates to current input and erase input." (interactive) (delete-minibuffer-contents) - (setq ivy--all-candidates - (ivy--filter ivy-text ivy--all-candidates))) + (if (ivy-state-dynamic-collection ivy-last) + (progn + (setf (ivy-state-dynamic-collection ivy-last) nil) + (setf (ivy-state-collection ivy-last) + (setq ivy--all-candidates ivy--old-cands))) + (setq ivy--all-candidates + (ivy--filter ivy-text ivy--all-candidates)))) ;;* Occur (defvar-local ivy-occur-last nil @@ -4541,6 +4703,16 @@ (ivy-occur-previous-line arg) (ivy-occur-press-and-switch)))) +(defun ivy-occur-next-error (n &optional reset) + "A `next-error-function' for `ivy-occur-mode'." + (interactive "p") + (when reset + (goto-char (point-min))) + (setq n (or n 1)) + (let ((ivy-calling t)) + (cond ((< n 0) (ivy-occur-previous-line (- n))) + (t (ivy-occur-next-line n))))) + (define-derived-mode ivy-occur-mode fundamental-mode "Ivy-Occur" "Major mode for output from \\[ivy-occur]. @@ -4568,17 +4740,6 @@ (when (fboundp 'wgrep-setup) (wgrep-setup))) -(defvar ivy--occurs-list nil - "A list of custom occur generators per command.") - -(defun ivy-set-occur (cmd occur) - "Assign CMD a custom OCCUR function." - (setq ivy--occurs-list - (plist-put ivy--occurs-list cmd occur))) - -(ivy-set-occur 'ivy-switch-buffer 'ivy-switch-buffer-occur) -(ivy-set-occur 'ivy-switch-buffer-other-window 'ivy-switch-buffer-occur) - (defun ivy--starts-with-dotslash (str) (string-match-p "\\`\\.[/\\]" str)) @@ -4603,6 +4764,18 @@ (insert (if (string-match-p "\\`.[/\\]" cand) "" " ") cand ?\n))) +(defun ivy--occur-default (cands) + "Insert CANDS into the current occur buffer." + (unless cands + (let ((coll (ivy-state-collection ivy-last))) + (when (arrayp coll) + (setq coll (all-completions "" coll (ivy-state-predicate ivy-last)))) + (setq cands (ivy--filter (ivy-state-text ivy-last) coll)))) + (ivy-occur-mode) + (insert (format "%d candidates:\n" (length cands))) + (ivy--occur-insert-lines cands) + (read-only-mode)) + (defun ivy-occur () "Stop completion and put the current candidates into a new buffer. @@ -4616,7 +4789,8 @@ (if (not (window-minibuffer-p)) (user-error "No completion session is active") (let* ((caller (ivy-state-caller ivy-last)) - (occur-fn (plist-get ivy--occurs-list caller)) + (occur-fn (or (plist-get ivy--occurs-list caller) + #'ivy--occur-default)) (buffer (generate-new-buffer (format "*ivy-occur%s \"%s\"*" @@ -4625,25 +4799,20 @@ "") ivy-text)))) (with-current-buffer buffer - (let ((inhibit-read-only t)) - (erase-buffer) - (if occur-fn - (funcall occur-fn) - (ivy-occur-mode) - (insert (format "%d candidates:\n" (length ivy--old-cands))) - (read-only-mode) - (ivy--occur-insert-lines - ivy--old-cands))) + (funcall occur-fn ivy--old-cands) (setf (ivy-state-text ivy-last) ivy-text) (setq ivy-occur-last ivy-last)) (ivy-exit-with-action - (lambda (_) (pop-to-buffer buffer)))))) + (lambda (_) + (pop-to-buffer buffer) + (setq next-error-last-buffer buffer) + (setq-local next-error-function #'ivy-occur-next-error)))))) (defun ivy-occur-revert-buffer () "Refresh the buffer making it up-to date with the collection. Currently only works for `swiper'. In that specific case, the -*ivy-occur* buffer becomes nearly useless as the orignal buffer +*ivy-occur* buffer becomes nearly useless as the original buffer is updated, since the line numbers no longer match. Calling this function is as if you called `ivy-occur' on the @@ -4651,21 +4820,13 @@ (interactive) (let ((caller (ivy-state-caller ivy-occur-last)) (ivy-last ivy-occur-last)) - (cond ((member caller '(swiper swiper-isearch)) - (let ((buffer (ivy-state-buffer ivy-occur-last))) - (unless (buffer-live-p buffer) - (error "Buffer was killed")) - (let ((inhibit-read-only t)) - (erase-buffer) - (funcall (plist-get ivy--occurs-list caller) t) - (ivy-occur-grep-mode)))) - ((memq caller '(counsel-git-grep counsel-grep counsel-ag counsel-rg)) - (let ((inhibit-read-only t) - (line (line-number-at-pos))) - (erase-buffer) - (funcall (plist-get ivy--occurs-list caller)) - (goto-char (point-min)) - (forward-line (1- line))))) + (let ((inhibit-read-only t) + (line (line-number-at-pos))) + (erase-buffer) + (funcall (or (plist-get ivy--occurs-list caller) + #'ivy--occur-default) nil) + (goto-char (point-min)) + (forward-line (1- line))) (setq ivy-occur-last ivy-last))) (declare-function wgrep-change-to-wgrep-mode "ext:wgrep") @@ -4709,15 +4870,14 @@ (declare-function swiper--cleanup "swiper") (declare-function swiper--add-overlays "swiper") (defvar ivy-occur-timer nil) -(defvar counsel-grep-last-line) (defun ivy--occur-press-update-window () - (cl-case (ivy-state-caller ivy-occur-last) - ((swiper swiper-isearch counsel-git-grep counsel-grep counsel-ag counsel-rg) + (cond + ((memq (ivy-state-caller ivy-occur-last) + (append '(swiper swiper-isearch) ivy-highlight-grep-commands)) (let ((window (ivy-state-window ivy-occur-last)) (buffer (ivy-state-buffer ivy-occur-last))) - (if (not (buffer-live-p buffer)) - (error "Buffer was killed") + (when (buffer-live-p buffer) (cond ((or (not (window-live-p window)) (equal window (selected-window))) (save-selected-window @@ -4727,7 +4887,8 @@ (with-selected-window window (switch-to-buffer buffer))))))) - ((counsel-describe-function counsel-describe-variable) + ((memq (ivy-state-caller ivy-occur-last) + '(counsel-describe-function counsel-describe-variable)) (setf (ivy-state-window ivy-occur-last) (selected-window)) (selected-window)))) @@ -4755,7 +4916,6 @@ (action (ivy--get-action ivy-last)) (ivy-exit 'done)) (with-ivy-window - (setq counsel-grep-last-line nil) (with-current-buffer (ivy--occur-press-buffer) (save-restriction (widen) @@ -4765,8 +4925,7 @@ (assoc str coll) (substring str offset))))) (if (memq (ivy-state-caller ivy-last) - '(swiper swiper-isearch - counsel-git-grep counsel-grep counsel-ag counsel-rg)) + (append '(swiper swiper-isearch) ivy-highlight-grep-commands)) (with-current-buffer (window-buffer (selected-window)) (swiper--cleanup) (swiper--add-overlays @@ -4872,6 +5031,26 @@ (view-mode) (goto-char (point-min)))) +(declare-function ffap-url-p "ffap") +(defvar ffap-url-fetcher) + +(defun ivy-ffap-url-p (string) + "Forward to `ffap-url-p'." + (require 'ffap) + (ffap-url-p string)) + +(defun ivy-ffap-url-fetcher (url) + "Calls `ffap-url-fetcher'." + (require 'ffap) + (funcall ffap-url-fetcher url)) + +(ivy-configure 'read-file-name-internal + :sort-fn #'ivy-sort-file-function-default + :display-transformer-fn #'ivy-read-file-transformer) + +(ivy-configure 'internal-complete-buffer + :display-transformer-fn #'ivy-switch-buffer-transformer) + (provide 'ivy) ;;; ivy.el ends here diff -Nru emacs-ivy-0.12.0+dfsg/ivy-hydra.el emacs-ivy-0.13.0/ivy-hydra.el --- emacs-ivy-0.12.0+dfsg/ivy-hydra.el 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/ivy-hydra.el 2019-10-16 16:57:42.000000000 +0000 @@ -4,8 +4,8 @@ ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/swiper -;; Version: 0.12.0 -;; Package-Requires: ((emacs "24.1") (ivy "0.12.0") (hydra "0.13.4")) +;; Version: 0.13.0 +;; Package-Requires: ((emacs "24.5") (ivy "0.13.0") (hydra "0.15.0")) ;; Keywords: convenience ;; This file is part of GNU Emacs. @@ -77,7 +77,8 @@ ("<" ivy-minibuffer-shrink) ("w" ivy-prev-action) ("s" ivy-next-action) - ("a" ivy-read-action) + ("a" (let ((ivy-read-action-function #'ivy-read-action-by-key)) + (ivy-read-action))) ("T" (setq truncate-lines (not truncate-lines))) ("C" ivy-toggle-case-fold) ("U" ivy-occur :exit t) @@ -108,7 +109,8 @@ (estimated-len (length doc)) (n-columns (if (> estimated-len (window-width)) ivy-dispatching-done-columns - nil))) + nil)) + (i 0)) (if (null (ivy--actionp actions)) (ivy-done) (funcall @@ -118,13 +120,13 @@ ,@(mapcar (lambda (x) (list (nth 0 x) `(progn - (ivy-set-action ',(nth 1 x)) + (setcar (ivy-state-action ivy-last) ,(cl-incf i)) (ivy-done)) (nth 2 x))) (cdr actions)) ,@extra-actions)))))) -(define-key ivy-minibuffer-map (kbd "M-o") 'ivy-dispatching-done-hydra) +(setq ivy-read-action-function (lambda (_) (ivy-dispatching-done-hydra))) (provide 'ivy-hydra) diff -Nru emacs-ivy-0.12.0+dfsg/ivy-overlay.el emacs-ivy-0.13.0/ivy-overlay.el --- emacs-ivy-0.12.0+dfsg/ivy-overlay.el 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/ivy-overlay.el 2019-10-16 16:57:42.000000000 +0000 @@ -62,6 +62,8 @@ (when (fboundp 'company-abort) (company-abort))) +(defvar ivy-height) + (defun ivy-overlay-show-after (str) "Display STR in an overlay at point. @@ -71,6 +73,9 @@ (progn (move-overlay ivy-overlay-at (1- (point)) (line-end-position)) (overlay-put ivy-overlay-at 'invisible nil)) + (let ((available-height (count-lines (point) (window-end nil t)))) + (unless (>= available-height ivy-height) + (recenter (- (window-height) ivy-height 2)))) (setq ivy-overlay-at (make-overlay (1- (point)) (line-end-position))) ;; Specify face to avoid clashing with other overlays. (overlay-put ivy-overlay-at 'face 'default) @@ -95,7 +100,7 @@ (or (and (eq major-mode 'org-mode) (plist-get (text-properties-at (point)) 'src-block)) - (<= (window-height) (+ ivy-height 3)) + (<= (window-height) (+ ivy-height 2)) (= (point) (point-min)) (< (- (+ (window-width) (window-hscroll)) (current-column)) 30))) diff -Nru emacs-ivy-0.12.0+dfsg/ivy-test.el emacs-ivy-0.13.0/ivy-test.el --- emacs-ivy-0.12.0+dfsg/ivy-test.el 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/ivy-test.el 2019-10-16 16:57:42.000000000 +0000 @@ -26,6 +26,12 @@ ;;; Code: +(defvar require-features nil) + +(defadvice require (before ivy-tests-require-hook (feature &rest _) activate) + "Record the requires into `require-features'." + (push feature require-features)) + (require 'ert) (require 'colir) @@ -37,30 +43,45 @@ (message "%s" (emacs-version)) +(ert-deftest ivy--lazy-load-ffap--ffap-url-p () + (should (not (memq 'ffap require-features))) + (should (not (fboundp 'ffap-url-p))) + (should (string= (ivy-ffap-url-p "https://foo.org") + "https://foo.org")) + (should (memq 'ffap require-features)) + (should (fboundp 'ffap-url-p))) + (defvar ivy-expr nil "Holds a test expression to evaluate with `ivy-eval'.") (defvar ivy-result nil "Holds the eval result of `ivy-expr' by `ivy-eval'.") +(defvar ivy-eval-dir nil + "Hold the `default-directory' value to be used by `ivy-eval'. +Since `execute-kbd-macro' doesn't pick up a let-bound `default-directory'.") + (defun ivy-eval () "Evaluate `ivy-expr'." (interactive) - (setq ivy-result (eval ivy-expr))) + (let ((default-directory (or ivy-eval-dir default-directory))) + (setq ivy-result (eval ivy-expr)))) (global-set-key (kbd "C-c e") 'ivy-eval) +(defvar ivy-test-inhibit-message t) + (cl-defun ivy-with (expr keys &key dir) "Evaluate EXPR followed by KEYS." (let ((ivy-expr expr) - (inhibit-message t) + (inhibit-message ivy-test-inhibit-message) (buf (current-buffer))) (save-window-excursion (unwind-protect (progn - ;; `execute-kbd-macro' doesn't pick up `default-directory' (when dir - (dired (expand-file-name dir (counsel-locate-git-root)))) + (setq dir (expand-file-name dir (counsel-locate-git-root)))) + (setq ivy-eval-dir dir) (execute-kbd-macro (vconcat (kbd "C-c e") (kbd keys)))) @@ -181,7 +202,11 @@ (should (string= (swiper--re-builder "^a") "^ ?\\(a\\)")) (should (string= (swiper--re-builder "^a b") - "^ \\(a\\).*?\\(b\\)"))) + "^ \\(a\\).*?\\(b\\)")) + (should + (string-match-p + "\\`\\\\_<.*\\\\_>\\'" + (swiper--re-builder "\\_")))) (ert-deftest swiper--re-builder-char-fold () :expected-result (if (>= emacs-major-version 25) @@ -219,7 +244,9 @@ "foo\\[")) (should (equal (ivy--regex ".org") - "\\.org"))) + "\\.org")) + (should (equal (ivy--regex "foo\\") "foo")) + (should (equal (ivy--regex "foo\\|") "foo"))) (ert-deftest ivy--split-negation () (should (equal (ivy--split-negation "") ())) @@ -288,7 +315,9 @@ (should (string= (ivy--regex-fuzzy "^") "^")) (should (string= (ivy--regex-fuzzy "$") - "$"))) + "$")) + (should (equal (ivy--regex-fuzzy "abc\\|") + "\\(a\\)[^b\n]*\\(b\\)[^c\n]*\\(c\\)"))) (ert-deftest ivy--regex-ignore-order () (should (equal (ivy--regex-ignore-order "tmux") @@ -320,7 +349,9 @@ (ivy--regex-ignore-order "! ! !") ;; Escape invalid regexps. (should (equal (ivy--regex-ignore-order "foo[ bar[xy]") - '(("foo\\[" . t) ("bar[xy]" . t))))) + '(("foo\\[" . t) ("bar[xy]" . t)))) + (should (equal (ivy--regex-ignore-order "foo\\|") + '(("foo" . t))))) (ert-deftest ivy--format () (should (string= (let ((ivy--index 10) @@ -723,7 +754,7 @@ (switch-to-buffer standard-output t) ,expr (ivy-mode) - (let ((inhibit-message t)) + (let ((inhibit-message ivy-test-inhibit-message)) (execute-kbd-macro ,(apply #'vconcat (mapcar #'kbd keys))))))) @@ -919,11 +950,38 @@ (should (eq (ivy--sort-function 'c) fn1)))) (ert-deftest ivy-read-directory-name () + (ivy-mode 1) (should - (equal "/tmp/" + (equal (expand-file-name "/tmp/") (ivy-with '(read-directory-name "cd: " "/tmp") - "RET")))) + "RET"))) + (should + (equal (expand-file-name "/tmp") + (ivy-with + '(read-directory-name "cd: ") + "C-M-j" + :dir "/tmp"))) + (should + (equal (expand-file-name "/tmp/") + (ivy-with + '(read-directory-name "cd: ") + "tmp C-j C-M-j" + :dir "/"))) + (should + (equal (expand-file-name "/") + (ivy-with + '(read-directory-name "cd: ") + "DEL C-M-j" + :dir "/tmp")))) + +(ert-deftest ivy-counsel-read-directory-name () + (should + (equal (expand-file-name "/tmp/") + (ivy-with + '(counsel-read-directory-name "cd: ") + "RET" + :dir "/tmp/")))) (ert-deftest ivy-partial-files () (when (file-exists-p "/tmp/ivy-partial-test") @@ -957,25 +1015,21 @@ (kill-buffer temp-buffer)))))) (ert-deftest counsel-yank-pop () - (let ((kill-ring '("foo"))) - (should (equal - (ivy-with-temp-buffer '(counsel-yank-pop) "C-m") - '(4 "foo"))) - (let ((counsel-yank-pop-after-point t)) - (should (equal - (ivy-with-temp-buffer '(counsel-yank-pop) "C-m") - '(1 "foo")))))) + (should (equal + (let ((kill-ring '("foo"))) + (ivy-with-temp-buffer '(counsel-yank-pop) "C-m")) + '(4 "foo"))) + (should (equal + (let ((kill-ring '("foo")) + (counsel-yank-pop-after-point t)) + (ivy-with-temp-buffer '(counsel-yank-pop) "C-m")) + '(1 "foo")))) (ert-deftest ivy-read-file-name-in-buffer-visiting-file () "Test `ivy-immediate-done' command in `read-file-name' without any editing in a buffer visiting a file." (let ((ivy-mode-reset-arg (if ivy-mode 1 0))) (ivy-mode 1) - ;; `ivy-read' returns "~/dummy-dir/dummy-file" (same object, not a copy). - ;; - ;; `read-file-name-default' will then return "" in order for - ;; `set-visited-file-name' to detect that the user typed RET with - ;; the minibuffer empty. (should (equal (ivy-with '(let ((insert-default-directory t)) @@ -984,11 +1038,22 @@ (read-file-name "Load file: " nil nil 'lambda))) ;; No editing, just command ivy-immediate-done "C-M-j") - "")) + "~/dummy-dir/dummy-file")) (should (equal (ivy-state-current ivy-last) "~/dummy-dir/dummy-file")) (ivy-mode ivy-mode-reset-arg))) +(ert-deftest ivy-read-file-name-make-directory () + (ivy-mode 1) + (should + (equal + (ivy-with + '(read-file-name "Make directory: " default-directory default-directory + nil nil) + "C-M-j" + :dir "/tmp/non-existant-dir/") + (expand-file-name "/tmp/non-existant-dir/")))) + (ert-deftest ivy-starts-with-dotslash () (should (ivy--starts-with-dotslash "./test1")) (should (ivy--starts-with-dotslash ".\\test2")) @@ -1044,16 +1109,17 @@ (let ((key (eval (cadr x)))) (list key (lookup-key global-map key))))) body)))) - `(let ((temp-buffer (generate-new-buffer " *temp*"))) + `(let ((temp-buffer (get-buffer-create " *temp*"))) (save-window-excursion (unwind-protect (progn (switch-to-buffer temp-buffer) + (erase-buffer) (insert ,text) (search-backward "|") (delete-char 1) (setq current-prefix-arg nil) - (let ((inhibit-message t)) + (let ((inhibit-message ivy-test-inhibit-message)) ,@(mapcar (lambda (x) (if (and (listp x) (stringp (car x))) @@ -1070,6 +1136,22 @@ (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))))) +(ert-deftest swiper-thing-at-point () + (should + (string= + (ivy-with-text + "let\n|let\nlet" + (global-set-key (kbd "C-s") #'swiper-thing-at-point) + ("C-s" "RET")) + "let\nlet|\nlet")) + (should + (string= + (ivy-with-text + "foo\nlet\nbar\n|let\nlet" + (global-set-key (kbd "C-s") #'swiper-thing-at-point) + ("C-s" "RET")) + "foo\nlet\nbar\nlet|\nlet"))) + (ert-deftest swiper-isearch () (should (string= @@ -1129,24 +1211,12 @@ (global-set-key (kbd "C-r") #'isearch-backward-regexp) ("C-r" "defun\\|defvar" "RET")) "(defun foo)\nasdf\n(|defvar bar)")) - ;; NOTE: The following two behaviors do not match - ;; `isearch-backward-regexp', but they match that of - ;; `swiper-isearch-forward', as `swiper-isearch' does not reset the - ;; point when the regexp becomes invalid, meaning the point is left - ;; at the initial match of the first part of the regexp. (should (string= (ivy-with-text "(defun foo)\nasdf\n(defvar bar)|" (global-set-key (kbd "C-r") #'swiper-isearch-backward) ("C-r" "defun\\|defvar" "RET")) - "(|defun foo)\nasdf\n(defvar bar)")) - (should - (string= - (ivy-with-text - "(defun foo)\nasdf\n(defvar bar)|" - (global-set-key (kbd "C-r") #'swiper-isearch-backward) - ("C-r" "defun\\|defvar" "C-n RET")) "(defun foo)\nasdf\n(|defvar bar)")) (should (string= @@ -1161,7 +1231,21 @@ "(defun foo)\nasdf\n(|defun bar)" (global-set-key (kbd "C-r") #'swiper-isearch-backward) ("C-r" "defun" "RET")) - "(|defun foo)\nasdf\n(defun bar)"))) + "(|defun foo)\nasdf\n(defun bar)")) + (should + (string= + (ivy-with-text + "(defun foo)\nasdf\n(de|fun bar)" + (global-set-key (kbd "C-r") #'swiper-isearch-backward) + ("C-r" "def" "RET")) + "(|defun foo)\nasdf\n(defun bar)")) + (should + (string= + (ivy-with-text + "(defun foo)\nasdf\n(de|fun bar)" + (global-set-key (kbd "C-r") #'swiper-isearch-backward) + ("C-r" "def?" "RET")) + "(defun foo)\nasdf\n(|defun bar)"))) (ert-deftest swiper-isearch-backward-backspace () (should @@ -1204,10 +1288,31 @@ ("C-s" "Foo" "C-n RET"))) "Foo\nfoo|\nFOO\n"))) +(ert-deftest ivy-swiper-wgrep () + :expected-result (if (and (= emacs-major-version 24) + (<= emacs-minor-version 3)) + ;; `wgrep' requires at least 24.5 + :failed + :passed) + (dolist (search-cmd '(swiper swiper-isearch)) + (should + (string= + (let ((default-directory "/tmp/")) + (ivy-with-text + "|a one\na two\na three" + (global-set-key (kbd "C-s") search-cmd) + ("C-s" "a" "C-c C-o" "C-x C-q" "C-e" "1" "C-n" "2" "C-n" "C-e" "3"))) + "-*- mode:grep; default-directory: \"/tmp/\" -*- + + +3 candidates: +./ *temp*:1:a one1 +./ *temp*:2:a two2 +./ *temp*:3:a three3| +")))) + (ert-deftest swiper--isearch-format () - (setq swiper--isearch-point-history - (list - (cons "" 1))) + (setq swiper--isearch-start-point 0) (with-temp-buffer (insert "line0\nline1\nline line\nline line\nline5") @@ -1252,17 +1357,7 @@ (should (equal (ivy--minibuffer-index-bounds 10 11 10) '(2 11 8))) (should (equal (ivy--minibuffer-index-bounds 1 3 10) '(0 3 1)))) -(defun counsel--setup-test-files () - (unless (file-exists-p "tests/") - (shell-command - "git clone -b test --single-branch https://github.com/abo-abo/swiper/ tests")) - (let ((default-directory (expand-file-name "tests/")) - (version "066ec1d")) - (shell-command - (format "git checkout %s || git fetch && git checkout %s" version version)))) - (ert-deftest counsel-find-file-with-dollars () - (counsel--setup-test-files) (should (string= (file-relative-name (ivy-with '(counsel-find-file) "fo C-m" @@ -1270,7 +1365,6 @@ "tests/find-file/files-with-dollar/foo$"))) (ert-deftest counsel-find-file-with-dotfiles () - (counsel--setup-test-files) (should (string= (file-relative-name (ivy-with '(counsel-find-file) "f C-m" @@ -1283,7 +1377,6 @@ "tests/find-file/dotfiles/.foobar1"))) (ert-deftest counsel-find-file-with-spaces () - (counsel--setup-test-files) (let ((ivy-extra-directories nil)) (should (string= (file-relative-name @@ -1308,6 +1401,37 @@ (should (string= (ivy-with read-numbers "C-' a") "1")) (should (string= (ivy-with read-numbers "C-v C-' d") "7"))))) +(ert-deftest ivy--yank-handle-case-fold () + (should (string= + (let ((ivy-text "")) + (ivy--yank-handle-case-fold "FirstName")) + "FirstName")) + (should (string= + (let ((ivy-text "f")) + (ivy--yank-handle-case-fold "irstName")) + "irstname"))) + +(ert-deftest ivy--handle-directory () + (should (string= (ivy--handle-directory "/") "/")) + (should (string= (let ((ivy--directory "/tmp/")) + (ivy--handle-directory "/sudo::")) + "/sudo::/tmp/"))) + +(defun ivy-test-run-tests () + (let ((test-sets + '( + ;; this test must run first as other tests might force a load + ivy--lazy-load-ffap--ffap-url-p + ;; run the rest of the tests + (not ivy--lazy-load-ffap--ffap-url-p))) + (unexpected 0)) + (dolist (test-set test-sets) + (cl-incf + unexpected + (ert-stats-completed-unexpected + (ert-run-tests-batch test-set)))) + (kill-emacs (if (zerop unexpected) 0 1)))) + (provide 'ivy-test) ;;; ivy-test.el ends here diff -Nru emacs-ivy-0.12.0+dfsg/Makefile emacs-ivy-0.13.0/Makefile --- emacs-ivy-0.12.0+dfsg/Makefile 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/Makefile 2019-10-16 16:57:42.000000000 +0000 @@ -6,8 +6,11 @@ all: test +deps: + $(emacs) -batch -l targets/install-deps.el + test: - $(emacs) -batch $(LOAD) -l ivy-test.el -f ert-run-tests-batch-and-exit + $(emacs) -batch $(LOAD) -l ivy-test.el -f ivy-test-run-tests checkdoc: $(emacs) -batch -l targets/checkdoc.el diff -Nru emacs-ivy-0.12.0+dfsg/swiper.el emacs-ivy-0.13.0/swiper.el --- emacs-ivy-0.12.0+dfsg/swiper.el 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/swiper.el 2019-10-16 16:57:42.000000000 +0000 @@ -1,11 +1,11 @@ ;;; swiper.el --- Isearch with an overview. Oh, man! -*- lexical-binding: t -*- -;; Copyright (C) 2015-2018 Free Software Foundation, Inc. +;; Copyright (C) 2015-2019 Free Software Foundation, Inc. ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/swiper -;; Version: 0.12.0 -;; Package-Requires: ((emacs "24.1") (ivy "0.12.0")) +;; Version: 0.13.0 +;; Package-Requires: ((emacs "24.5") (ivy "0.13.0")) ;; Keywords: matching ;; This file is part of GNU Emacs. @@ -170,8 +170,9 @@ (let ((end (window-end (selected-window) t)) (re (ivy--regex ivy-text))) (save-excursion - (goto-char (window-start)) - (while (re-search-forward re end t) + (beginning-of-line) + (while (and (re-search-forward re end t) + (not (eobp))) (let ((ov (make-overlay (1- (match-end 0)) (match-end 0))) (md (match-data))) (overlay-put @@ -180,7 +181,9 @@ (lambda (x) (list `(match-string ,x) (match-string x))) (number-sequence 0 (1- (/ (length md) 2))))) - (push ov swiper--query-replace-overlays))))))) + (push ov swiper--query-replace-overlays)) + (unless (> (match-end 0) (match-beginning 0)) + (forward-char))))))) (defun swiper-query-replace () "Start `query-replace' with string to replace from last search string." @@ -206,7 +209,7 @@ (ivy-read (format "Query replace %s with: " from) nil :def default - :update-fn #'swiper--query-replace-updatefn) + :caller 'swiper-query-replace) t))) (swiper--cleanup) (ivy-exit-with-action @@ -218,6 +221,9 @@ t t nil)))))) (swiper--query-replace-cleanup))))) +(ivy-configure 'swiper-query-replace + :update-fn #'swiper--query-replace-updatefn) + (defvar inhibit-message) (defun swiper-all-query-replace () @@ -370,11 +376,17 @@ (mc/create-fake-cursor-at-point)))) (multiple-cursors-mode 1)))))) +(defvar swiper--current-window-start nil + "Store `window-start' to restore it later. +This prevents a \"jumping\" behavior which occurs when variables +such as `scroll-conservatively' are set to a high value.") + (defun swiper-recenter-top-bottom (&optional arg) "Call (`recenter-top-bottom' ARG)." (interactive "P") (with-ivy-window - (recenter-top-bottom arg))) + (recenter-top-bottom arg) + (setq swiper--current-window-start (window-start)))) (defvar swiper-font-lock-exclude '(Man-mode @@ -436,7 +448,7 @@ (not (derived-mode-p 'prog-mode)))) (defun swiper-font-lock-ensure () - "Ensure the entired buffer is highlighted." + "Ensure the entire buffer is highlighted." (unless (swiper-font-lock-ensure-p) (unless (or (> (buffer-size) 100000) (null font-lock-mode)) (if (fboundp 'font-lock-ensure) @@ -447,7 +459,7 @@ "Store the current candidates format spec.") (defvar swiper--width nil - "Store the number of digits needed for the longest line nubmer.") + "Store the number of digits needed for the longest line number.") (defvar swiper-use-visual-line nil "When non-nil, use `line-move' instead of `forward-line'.") @@ -528,7 +540,7 @@ (put-text-property 0 1 'display line-number-str str)) (put-text-property - 0 1 'swiper-line-number line-number-str str)) + 0 1 'swiper-line-number line-number str)) (push str candidates))) (funcall advancer 1) (cl-incf line-number)) @@ -538,13 +550,6 @@ "The point when `swiper' starts.") ;;;###autoload -(defun swiper (&optional initial-input) - "`isearch-forward' with an overview. -When non-nil, INITIAL-INPUT is the initial search pattern." - (interactive) - (swiper--ivy (swiper--candidates) initial-input)) - -;;;###autoload (defun swiper-backward (&optional initial-input) "`isearch-backward' with an overview. When non-nil, INITIAL-INPUT is the initial search pattern." @@ -571,11 +576,6 @@ (deactivate-mark)) (swiper-all thing))) -(defvar swiper--current-window-start nil - "Store `window-start' to restore it later. -This prevents a \"jumping\" behavior which occurs when variables -such as `scroll-conservatively' are set to a high value.") - (defun swiper--extract-matches (regex cands) "Extract captured REGEX groups from CANDS." (let (res) @@ -604,15 +604,16 @@ (if (eq (ivy-state-caller ivy-last) 'swiper-isearch) (swiper--isearch-occur-cands cands) (mapcar (lambda (s) - (let ((l (get-text-property 0 'swiper-line-number s))) + (let ((n (get-text-property 0 'swiper-line-number s))) (setq s (substring s 1)) - (put-text-property 0 1 'swiper-line-number l s) - (cons (read l) s))) + (add-text-properties 0 1 (list 'swiper-line-number n) s) + (cons n s))) cands))) (offset (+ (length fname) 2))) (mapcar (lambda (x) (let ((nn (number-to-string (+ (car x) line-delta)))) + (remove-text-properties 0 1 '(display) (cdr x)) (put-text-property 0 (length nn) 'face 'ivy-grep-line-number nn) (put-text-property 0 1 'offset (+ offset (length nn)) fname) (format "%s:%s:%s" fname nn (cdr x)))) @@ -629,11 +630,32 @@ (setq last-pt pt)) (nreverse res))) -(defun swiper-occur (&optional revert) +(defun swiper--occur-insert-lines (cands) + (let ((inhibit-read-only t)) + ;; Need precise number of header lines for `wgrep' to work. + (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n" + default-directory)) + (insert (format "%d candidates:\n" (length cands))) + (ivy--occur-insert-lines cands) + (goto-char (point-min)) + (forward-line 4))) + +(defun swiper--occur-buffer () + (let ((buffer (ivy-state-buffer ivy-last))) + (unless (buffer-live-p buffer) + (setq buffer + (setf (ivy-state-buffer ivy-last) + (find-file-noselect + (plist-get (ivy-state-extra-props ivy-last) :fname)))) + (save-selected-window + (pop-to-buffer buffer)) + (setf (ivy-state-window ivy-last) (selected-window))) + buffer)) + +(defun swiper-occur (&optional cands) "Generate a custom occur buffer for `swiper'. -When REVERT is non-nil, regenerate the current *ivy-occur* buffer. When capture groups are present in the input, print them instead of lines." - (let* ((buffer (ivy-state-buffer ivy-last)) + (let* ((buffer (swiper--occur-buffer)) (fname (propertize (with-ivy-window (if (buffer-file-name buffer) @@ -648,15 +670,14 @@ (cands (swiper--occur-cands fname - (if (not revert) - ivy--old-cands - (setq ivy--old-re nil) - (save-window-excursion - (switch-to-buffer buffer) - (if (eq (ivy-state-caller ivy-last) 'swiper) - (let ((ivy--regex-function 'swiper--re-builder)) - (ivy--filter re (swiper--candidates))) - (swiper-isearch-function ivy-text))))))) + (or cands + (save-window-excursion + (setq ivy--old-re nil) + (switch-to-buffer buffer) + (if (eq (ivy-state-caller ivy-last) 'swiper) + (let ((ivy--regex-function 'swiper--re-builder)) + (ivy--filter re (swiper--candidates))) + (swiper-isearch-function ivy-text))))))) (if (string-match-p "\\\\(" re) (insert (mapconcat #'identity @@ -667,18 +688,8 @@ (unless (eq major-mode 'ivy-occur-grep-mode) (ivy-occur-grep-mode) (font-lock-mode -1)) - (setq swiper--current-window-start nil) - (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n" - default-directory)) - (insert (format "%d candidates:\n" (length cands))) - (ivy--occur-insert-lines - (mapcar - (lambda (cand) (concat "./" cand)) - cands)) - (goto-char (point-min)) - (forward-line 4)))) - -(ivy-set-occur 'swiper 'swiper-occur) + (swiper--occur-insert-lines + (mapcar (lambda (cand) (concat "./" cand)) cands))))) (declare-function evil-set-jump "ext:evil-jumps") @@ -725,17 +736,26 @@ (cl-remove-if-not #'cdr re) ".*?") re))) - (if (zerop ivy--subexps) - (prog1 (format "^ ?\\(%s\\)" re) - (setq ivy--subexps 1)) - (format "^ %s" re)))) + (cond + ((string= re "$") + "^$") + ((zerop ivy--subexps) + (prog1 (format "^ ?\\(%s\\)" re) + (setq ivy--subexps 1))) + (t + (format "^ %s" re))))) ((eq (bound-and-true-p search-default-mode) 'char-fold-to-regexp) - (let ((subs (ivy--split str))) - (setq ivy--subexps (length subs)) - (mapconcat - (lambda (s) (format "\\(%s\\)" (char-fold-to-regexp s))) - subs - ".*?"))) + (if (string-match "\\`\\\\_<\\(.+\\)\\\\_>\\'" str) + (concat + "\\_<" + (char-fold-to-regexp (match-string 1 str)) + "\\_>") + (let ((subs (ivy--split str))) + (setq ivy--subexps (length subs)) + (mapconcat + (lambda (s) (format "\\(%s\\)" (char-fold-to-regexp s))) + subs + ".*?")))) (t (funcall re-builder str))))) re)) @@ -750,43 +770,60 @@ "When non-nil don't go back to search start on abort." :type 'boolean) -(defun swiper--ivy (candidates &optional initial-input) - "Select one of CANDIDATES and move there. +;;;###autoload +(defun swiper (&optional initial-input) + "`isearch-forward' with an overview. When non-nil, INITIAL-INPUT is the initial search pattern." - (swiper--init) - (setq swiper-invocation-face - (plist-get (text-properties-at (point)) 'face)) - (let ((preselect - (if (or swiper-use-visual-line (null search-invisible)) - (count-screen-lines - (point-min) - (save-excursion (beginning-of-visual-line) (point))) - (1- (line-number-at-pos)))) - (minibuffer-allow-text-properties t) - res) - (unwind-protect - (and - (setq res - (ivy-read - "Swiper: " - candidates - :initial-input initial-input - :keymap swiper-map - :preselect preselect - :require-match t - :update-fn #'swiper--update-input-ivy - :unwind #'swiper--cleanup - :action #'swiper--action - :re-builder #'swiper--re-builder - :history 'swiper-history - :caller 'swiper)) - (point)) - (unless (or res swiper-stay-on-quit) - (goto-char swiper--opoint)) - (unless (or res (string= ivy-text "")) - (cl-pushnew ivy-text swiper-history)) - (when swiper--reveal-mode - (reveal-mode 1))))) + (interactive) + (let ((candidates (swiper--candidates))) + (swiper--init) + (setq swiper-invocation-face + (plist-get (text-properties-at (point)) 'face)) + (let ((preselect + (if (or swiper-use-visual-line (null search-invisible)) + (count-screen-lines + (point-min) + (save-excursion (beginning-of-visual-line) (point))) + (1- (line-number-at-pos)))) + (minibuffer-allow-text-properties t) + res) + (unwind-protect + (and + (setq res + (ivy-read + "Swiper: " + candidates + :initial-input initial-input + :keymap swiper-map + :preselect + (if initial-input + (cl-position-if + (lambda (x) + (= (1+ preselect) (get-text-property 0 'swiper-line-number x))) + (progn + (setq ivy--old-re nil) + (ivy--filter initial-input candidates))) + preselect) + :require-match t + :action #'swiper--action + :re-builder #'swiper--re-builder + :history 'swiper-history + :extra-props (list :fname (buffer-file-name)) + :caller 'swiper)) + (point)) + (unless (or res swiper-stay-on-quit) + (goto-char swiper--opoint)) + (unless (or res (string= ivy-text "")) + (cl-pushnew ivy-text swiper-history)) + (setq swiper--current-window-start nil) + (when swiper--reveal-mode + (reveal-mode 1)))))) + +(ivy-configure 'swiper + :occur #'swiper-occur + :update-fn #'swiper--update-input-ivy + :unwind-fn #'swiper--cleanup + :index-fn #'ivy-recompute-index-swiper) (defun swiper-toggle-face-matching () "Toggle matching only the candidates with `swiper-invocation-face'." @@ -891,15 +928,15 @@ (with-ivy-window (swiper--cleanup) (when (> (length (ivy-state-current ivy-last)) 0) - (let ((regexps (swiper--positive-regexps ivy-text))) + (let ((regexps (swiper--positive-regexps ivy-text)) + (re-idx -1) + (case-fold-search (ivy--case-fold-p ivy-text))) (dolist (re regexps) + (setq re-idx (1+ re-idx)) (let* ((re (replace-regexp-in-string " " "\t" re)) - (str (get-text-property 0 'swiper-line-number (ivy-state-current ivy-last))) - (num (if (string-match "^[0-9]+" str) - (string-to-number (match-string 0 str)) - 0))) + (num (get-text-property 0 'swiper-line-number (ivy-state-current ivy-last)))) (unless (memq this-command '(ivy-yank-word ivy-yank-symbol ivy-yank-char @@ -924,12 +961,7 @@ (setq swiper--current-match-start (match-beginning 0)))) (isearch-range-invisible (line-beginning-position) (line-end-position)) - (when (and (swiper--recenter-p) - (or - (< (point) (window-start)) - (> (point) (window-end (ivy-state-window ivy-last) t)))) - (recenter)) - (setq swiper--current-window-start (window-start)))) + (swiper--maybe-recenter))) (swiper--add-overlays re (max @@ -941,9 +973,11 @@ (if (swiper--recenter-p) (window-end (selected-window) t) (line-end-position (window-height))) - swiper--point-max)))))))) + swiper--point-max) + nil + re-idx))))))) -(defun swiper--add-overlays (re &optional beg end wnd) +(defun swiper--add-overlays (re &optional beg end wnd re-idx) "Add overlays for RE regexp in visible part of the current buffer. BEG and END, when specified, are the point bounds. WND, when specified is the window." @@ -984,16 +1018,16 @@ (buffer-substring-no-properties (line-beginning-position) (line-end-position))))))) - (swiper--add-properties faces adder-fn))))))))) + (swiper--add-properties faces adder-fn re-idx))))))))) -(defun swiper--add-properties (faces adder-fn) +(defun swiper--add-properties (faces adder-fn &optional re-idx) (let ((mb (match-beginning 0)) (me (match-end 0))) (unless (> (- me mb) 2017) (funcall adder-fn mb me (if (zerop ivy--subexps) - (cadr faces) + (nth (1+ (mod (or re-idx 0) (1- (length faces)))) faces) (car faces)) 0))) (let ((i 1) @@ -1023,11 +1057,23 @@ (defvar evil-ex-search-direction) (declare-function evil-ex-search-activate-highlight "evil-ex") +(defun swiper--maybe-recenter () + (cond (swiper-action-recenter + (recenter)) + ((swiper--recenter-p) + (when swiper--current-window-start + (set-window-start (selected-window) swiper--current-window-start)) + (when (or + (< (point) (window-start)) + (> (point) (window-end (ivy-state-window ivy-last) t))) + (recenter)))) + (setq swiper--current-window-start (window-start))) (defun swiper--action (x) "Goto line X." - (let ((ln (1- (read (get-text-property 0 'swiper-line-number x)))) - (re (ivy--regex ivy-text))) + (let ((ln (1- (get-text-property 0 'swiper-line-number x))) + (re (ivy--regex ivy-text)) + (case-fold-search (ivy--case-fold-p ivy-text))) (if (null x) (user-error "No candidates") (with-ivy-window @@ -1045,11 +1091,7 @@ (when (and (re-search-forward re (line-end-position) t) swiper-goto-start-of-match) (goto-char (match-beginning 0))) (swiper--ensure-visible) - (cond (swiper-action-recenter - (recenter)) - ((and swiper--current-window-start - (swiper--recenter-p)) - (set-window-start (selected-window) swiper--current-window-start))) + (swiper--maybe-recenter) (when (/= (point) swiper--opoint) (unless (and transient-mark-mode mark-active) (when (eq ivy-exit 'done) @@ -1104,9 +1146,13 @@ (let ((swiper-window-width (- (- (frame-width) (if (display-graphic-p) 0 1)) 4))) (ivy-read "Swiper: " swiper-multi-candidates :action #'swiper-multi-action-2 - :unwind #'swiper--cleanup :caller 'swiper-multi))) +(ivy-configure 'swiper-multi + :unwind-fn #'swiper--cleanup + :index-fn #'ivy-recompute-index-swiper + :format-fn #'swiper--all-format-function) + (defun swiper-multi-action-1 (x) "Add X to list of selected buffers `swiper-multi-buffers'. If X is already part of the list, remove it instead. Quit the selection if @@ -1138,7 +1184,7 @@ (with-ivy-window (switch-to-buffer buffer-name) (goto-char (point-min)) - (forward-line (1- (read (get-text-property 0 'swiper-line-number x)))) + (forward-line (1- (get-text-property 0 'swiper-line-number x))) (re-search-forward (ivy--regex ivy-text) (line-end-position) t) @@ -1248,14 +1294,15 @@ (let ((swiper-window-width (- (frame-width) (if (display-graphic-p) 0 1)))) (ivy-read "swiper-all: " 'swiper-all-function :action #'swiper-all-action - :unwind #'swiper--cleanup - :update-fn 'auto :dynamic-collection t :keymap swiper-all-map :initial-input initial-input - :caller 'swiper-multi))) + :caller 'swiper-all))) -(add-to-list 'ivy-format-functions-alist '(swiper-multi . swiper--all-format-function)) +(ivy-configure 'swiper-all + :update-fn 'auto + :unwind-fn #'swiper--cleanup + :format-fn #'swiper--all-format-function) (defun swiper-all-action (x) "Move to candidate X from `swiper-all'." @@ -1285,14 +1332,6 @@ res)) ;;* `swiper-isearch' -(defvar swiper--isearch-point-history nil - "Store the current input and point history for a single search. -Each element is a cons cell of an input and a point position that -corresponds to it. - -This ensures that if the user enters \"ab\", the point will -come back to the same place as when \"a\" was initially entered.") - (defun swiper-isearch-function (str) "Collect STR matches in the current buffer for `swiper-isearch'." (with-ivy-window @@ -1306,44 +1345,79 @@ (overlays-at (point)))))) (defvar swiper--isearch-backward nil) +(defvar swiper--isearch-start-point nil) + +(defun swiper--isearch-function-1 (re backward) + (unless (string= re ".") + (let (cands) + (save-excursion + (goto-char (if backward (point-max) (point-min))) + (while (and (funcall (if backward #'re-search-backward #'re-search-forward) re nil t) + (not (if backward (bobp) (eobp)))) + (when (swiper-match-usable-p) + (let ((pos (if (or backward swiper-goto-start-of-match) + (match-beginning 0) + (point)))) + (push pos cands))) + (when (= (match-beginning 0) (match-end 0)) + (if backward + (backward-char) + (forward-char))))) + (if backward + cands + (nreverse cands))))) + +(defun swiper--isearch-next-item (re cands) + (if swiper--isearch-backward + (or + (cl-position-if + (lambda (x) + (and + (< x swiper--isearch-start-point) + (eq 0 (string-match-p + re + (buffer-substring-no-properties + x swiper--isearch-start-point))))) + cands + :from-end t) + 0) + (or + (cl-position-if + (lambda (x) (> x swiper--isearch-start-point)) + cands) + 0))) + +(defun swiper--isearch-filter-ignore-order (re-full cands) + (let (filtered-cands) + (dolist (re-cons re-full cands) + (save-excursion + (dolist (cand cands) + (goto-char cand) + (beginning-of-line) + (unless (if (re-search-forward (car re-cons) (line-end-position) t) + (not (cdr re-cons)) + (cdr re-cons)) + (push cand filtered-cands)))) + (setq cands (nreverse filtered-cands)) + (setq filtered-cands nil)))) (defun swiper--isearch-function (str) - (let* ((case-fold-search (ivy--case-fold-p str)) - (re-full (funcall ivy--regex-function str)) - (re (ivy-re-to-str re-full))) - (unless (string= re "") - (let ((re (if (string-match "\\`\\(.*\\)[\\]|\\'" re) - (match-string 1 re) - re)) - (pt-hist (cdr (assoc str swiper--isearch-point-history))) - cands - idx-found - (idx 0)) - (save-excursion - (goto-char (if swiper--isearch-backward (point-max) (point-min))) - (while (funcall (if swiper--isearch-backward #'re-search-backward #'re-search-forward) re nil t) - (when (swiper-match-usable-p) - (unless idx-found - (when (or - (eq (match-beginning 0) pt-hist) - (if swiper--isearch-backward - (<= (match-beginning 0) (cdar swiper--isearch-point-history)) - (>= (match-beginning 0) (cdar swiper--isearch-point-history)))) - (push (cons str (match-beginning 0)) swiper--isearch-point-history) - (setq idx-found idx))) - (cl-incf idx) - (let ((pos (if (or swiper--isearch-backward swiper-goto-start-of-match) - (match-beginning 0) - (point)))) - (push pos cands))))) + (let ((re-full (funcall ivy--regex-function str))) + (unless (equal re-full "") + (let* ((case-fold-search (ivy--case-fold-p str)) + (re + (if (stringp re-full) + re-full + (mapconcat + #'ivy--regex-or-literal + (delq nil (mapcar (lambda (x) (and (cdr x) (car x))) re-full)) + "\\|"))) + (cands (swiper--isearch-function-1 re swiper--isearch-backward))) + (when (consp re-full) + (setq cands (swiper--isearch-filter-ignore-order re-full cands))) (setq ivy--old-re re) - (when idx-found - (ivy-set-index (if swiper--isearch-backward - (- (length cands) idx-found 1) - idx-found))) - (setq ivy--old-cands (if swiper--isearch-backward - cands - (nreverse cands))))))) + (ivy-set-index (swiper--isearch-next-item re cands)) + (setq ivy--old-cands cands))))) (defcustom swiper-isearch-highlight-delay '(2 0.2) "When `ivy-text' is too short, delay showing the overlay. @@ -1376,9 +1450,13 @@ (setq x (get-text-property 0 'point x)))) (with-ivy-window (goto-char x) + (when (and (or (eq this-command 'ivy-previous-line-or-history) + (and (eq this-command 'ivy-done) + (eq last-command 'ivy-previous-line-or-history))) + (looking-back ivy--old-re (line-beginning-position))) + (goto-char (match-beginning 0))) (isearch-range-invisible (point) (1+ (point))) - (when swiper-action-recenter - (recenter)) + (swiper--maybe-recenter) (unless (eq ivy-exit 'done) (swiper--cleanup) (swiper--delayed-add-overlays) @@ -1386,6 +1464,16 @@ (ivy-state-window ivy-last)))) (swiper--cleanup))) +(defun swiper-action-copy (_x) + "Copy line at point and go back." + (kill-new + (buffer-substring-no-properties + (line-beginning-position) (line-end-position))) + (goto-char swiper--opoint)) + +(ivy-add-actions 'swiper-isearch '(("w" swiper-action-copy "copy"))) +(ivy-add-actions 'swiper '(("w" swiper-action-copy "copy"))) + (defun swiper-isearch-thing-at-point () "Insert `symbol-at-point' into the minibuffer of `swiper-isearch'. When not running `swiper-isearch' already, start it." @@ -1399,8 +1487,6 @@ (deactivate-mark)) (bounds-of-thing-at-point 'symbol))) (setq str (buffer-substring-no-properties (car bnd) (cdr bnd)))) - (setq swiper--isearch-point-history - (list (cons "" (car bnd)))) (insert str) (unless regionp (ivy--insert-symbol-boundaries))) @@ -1434,11 +1520,13 @@ (defun swiper-isearch-format-function (cands) (if (numberp (car-safe cands)) - (swiper--isearch-format - ivy--index ivy--length ivy--old-cands - ivy--old-re - (ivy-state-current ivy-last) - (ivy-state-buffer ivy-last)) + (if (string= ivy--old-re "^$") + "" + (swiper--isearch-format + ivy--index ivy--length ivy--old-cands + ivy--old-re + (ivy-state-current ivy-last) + (ivy-state-buffer ivy-last))) (ivy-format-function-default cands))) (defun swiper--line-at-point (pt) @@ -1518,10 +1606,8 @@ "A `swiper' that's not line-based." (interactive) (swiper--init) + (setq swiper--isearch-start-point (point)) (swiper-font-lock-ensure) - (setq swiper--isearch-point-history - (list - (cons "" (- (point) (if swiper--isearch-backward 1 0))))) (let ((ivy-fixed-height-minibuffer t) (cursor-in-non-selected-windows nil) (swiper-min-highlight 1) @@ -1537,18 +1623,24 @@ :dynamic-collection t :require-match t :action #'swiper-isearch-action - :update-fn 'auto - :unwind #'swiper--cleanup :re-builder #'swiper--re-builder :history 'swiper-history + :extra-props (list :fname (buffer-file-name)) :caller 'swiper-isearch)) (point)) (unless (or res swiper-stay-on-quit) (goto-char swiper--opoint)) (isearch-clean-overlays) + (swiper--ensure-visible) (unless (or res (string= ivy-text "")) (cl-pushnew ivy-text swiper-history))))) +(ivy-configure 'swiper-isearch + :occur #'swiper-occur + :update-fn 'auto + :unwind-fn #'swiper--cleanup + :format-fn #'swiper-isearch-format-function) + ;;;###autoload (defun swiper-isearch-backward (&optional initial-input) "Like `swiper-isearch' but the first result is before the point." @@ -1556,9 +1648,6 @@ (let ((swiper--isearch-backward t)) (swiper-isearch initial-input))) -(add-to-list 'ivy-format-functions-alist '(swiper-isearch . swiper-isearch-format-function)) -(ivy-set-occur 'swiper-isearch 'swiper-occur) - (defun swiper-isearch-toggle () "Two-way toggle between `swiper-isearch' and isearch. Intended to be bound in `isearch-mode-map' and `swiper-map'." diff -Nru emacs-ivy-0.12.0+dfsg/targets/install-deps.el emacs-ivy-0.13.0/targets/install-deps.el --- emacs-ivy-0.12.0+dfsg/targets/install-deps.el 1970-01-01 00:00:00.000000000 +0000 +++ emacs-ivy-0.13.0/targets/install-deps.el 2019-10-16 16:57:42.000000000 +0000 @@ -0,0 +1,38 @@ +(setq melpa-stable (getenv "MELPA_STABLE")) +(setq package-user-dir + (expand-file-name + (format "~/.elpa/%s/elpa" + (concat emacs-version (when melpa-stable "-stable"))))) +(message "installing in %s ...\n" package-user-dir) +(package-initialize) +(setq package-archives + (list (if melpa-stable + '("melpa-stable" . "https://stable.melpa.org/packages/") + '("melpa" . "http://melpa.org/packages/")) + ;; '("gnu" . "http://elpa.gnu.org/packages/") + )) +(package-refresh-contents) + +(defconst ivy-dev-packages + '(avy + hydra + wgrep)) + +(dolist (package ivy-dev-packages) + (if (package-installed-p package) + (message "%S: OK" package) + (condition-case nil + (progn + (package-install package) + (message "%S: ...OK" package)) + (error + (message "%S: FAIL" package))))) + +(save-window-excursion + (package-list-packages t) + (condition-case nil + (progn + (package-menu-mark-upgrades) + (package-menu-execute t)) + (error + (message "All packages up to date")))) diff -Nru emacs-ivy-0.12.0+dfsg/.travis.yml emacs-ivy-0.13.0/.travis.yml --- emacs-ivy-0.12.0+dfsg/.travis.yml 2019-07-26 03:02:07.000000000 +0000 +++ emacs-ivy-0.13.0/.travis.yml 2019-10-16 16:57:42.000000000 +0000 @@ -1,6 +1,5 @@ language: emacs-lisp env: - - EVM_EMACS=emacs-24.3-travis - EVM_EMACS=emacs-24.5-travis - EVM_EMACS=emacs-25.3-travis - EVM_EMACS=emacs-26.2-travis @@ -14,4 +13,5 @@ - evm install $EVM_EMACS --use --skip script: + - make deps - make test