diff --git a/elpa/dash-2.17.0/dash-autoloads.el b/elpa/dash-2.17.0/dash-autoloads.el deleted file mode 100755 index 9c3f8a9..0000000 --- a/elpa/dash-2.17.0/dash-autoloads.el +++ /dev/null @@ -1,26 +0,0 @@ -;;; dash-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "dash" "dash.el" (0 0 0 0)) -;;; Generated autoloads from dash.el - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dash" '("!cdr" "!cons" "--" "->" "-a" "-butlast" "-c" "-d" "-e" "-f" "-gr" "-i" "-keep" "-l" "-m" "-non" "-only-some" "-p" "-r" "-s" "-t" "-u" "-value-to-list" "-when-let" "-zip" "dash-"))) - -;;;*** - -;;;### (autoloads nil nil ("dash-pkg.el") (0 0 0 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; dash-autoloads.el ends here diff --git a/elpa/dash-2.17.0/dash-pkg.el b/elpa/dash-2.17.0/dash-pkg.el deleted file mode 100755 index 73ae4ae..0000000 --- a/elpa/dash-2.17.0/dash-pkg.el +++ /dev/null @@ -1,9 +0,0 @@ -(define-package "dash" "2.17.0" "A modern list library for Emacs" 'nil :commit "721436b04da4e2795387cb48a98ac6de37ece0fd" :keywords - ("lists") - :authors - (("Magnar Sveen" . "magnars@gmail.com")) - :maintainer - ("Magnar Sveen" . "magnars@gmail.com")) -;; Local Variables: -;; no-byte-compile: t -;; End: diff --git a/elpa/dash-2.17.0/dash.info b/elpa/dash-2.17.0/dash.info deleted file mode 100755 index ee791c4..0000000 --- a/elpa/dash-2.17.0/dash.info +++ /dev/null @@ -1,3410 +0,0 @@ -This is dash.info, produced by makeinfo version 6.5 from dash.texi. - -This manual is for ‘dash.el’ version 2.12.1. - - Copyright © 2012-2015 Magnar Sveen - - 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 - . -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* Dash: (dash.info). A modern list library for GNU Emacs -END-INFO-DIR-ENTRY - - -File: dash.info, Node: Top, Next: Installation, Up: (dir) - -dash -**** - -This manual is for ‘dash.el’ version 2.12.1. - - Copyright © 2012-2015 Magnar Sveen - - 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 - . - -* Menu: - -* Installation:: -* Functions:: -* Development:: -* Index:: - -— The Detailed Node Listing — - -Installation - -* Using in a package:: -* Syntax highlighting of dash functions:: - -Functions - -* Maps:: -* Sublist selection:: -* List to list:: -* Reductions:: -* Unfolding:: -* Predicates:: -* Partitioning:: -* Indexing:: -* Set operations:: -* Other list operations:: -* Tree operations:: -* Threading macros:: -* Binding:: -* Side-effects:: -* Destructive operations:: -* Function combinators:: - -Development - -* Contribute:: How to contribute -* Changes:: List of significant changes by version -* Contributors:: List of contributors - - -File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top - -1 Installation -************** - -It’s available on Melpa (https://melpa.org/); use ‘M-x package-install’: - -‘M-x package-install dash’ - Install the dash library. - -‘M-x package-install dash-functional’ - Optional, if you want the function combinators. - - Alternatively, you can just dump dash.el or dash-functional.el in -your load path somewhere. - -* Menu: - -* Using in a package:: -* Syntax highlighting of dash functions:: - - -File: dash.info, Node: Using in a package, Next: Syntax highlighting of dash functions, Up: Installation - -1.1 Using in a package -====================== - -Add this to the big comment block at the top: - - ;; Package-Requires: ((dash "2.12.1")) - -To get function combinators: - - ;; Package-Requires: ((dash "2.12.1") (dash-functional "1.2.0") (emacs "24")) - - -File: dash.info, Node: Syntax highlighting of dash functions, Prev: Using in a package, Up: Installation - -1.2 Syntax highlighting of dash functions -========================================= - -Font lock of dash functions in emacs lisp buffers is now optional. -Include this in your emacs settings to get syntax highlighting: - - (eval-after-load 'dash '(dash-enable-font-lock)) - - -File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top - -2 Functions -*********** - -This chapter contains reference documentation for the dash application -programming interface (API). All functions and constructs in the library -are prefixed with a dash (-). - - There are also anaphoric versions of functions where that makes -sense, prefixed with two dashes instead of one. - - For instance, while ‘-map’ takes a function to map over the list, one -can also use the anaphoric form with double dashes - which will then be -executed with ‘it’ exposed as the list item. Here’s an example: - - (-map (lambda (n) (* n n)) '(1 2 3 4)) ;; normal version - - (--map (* it it) '(1 2 3 4)) ;; anaphoric version - -Of course, the original can also be written like - - (defun square (n) (* n n)) - - (-map 'square '(1 2 3 4)) - -which demonstrates the usefulness of both versions. - -* Menu: - -* Maps:: -* Sublist selection:: -* List to list:: -* Reductions:: -* Unfolding:: -* Predicates:: -* Partitioning:: -* Indexing:: -* Set operations:: -* Other list operations:: -* Tree operations:: -* Threading macros:: -* Binding:: -* Side-effects:: -* Destructive operations:: -* Function combinators:: - - -File: dash.info, Node: Maps, Next: Sublist selection, Up: Functions - -2.1 Maps -======== - -Functions in this category take a transforming function, which is then -applied sequentially to each or selected elements of the input list. -The results are collected in order and returned as new list. - - -- Function: -map (fn list) - Return a new list consisting of the result of applying FN to the - items in LIST. - - (-map (lambda (num) (* num num)) '(1 2 3 4)) - ⇒ '(1 4 9 16) - (-map 'square '(1 2 3 4)) - ⇒ '(1 4 9 16) - (--map (* it it) '(1 2 3 4)) - ⇒ '(1 4 9 16) - - -- Function: -map-when (pred rep list) - Return a new list where the elements in LIST that do not match the - PRED function are unchanged, and where the elements in LIST that do - match the PRED function are mapped through the REP function. - - Alias: ‘-replace-where’ - - See also: ‘-update-at’ (*note -update-at::) - - (-map-when 'even? 'square '(1 2 3 4)) - ⇒ '(1 4 3 16) - (--map-when (> it 2) (* it it) '(1 2 3 4)) - ⇒ '(1 2 9 16) - (--map-when (= it 2) 17 '(1 2 3 4)) - ⇒ '(1 17 3 4) - - -- Function: -map-first (pred rep list) - Replace first item in LIST satisfying PRED with result of REP - called on this item. - - See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note - -replace-first::) - - (-map-first 'even? 'square '(1 2 3 4)) - ⇒ '(1 4 3 4) - (--map-first (> it 2) (* it it) '(1 2 3 4)) - ⇒ '(1 2 9 4) - (--map-first (= it 2) 17 '(1 2 3 2)) - ⇒ '(1 17 3 2) - - -- Function: -map-last (pred rep list) - Replace last item in LIST satisfying PRED with result of REP called - on this item. - - See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note - -replace-last::) - - (-map-last 'even? 'square '(1 2 3 4)) - ⇒ '(1 2 3 16) - (--map-last (> it 2) (* it it) '(1 2 3 4)) - ⇒ '(1 2 3 16) - (--map-last (= it 2) 17 '(1 2 3 2)) - ⇒ '(1 2 3 17) - - -- Function: -map-indexed (fn list) - Return a new list consisting of the result of (FN index item) for - each item in LIST. - - In the anaphoric form ‘--map-indexed’, the index is exposed as - symbol ‘it-index’. - - See also: ‘-each-indexed’ (*note -each-indexed::). - - (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4)) - ⇒ '(1 1 1 1) - (--map-indexed (- it it-index) '(1 2 3 4)) - ⇒ '(1 1 1 1) - - -- Function: -annotate (fn list) - Return a list of cons cells where each cell is FN applied to each - element of LIST paired with the unmodified element of LIST. - - (-annotate '1+ '(1 2 3)) - ⇒ '((2 . 1) (3 . 2) (4 . 3)) - (-annotate 'length '(("h" "e" "l" "l" "o") ("hello" "world"))) - ⇒ '((5 "h" "e" "l" "l" "o") (2 "hello" "world")) - (--annotate (< 1 it) '(0 1 2 3)) - ⇒ '((nil . 0) (nil . 1) (t . 2) (t . 3)) - - -- Function: -splice (pred fun list) - Splice lists generated by FUN in place of elements matching PRED in - LIST. - - FUN takes the element matching PRED as input. - - This function can be used as replacement for ‘,@’ in case you need - to splice several lists at marked positions (for example with - keywords). - - See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’ - (*note -insert-at::) - - (-splice 'even? (lambda (x) (list x x)) '(1 2 3 4)) - ⇒ '(1 2 2 3 4 4) - (--splice 't (list it it) '(1 2 3 4)) - ⇒ '(1 1 2 2 3 3 4 4) - (--splice (equal it :magic) '((list of) (magical) (code)) '((foo) (bar) :magic (baz))) - ⇒ '((foo) (bar) (list of) (magical) (code) (baz)) - - -- Function: -splice-list (pred new-list list) - Splice NEW-LIST in place of elements matching PRED in LIST. - - See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note - -insert-at::) - - (-splice-list 'keywordp '(a b c) '(1 :foo 2)) - ⇒ '(1 a b c 2) - (-splice-list 'keywordp nil '(1 :foo 2)) - ⇒ '(1 2) - (--splice-list (keywordp it) '(a b c) '(1 :foo 2)) - ⇒ '(1 a b c 2) - - -- Function: -mapcat (fn list) - Return the concatenation of the result of mapping FN over LIST. - Thus function FN should return a list. - - (-mapcat 'list '(1 2 3)) - ⇒ '(1 2 3) - (-mapcat (lambda (item) (list 0 item)) '(1 2 3)) - ⇒ '(0 1 0 2 0 3) - (--mapcat (list 0 it) '(1 2 3)) - ⇒ '(0 1 0 2 0 3) - - -- Function: -copy (arg) - Create a shallow copy of LIST. - - (fn LIST) - - (-copy '(1 2 3)) - ⇒ '(1 2 3) - (let ((a '(1 2 3))) (eq a (-copy a))) - ⇒ nil - - -File: dash.info, Node: Sublist selection, Next: List to list, Prev: Maps, Up: Functions - -2.2 Sublist selection -===================== - -Functions returning a sublist of the original list. - - -- Function: -filter (pred list) - Return a new list of the items in LIST for which PRED returns a - non-nil value. - - Alias: ‘-select’ - - See also: ‘-keep’ (*note -keep::), ‘-remove’ (*note -remove::). - - (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) - ⇒ '(2 4) - (-filter 'even? '(1 2 3 4)) - ⇒ '(2 4) - (--filter (= 0 (% it 2)) '(1 2 3 4)) - ⇒ '(2 4) - - -- Function: -remove (pred list) - Return a new list of the items in LIST for which PRED returns nil. - - Alias: ‘-reject’ - - See also: ‘-filter’ (*note -filter::). - - (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) - ⇒ '(1 3) - (-remove 'even? '(1 2 3 4)) - ⇒ '(1 3) - (--remove (= 0 (% it 2)) '(1 2 3 4)) - ⇒ '(1 3) - - -- Function: -remove-first (pred list) - Return a new list with the first item matching PRED removed. - - Alias: ‘-reject-first’ - - See also: ‘-remove’ (*note -remove::), ‘-map-first’ (*note - -map-first::) - - (-remove-first 'even? '(1 3 5 4 7 8 10)) - ⇒ '(1 3 5 7 8 10) - (-remove-first 'stringp '(1 2 "first" "second" "third")) - ⇒ '(1 2 "second" "third") - (--remove-first (> it 3) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 2 3 5 6 7 8 9 10) - - -- Function: -remove-last (pred list) - Return a new list with the last item matching PRED removed. - - Alias: ‘-reject-last’ - - See also: ‘-remove’ (*note -remove::), ‘-map-last’ (*note - -map-last::) - - (-remove-last 'even? '(1 3 5 4 7 8 10 11)) - ⇒ '(1 3 5 4 7 8 11) - (-remove-last 'stringp '(1 2 "last" "second" "third")) - ⇒ '(1 2 "last" "second") - (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 2 3 4 5 6 7 8 9) - - -- Function: -remove-item (item list) - Remove all occurrences of ITEM from LIST. - - Comparison is done with ‘equal’. - - (-remove-item 3 '(1 2 3 2 3 4 5 3)) - ⇒ '(1 2 2 4 5) - (-remove-item 'foo '(foo bar baz foo)) - ⇒ '(bar baz) - (-remove-item "bob" '("alice" "bob" "eve" "bob" "dave")) - ⇒ '("alice" "eve" "dave") - - -- Function: -non-nil (list) - Return all non-nil elements of LIST. - - (-non-nil '(1 nil 2 nil nil 3 4 nil 5 nil)) - ⇒ '(1 2 3 4 5) - - -- Function: -slice (list from &optional to step) - Return copy of LIST, starting from index FROM to index TO. - - FROM or TO may be negative. These values are then interpreted - modulo the length of the list. - - If STEP is a number, only each STEPth item in the resulting section - is returned. Defaults to 1. - - (-slice '(1 2 3 4 5) 1) - ⇒ '(2 3 4 5) - (-slice '(1 2 3 4 5) 0 3) - ⇒ '(1 2 3) - (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) - ⇒ '(2 4 6 8) - - -- Function: -take (n list) - Return a new list of the first N items in LIST, or all items if - there are fewer than N. - - See also: ‘-take-last’ (*note -take-last::) - - (-take 3 '(1 2 3 4 5)) - ⇒ '(1 2 3) - (-take 17 '(1 2 3 4 5)) - ⇒ '(1 2 3 4 5) - - -- Function: -take-last (n list) - Return the last N items of LIST in order. - - See also: ‘-take’ (*note -take::) - - (-take-last 3 '(1 2 3 4 5)) - ⇒ '(3 4 5) - (-take-last 17 '(1 2 3 4 5)) - ⇒ '(1 2 3 4 5) - (-take-last 1 '(1 2 3 4 5)) - ⇒ '(5) - - -- Function: -drop (n list) - Return the tail of LIST without the first N items. - - See also: ‘-drop-last’ (*note -drop-last::) - - (fn N LIST) - - (-drop 3 '(1 2 3 4 5)) - ⇒ '(4 5) - (-drop 17 '(1 2 3 4 5)) - ⇒ '() - - -- Function: -drop-last (n list) - Remove the last N items of LIST and return a copy. - - See also: ‘-drop’ (*note -drop::) - - (-drop-last 3 '(1 2 3 4 5)) - ⇒ '(1 2) - (-drop-last 17 '(1 2 3 4 5)) - ⇒ '() - - -- Function: -take-while (pred list) - Return a new list of successive items from LIST while (PRED item) - returns a non-nil value. - - (-take-while 'even? '(1 2 3 4)) - ⇒ '() - (-take-while 'even? '(2 4 5 6)) - ⇒ '(2 4) - (--take-while (< it 4) '(1 2 3 4 3 2 1)) - ⇒ '(1 2 3) - - -- Function: -drop-while (pred list) - Return the tail of LIST starting from the first item for which - (PRED item) returns nil. - - (-drop-while 'even? '(1 2 3 4)) - ⇒ '(1 2 3 4) - (-drop-while 'even? '(2 4 5 6)) - ⇒ '(5 6) - (--drop-while (< it 4) '(1 2 3 4 3 2 1)) - ⇒ '(4 3 2 1) - - -- Function: -select-by-indices (indices list) - Return a list whose elements are elements from LIST selected as - ‘(nth i list)‘ for all i from INDICES. - - (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) - ⇒ '("c" "o" "l" "o" "r") - (-select-by-indices '(2 1 0) '("a" "b" "c")) - ⇒ '("c" "b" "a") - (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) - ⇒ '("f" "a" "r" "f" "a" "l" "l" "a") - - -- Function: -select-columns (columns table) - Select COLUMNS from TABLE. - - TABLE is a list of lists where each element represents one row. It - is assumed each row has the same length. - - Each row is transformed such that only the specified COLUMNS are - selected. - - See also: ‘-select-column’ (*note -select-column::), - ‘-select-by-indices’ (*note -select-by-indices::) - - (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c))) - ⇒ '((1 3) (a c) (:a :c)) - (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c))) - ⇒ '((2) (b) (:b)) - (-select-columns nil '((1 2 3) (a b c) (:a :b :c))) - ⇒ '(nil nil nil) - - -- Function: -select-column (column table) - Select COLUMN from TABLE. - - TABLE is a list of lists where each element represents one row. It - is assumed each row has the same length. - - The single selected column is returned as a list. - - See also: ‘-select-columns’ (*note -select-columns::), - ‘-select-by-indices’ (*note -select-by-indices::) - - (-select-column 1 '((1 2 3) (a b c) (:a :b :c))) - ⇒ '(2 b :b) - - -File: dash.info, Node: List to list, Next: Reductions, Prev: Sublist selection, Up: Functions - -2.3 List to list -================ - -Functions returning a modified copy of the input list. - - -- Function: -keep (fn list) - Return a new list of the non-nil results of applying FN to the - items in LIST. - - If you want to select the original items satisfying a predicate use - ‘-filter’ (*note -filter::). - - (-keep 'cdr '((1 2 3) (4 5) (6))) - ⇒ '((2 3) (5)) - (-keep (lambda (num) (when (> num 3) (* 10 num))) '(1 2 3 4 5 6)) - ⇒ '(40 50 60) - (--keep (when (> it 3) (* 10 it)) '(1 2 3 4 5 6)) - ⇒ '(40 50 60) - - -- Function: -concat (&rest lists) - Return a new list with the concatenation of the elements in the - supplied LISTS. - - (-concat '(1)) - ⇒ '(1) - (-concat '(1) '(2)) - ⇒ '(1 2) - (-concat '(1) '(2 3) '(4)) - ⇒ '(1 2 3 4) - - -- Function: -flatten (l) - Take a nested list L and return its contents as a single, flat - list. - - Note that because ‘nil’ represents a list of zero elements (an - empty list), any mention of nil in L will disappear after - flattening. If you need to preserve nils, consider ‘-flatten-n’ - (*note -flatten-n::) or map them to some unique symbol and then map - them back. - - Conses of two atoms are considered "terminals", that is, they - aren’t flattened further. - - See also: ‘-flatten-n’ (*note -flatten-n::) - - (-flatten '((1))) - ⇒ '(1) - (-flatten '((1 (2 3) (((4 (5))))))) - ⇒ '(1 2 3 4 5) - (-flatten '(1 2 (3 . 4))) - ⇒ '(1 2 (3 . 4)) - - -- Function: -flatten-n (num list) - Flatten NUM levels of a nested LIST. - - See also: ‘-flatten’ (*note -flatten::) - - (-flatten-n 1 '((1 2) ((3 4) ((5 6))))) - ⇒ '(1 2 (3 4) ((5 6))) - (-flatten-n 2 '((1 2) ((3 4) ((5 6))))) - ⇒ '(1 2 3 4 (5 6)) - (-flatten-n 3 '((1 2) ((3 4) ((5 6))))) - ⇒ '(1 2 3 4 5 6) - - -- Function: -replace (old new list) - Replace all OLD items in LIST with NEW. - - Elements are compared using ‘equal’. - - See also: ‘-replace-at’ (*note -replace-at::) - - (-replace 1 "1" '(1 2 3 4 3 2 1)) - ⇒ '("1" 2 3 4 3 2 "1") - (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) - ⇒ '("a" "nice" "bar" "sentence" "about" "bar") - (-replace 1 2 nil) - ⇒ nil - - -- Function: -replace-first (old new list) - Replace the first occurrence of OLD with NEW in LIST. - - Elements are compared using ‘equal’. - - See also: ‘-map-first’ (*note -map-first::) - - (-replace-first 1 "1" '(1 2 3 4 3 2 1)) - ⇒ '("1" 2 3 4 3 2 1) - (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) - ⇒ '("a" "nice" "bar" "sentence" "about" "foo") - (-replace-first 1 2 nil) - ⇒ nil - - -- Function: -replace-last (old new list) - Replace the last occurrence of OLD with NEW in LIST. - - Elements are compared using ‘equal’. - - See also: ‘-map-last’ (*note -map-last::) - - (-replace-last 1 "1" '(1 2 3 4 3 2 1)) - ⇒ '(1 2 3 4 3 2 "1") - (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) - ⇒ '("a" "nice" "foo" "sentence" "about" "bar") - (-replace-last 1 2 nil) - ⇒ nil - - -- Function: -insert-at (n x list) - Return a list with X inserted into LIST at position N. - - See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note - -splice-list::) - - (-insert-at 1 'x '(a b c)) - ⇒ '(a x b c) - (-insert-at 12 'x '(a b c)) - ⇒ '(a b c x) - - -- Function: -replace-at (n x list) - Return a list with element at Nth position in LIST replaced with X. - - See also: ‘-replace’ (*note -replace::) - - (-replace-at 0 9 '(0 1 2 3 4 5)) - ⇒ '(9 1 2 3 4 5) - (-replace-at 1 9 '(0 1 2 3 4 5)) - ⇒ '(0 9 2 3 4 5) - (-replace-at 4 9 '(0 1 2 3 4 5)) - ⇒ '(0 1 2 3 9 5) - - -- Function: -update-at (n func list) - Return a list with element at Nth position in LIST replaced with - ‘(func (nth n list))‘. - - See also: ‘-map-when’ (*note -map-when::) - - (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5)) - ⇒ '(9 1 2 3 4 5) - (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5)) - ⇒ '(0 9 2 3 4 5) - (--update-at 2 (length it) '("foo" "bar" "baz" "quux")) - ⇒ '("foo" "bar" 3 "quux") - - -- Function: -remove-at (n list) - Return a list with element at Nth position in LIST removed. - - See also: ‘-remove-at-indices’ (*note -remove-at-indices::), - ‘-remove’ (*note -remove::) - - (-remove-at 0 '("0" "1" "2" "3" "4" "5")) - ⇒ '("1" "2" "3" "4" "5") - (-remove-at 1 '("0" "1" "2" "3" "4" "5")) - ⇒ '("0" "2" "3" "4" "5") - (-remove-at 2 '("0" "1" "2" "3" "4" "5")) - ⇒ '("0" "1" "3" "4" "5") - - -- Function: -remove-at-indices (indices list) - Return a list whose elements are elements from LIST without - elements selected as ‘(nth i list)‘ for all i from INDICES. - - See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note - -remove::) - - (-remove-at-indices '(0) '("0" "1" "2" "3" "4" "5")) - ⇒ '("1" "2" "3" "4" "5") - (-remove-at-indices '(0 2 4) '("0" "1" "2" "3" "4" "5")) - ⇒ '("1" "3" "5") - (-remove-at-indices '(0 5) '("0" "1" "2" "3" "4" "5")) - ⇒ '("1" "2" "3" "4") - - -File: dash.info, Node: Reductions, Next: Unfolding, Prev: List to list, Up: Functions - -2.4 Reductions -============== - -Functions reducing lists into single value. - - -- Function: -reduce-from (fn initial-value list) - Return the result of applying FN to INITIAL-VALUE and the first - item in LIST, then applying FN to that result and the 2nd item, - etc. If LIST contains no items, return INITIAL-VALUE and do not - call FN. - - In the anaphoric form ‘--reduce-from’, the accumulated value is - exposed as symbol ‘acc’. - - See also: ‘-reduce’ (*note -reduce::), ‘-reduce-r’ (*note - -reduce-r::) - - (-reduce-from '- 10 '(1 2 3)) - ⇒ 4 - (-reduce-from (lambda (memo item) (format "(%s - %d)" memo item)) "10" '(1 2 3)) - ⇒ "(((10 - 1) - 2) - 3)" - (--reduce-from (concat acc " " it) "START" '("a" "b" "c")) - ⇒ "START a b c" - - -- Function: -reduce-r-from (fn initial-value list) - Replace conses with FN, nil with INITIAL-VALUE and evaluate the - resulting expression. If LIST is empty, INITIAL-VALUE is returned - and FN is not called. - - Note: this function works the same as ‘-reduce-from’ (*note - -reduce-from::) but the operation associates from right instead of - from left. - - See also: ‘-reduce-r’ (*note -reduce-r::), ‘-reduce’ (*note - -reduce::) - - (-reduce-r-from '- 10 '(1 2 3)) - ⇒ -8 - (-reduce-r-from (lambda (item memo) (format "(%d - %s)" item memo)) "10" '(1 2 3)) - ⇒ "(1 - (2 - (3 - 10)))" - (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c")) - ⇒ "a b c END" - - -- Function: -reduce (fn list) - Return the result of applying FN to the first 2 items in LIST, then - applying FN to that result and the 3rd item, etc. If LIST contains - no items, return the result of calling FN with no arguments. If - LIST contains a single item, return that item and do not call FN. - - In the anaphoric form ‘--reduce’, the accumulated value is exposed - as symbol ‘acc’. - - See also: ‘-reduce-from’ (*note -reduce-from::), ‘-reduce-r’ (*note - -reduce-r::) - - (-reduce '- '(1 2 3 4)) - ⇒ -8 - (-reduce 'list '(1 2 3 4)) - ⇒ '(((1 2) 3) 4) - (--reduce (format "%s-%d" acc it) '(1 2 3)) - ⇒ "1-2-3" - - -- Function: -reduce-r (fn list) - Replace conses with FN and evaluate the resulting expression. The - final nil is ignored. If LIST contains no items, return the result - of calling FN with no arguments. If LIST contains a single item, - return that item and do not call FN. - - The first argument of FN is the new item, the second is the - accumulated value. - - Note: this function works the same as ‘-reduce’ (*note -reduce::) - but the operation associates from right instead of from left. - - See also: ‘-reduce-r-from’ (*note -reduce-r-from::), ‘-reduce’ - (*note -reduce::) - - (-reduce-r '- '(1 2 3 4)) - ⇒ -2 - (-reduce-r (lambda (item memo) (format "%s-%d" memo item)) '(1 2 3)) - ⇒ "3-2-1" - (--reduce-r (format "%s-%d" acc it) '(1 2 3)) - ⇒ "3-2-1" - - -- Function: -reductions-from (fn init list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce-from’ (*note -reduce-from::) for explanation of the - arguments. - - See also: ‘-reductions’ (*note -reductions::), ‘-reductions-r’ - (*note -reductions-r::), ‘-reduce-r’ (*note -reduce-r::) - - (-reductions-from (lambda (a i) (format "(%s FN %d)" a i)) "INIT" '(1 2 3 4)) - ⇒ '("INIT" "(INIT FN 1)" "((INIT FN 1) FN 2)" "(((INIT FN 1) FN 2) FN 3)" "((((INIT FN 1) FN 2) FN 3) FN 4)") - (-reductions-from 'max 0 '(2 1 4 3)) - ⇒ '(0 2 2 4 4) - (-reductions-from '* 1 '(1 2 3 4)) - ⇒ '(1 1 2 6 24) - - -- Function: -reductions-r-from (fn init list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce-r-from’ (*note -reduce-r-from::) for explanation of - the arguments. - - See also: ‘-reductions-r’ (*note -reductions-r::), ‘-reductions’ - (*note -reductions::), ‘-reduce’ (*note -reduce::) - - (-reductions-r-from (lambda (i a) (format "(%d FN %s)" i a)) "INIT" '(1 2 3 4)) - ⇒ '("(1 FN (2 FN (3 FN (4 FN INIT))))" "(2 FN (3 FN (4 FN INIT)))" "(3 FN (4 FN INIT))" "(4 FN INIT)" "INIT") - (-reductions-r-from 'max 0 '(2 1 4 3)) - ⇒ '(4 4 4 3 0) - (-reductions-r-from '* 1 '(1 2 3 4)) - ⇒ '(24 24 12 4 1) - - -- Function: -reductions (fn list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce’ (*note -reduce::) for explanation of the arguments. - - See also: ‘-reductions-from’ (*note -reductions-from::), - ‘-reductions-r’ (*note -reductions-r::), ‘-reduce-r’ (*note - -reduce-r::) - - (-reductions (lambda (a i) (format "(%s FN %d)" a i)) '(1 2 3 4)) - ⇒ '(1 "(1 FN 2)" "((1 FN 2) FN 3)" "(((1 FN 2) FN 3) FN 4)") - (-reductions '+ '(1 2 3 4)) - ⇒ '(1 3 6 10) - (-reductions '* '(1 2 3 4)) - ⇒ '(1 2 6 24) - - -- Function: -reductions-r (fn list) - Return a list of the intermediate values of the reduction. - - See ‘-reduce-r’ (*note -reduce-r::) for explanation of the - arguments. - - See also: ‘-reductions-r-from’ (*note -reductions-r-from::), - ‘-reductions’ (*note -reductions::), ‘-reduce’ (*note -reduce::) - - (-reductions-r (lambda (i a) (format "(%d FN %s)" i a)) '(1 2 3 4)) - ⇒ '("(1 FN (2 FN (3 FN 4)))" "(2 FN (3 FN 4))" "(3 FN 4)" 4) - (-reductions-r '+ '(1 2 3 4)) - ⇒ '(10 9 7 4) - (-reductions-r '* '(1 2 3 4)) - ⇒ '(24 24 12 4) - - -- Function: -count (pred list) - Counts the number of items in LIST where (PRED item) is non-nil. - - (-count 'even? '(1 2 3 4 5)) - ⇒ 2 - (--count (< it 4) '(1 2 3 4)) - ⇒ 3 - - -- Function: -sum (list) - Return the sum of LIST. - - (-sum '()) - ⇒ 0 - (-sum '(1)) - ⇒ 1 - (-sum '(1 2 3 4)) - ⇒ 10 - - -- Function: -running-sum (list) - Return a list with running sums of items in LIST. - - LIST must be non-empty. - - (-running-sum '(1 2 3 4)) - ⇒ '(1 3 6 10) - (-running-sum '(1)) - ⇒ '(1) - (-running-sum '()) - ⇒ error - - -- Function: -product (list) - Return the product of LIST. - - (-product '()) - ⇒ 1 - (-product '(1)) - ⇒ 1 - (-product '(1 2 3 4)) - ⇒ 24 - - -- Function: -running-product (list) - Return a list with running products of items in LIST. - - LIST must be non-empty. - - (-running-product '(1 2 3 4)) - ⇒ '(1 2 6 24) - (-running-product '(1)) - ⇒ '(1) - (-running-product '()) - ⇒ error - - -- Function: -inits (list) - Return all prefixes of LIST. - - (-inits '(1 2 3 4)) - ⇒ '(nil (1) (1 2) (1 2 3) (1 2 3 4)) - (-inits nil) - ⇒ '(nil) - (-inits '(1)) - ⇒ '(nil (1)) - - -- Function: -tails (list) - Return all suffixes of LIST - - (-tails '(1 2 3 4)) - ⇒ '((1 2 3 4) (2 3 4) (3 4) (4) nil) - (-tails nil) - ⇒ '(nil) - (-tails '(1)) - ⇒ '((1) nil) - - -- Function: -common-prefix (&rest lists) - Return the longest common prefix of LISTS. - - (-common-prefix '(1)) - ⇒ '(1) - (-common-prefix '(1 2) '(3 4) '(1 2)) - ⇒ nil - (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4)) - ⇒ '(1 2) - - -- Function: -common-suffix (&rest lists) - Return the longest common suffix of LISTS. - - (-common-suffix '(1)) - ⇒ '(1) - (-common-suffix '(1 2) '(3 4) '(1 2)) - ⇒ nil - (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4)) - ⇒ '(3 4) - - -- Function: -min (list) - Return the smallest value from LIST of numbers or markers. - - (-min '(0)) - ⇒ 0 - (-min '(3 2 1)) - ⇒ 1 - (-min '(1 2 3)) - ⇒ 1 - - -- Function: -min-by (comparator list) - Take a comparison function COMPARATOR and a LIST and return the - least element of the list by the comparison function. - - See also combinator ‘-on’ (*note -on::) which can transform the - values before comparing them. - - (-min-by '> '(4 3 6 1)) - ⇒ 1 - (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) - ⇒ '(1 2 3) - (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) - ⇒ '(2) - - -- Function: -max (list) - Return the largest value from LIST of numbers or markers. - - (-max '(0)) - ⇒ 0 - (-max '(3 2 1)) - ⇒ 3 - (-max '(1 2 3)) - ⇒ 3 - - -- Function: -max-by (comparator list) - Take a comparison function COMPARATOR and a LIST and return the - greatest element of the list by the comparison function. - - See also combinator ‘-on’ (*note -on::) which can transform the - values before comparing them. - - (-max-by '> '(4 3 6 1)) - ⇒ 6 - (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) - ⇒ '(3 2) - (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) - ⇒ '(1 2 3) - - -File: dash.info, Node: Unfolding, Next: Predicates, Prev: Reductions, Up: Functions - -2.5 Unfolding -============= - -Operations dual to reductions, building lists from seed value rather -than consuming a list to produce a single value. - - -- Function: -iterate (fun init n) - Return a list of iterated applications of FUN to INIT. - - This means a list of form: - - (init (fun init) (fun (fun init)) ...) - - N is the length of the returned list. - - (-iterate '1+ 1 10) - ⇒ '(1 2 3 4 5 6 7 8 9 10) - (-iterate (lambda (x) (+ x x)) 2 5) - ⇒ '(2 4 8 16 32) - (--iterate (* it it) 2 5) - ⇒ '(2 4 16 256 65536) - - -- Function: -unfold (fun seed) - Build a list from SEED using FUN. - - This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while - -reduce-r consumes a list to produce a single value, ‘-unfold’ - (*note -unfold::) takes a seed value and builds a (potentially - infinite!) list. - - FUN should return ‘nil’ to stop the generating process, or a cons - (A . B), where A will be prepended to the result and B is the new - seed. - - (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10) - ⇒ '(10 9 8 7 6 5 4 3 2 1) - (--unfold (when it (cons it (cdr it))) '(1 2 3 4)) - ⇒ '((1 2 3 4) (2 3 4) (3 4) (4)) - (--unfold (when it (cons it (butlast it))) '(1 2 3 4)) - ⇒ '((1 2 3 4) (1 2 3) (1 2) (1)) - - -File: dash.info, Node: Predicates, Next: Partitioning, Prev: Unfolding, Up: Functions - -2.6 Predicates -============== - - -- Function: -any? (pred list) - Return t if (PRED x) is non-nil for any x in LIST, else nil. - - Alias: ‘-any-p’, ‘-some?’, ‘-some-p’ - - (-any? 'even? '(1 2 3)) - ⇒ t - (-any? 'even? '(1 3 5)) - ⇒ nil - (-any? 'null '(1 3 5)) - ⇒ nil - - -- Function: -all? (pred list) - Return t if (PRED x) is non-nil for all x in LIST, else nil. - - Alias: ‘-all-p’, ‘-every?’, ‘-every-p’ - - (-all? 'even? '(1 2 3)) - ⇒ nil - (-all? 'even? '(2 4 6)) - ⇒ t - (--all? (= 0 (% it 2)) '(2 4 6)) - ⇒ t - - -- Function: -none? (pred list) - Return t if (PRED x) is nil for all x in LIST, else nil. - - Alias: ‘-none-p’ - - (-none? 'even? '(1 2 3)) - ⇒ nil - (-none? 'even? '(1 3 5)) - ⇒ t - (--none? (= 0 (% it 2)) '(1 2 3)) - ⇒ nil - - -- Function: -only-some? (pred list) - Return ‘t‘ if at least one item of LIST matches PRED and at least - one item of LIST does not match PRED. Return ‘nil‘ both if all - items match the predicate or if none of the items match the - predicate. - - Alias: ‘-only-some-p’ - - (-only-some? 'even? '(1 2 3)) - ⇒ t - (-only-some? 'even? '(1 3 5)) - ⇒ nil - (-only-some? 'even? '(2 4 6)) - ⇒ nil - - -- Function: -contains? (list element) - Return non-nil if LIST contains ELEMENT. - - The test for equality is done with ‘equal’, or with ‘-compare-fn’ - if that’s non-nil. - - Alias: ‘-contains-p’ - - (-contains? '(1 2 3) 1) - ⇒ t - (-contains? '(1 2 3) 2) - ⇒ t - (-contains? '(1 2 3) 4) - ⇒ nil - - -- Function: -same-items? (list list2) - Return true if LIST and LIST2 has the same items. - - The order of the elements in the lists does not matter. - - Alias: ‘-same-items-p’ - - (-same-items? '(1 2 3) '(1 2 3)) - ⇒ t - (-same-items? '(1 2 3) '(3 2 1)) - ⇒ t - (-same-items? '(1 2 3) '(1 2 3 4)) - ⇒ nil - - -- Function: -is-prefix? (prefix list) - Return non-nil if PREFIX is prefix of LIST. - - Alias: ‘-is-prefix-p’ - - (-is-prefix? '(1 2 3) '(1 2 3 4 5)) - ⇒ t - (-is-prefix? '(1 2 3 4 5) '(1 2 3)) - ⇒ nil - (-is-prefix? '(1 3) '(1 2 3 4 5)) - ⇒ nil - - -- Function: -is-suffix? (suffix list) - Return non-nil if SUFFIX is suffix of LIST. - - Alias: ‘-is-suffix-p’ - - (-is-suffix? '(3 4 5) '(1 2 3 4 5)) - ⇒ t - (-is-suffix? '(1 2 3 4 5) '(3 4 5)) - ⇒ nil - (-is-suffix? '(3 5) '(1 2 3 4 5)) - ⇒ nil - - -- Function: -is-infix? (infix list) - Return non-nil if INFIX is infix of LIST. - - This operation runs in O(n^2) time - - Alias: ‘-is-infix-p’ - - (-is-infix? '(1 2 3) '(1 2 3 4 5)) - ⇒ t - (-is-infix? '(2 3 4) '(1 2 3 4 5)) - ⇒ t - (-is-infix? '(3 4 5) '(1 2 3 4 5)) - ⇒ t - - -File: dash.info, Node: Partitioning, Next: Indexing, Prev: Predicates, Up: Functions - -2.7 Partitioning -================ - -Functions partitioning the input list into a list of lists. - - -- Function: -split-at (n list) - Return a list of ((-take N LIST) (-drop N LIST)), in no more than - one pass through the list. - - (-split-at 3 '(1 2 3 4 5)) - ⇒ '((1 2 3) (4 5)) - (-split-at 17 '(1 2 3 4 5)) - ⇒ '((1 2 3 4 5) nil) - - -- Function: -split-with (pred list) - Return a list of ((-take-while PRED LIST) (-drop-while PRED LIST)), - in no more than one pass through the list. - - (-split-with 'even? '(1 2 3 4)) - ⇒ '(nil (1 2 3 4)) - (-split-with 'even? '(2 4 5 6)) - ⇒ '((2 4) (5 6)) - (--split-with (< it 4) '(1 2 3 4 3 2 1)) - ⇒ '((1 2 3) (4 3 2 1)) - - -- Macro: -split-on (item list) - Split the LIST each time ITEM is found. - - Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is - discarded from the results. Empty lists are also removed from the - result. - - Comparison is done by ‘equal’. - - See also ‘-split-when’ (*note -split-when::) - - (-split-on '| '(Nil | Leaf a | Node [Tree a])) - ⇒ '((Nil) (Leaf a) (Node [Tree a])) - (-split-on ':endgroup '("a" "b" :endgroup "c" :endgroup "d" "e")) - ⇒ '(("a" "b") ("c") ("d" "e")) - (-split-on ':endgroup '("a" "b" :endgroup :endgroup "d" "e")) - ⇒ '(("a" "b") ("d" "e")) - - -- Function: -split-when (fn list) - Split the LIST on each element where FN returns non-nil. - - Unlike ‘-partition-by’ (*note -partition-by::), the "matched" - element is discarded from the results. Empty lists are also - removed from the result. - - This function can be thought of as a generalization of - ‘split-string’. - - (-split-when 'even? '(1 2 3 4 5 6)) - ⇒ '((1) (3) (5)) - (-split-when 'even? '(1 2 3 4 6 8 9)) - ⇒ '((1) (3) (9)) - (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args)) - ⇒ '((a b) (c d) (args)) - - -- Function: -separate (pred list) - Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one - pass through the list. - - (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7)) - ⇒ '((2 4 6) (1 3 5 7)) - (--separate (< it 5) '(3 7 5 9 3 2 1 4 6)) - ⇒ '((3 3 2 1 4) (7 5 9 6)) - (-separate 'cdr '((1 2) (1) (1 2 3) (4))) - ⇒ '(((1 2) (1 2 3)) ((1) (4))) - - -- Function: -partition (n list) - Return a new list with the items in LIST grouped into N-sized - sublists. If there are not enough items to make the last group - N-sized, those items are discarded. - - (-partition 2 '(1 2 3 4 5 6)) - ⇒ '((1 2) (3 4) (5 6)) - (-partition 2 '(1 2 3 4 5 6 7)) - ⇒ '((1 2) (3 4) (5 6)) - (-partition 3 '(1 2 3 4 5 6 7)) - ⇒ '((1 2 3) (4 5 6)) - - -- Function: -partition-all (n list) - Return a new list with the items in LIST grouped into N-sized - sublists. The last group may contain less than N items. - - (-partition-all 2 '(1 2 3 4 5 6)) - ⇒ '((1 2) (3 4) (5 6)) - (-partition-all 2 '(1 2 3 4 5 6 7)) - ⇒ '((1 2) (3 4) (5 6) (7)) - (-partition-all 3 '(1 2 3 4 5 6 7)) - ⇒ '((1 2 3) (4 5 6) (7)) - - -- Function: -partition-in-steps (n step list) - Return a new list with the items in LIST grouped into N-sized - sublists at offsets STEP apart. If there are not enough items to - make the last group N-sized, those items are discarded. - - (-partition-in-steps 2 1 '(1 2 3 4)) - ⇒ '((1 2) (2 3) (3 4)) - (-partition-in-steps 3 2 '(1 2 3 4)) - ⇒ '((1 2 3)) - (-partition-in-steps 3 2 '(1 2 3 4 5)) - ⇒ '((1 2 3) (3 4 5)) - - -- Function: -partition-all-in-steps (n step list) - Return a new list with the items in LIST grouped into N-sized - sublists at offsets STEP apart. The last groups may contain less - than N items. - - (-partition-all-in-steps 2 1 '(1 2 3 4)) - ⇒ '((1 2) (2 3) (3 4) (4)) - (-partition-all-in-steps 3 2 '(1 2 3 4)) - ⇒ '((1 2 3) (3 4)) - (-partition-all-in-steps 3 2 '(1 2 3 4 5)) - ⇒ '((1 2 3) (3 4 5) (5)) - - -- Function: -partition-by (fn list) - Apply FN to each item in LIST, splitting it each time FN returns a - new value. - - (-partition-by 'even? '()) - ⇒ '() - (-partition-by 'even? '(1 1 2 2 2 3 4 6 8)) - ⇒ '((1 1) (2 2 2) (3) (4 6 8)) - (--partition-by (< it 3) '(1 2 3 4 3 2 1)) - ⇒ '((1 2) (3 4 3) (2 1)) - - -- Function: -partition-by-header (fn list) - Apply FN to the first item in LIST. That is the header value. - Apply FN to each item in LIST, splitting it each time FN returns - the header value, but only after seeing at least one other value - (the body). - - (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4)) - ⇒ '((1 2 3) (1 2) (1 2 3 4)) - (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0)) - ⇒ '((1 2 0) (1 0) (1 2 3 0)) - (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1)) - ⇒ '((2 1 1 1) (4 1 3 5) (6 6 1)) - - -- Function: -partition-after-pred (pred list) - Partition directly after each time PRED is true on an element of - LIST. - - (-partition-after-pred #'odd? '()) - ⇒ '() - (-partition-after-pred #'odd? '(1)) - ⇒ '((1)) - (-partition-after-pred #'odd? '(0 1)) - ⇒ '((0 1)) - - -- Function: -partition-before-pred (pred list) - Partition directly before each time PRED is true on an element of - LIST. - - (-partition-before-pred #'odd? '()) - ⇒ '() - (-partition-before-pred #'odd? '(1)) - ⇒ '((1)) - (-partition-before-pred #'odd? '(0 1)) - ⇒ '((0) (1)) - - -- Function: -partition-before-item (item list) - Partition directly before each time ITEM appears in LIST. - - (-partition-before-item 3 '()) - ⇒ '() - (-partition-before-item 3 '(1)) - ⇒ '((1)) - (-partition-before-item 3 '(3)) - ⇒ '((3)) - - -- Function: -partition-after-item (item list) - Partition directly after each time ITEM appears in LIST. - - (-partition-after-item 3 '()) - ⇒ '() - (-partition-after-item 3 '(1)) - ⇒ '((1)) - (-partition-after-item 3 '(3)) - ⇒ '((3)) - - -- Function: -group-by (fn list) - Separate LIST into an alist whose keys are FN applied to the - elements of LIST. Keys are compared by ‘equal’. - - (-group-by 'even? '()) - ⇒ '() - (-group-by 'even? '(1 1 2 2 2 3 4 6 8)) - ⇒ '((nil 1 1 3) (t 2 2 2 4 6 8)) - (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) - ⇒ '(("a" "a/b" "a/e") ("c" "c/d")) - - -File: dash.info, Node: Indexing, Next: Set operations, Prev: Partitioning, Up: Functions - -2.8 Indexing -============ - -Return indices of elements based on predicates, sort elements by indices -etc. - - -- Function: -elem-index (elem list) - Return the index of the first element in the given LIST which is - equal to the query element ELEM, or nil if there is no such - element. - - (-elem-index 2 '(6 7 8 2 3 4)) - ⇒ 3 - (-elem-index "bar" '("foo" "bar" "baz")) - ⇒ 1 - (-elem-index '(1 2) '((3) (5 6) (1 2) nil)) - ⇒ 2 - - -- Function: -elem-indices (elem list) - Return the indices of all elements in LIST equal to the query - element ELEM, in ascending order. - - (-elem-indices 2 '(6 7 8 2 3 4 2 1)) - ⇒ '(3 6) - (-elem-indices "bar" '("foo" "bar" "baz")) - ⇒ '(1) - (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) - ⇒ '(1 3) - - -- Function: -find-index (pred list) - Take a predicate PRED and a LIST and return the index of the first - element in the list satisfying the predicate, or nil if there is no - such element. - - See also ‘-first’ (*note -first::). - - (-find-index 'even? '(2 4 1 6 3 3 5 8)) - ⇒ 0 - (--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) - ⇒ 3 - (-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) - ⇒ 1 - - -- Function: -find-last-index (pred list) - Take a predicate PRED and a LIST and return the index of the last - element in the list satisfying the predicate, or nil if there is no - such element. - - See also ‘-last’ (*note -last::). - - (-find-last-index 'even? '(2 4 1 6 3 3 5 8)) - ⇒ 7 - (--find-last-index (< 5 it) '(2 7 1 6 3 8 5 2)) - ⇒ 5 - (-find-last-index (-partial 'string-lessp "baz") '("q" "foo" "baz")) - ⇒ 1 - - -- Function: -find-indices (pred list) - Return the indices of all elements in LIST satisfying the predicate - PRED, in ascending order. - - (-find-indices 'even? '(2 4 1 6 3 3 5 8)) - ⇒ '(0 1 3 7) - (--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) - ⇒ '(3 7) - (-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) - ⇒ '(1) - - -- Function: -grade-up (comparator list) - Grade elements of LIST using COMPARATOR relation, yielding a - permutation vector such that applying this permutation to LIST - sorts it in ascending order. - - (-grade-up '< '(3 1 4 2 1 3 3)) - ⇒ '(1 4 3 0 5 6 2) - (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up '< l) l)) - ⇒ '(1 1 2 3 3 3 4) - - -- Function: -grade-down (comparator list) - Grade elements of LIST using COMPARATOR relation, yielding a - permutation vector such that applying this permutation to LIST - sorts it in descending order. - - (-grade-down '< '(3 1 4 2 1 3 3)) - ⇒ '(2 0 5 6 3 1 4) - (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down '< l) l)) - ⇒ '(4 3 3 3 2 1 1) - - -File: dash.info, Node: Set operations, Next: Other list operations, Prev: Indexing, Up: Functions - -2.9 Set operations -================== - -Operations pretending lists are sets. - - -- Function: -union (list list2) - Return a new list containing the elements of LIST and elements of - LIST2 that are not in LIST. The test for equality is done with - ‘equal’, or with ‘-compare-fn’ if that’s non-nil. - - (-union '(1 2 3) '(3 4 5)) - ⇒ '(1 2 3 4 5) - (-union '(1 2 3 4) '()) - ⇒ '(1 2 3 4) - (-union '(1 1 2 2) '(3 2 1)) - ⇒ '(1 1 2 2 3) - - -- Function: -difference (list list2) - Return a new list with only the members of LIST that are not in - LIST2. The test for equality is done with ‘equal’, or with - ‘-compare-fn’ if that’s non-nil. - - (-difference '() '()) - ⇒ '() - (-difference '(1 2 3) '(4 5 6)) - ⇒ '(1 2 3) - (-difference '(1 2 3 4) '(3 4 5 6)) - ⇒ '(1 2) - - -- Function: -intersection (list list2) - Return a new list containing only the elements that are members of - both LIST and LIST2. The test for equality is done with ‘equal’, - or with ‘-compare-fn’ if that’s non-nil. - - (-intersection '() '()) - ⇒ '() - (-intersection '(1 2 3) '(4 5 6)) - ⇒ '() - (-intersection '(1 2 3 4) '(3 4 5 6)) - ⇒ '(3 4) - - -- Function: -powerset (list) - Return the power set of LIST. - - (-powerset '()) - ⇒ '(nil) - (-powerset '(x y z)) - ⇒ '((x y z) (x y) (x z) (x) (y z) (y) (z) nil) - - -- Function: -permutations (list) - Return the permutations of LIST. - - (-permutations '()) - ⇒ '(nil) - (-permutations '(1 2)) - ⇒ '((1 2) (2 1)) - (-permutations '(a b c)) - ⇒ '((a b c) (a c b) (b a c) (b c a) (c a b) (c b a)) - - -- Function: -distinct (list) - Return a new list with all duplicates removed. The test for - equality is done with ‘equal’, or with ‘-compare-fn’ if that’s - non-nil. - - Alias: ‘-uniq’ - - (-distinct '()) - ⇒ '() - (-distinct '(1 2 2 4)) - ⇒ '(1 2 4) - (-distinct '(t t t)) - ⇒ '(t) - - -File: dash.info, Node: Other list operations, Next: Tree operations, Prev: Set operations, Up: Functions - -2.10 Other list operations -========================== - -Other list functions not fit to be classified elsewhere. - - -- Function: -rotate (n list) - Rotate LIST N places to the right. With N negative, rotate to the - left. The time complexity is O(n). - - (-rotate 3 '(1 2 3 4 5 6 7)) - ⇒ '(5 6 7 1 2 3 4) - (-rotate -3 '(1 2 3 4 5 6 7)) - ⇒ '(4 5 6 7 1 2 3) - (-rotate 16 '(1 2 3 4 5 6 7)) - ⇒ '(6 7 1 2 3 4 5) - - -- Function: -repeat (n x) - Return a list with X repeated N times. Return nil if N is less - than 1. - - (-repeat 3 :a) - ⇒ '(:a :a :a) - (-repeat 1 :a) - ⇒ '(:a) - (-repeat 0 :a) - ⇒ nil - - -- Function: -cons* (&rest args) - Make a new list from the elements of ARGS. - - The last 2 members of ARGS are used as the final cons of the result - so if the final member of ARGS is not a list the result is a dotted - list. - - (-cons* 1 2) - ⇒ '(1 . 2) - (-cons* 1 2 3) - ⇒ '(1 2 . 3) - (-cons* 1) - ⇒ 1 - - -- Function: -snoc (list elem &rest elements) - Append ELEM to the end of the list. - - This is like ‘cons’, but operates on the end of list. - - If ELEMENTS is non nil, append these to the list as well. - - (-snoc '(1 2 3) 4) - ⇒ '(1 2 3 4) - (-snoc '(1 2 3) 4 5 6) - ⇒ '(1 2 3 4 5 6) - (-snoc '(1 2 3) '(4 5 6)) - ⇒ '(1 2 3 (4 5 6)) - - -- Function: -interpose (sep list) - Return a new list of all elements in LIST separated by SEP. - - (-interpose "-" '()) - ⇒ '() - (-interpose "-" '("a")) - ⇒ '("a") - (-interpose "-" '("a" "b" "c")) - ⇒ '("a" "-" "b" "-" "c") - - -- Function: -interleave (&rest lists) - Return a new list of the first item in each list, then the second - etc. - - (-interleave '(1 2) '("a" "b")) - ⇒ '(1 "a" 2 "b") - (-interleave '(1 2) '("a" "b") '("A" "B")) - ⇒ '(1 "a" "A" 2 "b" "B") - (-interleave '(1 2 3) '("a" "b")) - ⇒ '(1 "a" 2 "b") - - -- Function: -zip-with (fn list1 list2) - Zip the two lists LIST1 and LIST2 using a function FN. This - function is applied pairwise taking as first argument element of - LIST1 and as second argument element of LIST2 at corresponding - position. - - The anaphoric form ‘--zip-with’ binds the elements from LIST1 as - symbol ‘it’, and the elements from LIST2 as symbol ‘other’. - - (-zip-with '+ '(1 2 3) '(4 5 6)) - ⇒ '(5 7 9) - (-zip-with 'cons '(1 2 3) '(4 5 6)) - ⇒ '((1 . 4) (2 . 5) (3 . 6)) - (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) - ⇒ '("Batman and Robin" "Jekyll and Hyde") - - -- Function: -zip (&rest lists) - Zip LISTS together. Group the head of each list, followed by the - second elements of each list, and so on. The lengths of the - returned groupings are equal to the length of the shortest input - list. - - If two lists are provided as arguments, return the groupings as a - list of cons cells. Otherwise, return the groupings as a list of - lists. - - Use ‘-zip-lists’ (*note -zip-lists::) if you need the return value - to always be a list of lists. - - Alias: ‘-zip-pair’ - - See also: ‘-zip-lists’ (*note -zip-lists::) - - (-zip '(1 2 3) '(4 5 6)) - ⇒ '((1 . 4) (2 . 5) (3 . 6)) - (-zip '(1 2 3) '(4 5 6 7)) - ⇒ '((1 . 4) (2 . 5) (3 . 6)) - (-zip '(1 2) '(3 4 5) '(6)) - ⇒ '((1 3 6)) - - -- Function: -zip-lists (&rest lists) - Zip LISTS together. Group the head of each list, followed by the - second elements of each list, and so on. The lengths of the - returned groupings are equal to the length of the shortest input - list. - - The return value is always list of lists, which is a difference - from ‘-zip-pair’ which returns a cons-cell in case two input lists - are provided. - - See also: ‘-zip’ (*note -zip::) - - (-zip-lists '(1 2 3) '(4 5 6)) - ⇒ '((1 4) (2 5) (3 6)) - (-zip-lists '(1 2 3) '(4 5 6 7)) - ⇒ '((1 4) (2 5) (3 6)) - (-zip-lists '(1 2) '(3 4 5) '(6)) - ⇒ '((1 3 6)) - - -- Function: -zip-fill (fill-value &rest lists) - Zip LISTS, with FILL-VALUE padded onto the shorter lists. The - lengths of the returned groupings are equal to the length of the - longest input list. - - (-zip-fill 0 '(1 2 3 4 5) '(6 7 8 9)) - ⇒ '((1 . 6) (2 . 7) (3 . 8) (4 . 9) (5 . 0)) - - -- Function: -unzip (lists) - Unzip LISTS. - - This works just like ‘-zip’ (*note -zip::) but takes a list of - lists instead of a variable number of arguments, such that - - (-unzip (-zip L1 L2 L3 ...)) - - is identity (given that the lists are the same length). - - Note in particular that calling this on a list of two lists will - return a list of cons-cells such that the aboce identity works. - - See also: ‘-zip’ (*note -zip::) - - (-unzip (-zip '(1 2 3) '(a b c) '("e" "f" "g"))) - ⇒ '((1 2 3) (a b c) ("e" "f" "g")) - (-unzip '((1 2) (3 4) (5 6) (7 8) (9 10))) - ⇒ '((1 3 5 7 9) (2 4 6 8 10)) - (-unzip '((1 2) (3 4))) - ⇒ '((1 . 3) (2 . 4)) - - -- Function: -cycle (list) - Return an infinite copy of LIST that will cycle through the - elements and repeat from the beginning. - - (-take 5 (-cycle '(1 2 3))) - ⇒ '(1 2 3 1 2) - (-take 7 (-cycle '(1 "and" 3))) - ⇒ '(1 "and" 3 1 "and" 3 1) - (-zip (-cycle '(1 2 3)) '(1 2)) - ⇒ '((1 . 1) (2 . 2)) - - -- Function: -pad (fill-value &rest lists) - Appends FILL-VALUE to the end of each list in LISTS such that they - will all have the same length. - - (-pad 0 '()) - ⇒ '(nil) - (-pad 0 '(1)) - ⇒ '((1)) - (-pad 0 '(1 2 3) '(4 5)) - ⇒ '((1 2 3) (4 5 0)) - - -- Function: -table (fn &rest lists) - Compute outer product of LISTS using function FN. - - The function FN should have the same arity as the number of - supplied lists. - - The outer product is computed by applying fn to all possible - combinations created by taking one element from each list in order. - The dimension of the result is (length lists). - - See also: ‘-table-flat’ (*note -table-flat::) - - (-table '* '(1 2 3) '(1 2 3)) - ⇒ '((1 2 3) (2 4 6) (3 6 9)) - (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4))) - ⇒ '((7 15) (10 22)) - (apply '-table 'list (-repeat 3 '(1 2))) - ⇒ '((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2)))) - - -- Function: -table-flat (fn &rest lists) - Compute flat outer product of LISTS using function FN. - - The function FN should have the same arity as the number of - supplied lists. - - The outer product is computed by applying fn to all possible - combinations created by taking one element from each list in order. - The results are flattened, ignoring the tensor structure of the - result. This is equivalent to calling: - - (-flatten-n (1- (length lists)) (apply ’-table fn lists)) - - but the implementation here is much more efficient. - - See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note - -table::) - - (-table-flat 'list '(1 2 3) '(a b c)) - ⇒ '((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c)) - (-table-flat '* '(1 2 3) '(1 2 3)) - ⇒ '(1 2 3 2 4 6 3 6 9) - (apply '-table-flat 'list (-repeat 3 '(1 2))) - ⇒ '((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2)) - - -- Function: -first (pred list) - Return the first x in LIST where (PRED x) is non-nil, else nil. - - To get the first item in the list no questions asked, use ‘car’. - - Alias: ‘-find’ - - (-first 'even? '(1 2 3)) - ⇒ 2 - (-first 'even? '(1 3 5)) - ⇒ nil - (-first 'null '(1 3 5)) - ⇒ nil - - -- Function: -some (pred list) - Return (PRED x) for the first LIST item where (PRED x) is non-nil, - else nil. - - Alias: ‘-any’ - - (-some 'even? '(1 2 3)) - ⇒ t - (-some 'null '(1 2 3)) - ⇒ nil - (-some 'null '(1 2 nil)) - ⇒ t - - -- Function: -last (pred list) - Return the last x in LIST where (PRED x) is non-nil, else nil. - - (-last 'even? '(1 2 3 4 5 6 3 3 3)) - ⇒ 6 - (-last 'even? '(1 3 7 5 9)) - ⇒ nil - (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one")) - ⇒ "short" - - -- Function: -first-item (list) - Return the first item of LIST, or nil on an empty list. - - See also: ‘-second-item’ (*note -second-item::), ‘-last-item’ - (*note -last-item::). - - (fn LIST) - - (-first-item '(1 2 3)) - ⇒ 1 - (-first-item nil) - ⇒ nil - (let ((list (list 1 2 3))) (setf (-first-item list) 5) list) - ⇒ '(5 2 3) - - -- Function: -second-item (arg1) - Return the second item of LIST, or nil if LIST is too short. - - See also: ‘-third-item’ (*note -third-item::). - - (fn LIST) - - (-second-item '(1 2 3)) - ⇒ 2 - (-second-item nil) - ⇒ nil - - -- Function: -third-item (arg1) - Return the third item of LIST, or nil if LIST is too short. - - See also: ‘-fourth-item’ (*note -fourth-item::). - - (fn LIST) - - (-third-item '(1 2 3)) - ⇒ 3 - (-third-item nil) - ⇒ nil - - -- Function: -fourth-item (list) - Return the fourth item of LIST, or nil if LIST is too short. - - See also: ‘-fifth-item’ (*note -fifth-item::). - - (-fourth-item '(1 2 3 4)) - ⇒ 4 - (-fourth-item nil) - ⇒ nil - - -- Function: -fifth-item (list) - Return the fifth item of LIST, or nil if LIST is too short. - - See also: ‘-last-item’ (*note -last-item::). - - (-fifth-item '(1 2 3 4 5)) - ⇒ 5 - (-fifth-item nil) - ⇒ nil - - -- Function: -last-item (list) - Return the last item of LIST, or nil on an empty list. - - (-last-item '(1 2 3)) - ⇒ 3 - (-last-item nil) - ⇒ nil - (let ((list (list 1 2 3))) (setf (-last-item list) 5) list) - ⇒ '(1 2 5) - - -- Function: -butlast (list) - Return a list of all items in list except for the last. - - (-butlast '(1 2 3)) - ⇒ '(1 2) - (-butlast '(1 2)) - ⇒ '(1) - (-butlast '(1)) - ⇒ nil - - -- Function: -sort (comparator list) - Sort LIST, stably, comparing elements using COMPARATOR. Return the - sorted list. LIST is NOT modified by side effects. COMPARATOR is - called with two elements of LIST, and should return non-nil if the - first element should sort before the second. - - (-sort '< '(3 1 2)) - ⇒ '(1 2 3) - (-sort '> '(3 1 2)) - ⇒ '(3 2 1) - (--sort (< it other) '(3 1 2)) - ⇒ '(1 2 3) - - -- Function: -list (&rest args) - Return a list with ARGS. - - If first item of ARGS is already a list, simply return ARGS. If - not, return a list with ARGS as elements. - - (-list 1) - ⇒ '(1) - (-list 1 2 3) - ⇒ '(1 2 3) - (-list '(1 2 3)) - ⇒ '(1 2 3) - - -- Function: -fix (fn list) - Compute the (least) fixpoint of FN with initial input LIST. - - FN is called at least once, results are compared with ‘equal’. - - (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3 4 5 6))) - ⇒ '((1) (2) (3) (4) (5) (6)) - (let ((data '(("starwars" "scifi") ("jedi" "starwars" "warrior")))) (--fix (-uniq (--mapcat (cons it (cdr (assoc it data))) it)) '("jedi" "book"))) - ⇒ '("jedi" "starwars" "warrior" "scifi" "book") - - -File: dash.info, Node: Tree operations, Next: Threading macros, Prev: Other list operations, Up: Functions - -2.11 Tree operations -==================== - -Functions pretending lists are trees. - - -- Function: -tree-seq (branch children tree) - Return a sequence of the nodes in TREE, in depth-first search - order. - - BRANCH is a predicate of one argument that returns non-nil if the - passed argument is a branch, that is, a node that can have - children. - - CHILDREN is a function of one argument that returns the children of - the passed branch node. - - Non-branch nodes are simply copied. - - (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7)))) - ⇒ '((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7) - (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7)))) - ⇒ '((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1) - (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]]) - ⇒ '([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7) - - -- Function: -tree-map (fn tree) - Apply FN to each element of TREE while preserving the tree - structure. - - (-tree-map '1+ '(1 (2 3) (4 (5 6) 7))) - ⇒ '(2 (3 4) (5 (6 7) 8)) - (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4)) - ⇒ '((1 . 2) ((2 . 4) (3 . 8)) (4 . 16)) - (--tree-map (length it) '("" ("

" "text" "

") "")) - ⇒ '(6 (3 4 4) 7) - - -- Function: -tree-map-nodes (pred fun tree) - Call FUN on each node of TREE that satisfies PRED. - - If PRED returns nil, continue descending down this node. If PRED - returns non-nil, apply FUN to this node and do not descend further. - - (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8))) - ⇒ '(1 5 4 (5 13 8)) - (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8))) - ⇒ '(1 ":foo" 4 ((5 6 ":bar") ":baz" 8)) - (--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d)))) - ⇒ '(with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode))) - - -- Function: -tree-reduce (fn tree) - Use FN to reduce elements of list TREE. If elements of TREE are - lists themselves, apply the reduction recursively. - - FN is first applied to first element of the list and second - element, then on this result and third element from the list etc. - - See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of - zero or one element handled. - - (-tree-reduce '+ '(1 (2 3) (4 5))) - ⇒ 15 - (-tree-reduce 'concat '("strings" (" on" " various") ((" levels")))) - ⇒ "strings on various levels" - (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "")))) '(body (p "some words") (div "more" (b "bold") "words"))) - ⇒ "

some words

more bold words
" - - -- Function: -tree-reduce-from (fn init-value tree) - Use FN to reduce elements of list TREE. If elements of TREE are - lists themselves, apply the reduction recursively. - - FN is first applied to INIT-VALUE and first element of the list, - then on this result and second element from the list etc. - - The initial value is ignored on cons pairs as they always contain - two elements. - - (-tree-reduce-from '+ 1 '(1 (1 1) ((1)))) - ⇒ 8 - (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7))) - ⇒ '((7 6) ((5 4) 3 2) 1) - - -- Function: -tree-mapreduce (fn folder tree) - Apply FN to each element of TREE, and make a list of the results. - If elements of TREE are lists themselves, apply FN recursively to - elements of these nested lists. - - Then reduce the resulting lists using FOLDER and initial value - INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). - - This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::) - after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it - only traverse the structure once. - - (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9)))) - ⇒ '(1 2 3 4 5 6 7 8 9) - (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3)))) - ⇒ 9 - (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3)))) - ⇒ 3 - - -- Function: -tree-mapreduce-from (fn folder init-value tree) - Apply FN to each element of TREE, and make a list of the results. - If elements of TREE are lists themselves, apply FN recursively to - elements of these nested lists. - - Then reduce the resulting lists using FOLDER and initial value - INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). - - This is the same as calling ‘-tree-reduce-from’ (*note - -tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is - twice as fast as it only traverse the structure once. - - (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9)))) - ⇒ 362880 - (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3)))) - ⇒ '(2 (4 (8 18) (4 2)) (14 (8 6))) - (concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elips-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam))))) - ⇒ "{elips-mode : {foo : {bar -> booze{, baz -> qux{, c-mode : {foo -> bla, bum -> bam}}" - - -- Function: -clone (list) - Create a deep copy of LIST. The new list has the same elements and - structure but all cons are replaced with new ones. This is useful - when you need to clone a structure such as plist or alist. - - (let* ((a '(1 2 3)) (b (-clone a))) (nreverse a) b) - ⇒ '(1 2 3) - - -File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations, Up: Functions - -2.12 Threading macros -===================== - - -- Macro: -> (x &optional form &rest more) - Thread the expr through the forms. Insert X as the second item in - the first form, making a list of it if it is not a list already. - If there are more forms, insert the first form as the second item - in second form, etc. - - (-> '(2 3 5)) - ⇒ '(2 3 5) - (-> '(2 3 5) (append '(8 13))) - ⇒ '(2 3 5 8 13) - (-> '(2 3 5) (append '(8 13)) (-slice 1 -1)) - ⇒ '(3 5 8) - - -- Macro: ->> (x &optional form &rest more) - Thread the expr through the forms. Insert X as the last item in - the first form, making a list of it if it is not a list already. - If there are more forms, insert the first form as the last item in - second form, etc. - - (->> '(1 2 3) (-map 'square)) - ⇒ '(1 4 9) - (->> '(1 2 3) (-map 'square) (-remove 'even?)) - ⇒ '(1 9) - (->> '(1 2 3) (-map 'square) (-reduce '+)) - ⇒ 14 - - -- Macro: --> (x &rest forms) - Starting with the value of X, thread each expression through FORMS. - - Insert X at the position signified by the symbol ‘it’ in the first - form. If there are more forms, insert the first form at the - position signified by ‘it’ in in second form, etc. - - (--> "def" (concat "abc" it "ghi")) - ⇒ "abcdefghi" - (--> "def" (concat "abc" it "ghi") (upcase it)) - ⇒ "ABCDEFGHI" - (--> "def" (concat "abc" it "ghi") upcase) - ⇒ "ABCDEFGHI" - - -- Macro: -as-> (value variable &rest forms) - Starting with VALUE, thread VARIABLE through FORMS. - - In the first form, bind VARIABLE to VALUE. In the second form, - bind VARIABLE to the result of the first form, and so forth. - - (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var)) - ⇒ '(8) - (-as-> 3 my-var 1+) - ⇒ 4 - (-as-> 3 my-var) - ⇒ 3 - - -- Macro: -some-> (x &optional form &rest more) - When expr is non-nil, thread it through the first form (via ‘->’ - (*note ->::)), and when that result is non-nil, through the next - form, etc. - - (-some-> '(2 3 5)) - ⇒ '(2 3 5) - (-some-> 5 square) - ⇒ 25 - (-some-> 5 even? square) - ⇒ nil - - -- Macro: -some->> (x &optional form &rest more) - When expr is non-nil, thread it through the first form (via ‘->>’ - (*note ->>::)), and when that result is non-nil, through the next - form, etc. - - (-some->> '(1 2 3) (-map 'square)) - ⇒ '(1 4 9) - (-some->> '(1 3 5) (-last 'even?) (+ 100)) - ⇒ nil - (-some->> '(2 4 6) (-last 'even?) (+ 100)) - ⇒ 106 - - -- Macro: -some--> (x &optional form &rest more) - When expr in non-nil, thread it through the first form (via ‘-->’ - (*note -->::)), and when that result is non-nil, through the next - form, etc. - - (-some--> "def" (concat "abc" it "ghi")) - ⇒ "abcdefghi" - (-some--> nil (concat "abc" it "ghi")) - ⇒ nil - (-some--> '(1 3 5) (-filter 'even? it) (append it it) (-map 'square it)) - ⇒ nil - - -File: dash.info, Node: Binding, Next: Side-effects, Prev: Threading macros, Up: Functions - -2.13 Binding -============ - -Convenient versions of ‘let‘ and ‘let*‘ constructs combined with flow -control. - - -- Macro: -when-let (var-val &rest body) - If VAL evaluates to non-nil, bind it to VAR and execute body. - - Note: binding is done according to ‘-let’ (*note -let::). - - (fn (VAR VAL) &rest BODY) - - (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2)) - ⇒ 5 - (-when-let ((&plist :foo foo) (list :foo "foo")) foo) - ⇒ "foo" - (-when-let ((&plist :foo foo) (list :bar "bar")) foo) - ⇒ nil - - -- Macro: -when-let* (vars-vals &rest body) - If all VALS evaluate to true, bind them to their corresponding VARS - and execute body. VARS-VALS should be a list of (VAR VAL) pairs. - - Note: binding is done according to ‘-let*’ (*note -let*::). VALS - are evaluated sequentially, and evaluation stops after the first - nil VAL is encountered. - - (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z)) - ⇒ 15 - (-when-let* ((x 5) (y nil) (z 7)) (+ x y z)) - ⇒ nil - - -- Macro: -if-let (var-val then &rest else) - If VAL evaluates to non-nil, bind it to VAR and do THEN, otherwise - do ELSE. - - Note: binding is done according to ‘-let’ (*note -let::). - - (fn (VAR VAL) THEN &rest ELSE) - - (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7) - ⇒ 7 - (--if-let (even? 4) it nil) - ⇒ t - - -- Macro: -if-let* (vars-vals then &rest else) - If all VALS evaluate to true, bind them to their corresponding VARS - and do THEN, otherwise do ELSE. VARS-VALS should be a list of (VAR - VAL) pairs. - - Note: binding is done according to ‘-let*’ (*note -let*::). VALS - are evaluated sequentially, and evaluation stops after the first - nil VAL is encountered. - - (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo") - ⇒ 15 - (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo") - ⇒ "foo" - (-if-let* (((_ _ x) '(nil nil 7))) x) - ⇒ 7 - - -- Macro: -let (varlist &rest body) - Bind variables according to VARLIST then eval BODY. - - VARLIST is a list of lists of the form (PATTERN SOURCE). Each - PATTERN is matched against the SOURCE "structurally". SOURCE is - only evaluated once for each PATTERN. Each PATTERN is matched - recursively, and can therefore contain sub-patterns which are - matched against corresponding sub-expressions of SOURCE. - - All the SOURCEs are evalled before any symbols are bound (i.e. "in - parallel"). - - If VARLIST only contains one (PATTERN SOURCE) element, you can - optionally specify it using a vector and discarding the outer-most - parens. Thus - - (-let ((PATTERN SOURCE)) ..) - - becomes - - (-let [PATTERN SOURCE] ..). - - ‘-let’ (*note -let::) uses a convention of not binding places - (symbols) starting with _ whenever it’s possible. You can use this - to skip over entries you don’t care about. However, this is not - *always* possible (as a result of implementation) and these symbols - might get bound to undefined values. - - Following is the overview of supported patterns. Remember that - patterns can be matched recursively, so every a, b, aK in the - following can be a matching construct and not necessarily a - symbol/variable. - - Symbol: - - a - bind the SOURCE to A. This is just like regular ‘let’. - - Conses and lists: - - (a) - bind ‘car’ of cons/list to A - - (a . b) - bind car of cons to A and ‘cdr’ to B - - (a b) - bind car of list to A and ‘cadr’ to B - - (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3 - ... - - (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to - REST. - - Vectors: - - [a] - bind 0th element of a non-list sequence to A (works with - vectors, strings, bit arrays...) - - [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st - to A1, 2nd to A2, ... If the PATTERN is shorter than SOURCE, the - values at places not in PATTERN are ignored. If the PATTERN is - longer than SOURCE, an ‘error’ is thrown. - - [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the - sequence to REST. This is conceptually the same as improper list - matching (a1 a2 ... aN . rest) - - Key/value stores: - - (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the - SOURCE plist to aK. If the value is not found, aK is nil. Uses - ‘plist-get’ to fetch values. - - (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the - SOURCE alist to aK. If the value is not found, aK is nil. Uses - ‘assoc’ to fetch values. - - (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the - SOURCE hash table to aK. If the value is not found, aK is nil. - Uses ‘gethash’ to fetch values. - - Further, special keyword &keys supports "inline" matching of - plist-like key-value pairs, similarly to &keys keyword of - ‘cl-defun’. - - (a1 a2 ... aN &keys key1 b1 ... keyN bK) - - This binds N values from the list to a1 ... aN, then interprets - the cdr as a plist (see key/value matching above). - - A shorthand notation for kv-destructuring exists which allows the - patterns be optionally left out and derived from the key name in - the following fashion: - - - a key :foo is converted into ‘foo’ pattern, - a key ’bar is - converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’ - pattern. - - That is, the entire value under the key is bound to the derived - variable without any further destructuring. - - This is possible only when the form following the key is not a - valid pattern (i.e. not a symbol, a cons cell or a vector). - Otherwise the matching proceeds as usual and in case of an invalid - spec fails with an error. - - Thus the patterns are normalized as follows: - - ;; derive all the missing patterns (&plist :foo ’bar "baz") => - (&plist :foo foo ’bar bar "baz" baz) - - ;; we can specify some but not others (&plist :foo ’bar - explicit-bar) => (&plist :foo foo ’bar explicit-bar) - - ;; nothing happens, we store :foo in x (&plist :foo x) => (&plist - :foo x) - - ;; nothing happens, we match recursively (&plist :foo (a b c)) => - (&plist :foo (a b c)) - - You can name the source using the syntax SYMBOL &as PATTERN. This - syntax works with lists (proper or improper), vectors and all types - of maps. - - (list &as a b c) (list 1 2 3) - - binds A to 1, B to 2, C to 3 and LIST to (1 2 3). - - Similarly: - - (bounds &as beg . end) (cons 1 2) - - binds BEG to 1, END to 2 and BOUNDS to (1 . 2). - - (items &as first . rest) (list 1 2 3) - - binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3) - - [vect &as _ b c] [1 2 3] - - binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as - usual). - - (plist &as &plist :b b) (list :a 1 :b 2 :c 3) - - binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and - &hash. - - This is especially useful when we want to capture the result of a - computation and destructure at the same time. Consider the form - (function-returning-complex-structure) returning a list of two - vectors with two items each. We want to capture this entire result - and pass it to another computation, but at the same time we want to - get the second item from each vector. We can achieve it with - pattern - - (result &as [_ a] [_ b]) (function-returning-complex-structure) - - Note: Clojure programmers may know this feature as the ":as - binding". The difference is that we put the &as at the front - because we need to support improper list binding. - - (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d)) - ⇒ '(1 2 3 4) - (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d)) - ⇒ '(1 2 3 (4 5 6)) - (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar)) - ⇒ '(1 2) - - -- Macro: -let* (varlist &rest body) - Bind variables according to VARLIST then eval BODY. - - VARLIST is a list of lists of the form (PATTERN SOURCE). Each - PATTERN is matched against the SOURCE structurally. SOURCE is only - evaluated once for each PATTERN. - - Each SOURCE can refer to the symbols already bound by this VARLIST. - This is useful if you want to destructure SOURCE recursively but - also want to name the intermediate structures. - - See ‘-let’ (*note -let::) for the list of all possible patterns. - - (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d)) - ⇒ '(1 2 3 4) - (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d)) - ⇒ '(1 (2 . 3) 2 3) - (-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar)) - ⇒ '(1 a b c (a b c)) - - -- Macro: -lambda (match-form &rest body) - Return a lambda which destructures its input as MATCH-FORM and - executes BODY. - - Note that you have to enclose the MATCH-FORM in a pair of parens, - such that: - - (-lambda (x) body) (-lambda (x y ...) body) - - has the usual semantics of ‘lambda’. Furthermore, these get - translated into normal lambda, so there is no performance penalty. - - See ‘-let’ (*note -let::) for the description of destructuring - mechanism. - - (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6))) - ⇒ '(3 7 11) - (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6])) - ⇒ '(3 7 11) - (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6)) - ⇒ '(2 3 5 6) - - -- Macro: -setq (&rest forms) - Bind each MATCH-FORM to the value of its VAL. - - MATCH-FORM destructuring is done according to the rules of ‘-let’ - (*note -let::). - - This macro allows you to bind multiple variables by destructuring - the value, so for example: - - (-setq (a b) x (&plist :c c) plist) - - expands roughly speaking to the following code - - (setq a (car x) b (cadr x) c (plist-get plist :c)) - - Care is taken to only evaluate each VAL once so that in case of - multiple assignments it does not cause unexpected side effects. - - (fn [MATCH-FORM VAL]...) - - (progn (-setq a 1) a) - ⇒ 1 - (progn (-setq (a b) (list 1 2)) (list a b)) - ⇒ '(1 2) - (progn (-setq (&plist :c c) (list :c "c")) c) - ⇒ "c" - - -File: dash.info, Node: Side-effects, Next: Destructive operations, Prev: Binding, Up: Functions - -2.14 Side-effects -================= - -Functions iterating over lists for side-effect only. - - -- Function: -each (list fn) - Call FN with every item in LIST. Return nil, used for side-effects - only. - - (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s))))) - ⇒ nil - (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s)))) s) - ⇒ '(3 2 1) - (let (s) (--each '(1 2 3) (setq s (cons it s))) s) - ⇒ '(3 2 1) - - -- Function: -each-while (list pred fn) - Call FN with every item in LIST while (PRED item) is non-nil. - Return nil, used for side-effects only. - - (let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) - ⇒ '(4 2) - (let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) - ⇒ '(2 1) - - -- Function: -each-indexed (list fn) - Call (FN index item) for each item in LIST. - - In the anaphoric form ‘--each-indexed’, the index is exposed as - symbol ‘it-index’. - - See also: ‘-map-indexed’ (*note -map-indexed::). - - (let (s) (-each-indexed '(a b c) (lambda (index item) (setq s (cons (list item index) s)))) s) - ⇒ '((c 2) (b 1) (a 0)) - (let (s) (--each-indexed '(a b c) (setq s (cons (list it it-index) s))) s) - ⇒ '((c 2) (b 1) (a 0)) - - -- Function: -each-r (list fn) - Call FN with every item in LIST in reversed order. Return nil, - used for side-effects only. - - (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s))))) - ⇒ nil - (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s)))) s) - ⇒ '(1 2 3) - (let (s) (--each-r '(1 2 3) (setq s (cons it s))) s) - ⇒ '(1 2 3) - - -- Function: -each-r-while (list pred fn) - Call FN with every item in reversed LIST while (PRED item) is - non-nil. Return nil, used for side-effects only. - - (let (s) (-each-r-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) - ⇒ '(6) - (let (s) (--each-r-while '(1 2 3 4) (>= it 3) (!cons it s)) s) - ⇒ '(3 4) - - -- Function: -dotimes (num fn) - Repeatedly calls FN (presumably for side-effects) passing in - integers from 0 through NUM-1. - - (let (s) (-dotimes 3 (lambda (n) (!cons n s))) s) - ⇒ '(2 1 0) - (let (s) (--dotimes 5 (!cons it s)) s) - ⇒ '(4 3 2 1 0) - - -- Macro: -doto (eval-initial-value &rest forms) - Eval a form, then insert that form as the 2nd argument to other - forms. The EVAL-INITIAL-VALUE form is evaluated once. Its result - is passed to FORMS, which are then evaluated sequentially. Returns - the target form. - - (-doto '(1 2 3) (!cdr) (!cdr)) - ⇒ '(3) - (-doto '(1 . 2) (setcar 3) (setcdr 4)) - ⇒ '(3 . 4) - - -- Macro: --doto (eval-initial-value &rest forms) - Anaphoric form of ‘-doto’ (*note -doto::). Note: ‘it’ is not - required in each form. - - (gethash "key" (--doto (make-hash-table :test 'equal) (puthash "key" "value" it))) - ⇒ "value" - - -File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side-effects, Up: Functions - -2.15 Destructive operations -=========================== - - -- Macro: !cons (car cdr) - Destructive: Set CDR to the cons of CAR and CDR. - - (let (l) (!cons 5 l) l) - ⇒ '(5) - (let ((l '(3))) (!cons 5 l) l) - ⇒ '(5 3) - - -- Macro: !cdr (list) - Destructive: Set LIST to the cdr of LIST. - - (let ((l '(3))) (!cdr l) l) - ⇒ '() - (let ((l '(3 5))) (!cdr l) l) - ⇒ '(5) - - -File: dash.info, Node: Function combinators, Prev: Destructive operations, Up: Functions - -2.16 Function combinators -========================= - -These combinators require Emacs 24 for its lexical scope. So they are -offered in a separate package: ‘dash-functional‘. - - -- Function: -partial (fn &rest args) - Takes a function FN and fewer than the normal arguments to FN, and - returns a fn that takes a variable number of additional ARGS. When - called, the returned function calls FN with ARGS first and then - additional args. - - (funcall (-partial '- 5) 3) - ⇒ 2 - (funcall (-partial '+ 5 2) 3) - ⇒ 10 - - -- Function: -rpartial (fn &rest args) - Takes a function FN and fewer than the normal arguments to FN, and - returns a fn that takes a variable number of additional ARGS. When - called, the returned function calls FN with the additional args - first and then ARGS. - - (funcall (-rpartial '- 5) 8) - ⇒ 3 - (funcall (-rpartial '- 5 2) 10) - ⇒ 3 - - -- Function: -juxt (&rest fns) - Takes a list of functions and returns a fn that is the - juxtaposition of those fns. The returned fn takes a variable - number of args, and returns a list containing the result of - applying each fn to the args (left-to-right). - - (funcall (-juxt '+ '-) 3 5) - ⇒ '(8 -2) - (-map (-juxt 'identity 'square) '(1 2 3)) - ⇒ '((1 1) (2 4) (3 9)) - - -- Function: -compose (&rest fns) - Takes a list of functions and returns a fn that is the composition - of those fns. The returned fn takes a variable number of - arguments, and returns the result of applying each fn to the result - of applying the previous fn to the arguments (right-to-left). - - (funcall (-compose 'square '+) 2 3) - ⇒ (square (+ 2 3)) - (funcall (-compose 'identity 'square) 3) - ⇒ (square 3) - (funcall (-compose 'square 'identity) 3) - ⇒ (square 3) - - -- Function: -applify (fn) - Changes an n-arity function FN to a 1-arity function that expects a - list with n items as arguments - - (-map (-applify '+) '((1 1 1) (1 2 3) (5 5 5))) - ⇒ '(3 6 15) - (-map (-applify (lambda (a b c) `(,a (,b (,c))))) '((1 1 1) (1 2 3) (5 5 5))) - ⇒ '((1 (1 (1))) (1 (2 (3))) (5 (5 (5)))) - (funcall (-applify '<) '(3 6)) - ⇒ t - - -- Function: -on (operator transformer) - Return a function of two arguments that first applies TRANSFORMER - to each of them and then applies OPERATOR on the results (in the - same order). - - In types: (b -> b -> c) -> (a -> b) -> a -> a -> c - - (-sort (-on '< 'length) '((1 2 3) (1) (1 2))) - ⇒ '((1) (1 2) (1 2 3)) - (-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) - ⇒ '(4) - (-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) - ⇒ 22 - - -- Function: -flip (func) - Swap the order of arguments for binary function FUNC. - - In types: (a -> b -> c) -> b -> a -> c - - (funcall (-flip '<) 2 1) - ⇒ t - (funcall (-flip '-) 3 8) - ⇒ 5 - (-sort (-flip '<) '(4 3 6 1)) - ⇒ '(6 4 3 1) - - -- Function: -const (c) - Return a function that returns C ignoring any additional arguments. - - In types: a -> b -> a - - (funcall (-const 2) 1 3 "foo") - ⇒ 2 - (-map (-const 1) '("a" "b" "c" "d")) - ⇒ '(1 1 1 1) - (-sum (-map (-const 1) '("a" "b" "c" "d"))) - ⇒ 4 - - -- Macro: -cut (&rest params) - Take n-ary function and n arguments and specialize some of them. - Arguments denoted by <> will be left unspecialized. - - See SRFI-26 for detailed description. - - (funcall (-cut list 1 <> 3 <> 5) 2 4) - ⇒ '(1 2 3 4 5) - (-map (-cut funcall <> 5) '(1+ 1- (lambda (x) (/ 1.0 x)))) - ⇒ '(6 4 0.2) - (-map (-cut <> 1 2 3) (list 'list 'vector 'string)) - ⇒ '((1 2 3) [1 2 3] "") - - -- Function: -not (pred) - Take a unary predicate PRED and return a unary predicate that - returns t if PRED returns nil and nil if PRED returns non-nil. - - (funcall (-not 'even?) 5) - ⇒ t - (-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) - ⇒ '(1 2 3 4) - - -- Function: -orfn (&rest preds) - Take list of unary predicates PREDS and return a unary predicate - with argument x that returns non-nil if at least one of the PREDS - returns non-nil on x. - - In types: [a -> Bool] -> a -> Bool - - (-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 2 3 4 6 8 10) - (funcall (-orfn 'stringp 'even?) "foo") - ⇒ t - - -- Function: -andfn (&rest preds) - Take list of unary predicates PREDS and return a unary predicate - with argument x that returns non-nil if all of the PREDS returns - non-nil on x. - - In types: [a -> Bool] -> a -> Bool - - (funcall (-andfn (-cut < <> 10) 'even?) 6) - ⇒ t - (funcall (-andfn (-cut < <> 10) 'even?) 12) - ⇒ nil - (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) - ⇒ '(1 3 5) - - -- Function: -iteratefn (fn n) - Return a function FN composed N times with itself. - - FN is a unary function. If you need to use a function of higher - arity, use ‘-applify’ (*note -applify::) first to turn it into a - unary function. - - With n = 0, this acts as identity function. - - In types: (a -> a) -> Int -> a -> a. - - This function satisfies the following law: - - (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init - (1+ n))). - - (funcall (-iteratefn (lambda (x) (* x x)) 3) 2) - ⇒ 256 - (funcall (-iteratefn '1+ 3) 1) - ⇒ 4 - (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) - ⇒ '(4 5) - - -- Function: -fixfn (fn &optional equal-test halt-test) - Return a function that computes the (least) fixpoint of FN. - - FN must be a unary function. The returned lambda takes a single - argument, X, the initial value for the fixpoint iteration. The - iteration halts when either of the following conditions is - satisfied: - - 1. Iteration converges to the fixpoint, with equality being tested - using EQUAL-TEST. If EQUAL-TEST is not specified, ‘equal’ is used. - For functions over the floating point numbers, it may be necessary - to provide an appropriate appoximate comparison test. - - 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a - simple counter that returns t after ‘-fixfn-max-iterations’, to - guard against infinite iteration. Otherwise, HALT-TEST must be a - function that accepts a single argument, the current value of X, - and returns non-nil as long as iteration should continue. In this - way, a more sophisticated convergence test may be supplied by the - caller. - - The return value of the lambda is either the fixpoint or, if - iteration halted before converging, a cons with car ‘halted’ and - cdr the final output from HALT-TEST. - - In types: (a -> a) -> a -> a. - - (funcall (-fixfn 'cos 'approx-equal) 0.7) - ⇒ 0.7390851332151607 - (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) - ⇒ 1.8555845286409378 - (funcall (-fixfn 'sin 'approx-equal) 0.1) - ⇒ '(halted . t) - - -- Function: -prodfn (&rest fns) - Take a list of n functions and return a function that takes a list - of length n, applying i-th function to i-th element of the input - list. Returns a list of length n. - - In types (for n=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d) - - This function satisfies the following laws: - - (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn - (-compose f f’) (-compose g g’) ...) (-prodfn f g ...) = (-juxt - (-compose f (-partial ’nth 0)) (-compose g (-partial ’nth 1)) ...) - (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose - f f’) (-compose g g’) ...) (-compose (-partial ’nth n) (-prod f1 - f2 ...)) = (-compose fn (-partial ’nth n)) - - (funcall (-prodfn '1+ '1- 'number-to-string) '(1 2 3)) - ⇒ '(2 1 "3") - (-map (-prodfn '1+ '1-) '((1 2) (3 4) (5 6) (7 8))) - ⇒ '((2 1) (4 3) (6 5) (8 7)) - (apply '+ (funcall (-prodfn 'length 'string-to-number) '((1 2 3) "15"))) - ⇒ 18 - - -File: dash.info, Node: Development, Next: Index, Prev: Functions, Up: Top - -3 Development -************* - -The dash repository is hosted on GitHub: - - -* Menu: - -* Contribute:: How to contribute -* Changes:: List of significant changes by version -* Contributors:: List of contributors - - -File: dash.info, Node: Contribute, Next: Changes, Up: Development - -3.1 Contribute -============== - -Yes, please do. Pure functions in the list manipulation realm only, -please. There’s a suite of tests in dev/examples.el, so remember to add -tests for your function, or it might get broken later. - - Run the tests with ‘./run-tests.sh’. Create the docs with -‘./create-docs.sh’. I highly recommend that you install these as a -pre-commit hook, so that the tests are always running and the docs are -always in sync: - -cp pre-commit.sh .git/hooks/pre-commit - - Oh, and don’t edit ‘README.md’ directly, it is auto-generated. -Change ‘readme-template.md’ or ‘examples-to-docs.el’ instead. The same -goes for the info manual. - - -File: dash.info, Node: Changes, Next: Contributors, Prev: Contribute, Up: Development - -3.2 Changes -=========== - -Changes in 2.10: - - • Add ‘-let’ destructuring to ‘-if-let’ and ‘-when-let’ (Fredrik - Bergroth) - -Changes in 2.9: - - • Add ‘-let’, ‘-let*’ and ‘-lambda’ with destructuring - • Add ‘-tree-seq’ and ‘-tree-map-nodes’ - • Add ‘-non-nil’ - • Add ‘-fix’ - • Add ‘-fixfn’ (dash-functional 1.2) - • Add ‘-copy’ (Wilfred Hughes) - -Changes in 2.8: - - • Add ‘-butlast’ - -Changes in 2.7: - - • ‘-zip’ now supports more than two lists (Steve Lamb) - • Add ‘-cycle’, ‘-pad’, ‘-annotate’, ‘-zip-fill’ (Steve Lamb) - • Add ‘-table’, ‘-table-flat’ (finite cartesian product) - • Add ‘-flatten-n’ - • ‘-slice’ now supports "step" argument - • Add functional combinators ‘-iteratefn’, ‘-prodfn’ - • Add ‘-replace’, ‘-splice’, ‘-splice-list’ which generalize - ‘-replace-at’ and ‘-insert-at’ - • Add ‘-compose’, ‘-iteratefn’ and ‘-prodfn’ (dash-functional 1.1) - -Changes in 2.6: - - • Add ‘-is-prefix-p’, ‘-is-suffix-p’, ‘-is-infix-p’ (Matus Goljer) - • Add ‘-iterate’, ‘-unfold’ (Matus Goljer) - • Add ‘-split-on’, ‘-split-when’ (Matus Goljer) - • Add ‘-find-last-index’ (Matus Goljer) - • Add ‘-list’ (Johan Andersson) - -Changes in 2.5: - - • Add ‘-same-items?’ (Johan Andersson) - • A few bugfixes - -Changes in 2.4: - - • Add ‘-snoc’ (Matus Goljer) - • Add ‘-replace-at’, ‘-update-at’, ‘-remove-at’, and - ‘-remove-at-indices’ (Matus Goljer) - -Changes in 2.3: - - • Add tree operations (Matus Goljer) - • Make font-lock optional - -Changes in 2.2: - - • Add ‘-compose’ (Christina Whyte) - -Changes in 2.1: - - • Add indexing operations (Matus Goljer) - -Changes in 2.0: - - • Split out ‘dash-functional.el’ (Matus Goljer) - • Add ‘-andfn’, ‘-orfn’, ‘-not’, ‘-cut’, ‘-const’, ‘-flip’ and ‘-on’. - (Matus Goljer) - • Fix ‘-min’, ‘-max’, ‘-min-by’ and ‘-max-by’ (Matus Goljer) - -Changes in 1.8: - - • Add ‘-first-item’ and ‘-last-item’ (Wilfred Hughes) - -Changes in 1.7: - - • Add ‘-rotate’ (Matus Goljer) - -Changes in 1.6: - - • Add ‘-min’, ‘-max’, ‘-min-by’ and ‘-max-by’ (Johan Andersson) - -Changes in 1.5: - - • Add ‘-sum’ and ‘-product’ (Johan Andersson) - -Changes in 1.4: - - • Add ‘-sort’ - • Add ‘-reduce-r’ (Matus Goljer) - • Add ‘-reduce-r-from’ (Matus Goljer) - -Changes in 1.3: - - • Add ‘-partition-in-steps’ - • Add ‘-partition-all-in-steps’ - -Changes in 1.2: - - • Add ‘-last’ (Matus Goljer) - • Add ‘-insert-at’ (Emanuel Evans) - • Add ‘-when-let’ and ‘-if-let’ (Emanuel Evans) - • Add ‘-when-let*’ and ‘-if-let*’ (Emanuel Evans) - • Some bugfixes - - -File: dash.info, Node: Contributors, Prev: Changes, Up: Development - -3.3 Contributors -================ - - • Matus Goljer (https://github.com/Fuco1) contributed lots of - features and functions. - • Takafumi Arakaki (https://github.com/tkf) contributed ‘-group-by’. - • tali713 (https://github.com/tali713) is the author of ‘-applify’. - • Víctor M. Valenzuela (https://github.com/vemv) contributed - ‘-repeat’. - • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’. - • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’, - ‘-first-item’ and ‘-last-item’. - • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’, - ‘-when-let’ and ‘-insert-at’. - • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’, - ‘-product’ and ‘-same-items?’ - • Christina Whyte (https://github.com/kurisuwhyte) contributed - ‘-compose’ - • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’, - ‘-pad’, ‘-annotate’, ‘-zip-fill’ and an n-ary version of ‘-zip’. - • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’ - family use ‘-let’ destructuring and improved script for generating - documentation. - • Mark Oteiza (https://github.com/holomorph) contributed the script - to create an info manual. - • Vasilij Schneidermann (https://github.com/wasamasa) contributed - ‘-some’. - • William West (https://github.com/occidens) made ‘-fixfn’ more - robust at handling floats. - - Thanks! - - -File: dash.info, Node: Index, Prev: Development, Up: Top - -Index -***** - -[index] -* Menu: - -* !cdr: Destructive operations. - (line 14) -* !cons: Destructive operations. - (line 6) -* -->: Threading macros. (line 32) -* --doto: Side-effects. (line 81) -* ->: Threading macros. (line 6) -* ->>: Threading macros. (line 19) -* -all?: Predicates. (line 18) -* -andfn: Function combinators. - (line 138) -* -annotate: Maps. (line 79) -* -any?: Predicates. (line 6) -* -applify: Function combinators. - (line 55) -* -as->: Threading macros. (line 46) -* -butlast: Other list operations. - (line 340) -* -clone: Tree operations. (line 122) -* -common-prefix: Reductions. (line 223) -* -common-suffix: Reductions. (line 233) -* -compose: Function combinators. - (line 42) -* -concat: List to list. (line 22) -* -cons*: Other list operations. - (line 30) -* -const: Function combinators. - (line 92) -* -contains?: Predicates. (line 57) -* -copy: Maps. (line 134) -* -count: Reductions. (line 151) -* -cut: Function combinators. - (line 104) -* -cycle: Other list operations. - (line 168) -* -difference: Set operations. (line 20) -* -distinct: Set operations. (line 62) -* -dotimes: Side-effects. (line 61) -* -doto: Side-effects. (line 70) -* -drop: Sublist selection. (line 124) -* -drop-last: Sublist selection. (line 136) -* -drop-while: Sublist selection. (line 157) -* -each: Side-effects. (line 8) -* -each-indexed: Side-effects. (line 28) -* -each-r: Side-effects. (line 41) -* -each-r-while: Side-effects. (line 52) -* -each-while: Side-effects. (line 19) -* -elem-index: Indexing. (line 9) -* -elem-indices: Indexing. (line 21) -* -fifth-item: Other list operations. - (line 320) -* -filter: Sublist selection. (line 8) -* -find-index: Indexing. (line 32) -* -find-indices: Indexing. (line 60) -* -find-last-index: Indexing. (line 46) -* -first: Other list operations. - (line 234) -* -first-item: Other list operations. - (line 271) -* -fix: Other list operations. - (line 376) -* -fixfn: Function combinators. - (line 175) -* -flatten: List to list. (line 33) -* -flatten-n: List to list. (line 55) -* -flip: Function combinators. - (line 80) -* -fourth-item: Other list operations. - (line 310) -* -grade-down: Indexing. (line 81) -* -grade-up: Indexing. (line 71) -* -group-by: Partitioning. (line 187) -* -if-let: Binding. (line 36) -* -if-let*: Binding. (line 49) -* -inits: Reductions. (line 203) -* -insert-at: List to list. (line 109) -* -interleave: Other list operations. - (line 68) -* -interpose: Other list operations. - (line 58) -* -intersection: Set operations. (line 32) -* -is-infix?: Predicates. (line 110) -* -is-prefix?: Predicates. (line 86) -* -is-suffix?: Predicates. (line 98) -* -iterate: Unfolding. (line 9) -* -iteratefn: Function combinators. - (line 152) -* -juxt: Function combinators. - (line 31) -* -keep: List to list. (line 8) -* -lambda: Binding. (line 252) -* -last: Other list operations. - (line 261) -* -last-item: Other list operations. - (line 330) -* -let: Binding. (line 65) -* -let*: Binding. (line 232) -* -list: Other list operations. - (line 363) -* -map: Maps. (line 10) -* -map-first: Maps. (line 37) -* -map-indexed: Maps. (line 65) -* -map-last: Maps. (line 51) -* -map-when: Maps. (line 21) -* -mapcat: Maps. (line 123) -* -max: Reductions. (line 267) -* -max-by: Reductions. (line 277) -* -min: Reductions. (line 243) -* -min-by: Reductions. (line 253) -* -non-nil: Sublist selection. (line 79) -* -none?: Predicates. (line 30) -* -not: Function combinators. - (line 117) -* -on: Function combinators. - (line 66) -* -only-some?: Predicates. (line 42) -* -orfn: Function combinators. - (line 126) -* -pad: Other list operations. - (line 179) -* -partial: Function combinators. - (line 9) -* -partition: Partitioning. (line 74) -* -partition-after-item: Partitioning. (line 177) -* -partition-after-pred: Partitioning. (line 145) -* -partition-all: Partitioning. (line 86) -* -partition-all-in-steps: Partitioning. (line 109) -* -partition-before-item: Partitioning. (line 167) -* -partition-before-pred: Partitioning. (line 156) -* -partition-by: Partitioning. (line 121) -* -partition-by-header: Partitioning. (line 132) -* -partition-in-steps: Partitioning. (line 97) -* -permutations: Set operations. (line 52) -* -powerset: Set operations. (line 44) -* -prodfn: Function combinators. - (line 209) -* -product: Reductions. (line 181) -* -reduce: Reductions. (line 46) -* -reduce-from: Reductions. (line 8) -* -reduce-r: Reductions. (line 65) -* -reduce-r-from: Reductions. (line 27) -* -reductions: Reductions. (line 119) -* -reductions-from: Reductions. (line 87) -* -reductions-r: Reductions. (line 135) -* -reductions-r-from: Reductions. (line 103) -* -remove: Sublist selection. (line 23) -* -remove-at: List to list. (line 145) -* -remove-at-indices: List to list. (line 158) -* -remove-first: Sublist selection. (line 37) -* -remove-item: Sublist selection. (line 67) -* -remove-last: Sublist selection. (line 52) -* -repeat: Other list operations. - (line 19) -* -replace: List to list. (line 67) -* -replace-at: List to list. (line 120) -* -replace-first: List to list. (line 81) -* -replace-last: List to list. (line 95) -* -rotate: Other list operations. - (line 8) -* -rpartial: Function combinators. - (line 20) -* -running-product: Reductions. (line 191) -* -running-sum: Reductions. (line 169) -* -same-items?: Predicates. (line 72) -* -second-item: Other list operations. - (line 286) -* -select-by-indices: Sublist selection. (line 168) -* -select-column: Sublist selection. (line 198) -* -select-columns: Sublist selection. (line 179) -* -separate: Partitioning. (line 63) -* -setq: Binding. (line 274) -* -slice: Sublist selection. (line 85) -* -snoc: Other list operations. - (line 44) -* -some: Other list operations. - (line 248) -* -some-->: Threading macros. (line 83) -* -some->: Threading macros. (line 59) -* -some->>: Threading macros. (line 71) -* -sort: Other list operations. - (line 350) -* -splice: Maps. (line 90) -* -splice-list: Maps. (line 110) -* -split-at: Partitioning. (line 8) -* -split-on: Partitioning. (line 28) -* -split-when: Partitioning. (line 46) -* -split-with: Partitioning. (line 17) -* -sum: Reductions. (line 159) -* -table: Other list operations. - (line 190) -* -table-flat: Other list operations. - (line 209) -* -tails: Reductions. (line 213) -* -take: Sublist selection. (line 101) -* -take-last: Sublist selection. (line 112) -* -take-while: Sublist selection. (line 146) -* -third-item: Other list operations. - (line 298) -* -tree-map: Tree operations. (line 28) -* -tree-map-nodes: Tree operations. (line 39) -* -tree-mapreduce: Tree operations. (line 84) -* -tree-mapreduce-from: Tree operations. (line 103) -* -tree-reduce: Tree operations. (line 52) -* -tree-reduce-from: Tree operations. (line 69) -* -tree-seq: Tree operations. (line 8) -* -unfold: Unfolding. (line 25) -* -union: Set operations. (line 8) -* -unzip: Other list operations. - (line 146) -* -update-at: List to list. (line 132) -* -when-let: Binding. (line 9) -* -when-let*: Binding. (line 23) -* -zip: Other list operations. - (line 95) -* -zip-fill: Other list operations. - (line 138) -* -zip-lists: Other list operations. - (line 119) -* -zip-with: Other list operations. - (line 79) - - - -Tag Table: -Node: Top946 -Node: Installation2425 -Node: Using in a package2958 -Node: Syntax highlighting of dash functions3322 -Node: Functions3705 -Node: Maps4916 -Ref: -map5211 -Ref: -map-when5552 -Ref: -map-first6130 -Ref: -map-last6608 -Ref: -map-indexed7081 -Ref: -annotate7561 -Ref: -splice8051 -Ref: -splice-list8832 -Ref: -mapcat9294 -Ref: -copy9670 -Node: Sublist selection9874 -Ref: -filter10067 -Ref: -remove10519 -Ref: -remove-first10925 -Ref: -remove-last11452 -Ref: -remove-item11973 -Ref: -non-nil12368 -Ref: -slice12527 -Ref: -take13059 -Ref: -take-last13367 -Ref: -drop13690 -Ref: -drop-last13963 -Ref: -take-while14223 -Ref: -drop-while14573 -Ref: -select-by-indices14929 -Ref: -select-columns15443 -Ref: -select-column16149 -Node: List to list16613 -Ref: -keep16805 -Ref: -concat17308 -Ref: -flatten17605 -Ref: -flatten-n18364 -Ref: -replace18751 -Ref: -replace-first19214 -Ref: -replace-last19711 -Ref: -insert-at20201 -Ref: -replace-at20528 -Ref: -update-at20918 -Ref: -remove-at21409 -Ref: -remove-at-indices21897 -Node: Reductions22479 -Ref: -reduce-from22648 -Ref: -reduce-r-from23414 -Ref: -reduce24181 -Ref: -reduce-r24910 -Ref: -reductions-from25781 -Ref: -reductions-r-from26496 -Ref: -reductions27221 -Ref: -reductions-r27846 -Ref: -count28481 -Ref: -sum28705 -Ref: -running-sum28894 -Ref: -product29187 -Ref: -running-product29396 -Ref: -inits29709 -Ref: -tails29957 -Ref: -common-prefix30204 -Ref: -common-suffix30501 -Ref: -min30798 -Ref: -min-by31024 -Ref: -max31547 -Ref: -max-by31772 -Node: Unfolding32300 -Ref: -iterate32539 -Ref: -unfold32984 -Node: Predicates33792 -Ref: -any?33916 -Ref: -all?34236 -Ref: -none?34566 -Ref: -only-some?34868 -Ref: -contains?35353 -Ref: -same-items?35742 -Ref: -is-prefix?36127 -Ref: -is-suffix?36450 -Ref: -is-infix?36773 -Node: Partitioning37127 -Ref: -split-at37315 -Ref: -split-with37600 -Ref: -split-on38003 -Ref: -split-when38679 -Ref: -separate39319 -Ref: -partition39761 -Ref: -partition-all40213 -Ref: -partition-in-steps40641 -Ref: -partition-all-in-steps41138 -Ref: -partition-by41623 -Ref: -partition-by-header42005 -Ref: -partition-after-pred42609 -Ref: -partition-before-pred42953 -Ref: -partition-before-item43304 -Ref: -partition-after-item43615 -Ref: -group-by43921 -Node: Indexing44358 -Ref: -elem-index44560 -Ref: -elem-indices44955 -Ref: -find-index45338 -Ref: -find-last-index45827 -Ref: -find-indices46331 -Ref: -grade-up46739 -Ref: -grade-down47142 -Node: Set operations47552 -Ref: -union47735 -Ref: -difference48177 -Ref: -intersection48594 -Ref: -powerset49031 -Ref: -permutations49244 -Ref: -distinct49544 -Node: Other list operations49922 -Ref: -rotate50147 -Ref: -repeat50517 -Ref: -cons*50780 -Ref: -snoc51167 -Ref: -interpose51580 -Ref: -interleave51878 -Ref: -zip-with52247 -Ref: -zip52964 -Ref: -zip-lists53796 -Ref: -zip-fill54497 -Ref: -unzip54820 -Ref: -cycle55565 -Ref: -pad55938 -Ref: -table56261 -Ref: -table-flat57050 -Ref: -first58058 -Ref: -some58430 -Ref: -last58739 -Ref: -first-item59073 -Ref: -second-item59489 -Ref: -third-item59769 -Ref: -fourth-item60047 -Ref: -fifth-item60313 -Ref: -last-item60575 -Ref: -butlast60867 -Ref: -sort61114 -Ref: -list61603 -Ref: -fix61934 -Node: Tree operations62474 -Ref: -tree-seq62670 -Ref: -tree-map63528 -Ref: -tree-map-nodes63971 -Ref: -tree-reduce64821 -Ref: -tree-reduce-from65703 -Ref: -tree-mapreduce66304 -Ref: -tree-mapreduce-from67164 -Ref: -clone68450 -Node: Threading macros68778 -Ref: ->68923 -Ref: ->>69414 -Ref: -->69919 -Ref: -as->70475 -Ref: -some->70930 -Ref: -some->>71304 -Ref: -some-->71740 -Node: Binding72211 -Ref: -when-let72423 -Ref: -when-let*72908 -Ref: -if-let73431 -Ref: -if-let*73826 -Ref: -let74443 -Ref: -let*80533 -Ref: -lambda81473 -Ref: -setq82270 -Node: Side-effects83086 -Ref: -each83280 -Ref: -each-while83687 -Ref: -each-indexed84047 -Ref: -each-r84565 -Ref: -each-r-while84998 -Ref: -dotimes85373 -Ref: -doto85676 -Ref: --doto86104 -Node: Destructive operations86379 -Ref: !cons86552 -Ref: !cdr86758 -Node: Function combinators86953 -Ref: -partial87227 -Ref: -rpartial87623 -Ref: -juxt88026 -Ref: -compose88458 -Ref: -applify89011 -Ref: -on89442 -Ref: -flip89968 -Ref: -const90280 -Ref: -cut90619 -Ref: -not91105 -Ref: -orfn91415 -Ref: -andfn91849 -Ref: -iteratefn92344 -Ref: -fixfn93047 -Ref: -prodfn94609 -Node: Development95677 -Node: Contribute96026 -Node: Changes96774 -Node: Contributors99772 -Node: Index101391 - -End Tag Table - - -Local Variables: -coding: utf-8 -End: diff --git a/elpa/dash-2.18.0/dash-autoloads.el b/elpa/dash-2.18.0/dash-autoloads.el new file mode 100644 index 0000000..3a96693 --- /dev/null +++ b/elpa/dash-2.18.0/dash-autoloads.el @@ -0,0 +1,74 @@ +;;; dash-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "dash" "dash.el" (0 0 0 0)) +;;; Generated autoloads from dash.el + +(autoload 'dash-fontify-mode "dash" "\ +Toggle fontification of Dash special variables. + +If called interactively, enable Dash-Fontify mode if ARG is +positive, and disable it if ARG is zero or negative. If called +from Lisp, also enable the mode if ARG is omitted or nil, and +toggle it if ARG is `toggle'; disable the mode otherwise. + +Dash-Fontify mode is a buffer-local minor mode intended for Emacs +Lisp buffers. Enabling it causes the special variables bound in +anaphoric Dash macros to be fontified. These anaphoras include +`it', `it-index', `acc', and `other'. In older Emacs versions +which do not dynamically detect macros, Dash-Fontify mode +additionally fontifies Dash macro calls. + +See also `dash-fontify-mode-lighter' and +`global-dash-fontify-mode'. + +\(fn &optional ARG)" t nil) + +(put 'global-dash-fontify-mode 'globalized-minor-mode t) + +(defvar global-dash-fontify-mode nil "\ +Non-nil if Global Dash-Fontify mode is enabled. +See the `global-dash-fontify-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-dash-fontify-mode'.") + +(custom-autoload 'global-dash-fontify-mode "dash" nil) + +(autoload 'global-dash-fontify-mode "dash" "\ +Toggle Dash-Fontify mode in all buffers. +With prefix ARG, enable Global Dash-Fontify mode if ARG is positive; +otherwise, disable it. If called from Lisp, enable the mode if +ARG is omitted or nil. + +Dash-Fontify mode is enabled in all buffers where +`dash--turn-on-fontify-mode' would do it. +See `dash-fontify-mode' for more information on Dash-Fontify mode. + +\(fn &optional ARG)" t nil) + +(autoload 'dash-register-info-lookup "dash" "\ +Register the Dash Info manual with `info-lookup-symbol'. +This allows Dash symbols to be looked up with \\[info-lookup-symbol]." t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dash" '("!cdr" "!cons" "--" "->" "-a" "-butlast" "-c" "-d" "-e" "-f" "-gr" "-i" "-juxt" "-keep" "-l" "-m" "-no" "-o" "-p" "-r" "-s" "-t" "-u" "-value-to-list" "-when-let" "-zip" "dash-"))) + +;;;*** + +;;;### (autoloads nil nil ("dash-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; dash-autoloads.el ends here diff --git a/elpa/dash-2.18.0/dash-pkg.el b/elpa/dash-2.18.0/dash-pkg.el new file mode 100644 index 0000000..b7be1dc --- /dev/null +++ b/elpa/dash-2.18.0/dash-pkg.el @@ -0,0 +1,12 @@ +(define-package "dash" "2.18.0" "A modern list library for Emacs" + '((emacs "24")) + :commit "0e975782086020aa12863fdb658d6a3cc748a10c" :authors + '(("Magnar Sveen" . "magnars@gmail.com")) + :maintainer + '("Magnar Sveen" . "magnars@gmail.com") + :keywords + '("extensions" "lisp") + :url "https://github.com/magnars/dash.el") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/dash-2.17.0/dash.el b/elpa/dash-2.18.0/dash.el old mode 100755 new mode 100644 similarity index 65% rename from elpa/dash-2.17.0/dash.el rename to elpa/dash-2.18.0/dash.el index bc713ce..80d4ef9 --- a/elpa/dash-2.17.0/dash.el +++ b/elpa/dash-2.18.0/dash.el @@ -1,12 +1,14 @@ ;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*- -;; Copyright (C) 2012-2016 Free Software Foundation, Inc. +;; Copyright (C) 2012-2021 Free Software Foundation, Inc. ;; Author: Magnar Sveen -;; Version: 2.17.0 -;; Keywords: lists +;; Version: 2.18.0 +;; Package-Requires: ((emacs "24")) +;; Keywords: extensions, lisp +;; Homepage: https://github.com/magnars/dash.el -;; This program is free software; you can redistribute it and/or modify +;; 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. @@ -17,19 +19,13 @@ ;; 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 . +;; along with this program. If not, see . ;;; Commentary: -;; A modern list api for Emacs. -;; -;; See documentation on https://github.com/magnars/dash.el#functions -;; -;; **Please note** The lexical binding in this file is not utilised at the -;; moment. We will take full advantage of lexical binding in an upcoming 3.0 -;; release of Dash. In the meantime, we've added the pragma to avoid a bug that -;; you can read more about in https://github.com/magnars/dash.el/issues/130. +;; A modern list API for Emacs. ;; +;; See its overview at https://github.com/magnars/dash.el#functions. ;;; Code: @@ -40,22 +36,11 @@ (require 'cl))) (defgroup dash () - "Customize group for dash.el" + "Customize group for Dash, a modern list library." + :group 'extensions :group 'lisp :prefix "dash-") -(defun dash--enable-fontlock (symbol value) - (when value - (dash-enable-font-lock)) - (set-default symbol value)) - -(defcustom dash-enable-fontlock nil - "If non-nil, enable fontification of dash functions, macros and -special values." - :type 'boolean - :set 'dash--enable-fontlock - :group 'dash) - (defmacro !cons (car cdr) "Destructive: Set CDR to the cons of CAR and CDR." `(setq ,cdr (cons ,car ,cdr))) @@ -65,385 +50,552 @@ special values." `(setq ,list (cdr ,list))) (defmacro --each (list &rest body) - "Anaphoric form of `-each'." - (declare (debug (form body)) - (indent 1)) - (let ((l (make-symbol "list"))) + "Evaluate BODY for each element of LIST and return nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating BODY. +This is the anaphoric counterpart to `-each'." + (declare (debug (form body)) (indent 1)) + (let ((l (make-symbol "list")) + (i (make-symbol "i"))) `(let ((,l ,list) - (it-index 0)) + (,i 0) + it it-index) + (ignore it it-index) (while ,l - (let ((it (car ,l))) - ,@body) - (setq it-index (1+ it-index)) - (!cdr ,l))))) - -(defmacro -doto (eval-initial-value &rest forms) - "Eval a form, then insert that form as the 2nd argument to other forms. -The EVAL-INITIAL-VALUE form is evaluated once. Its result is -passed to FORMS, which are then evaluated sequentially. Returns -the target form." - (declare (indent 1)) - (let ((retval (make-symbol "value"))) - `(let ((,retval ,eval-initial-value)) - ,@(mapcar (lambda (form) - (if (sequencep form) - `(,(-first-item form) ,retval ,@(cdr form)) - `(funcall form ,retval))) - forms) - ,retval))) - -(defmacro --doto (eval-initial-value &rest forms) - "Anaphoric form of `-doto'. -Note: `it' is not required in each form." - (declare (indent 1)) - `(let ((it ,eval-initial-value)) - ,@forms - it)) + (setq it (pop ,l) it-index ,i ,i (1+ ,i)) + ,@body)))) (defun -each (list fn) - "Call FN with every item in LIST. Return nil, used for side-effects only." - (--each list (funcall fn it))) + "Call FN on each element of LIST. +Return nil; this function is intended for side effects. + +Its anaphoric counterpart is `--each'. -(put '-each 'lisp-indent-function 1) +For access to the current element's index in LIST, see +`-each-indexed'." + (declare (indent 1)) + (ignore (mapc fn list))) (defalias '--each-indexed '--each) (defun -each-indexed (list fn) - "Call (FN index item) for each item in LIST. - -In the anaphoric form `--each-indexed', the index is exposed as symbol `it-index'. + "Call FN on each index and element of LIST. +For each ITEM at INDEX in LIST, call (funcall FN INDEX ITEM). +Return nil; this function is intended for side effects. See also: `-map-indexed'." + (declare (indent 1)) (--each list (funcall fn it-index it))) -(put '-each-indexed 'lisp-indent-function 1) (defmacro --each-while (list pred &rest body) - "Anaphoric form of `-each-while'." - (declare (debug (form form body)) - (indent 2)) + "Evaluate BODY for each item in LIST, while PRED evaluates to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating PRED or BODY. Once +an element is reached for which PRED evaluates to nil, no further +BODY is evaluated. The return value is always nil. +This is the anaphoric counterpart to `-each-while'." + (declare (debug (form form body)) (indent 2)) (let ((l (make-symbol "list")) - (c (make-symbol "continue"))) + (i (make-symbol "i")) + (elt (make-symbol "elt"))) `(let ((,l ,list) - (,c t) - (it-index 0)) - (while (and ,l ,c) - (let ((it (car ,l))) - (if (not ,pred) (setq ,c nil) ,@body)) - (setq it-index (1+ it-index)) - (!cdr ,l))))) + (,i 0) + ,elt it it-index) + (ignore it it-index) + (while (and ,l (setq ,elt (pop ,l) it ,elt it-index ,i) ,pred) + (setq it ,elt it-index ,i ,i (1+ ,i)) + ,@body)))) (defun -each-while (list pred fn) - "Call FN with every item in LIST while (PRED item) is non-nil. -Return nil, used for side-effects only." - (--each-while list (funcall pred it) (funcall fn it))) + "Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil. +Once an ITEM is reached for which PRED returns nil, FN is no +longer called. Return nil; this function is intended for side +effects. -(put '-each-while 'lisp-indent-function 2) +Its anaphoric counterpart is `--each-while'." + (declare (indent 2)) + (--each-while list (funcall pred it) (funcall fn it))) (defmacro --each-r (list &rest body) - "Anaphoric form of `-each-r'." - (declare (debug (form body)) - (indent 1)) - (let ((v (make-symbol "vector"))) - ;; Implementation note: building vector is considerably faster + "Evaluate BODY for each element of LIST in reversed order. +Each element of LIST in turn, starting at its end, is bound to +`it' and its index within LIST to `it-index' before evaluating +BODY. The return value is always nil. +This is the anaphoric counterpart to `-each-r'." + (declare (debug (form body)) (indent 1)) + (let ((v (make-symbol "vector")) + (i (make-symbol "i"))) + ;; Implementation note: building a vector is considerably faster ;; than building a reversed list (vector takes less memory, so - ;; there is less GC), plus length comes naturally. In-place - ;; 'nreverse' would be faster still, but BODY would be able to see - ;; that, even if modification was reversed before we return. + ;; there is less GC), plus `length' comes naturally. In-place + ;; `nreverse' would be faster still, but BODY would be able to see + ;; that, even if the modification was undone before we return. `(let* ((,v (vconcat ,list)) - (it-index (length ,v)) - it) - (while (> it-index 0) - (setq it-index (1- it-index)) - (setq it (aref ,v it-index)) + (,i (length ,v)) + it it-index) + (ignore it it-index) + (while (> ,i 0) + (setq ,i (1- ,i) it-index ,i it (aref ,v ,i)) ,@body)))) (defun -each-r (list fn) - "Call FN with every item in LIST in reversed order. - Return nil, used for side-effects only." + "Call FN on each element of LIST in reversed order. +Return nil; this function is intended for side effects. + +Its anaphoric counterpart is `--each-r'." (--each-r list (funcall fn it))) (defmacro --each-r-while (list pred &rest body) - "Anaphoric form of `-each-r-while'." - (declare (debug (form form body)) - (indent 2)) - (let ((v (make-symbol "vector"))) + "Eval BODY for each item in reversed LIST, while PRED evals to non-nil. +Each element of LIST in turn, starting at its end, is bound to +`it' and its index within LIST to `it-index' before evaluating +PRED or BODY. Once an element is reached for which PRED +evaluates to nil, no further BODY is evaluated. The return value +is always nil. +This is the anaphoric counterpart to `-each-r-while'." + (declare (debug (form form body)) (indent 2)) + (let ((v (make-symbol "vector")) + (i (make-symbol "i")) + (elt (make-symbol "elt"))) `(let* ((,v (vconcat ,list)) - (it-index (length ,v)) - it) - (while (> it-index 0) - (setq it-index (1- it-index)) - (setq it (aref ,v it-index)) - (if (not ,pred) - (setq it-index -1) - ,@body))))) + (,i (length ,v)) + ,elt it it-index) + (ignore it it-index) + (while (when (> ,i 0) + (setq ,i (1- ,i) it-index ,i) + (setq ,elt (aref ,v ,i) it ,elt) + ,pred) + (setq it-index ,i it ,elt) + ,@body)))) (defun -each-r-while (list pred fn) - "Call FN with every item in reversed LIST while (PRED item) is non-nil. -Return nil, used for side-effects only." + "Call FN on each ITEM in reversed LIST, while (PRED ITEM) is non-nil. +Once an ITEM is reached for which PRED returns nil, FN is no +longer called. Return nil; this function is intended for side +effects. + +Its anaphoric counterpart is `--each-r-while'." (--each-r-while list (funcall pred it) (funcall fn it))) (defmacro --dotimes (num &rest body) - "Repeatedly executes BODY (presumably for side-effects) with symbol `it' bound to integers from 0 through NUM-1." - (declare (debug (form body)) - (indent 1)) - (let ((n (make-symbol "num"))) + "Evaluate BODY NUM times, presumably for side effects. +BODY is evaluated with the local variable `it' temporarily bound +to successive integers running from 0, inclusive, to NUM, +exclusive. BODY is not evaluated if NUM is less than 1. +This is the anaphoric counterpart to `-dotimes'." + (declare (debug (form body)) (indent 1)) + (let ((n (make-symbol "num")) + (i (make-symbol "i"))) `(let ((,n ,num) - (it 0)) - (while (< it ,n) - ,@body - (setq it (1+ it)))))) + (,i 0) + it) + (ignore it) + (while (< ,i ,n) + (setq it ,i ,i (1+ ,i)) + ,@body)))) (defun -dotimes (num fn) - "Repeatedly calls FN (presumably for side-effects) passing in integers from 0 through NUM-1." - (--dotimes num (funcall fn it))) + "Call FN NUM times, presumably for side effects. +FN is called with a single argument on successive integers +running from 0, inclusive, to NUM, exclusive. FN is not called +if NUM is less than 1. -(put '-dotimes 'lisp-indent-function 1) +This function's anaphoric counterpart is `--dotimes'." + (declare (indent 1)) + (--dotimes num (funcall fn it))) (defun -map (fn list) - "Return a new list consisting of the result of applying FN to the items in LIST." + "Apply FN to each item in LIST and return the list of results. + +This function's anaphoric counterpart is `--map'." (mapcar fn list)) (defmacro --map (form list) - "Anaphoric form of `-map'." - (declare (debug (form form))) - `(mapcar (lambda (it) ,form) ,list)) - -(defmacro --reduce-from (form initial-value list) - "Anaphoric form of `-reduce-from'." + "Eval FORM for each item in LIST and return the list of results. +Each element of LIST in turn is bound to `it' before evaluating +FORM. +This is the anaphoric counterpart to `-map'." + (declare (debug (def-form form))) + `(mapcar (lambda (it) (ignore it) ,form) ,list)) + +(defmacro --reduce-from (form init list) + "Accumulate a value by evaluating FORM across LIST. +This macro is like `--each' (which see), but it additionally +provides an accumulator variable `acc' which it successively +binds to the result of evaluating FORM for the current LIST +element before processing the next element. For the first +element, `acc' is initialized with the result of evaluating INIT. +The return value is the resulting value of `acc'. If LIST is +empty, FORM is not evaluated, and the return value is the result +of INIT. +This is the anaphoric counterpart to `-reduce-from'." (declare (debug (form form form))) - `(let ((acc ,initial-value)) + `(let ((acc ,init)) (--each ,list (setq acc ,form)) acc)) -(defun -reduce-from (fn initial-value list) - "Return the result of applying FN to INITIAL-VALUE and the -first item in LIST, then applying FN to that result and the 2nd -item, etc. If LIST contains no items, return INITIAL-VALUE and -do not call FN. +(defun -reduce-from (fn init list) + "Reduce the function FN across LIST, starting with INIT. +Return the result of applying FN to INIT and the first element of +LIST, then applying FN to that result and the second element, +etc. If LIST is empty, return INIT without calling FN. -In the anaphoric form `--reduce-from', the accumulated value is -exposed as symbol `acc'. +This function's anaphoric counterpart is `--reduce-from'. -See also: `-reduce', `-reduce-r'" - (--reduce-from (funcall fn acc it) initial-value list)) +For other folds, see also `-reduce' and `-reduce-r'." + (--reduce-from (funcall fn acc it) init list)) (defmacro --reduce (form list) - "Anaphoric form of `-reduce'." + "Accumulate a value by evaluating FORM across LIST. +This macro is like `--reduce-from' (which see), except the first +element of LIST is taken as INIT. Thus if LIST contains a single +item, it is returned without evaluating FORM. If LIST is empty, +FORM is evaluated with `it' and `acc' bound to nil. +This is the anaphoric counterpart to `-reduce'." (declare (debug (form form))) (let ((lv (make-symbol "list-value"))) `(let ((,lv ,list)) (if ,lv (--reduce-from ,form (car ,lv) (cdr ,lv)) - (let (acc it) ,form))))) + (let (acc it) + (ignore acc it) + ,form))))) (defun -reduce (fn list) - "Return the result of applying FN to the first 2 items in LIST, -then applying FN to that result and the 3rd item, etc. If LIST -contains no items, return the result of calling FN with no -arguments. If LIST contains a single item, return that item -and do not call FN. + "Reduce the function FN across LIST. +Return the result of applying FN to the first two elements of +LIST, then applying FN to that result and the third element, etc. +If LIST contains a single element, return it without calling FN. +If LIST is empty, return the result of calling FN with no +arguments. -In the anaphoric form `--reduce', the accumulated value is -exposed as symbol `acc'. +This function's anaphoric counterpart is `--reduce'. -See also: `-reduce-from', `-reduce-r'" +For other folds, see also `-reduce-from' and `-reduce-r'." (if list (-reduce-from fn (car list) (cdr list)) (funcall fn))) -(defmacro --reduce-r-from (form initial-value list) - "Anaphoric version of `-reduce-r-from'." +(defmacro --reduce-r-from (form init list) + "Accumulate a value by evaluating FORM across LIST in reverse. +This macro is like `--reduce-from', except it starts from the end +of LIST. +This is the anaphoric counterpart to `-reduce-r-from'." (declare (debug (form form form))) - `(--reduce-from ,form ,initial-value (reverse ,list))) + `(let ((acc ,init)) + (--each-r ,list (setq acc ,form)) + acc)) + +(defun -reduce-r-from (fn init list) + "Reduce the function FN across LIST in reverse, starting with INIT. +Return the result of applying FN to the last element of LIST and +INIT, then applying FN to the second-to-last element and the +previous result of FN, etc. That is, the first argument of FN is +the current element, and its second argument the accumulated +value. If LIST is empty, return INIT without calling FN. -(defun -reduce-r-from (fn initial-value list) - "Replace conses with FN, nil with INITIAL-VALUE and evaluate -the resulting expression. If LIST is empty, INITIAL-VALUE is -returned and FN is not called. +This function is like `-reduce-from' but the operation associates +from the right rather than left. In other words, it starts from +the end of LIST and flips the arguments to FN. Conceptually, it +is like replacing the conses in LIST with applications of FN, and +its last link with INIT, and evaluating the resulting expression. -Note: this function works the same as `-reduce-from' but the -operation associates from right instead of from left. +This function's anaphoric counterpart is `--reduce-r-from'. -See also: `-reduce-r', `-reduce'" - (--reduce-r-from (funcall fn it acc) initial-value list)) +For other folds, see also `-reduce-r' and `-reduce'." + (--reduce-r-from (funcall fn it acc) init list)) (defmacro --reduce-r (form list) - "Anaphoric version of `-reduce-r'." + "Accumulate a value by evaluating FORM across LIST in reverse order. +This macro is like `--reduce', except it starts from the end of +LIST. +This is the anaphoric counterpart to `-reduce-r'." (declare (debug (form form))) `(--reduce ,form (reverse ,list))) (defun -reduce-r (fn list) - "Replace conses with FN and evaluate the resulting expression. -The final nil is ignored. If LIST contains no items, return the -result of calling FN with no arguments. If LIST contains a single -item, return that item and do not call FN. - -The first argument of FN is the new item, the second is the -accumulated value. - -Note: this function works the same as `-reduce' but the operation -associates from right instead of from left. - -See also: `-reduce-r-from', `-reduce'" + "Reduce the function FN across LIST in reverse. +Return the result of applying FN to the last two elements of +LIST, then applying FN to the third-to-last element and the +previous result of FN, etc. That is, the first argument of FN is +the current element, and its second argument the accumulated +value. If LIST contains a single element, return it without +calling FN. If LIST is empty, return the result of calling FN +with no arguments. + +This function is like `-reduce' but the operation associates from +the right rather than left. In other words, it starts from the +end of LIST and flips the arguments to FN. Conceptually, it is +like replacing the conses in LIST with applications of FN, +ignoring its last link, and evaluating the resulting expression. + +This function's anaphoric counterpart is `--reduce-r'. + +For other folds, see also `-reduce-r-from' and `-reduce'." (if list (--reduce-r (funcall fn it acc) list) (funcall fn))) +(defmacro --reductions-from (form init list) + "Return a list of FORM's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce-from' (which see) is called with the same +arguments. +This is the anaphoric counterpart to `-reductions-from'." + (declare (debug (form form form))) + `(nreverse + (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc) + (list ,init) + ,list))) + (defun -reductions-from (fn init list) - "Return a list of the intermediate values of the reduction. + "Return a list of FN's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce-from' (which see) is called with the same +arguments. + +This function's anaphoric counterpart is `--reductions-from'. -See `-reduce-from' for explanation of the arguments. +For other folds, see also `-reductions' and `-reductions-r'." + (--reductions-from (funcall fn acc it) init list)) -See also: `-reductions', `-reductions-r', `-reduce-r'" - (nreverse (--reduce-from (cons (funcall fn (car acc) it) acc) (list init) list))) +(defmacro --reductions (form list) + "Return a list of FORM's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce' (which see) is called with the same arguments. +This is the anaphoric counterpart to `-reductions'." + (declare (debug (form form))) + (let ((lv (make-symbol "list-value"))) + `(let ((,lv ,list)) + (if ,lv + (--reductions-from ,form (car ,lv) (cdr ,lv)) + (let (acc it) + (ignore acc it) + (list ,form)))))) (defun -reductions (fn list) - "Return a list of the intermediate values of the reduction. + "Return a list of FN's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce' (which see) is called with the same arguments. -See `-reduce' for explanation of the arguments. +This function's anaphoric counterpart is `--reductions'. -See also: `-reductions-from', `-reductions-r', `-reduce-r'" - (and list (-reductions-from fn (car list) (cdr list)))) +For other folds, see also `-reductions' and `-reductions-r'." + (if list + (--reductions-from (funcall fn acc it) (car list) (cdr list)) + (list (funcall fn)))) + +(defmacro --reductions-r-from (form init list) + "Return a list of FORM's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce-r-from' (which see) is called with the same +arguments. +This is the anaphoric counterpart to `-reductions-r-from'." + (declare (debug (form form form))) + `(--reduce-r-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc) + (list ,init) + ,list)) (defun -reductions-r-from (fn init list) - "Return a list of the intermediate values of the reduction. - -See `-reduce-r-from' for explanation of the arguments. - -See also: `-reductions-r', `-reductions', `-reduce'" - (--reduce-r-from (cons (funcall fn it (car acc)) acc) (list init) list)) + "Return a list of FN's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce-r-from' (which see) is called with the same +arguments. + +This function's anaphoric counterpart is `--reductions-r-from'. + +For other folds, see also `-reductions' and `-reductions-r'." + (--reductions-r-from (funcall fn it acc) init list)) + +(defmacro --reductions-r (form list) + "Return a list of FORM's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce-re' (which see) is called with the same arguments. +This is the anaphoric counterpart to `-reductions-r'." + (declare (debug (form list))) + (let ((lv (make-symbol "list-value"))) + `(let ((,lv (reverse ,list))) + (if ,lv + (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc) + (list (car ,lv)) + (cdr ,lv)) + (let (acc it) + (ignore acc it) + (list ,form)))))) (defun -reductions-r (fn list) - "Return a list of the intermediate values of the reduction. + "Return a list of FN's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce-r' (which see) is called with the same arguments. -See `-reduce-r' for explanation of the arguments. +This function's anaphoric counterpart is `--reductions-r'. -See also: `-reductions-r-from', `-reductions', `-reduce'" - (when list - (let ((rev (reverse list))) - (--reduce-from (cons (funcall fn it (car acc)) acc) - (list (car rev)) - (cdr rev))))) +For other folds, see also `-reductions-r-from' and +`-reductions'." + (if list + (--reductions-r (funcall fn it acc) list) + (list (funcall fn)))) (defmacro --filter (form list) - "Anaphoric form of `-filter'. - -See also: `--remove'." + "Return a new list of the items in LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-filter'. +For the opposite operation, see also `--remove'." (declare (debug (form form))) (let ((r (make-symbol "result"))) `(let (,r) - (--each ,list (when ,form (!cons it ,r))) + (--each ,list (when ,form (push it ,r))) (nreverse ,r)))) (defun -filter (pred list) - "Return a new list of the items in LIST for which PRED returns a non-nil value. + "Return a new list of the items in LIST for which PRED returns non-nil. -Alias: `-select' +Alias: `-select'. -See also: `-keep', `-remove'." +This function's anaphoric counterpart is `--filter'. + +For similar operations, see also `-keep' and `-remove'." (--filter (funcall pred it) list)) (defalias '-select '-filter) (defalias '--select '--filter) (defmacro --remove (form list) - "Anaphoric form of `-remove'. - -See also `--filter'." + "Return a new list of the items in LIST for which FORM evals to nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-remove'. +For the opposite operation, see also `--filter'." (declare (debug (form form))) `(--filter (not ,form) ,list)) (defun -remove (pred list) "Return a new list of the items in LIST for which PRED returns nil. -Alias: `-reject' +Alias: `-reject'. + +This function's anaphoric counterpart is `--remove'. -See also: `-filter'." +For similar operations, see also `-keep' and `-filter'." (--remove (funcall pred it) list)) (defalias '-reject '-remove) (defalias '--reject '--remove) +(defmacro --remove-first (form list) + "Remove the first item from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. This is a +non-destructive operation, but only the front of LIST leading up +to the removed item is a copy; the rest is LIST's original tail. +If no item is removed, then the result is a complete copy. +This is the anaphoric counterpart to `-remove-first'." + (declare (debug (form form))) + (let ((front (make-symbol "front")) + (tail (make-symbol "tail"))) + `(let ((,tail ,list) ,front) + (--each-while ,tail (not ,form) + (push (pop ,tail) ,front)) + (if ,tail + (nconc (nreverse ,front) (cdr ,tail)) + (nreverse ,front))))) + (defun -remove-first (pred list) - "Return a new list with the first item matching PRED removed. + "Remove the first item from LIST for which PRED returns non-nil. +This is a non-destructive operation, but only the front of LIST +leading up to the removed item is a copy; the rest is LIST's +original tail. If no item is removed, then the result is a +complete copy. -Alias: `-reject-first' +Alias: `-reject-first'. -See also: `-remove', `-map-first'" - (let (front) - (while (and list (not (funcall pred (car list)))) - (push (car list) front) - (!cdr list)) - (if list - (-concat (nreverse front) (cdr list)) - (nreverse front)))) +This function's anaphoric counterpart is `--remove-first'. -(defmacro --remove-first (form list) - "Anaphoric form of `-remove-first'." - (declare (debug (form form))) - `(-remove-first (lambda (it) ,form) ,list)) +See also `-map-first', `-remove-item', and `-remove-last'." + (--remove-first (funcall pred it) list)) (defalias '-reject-first '-remove-first) (defalias '--reject-first '--remove-first) +(defmacro --remove-last (form list) + "Remove the last item from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' before evaluating +FORM. The result is a copy of LIST regardless of whether an +element is removed. +This is the anaphoric counterpart to `-remove-last'." + (declare (debug (form form))) + `(nreverse (--remove-first ,form (reverse ,list)))) + (defun -remove-last (pred list) - "Return a new list with the last item matching PRED removed. + "Remove the last item from LIST for which PRED returns non-nil. +The result is a copy of LIST regardless of whether an element is +removed. -Alias: `-reject-last' +Alias: `-reject-last'. -See also: `-remove', `-map-last'" - (nreverse (-remove-first pred (reverse list)))) +This function's anaphoric counterpart is `--remove-last'. -(defmacro --remove-last (form list) - "Anaphoric form of `-remove-last'." - (declare (debug (form form))) - `(-remove-last (lambda (it) ,form) ,list)) +See also `-map-last', `-remove-item', and `-remove-first'." + (--remove-last (funcall pred it) list)) (defalias '-reject-last '-remove-last) (defalias '--reject-last '--remove-last) -(defun -remove-item (item list) - "Remove all occurrences of ITEM from LIST. - -Comparison is done with `equal'." - (declare (pure t) (side-effect-free t)) - (--remove (equal it item) list)) +(defalias '-remove-item #'remove + "Return a copy of LIST with all occurrences of ITEM removed. +The comparison is done with `equal'. +\n(fn ITEM LIST)") (defmacro --keep (form list) - "Anaphoric form of `-keep'." + "Eval FORM for each item in LIST and return the non-nil results. +Like `--filter', but returns the non-nil results of FORM instead +of the corresponding elements of LIST. Each element of LIST in +turn is bound to `it' and its index within LIST to `it-index' +before evaluating FORM. +This is the anaphoric counterpart to `-keep'." (declare (debug (form form))) (let ((r (make-symbol "result")) (m (make-symbol "mapped"))) `(let (,r) - (--each ,list (let ((,m ,form)) (when ,m (!cons ,m ,r)))) + (--each ,list (let ((,m ,form)) (when ,m (push ,m ,r)))) (nreverse ,r)))) (defun -keep (fn list) - "Return a new list of the non-nil results of applying FN to the items in LIST. + "Return a new list of the non-nil results of applying FN to each item in LIST. +Like `-filter', but returns the non-nil results of FN instead of +the corresponding elements of LIST. -If you want to select the original items satisfying a predicate use `-filter'." +Its anaphoric counterpart is `--keep'." (--keep (funcall fn it) list)) (defun -non-nil (list) - "Return all non-nil elements of LIST." + "Return a copy of LIST with all nil items removed." (declare (pure t) (side-effect-free t)) - (-remove 'null list)) + (--filter it list)) (defmacro --map-indexed (form list) - "Anaphoric form of `-map-indexed'." + "Eval FORM for each item in LIST and return the list of results. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. This is like +`--map', but additionally makes `it-index' available to FORM. + +This is the anaphoric counterpart to `-map-indexed'." (declare (debug (form form))) (let ((r (make-symbol "result"))) `(let (,r) (--each ,list - (!cons ,form ,r)) + (push ,form ,r)) (nreverse ,r)))) (defun -map-indexed (fn list) - "Return a new list consisting of the result of (FN index item) for each item in LIST. + "Apply FN to each index and item in LIST and return the list of results. +This is like `-map', but FN takes two arguments: the index of the +current element within LIST, and the element itself. -In the anaphoric form `--map-indexed', the index is exposed as symbol `it-index'. +This function's anaphoric counterpart is `--map-indexed'. -See also: `-each-indexed'." +For a side-effecting variant, see also `-each-indexed'." (--map-indexed (funcall fn it-index it) list)) (defmacro --map-when (pred rep list) @@ -530,6 +682,26 @@ See also: `-map-last'" Thus function FN should return a list." (--mapcat (funcall fn it) list)) +(defmacro --iterate (form init n) + "Anaphoric version of `-iterate'." + (declare (debug (form form form))) + (let ((res (make-symbol "result"))) + `(let ((it ,init) ,res) + (dotimes (_ ,n) + (push it ,res) + (setq it ,form)) + (nreverse ,res)))) + +(defun -iterate (fun init n) + "Return a list of iterated applications of FUN to INIT. + +This means a list of the form: + + (INIT (FUN INIT) (FUN (FUN INIT)) ...) + +N is the length of the returned list." + (--iterate (funcall fun it) init n)) + (defun -flatten (l) "Take a nested list L and return its contents as a single, flat list. @@ -547,11 +719,6 @@ See also: `-flatten-n'" (-mapcat '-flatten l) (list l))) -(defmacro --iterate (form init n) - "Anaphoric version of `-iterate'." - (declare (debug (form form form))) - `(-iterate (lambda (it) ,form) ,init ,n)) - (defun -flatten-n (num list) "Flatten NUM levels of a nested LIST. @@ -603,12 +770,17 @@ See also: `-splice', `-insert-at'" (defun -cons* (&rest args) "Make a new list from the elements of ARGS. - -The last 2 members of ARGS are used as the final cons of the -result so if the final member of ARGS is not a list the result is -a dotted list." +The last 2 elements of ARGS are used as the final cons of the +result, so if the final element of ARGS is not a list, the result +is a dotted list. With no ARGS, return nil." (declare (pure t) (side-effect-free t)) - (-reduce-r 'cons args)) + (let* ((len (length args)) + (tail (nthcdr (- len 2) args)) + (last (cdr tail))) + (if (null last) + (car args) + (setcdr tail (car last)) + args))) (defun -snoc (list elem &rest elements) "Append ELEM to the end of the list. @@ -619,38 +791,49 @@ If ELEMENTS is non nil, append these to the list as well." (-concat list (list elem) elements)) (defmacro --first (form list) - "Anaphoric form of `-first'." + "Return the first item in LIST for which FORM evals to non-nil. +Return nil if no such element is found. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-first'." (declare (debug (form form))) (let ((n (make-symbol "needle"))) `(let (,n) - (--each-while ,list (not ,n) - (when ,form (setq ,n it))) + (--each-while ,list (or (not ,form) + (ignore (setq ,n it)))) ,n))) (defun -first (pred list) - "Return the first x in LIST where (PRED x) is non-nil, else nil. - + "Return the first item in LIST for which PRED returns non-nil. +Return nil if no such element is found. To get the first item in the list no questions asked, use `car'. -Alias: `-find'" +Alias: `-find'. + +This function's anaphoric counterpart is `--first'." (--first (funcall pred it) list)) (defalias '-find '-first) (defalias '--find '--first) (defmacro --some (form list) - "Anaphoric form of `-some'." + "Return non-nil if FORM evals to non-nil for at least one item in LIST. +If so, return the first such result of FORM. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-some'." (declare (debug (form form))) (let ((n (make-symbol "needle"))) `(let (,n) - (--each-while ,list (not ,n) - (setq ,n ,form)) + (--each-while ,list (not (setq ,n ,form))) ,n))) (defun -some (pred list) "Return (PRED x) for the first LIST item where (PRED x) is non-nil, else nil. -Alias: `-any'" +Alias: `-any'. + +This function's anaphoric counterpart is `--some'." (--some (funcall pred it) list)) (defalias '-any '-some) @@ -743,9 +926,10 @@ See also: `-last-item'." "Counts the number of items in LIST where (PRED item) is non-nil." (--count (funcall pred it) list)) -(defun ---truthy? (val) +(defun ---truthy? (obj) + "Return OBJ as a boolean value (t or nil)." (declare (pure t) (side-effect-free t)) - (not (null val))) + (and obj t)) (defmacro --any? (form list) "Anaphoric form of `-any?'." @@ -847,73 +1031,100 @@ section is returned. Defaults to 1." (push it new-list))) (nreverse new-list))) -(defun -take (n list) - "Return a new list of the first N items in LIST, or all items if there are fewer than N. - -See also: `-take-last'" - (declare (pure t) (side-effect-free t)) - (let (result) - (--dotimes n - (when list - (!cons (car list) result) - (!cdr list))) - (nreverse result))) - -(defun -take-last (n list) - "Return the last N items of LIST in order. - -See also: `-take'" - (declare (pure t) (side-effect-free t)) - (copy-sequence (last list n))) - -(defalias '-drop 'nthcdr - "Return the tail of LIST without the first N items. - -See also: `-drop-last' - -\(fn N LIST)") - -(defun -drop-last (n list) - "Remove the last N items of LIST and return a copy. - -See also: `-drop'" - ;; No alias because we don't want magic optional argument - (declare (pure t) (side-effect-free t)) - (butlast list n)) - (defmacro --take-while (form list) - "Anaphoric form of `-take-while'." + "Take successive items from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. Return a new +list of the successive elements from the start of LIST for which +FORM evaluates to non-nil. +This is the anaphoric counterpart to `-take-while'." (declare (debug (form form))) (let ((r (make-symbol "result"))) `(let (,r) - (--each-while ,list ,form (!cons it ,r)) + (--each-while ,list ,form (push it ,r)) (nreverse ,r)))) (defun -take-while (pred list) - "Return a new list of successive items from LIST while (PRED item) returns a non-nil value." + "Take successive items from LIST for which PRED returns non-nil. +PRED is a function of one argument. Return a new list of the +successive elements from the start of LIST for which PRED returns +non-nil. + +This function's anaphoric counterpart is `--take-while'. + +For another variant, see also `-drop-while'." (--take-while (funcall pred it) list)) (defmacro --drop-while (form list) - "Anaphoric form of `-drop-while'." + "Drop successive items from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. Return the +tail (not a copy) of LIST starting from its first element for +which FORM evaluates to nil. +This is the anaphoric counterpart to `-drop-while'." (declare (debug (form form))) (let ((l (make-symbol "list"))) `(let ((,l ,list)) - (while (and ,l (let ((it (car ,l))) ,form)) - (!cdr ,l)) + (--each-while ,l ,form (pop ,l)) ,l))) (defun -drop-while (pred list) - "Return the tail of LIST starting from the first item for which (PRED item) returns nil." + "Drop successive items from LIST for which PRED returns non-nil. +PRED is a function of one argument. Return the tail (not a copy) +of LIST starting from its first element for which PRED returns +nil. + +This function's anaphoric counterpart is `--drop-while'. + +For another variant, see also `-take-while'." (--drop-while (funcall pred it) list)) +(defun -take (n list) + "Return a copy of the first N items in LIST. +Return a copy of LIST if it contains N items or fewer. +Return nil if N is zero or less. + +See also: `-take-last'." + (declare (pure t) (side-effect-free t)) + (--take-while (< it-index n) list)) + +(defun -take-last (n list) + "Return a copy of the last N items of LIST in order. +Return a copy of LIST if it contains N items or fewer. +Return nil if N is zero or less. + +See also: `-take'." + (declare (pure t) (side-effect-free t)) + (copy-sequence (last list n))) + +(defalias '-drop #'nthcdr + "Return the tail (not a copy) of LIST without the first N items. +Return nil if LIST contains N items or fewer. +Return LIST if N is zero or less. + +For another variant, see also `-drop-last'. +\n(fn N LIST)") + +(defun -drop-last (n list) + "Return a copy of LIST without its last N items. +Return a copy of LIST if N is zero or less. +Return nil if LIST contains N items or fewer. + +See also: `-drop'." + (declare (pure t) (side-effect-free t)) + (nbutlast (copy-sequence list) n)) + (defun -split-at (n list) - "Return a list of ((-take N LIST) (-drop N LIST)), in no more than one pass through the list." + "Split LIST into two sublists after the Nth element. +The result is a list of two elements (TAKE DROP) where TAKE is a +new list of the first N elements of LIST, and DROP is the +remaining elements of LIST (not a copy). TAKE and DROP are like +the results of `-take' and `-drop', respectively, but the split +is done in a single list traversal." (declare (pure t) (side-effect-free t)) (let (result) - (--dotimes n - (when list - (!cons (car list) result) - (!cdr list))) + (--each-while list (< it-index n) + (push (pop list) result)) (list (nreverse result) list))) (defun -rotate (n list) @@ -924,7 +1135,7 @@ The time complexity is O(n)." (let* ((len (length list)) (n-mod-len (mod n len)) (new-tail-len (- len n-mod-len))) - (append (-drop new-tail-len list) (-take new-tail-len list))))) + (append (nthcdr new-tail-len list) (-take new-tail-len list))))) (defun -insert-at (n x list) "Return a list with X inserted into LIST at position N. @@ -1047,28 +1258,29 @@ This function can be thought of as a generalization of "Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one pass through the list." (--separate (funcall pred it) list)) -(defun ---partition-all-in-steps-reversed (n step list) - "Private: Used by -partition-all-in-steps and -partition-in-steps." +(defun dash--partition-all-in-steps-reversed (n step list) + "Used by `-partition-all-in-steps' and `-partition-in-steps'." (when (< step 1) - (error "Step must be a positive number, or you're looking at some juicy infinite loops.")) - (let ((result nil)) + (signal 'wrong-type-argument + `("Step size < 1 results in juicy infinite loops" ,step))) + (let (result) (while list - (!cons (-take n list) result) - (setq list (-drop step list))) + (push (-take n list) result) + (setq list (nthcdr step list))) result)) (defun -partition-all-in-steps (n step list) "Return a new list with the items in LIST grouped into N-sized sublists at offsets STEP apart. The last groups may contain less than N items." (declare (pure t) (side-effect-free t)) - (nreverse (---partition-all-in-steps-reversed n step list))) + (nreverse (dash--partition-all-in-steps-reversed n step list))) (defun -partition-in-steps (n step list) "Return a new list with the items in LIST grouped into N-sized sublists at offsets STEP apart. If there are not enough items to make the last group N-sized, those items are discarded." (declare (pure t) (side-effect-free t)) - (let ((result (---partition-all-in-steps-reversed n step list))) + (let ((result (dash--partition-all-in-steps-reversed n step list))) (while (and result (< (length (car result)) n)) (!cdr result)) (nreverse result))) @@ -1328,16 +1540,18 @@ a variable number of arguments, such that is identity (given that the lists are the same length). Note in particular that calling this on a list of two lists will -return a list of cons-cells such that the aboce identity works. +return a list of cons-cells such that the above identity works. See also: `-zip'" (apply '-zip lists)) (defun -cycle (list) - "Return an infinite copy of LIST that will cycle through the -elements and repeat from the beginning." + "Return an infinite circular copy of LIST. +The returned list cycles through the elements of LIST and repeats +from the beginning." (declare (pure t) (side-effect-free t)) - (let ((newlist (-map 'identity list))) + ;; Also works with sequences that aren't lists. + (let ((newlist (append list ()))) (nconc newlist newlist))) (defun -pad (fill-value &rest lists) @@ -1419,13 +1633,6 @@ See also: `-flatten-n', `-table'" (dash--table-carry lists restore-lists))) (nreverse re))) -(defun -partial (fn &rest args) - "Take a function FN and fewer than the normal arguments to FN, -and return a fn that takes a variable number of additional ARGS. -When called, the returned function calls FN with ARGS first and -then additional args." - (apply 'apply-partially fn args)) - (defun -elem-index (elem list) "Return the index of the first element in the given LIST which is equal to the query element ELEM, or nil if there is no @@ -1540,7 +1747,7 @@ last item in second form, etc." Insert X at the position signified by the symbol `it' in the first form. If there are more forms, insert the first form at the position signified by `it' in in second form, etc." - (declare (debug (form body))) + (declare (debug (form body)) (indent 1)) `(-as-> ,x it ,@forms)) (defmacro -as-> (value variable &rest forms) @@ -1580,36 +1787,54 @@ and when that result is non-nil, through the next form, etc." (->> ,result ,form)) ,@more)))) -(defmacro -some--> (x &optional form &rest more) - "When expr in non-nil, thread it through the first form (via `-->'), -and when that result is non-nil, through the next form, etc." - (declare (debug ->) - (indent 1)) - (if (null form) x +(defmacro -some--> (expr &rest forms) + "Thread EXPR through FORMS via `-->', while the result is non-nil. +When EXPR evaluates to non-nil, thread the result through the +first of FORMS, and when that result is non-nil, thread it +through the next form, etc." + (declare (debug (form &rest &or symbolp consp)) (indent 1)) + (if (null forms) expr (let ((result (make-symbol "result"))) - `(-some--> (-when-let (,result ,x) - (--> ,result ,form)) - ,@more)))) + `(-some--> (-when-let (,result ,expr) + (--> ,result ,(car forms))) + ,@(cdr forms))))) + +(defmacro -doto (init &rest forms) + "Evaluate INIT and pass it as argument to FORMS with `->'. +The RESULT of evaluating INIT is threaded through each of FORMS +individually using `->', which see. The return value is RESULT, +which FORMS may have modified by side effect." + (declare (debug (form &rest &or symbolp consp)) (indent 1)) + (let ((retval (make-symbol "result"))) + `(let ((,retval ,init)) + ,@(mapcar (lambda (form) `(-> ,retval ,form)) forms) + ,retval))) + +(defmacro --doto (init &rest forms) + "Anaphoric form of `-doto'. +This just evaluates INIT, binds the result to `it', evaluates +FORMS, and returns the final value of `it'. +Note: `it' need not be used in each form." + (declare (debug (form body)) (indent 1)) + `(let ((it ,init)) + ,@forms + it)) (defun -grade-up (comparator list) - "Grade elements of LIST using COMPARATOR relation, yielding a -permutation vector such that applying this permutation to LIST -sorts it in ascending order." - ;; ugly hack to "fix" lack of lexical scope - (let ((comp `(lambda (it other) (funcall ',comparator (car it) (car other))))) - (->> (--map-indexed (cons it it-index) list) - (-sort comp) - (-map 'cdr)))) + "Grade elements of LIST using COMPARATOR relation. +This yields a permutation vector such that applying this +permutation to LIST sorts it in ascending order." + (->> (--map-indexed (cons it it-index) list) + (-sort (lambda (it other) (funcall comparator (car it) (car other)))) + (mapcar #'cdr))) (defun -grade-down (comparator list) - "Grade elements of LIST using COMPARATOR relation, yielding a -permutation vector such that applying this permutation to LIST -sorts it in descending order." - ;; ugly hack to "fix" lack of lexical scope - (let ((comp `(lambda (it other) (funcall ',comparator (car other) (car it))))) - (->> (--map-indexed (cons it it-index) list) - (-sort comp) - (-map 'cdr)))) + "Grade elements of LIST using COMPARATOR relation. +This yields a permutation vector such that applying this +permutation to LIST sorts it in descending order." + (->> (--map-indexed (cons it it-index) list) + (-sort (lambda (it other) (funcall comparator (car other) (car it)))) + (mapcar #'cdr))) (defvar dash--source-counter 0 "Monotonic counter for generated symbols.") @@ -1717,17 +1942,6 @@ SOURCE is a proper or improper list." (t ;; Handle improper lists. Last matching place, no need for shift (dash--match match-form (dash--match-cons-get-cdr skip-cdr source)))))) -(defun dash--vector-tail (seq start) - "Return the tail of SEQ starting at START." - (cond - ((vectorp seq) - (let* ((re-length (- (length seq) start)) - (re (make-vector re-length 0))) - (--dotimes re-length (aset re it (aref seq (+ it start)))) - re)) - ((stringp seq) - (substring seq start)))) - (defun dash--match-vector (match-form source) "Setup a vector matching environment and call the real matcher." (let ((s (dash--match-make-source-symbol))) @@ -1775,7 +1989,7 @@ is discarded." (eq m '&rest)) (prog1 (dash--match (aref match-form (1+ i)) - `(dash--vector-tail ,source ,i)) + `(substring ,source ,i)) (setq i l))) ((and (symbolp m) ;; do not match symbols starting with _ @@ -1926,7 +2140,7 @@ Key-value stores are disambiguated by placing a token &plist, (eq '&as (aref match-form 1))) (let ((s (aref match-form 0))) (cons (list s source) - (dash--match (dash--vector-tail match-form 2) s)))) + (dash--match (substring match-form 2) s)))) (t (dash--match-vector match-form source)))))) (defun dash--normalize-let-varlist (varlist) @@ -1978,11 +2192,11 @@ If VARLIST only contains one (PATTERN SOURCE) element, you can optionally specify it using a vector and discarding the outer-most parens. Thus - (-let ((PATTERN SOURCE)) ..) + (-let ((PATTERN SOURCE)) ...) becomes - (-let [PATTERN SOURCE] ..). + (-let [PATTERN SOURCE] ...). `-let' uses a convention of not binding places (symbols) starting with _ whenever it's possible. You can use this to skip over @@ -2007,7 +2221,7 @@ Conses and lists: (a b) - bind car of list to A and `cadr' to B - (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3 ... + (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3... (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST. @@ -2146,27 +2360,28 @@ such that: (-lambda (x y ...) body) has the usual semantics of `lambda'. Furthermore, these get -translated into normal lambda, so there is no performance +translated into normal `lambda', so there is no performance penalty. -See `-let' for the description of destructuring mechanism." +See `-let' for a description of the destructuring mechanism." (declare (doc-string 2) (indent defun) (debug (&define sexp [&optional stringp] [&optional ("interactive" interactive)] def-body))) (cond - ((not (consp match-form)) - (signal 'wrong-type-argument "match-form must be a list")) - ;; no destructuring, so just return regular lambda to make things faster - ((-all? 'symbolp match-form) + ((nlistp match-form) + (signal 'wrong-type-argument (list #'listp match-form))) + ;; No destructuring, so just return regular `lambda' for speed. + ((-all? #'symbolp match-form) `(lambda ,match-form ,@body)) - (t - (let* ((inputs (--map-indexed (list it (make-symbol (format "input%d" it-index))) match-form))) - ;; TODO: because inputs to the lambda are evaluated only once, - ;; -let* need not to create the extra bindings to ensure that. + ((let ((inputs (--map-indexed + (list it (make-symbol (format "input%d" it-index))) + match-form))) + ;; TODO: because inputs to the `lambda' are evaluated only once, + ;; `-let*' need not create the extra bindings to ensure that. ;; We should find a way to optimize that. Not critical however. - `(lambda ,(--map (cadr it) inputs) + `(lambda ,(mapcar #'cadr inputs) (-let* ,inputs ,@body)))))) (defmacro -setq (&rest forms) @@ -2193,7 +2408,7 @@ multiple assignments it does not cause unexpected side effects. (declare (debug (&rest sexp form)) (indent 1)) (when (= (mod (length forms) 2) 1) - (error "Odd number of arguments")) + (signal 'wrong-number-of-arguments (list '-setq (1+ (length forms))))) (let* ((forms-and-sources ;; First get all the necessary mappings with all the ;; intermediate bindings. @@ -2426,20 +2641,22 @@ Alias: `-same-items-p'" (defalias '-same-items-p '-same-items?) (defun -is-prefix? (prefix list) - "Return non-nil if PREFIX is prefix of LIST. + "Return non-nil if PREFIX is a prefix of LIST. -Alias: `-is-prefix-p'" +Alias: `-is-prefix-p'." (declare (pure t) (side-effect-free t)) - (--each-while list (equal (car prefix) it) - (!cdr prefix)) - (not prefix)) + (--each-while list (and (equal (car prefix) it) + (!cdr prefix))) + (null prefix)) (defun -is-suffix? (suffix list) - "Return non-nil if SUFFIX is suffix of LIST. + "Return non-nil if SUFFIX is a suffix of LIST. -Alias: `-is-suffix-p'" +Alias: `-is-suffix-p'." (declare (pure t) (side-effect-free t)) - (-is-prefix? (reverse suffix) (reverse list))) + (cond ((null suffix)) + ((setq list (member (car suffix) list)) + (equal (cdr suffix) (cdr list))))) (defun -is-infix? (infix list) "Return non-nil if INFIX is infix of LIST. @@ -2470,22 +2687,24 @@ if the first element should sort before the second." (declare (debug (form form))) `(-sort (lambda (it other) ,form) ,list)) -(defun -list (&rest args) - "Return a list with ARGS. +(defun -list (&optional arg &rest args) + "Ensure ARG is a list. +If ARG is already a list, return it as is (not a copy). +Otherwise, return a new list with ARG as its only element. -If first item of ARGS is already a list, simply return ARGS. If -not, return a list with ARGS as elements." - (declare (pure t) (side-effect-free t)) - (let ((arg (car args))) - (if (listp arg) arg args))) +Another supported calling convention is (-list &rest ARGS). +In this case, if ARG is not a list, a new list with all of +ARGS as elements is returned. This use is supported for +backward compatibility and is otherwise deprecated." + (declare (advertised-calling-convention (arg) "2.18.0") + (pure t) (side-effect-free t)) + (if (listp arg) arg (cons arg args))) (defun -repeat (n x) - "Return a list with X repeated N times. + "Return a new list of length N with each element being X. Return nil if N is less than 1." (declare (pure t) (side-effect-free t)) - (let (ret) - (--dotimes n (!cons x ret)) - ret)) + (and (natnump n) (make-list n x))) (defun -sum (list) "Return the sum of LIST." @@ -2494,12 +2713,10 @@ Return nil if N is less than 1." (defun -running-sum (list) "Return a list with running sums of items in LIST. - LIST must be non-empty." (declare (pure t) (side-effect-free t)) - (unless (consp list) - (error "LIST must be non-empty")) - (-reductions '+ list)) + (or list (signal 'wrong-type-argument (list #'consp list))) + (-reductions #'+ list)) (defun -product (list) "Return the product of LIST." @@ -2508,12 +2725,10 @@ LIST must be non-empty." (defun -running-product (list) "Return a list with running products of items in LIST. - LIST must be non-empty." (declare (pure t) (side-effect-free t)) - (unless (consp list) - (error "LIST must be non-empty")) - (-reductions '* list)) + (or list (signal 'wrong-type-argument (list #'consp list))) + (-reductions #'* list)) (defun -max (list) "Return the largest value from LIST of numbers or markers." @@ -2555,19 +2770,20 @@ The items for the comparator form are exposed as \"it\" and \"other\"." (declare (debug (form form))) `(-min-by (lambda (it other) ,form) ,list)) -(defun -iterate (fun init n) - "Return a list of iterated applications of FUN to INIT. - -This means a list of form: - - (init (fun init) (fun (fun init)) ...) - -N is the length of the returned list." - (if (= n 0) nil - (let ((r (list init))) - (--dotimes (1- n) - (push (funcall fun (car r)) r)) - (nreverse r)))) +(defun -iota (count &optional start step) + "Return a list containing COUNT numbers. +Starts from START and adds STEP each time. The default START is +zero, the default STEP is 1. +This function takes its name from the corresponding primitive in +the APL language." + (declare (pure t) (side-effect-free t)) + (unless (natnump count) + (signal 'wrong-type-argument (list #'natnump count))) + (or start (setq start 0)) + (or step (setq step 1)) + (if (zerop step) + (make-list count start) + (--iterate (+ it step) start count))) (defun -fix (fn list) "Compute the (least) fixpoint of FN with initial input LIST. @@ -2604,14 +2820,13 @@ the new seed." (declare (debug (form form))) `(-unfold (lambda (it) ,form) ,seed)) -(defun -cons-pair? (con) - "Return non-nil if CON is true cons pair. -That is (A . B) where B is not a list. +(defun -cons-pair? (obj) + "Return non-nil if OBJ is a true cons pair. +That is, a cons (A . B) where B is not a list. -Alias: `-cons-pair-p'" +Alias: `-cons-pair-p'." (declare (pure t) (side-effect-free t)) - (and (listp con) - (not (listp (cdr con))))) + (nlistp (cdr-safe obj))) (defalias '-cons-pair-p '-cons-pair?) @@ -2774,299 +2989,389 @@ replaced with new ones. This is useful when you need to clone a structure such as plist or alist." (declare (pure t) (side-effect-free t)) (-tree-map 'identity list)) + +;;; Combinators -(defun dash-enable-font-lock () - "Add syntax highlighting to dash functions, macros and magic values." - (eval-after-load 'lisp-mode - '(progn - (let ((new-keywords '( - "!cons" - "!cdr" - "-each" - "--each" - "-each-indexed" - "--each-indexed" - "-each-while" - "--each-while" - "-doto" - "-dotimes" - "--dotimes" - "-map" - "--map" - "-reduce-from" - "--reduce-from" - "-reduce" - "--reduce" - "-reduce-r-from" - "--reduce-r-from" - "-reduce-r" - "--reduce-r" - "-reductions-from" - "-reductions-r-from" - "-reductions" - "-reductions-r" - "-filter" - "--filter" - "-select" - "--select" - "-remove" - "--remove" - "-reject" - "--reject" - "-remove-first" - "--remove-first" - "-reject-first" - "--reject-first" - "-remove-last" - "--remove-last" - "-reject-last" - "--reject-last" - "-remove-item" - "-non-nil" - "-keep" - "--keep" - "-map-indexed" - "--map-indexed" - "-splice" - "--splice" - "-splice-list" - "--splice-list" - "-map-when" - "--map-when" - "-replace-where" - "--replace-where" - "-map-first" - "--map-first" - "-map-last" - "--map-last" - "-replace" - "-replace-first" - "-replace-last" - "-flatten" - "-flatten-n" - "-concat" - "-mapcat" - "--mapcat" - "-copy" - "-cons*" - "-snoc" - "-first" - "--first" - "-find" - "--find" - "-some" - "--some" - "-any" - "--any" - "-last" - "--last" - "-first-item" - "-second-item" - "-third-item" - "-fourth-item" - "-fifth-item" - "-last-item" - "-butlast" - "-count" - "--count" - "-any?" - "--any?" - "-some?" - "--some?" - "-any-p" - "--any-p" - "-some-p" - "--some-p" - "-some->" - "-some->>" - "-some-->" - "-all?" - "-all-p" - "--all?" - "--all-p" - "-every?" - "--every?" - "-all-p" - "--all-p" - "-every-p" - "--every-p" - "-none?" - "--none?" - "-none-p" - "--none-p" - "-only-some?" - "--only-some?" - "-only-some-p" - "--only-some-p" - "-slice" - "-take" - "-drop" - "-drop-last" - "-take-last" - "-take-while" - "--take-while" - "-drop-while" - "--drop-while" - "-split-at" - "-rotate" - "-insert-at" - "-replace-at" - "-update-at" - "--update-at" - "-remove-at" - "-remove-at-indices" - "-split-with" - "--split-with" - "-split-on" - "-split-when" - "--split-when" - "-separate" - "--separate" - "-partition-all-in-steps" - "-partition-in-steps" - "-partition-all" - "-partition" - "-partition-after-item" - "-partition-after-pred" - "-partition-before-item" - "-partition-before-pred" - "-partition-by" - "--partition-by" - "-partition-by-header" - "--partition-by-header" - "-group-by" - "--group-by" - "-interpose" - "-interleave" - "-unzip" - "-zip-with" - "--zip-with" - "-zip" - "-zip-fill" - "-zip-lists" - "-zip-pair" - "-cycle" - "-pad" - "-annotate" - "--annotate" - "-table" - "-table-flat" - "-partial" - "-elem-index" - "-elem-indices" - "-find-indices" - "--find-indices" - "-find-index" - "--find-index" - "-find-last-index" - "--find-last-index" - "-select-by-indices" - "-select-columns" - "-select-column" - "-grade-up" - "-grade-down" - "->" - "->>" - "-->" - "-as->" - "-when-let" - "-when-let*" - "--when-let" - "-if-let" - "-if-let*" - "--if-let" - "-let*" - "-let" - "-lambda" - "-distinct" - "-uniq" - "-union" - "-intersection" - "-difference" - "-powerset" - "-permutations" - "-inits" - "-tails" - "-common-prefix" - "-common-suffix" - "-contains?" - "-contains-p" - "-same-items?" - "-same-items-p" - "-is-prefix-p" - "-is-prefix?" - "-is-suffix-p" - "-is-suffix?" - "-is-infix-p" - "-is-infix?" - "-sort" - "--sort" - "-list" - "-repeat" - "-sum" - "-running-sum" - "-product" - "-running-product" - "-max" - "-min" - "-max-by" - "--max-by" - "-min-by" - "--min-by" - "-iterate" - "--iterate" - "-fix" - "--fix" - "-unfold" - "--unfold" - "-cons-pair?" - "-cons-pair-p" - "-cons-to-list" - "-value-to-list" - "-tree-mapreduce-from" - "--tree-mapreduce-from" - "-tree-mapreduce" - "--tree-mapreduce" - "-tree-map" - "--tree-map" - "-tree-reduce-from" - "--tree-reduce-from" - "-tree-reduce" - "--tree-reduce" - "-tree-seq" - "--tree-seq" - "-tree-map-nodes" - "--tree-map-nodes" - "-clone" - "-rpartial" - "-juxt" - "-applify" - "-on" - "-flip" - "-const" - "-cut" - "-orfn" - "-andfn" - "-iteratefn" - "-fixfn" - "-prodfn" - )) - (special-variables '( - "it" - "it-index" - "acc" - "other" - ))) - (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "\\_<" (regexp-opt special-variables 'paren) "\\_>") - 1 font-lock-variable-name-face)) 'append) - (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "(\\s-*" (regexp-opt new-keywords 'paren) "\\_>") - 1 font-lock-keyword-face)) 'append)) - (--each (buffer-list) - (with-current-buffer it - (when (and (eq major-mode 'emacs-lisp-mode) - (boundp 'font-lock-mode) - font-lock-mode) - (font-lock-refresh-defaults))))))) +(defun -partial (fn &rest args) + "Take a function FN and fewer than the normal arguments to FN, +and return a fn that takes a variable number of additional ARGS. +When called, the returned function calls FN with ARGS first and +then additional args." + (apply 'apply-partially fn args)) + +(defun -rpartial (fn &rest args) + "Takes a function FN and fewer than the normal arguments to FN, +and returns a fn that takes a variable number of additional ARGS. +When called, the returned function calls FN with the additional +args first and then ARGS." + (lambda (&rest args-before) (apply fn (append args-before args)))) + +(defun -juxt (&rest fns) + "Takes a list of functions and returns a fn that is the +juxtaposition of those fns. The returned fn takes a variable +number of args, and returns a list containing the result of +applying each fn to the args (left-to-right)." + (lambda (&rest args) (mapcar (lambda (x) (apply x args)) fns))) + +(defun -compose (&rest fns) + "Takes a list of functions and returns a fn that is the +composition of those fns. The returned fn takes a variable +number of arguments, and returns the result of applying +each fn to the result of applying the previous fn to +the arguments (right-to-left)." + (lambda (&rest args) + (car (-reduce-r-from (lambda (fn xs) (list (apply fn xs))) + args fns)))) + +(defun -applify (fn) + "Changes an n-arity function FN to a 1-arity function that +expects a list with n items as arguments" + (apply-partially 'apply fn)) + +(defun -on (operator transformer) + "Return a function of two arguments that first applies +TRANSFORMER to each of them and then applies OPERATOR on the +results (in the same order). + +In types: (b -> b -> c) -> (a -> b) -> a -> a -> c" + (lambda (x y) (funcall operator (funcall transformer x) (funcall transformer y)))) + +(defun -flip (func) + "Swap the order of arguments for binary function FUNC. + +In types: (a -> b -> c) -> b -> a -> c" + (lambda (x y) (funcall func y x))) + +(defun -const (c) + "Return a function that returns C ignoring any additional arguments. + +In types: a -> b -> a" + (lambda (&rest _) c)) + +(defmacro -cut (&rest params) + "Take n-ary function and n arguments and specialize some of them. +Arguments denoted by <> will be left unspecialized. + +See SRFI-26 for detailed description." + (let* ((i 0) + (args (--keep (when (eq it '<>) + (setq i (1+ i)) + (make-symbol (format "D%d" i))) + params))) + `(lambda ,args + ,(let ((body (--map (if (eq it '<>) (pop args) it) params))) + (if (eq (car params) '<>) + (cons 'funcall body) + body))))) + +(defun -not (pred) + "Take a unary predicate PRED and return a unary predicate +that returns t if PRED returns nil and nil if PRED returns +non-nil." + (lambda (x) (not (funcall pred x)))) + +(defun -orfn (&rest preds) + "Take list of unary predicates PREDS and return a unary +predicate with argument x that returns non-nil if at least one of +the PREDS returns non-nil on x. + +In types: [a -> Bool] -> a -> Bool" + (lambda (x) (-any? (-cut funcall <> x) preds))) + +(defun -andfn (&rest preds) + "Take list of unary predicates PREDS and return a unary +predicate with argument x that returns non-nil if all of the +PREDS returns non-nil on x. + +In types: [a -> Bool] -> a -> Bool" + (lambda (x) (-all? (-cut funcall <> x) preds))) + +(defun -iteratefn (fn n) + "Return a function FN composed N times with itself. + +FN is a unary function. If you need to use a function of higher +arity, use `-applify' first to turn it into a unary function. + +With n = 0, this acts as identity function. + +In types: (a -> a) -> Int -> a -> a. + +This function satisfies the following law: + + (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n)))." + (lambda (x) (--dotimes n (setq x (funcall fn x))) x)) + +(defun -counter (&optional beg end inc) + "Return a closure that counts from BEG to END, with increment INC. + +The closure will return the next value in the counting sequence +each time it is called, and nil after END is reached. BEG +defaults to 0, INC defaults to 1, and if END is nil, the counter +will increment indefinitely. + +The closure accepts any number of arguments, which are discarded." + (let ((inc (or inc 1)) + (n (or beg 0))) + (lambda (&rest _) + (when (or (not end) (< n end)) + (prog1 n + (setq n (+ n inc))))))) + +(defvar -fixfn-max-iterations 1000 + "The default maximum number of iterations performed by `-fixfn' + unless otherwise specified.") + +(defun -fixfn (fn &optional equal-test halt-test) + "Return a function that computes the (least) fixpoint of FN. + +FN must be a unary function. The returned lambda takes a single +argument, X, the initial value for the fixpoint iteration. The +iteration halts when either of the following conditions is satisfied: + + 1. Iteration converges to the fixpoint, with equality being + tested using EQUAL-TEST. If EQUAL-TEST is not specified, + `equal' is used. For functions over the floating point + numbers, it may be necessary to provide an appropriate + approximate comparison test. + + 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a + simple counter that returns t after `-fixfn-max-iterations', + to guard against infinite iteration. Otherwise, HALT-TEST + must be a function that accepts a single argument, the + current value of X, and returns non-nil as long as iteration + should continue. In this way, a more sophisticated + convergence test may be supplied by the caller. + +The return value of the lambda is either the fixpoint or, if +iteration halted before converging, a cons with car `halted' and +cdr the final output from HALT-TEST. + +In types: (a -> a) -> a -> a." + (let ((eqfn (or equal-test 'equal)) + (haltfn (or halt-test + (-not + (-counter 0 -fixfn-max-iterations))))) + (lambda (x) + (let ((re (funcall fn x)) + (halt? (funcall haltfn x))) + (while (and (not halt?) (not (funcall eqfn x re))) + (setq x re + re (funcall fn re) + halt? (funcall haltfn re))) + (if halt? (cons 'halted halt?) + re))))) + +(defun -prodfn (&rest fns) + "Take a list of n functions and return a function that takes a +list of length n, applying i-th function to i-th element of the +input list. Returns a list of length n. + +In types (for n=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d) + +This function satisfies the following laws: + + (-compose (-prodfn f g ...) (-prodfn f\\=' g\\=' ...)) = (-prodfn (-compose f f\\=') (-compose g g\\=') ...) + (-prodfn f g ...) = (-juxt (-compose f (-partial \\='nth 0)) (-compose g (-partial \\='nth 1)) ...) + (-compose (-prodfn f g ...) (-juxt f\\=' g\\=' ...)) = (-juxt (-compose f f\\=') (-compose g g\\=') ...) + (-compose (-partial \\='nth n) (-prod f1 f2 ...)) = (-compose fn (-partial \\='nth n))" + (lambda (x) (-zip-with 'funcall fns x))) + +;;; Font lock + +(defvar dash--keywords + `(;; TODO: Do not fontify the following automatic variables + ;; globally; detect and limit to their local anaphoric scope. + (,(rx symbol-start (| "acc" "it" "it-index" "other") symbol-end) + 0 font-lock-variable-name-face) + ;; Macros in dev/examples.el. Based on `lisp-mode-symbol-regexp'. + (,(rx ?\( (group (| "defexamples" "def-example-group")) symbol-end + (+ (in "\t ")) + (group (* (| (syntax word) (syntax symbol) (: ?\\ nonl))))) + (1 font-lock-keyword-face) + (2 font-lock-function-name-face)) + ;; Symbols in dev/examples.el. + ,(rx symbol-start (| "=>" "~>" "!!>") symbol-end) + ;; Elisp macro fontification was static prior to Emacs 25. + ,@(when (< emacs-major-version 25) + (let ((macs '("!cdr" + "!cons" + "-->" + "--all?" + "--annotate" + "--any?" + "--count" + "--dotimes" + "--doto" + "--drop-while" + "--each" + "--each-r" + "--each-r-while" + "--each-while" + "--filter" + "--find-index" + "--find-indices" + "--find-last-index" + "--first" + "--fix" + "--group-by" + "--if-let" + "--iterate" + "--keep" + "--last" + "--map" + "--map-first" + "--map-indexed" + "--map-last" + "--map-when" + "--mapcat" + "--max-by" + "--min-by" + "--none?" + "--only-some?" + "--partition-by" + "--partition-by-header" + "--reduce" + "--reduce-from" + "--reduce-r" + "--reduce-r-from" + "--reductions" + "--reductions-from" + "--reductions-r" + "--reductions-r-from" + "--remove" + "--remove-first" + "--remove-last" + "--separate" + "--some" + "--sort" + "--splice" + "--splice-list" + "--split-when" + "--split-with" + "--take-while" + "--tree-map" + "--tree-map-nodes" + "--tree-mapreduce" + "--tree-mapreduce-from" + "--tree-reduce" + "--tree-reduce-from" + "--tree-seq" + "--unfold" + "--update-at" + "--when-let" + "--zip-with" + "->" + "->>" + "-as->" + "-doto" + "-if-let" + "-if-let*" + "-lambda" + "-let" + "-let*" + "-setq" + "-some-->" + "-some->" + "-some->>" + "-split-on" + "-when-let" + "-when-let*"))) + `((,(concat "(" (regexp-opt macs 'symbols)) . 1))))) + "Font lock keywords for `dash-fontify-mode'.") + +(defcustom dash-fontify-mode-lighter nil + "Mode line lighter for `dash-fontify-mode'. +Either a string to display in the mode line when +`dash-fontify-mode' is on, or nil to display +nothing (the default)." + :package-version '(dash . "2.18.0") + :group 'dash + :type '(choice (string :tag "Lighter" :value " Dash") + (const :tag "Nothing" nil))) + +;;;###autoload +(define-minor-mode dash-fontify-mode + "Toggle fontification of Dash special variables. + +Dash-Fontify mode is a buffer-local minor mode intended for Emacs +Lisp buffers. Enabling it causes the special variables bound in +anaphoric Dash macros to be fontified. These anaphoras include +`it', `it-index', `acc', and `other'. In older Emacs versions +which do not dynamically detect macros, Dash-Fontify mode +additionally fontifies Dash macro calls. + +See also `dash-fontify-mode-lighter' and +`global-dash-fontify-mode'." + :group 'dash :lighter dash-fontify-mode-lighter + (if dash-fontify-mode + (font-lock-add-keywords nil dash--keywords t) + (font-lock-remove-keywords nil dash--keywords)) + (cond ((fboundp 'font-lock-flush) ;; Added in Emacs 25. + (font-lock-flush)) + ;; `font-lock-fontify-buffer' unconditionally enables + ;; `font-lock-mode' and is marked `interactive-only' in later + ;; Emacs versions which have `font-lock-flush', so we guard + ;; and pacify as needed, respectively. + (font-lock-mode + (with-no-warnings + (font-lock-fontify-buffer))))) + +(defun dash--turn-on-fontify-mode () + "Enable `dash-fontify-mode' if in an Emacs Lisp buffer." + (when (derived-mode-p #'emacs-lisp-mode) + (dash-fontify-mode))) + +;;;###autoload +(define-globalized-minor-mode global-dash-fontify-mode + dash-fontify-mode dash--turn-on-fontify-mode + :group 'dash) + +(defcustom dash-enable-fontlock nil + "If non-nil, fontify Dash macro calls and special variables." + :group 'dash + :set (lambda (sym val) + (set-default sym val) + (global-dash-fontify-mode (if val 1 0))) + :type 'boolean) + +(make-obsolete-variable + 'dash-enable-fontlock #'global-dash-fontify-mode "2.18.0") + +(define-obsolete-function-alias + 'dash-enable-font-lock #'global-dash-fontify-mode "2.18.0") + +;;; Info + +(defvar dash--info-doc-spec '("(dash) Index" nil "^ -+ .*: " "\\( \\|$\\)") + "The Dash :doc-spec entry for `info-lookup-alist'. +It is based on that for `emacs-lisp-mode'.") + +(defun dash--info-elisp-docs () + "Return the `emacs-lisp-mode' symbol docs from `info-lookup-alist'. +Specifically, return the cons containing their +`info-lookup->doc-spec' so that we can modify it." + (defvar info-lookup-alist) + (nthcdr 3 (assq #'emacs-lisp-mode (cdr (assq 'symbol info-lookup-alist))))) + +;;;###autoload +(defun dash-register-info-lookup () + "Register the Dash Info manual with `info-lookup-symbol'. +This allows Dash symbols to be looked up with \\[info-lookup-symbol]." + (interactive) + (require 'info-look) + (let ((docs (dash--info-elisp-docs))) + (setcar docs (append (car docs) (list dash--info-doc-spec))) + (info-lookup-reset))) + +(defun dash-unload-function () + "Remove Dash from `info-lookup-alist'. +Used by `unload-feature', which see." + (let ((docs (and (featurep 'info-look) + (dash--info-elisp-docs)))) + (when (member dash--info-doc-spec (car docs)) + (setcar docs (remove dash--info-doc-spec (car docs))) + (info-lookup-reset))) + nil) (provide 'dash) ;;; dash.el ends here diff --git a/elpa/dash-2.18.0/dash.info b/elpa/dash-2.18.0/dash.info new file mode 100644 index 0000000..d4550b0 --- /dev/null +++ b/elpa/dash-2.18.0/dash.info @@ -0,0 +1,4656 @@ +This is dash.info, produced by makeinfo version 6.5 from dash.texi. + +This manual is for Dash version 2.18.0. + + Copyright © 2012–2021 Free Software Foundation, Inc. + + 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 the Invariant Sections being “GNU General Public + License,” and no Front-Cover Texts or Back-Cover Texts. A copy of + the license is included in the section entitled “GNU Free + Documentation License”. +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Dash: (dash.info). A modern list library for GNU Emacs. +END-INFO-DIR-ENTRY + + +File: dash.info, Node: Top, Next: Installation, Up: (dir) + +Dash +**** + +This manual is for Dash version 2.18.0. + + Copyright © 2012–2021 Free Software Foundation, Inc. + + 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 the Invariant Sections being “GNU General Public + License,” and no Front-Cover Texts or Back-Cover Texts. A copy of + the license is included in the section entitled “GNU Free + Documentation License”. + +* Menu: + +* Installation:: Installing and configuring Dash. +* Functions:: Dash API reference. +* Development:: Contributing to Dash development. + +Appendices + +* FDL:: The license for this documentation. +* GPL:: Conditions for copying and changing Dash. +* Index:: Index including functions and macros. + + — The Detailed Node Listing — + +Installation + +* Using in a package:: Listing Dash as a package dependency. +* Fontification of special variables:: Font Lock of anaphoric macro variables. +* Info symbol lookup:: Looking up Dash symbols in this manual. + +Functions + +* Maps:: +* Sublist selection:: +* List to list:: +* Reductions:: +* Unfolding:: +* Predicates:: +* Partitioning:: +* Indexing:: +* Set operations:: +* Other list operations:: +* Tree operations:: +* Threading macros:: +* Binding:: +* Side effects:: +* Destructive operations:: +* Function combinators:: + +Development + +* Contribute:: How to contribute. +* Contributors:: List of contributors. + + +File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top + +1 Installation +************** + +Dash is available on GNU ELPA (https://elpa.gnu.org/) and MELPA +(https://melpa.org/), and can be installed with the standard command +‘package-install’ (*note (emacs)Package Installation::). + +‘M-x package-install dash ’ + Install the Dash library. + + Alternatively, you can just dump ‘dash.el’ in your ‘load-path’ +somewhere (*note (emacs)Lisp Libraries::). + +* Menu: + +* Using in a package:: Listing Dash as a package dependency. +* Fontification of special variables:: Font Lock of anaphoric macro variables. +* Info symbol lookup:: Looking up Dash symbols in this manual. + + +File: dash.info, Node: Using in a package, Next: Fontification of special variables, Up: Installation + +1.1 Using in a package +====================== + +If you use Dash in your own package, be sure to list it as a dependency +in the library’s headers as follows (*note (elisp)Library Headers::). + + ;; Package-Requires: ((dash "2.18.0")) + + +File: dash.info, Node: Fontification of special variables, Next: Info symbol lookup, Prev: Using in a package, Up: Installation + +1.2 Fontification of special variables +====================================== + +The autoloaded minor mode ‘dash-fontify-mode’ is provided for optional +fontification of anaphoric Dash variables (‘it’, ‘acc’, etc.) in Emacs +Lisp buffers using search-based Font Lock (*note (emacs)Font Lock::). +In older Emacs versions which do not dynamically detect macros, the +minor mode also fontifies calls to Dash macros. + + To automatically enable the minor mode in all Emacs Lisp buffers, +just call its autoloaded global counterpart ‘global-dash-fontify-mode’, +either interactively or from your ‘user-init-file’: + + (global-dash-fontify-mode) + + +File: dash.info, Node: Info symbol lookup, Prev: Fontification of special variables, Up: Installation + +1.3 Info symbol lookup +====================== + +While editing Elisp files, you can use ‘C-h S’ (‘info-lookup-symbol’) to +look up Elisp symbols in the relevant Info manuals (*note (emacs)Info +Lookup::). To enable the same for Dash symbols, use the command +‘dash-register-info-lookup’. It can be called directly when needed, or +automatically from your ‘user-init-file’. For example: + + (with-eval-after-load 'info-look + (dash-register-info-lookup)) + + +File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top + +2 Functions +*********** + +This chapter contains reference documentation for the Dash API +(Application Programming Interface). The names of all public functions +defined in the library are prefixed with a dash character (‘-’). + + The library also provides anaphoric macro versions of functions where +that makes sense. The names of these macros are prefixed with two +dashes (‘--’) instead of one. + + For instance, while the function ‘-map’ applies a function to each +element of a list, its anaphoric counterpart ‘--map’ evaluates a form +with the local variable ‘it’ temporarily bound to the current list +element instead. + + ;; Normal version. + (-map (lambda (n) (* n n)) '(1 2 3 4)) + ⇒ (1 4 9 16) + + ;; Anaphoric version. + (--map (* it it) '(1 2 3 4)) + ⇒ (1 4 9 16) + + The normal version can, of course, also be written as in the +following example, which demonstrates the utility of both versions. + + (defun my-square (n) + "Return N multiplied by itself." + (* n n)) + + (-map #'my-square '(1 2 3 4)) + ⇒ (1 4 9 16) + +* Menu: + +* Maps:: +* Sublist selection:: +* List to list:: +* Reductions:: +* Unfolding:: +* Predicates:: +* Partitioning:: +* Indexing:: +* Set operations:: +* Other list operations:: +* Tree operations:: +* Threading macros:: +* Binding:: +* Side effects:: +* Destructive operations:: +* Function combinators:: + + +File: dash.info, Node: Maps, Next: Sublist selection, Up: Functions + +2.1 Maps +======== + +Functions in this category take a transforming function, which is then +applied sequentially to each or selected elements of the input list. +The results are collected in order and returned as a new list. + + -- Function: -map (fn list) + Apply FN to each item in LIST and return the list of results. + + This function’s anaphoric counterpart is ‘--map’. + + (-map (lambda (num) (* num num)) '(1 2 3 4)) + ⇒ (1 4 9 16) + (-map #'1+ '(1 2 3 4)) + ⇒ (2 3 4 5) + (--map (* it it) '(1 2 3 4)) + ⇒ (1 4 9 16) + + -- Function: -map-when (pred rep list) + Return a new list where the elements in LIST that do not match the + PRED function are unchanged, and where the elements in LIST that do + match the PRED function are mapped through the REP function. + + Alias: ‘-replace-where’ + + See also: ‘-update-at’ (*note -update-at::) + + (-map-when 'even? 'square '(1 2 3 4)) + ⇒ (1 4 3 16) + (--map-when (> it 2) (* it it) '(1 2 3 4)) + ⇒ (1 2 9 16) + (--map-when (= it 2) 17 '(1 2 3 4)) + ⇒ (1 17 3 4) + + -- Function: -map-first (pred rep list) + Replace first item in LIST satisfying PRED with result of REP + called on this item. + + See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note + -replace-first::) + + (-map-first 'even? 'square '(1 2 3 4)) + ⇒ (1 4 3 4) + (--map-first (> it 2) (* it it) '(1 2 3 4)) + ⇒ (1 2 9 4) + (--map-first (= it 2) 17 '(1 2 3 2)) + ⇒ (1 17 3 2) + + -- Function: -map-last (pred rep list) + Replace last item in LIST satisfying PRED with result of REP called + on this item. + + See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note + -replace-last::) + + (-map-last 'even? 'square '(1 2 3 4)) + ⇒ (1 2 3 16) + (--map-last (> it 2) (* it it) '(1 2 3 4)) + ⇒ (1 2 3 16) + (--map-last (= it 2) 17 '(1 2 3 2)) + ⇒ (1 2 3 17) + + -- Function: -map-indexed (fn list) + Apply FN to each index and item in LIST and return the list of + results. This is like ‘-map’ (*note -map::), but FN takes two + arguments: the index of the current element within LIST, and the + element itself. + + This function’s anaphoric counterpart is ‘--map-indexed’. + + For a side-effecting variant, see also ‘-each-indexed’ (*note + -each-indexed::). + + (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4)) + ⇒ (1 1 1 1) + (--map-indexed (- it it-index) '(1 2 3 4)) + ⇒ (1 1 1 1) + (-map-indexed #'* '(1 2 3 4)) + ⇒ (0 2 6 12) + + -- Function: -annotate (fn list) + Return a list of cons cells where each cell is FN applied to each + element of LIST paired with the unmodified element of LIST. + + (-annotate '1+ '(1 2 3)) + ⇒ ((2 . 1) (3 . 2) (4 . 3)) + (-annotate 'length '(("h" "e" "l" "l" "o") ("hello" "world"))) + ⇒ ((5 "h" "e" "l" "l" "o") (2 "hello" "world")) + (--annotate (< 1 it) '(0 1 2 3)) + ⇒ ((nil . 0) (nil . 1) (t . 2) (t . 3)) + + -- Function: -splice (pred fun list) + Splice lists generated by FUN in place of elements matching PRED in + LIST. + + FUN takes the element matching PRED as input. + + This function can be used as replacement for ‘,@’ in case you need + to splice several lists at marked positions (for example with + keywords). + + See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’ + (*note -insert-at::) + + (-splice 'even? (lambda (x) (list x x)) '(1 2 3 4)) + ⇒ (1 2 2 3 4 4) + (--splice 't (list it it) '(1 2 3 4)) + ⇒ (1 1 2 2 3 3 4 4) + (--splice (equal it :magic) '((list of) (magical) (code)) '((foo) (bar) :magic (baz))) + ⇒ ((foo) (bar) (list of) (magical) (code) (baz)) + + -- Function: -splice-list (pred new-list list) + Splice NEW-LIST in place of elements matching PRED in LIST. + + See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note + -insert-at::) + + (-splice-list 'keywordp '(a b c) '(1 :foo 2)) + ⇒ (1 a b c 2) + (-splice-list 'keywordp nil '(1 :foo 2)) + ⇒ (1 2) + (--splice-list (keywordp it) '(a b c) '(1 :foo 2)) + ⇒ (1 a b c 2) + + -- Function: -mapcat (fn list) + Return the concatenation of the result of mapping FN over LIST. + Thus function FN should return a list. + + (-mapcat 'list '(1 2 3)) + ⇒ (1 2 3) + (-mapcat (lambda (item) (list 0 item)) '(1 2 3)) + ⇒ (0 1 0 2 0 3) + (--mapcat (list 0 it) '(1 2 3)) + ⇒ (0 1 0 2 0 3) + + -- Function: -copy (list) + Create a shallow copy of LIST. + + (-copy '(1 2 3)) + ⇒ (1 2 3) + (let ((a '(1 2 3))) (eq a (-copy a))) + ⇒ nil + + +File: dash.info, Node: Sublist selection, Next: List to list, Prev: Maps, Up: Functions + +2.2 Sublist selection +===================== + +Functions returning a sublist of the original list. + + -- Function: -filter (pred list) + Return a new list of the items in LIST for which PRED returns + non-nil. + + Alias: ‘-select’. + + This function’s anaphoric counterpart is ‘--filter’. + + For similar operations, see also ‘-keep’ (*note -keep::) and + ‘-remove’ (*note -remove::). + + (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) + ⇒ (2 4) + (-filter #'natnump '(-2 -1 0 1 2)) + ⇒ (0 1 2) + (--filter (= 0 (% it 2)) '(1 2 3 4)) + ⇒ (2 4) + + -- Function: -remove (pred list) + Return a new list of the items in LIST for which PRED returns nil. + + Alias: ‘-reject’. + + This function’s anaphoric counterpart is ‘--remove’. + + For similar operations, see also ‘-keep’ (*note -keep::) and + ‘-filter’ (*note -filter::). + + (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) + ⇒ (1 3) + (-remove #'natnump '(-2 -1 0 1 2)) + ⇒ (-2 -1) + (--remove (= 0 (% it 2)) '(1 2 3 4)) + ⇒ (1 3) + + -- Function: -remove-first (pred list) + Remove the first item from LIST for which PRED returns non-nil. + This is a non-destructive operation, but only the front of LIST + leading up to the removed item is a copy; the rest is LIST’s + original tail. If no item is removed, then the result is a + complete copy. + + Alias: ‘-reject-first’. + + This function’s anaphoric counterpart is ‘--remove-first’. + + See also ‘-map-first’ (*note -map-first::), ‘-remove-item’ (*note + -remove-item::), and ‘-remove-last’ (*note -remove-last::). + + (-remove-first #'natnump '(-2 -1 0 1 2)) + ⇒ (-2 -1 1 2) + (-remove-first #'stringp '(1 2 "first" "second")) + ⇒ (1 2 "second") + (--remove-first (> it 3) '(1 2 3 4 5 6)) + ⇒ (1 2 3 5 6) + + -- Function: -remove-last (pred list) + Remove the last item from LIST for which PRED returns non-nil. The + result is a copy of LIST regardless of whether an element is + removed. + + Alias: ‘-reject-last’. + + This function’s anaphoric counterpart is ‘--remove-last’. + + See also ‘-map-last’ (*note -map-last::), ‘-remove-item’ (*note + -remove-item::), and ‘-remove-first’ (*note -remove-first::). + + (-remove-last #'natnump '(1 3 5 4 7 8 10 -11)) + ⇒ (1 3 5 4 7 8 -11) + (-remove-last #'stringp '(1 2 "last" "second")) + ⇒ (1 2 "last") + (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10)) + ⇒ (1 2 3 4 5 6 7 8 9) + + -- Function: -remove-item (item list) + Return a copy of LIST with all occurrences of ITEM removed. The + comparison is done with ‘equal’. + + (-remove-item 3 '(1 2 3 2 3 4 5 3)) + ⇒ (1 2 2 4 5) + (-remove-item 'foo '(foo bar baz foo)) + ⇒ (bar baz) + (-remove-item "bob" '("alice" "bob" "eve" "bob")) + ⇒ ("alice" "eve") + + -- Function: -non-nil (list) + Return a copy of LIST with all nil items removed. + + (-non-nil '(nil 1 nil 2 nil nil 3 4 nil 5 nil)) + ⇒ (1 2 3 4 5) + (-non-nil '((nil))) + ⇒ ((nil)) + (-non-nil ()) + ⇒ () + + -- Function: -slice (list from &optional to step) + Return copy of LIST, starting from index FROM to index TO. + + FROM or TO may be negative. These values are then interpreted + modulo the length of the list. + + If STEP is a number, only each STEPth item in the resulting section + is returned. Defaults to 1. + + (-slice '(1 2 3 4 5) 1) + ⇒ (2 3 4 5) + (-slice '(1 2 3 4 5) 0 3) + ⇒ (1 2 3) + (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) + ⇒ (2 4 6 8) + + -- Function: -take (n list) + Return a copy of the first N items in LIST. Return a copy of LIST + if it contains N items or fewer. Return nil if N is zero or less. + + See also: ‘-take-last’ (*note -take-last::). + + (-take 3 '(1 2 3 4 5)) + ⇒ (1 2 3) + (-take 17 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + (-take 0 '(1 2 3 4 5)) + ⇒ () + + -- Function: -take-last (n list) + Return a copy of the last N items of LIST in order. Return a copy + of LIST if it contains N items or fewer. Return nil if N is zero + or less. + + See also: ‘-take’ (*note -take::). + + (-take-last 3 '(1 2 3 4 5)) + ⇒ (3 4 5) + (-take-last 17 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + (-take-last 1 '(1 2 3 4 5)) + ⇒ (5) + + -- Function: -drop (n list) + Return the tail (not a copy) of LIST without the first N items. + Return nil if LIST contains N items or fewer. Return LIST if N is + zero or less. + + For another variant, see also ‘-drop-last’ (*note -drop-last::). + + (-drop 3 '(1 2 3 4 5)) + ⇒ (4 5) + (-drop 17 '(1 2 3 4 5)) + ⇒ () + (-drop 0 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + + -- Function: -drop-last (n list) + Return a copy of LIST without its last N items. Return a copy of + LIST if N is zero or less. Return nil if LIST contains N items or + fewer. + + See also: ‘-drop’ (*note -drop::). + + (-drop-last 3 '(1 2 3 4 5)) + ⇒ (1 2) + (-drop-last 17 '(1 2 3 4 5)) + ⇒ () + (-drop-last 0 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + + -- Function: -take-while (pred list) + Take successive items from LIST for which PRED returns non-nil. + PRED is a function of one argument. Return a new list of the + successive elements from the start of LIST for which PRED returns + non-nil. + + This function’s anaphoric counterpart is ‘--take-while’. + + For another variant, see also ‘-drop-while’ (*note -drop-while::). + + (-take-while #'even? '(1 2 3 4)) + ⇒ () + (-take-while #'even? '(2 4 5 6)) + ⇒ (2 4) + (--take-while (< it 4) '(1 2 3 4 3 2 1)) + ⇒ (1 2 3) + + -- Function: -drop-while (pred list) + Drop successive items from LIST for which PRED returns non-nil. + PRED is a function of one argument. Return the tail (not a copy) + of LIST starting from its first element for which PRED returns nil. + + This function’s anaphoric counterpart is ‘--drop-while’. + + For another variant, see also ‘-take-while’ (*note -take-while::). + + (-drop-while #'even? '(1 2 3 4)) + ⇒ (1 2 3 4) + (-drop-while #'even? '(2 4 5 6)) + ⇒ (5 6) + (--drop-while (< it 4) '(1 2 3 4 3 2 1)) + ⇒ (4 3 2 1) + + -- Function: -select-by-indices (indices list) + Return a list whose elements are elements from LIST selected as + ‘(nth i list)‘ for all i from INDICES. + + (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) + ⇒ ("c" "o" "l" "o" "r") + (-select-by-indices '(2 1 0) '("a" "b" "c")) + ⇒ ("c" "b" "a") + (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) + ⇒ ("f" "a" "r" "f" "a" "l" "l" "a") + + -- Function: -select-columns (columns table) + Select COLUMNS from TABLE. + + TABLE is a list of lists where each element represents one row. It + is assumed each row has the same length. + + Each row is transformed such that only the specified COLUMNS are + selected. + + See also: ‘-select-column’ (*note -select-column::), + ‘-select-by-indices’ (*note -select-by-indices::) + + (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c))) + ⇒ ((1 3) (a c) (:a :c)) + (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c))) + ⇒ ((2) (b) (:b)) + (-select-columns nil '((1 2 3) (a b c) (:a :b :c))) + ⇒ (nil nil nil) + + -- Function: -select-column (column table) + Select COLUMN from TABLE. + + TABLE is a list of lists where each element represents one row. It + is assumed each row has the same length. + + The single selected column is returned as a list. + + See also: ‘-select-columns’ (*note -select-columns::), + ‘-select-by-indices’ (*note -select-by-indices::) + + (-select-column 1 '((1 2 3) (a b c) (:a :b :c))) + ⇒ (2 b :b) + + +File: dash.info, Node: List to list, Next: Reductions, Prev: Sublist selection, Up: Functions + +2.3 List to list +================ + +Functions returning a modified copy of the input list. + + -- Function: -keep (fn list) + Return a new list of the non-nil results of applying FN to each + item in LIST. Like ‘-filter’ (*note -filter::), but returns the + non-nil results of FN instead of the corresponding elements of + LIST. + + Its anaphoric counterpart is ‘--keep’. + + (-keep #'cdr '((1 2 3) (4 5) (6))) + ⇒ ((2 3) (5)) + (-keep (lambda (n) (and (> n 3) (* 10 n))) '(1 2 3 4 5 6)) + ⇒ (40 50 60) + (--keep (and (> it 3) (* 10 it)) '(1 2 3 4 5 6)) + ⇒ (40 50 60) + + -- Function: -concat (&rest lists) + Return a new list with the concatenation of the elements in the + supplied LISTS. + + (-concat '(1)) + ⇒ (1) + (-concat '(1) '(2)) + ⇒ (1 2) + (-concat '(1) '(2 3) '(4)) + ⇒ (1 2 3 4) + + -- Function: -flatten (l) + Take a nested list L and return its contents as a single, flat + list. + + Note that because ‘nil’ represents a list of zero elements (an + empty list), any mention of nil in L will disappear after + flattening. If you need to preserve nils, consider ‘-flatten-n’ + (*note -flatten-n::) or map them to some unique symbol and then map + them back. + + Conses of two atoms are considered "terminals", that is, they + aren’t flattened further. + + See also: ‘-flatten-n’ (*note -flatten-n::) + + (-flatten '((1))) + ⇒ (1) + (-flatten '((1 (2 3) (((4 (5))))))) + ⇒ (1 2 3 4 5) + (-flatten '(1 2 (3 . 4))) + ⇒ (1 2 (3 . 4)) + + -- Function: -flatten-n (num list) + Flatten NUM levels of a nested LIST. + + See also: ‘-flatten’ (*note -flatten::) + + (-flatten-n 1 '((1 2) ((3 4) ((5 6))))) + ⇒ (1 2 (3 4) ((5 6))) + (-flatten-n 2 '((1 2) ((3 4) ((5 6))))) + ⇒ (1 2 3 4 (5 6)) + (-flatten-n 3 '((1 2) ((3 4) ((5 6))))) + ⇒ (1 2 3 4 5 6) + + -- Function: -replace (old new list) + Replace all OLD items in LIST with NEW. + + Elements are compared using ‘equal’. + + See also: ‘-replace-at’ (*note -replace-at::) + + (-replace 1 "1" '(1 2 3 4 3 2 1)) + ⇒ ("1" 2 3 4 3 2 "1") + (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) + ⇒ ("a" "nice" "bar" "sentence" "about" "bar") + (-replace 1 2 nil) + ⇒ nil + + -- Function: -replace-first (old new list) + Replace the first occurrence of OLD with NEW in LIST. + + Elements are compared using ‘equal’. + + See also: ‘-map-first’ (*note -map-first::) + + (-replace-first 1 "1" '(1 2 3 4 3 2 1)) + ⇒ ("1" 2 3 4 3 2 1) + (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) + ⇒ ("a" "nice" "bar" "sentence" "about" "foo") + (-replace-first 1 2 nil) + ⇒ nil + + -- Function: -replace-last (old new list) + Replace the last occurrence of OLD with NEW in LIST. + + Elements are compared using ‘equal’. + + See also: ‘-map-last’ (*note -map-last::) + + (-replace-last 1 "1" '(1 2 3 4 3 2 1)) + ⇒ (1 2 3 4 3 2 "1") + (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) + ⇒ ("a" "nice" "foo" "sentence" "about" "bar") + (-replace-last 1 2 nil) + ⇒ nil + + -- Function: -insert-at (n x list) + Return a list with X inserted into LIST at position N. + + See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note + -splice-list::) + + (-insert-at 1 'x '(a b c)) + ⇒ (a x b c) + (-insert-at 12 'x '(a b c)) + ⇒ (a b c x) + + -- Function: -replace-at (n x list) + Return a list with element at Nth position in LIST replaced with X. + + See also: ‘-replace’ (*note -replace::) + + (-replace-at 0 9 '(0 1 2 3 4 5)) + ⇒ (9 1 2 3 4 5) + (-replace-at 1 9 '(0 1 2 3 4 5)) + ⇒ (0 9 2 3 4 5) + (-replace-at 4 9 '(0 1 2 3 4 5)) + ⇒ (0 1 2 3 9 5) + + -- Function: -update-at (n func list) + Return a list with element at Nth position in LIST replaced with + ‘(func (nth n list))‘. + + See also: ‘-map-when’ (*note -map-when::) + + (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5)) + ⇒ (9 1 2 3 4 5) + (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5)) + ⇒ (0 9 2 3 4 5) + (--update-at 2 (length it) '("foo" "bar" "baz" "quux")) + ⇒ ("foo" "bar" 3 "quux") + + -- Function: -remove-at (n list) + Return a list with element at Nth position in LIST removed. + + See also: ‘-remove-at-indices’ (*note -remove-at-indices::), + ‘-remove’ (*note -remove::) + + (-remove-at 0 '("0" "1" "2" "3" "4" "5")) + ⇒ ("1" "2" "3" "4" "5") + (-remove-at 1 '("0" "1" "2" "3" "4" "5")) + ⇒ ("0" "2" "3" "4" "5") + (-remove-at 2 '("0" "1" "2" "3" "4" "5")) + ⇒ ("0" "1" "3" "4" "5") + + -- Function: -remove-at-indices (indices list) + Return a list whose elements are elements from LIST without + elements selected as ‘(nth i list)‘ for all i from INDICES. + + See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note + -remove::) + + (-remove-at-indices '(0) '("0" "1" "2" "3" "4" "5")) + ⇒ ("1" "2" "3" "4" "5") + (-remove-at-indices '(0 2 4) '("0" "1" "2" "3" "4" "5")) + ⇒ ("1" "3" "5") + (-remove-at-indices '(0 5) '("0" "1" "2" "3" "4" "5")) + ⇒ ("1" "2" "3" "4") + + +File: dash.info, Node: Reductions, Next: Unfolding, Prev: List to list, Up: Functions + +2.4 Reductions +============== + +Functions reducing lists to a single value (which may also be a list). + + -- Function: -reduce-from (fn init list) + Reduce the function FN across LIST, starting with INIT. Return the + result of applying FN to INIT and the first element of LIST, then + applying FN to that result and the second element, etc. If LIST is + empty, return INIT without calling FN. + + This function’s anaphoric counterpart is ‘--reduce-from’. + + For other folds, see also ‘-reduce’ (*note -reduce::) and + ‘-reduce-r’ (*note -reduce-r::). + + (-reduce-from #'- 10 '(1 2 3)) + ⇒ 4 + (-reduce-from #'list 10 '(1 2 3)) + ⇒ (((10 1) 2) 3) + (--reduce-from (concat acc " " it) "START" '("a" "b" "c")) + ⇒ "START a b c" + + -- Function: -reduce-r-from (fn init list) + Reduce the function FN across LIST in reverse, starting with INIT. + Return the result of applying FN to the last element of LIST and + INIT, then applying FN to the second-to-last element and the + previous result of FN, etc. That is, the first argument of FN is + the current element, and its second argument the accumulated value. + If LIST is empty, return INIT without calling FN. + + This function is like ‘-reduce-from’ (*note -reduce-from::) but the + operation associates from the right rather than left. In other + words, it starts from the end of LIST and flips the arguments to + FN. Conceptually, it is like replacing the conses in LIST with + applications of FN, and its last link with INIT, and evaluating the + resulting expression. + + This function’s anaphoric counterpart is ‘--reduce-r-from’. + + For other folds, see also ‘-reduce-r’ (*note -reduce-r::) and + ‘-reduce’ (*note -reduce::). + + (-reduce-r-from #'- 10 '(1 2 3)) + ⇒ -8 + (-reduce-r-from #'list 10 '(1 2 3)) + ⇒ (1 (2 (3 10))) + (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c")) + ⇒ "a b c END" + + -- Function: -reduce (fn list) + Reduce the function FN across LIST. Return the result of applying + FN to the first two elements of LIST, then applying FN to that + result and the third element, etc. If LIST contains a single + element, return it without calling FN. If LIST is empty, return + the result of calling FN with no arguments. + + This function’s anaphoric counterpart is ‘--reduce’. + + For other folds, see also ‘-reduce-from’ (*note -reduce-from::) and + ‘-reduce-r’ (*note -reduce-r::). + + (-reduce #'- '(1 2 3 4)) + ⇒ -8 + (-reduce #'list '(1 2 3 4)) + ⇒ (((1 2) 3) 4) + (--reduce (format "%s-%d" acc it) '(1 2 3)) + ⇒ "1-2-3" + + -- Function: -reduce-r (fn list) + Reduce the function FN across LIST in reverse. Return the result + of applying FN to the last two elements of LIST, then applying FN + to the third-to-last element and the previous result of FN, etc. + That is, the first argument of FN is the current element, and its + second argument the accumulated value. If LIST contains a single + element, return it without calling FN. If LIST is empty, return + the result of calling FN with no arguments. + + This function is like ‘-reduce’ (*note -reduce::) but the operation + associates from the right rather than left. In other words, it + starts from the end of LIST and flips the arguments to FN. + Conceptually, it is like replacing the conses in LIST with + applications of FN, ignoring its last link, and evaluating the + resulting expression. + + This function’s anaphoric counterpart is ‘--reduce-r’. + + For other folds, see also ‘-reduce-r-from’ (*note -reduce-r-from::) + and ‘-reduce’ (*note -reduce::). + + (-reduce-r #'- '(1 2 3 4)) + ⇒ -2 + (-reduce-r #'list '(1 2 3 4)) + ⇒ (1 (2 (3 4))) + (--reduce-r (format "%s-%d" acc it) '(1 2 3)) + ⇒ "3-2-1" + + -- Function: -reductions-from (fn init list) + Return a list of FN’s intermediate reductions across LIST. That + is, a list of the intermediate values of the accumulator when + ‘-reduce-from’ (*note -reduce-from::) (which see) is called with + the same arguments. + + This function’s anaphoric counterpart is ‘--reductions-from’. + + For other folds, see also ‘-reductions’ (*note -reductions::) and + ‘-reductions-r’ (*note -reductions-r::). + + (-reductions-from #'max 0 '(2 1 4 3)) + ⇒ (0 2 2 4 4) + (-reductions-from #'* 1 '(1 2 3 4)) + ⇒ (1 1 2 6 24) + (--reductions-from (format "(FN %s %d)" acc it) "INIT" '(1 2 3)) + ⇒ ("INIT" "(FN INIT 1)" "(FN (FN INIT 1) 2)" "(FN (FN (FN INIT 1) 2) 3)") + + -- Function: -reductions-r-from (fn init list) + Return a list of FN’s intermediate reductions across reversed LIST. + That is, a list of the intermediate values of the accumulator when + ‘-reduce-r-from’ (*note -reduce-r-from::) (which see) is called + with the same arguments. + + This function’s anaphoric counterpart is ‘--reductions-r-from’. + + For other folds, see also ‘-reductions’ (*note -reductions::) and + ‘-reductions-r’ (*note -reductions-r::). + + (-reductions-r-from #'max 0 '(2 1 4 3)) + ⇒ (4 4 4 3 0) + (-reductions-r-from #'* 1 '(1 2 3 4)) + ⇒ (24 24 12 4 1) + (--reductions-r-from (format "(FN %d %s)" it acc) "INIT" '(1 2 3)) + ⇒ ("(FN 1 (FN 2 (FN 3 INIT)))" "(FN 2 (FN 3 INIT))" "(FN 3 INIT)" "INIT") + + -- Function: -reductions (fn list) + Return a list of FN’s intermediate reductions across LIST. That + is, a list of the intermediate values of the accumulator when + ‘-reduce’ (*note -reduce::) (which see) is called with the same + arguments. + + This function’s anaphoric counterpart is ‘--reductions’. + + For other folds, see also ‘-reductions’ (*note -reductions::) and + ‘-reductions-r’ (*note -reductions-r::). + + (-reductions #'+ '(1 2 3 4)) + ⇒ (1 3 6 10) + (-reductions #'* '(1 2 3 4)) + ⇒ (1 2 6 24) + (--reductions (format "(FN %s %d)" acc it) '(1 2 3)) + ⇒ (1 "(FN 1 2)" "(FN (FN 1 2) 3)") + + -- Function: -reductions-r (fn list) + Return a list of FN’s intermediate reductions across reversed LIST. + That is, a list of the intermediate values of the accumulator when + ‘-reduce-r’ (*note -reduce-r::) (which see) is called with the same + arguments. + + This function’s anaphoric counterpart is ‘--reductions-r’. + + For other folds, see also ‘-reductions-r-from’ (*note + -reductions-r-from::) and ‘-reductions’ (*note -reductions::). + + (-reductions-r #'+ '(1 2 3 4)) + ⇒ (10 9 7 4) + (-reductions-r #'* '(1 2 3 4)) + ⇒ (24 24 12 4) + (--reductions-r (format "(FN %d %s)" it acc) '(1 2 3)) + ⇒ ("(FN 1 (FN 2 3))" "(FN 2 3)" 3) + + -- Function: -count (pred list) + Counts the number of items in LIST where (PRED item) is non-nil. + + (-count 'even? '(1 2 3 4 5)) + ⇒ 2 + (--count (< it 4) '(1 2 3 4)) + ⇒ 3 + + -- Function: -sum (list) + Return the sum of LIST. + + (-sum ()) + ⇒ 0 + (-sum '(1)) + ⇒ 1 + (-sum '(1 2 3 4)) + ⇒ 10 + + -- Function: -running-sum (list) + Return a list with running sums of items in LIST. LIST must be + non-empty. + + (-running-sum '(1 2 3 4)) + ⇒ (1 3 6 10) + (-running-sum '(1)) + ⇒ (1) + (-running-sum ()) + error→ Wrong type argument: consp, nil + + -- Function: -product (list) + Return the product of LIST. + + (-product ()) + ⇒ 1 + (-product '(1)) + ⇒ 1 + (-product '(1 2 3 4)) + ⇒ 24 + + -- Function: -running-product (list) + Return a list with running products of items in LIST. LIST must be + non-empty. + + (-running-product '(1 2 3 4)) + ⇒ (1 2 6 24) + (-running-product '(1)) + ⇒ (1) + (-running-product ()) + error→ Wrong type argument: consp, nil + + -- Function: -inits (list) + Return all prefixes of LIST. + + (-inits '(1 2 3 4)) + ⇒ (nil (1) (1 2) (1 2 3) (1 2 3 4)) + (-inits nil) + ⇒ (nil) + (-inits '(1)) + ⇒ (nil (1)) + + -- Function: -tails (list) + Return all suffixes of LIST + + (-tails '(1 2 3 4)) + ⇒ ((1 2 3 4) (2 3 4) (3 4) (4) nil) + (-tails nil) + ⇒ (nil) + (-tails '(1)) + ⇒ ((1) nil) + + -- Function: -common-prefix (&rest lists) + Return the longest common prefix of LISTS. + + (-common-prefix '(1)) + ⇒ (1) + (-common-prefix '(1 2) '(3 4) '(1 2)) + ⇒ () + (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4)) + ⇒ (1 2) + + -- Function: -common-suffix (&rest lists) + Return the longest common suffix of LISTS. + + (-common-suffix '(1)) + ⇒ (1) + (-common-suffix '(1 2) '(3 4) '(1 2)) + ⇒ () + (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4)) + ⇒ (3 4) + + -- Function: -min (list) + Return the smallest value from LIST of numbers or markers. + + (-min '(0)) + ⇒ 0 + (-min '(3 2 1)) + ⇒ 1 + (-min '(1 2 3)) + ⇒ 1 + + -- Function: -min-by (comparator list) + Take a comparison function COMPARATOR and a LIST and return the + least element of the list by the comparison function. + + See also combinator ‘-on’ (*note -on::) which can transform the + values before comparing them. + + (-min-by '> '(4 3 6 1)) + ⇒ 1 + (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) + ⇒ (1 2 3) + (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) + ⇒ (2) + + -- Function: -max (list) + Return the largest value from LIST of numbers or markers. + + (-max '(0)) + ⇒ 0 + (-max '(3 2 1)) + ⇒ 3 + (-max '(1 2 3)) + ⇒ 3 + + -- Function: -max-by (comparator list) + Take a comparison function COMPARATOR and a LIST and return the + greatest element of the list by the comparison function. + + See also combinator ‘-on’ (*note -on::) which can transform the + values before comparing them. + + (-max-by '> '(4 3 6 1)) + ⇒ 6 + (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) + ⇒ (3 2) + (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) + ⇒ (1 2 3) + + +File: dash.info, Node: Unfolding, Next: Predicates, Prev: Reductions, Up: Functions + +2.5 Unfolding +============= + +Operations dual to reductions, building lists from a seed value rather +than consuming a list to produce a single value. + + -- Function: -iterate (fun init n) + Return a list of iterated applications of FUN to INIT. + + This means a list of the form: + + (INIT (FUN INIT) (FUN (FUN INIT)) ...) + + N is the length of the returned list. + + (-iterate #'1+ 1 10) + ⇒ (1 2 3 4 5 6 7 8 9 10) + (-iterate (lambda (x) (+ x x)) 2 5) + ⇒ (2 4 8 16 32) + (--iterate (* it it) 2 5) + ⇒ (2 4 16 256 65536) + + -- Function: -unfold (fun seed) + Build a list from SEED using FUN. + + This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while + -reduce-r consumes a list to produce a single value, ‘-unfold’ + (*note -unfold::) takes a seed value and builds a (potentially + infinite!) list. + + FUN should return ‘nil’ to stop the generating process, or a cons + (A . B), where A will be prepended to the result and B is the new + seed. + + (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10) + ⇒ (10 9 8 7 6 5 4 3 2 1) + (--unfold (when it (cons it (cdr it))) '(1 2 3 4)) + ⇒ ((1 2 3 4) (2 3 4) (3 4) (4)) + (--unfold (when it (cons it (butlast it))) '(1 2 3 4)) + ⇒ ((1 2 3 4) (1 2 3) (1 2) (1)) + + +File: dash.info, Node: Predicates, Next: Partitioning, Prev: Unfolding, Up: Functions + +2.6 Predicates +============== + +Reductions of one or more lists to a boolean value. + + -- Function: -any? (pred list) + Return t if (PRED x) is non-nil for any x in LIST, else nil. + + Alias: ‘-any-p’, ‘-some?’, ‘-some-p’ + + (-any? 'even? '(1 2 3)) + ⇒ t + (-any? 'even? '(1 3 5)) + ⇒ nil + (-any? 'null '(1 3 5)) + ⇒ nil + + -- Function: -all? (pred list) + Return t if (PRED x) is non-nil for all x in LIST, else nil. + + Alias: ‘-all-p’, ‘-every?’, ‘-every-p’ + + (-all? 'even? '(1 2 3)) + ⇒ nil + (-all? 'even? '(2 4 6)) + ⇒ t + (--all? (= 0 (% it 2)) '(2 4 6)) + ⇒ t + + -- Function: -none? (pred list) + Return t if (PRED x) is nil for all x in LIST, else nil. + + Alias: ‘-none-p’ + + (-none? 'even? '(1 2 3)) + ⇒ nil + (-none? 'even? '(1 3 5)) + ⇒ t + (--none? (= 0 (% it 2)) '(1 2 3)) + ⇒ nil + + -- Function: -only-some? (pred list) + Return ‘t‘ if at least one item of LIST matches PRED and at least + one item of LIST does not match PRED. Return ‘nil‘ both if all + items match the predicate or if none of the items match the + predicate. + + Alias: ‘-only-some-p’ + + (-only-some? 'even? '(1 2 3)) + ⇒ t + (-only-some? 'even? '(1 3 5)) + ⇒ nil + (-only-some? 'even? '(2 4 6)) + ⇒ nil + + -- Function: -contains? (list element) + Return non-nil if LIST contains ELEMENT. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that’s non-nil. + + Alias: ‘-contains-p’ + + (-contains? '(1 2 3) 1) + ⇒ t + (-contains? '(1 2 3) 2) + ⇒ t + (-contains? '(1 2 3) 4) + ⇒ nil + + -- Function: -same-items? (list list2) + Return true if LIST and LIST2 has the same items. + + The order of the elements in the lists does not matter. + + Alias: ‘-same-items-p’ + + (-same-items? '(1 2 3) '(1 2 3)) + ⇒ t + (-same-items? '(1 2 3) '(3 2 1)) + ⇒ t + (-same-items? '(1 2 3) '(1 2 3 4)) + ⇒ nil + + -- Function: -is-prefix? (prefix list) + Return non-nil if PREFIX is a prefix of LIST. + + Alias: ‘-is-prefix-p’. + + (-is-prefix? '(1 2 3) '(1 2 3 4 5)) + ⇒ t + (-is-prefix? '(1 2 3 4 5) '(1 2 3)) + ⇒ nil + (-is-prefix? '(1 3) '(1 2 3 4 5)) + ⇒ nil + + -- Function: -is-suffix? (suffix list) + Return non-nil if SUFFIX is a suffix of LIST. + + Alias: ‘-is-suffix-p’. + + (-is-suffix? '(3 4 5) '(1 2 3 4 5)) + ⇒ t + (-is-suffix? '(1 2 3 4 5) '(3 4 5)) + ⇒ nil + (-is-suffix? '(3 5) '(1 2 3 4 5)) + ⇒ nil + + -- Function: -is-infix? (infix list) + Return non-nil if INFIX is infix of LIST. + + This operation runs in O(n^2) time + + Alias: ‘-is-infix-p’ + + (-is-infix? '(1 2 3) '(1 2 3 4 5)) + ⇒ t + (-is-infix? '(2 3 4) '(1 2 3 4 5)) + ⇒ t + (-is-infix? '(3 4 5) '(1 2 3 4 5)) + ⇒ t + + -- Function: -cons-pair? (obj) + Return non-nil if OBJ is a true cons pair. That is, a cons (A . + B) where B is not a list. + + Alias: ‘-cons-pair-p’. + + (-cons-pair? '(1 . 2)) + ⇒ t + (-cons-pair? '(1 2)) + ⇒ nil + (-cons-pair? '(1)) + ⇒ nil + + +File: dash.info, Node: Partitioning, Next: Indexing, Prev: Predicates, Up: Functions + +2.7 Partitioning +================ + +Functions partitioning the input list into a list of lists. + + -- Function: -split-at (n list) + Split LIST into two sublists after the Nth element. The result is + a list of two elements (TAKE DROP) where TAKE is a new list of the + first N elements of LIST, and DROP is the remaining elements of + LIST (not a copy). TAKE and DROP are like the results of ‘-take’ + (*note -take::) and ‘-drop’ (*note -drop::), respectively, but the + split is done in a single list traversal. + + (-split-at 3 '(1 2 3 4 5)) + ⇒ ((1 2 3) (4 5)) + (-split-at 17 '(1 2 3 4 5)) + ⇒ ((1 2 3 4 5) nil) + (-split-at 0 '(1 2 3 4 5)) + ⇒ (nil (1 2 3 4 5)) + + -- Function: -split-with (pred list) + Return a list of ((-take-while PRED LIST) (-drop-while PRED LIST)), + in no more than one pass through the list. + + (-split-with 'even? '(1 2 3 4)) + ⇒ (nil (1 2 3 4)) + (-split-with 'even? '(2 4 5 6)) + ⇒ ((2 4) (5 6)) + (--split-with (< it 4) '(1 2 3 4 3 2 1)) + ⇒ ((1 2 3) (4 3 2 1)) + + -- Macro: -split-on (item list) + Split the LIST each time ITEM is found. + + Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is + discarded from the results. Empty lists are also removed from the + result. + + Comparison is done by ‘equal’. + + See also ‘-split-when’ (*note -split-when::) + + (-split-on '| '(Nil | Leaf a | Node [Tree a])) + ⇒ ((Nil) (Leaf a) (Node [Tree a])) + (-split-on ':endgroup '("a" "b" :endgroup "c" :endgroup "d" "e")) + ⇒ (("a" "b") ("c") ("d" "e")) + (-split-on ':endgroup '("a" "b" :endgroup :endgroup "d" "e")) + ⇒ (("a" "b") ("d" "e")) + + -- Function: -split-when (fn list) + Split the LIST on each element where FN returns non-nil. + + Unlike ‘-partition-by’ (*note -partition-by::), the "matched" + element is discarded from the results. Empty lists are also + removed from the result. + + This function can be thought of as a generalization of + ‘split-string’. + + (-split-when 'even? '(1 2 3 4 5 6)) + ⇒ ((1) (3) (5)) + (-split-when 'even? '(1 2 3 4 6 8 9)) + ⇒ ((1) (3) (9)) + (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args)) + ⇒ ((a b) (c d) (args)) + + -- Function: -separate (pred list) + Return a list of ((-filter PRED LIST) (-remove PRED LIST)), in one + pass through the list. + + (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7)) + ⇒ ((2 4 6) (1 3 5 7)) + (--separate (< it 5) '(3 7 5 9 3 2 1 4 6)) + ⇒ ((3 3 2 1 4) (7 5 9 6)) + (-separate 'cdr '((1 2) (1) (1 2 3) (4))) + ⇒ (((1 2) (1 2 3)) ((1) (4))) + + -- Function: -partition (n list) + Return a new list with the items in LIST grouped into N-sized + sublists. If there are not enough items to make the last group + N-sized, those items are discarded. + + (-partition 2 '(1 2 3 4 5 6)) + ⇒ ((1 2) (3 4) (5 6)) + (-partition 2 '(1 2 3 4 5 6 7)) + ⇒ ((1 2) (3 4) (5 6)) + (-partition 3 '(1 2 3 4 5 6 7)) + ⇒ ((1 2 3) (4 5 6)) + + -- Function: -partition-all (n list) + Return a new list with the items in LIST grouped into N-sized + sublists. The last group may contain less than N items. + + (-partition-all 2 '(1 2 3 4 5 6)) + ⇒ ((1 2) (3 4) (5 6)) + (-partition-all 2 '(1 2 3 4 5 6 7)) + ⇒ ((1 2) (3 4) (5 6) (7)) + (-partition-all 3 '(1 2 3 4 5 6 7)) + ⇒ ((1 2 3) (4 5 6) (7)) + + -- Function: -partition-in-steps (n step list) + Return a new list with the items in LIST grouped into N-sized + sublists at offsets STEP apart. If there are not enough items to + make the last group N-sized, those items are discarded. + + (-partition-in-steps 2 1 '(1 2 3 4)) + ⇒ ((1 2) (2 3) (3 4)) + (-partition-in-steps 3 2 '(1 2 3 4)) + ⇒ ((1 2 3)) + (-partition-in-steps 3 2 '(1 2 3 4 5)) + ⇒ ((1 2 3) (3 4 5)) + + -- Function: -partition-all-in-steps (n step list) + Return a new list with the items in LIST grouped into N-sized + sublists at offsets STEP apart. The last groups may contain less + than N items. + + (-partition-all-in-steps 2 1 '(1 2 3 4)) + ⇒ ((1 2) (2 3) (3 4) (4)) + (-partition-all-in-steps 3 2 '(1 2 3 4)) + ⇒ ((1 2 3) (3 4)) + (-partition-all-in-steps 3 2 '(1 2 3 4 5)) + ⇒ ((1 2 3) (3 4 5) (5)) + + -- Function: -partition-by (fn list) + Apply FN to each item in LIST, splitting it each time FN returns a + new value. + + (-partition-by 'even? ()) + ⇒ () + (-partition-by 'even? '(1 1 2 2 2 3 4 6 8)) + ⇒ ((1 1) (2 2 2) (3) (4 6 8)) + (--partition-by (< it 3) '(1 2 3 4 3 2 1)) + ⇒ ((1 2) (3 4 3) (2 1)) + + -- Function: -partition-by-header (fn list) + Apply FN to the first item in LIST. That is the header value. + Apply FN to each item in LIST, splitting it each time FN returns + the header value, but only after seeing at least one other value + (the body). + + (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4)) + ⇒ ((1 2 3) (1 2) (1 2 3 4)) + (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0)) + ⇒ ((1 2 0) (1 0) (1 2 3 0)) + (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1)) + ⇒ ((2 1 1 1) (4 1 3 5) (6 6 1)) + + -- Function: -partition-after-pred (pred list) + Partition directly after each time PRED is true on an element of + LIST. + + (-partition-after-pred #'booleanp ()) + ⇒ () + (-partition-after-pred #'booleanp '(t t)) + ⇒ ((t) (t)) + (-partition-after-pred #'booleanp '(0 0 t t 0 t)) + ⇒ ((0 0 t) (t) (0 t)) + + -- Function: -partition-before-pred (pred list) + Partition directly before each time PRED is true on an element of + LIST. + + (-partition-before-pred #'booleanp ()) + ⇒ () + (-partition-before-pred #'booleanp '(0 t)) + ⇒ ((0) (t)) + (-partition-before-pred #'booleanp '(0 0 t 0 t t)) + ⇒ ((0 0) (t 0) (t) (t)) + + -- Function: -partition-before-item (item list) + Partition directly before each time ITEM appears in LIST. + + (-partition-before-item 3 ()) + ⇒ () + (-partition-before-item 3 '(1)) + ⇒ ((1)) + (-partition-before-item 3 '(3)) + ⇒ ((3)) + + -- Function: -partition-after-item (item list) + Partition directly after each time ITEM appears in LIST. + + (-partition-after-item 3 ()) + ⇒ () + (-partition-after-item 3 '(1)) + ⇒ ((1)) + (-partition-after-item 3 '(3)) + ⇒ ((3)) + + -- Function: -group-by (fn list) + Separate LIST into an alist whose keys are FN applied to the + elements of LIST. Keys are compared by ‘equal’. + + (-group-by 'even? ()) + ⇒ () + (-group-by 'even? '(1 1 2 2 2 3 4 6 8)) + ⇒ ((nil 1 1 3) (t 2 2 2 4 6 8)) + (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) + ⇒ (("a" "a/b" "a/e") ("c" "c/d")) + + +File: dash.info, Node: Indexing, Next: Set operations, Prev: Partitioning, Up: Functions + +2.8 Indexing +============ + +Functions retrieving or sorting based on list indices and related +predicates. + + -- Function: -elem-index (elem list) + Return the index of the first element in the given LIST which is + equal to the query element ELEM, or nil if there is no such + element. + + (-elem-index 2 '(6 7 8 2 3 4)) + ⇒ 3 + (-elem-index "bar" '("foo" "bar" "baz")) + ⇒ 1 + (-elem-index '(1 2) '((3) (5 6) (1 2) nil)) + ⇒ 2 + + -- Function: -elem-indices (elem list) + Return the indices of all elements in LIST equal to the query + element ELEM, in ascending order. + + (-elem-indices 2 '(6 7 8 2 3 4 2 1)) + ⇒ (3 6) + (-elem-indices "bar" '("foo" "bar" "baz")) + ⇒ (1) + (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) + ⇒ (1 3) + + -- Function: -find-index (pred list) + Take a predicate PRED and a LIST and return the index of the first + element in the list satisfying the predicate, or nil if there is no + such element. + + See also ‘-first’ (*note -first::). + + (-find-index 'even? '(2 4 1 6 3 3 5 8)) + ⇒ 0 + (--find-index (< 5 it) '(2 4 1 6 3 3 5 8)) + ⇒ 3 + (-find-index (-partial 'string-lessp "baz") '("bar" "foo" "baz")) + ⇒ 1 + + -- Function: -find-last-index (pred list) + Take a predicate PRED and a LIST and return the index of the last + element in the list satisfying the predicate, or nil if there is no + such element. + + See also ‘-last’ (*note -last::). + + (-find-last-index 'even? '(2 4 1 6 3 3 5 8)) + ⇒ 7 + (--find-last-index (< 5 it) '(2 7 1 6 3 8 5 2)) + ⇒ 5 + (-find-last-index (-partial 'string-lessp "baz") '("q" "foo" "baz")) + ⇒ 1 + + -- Function: -find-indices (pred list) + Return the indices of all elements in LIST satisfying the predicate + PRED, in ascending order. + + (-find-indices 'even? '(2 4 1 6 3 3 5 8)) + ⇒ (0 1 3 7) + (--find-indices (< 5 it) '(2 4 1 6 3 3 5 8)) + ⇒ (3 7) + (-find-indices (-partial 'string-lessp "baz") '("bar" "foo" "baz")) + ⇒ (1) + + -- Function: -grade-up (comparator list) + Grade elements of LIST using COMPARATOR relation. This yields a + permutation vector such that applying this permutation to LIST + sorts it in ascending order. + + (-grade-up #'< '(3 1 4 2 1 3 3)) + ⇒ (1 4 3 0 5 6 2) + (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up #'< l) l)) + ⇒ (1 1 2 3 3 3 4) + + -- Function: -grade-down (comparator list) + Grade elements of LIST using COMPARATOR relation. This yields a + permutation vector such that applying this permutation to LIST + sorts it in descending order. + + (-grade-down #'< '(3 1 4 2 1 3 3)) + ⇒ (2 0 5 6 3 1 4) + (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down #'< l) l)) + ⇒ (4 3 3 3 2 1 1) + + +File: dash.info, Node: Set operations, Next: Other list operations, Prev: Indexing, Up: Functions + +2.9 Set operations +================== + +Operations pretending lists are sets. + + -- Function: -union (list list2) + Return a new list containing the elements of LIST and elements of + LIST2 that are not in LIST. The test for equality is done with + ‘equal’, or with ‘-compare-fn’ if that’s non-nil. + + (-union '(1 2 3) '(3 4 5)) + ⇒ (1 2 3 4 5) + (-union '(1 2 3 4) ()) + ⇒ (1 2 3 4) + (-union '(1 1 2 2) '(3 2 1)) + ⇒ (1 1 2 2 3) + + -- Function: -difference (list list2) + Return a new list with only the members of LIST that are not in + LIST2. The test for equality is done with ‘equal’, or with + ‘-compare-fn’ if that’s non-nil. + + (-difference () ()) + ⇒ () + (-difference '(1 2 3) '(4 5 6)) + ⇒ (1 2 3) + (-difference '(1 2 3 4) '(3 4 5 6)) + ⇒ (1 2) + + -- Function: -intersection (list list2) + Return a new list containing only the elements that are members of + both LIST and LIST2. The test for equality is done with ‘equal’, + or with ‘-compare-fn’ if that’s non-nil. + + (-intersection () ()) + ⇒ () + (-intersection '(1 2 3) '(4 5 6)) + ⇒ () + (-intersection '(1 2 3 4) '(3 4 5 6)) + ⇒ (3 4) + + -- Function: -powerset (list) + Return the power set of LIST. + + (-powerset ()) + ⇒ (nil) + (-powerset '(x y z)) + ⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil) + + -- Function: -permutations (list) + Return the permutations of LIST. + + (-permutations ()) + ⇒ (nil) + (-permutations '(1 2)) + ⇒ ((1 2) (2 1)) + (-permutations '(a b c)) + ⇒ ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a)) + + -- Function: -distinct (list) + Return a new list with all duplicates removed. The test for + equality is done with ‘equal’, or with ‘-compare-fn’ if that’s + non-nil. + + Alias: ‘-uniq’ + + (-distinct ()) + ⇒ () + (-distinct '(1 2 2 4)) + ⇒ (1 2 4) + (-distinct '(t t t)) + ⇒ (t) + + +File: dash.info, Node: Other list operations, Next: Tree operations, Prev: Set operations, Up: Functions + +2.10 Other list operations +========================== + +Other list functions not fit to be classified elsewhere. + + -- Function: -rotate (n list) + Rotate LIST N places to the right. With N negative, rotate to the + left. The time complexity is O(n). + + (-rotate 3 '(1 2 3 4 5 6 7)) + ⇒ (5 6 7 1 2 3 4) + (-rotate -3 '(1 2 3 4 5 6 7)) + ⇒ (4 5 6 7 1 2 3) + (-rotate 16 '(1 2 3 4 5 6 7)) + ⇒ (6 7 1 2 3 4 5) + + -- Function: -repeat (n x) + Return a new list of length N with each element being X. Return + nil if N is less than 1. + + (-repeat 3 :a) + ⇒ (:a :a :a) + (-repeat 1 :a) + ⇒ (:a) + (-repeat 0 :a) + ⇒ nil + + -- Function: -cons* (&rest args) + Make a new list from the elements of ARGS. The last 2 elements of + ARGS are used as the final cons of the result, so if the final + element of ARGS is not a list, the result is a dotted list. With + no ARGS, return nil. + + (-cons* 1 2) + ⇒ (1 . 2) + (-cons* 1 2 3) + ⇒ (1 2 . 3) + (-cons* 1) + ⇒ 1 + + -- Function: -snoc (list elem &rest elements) + Append ELEM to the end of the list. + + This is like ‘cons’, but operates on the end of list. + + If ELEMENTS is non nil, append these to the list as well. + + (-snoc '(1 2 3) 4) + ⇒ (1 2 3 4) + (-snoc '(1 2 3) 4 5 6) + ⇒ (1 2 3 4 5 6) + (-snoc '(1 2 3) '(4 5 6)) + ⇒ (1 2 3 (4 5 6)) + + -- Function: -interpose (sep list) + Return a new list of all elements in LIST separated by SEP. + + (-interpose "-" ()) + ⇒ () + (-interpose "-" '("a")) + ⇒ ("a") + (-interpose "-" '("a" "b" "c")) + ⇒ ("a" "-" "b" "-" "c") + + -- Function: -interleave (&rest lists) + Return a new list of the first item in each list, then the second + etc. + + (-interleave '(1 2) '("a" "b")) + ⇒ (1 "a" 2 "b") + (-interleave '(1 2) '("a" "b") '("A" "B")) + ⇒ (1 "a" "A" 2 "b" "B") + (-interleave '(1 2 3) '("a" "b")) + ⇒ (1 "a" 2 "b") + + -- Function: -iota (count &optional start step) + Return a list containing COUNT numbers. Starts from START and adds + STEP each time. The default START is zero, the default STEP is 1. + This function takes its name from the corresponding primitive in + the APL language. + + (-iota 6) + ⇒ (0 1 2 3 4 5) + (-iota 4 2.5 -2) + ⇒ (2.5 0.5 -1.5 -3.5) + (-iota -1) + error→ Wrong type argument: natnump, -1 + + -- Function: -zip-with (fn list1 list2) + Zip the two lists LIST1 and LIST2 using a function FN. This + function is applied pairwise taking as first argument element of + LIST1 and as second argument element of LIST2 at corresponding + position. + + The anaphoric form ‘--zip-with’ binds the elements from LIST1 as + symbol ‘it’, and the elements from LIST2 as symbol ‘other’. + + (-zip-with '+ '(1 2 3) '(4 5 6)) + ⇒ (5 7 9) + (-zip-with 'cons '(1 2 3) '(4 5 6)) + ⇒ ((1 . 4) (2 . 5) (3 . 6)) + (--zip-with (concat it " and " other) '("Batman" "Jekyll") '("Robin" "Hyde")) + ⇒ ("Batman and Robin" "Jekyll and Hyde") + + -- Function: -zip (&rest lists) + Zip LISTS together. Group the head of each list, followed by the + second elements of each list, and so on. The lengths of the + returned groupings are equal to the length of the shortest input + list. + + If two lists are provided as arguments, return the groupings as a + list of cons cells. Otherwise, return the groupings as a list of + lists. + + Use ‘-zip-lists’ (*note -zip-lists::) if you need the return value + to always be a list of lists. + + Alias: ‘-zip-pair’ + + See also: ‘-zip-lists’ (*note -zip-lists::) + + (-zip '(1 2 3) '(4 5 6)) + ⇒ ((1 . 4) (2 . 5) (3 . 6)) + (-zip '(1 2 3) '(4 5 6 7)) + ⇒ ((1 . 4) (2 . 5) (3 . 6)) + (-zip '(1 2) '(3 4 5) '(6)) + ⇒ ((1 3 6)) + + -- Function: -zip-lists (&rest lists) + Zip LISTS together. Group the head of each list, followed by the + second elements of each list, and so on. The lengths of the + returned groupings are equal to the length of the shortest input + list. + + The return value is always list of lists, which is a difference + from ‘-zip-pair’ which returns a cons-cell in case two input lists + are provided. + + See also: ‘-zip’ (*note -zip::) + + (-zip-lists '(1 2 3) '(4 5 6)) + ⇒ ((1 4) (2 5) (3 6)) + (-zip-lists '(1 2 3) '(4 5 6 7)) + ⇒ ((1 4) (2 5) (3 6)) + (-zip-lists '(1 2) '(3 4 5) '(6)) + ⇒ ((1 3 6)) + + -- Function: -zip-fill (fill-value &rest lists) + Zip LISTS, with FILL-VALUE padded onto the shorter lists. The + lengths of the returned groupings are equal to the length of the + longest input list. + + (-zip-fill 0 '(1 2 3 4 5) '(6 7 8 9)) + ⇒ ((1 . 6) (2 . 7) (3 . 8) (4 . 9) (5 . 0)) + + -- Function: -unzip (lists) + Unzip LISTS. + + This works just like ‘-zip’ (*note -zip::) but takes a list of + lists instead of a variable number of arguments, such that + + (-unzip (-zip L1 L2 L3 ...)) + + is identity (given that the lists are the same length). + + Note in particular that calling this on a list of two lists will + return a list of cons-cells such that the above identity works. + + See also: ‘-zip’ (*note -zip::) + + (-unzip (-zip '(1 2 3) '(a b c) '("e" "f" "g"))) + ⇒ ((1 2 3) (a b c) ("e" "f" "g")) + (-unzip '((1 2) (3 4) (5 6) (7 8) (9 10))) + ⇒ ((1 3 5 7 9) (2 4 6 8 10)) + (-unzip '((1 2) (3 4))) + ⇒ ((1 . 3) (2 . 4)) + + -- Function: -cycle (list) + Return an infinite circular copy of LIST. The returned list cycles + through the elements of LIST and repeats from the beginning. + + (-take 5 (-cycle '(1 2 3))) + ⇒ (1 2 3 1 2) + (-take 7 (-cycle '(1 "and" 3))) + ⇒ (1 "and" 3 1 "and" 3 1) + (-zip (-cycle '(1 2 3)) '(1 2)) + ⇒ ((1 . 1) (2 . 2)) + + -- Function: -pad (fill-value &rest lists) + Appends FILL-VALUE to the end of each list in LISTS such that they + will all have the same length. + + (-pad 0 ()) + ⇒ (nil) + (-pad 0 '(1)) + ⇒ ((1)) + (-pad 0 '(1 2 3) '(4 5)) + ⇒ ((1 2 3) (4 5 0)) + + -- Function: -table (fn &rest lists) + Compute outer product of LISTS using function FN. + + The function FN should have the same arity as the number of + supplied lists. + + The outer product is computed by applying fn to all possible + combinations created by taking one element from each list in order. + The dimension of the result is (length lists). + + See also: ‘-table-flat’ (*note -table-flat::) + + (-table '* '(1 2 3) '(1 2 3)) + ⇒ ((1 2 3) (2 4 6) (3 6 9)) + (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4))) + ⇒ ((7 15) (10 22)) + (apply '-table 'list (-repeat 3 '(1 2))) + ⇒ ((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2)))) + + -- Function: -table-flat (fn &rest lists) + Compute flat outer product of LISTS using function FN. + + The function FN should have the same arity as the number of + supplied lists. + + The outer product is computed by applying fn to all possible + combinations created by taking one element from each list in order. + The results are flattened, ignoring the tensor structure of the + result. This is equivalent to calling: + + (-flatten-n (1- (length lists)) (apply ’-table fn lists)) + + but the implementation here is much more efficient. + + See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note + -table::) + + (-table-flat 'list '(1 2 3) '(a b c)) + ⇒ ((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c)) + (-table-flat '* '(1 2 3) '(1 2 3)) + ⇒ (1 2 3 2 4 6 3 6 9) + (apply '-table-flat 'list (-repeat 3 '(1 2))) + ⇒ ((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2)) + + -- Function: -first (pred list) + Return the first item in LIST for which PRED returns non-nil. + Return nil if no such element is found. To get the first item in + the list no questions asked, use ‘car’. + + Alias: ‘-find’. + + This function’s anaphoric counterpart is ‘--first’. + + (-first #'natnump '(-1 0 1)) + ⇒ 0 + (-first #'null '(1 2 3)) + ⇒ nil + (--first (> it 2) '(1 2 3)) + ⇒ 3 + + -- Function: -some (pred list) + Return (PRED x) for the first LIST item where (PRED x) is non-nil, + else nil. + + Alias: ‘-any’. + + This function’s anaphoric counterpart is ‘--some’. + + (-some (lambda (s) (string-match-p "x" s)) '("foo" "axe" "xor")) + ⇒ 1 + (-some (lambda (s) (string-match-p "x" s)) '("foo" "bar" "baz")) + ⇒ nil + (--some (member 'foo it) '((foo bar) (baz))) + ⇒ (foo bar) + + -- Function: -last (pred list) + Return the last x in LIST where (PRED x) is non-nil, else nil. + + (-last 'even? '(1 2 3 4 5 6 3 3 3)) + ⇒ 6 + (-last 'even? '(1 3 7 5 9)) + ⇒ nil + (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one")) + ⇒ "short" + + -- Function: -first-item (list) + Return the first item of LIST, or nil on an empty list. + + See also: ‘-second-item’ (*note -second-item::), ‘-last-item’ + (*note -last-item::). + + (-first-item '(1 2 3)) + ⇒ 1 + (-first-item nil) + ⇒ nil + (let ((list (list 1 2 3))) (setf (-first-item list) 5) list) + ⇒ (5 2 3) + + -- Function: -second-item (list) + Return the second item of LIST, or nil if LIST is too short. + + See also: ‘-third-item’ (*note -third-item::). + + (-second-item '(1 2 3)) + ⇒ 2 + (-second-item nil) + ⇒ nil + + -- Function: -third-item (list) + Return the third item of LIST, or nil if LIST is too short. + + See also: ‘-fourth-item’ (*note -fourth-item::). + + (-third-item '(1 2 3)) + ⇒ 3 + (-third-item nil) + ⇒ nil + + -- Function: -fourth-item (list) + Return the fourth item of LIST, or nil if LIST is too short. + + See also: ‘-fifth-item’ (*note -fifth-item::). + + (-fourth-item '(1 2 3 4)) + ⇒ 4 + (-fourth-item nil) + ⇒ nil + + -- Function: -fifth-item (list) + Return the fifth item of LIST, or nil if LIST is too short. + + See also: ‘-last-item’ (*note -last-item::). + + (-fifth-item '(1 2 3 4 5)) + ⇒ 5 + (-fifth-item nil) + ⇒ nil + + -- Function: -last-item (list) + Return the last item of LIST, or nil on an empty list. + + (-last-item '(1 2 3)) + ⇒ 3 + (-last-item nil) + ⇒ nil + (let ((list (list 1 2 3))) (setf (-last-item list) 5) list) + ⇒ (1 2 5) + + -- Function: -butlast (list) + Return a list of all items in list except for the last. + + (-butlast '(1 2 3)) + ⇒ (1 2) + (-butlast '(1 2)) + ⇒ (1) + (-butlast '(1)) + ⇒ nil + + -- Function: -sort (comparator list) + Sort LIST, stably, comparing elements using COMPARATOR. Return the + sorted list. LIST is NOT modified by side effects. COMPARATOR is + called with two elements of LIST, and should return non-nil if the + first element should sort before the second. + + (-sort '< '(3 1 2)) + ⇒ (1 2 3) + (-sort '> '(3 1 2)) + ⇒ (3 2 1) + (--sort (< it other) '(3 1 2)) + ⇒ (1 2 3) + + -- Function: -list (arg) + Ensure ARG is a list. If ARG is already a list, return it as is + (not a copy). Otherwise, return a new list with ARG as its only + element. + + Another supported calling convention is (-list &rest ARGS). In + this case, if ARG is not a list, a new list with all of ARGS as + elements is returned. This use is supported for backward + compatibility and is otherwise deprecated. + + (-list 1) + ⇒ (1) + (-list ()) + ⇒ () + (-list '(1 2 3)) + ⇒ (1 2 3) + + -- Function: -fix (fn list) + Compute the (least) fixpoint of FN with initial input LIST. + + FN is called at least once, results are compared with ‘equal’. + + (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3))) + ⇒ ((1) (2) (3)) + (let ((l '((starwars scifi) (jedi starwars warrior)))) (--fix (-uniq (--mapcat (cons it (cdr (assq it l))) it)) '(jedi book))) + ⇒ (jedi starwars warrior scifi book) + + +File: dash.info, Node: Tree operations, Next: Threading macros, Prev: Other list operations, Up: Functions + +2.11 Tree operations +==================== + +Functions pretending lists are trees. + + -- Function: -tree-seq (branch children tree) + Return a sequence of the nodes in TREE, in depth-first search + order. + + BRANCH is a predicate of one argument that returns non-nil if the + passed argument is a branch, that is, a node that can have + children. + + CHILDREN is a function of one argument that returns the children of + the passed branch node. + + Non-branch nodes are simply copied. + + (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7)))) + ⇒ ((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7) + (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7)))) + ⇒ ((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1) + (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]]) + ⇒ ([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7) + + -- Function: -tree-map (fn tree) + Apply FN to each element of TREE while preserving the tree + structure. + + (-tree-map '1+ '(1 (2 3) (4 (5 6) 7))) + ⇒ (2 (3 4) (5 (6 7) 8)) + (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4)) + ⇒ ((1 . 2) ((2 . 4) (3 . 8)) (4 . 16)) + (--tree-map (length it) '("" ("

" "text" "

") "")) + ⇒ (6 (3 4 4) 7) + + -- Function: -tree-map-nodes (pred fun tree) + Call FUN on each node of TREE that satisfies PRED. + + If PRED returns nil, continue descending down this node. If PRED + returns non-nil, apply FUN to this node and do not descend further. + + (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8))) + ⇒ (1 5 4 (5 13 8)) + (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8))) + ⇒ (1 ":foo" 4 ((5 6 ":bar") ":baz" 8)) + (--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d)))) + ⇒ (with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode))) + + -- Function: -tree-reduce (fn tree) + Use FN to reduce elements of list TREE. If elements of TREE are + lists themselves, apply the reduction recursively. + + FN is first applied to first element of the list and second + element, then on this result and third element from the list etc. + + See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of + zero or one element handled. + + (-tree-reduce '+ '(1 (2 3) (4 5))) + ⇒ 15 + (-tree-reduce 'concat '("strings" (" on" " various") ((" levels")))) + ⇒ "strings on various levels" + (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "")))) '(body (p "some words") (div "more" (b "bold") "words"))) + ⇒ "

some words

more bold words
" + + -- Function: -tree-reduce-from (fn init-value tree) + Use FN to reduce elements of list TREE. If elements of TREE are + lists themselves, apply the reduction recursively. + + FN is first applied to INIT-VALUE and first element of the list, + then on this result and second element from the list etc. + + The initial value is ignored on cons pairs as they always contain + two elements. + + (-tree-reduce-from '+ 1 '(1 (1 1) ((1)))) + ⇒ 8 + (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7))) + ⇒ ((7 6) ((5 4) 3 2) 1) + + -- Function: -tree-mapreduce (fn folder tree) + Apply FN to each element of TREE, and make a list of the results. + If elements of TREE are lists themselves, apply FN recursively to + elements of these nested lists. + + Then reduce the resulting lists using FOLDER and initial value + INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). + + This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::) + after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it + only traverse the structure once. + + (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9)))) + ⇒ (1 2 3 4 5 6 7 8 9) + (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3)))) + ⇒ 9 + (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3)))) + ⇒ 3 + + -- Function: -tree-mapreduce-from (fn folder init-value tree) + Apply FN to each element of TREE, and make a list of the results. + If elements of TREE are lists themselves, apply FN recursively to + elements of these nested lists. + + Then reduce the resulting lists using FOLDER and initial value + INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). + + This is the same as calling ‘-tree-reduce-from’ (*note + -tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is + twice as fast as it only traverse the structure once. + + (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9)))) + ⇒ 362880 + (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3)))) + ⇒ (2 (4 (8 18) (4 2)) (14 (8 6))) + (concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elisp-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam))))) + ⇒ "{elisp-mode : {foo : {bar -> booze}, baz -> qux}, c-mode : {foo -> bla, bum -> bam}}" + + -- Function: -clone (list) + Create a deep copy of LIST. The new list has the same elements and + structure but all cons are replaced with new ones. This is useful + when you need to clone a structure such as plist or alist. + + (let* ((a '(1 2 3)) (b (-clone a))) (nreverse a) b) + ⇒ (1 2 3) + + +File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations, Up: Functions + +2.12 Threading macros +===================== + +Macros that conditionally combine sequential forms for brevity or +readability. + + -- Macro: -> (x &optional form &rest more) + Thread the expr through the forms. Insert X as the second item in + the first form, making a list of it if it is not a list already. + If there are more forms, insert the first form as the second item + in second form, etc. + + (-> '(2 3 5)) + ⇒ (2 3 5) + (-> '(2 3 5) (append '(8 13))) + ⇒ (2 3 5 8 13) + (-> '(2 3 5) (append '(8 13)) (-slice 1 -1)) + ⇒ (3 5 8) + + -- Macro: ->> (x &optional form &rest more) + Thread the expr through the forms. Insert X as the last item in + the first form, making a list of it if it is not a list already. + If there are more forms, insert the first form as the last item in + second form, etc. + + (->> '(1 2 3) (-map 'square)) + ⇒ (1 4 9) + (->> '(1 2 3) (-map 'square) (-remove 'even?)) + ⇒ (1 9) + (->> '(1 2 3) (-map 'square) (-reduce '+)) + ⇒ 14 + + -- Macro: --> (x &rest forms) + Starting with the value of X, thread each expression through FORMS. + + Insert X at the position signified by the symbol ‘it’ in the first + form. If there are more forms, insert the first form at the + position signified by ‘it’ in in second form, etc. + + (--> "def" (concat "abc" it "ghi")) + ⇒ "abcdefghi" + (--> "def" (concat "abc" it "ghi") (upcase it)) + ⇒ "ABCDEFGHI" + (--> "def" (concat "abc" it "ghi") upcase) + ⇒ "ABCDEFGHI" + + -- Macro: -as-> (value variable &rest forms) + Starting with VALUE, thread VARIABLE through FORMS. + + In the first form, bind VARIABLE to VALUE. In the second form, + bind VARIABLE to the result of the first form, and so forth. + + (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var)) + ⇒ (8) + (-as-> 3 my-var 1+) + ⇒ 4 + (-as-> 3 my-var) + ⇒ 3 + + -- Macro: -some-> (x &optional form &rest more) + When expr is non-nil, thread it through the first form (via ‘->’ + (*note ->::)), and when that result is non-nil, through the next + form, etc. + + (-some-> '(2 3 5)) + ⇒ (2 3 5) + (-some-> 5 square) + ⇒ 25 + (-some-> 5 even? square) + ⇒ nil + + -- Macro: -some->> (x &optional form &rest more) + When expr is non-nil, thread it through the first form (via ‘->>’ + (*note ->>::)), and when that result is non-nil, through the next + form, etc. + + (-some->> '(1 2 3) (-map 'square)) + ⇒ (1 4 9) + (-some->> '(1 3 5) (-last 'even?) (+ 100)) + ⇒ nil + (-some->> '(2 4 6) (-last 'even?) (+ 100)) + ⇒ 106 + + -- Macro: -some--> (expr &rest forms) + Thread EXPR through FORMS via ‘-->’ (*note -->::), while the result + is non-nil. When EXPR evaluates to non-nil, thread the result + through the first of FORMS, and when that result is non-nil, thread + it through the next form, etc. + + (-some--> "def" (concat "abc" it "ghi")) + ⇒ "abcdefghi" + (-some--> nil (concat "abc" it "ghi")) + ⇒ nil + (-some--> '(0 1) (-remove #'natnump it) (append it it) (-map #'1+ it)) + ⇒ () + + -- Macro: -doto (init &rest forms) + Evaluate INIT and pass it as argument to FORMS with ‘->’ (*note + ->::). The RESULT of evaluating INIT is threaded through each of + FORMS individually using ‘->’ (*note ->::), which see. The return + value is RESULT, which FORMS may have modified by side effect. + + (-doto (list 1 2 3) pop pop) + ⇒ (3) + (-doto (cons 1 2) (setcar 3) (setcdr 4)) + ⇒ (3 . 4) + (gethash 'k (--doto (make-hash-table) (puthash 'k 'v it))) + ⇒ v + + +File: dash.info, Node: Binding, Next: Side effects, Prev: Threading macros, Up: Functions + +2.13 Binding +============ + +Macros that combine ‘let’ and ‘let*’ with destructuring and flow +control. + + -- Macro: -when-let ((var val) &rest body) + If VAL evaluates to non-nil, bind it to VAR and execute body. + + Note: binding is done according to ‘-let’ (*note -let::). + + (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2)) + ⇒ 5 + (-when-let ((&plist :foo foo) (list :foo "foo")) foo) + ⇒ "foo" + (-when-let ((&plist :foo foo) (list :bar "bar")) foo) + ⇒ nil + + -- Macro: -when-let* (vars-vals &rest body) + If all VALS evaluate to true, bind them to their corresponding VARS + and execute body. VARS-VALS should be a list of (VAR VAL) pairs. + + Note: binding is done according to ‘-let*’ (*note -let*::). VALS + are evaluated sequentially, and evaluation stops after the first + nil VAL is encountered. + + (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z)) + ⇒ 15 + (-when-let* ((x 5) (y nil) (z 7)) (+ x y z)) + ⇒ nil + + -- Macro: -if-let ((var val) then &rest else) + If VAL evaluates to non-nil, bind it to VAR and do THEN, otherwise + do ELSE. + + Note: binding is done according to ‘-let’ (*note -let::). + + (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7) + ⇒ 7 + (--if-let (even? 4) it nil) + ⇒ t + + -- Macro: -if-let* (vars-vals then &rest else) + If all VALS evaluate to true, bind them to their corresponding VARS + and do THEN, otherwise do ELSE. VARS-VALS should be a list of (VAR + VAL) pairs. + + Note: binding is done according to ‘-let*’ (*note -let*::). VALS + are evaluated sequentially, and evaluation stops after the first + nil VAL is encountered. + + (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo") + ⇒ 15 + (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo") + ⇒ "foo" + (-if-let* (((_ _ x) '(nil nil 7))) x) + ⇒ 7 + + -- Macro: -let (varlist &rest body) + Bind variables according to VARLIST then eval BODY. + + VARLIST is a list of lists of the form (PATTERN SOURCE). Each + PATTERN is matched against the SOURCE "structurally". SOURCE is + only evaluated once for each PATTERN. Each PATTERN is matched + recursively, and can therefore contain sub-patterns which are + matched against corresponding sub-expressions of SOURCE. + + All the SOURCEs are evalled before any symbols are bound (i.e. "in + parallel"). + + If VARLIST only contains one (PATTERN SOURCE) element, you can + optionally specify it using a vector and discarding the outer-most + parens. Thus + + (-let ((PATTERN SOURCE)) ...) + + becomes + + (-let [PATTERN SOURCE] ...). + + ‘-let’ (*note -let::) uses a convention of not binding places + (symbols) starting with _ whenever it’s possible. You can use this + to skip over entries you don’t care about. However, this is not + *always* possible (as a result of implementation) and these symbols + might get bound to undefined values. + + Following is the overview of supported patterns. Remember that + patterns can be matched recursively, so every a, b, aK in the + following can be a matching construct and not necessarily a + symbol/variable. + + Symbol: + + a - bind the SOURCE to A. This is just like regular ‘let’. + + Conses and lists: + + (a) - bind ‘car’ of cons/list to A + + (a . b) - bind car of cons to A and ‘cdr’ to B + + (a b) - bind car of list to A and ‘cadr’ to B + + (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to + A3... + + (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST. + + Vectors: + + [a] - bind 0th element of a non-list sequence to A (works with + vectors, strings, bit arrays...) + + [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st + to A1, 2nd to A2, ... If the PATTERN is shorter than SOURCE, the + values at places not in PATTERN are ignored. If the PATTERN is + longer than SOURCE, an ‘error’ is thrown. + + [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the + sequence to REST. This is conceptually the same as improper list + matching (a1 a2 ... aN . rest) + + Key/value stores: + + (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the + SOURCE plist to aK. If the value is not found, aK is nil. Uses + ‘plist-get’ to fetch values. + + (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the + SOURCE alist to aK. If the value is not found, aK is nil. Uses + ‘assoc’ to fetch values. + + (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the + SOURCE hash table to aK. If the value is not found, aK is nil. + Uses ‘gethash’ to fetch values. + + Further, special keyword &keys supports "inline" matching of + plist-like key-value pairs, similarly to &keys keyword of + ‘cl-defun’. + + (a1 a2 ... aN &keys key1 b1 ... keyN bK) + + This binds N values from the list to a1 ... aN, then interprets the + cdr as a plist (see key/value matching above). + + A shorthand notation for kv-destructuring exists which allows the + patterns be optionally left out and derived from the key name in + the following fashion: + + - a key :foo is converted into ‘foo’ pattern, - a key ’bar is + converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’ + pattern. + + That is, the entire value under the key is bound to the derived + variable without any further destructuring. + + This is possible only when the form following the key is not a + valid pattern (i.e. not a symbol, a cons cell or a vector). + Otherwise the matching proceeds as usual and in case of an invalid + spec fails with an error. + + Thus the patterns are normalized as follows: + + ;; derive all the missing patterns (&plist :foo ’bar "baz") => + (&plist :foo foo ’bar bar "baz" baz) + + ;; we can specify some but not others (&plist :foo ’bar + explicit-bar) => (&plist :foo foo ’bar explicit-bar) + + ;; nothing happens, we store :foo in x (&plist :foo x) => (&plist + :foo x) + + ;; nothing happens, we match recursively (&plist :foo (a b c)) => + (&plist :foo (a b c)) + + You can name the source using the syntax SYMBOL &as PATTERN. This + syntax works with lists (proper or improper), vectors and all types + of maps. + + (list &as a b c) (list 1 2 3) + + binds A to 1, B to 2, C to 3 and LIST to (1 2 3). + + Similarly: + + (bounds &as beg . end) (cons 1 2) + + binds BEG to 1, END to 2 and BOUNDS to (1 . 2). + + (items &as first . rest) (list 1 2 3) + + binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3) + + [vect &as _ b c] [1 2 3] + + binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as + usual). + + (plist &as &plist :b b) (list :a 1 :b 2 :c 3) + + binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and + &hash. + + This is especially useful when we want to capture the result of a + computation and destructure at the same time. Consider the form + (function-returning-complex-structure) returning a list of two + vectors with two items each. We want to capture this entire result + and pass it to another computation, but at the same time we want to + get the second item from each vector. We can achieve it with + pattern + + (result &as [_ a] [_ b]) (function-returning-complex-structure) + + Note: Clojure programmers may know this feature as the ":as + binding". The difference is that we put the &as at the front + because we need to support improper list binding. + + (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d)) + ⇒ (1 2 3 4) + (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d)) + ⇒ (1 2 3 (4 5 6)) + (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar)) + ⇒ (1 2) + + -- Macro: -let* (varlist &rest body) + Bind variables according to VARLIST then eval BODY. + + VARLIST is a list of lists of the form (PATTERN SOURCE). Each + PATTERN is matched against the SOURCE structurally. SOURCE is only + evaluated once for each PATTERN. + + Each SOURCE can refer to the symbols already bound by this VARLIST. + This is useful if you want to destructure SOURCE recursively but + also want to name the intermediate structures. + + See ‘-let’ (*note -let::) for the list of all possible patterns. + + (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d)) + ⇒ (1 2 3 4) + (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d)) + ⇒ (1 (2 . 3) 2 3) + (-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar)) + ⇒ (1 a b c (a b c)) + + -- Macro: -lambda (match-form &rest body) + Return a lambda which destructures its input as MATCH-FORM and + executes BODY. + + Note that you have to enclose the MATCH-FORM in a pair of parens, + such that: + + (-lambda (x) body) (-lambda (x y ...) body) + + has the usual semantics of ‘lambda’. Furthermore, these get + translated into normal ‘lambda’, so there is no performance + penalty. + + See ‘-let’ (*note -let::) for a description of the destructuring + mechanism. + + (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6))) + ⇒ (3 7 11) + (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6])) + ⇒ (3 7 11) + (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6)) + ⇒ (2 3 5 6) + + -- Macro: -setq ([match-form val] ...) + Bind each MATCH-FORM to the value of its VAL. + + MATCH-FORM destructuring is done according to the rules of ‘-let’ + (*note -let::). + + This macro allows you to bind multiple variables by destructuring + the value, so for example: + + (-setq (a b) x (&plist :c c) plist) + + expands roughly speaking to the following code + + (setq a (car x) b (cadr x) c (plist-get plist :c)) + + Care is taken to only evaluate each VAL once so that in case of + multiple assignments it does not cause unexpected side effects. + + (let (a) (-setq a 1) a) + ⇒ 1 + (let (a b) (-setq (a b) (list 1 2)) (list a b)) + ⇒ (1 2) + (let (c) (-setq (&plist :c c) (list :c "c")) c) + ⇒ "c" + + +File: dash.info, Node: Side effects, Next: Destructive operations, Prev: Binding, Up: Functions + +2.14 Side effects +================= + +Functions iterating over lists for side effect only. + + -- Function: -each (list fn) + Call FN on each element of LIST. Return nil; this function is + intended for side effects. + + Its anaphoric counterpart is ‘--each’. + + For access to the current element’s index in LIST, see + ‘-each-indexed’ (*note -each-indexed::). + + (let (l) (-each '(1 2 3) (lambda (x) (push x l))) l) + ⇒ (3 2 1) + (let (l) (--each '(1 2 3) (push it l)) l) + ⇒ (3 2 1) + (-each '(1 2 3) #'identity) + ⇒ nil + + -- Function: -each-while (list pred fn) + Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil. Once + an ITEM is reached for which PRED returns nil, FN is no longer + called. Return nil; this function is intended for side effects. + + Its anaphoric counterpart is ‘--each-while’. + + (let (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) + ⇒ (4 2) + (let (l) (--each-while '(1 2 3 4) (< it 3) (push it l)) l) + ⇒ (2 1) + (let ((s 0)) (--each-while '(1 3 4 5) (< it 5) (setq s (+ s it))) s) + ⇒ 8 + + -- Function: -each-indexed (list fn) + Call FN on each index and element of LIST. For each ITEM at INDEX + in LIST, call (funcall FN INDEX ITEM). Return nil; this function + is intended for side effects. + + See also: ‘-map-indexed’ (*note -map-indexed::). + + (let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l) + ⇒ ((c 2) (b 1) (a 0)) + (let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l) + ⇒ ((c 2) (b 1) (a 0)) + (let (l) (--each-indexed () (push it l)) l) + ⇒ () + + -- Function: -each-r (list fn) + Call FN on each element of LIST in reversed order. Return nil; + this function is intended for side effects. + + Its anaphoric counterpart is ‘--each-r’. + + (let (l) (-each-r '(1 2 3) (lambda (x) (push x l))) l) + ⇒ (1 2 3) + (let (l) (--each-r '(1 2 3) (push it l)) l) + ⇒ (1 2 3) + (-each-r '(1 2 3) #'identity) + ⇒ nil + + -- Function: -each-r-while (list pred fn) + Call FN on each ITEM in reversed LIST, while (PRED ITEM) is + non-nil. Once an ITEM is reached for which PRED returns nil, FN is + no longer called. Return nil; this function is intended for side + effects. + + Its anaphoric counterpart is ‘--each-r-while’. + + (let (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) + ⇒ (6) + (let (l) (--each-r-while '(1 2 3 4) (>= it 3) (push it l)) l) + ⇒ (3 4) + (let ((s 0)) (--each-r-while '(1 2 3 5) (> it 1) (setq s (+ s it))) s) + ⇒ 10 + + -- Function: -dotimes (num fn) + Call FN NUM times, presumably for side effects. FN is called with + a single argument on successive integers running from 0, inclusive, + to NUM, exclusive. FN is not called if NUM is less than 1. + + This function’s anaphoric counterpart is ‘--dotimes’. + + (let (s) (-dotimes 3 (lambda (n) (push n s))) s) + ⇒ (2 1 0) + (let (s) (-dotimes 0 (lambda (n) (push n s))) s) + ⇒ () + (let (s) (--dotimes 5 (push it s)) s) + ⇒ (4 3 2 1 0) + + +File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side effects, Up: Functions + +2.15 Destructive operations +=========================== + +Macros that modify variables holding lists. + + -- Macro: !cons (car cdr) + Destructive: Set CDR to the cons of CAR and CDR. + + (let (l) (!cons 5 l) l) + ⇒ (5) + (let ((l '(3))) (!cons 5 l) l) + ⇒ (5 3) + + -- Macro: !cdr (list) + Destructive: Set LIST to the cdr of LIST. + + (let ((l '(3))) (!cdr l) l) + ⇒ () + (let ((l '(3 5))) (!cdr l) l) + ⇒ (5) + + +File: dash.info, Node: Function combinators, Prev: Destructive operations, Up: Functions + +2.16 Function combinators +========================= + +Functions that manipulate and compose other functions. + + -- Function: -partial (fn &rest args) + Take a function FN and fewer than the normal arguments to FN, and + return a fn that takes a variable number of additional ARGS. When + called, the returned function calls FN with ARGS first and then + additional args. + + (funcall (-partial '- 5) 3) + ⇒ 2 + (funcall (-partial '+ 5 2) 3) + ⇒ 10 + + -- Function: -rpartial (fn &rest args) + Takes a function FN and fewer than the normal arguments to FN, and + returns a fn that takes a variable number of additional ARGS. When + called, the returned function calls FN with the additional args + first and then ARGS. + + (funcall (-rpartial '- 5) 8) + ⇒ 3 + (funcall (-rpartial '- 5 2) 10) + ⇒ 3 + + -- Function: -juxt (&rest fns) + Takes a list of functions and returns a fn that is the + juxtaposition of those fns. The returned fn takes a variable + number of args, and returns a list containing the result of + applying each fn to the args (left-to-right). + + (funcall (-juxt '+ '-) 3 5) + ⇒ (8 -2) + (-map (-juxt 'identity 'square) '(1 2 3)) + ⇒ ((1 1) (2 4) (3 9)) + + -- Function: -compose (&rest fns) + Takes a list of functions and returns a fn that is the composition + of those fns. The returned fn takes a variable number of + arguments, and returns the result of applying each fn to the result + of applying the previous fn to the arguments (right-to-left). + + (funcall (-compose 'square '+) 2 3) + ⇒ (square (+ 2 3)) + (funcall (-compose 'identity 'square) 3) + ⇒ (square 3) + (funcall (-compose 'square 'identity) 3) + ⇒ (square 3) + + -- Function: -applify (fn) + Changes an n-arity function FN to a 1-arity function that expects a + list with n items as arguments + + (-map (-applify '+) '((1 1 1) (1 2 3) (5 5 5))) + ⇒ (3 6 15) + (-map (-applify (lambda (a b c) `(,a (,b (,c))))) '((1 1 1) (1 2 3) (5 5 5))) + ⇒ ((1 (1 (1))) (1 (2 (3))) (5 (5 (5)))) + (funcall (-applify '<) '(3 6)) + ⇒ t + + -- Function: -on (operator transformer) + Return a function of two arguments that first applies TRANSFORMER + to each of them and then applies OPERATOR on the results (in the + same order). + + In types: (b -> b -> c) -> (a -> b) -> a -> a -> c + + (-sort (-on '< 'length) '((1 2 3) (1) (1 2))) + ⇒ ((1) (1 2) (1 2 3)) + (-min-by (-on '> 'length) '((1 2 3) (4) (1 2))) + ⇒ (4) + (-min-by (-on 'string-lessp 'number-to-string) '(2 100 22)) + ⇒ 22 + + -- Function: -flip (func) + Swap the order of arguments for binary function FUNC. + + In types: (a -> b -> c) -> b -> a -> c + + (funcall (-flip '<) 2 1) + ⇒ t + (funcall (-flip '-) 3 8) + ⇒ 5 + (-sort (-flip '<) '(4 3 6 1)) + ⇒ (6 4 3 1) + + -- Function: -const (c) + Return a function that returns C ignoring any additional arguments. + + In types: a -> b -> a + + (funcall (-const 2) 1 3 "foo") + ⇒ 2 + (-map (-const 1) '("a" "b" "c" "d")) + ⇒ (1 1 1 1) + (-sum (-map (-const 1) '("a" "b" "c" "d"))) + ⇒ 4 + + -- Macro: -cut (&rest params) + Take n-ary function and n arguments and specialize some of them. + Arguments denoted by <> will be left unspecialized. + + See SRFI-26 for detailed description. + + (funcall (-cut list 1 <> 3 <> 5) 2 4) + ⇒ (1 2 3 4 5) + (-map (-cut funcall <> 5) `(1+ 1- ,(lambda (x) (/ 1.0 x)))) + ⇒ (6 4 0.2) + (-map (-cut <> 1 2 3) '(list vector string)) + ⇒ ((1 2 3) [1 2 3] "\1\2\3") + + -- Function: -not (pred) + Take a unary predicate PRED and return a unary predicate that + returns t if PRED returns nil and nil if PRED returns non-nil. + + (funcall (-not 'even?) 5) + ⇒ t + (-filter (-not (-partial '< 4)) '(1 2 3 4 5 6 7 8)) + ⇒ (1 2 3 4) + + -- Function: -orfn (&rest preds) + Take list of unary predicates PREDS and return a unary predicate + with argument x that returns non-nil if at least one of the PREDS + returns non-nil on x. + + In types: [a -> Bool] -> a -> Bool + + (-filter (-orfn 'even? (-partial (-flip '<) 5)) '(1 2 3 4 5 6 7 8 9 10)) + ⇒ (1 2 3 4 6 8 10) + (funcall (-orfn 'stringp 'even?) "foo") + ⇒ t + + -- Function: -andfn (&rest preds) + Take list of unary predicates PREDS and return a unary predicate + with argument x that returns non-nil if all of the PREDS returns + non-nil on x. + + In types: [a -> Bool] -> a -> Bool + + (funcall (-andfn (-cut < <> 10) 'even?) 6) + ⇒ t + (funcall (-andfn (-cut < <> 10) 'even?) 12) + ⇒ nil + (-filter (-andfn (-not 'even?) (-cut >= 5 <>)) '(1 2 3 4 5 6 7 8 9 10)) + ⇒ (1 3 5) + + -- Function: -iteratefn (fn n) + Return a function FN composed N times with itself. + + FN is a unary function. If you need to use a function of higher + arity, use ‘-applify’ (*note -applify::) first to turn it into a + unary function. + + With n = 0, this acts as identity function. + + In types: (a -> a) -> Int -> a -> a. + + This function satisfies the following law: + + (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init + (1+ n))). + + (funcall (-iteratefn (lambda (x) (* x x)) 3) 2) + ⇒ 256 + (funcall (-iteratefn '1+ 3) 1) + ⇒ 4 + (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) + ⇒ (4 5) + + -- Function: -fixfn (fn &optional equal-test halt-test) + Return a function that computes the (least) fixpoint of FN. + + FN must be a unary function. The returned lambda takes a single + argument, X, the initial value for the fixpoint iteration. The + iteration halts when either of the following conditions is + satisfied: + + 1. Iteration converges to the fixpoint, with equality being tested + using EQUAL-TEST. If EQUAL-TEST is not specified, ‘equal’ is used. + For functions over the floating point numbers, it may be necessary + to provide an appropriate approximate comparison test. + + 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a + simple counter that returns t after ‘-fixfn-max-iterations’, to + guard against infinite iteration. Otherwise, HALT-TEST must be a + function that accepts a single argument, the current value of X, + and returns non-nil as long as iteration should continue. In this + way, a more sophisticated convergence test may be supplied by the + caller. + + The return value of the lambda is either the fixpoint or, if + iteration halted before converging, a cons with car ‘halted’ and + cdr the final output from HALT-TEST. + + In types: (a -> a) -> a -> a. + + (funcall (-fixfn #'cos #'approx=) 0.7) + ⇒ 0.7390851332151607 + (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) + ⇒ 1.8555845286409378 + (funcall (-fixfn #'sin #'approx=) 0.1) + ⇒ (halted . t) + + -- Function: -prodfn (&rest fns) + Take a list of n functions and return a function that takes a list + of length n, applying i-th function to i-th element of the input + list. Returns a list of length n. + + In types (for n=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d) + + This function satisfies the following laws: + + (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn + (-compose f f’) (-compose g g’) ...) (-prodfn f g ...) = (-juxt + (-compose f (-partial ’nth 0)) (-compose g (-partial ’nth 1)) ...) + (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose f + f’) (-compose g g’) ...) (-compose (-partial ’nth n) (-prod f1 f2 + ...)) = (-compose fn (-partial ’nth n)) + + (funcall (-prodfn '1+ '1- 'number-to-string) '(1 2 3)) + ⇒ (2 1 "3") + (-map (-prodfn '1+ '1-) '((1 2) (3 4) (5 6) (7 8))) + ⇒ ((2 1) (4 3) (6 5) (8 7)) + (apply '+ (funcall (-prodfn 'length 'string-to-number) '((1 2 3) "15"))) + ⇒ 18 + + +File: dash.info, Node: Development, Next: FDL, Prev: Functions, Up: Top + +3 Development +************* + +The Dash repository is hosted on GitHub at +. + +* Menu: + +* Contribute:: How to contribute. +* Contributors:: List of contributors. + + +File: dash.info, Node: Contribute, Next: Contributors, Up: Development + +3.1 Contribute +============== + +Yes, please do. Pure functions in the list manipulation realm only, +please. There’s a suite of examples/tests in ‘dev/examples.el’, so +remember to add tests for your additions, or they may get broken later. + + Run the tests with ‘make check’. Regenerate the docs with ‘make +docs’. Contributors are encouraged to install these commands as a Git +pre-commit hook, so that the tests are always running and the docs are +always in sync: + + $ cp dev/pre-commit.sh .git/hooks/pre-commit + + Oh, and don’t edit ‘README.md’ or ‘dash.texi’ directly, as they are +auto-generated. Instead, change their respective templates +‘readme-template.md’ or ‘dash-template.texi’. + + To ensure that Dash can be distributed with GNU ELPA or Emacs, we +require that all contributors assign copyright to the Free Software +Foundation. For more on this, *note (emacs)Copyright Assignment::. + + +File: dash.info, Node: Contributors, Prev: Contribute, Up: Development + +3.2 Contributors +================ + + • Matus Goljer (https://github.com/Fuco1) contributed lots of + features and functions. + • Takafumi Arakaki (https://github.com/tkf) contributed ‘-group-by’. + • tali713 (https://github.com/tali713) is the author of ‘-applify’. + • Víctor M. Valenzuela (https://github.com/vemv) contributed + ‘-repeat’. + • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’. + • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’, + ‘-first-item’, and ‘-last-item’. + • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’, + ‘-when-let’, and ‘-insert-at’. + • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’, + ‘-product’, and ‘-same-items?’. + • Christina Whyte (https://github.com/kurisuwhyte) contributed + ‘-compose’. + • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’, + ‘-pad’, ‘-annotate’, ‘-zip-fill’, and a variadic version of ‘-zip’. + • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’ + family use ‘-let’ destructuring and improved the script for + generating documentation. + • Mark Oteiza (https://github.com/holomorph) contributed ‘-iota’ and + the script to create an Info manual. + • Vasilij Schneidermann (https://github.com/wasamasa) contributed + ‘-some’. + • William West (https://github.com/occidens) made ‘-fixfn’ more + robust at handling floats. + • Cam Saul (https://github.com/camsaul) contributed ‘-some->’, + ‘-some->>’, and ‘-some-->’. + • Basil L. Contovounesios (https://github.com/basil-conto) + contributed ‘-common-prefix’, ‘-common-suffix’, and various other + improvements. + • Paul Pogonyshev (https://github.com/doublep) contributed ‘-each-r’ + and ‘-each-r-while’. + + Thanks! + + New contributors are very welcome. *Note Contribute::. + + +File: dash.info, Node: FDL, Next: GPL, Prev: Development, Up: Top + +Appendix A GNU Free Documentation License +***************************************** + + Version 1.3, 3 November 2008 + + Copyright © 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 + . + + 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. + + +File: dash.info, Node: GPL, Next: Index, Prev: FDL, Up: Top + +Appendix B GNU General Public License +************************************* + + Version 3, 29 June 2007 + + Copyright © 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. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) YEAR NAME OF AUTHOR + + 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: + + PROGRAM Copyright (C) YEAR NAME OF AUTHOR + 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 . + + +File: dash.info, Node: Index, Prev: GPL, Up: Top + +Index +***** + +[index] +* Menu: + +* !cdr: Destructive operations. + (line 16) +* !cons: Destructive operations. + (line 8) +* -->: Threading macros. (line 35) +* ->: Threading macros. (line 9) +* ->>: Threading macros. (line 22) +* -all?: Predicates. (line 20) +* -andfn: Function combinators. + (line 137) +* -annotate: Maps. (line 84) +* -any?: Predicates. (line 8) +* -applify: Function combinators. + (line 54) +* -as->: Threading macros. (line 49) +* -butlast: Other list operations. + (line 350) +* -clone: Tree operations. (line 122) +* -common-prefix: Reductions. (line 242) +* -common-suffix: Reductions. (line 252) +* -compose: Function combinators. + (line 41) +* -concat: List to list. (line 23) +* -cons*: Other list operations. + (line 30) +* -cons-pair?: Predicates. (line 126) +* -const: Function combinators. + (line 91) +* -contains?: Predicates. (line 59) +* -copy: Maps. (line 139) +* -count: Reductions. (line 172) +* -cut: Function combinators. + (line 103) +* -cycle: Other list operations. + (line 180) +* -difference: Set operations. (line 20) +* -distinct: Set operations. (line 62) +* -dotimes: Side effects. (line 80) +* -doto: Threading macros. (line 99) +* -drop: Sublist selection. (line 147) +* -drop-last: Sublist selection. (line 161) +* -drop-while: Sublist selection. (line 192) +* -each: Side effects. (line 8) +* -each-indexed: Side effects. (line 38) +* -each-r: Side effects. (line 52) +* -each-r-while: Side effects. (line 65) +* -each-while: Side effects. (line 24) +* -elem-index: Indexing. (line 9) +* -elem-indices: Indexing. (line 21) +* -fifth-item: Other list operations. + (line 330) +* -filter: Sublist selection. (line 8) +* -find-index: Indexing. (line 32) +* -find-indices: Indexing. (line 60) +* -find-last-index: Indexing. (line 46) +* -first: Other list operations. + (line 246) +* -first-item: Other list operations. + (line 287) +* -fix: Other list operations. + (line 390) +* -fixfn: Function combinators. + (line 174) +* -flatten: List to list. (line 34) +* -flatten-n: List to list. (line 56) +* -flip: Function combinators. + (line 79) +* -fourth-item: Other list operations. + (line 320) +* -grade-down: Indexing. (line 81) +* -grade-up: Indexing. (line 71) +* -group-by: Partitioning. (line 193) +* -if-let: Binding. (line 34) +* -if-let*: Binding. (line 45) +* -inits: Reductions. (line 222) +* -insert-at: List to list. (line 110) +* -interleave: Other list operations. + (line 67) +* -interpose: Other list operations. + (line 57) +* -intersection: Set operations. (line 32) +* -iota: Other list operations. + (line 78) +* -is-infix?: Predicates. (line 112) +* -is-prefix?: Predicates. (line 88) +* -is-suffix?: Predicates. (line 100) +* -iterate: Unfolding. (line 9) +* -iteratefn: Function combinators. + (line 151) +* -juxt: Function combinators. + (line 30) +* -keep: List to list. (line 8) +* -lambda: Binding. (line 247) +* -last: Other list operations. + (line 277) +* -last-item: Other list operations. + (line 340) +* -let: Binding. (line 61) +* -let*: Binding. (line 227) +* -list: Other list operations. + (line 373) +* -map: Maps. (line 10) +* -map-first: Maps. (line 38) +* -map-indexed: Maps. (line 66) +* -map-last: Maps. (line 52) +* -map-when: Maps. (line 22) +* -mapcat: Maps. (line 128) +* -max: Reductions. (line 286) +* -max-by: Reductions. (line 296) +* -min: Reductions. (line 262) +* -min-by: Reductions. (line 272) +* -non-nil: Sublist selection. (line 94) +* -none?: Predicates. (line 32) +* -not: Function combinators. + (line 116) +* -on: Function combinators. + (line 65) +* -only-some?: Predicates. (line 44) +* -orfn: Function combinators. + (line 125) +* -pad: Other list operations. + (line 191) +* -partial: Function combinators. + (line 8) +* -partition: Partitioning. (line 80) +* -partition-after-item: Partitioning. (line 183) +* -partition-after-pred: Partitioning. (line 151) +* -partition-all: Partitioning. (line 92) +* -partition-all-in-steps: Partitioning. (line 115) +* -partition-before-item: Partitioning. (line 173) +* -partition-before-pred: Partitioning. (line 162) +* -partition-by: Partitioning. (line 127) +* -partition-by-header: Partitioning. (line 138) +* -partition-in-steps: Partitioning. (line 103) +* -permutations: Set operations. (line 52) +* -powerset: Set operations. (line 44) +* -prodfn: Function combinators. + (line 208) +* -product: Reductions. (line 201) +* -reduce: Reductions. (line 53) +* -reduce-from: Reductions. (line 8) +* -reduce-r: Reductions. (line 72) +* -reduce-r-from: Reductions. (line 26) +* -reductions: Reductions. (line 136) +* -reductions-from: Reductions. (line 100) +* -reductions-r: Reductions. (line 154) +* -reductions-r-from: Reductions. (line 118) +* -remove: Sublist selection. (line 26) +* -remove-at: List to list. (line 146) +* -remove-at-indices: List to list. (line 159) +* -remove-first: Sublist selection. (line 43) +* -remove-item: Sublist selection. (line 83) +* -remove-last: Sublist selection. (line 64) +* -repeat: Other list operations. + (line 19) +* -replace: List to list. (line 68) +* -replace-at: List to list. (line 121) +* -replace-first: List to list. (line 82) +* -replace-last: List to list. (line 96) +* -rotate: Other list operations. + (line 8) +* -rpartial: Function combinators. + (line 19) +* -running-product: Reductions. (line 211) +* -running-sum: Reductions. (line 190) +* -same-items?: Predicates. (line 74) +* -second-item: Other list operations. + (line 300) +* -select-by-indices: Sublist selection. (line 208) +* -select-column: Sublist selection. (line 238) +* -select-columns: Sublist selection. (line 219) +* -separate: Partitioning. (line 69) +* -setq: Binding. (line 270) +* -slice: Sublist selection. (line 104) +* -snoc: Other list operations. + (line 43) +* -some: Other list operations. + (line 262) +* -some-->: Threading macros. (line 86) +* -some->: Threading macros. (line 62) +* -some->>: Threading macros. (line 74) +* -sort: Other list operations. + (line 360) +* -splice: Maps. (line 95) +* -splice-list: Maps. (line 115) +* -split-at: Partitioning. (line 8) +* -split-on: Partitioning. (line 34) +* -split-when: Partitioning. (line 52) +* -split-with: Partitioning. (line 23) +* -sum: Reductions. (line 180) +* -table: Other list operations. + (line 202) +* -table-flat: Other list operations. + (line 221) +* -tails: Reductions. (line 232) +* -take: Sublist selection. (line 120) +* -take-last: Sublist selection. (line 133) +* -take-while: Sublist selection. (line 175) +* -third-item: Other list operations. + (line 310) +* -tree-map: Tree operations. (line 28) +* -tree-map-nodes: Tree operations. (line 39) +* -tree-mapreduce: Tree operations. (line 84) +* -tree-mapreduce-from: Tree operations. (line 103) +* -tree-reduce: Tree operations. (line 52) +* -tree-reduce-from: Tree operations. (line 69) +* -tree-seq: Tree operations. (line 8) +* -unfold: Unfolding. (line 25) +* -union: Set operations. (line 8) +* -unzip: Other list operations. + (line 158) +* -update-at: List to list. (line 133) +* -when-let: Binding. (line 9) +* -when-let*: Binding. (line 21) +* -zip: Other list operations. + (line 107) +* -zip-fill: Other list operations. + (line 150) +* -zip-lists: Other list operations. + (line 131) +* -zip-with: Other list operations. + (line 91) +* dash-fontify-mode: Fontification of special variables. + (line 6) +* dash-register-info-lookup: Info symbol lookup. (line 6) +* global-dash-fontify-mode: Fontification of special variables. + (line 12) + + + +Tag Table: +Node: Top742 +Node: Installation2397 +Node: Using in a package3112 +Node: Fontification of special variables3457 +Node: Info symbol lookup4247 +Node: Functions4830 +Node: Maps6314 +Ref: -map6611 +Ref: -map-when6984 +Ref: -map-first7559 +Ref: -map-last8034 +Ref: -map-indexed8504 +Ref: -annotate9190 +Ref: -splice9677 +Ref: -splice-list10455 +Ref: -mapcat10914 +Ref: -copy11287 +Node: Sublist selection11475 +Ref: -filter11668 +Ref: -remove12215 +Ref: -remove-first12753 +Ref: -remove-last13595 +Ref: -remove-item14320 +Ref: -non-nil14720 +Ref: -slice14996 +Ref: -take15525 +Ref: -take-last15932 +Ref: -drop16363 +Ref: -drop-last16804 +Ref: -take-while17230 +Ref: -drop-while17845 +Ref: -select-by-indices18461 +Ref: -select-columns18972 +Ref: -select-column19675 +Node: List to list20138 +Ref: -keep20330 +Ref: -concat20894 +Ref: -flatten21188 +Ref: -flatten-n21944 +Ref: -replace22328 +Ref: -replace-first22789 +Ref: -replace-last23284 +Ref: -insert-at23772 +Ref: -replace-at24097 +Ref: -update-at24484 +Ref: -remove-at24972 +Ref: -remove-at-indices25457 +Node: Reductions26036 +Ref: -reduce-from26232 +Ref: -reduce-r-from26956 +Ref: -reduce28219 +Ref: -reduce-r28970 +Ref: -reductions-from30248 +Ref: -reductions-r-from31054 +Ref: -reductions31884 +Ref: -reductions-r32595 +Ref: -count33340 +Ref: -sum33564 +Ref: -running-sum33752 +Ref: -product34073 +Ref: -running-product34281 +Ref: -inits34622 +Ref: -tails34867 +Ref: -common-prefix35111 +Ref: -common-suffix35405 +Ref: -min35699 +Ref: -min-by35925 +Ref: -max36446 +Ref: -max-by36671 +Node: Unfolding37197 +Ref: -iterate37438 +Ref: -unfold37885 +Node: Predicates38690 +Ref: -any?38867 +Ref: -all?39187 +Ref: -none?39517 +Ref: -only-some?39819 +Ref: -contains?40304 +Ref: -same-items?40693 +Ref: -is-prefix?41078 +Ref: -is-suffix?41404 +Ref: -is-infix?41730 +Ref: -cons-pair?42084 +Node: Partitioning42409 +Ref: -split-at42597 +Ref: -split-with43261 +Ref: -split-on43661 +Ref: -split-when44334 +Ref: -separate44971 +Ref: -partition45410 +Ref: -partition-all45859 +Ref: -partition-in-steps46284 +Ref: -partition-all-in-steps46778 +Ref: -partition-by47260 +Ref: -partition-by-header47638 +Ref: -partition-after-pred48239 +Ref: -partition-before-pred48617 +Ref: -partition-before-item49002 +Ref: -partition-after-item49309 +Ref: -group-by49611 +Node: Indexing50044 +Ref: -elem-index50246 +Ref: -elem-indices50641 +Ref: -find-index51021 +Ref: -find-last-index51510 +Ref: -find-indices52014 +Ref: -grade-up52419 +Ref: -grade-down52826 +Node: Set operations53240 +Ref: -union53423 +Ref: -difference53861 +Ref: -intersection54273 +Ref: -powerset54705 +Ref: -permutations54915 +Ref: -distinct55211 +Node: Other list operations55585 +Ref: -rotate55810 +Ref: -repeat56177 +Ref: -cons*56456 +Ref: -snoc56872 +Ref: -interpose57282 +Ref: -interleave57576 +Ref: -iota57942 +Ref: -zip-with58425 +Ref: -zip59139 +Ref: -zip-lists59968 +Ref: -zip-fill60666 +Ref: -unzip60988 +Ref: -cycle61730 +Ref: -pad62129 +Ref: -table62448 +Ref: -table-flat63234 +Ref: -first64239 +Ref: -some64725 +Ref: -last65209 +Ref: -first-item65543 +Ref: -second-item65942 +Ref: -third-item66206 +Ref: -fourth-item66468 +Ref: -fifth-item66734 +Ref: -last-item66996 +Ref: -butlast67287 +Ref: -sort67532 +Ref: -list68018 +Ref: -fix68587 +Node: Tree operations69076 +Ref: -tree-seq69272 +Ref: -tree-map70127 +Ref: -tree-map-nodes70567 +Ref: -tree-reduce71414 +Ref: -tree-reduce-from72296 +Ref: -tree-mapreduce72896 +Ref: -tree-mapreduce-from73755 +Ref: -clone75040 +Node: Threading macros75367 +Ref: ->75592 +Ref: ->>76080 +Ref: -->76583 +Ref: -as->77139 +Ref: -some->77593 +Ref: -some->>77966 +Ref: -some-->78401 +Ref: -doto78950 +Node: Binding79503 +Ref: -when-let79710 +Ref: -when-let*80165 +Ref: -if-let80688 +Ref: -if-let*81048 +Ref: -let81665 +Ref: -let*87737 +Ref: -lambda88674 +Ref: -setq89480 +Node: Side effects90281 +Ref: -each90475 +Ref: -each-while90996 +Ref: -each-indexed91598 +Ref: -each-r92184 +Ref: -each-r-while92620 +Ref: -dotimes93246 +Node: Destructive operations93799 +Ref: !cons94017 +Ref: !cdr94221 +Node: Function combinators94414 +Ref: -partial94618 +Ref: -rpartial95012 +Ref: -juxt95415 +Ref: -compose95845 +Ref: -applify96398 +Ref: -on96827 +Ref: -flip97351 +Ref: -const97662 +Ref: -cut98000 +Ref: -not98480 +Ref: -orfn98789 +Ref: -andfn99222 +Ref: -iteratefn99716 +Ref: -fixfn100418 +Ref: -prodfn101974 +Node: Development103032 +Node: Contribute103321 +Node: Contributors104333 +Node: FDL106426 +Node: GPL131746 +Node: Index169495 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/dash-2.17.0/dir b/elpa/dash-2.18.0/dir old mode 100755 new mode 100644 similarity index 99% rename from elpa/dash-2.17.0/dir rename to elpa/dash-2.18.0/dir index 49b1700..7d473f4 --- a/elpa/dash-2.17.0/dir +++ b/elpa/dash-2.18.0/dir @@ -15,4 +15,4 @@ File: dir, Node: Top This is the top of the INFO tree * Menu: Emacs -* Dash: (dash.info). A modern list library for GNU Emacs +* Dash: (dash.info). A modern list library for GNU Emacs. diff --git a/elpa/dockerfile-mode-1.3/dockerfile-mode-pkg.el b/elpa/dockerfile-mode-1.3/dockerfile-mode-pkg.el deleted file mode 100755 index 98dec20..0000000 --- a/elpa/dockerfile-mode-1.3/dockerfile-mode-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from /data/data/com.termux/files/home/.emacs.d/elpa/dockerfile-mode-1.3/dockerfile-mode.el -*- no-byte-compile: t -*- -(define-package "dockerfile-mode" "1.3" "Major mode for editing Docker's Dockerfiles" '((emacs "24") (s "1.12")) :commit "d31f7685ebc5832d957e25070a930aa42984327d" :url "https://github.com/spotify/dockerfile-mode") diff --git a/elpa/dockerfile-mode-1.3/dockerfile-mode-autoloads.el b/elpa/dockerfile-mode-1.4/dockerfile-mode-autoloads.el old mode 100755 new mode 100644 similarity index 88% rename from elpa/dockerfile-mode-1.3/dockerfile-mode-autoloads.el rename to elpa/dockerfile-mode-1.4/dockerfile-mode-autoloads.el index 15510a8..7a49a5c --- a/elpa/dockerfile-mode-1.3/dockerfile-mode-autoloads.el +++ b/elpa/dockerfile-mode-1.4/dockerfile-mode-autoloads.el @@ -30,7 +30,9 @@ A major mode to edit Dockerfiles. \(fn)" t nil) -(add-to-list 'auto-mode-alist '("Dockerfile\\(?:\\..*\\)?\\'" . dockerfile-mode)) +(add-to-list 'auto-mode-alist '("/Dockerfile\\(?:\\..*\\)?\\'" . dockerfile-mode)) + +(add-to-list 'auto-mode-alist '("\\.dockerfile\\'" . dockerfile-mode)) (if (fboundp 'register-definition-prefixes) (register-definition-prefixes "dockerfile-mode" '("dockerfile-"))) diff --git a/elpa/dockerfile-mode-1.4/dockerfile-mode-pkg.el b/elpa/dockerfile-mode-1.4/dockerfile-mode-pkg.el new file mode 100644 index 0000000..385f85a --- /dev/null +++ b/elpa/dockerfile-mode-1.4/dockerfile-mode-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from /home/raphael/.emacs.d/elpa/dockerfile-mode-1.4/dockerfile-mode.el -*- no-byte-compile: t -*- +(define-package "dockerfile-mode" "1.4" "Major mode for editing Docker's Dockerfiles" '((emacs "24")) :commit "ed1d04c89cd8b53963f2dcae7cb3a46967e0abbf" :url "https://github.com/spotify/dockerfile-mode") diff --git a/elpa/dockerfile-mode-1.3/dockerfile-mode.el b/elpa/dockerfile-mode-1.4/dockerfile-mode.el old mode 100755 new mode 100644 similarity index 88% rename from elpa/dockerfile-mode-1.3/dockerfile-mode.el rename to elpa/dockerfile-mode-1.4/dockerfile-mode.el index e640db1..369d087 --- a/elpa/dockerfile-mode-1.3/dockerfile-mode.el +++ b/elpa/dockerfile-mode-1.4/dockerfile-mode.el @@ -1,9 +1,9 @@ ;;; dockerfile-mode.el --- Major mode for editing Docker's Dockerfiles -*- lexical-binding: t -*- ;; Copyright (c) 2013 Spotify AB -;; Package-Requires: ((emacs "24") (s "1.12")) -;; Package-Version: 1.3 -;; Package-Commit: d31f7685ebc5832d957e25070a930aa42984327d +;; Package-Requires: ((emacs "24")) +;; Package-Version: 1.4 +;; Package-Commit: ed1d04c89cd8b53963f2dcae7cb3a46967e0abbf ;; Homepage: https://github.com/spotify/dockerfile-mode ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); you may not @@ -28,7 +28,6 @@ (require 'sh-script) (require 'rx) -(require 's) (declare-function cygwin-convert-file-name-to-windows "cygw32.c" (file &optional absolute-p)) @@ -62,6 +61,20 @@ Each element of the list will be passed as a separate :type '(repeat string) :group 'dockerfile) +(defcustom dockerfile-use-buildkit nil + "If t use Docker buildkit for building images + +This is the new buildsystem for docker, and in time it will replace the old one +but for now it has to be explicitly enabled to work. +It is supported from docker 18.09" + :type 'boolean) + +(defcustom dockerfile-indent-offset (or standard-indent 2) + "Dockerfile number of columns for margin-changing functions to indent." + :type 'integer + :safe #'integerp + :group 'dockerfile) + (defface dockerfile-image-name '((t (:inherit (font-lock-type-face bold)))) "Face to highlight the base image name after FROM instruction.") @@ -125,7 +138,7 @@ Each element of the list will be passed as a separate "Indent lines in a Dockerfile. Lines beginning with a keyword are ignored, and any others are -indented by one `tab-width'." +indented by one `dockerfile-indent-offset'." (unless (member (get-text-property (point-at-bol) 'face) '(font-lock-comment-delimiter-face font-lock-keyword-face)) (save-excursion @@ -134,7 +147,7 @@ indented by one `tab-width'." (unless (equal (point) (point-at-eol)) ; Ignore empty lines. ;; Delete existing whitespace. (delete-char (- (point-at-bol) (point))) - (indent-to tab-width))))) + (indent-to dockerfile-indent-offset))))) (defun dockerfile-build-arg-string () "Create a --build-arg string for each element in `dockerfile-build-args'." @@ -146,7 +159,8 @@ indented by one `tab-width'." If in Cygwin environment, uses Cygwin specific function to convert the file name. Otherwise, uses Emacs' standard conversion function." (if (fboundp 'cygwin-convert-file-name-to-windows) - (s-replace "\\" "\\\\" (cygwin-convert-file-name-to-windows file)) + (replace-regexp-in-string + (rx "\\") "\\\\" (cygwin-convert-file-name-to-windows file) t t) (convert-standard-filename file))) (defun dockerfile-tag-string (image-name) @@ -156,7 +170,7 @@ file name. Otherwise, uses Emacs' standard conversion function." (defvar dockerfile-image-name nil "Name of the dockerfile currently being used. This can be set in file or directory-local variables.") -(define-obsolete-variable-alias 'docker-image-name 'dockerfile-image-name) +(define-obsolete-variable-alias 'docker-image-name 'dockerfile-image-name "2017-10-22") (defvar dockerfile-image-name-history nil "History of image names read by `dockerfile-read-image-name'.") @@ -178,7 +192,8 @@ The build string will be of the format: (save-buffer) (compilation-start (format - "%s%s build %s %s %s -f %s %s" + "%s%s%s build %s %s %s -f %s %s" + (if dockerfile-use-buildkit "DOCKER_BUILDKIT=1 " "") (if dockerfile-use-sudo "sudo " "") dockerfile-mode-command (if no-cache "--no-cache" "") @@ -228,7 +243,10 @@ returned, otherwise the base image name is used." (set (make-local-variable 'indent-line-function) #'dockerfile-indent-line-function)) ;;;###autoload -(add-to-list 'auto-mode-alist '("Dockerfile\\(?:\\..*\\)?\\'" . dockerfile-mode)) +(add-to-list 'auto-mode-alist '("/Dockerfile\\(?:\\..*\\)?\\'" . dockerfile-mode)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.dockerfile\\'" . dockerfile-mode)) (provide 'dockerfile-mode) diff --git a/elpa/ivy-0.13.1.signed b/elpa/ivy-0.13.1.signed new file mode 100644 index 0000000..f46a755 --- /dev/null +++ b/elpa/ivy-0.13.1.signed @@ -0,0 +1 @@ +Good signature from 066DAFCB81E42C40 GNU ELPA Signing Agent (2019) (trust undefined) created at 2020-06-22T16:05:01-0500 using RSA \ No newline at end of file diff --git a/elpa/ivy-0.13.1/ChangeLog b/elpa/ivy-0.13.1/ChangeLog new file mode 100644 index 0000000..2a71274 --- /dev/null +++ b/elpa/ivy-0.13.1/ChangeLog @@ -0,0 +1,76 @@ +2020-06-22 Oleh Krehel + + Split package ivy into ivy, swiper, counsel + + Publishing them in a single package on GNU ELPA has lead to version + conflicts. + +2019-10-16 Oleh Krehel + + Merge commit 'cd634c6f51458f81898ecf2821ac3169cb65a1eb' from ivy + +2019-07-20 Oleh Krehel + + packages/ivy/dir: Use install-info + +2019-07-20 Oleh Krehel + + Merge commit '85d1e2e779ca92e6ef8e47d08f866b13d4d87aee' from ivy + +2019-05-13 Stefan Monnier + + * avy/targets/checkdoc.el, ivy/doc/scripts.el: copyright tweak + +2019-05-11 Oleh Krehel + + Merge commit '525b2e4887dd839045313f32d3ddeb5cab4c7a7e' from ivy + +2018-01-12 Oleh Krehel + + Fix bad git subtree merge for ivy + +2017-11-30 Oleh Krehel + + Merge commit '4a2cee03519f98cf95b29905dec2566a39ff717e' from swiper + +2017-04-10 Stefan Monnier + + ivy/targets/obsolete-config.el: Satisfy check_copyright + +2017-04-10 Oleh Krehel + + Add 'packages/ivy/' from commit + 'f4b433436668ac09f3d1815fbfb4b71f3e0690fa' + + git-subtree-dir: packages/ivy git-subtree-mainline: + 6f4e442a66d625f647faa51e88e052c3d93e9657 git-subtree-split: + f4b433436668ac09f3d1815fbfb4b71f3e0690fa + +2017-04-10 Oleh Krehel + + Remove ivy 0.9.0 to add it again with subtree + +2017-04-09 Oleh Krehel + + Merge commit 'af746cad0e9c5d010ea530381111372f7daae55b' from swiper + +2017-04-08 Oleh Krehel + + Merge commit 'ace01d5603ddf49b025eb811b612af72ec38dcfb' from swiper + +2016-07-11 Paul Eggert + + Fix some quoting problems in doc strings + + Most of these are minor issues involving, e.g., quoting `like this' + instead of 'like this'. A few involve escaping ` and ' with a preceding + \= when the characters should not be turned into curved single quotes. + +2016-04-25 Oleh Krehel + + Merge commit 'db005182ad0fd05c07e8e5c085abe6c750e6c578' from ivy + +2016-04-25 Oleh Krehel + + Rename swiper -> ivy + diff --git a/elpa/ivy-0.13.1/colir.el b/elpa/ivy-0.13.1/colir.el new file mode 100644 index 0000000..9e61273 --- /dev/null +++ b/elpa/ivy-0.13.1/colir.el @@ -0,0 +1,124 @@ +;;; colir.el --- Color blending library -*- lexical-binding: t -*- + +;; Copyright (C) 2015-2019 Free Software Foundation, Inc. + +;; Author: Oleh Krehel + +;; This file is part of GNU Emacs. + +;; This file 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, 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. + +;; For a full copy of the GNU General Public License +;; see . + +;;; Commentary: + +;; This package solves the problem of adding a face with a background +;; to text which may already have a background. In all conflicting +;; areas, instead of choosing either the original or the new +;; background face, their blended sum is used. +;; +;; The blend mode functions are taken from URL +;; `https://en.wikipedia.org/wiki/Blend_modes'. + +;;; Code: + +(require 'cl-lib) +(require 'color) + +(defcustom colir-compose-method #'colir-compose-alpha + "Select a method to compose two color channels." + :group 'ivy + :type '(radio + (function-item colir-compose-alpha) + (function-item colir-compose-overlay) + (function-item colir-compose-soft-light))) + +(defun colir-compose-soft-light (a b) + "Compose A and B channels." + (if (< b 0.5) + (+ (* 2 a b) (* a a (- 1 b b))) + (+ (* 2 a (- 1 b)) (* (sqrt a) (- (* 2 b) 1))))) + +(defun colir-compose-overlay (a b) + "Compose A and B channels." + (if (< a 0.5) + (* 2 a b) + (- 1 (* 2 (- 1 a) (- 1 b))))) + +(defun colir-compose-alpha (a b &optional alpha gamma) + "Compose A and B channels. +Optional argument ALPHA is a number between 0.0 and 1.0 which corresponds +to the influence of A on the result. Default value is 0.5. +Optional argument GAMMA is used for gamma correction. Default value is 2.2." + (setq alpha (or alpha 0.5)) + (setq gamma (or gamma 2.2)) + (+ (* (expt a gamma) alpha) (* (expt b gamma) (- 1 alpha)))) + +(defun colir-blend (c1 c2) + "Blend the two colors C1 and C2 using `colir-compose-method'. +C1 and C2 are triples of floats in [0.0 1.0] range." + (apply #'color-rgb-to-hex + (cl-mapcar + (if (eq (frame-parameter nil 'background-mode) 'dark) + ;; this method works nicely for dark themes + 'colir-compose-soft-light + colir-compose-method) + c1 c2))) + +(defun colir-color-parse (color) + "Convert string COLOR to triple of floats in [0.0 1.0]." + (if (string-match "#\\([[:xdigit:]]\\{2\\}\\)\\([[:xdigit:]]\\{2\\}\\)\\([[:xdigit:]]\\{2\\}\\)" color) + (mapcar (lambda (v) (/ (string-to-number v 16) 255.0)) + (list (match-string 1 color) (match-string 2 color) (match-string 3 color))) + ;; does not work properly in terminal (maps color to nearest color + ;; from available color palette). + (color-name-to-rgb color))) + +(defun colir--blend-background (start next prevn face object) + (let ((background-prev (face-background prevn))) + (progn + (put-text-property + start next 'face + (if background-prev + (cons `(background-color + . ,(colir-blend + (colir-color-parse background-prev) + (colir-color-parse (face-background face nil t)))) + prevn) + (list face prevn)) + object)))) + +(defun colir-blend-face-background (start end face &optional object) + "Append to the face property of the text from START to END the face FACE. +When the text already has a face with a non-plain background, +blend it with the background of FACE. +Optional argument OBJECT is the string or buffer containing the text. +See also `font-lock-append-text-property'." + (let (next prev prevn) + (while (/= start end) + (setq next (next-single-property-change start 'face object end)) + (setq prev (get-text-property start 'face object)) + (setq prevn (if (listp prev) + (cl-find-if #'atom prev) + prev)) + (cond + ((or (keywordp (car-safe prev)) (consp (car-safe prev))) + (put-text-property start next 'face (cons face prev) object)) + ((facep prevn) + (colir--blend-background start next prevn face object)) + (t + (put-text-property start next 'face face object))) + (setq start next)))) + +(provide 'colir) + +;;; colir.el ends here diff --git a/elpa/ivy-0.13.1/dir b/elpa/ivy-0.13.1/dir new file mode 100644 index 0000000..b68b083 --- /dev/null +++ b/elpa/ivy-0.13.1/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Ivy: (ivy). Using Ivy for completion. diff --git a/elpa/ivy-0.13.1/ivy-autoloads.el b/elpa/ivy-0.13.1/ivy-autoloads.el new file mode 100644 index 0000000..e584cdc --- /dev/null +++ b/elpa/ivy-0.13.1/ivy-autoloads.el @@ -0,0 +1,168 @@ +;;; ivy-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "colir" "colir.el" (0 0 0 0)) +;;; Generated autoloads from colir.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "colir" '("colir-"))) + +;;;*** + +;;;### (autoloads nil "ivy" "ivy.el" (0 0 0 0)) +;;; Generated autoloads from ivy.el + +(autoload 'ivy-resume "ivy" "\ +Resume the last completion session." t nil) + +(autoload 'ivy-read "ivy" "\ +Read a string in the minibuffer, with completion. + +PROMPT is a string, normally ending in a colon and a space. +`ivy-count-format' is prepended to PROMPT during completion. + +COLLECTION is either a list of strings, a function, an alist, or +a hash table, supplied for `minibuffer-completion-table'. + +PREDICATE is applied to filter out the COLLECTION immediately. +This argument is for compatibility with `completing-read'. + +When REQUIRE-MATCH is non-nil, only members of COLLECTION can be +selected. + +If INITIAL-INPUT is non-nil, then insert that input in the +minibuffer initially. + +HISTORY is a name of a variable to hold the completion session +history. + +KEYMAP is composed with `ivy-minibuffer-map'. + +PRESELECT, when non-nil, determines which one of the candidates +matching INITIAL-INPUT to select initially. An integer stands +for the position of the desired candidate in the collection, +counting from zero. Otherwise, use the first occurrence of +PRESELECT in the collection. Comparison is first done with +`equal'. If that fails, and when applicable, match PRESELECT as +a regular expression. + +DEF is for compatibility with `completing-read'. + +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 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 +its only argument. When it's nil, ACTION is called on each marked +candidate. + +UNWIND is a function of no arguments to call before exiting. + +RE-BUILDER is a function transforming input text into a regex +pattern. + +MATCHER is a function which can override how candidates are +filtered based on user input. It takes a regex pattern and a +list of candidates, and returns the list of matching candidates. + +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. + +\(fn PROMPT COLLECTION &key PREDICATE REQUIRE-MATCH INITIAL-INPUT HISTORY PRESELECT DEF KEYMAP UPDATE-FN SORT ACTION MULTI-ACTION UNWIND RE-BUILDER MATCHER DYNAMIC-COLLECTION EXTRA-PROPS CALLER)" nil nil) + +(autoload 'ivy-completing-read "ivy" "\ +Read a string in the minibuffer, with completion. + +This interface conforms to `completing-read' and can be used for +`completing-read-function'. + +PROMPT is a string that normally ends in a colon and a space. +COLLECTION is either a list of strings, an alist, an obarray, or a hash table. +PREDICATE limits completion to a subset of COLLECTION. +REQUIRE-MATCH is a boolean value. See `completing-read'. +INITIAL-INPUT is a string inserted into the minibuffer initially. +HISTORY is a list of previously selected inputs. +DEF is the default value. +INHERIT-INPUT-METHOD is currently ignored. + +\(fn PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HISTORY DEF INHERIT-INPUT-METHOD)" nil nil) + +(defvar ivy-mode nil "\ +Non-nil if Ivy mode is enabled. +See the `ivy-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `ivy-mode'.") + +(custom-autoload 'ivy-mode "ivy" nil) + +(autoload 'ivy-mode "ivy" "\ +Toggle Ivy mode on or off. +Turn Ivy mode on if ARG is positive, off otherwise. +Turning on Ivy mode sets `completing-read-function' to +`ivy-completing-read'. + +Global bindings: +\\{ivy-mode-map} + +Minibuffer bindings: +\\{ivy-minibuffer-map} + +\(fn &optional ARG)" t nil) + +(autoload 'ivy-switch-buffer "ivy" "\ +Switch to another buffer." t nil) + +(autoload 'ivy-switch-view "ivy" "\ +Switch to one of the window views stored by `ivy-push-view'." t nil) + +(autoload 'ivy-switch-buffer-other-window "ivy" "\ +Switch to another buffer in another window." t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ivy" '("ivy-" "with-ivy-window"))) + +;;;*** + +;;;### (autoloads nil "ivy-hydra" "ivy-hydra.el" (0 0 0 0)) +;;; Generated autoloads from ivy-hydra.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ivy-hydra" '("hydra-ivy" "ivy-"))) + +;;;*** + +;;;### (autoloads nil "ivy-overlay" "ivy-overlay.el" (0 0 0 0)) +;;; Generated autoloads from ivy-overlay.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ivy-overlay" '("ivy-"))) + +;;;*** + +;;;### (autoloads nil nil ("ivy-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; ivy-autoloads.el ends here diff --git a/elpa/ivy-0.13.1/ivy-hydra.el b/elpa/ivy-0.13.1/ivy-hydra.el new file mode 100644 index 0000000..ce31f2b --- /dev/null +++ b/elpa/ivy-0.13.1/ivy-hydra.el @@ -0,0 +1,133 @@ +;;; ivy-hydra.el --- Additional key bindings for Ivy -*- lexical-binding: t -*- + +;; Copyright (C) 2015-2019 Free Software Foundation, Inc. + +;; Author: Oleh Krehel +;; URL: https://github.com/abo-abo/swiper +;; 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. + +;; This file 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, 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. + +;; For a full copy of the GNU General Public License +;; see . + +;;; Commentary: + +;; This package provides the `hydra-ivy/body' command, which is a +;; quasi-prefix map, with many useful bindings. These bindings are +;; shorter than usual, using mostly unprefixed keys. + +;;; Code: + +(require 'ivy) +(require 'hydra) + +(defun ivy--matcher-desc () + "Return description of `ivy--regex-function'." + (let ((cell (assq ivy--regex-function ivy-preferred-re-builders))) + (if cell + (cdr cell) + "other"))) + +(defhydra hydra-ivy (:hint nil + :color pink) + " +^ ^ ^ ^ ^ ^ | ^Call^ ^ ^ | ^Cancel^ | ^Options^ | Action _w_/_s_/_a_: %-14s(ivy-action-name) +^-^-^-^-^-^-+-^-^---------^-^--+-^-^------+-^-^-------+-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------- +^ ^ _k_ ^ ^ | _f_ollow occ_U_r | _i_nsert | _c_: calling %-5s(if ivy-calling \"on\" \"off\") _C_ase-fold: %-10`ivy-case-fold-search +_h_ ^+^ _l_ | _d_one ^ ^ | _o_ops | _M_: matcher %-5s(ivy--matcher-desc)^^^^^^^^^^^^ _T_runcate: %-11`truncate-lines +^ ^ _j_ ^ ^ | _g_o ^ ^ | ^ ^ | _<_/_>_: shrink/grow^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _D_efinition of this menu +" + ;; arrows + ("h" ivy-beginning-of-buffer) + ("j" ivy-next-line) + ("k" ivy-previous-line) + ("l" ivy-end-of-buffer) + ;; mark + ("m" ivy-mark) + ("u" ivy-unmark) + ("DEL" ivy-unmark-backward) + ("t" ivy-toggle-marks) + ;; actions + ("o" keyboard-escape-quit :exit t) + ("r" ivy-dispatching-done-hydra :exit t) + ("C-g" keyboard-escape-quit :exit t) + ("i" nil) + ("C-o" nil) + ("f" ivy-alt-done :exit nil) + ("C-j" ivy-alt-done :exit nil) + ("d" ivy-done :exit t) + ("g" ivy-call) + ("C-m" ivy-done :exit t) + ("c" ivy-toggle-calling) + ("M" ivy-rotate-preferred-builders) + (">" ivy-minibuffer-grow) + ("<" ivy-minibuffer-shrink) + ("w" ivy-prev-action) + ("s" ivy-next-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) + ("D" (ivy-exit-with-action + (lambda (_) (find-function 'hydra-ivy/body))) + :exit t)) + +(defvar ivy-dispatching-done-columns 2 + "Number of columns to use if the hint does not fit on one line.") + +(defvar ivy-dispatching-done-idle nil + "When non-nil, the hint will be delayed by this many seconds.") + +(defvar ivy-dispatching-done-hydra-exit-keys '(("M-o" nil "back") + ("C-g" nil)) + "Keys that can be used to exit `ivy-dispatching-done-hydra'.") + +(defun ivy-dispatching-done-hydra () + "Select one of the available actions and call `ivy-done'." + (interactive) + (let* ((actions (ivy-state-action ivy-last)) + (extra-actions ivy-dispatching-done-hydra-exit-keys) + (doc (concat "action: " + (mapconcat + (lambda (x) (format "[%s] %s" (nth 0 x) (nth 2 x))) + (append (cdr actions) + extra-actions) ", "))) + (estimated-len (length doc)) + (n-columns (if (> estimated-len (window-width)) + ivy-dispatching-done-columns + nil)) + (i 0)) + (if (null (ivy--actionp actions)) + (ivy-done) + (funcall + (eval + `(defhydra ivy-read-action (:color teal :columns ,n-columns :idle ,ivy-dispatching-done-idle) + "action" + ,@(mapcar (lambda (x) + (list (nth 0 x) + `(progn + (setcar (ivy-state-action ivy-last) ,(cl-incf i)) + (ivy-done)) + (nth 2 x))) + (cdr actions)) + ,@extra-actions)))))) + +(setq ivy-read-action-function (lambda (_) (ivy-dispatching-done-hydra))) + +(provide 'ivy-hydra) + +;;; ivy-hydra.el ends here diff --git a/elpa/ivy-0.13.1/ivy-overlay.el b/elpa/ivy-0.13.1/ivy-overlay.el new file mode 100644 index 0000000..7a77bcf --- /dev/null +++ b/elpa/ivy-0.13.1/ivy-overlay.el @@ -0,0 +1,154 @@ +;;; ivy-overlay.el --- Overlay display functions for Ivy -*- lexical-binding: t -*- + +;; Copyright (C) 2016-2019 Free Software Foundation, Inc. + +;; Author: Oleh Krehel +;; Keywords: convenience + +;; 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 . + +;;; Commentary: + +;; This package allows to setup Ivy's completion at point to actually +;; show the candidates and the input at point, instead of in the +;; minibuffer. + +;;; Code: + +(defface ivy-cursor + '((((class color) (background light)) + :background "black" :foreground "white") + (((class color) (background dark)) + :background "white" :foreground "black")) + "Cursor face for inline completion." + :group 'ivy-faces) + +(defvar ivy--old-cursor-type t) + +(defvar ivy-overlay-at nil + "Overlay variable for `ivy-display-function-overlay'.") + +(declare-function ivy--truncate-string "ivy") + +(defun ivy-left-pad (str width) + "Return STR, but with each line indented by WIDTH spaces. +Lines are truncated to the window width." + (let ((padding (make-string width ?\s))) + (mapconcat (lambda (x) + (ivy--truncate-string (concat padding x) + (1- (+ (window-width) + (window-hscroll))))) + (split-string str "\n") + "\n"))) + +(defun ivy-overlay-cleanup () + "Clean up after `ivy-display-function-overlay'." + (when (overlayp ivy-overlay-at) + (delete-overlay ivy-overlay-at) + (setq ivy-overlay-at nil)) + (unless cursor-type + (setq cursor-type ivy--old-cursor-type)) + (when (fboundp 'company-abort) + (company-abort))) + +(defvar ivy-height) + +(defun ivy-overlay-show-after (str) + "Display STR in an overlay at point. + +First, fill each line of STR with spaces to the current column. +Then attach the overlay to the character before point." + (if ivy-overlay-at + (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) + (overlay-put ivy-overlay-at 'priority 9999)) + (overlay-put ivy-overlay-at 'display str) + (overlay-put ivy-overlay-at 'after-string "")) + +(declare-function org-current-level "org") +(declare-function org-at-heading-p "org") +(defvar org-indent-indentation-per-level) +(defvar ivy-height) +(defvar ivy-last) +(defvar ivy-text) +(defvar ivy-completion-beg) +(declare-function ivy-add-face-text-property "ivy") +(declare-function ivy--get-window "ivy") +(declare-function ivy-state-current "ivy") +(declare-function ivy-state-window "ivy") +(declare-function ivy--remove-prefix "ivy") + +(defun ivy-overlay-impossible-p (_str) + (or + (and (eq major-mode 'org-mode) + (plist-get (text-properties-at (point)) 'src-block)) + (<= (window-height) (+ ivy-height 2)) + (= (point) (point-min)) + (< (- (+ (window-width) (window-hscroll)) (current-column)) + 30))) + +(defun ivy-display-function-overlay (str) + "Called from the minibuffer, display STR in an overlay in Ivy window. +Hide the minibuffer contents and cursor." + (if (save-selected-window + (select-window (ivy-state-window ivy-last)) + (ivy-overlay-impossible-p str)) + (let ((buffer-undo-list t)) + (save-excursion + (forward-line 1) + (insert str))) + (ivy-add-face-text-property (minibuffer-prompt-end) (point-max) + '(:foreground "white")) + (setq cursor-type nil) + (with-selected-window (ivy--get-window ivy-last) + (when cursor-type + (setq ivy--old-cursor-type cursor-type)) + (setq cursor-type nil) + (let ((overlay-str + (apply + #'concat + (buffer-substring (max (point-min) (1- (point))) (point)) + ivy-text + (and (eolp) " ") + (buffer-substring (point) (line-end-position)) + (and (> (length str) 0) + (list "\n" + (ivy-left-pad + (ivy--remove-prefix "\n" str) + (+ + (if (and (eq major-mode 'org-mode) + (bound-and-true-p org-indent-mode)) + (if (org-at-heading-p) + (1- (org-current-level)) + (* org-indent-indentation-per-level (org-current-level))) + 0) + (save-excursion + (when ivy-completion-beg + (goto-char ivy-completion-beg)) + (current-column))))))))) + (let ((cursor-offset (1+ (length ivy-text)))) + (ivy-add-face-text-property cursor-offset (1+ cursor-offset) + 'ivy-cursor overlay-str t)) + (ivy-overlay-show-after overlay-str))))) + +(provide 'ivy-overlay) + +;;; ivy-overlay.el ends here diff --git a/elpa/ivy-0.13.1/ivy-pkg.el b/elpa/ivy-0.13.1/ivy-pkg.el new file mode 100644 index 0000000..33ff7a9 --- /dev/null +++ b/elpa/ivy-0.13.1/ivy-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from ivy.el -*- no-byte-compile: t -*- +(define-package "ivy" "0.13.1" "Incremental Vertical completYon" '((emacs "24.5")) :keywords '("matching") :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) :maintainer '("Oleh Krehel" . "ohwoeowho@gmail.com") :url "https://github.com/abo-abo/swiper") diff --git a/elpa/ivy-0.13.1/ivy.el b/elpa/ivy-0.13.1/ivy.el new file mode 100644 index 0000000..04ef620 --- /dev/null +++ b/elpa/ivy-0.13.1/ivy.el @@ -0,0 +1,5056 @@ +;;; ivy.el --- Incremental Vertical completYon -*- lexical-binding: t -*- + +;; Copyright (C) 2015-2019 Free Software Foundation, Inc. + +;; Author: Oleh Krehel +;; URL: https://github.com/abo-abo/swiper +;; Version: 0.13.1 +;; Package-Requires: ((emacs "24.5")) +;; Keywords: matching + +;; This file is part of GNU Emacs. + +;; This file 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, 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. + +;; For a full copy of the GNU General Public License +;; see . + +;;; Commentary: + +;; This package provides `ivy-read' as an alternative to +;; `completing-read' and similar functions. +;; +;; There's no intricate code to determine the best candidate. +;; Instead, the user can navigate to it with `ivy-next-line' and +;; `ivy-previous-line'. +;; +;; The matching is done by splitting the input text by spaces and +;; re-building it into a regex. +;; So "for example" is transformed into "\\(for\\).*\\(example\\)". + +;;; Code: + +(require 'cl-lib) +(require 'ivy-overlay) +(require 'colir) +(require 'ring) + +;;* Customization +(defgroup ivy nil + "Incremental vertical completion." + :group 'convenience) + +(defgroup ivy-faces nil + "Font-lock faces for `ivy'." + :group 'ivy + :group 'faces) + +(defface ivy-current-match + '((((class color) (background light)) + :background "#1a4b77" :foreground "white") + (((class color) (background dark)) + :background "#65a7e2" :foreground "black")) + "Face used by Ivy for highlighting the current match.") + +(defface ivy-minibuffer-match-highlight + '((t :inherit highlight)) + "Face used by Ivy for highlighting the match under the cursor.") + +(defface ivy-minibuffer-match-face-1 + '((((class color) (background light)) + :background "#d3d3d3") + (((class color) (background dark)) + :background "#555555")) + "The background face for `ivy' minibuffer matches.") + +(defface ivy-minibuffer-match-face-2 + '((((class color) (background light)) + :background "#e99ce8" :weight bold) + (((class color) (background dark)) + :background "#777777" :weight bold)) + "Face for `ivy' minibuffer matches numbered 1 modulo 3.") + +(defface ivy-minibuffer-match-face-3 + '((((class color) (background light)) + :background "#bbbbff" :weight bold) + (((class color) (background dark)) + :background "#7777ff" :weight bold)) + "Face for `ivy' minibuffer matches numbered 2 modulo 3.") + +(defface ivy-minibuffer-match-face-4 + '((((class color) (background light)) + :background "#ffbbff" :weight bold) + (((class color) (background dark)) + :background "#8a498a" :weight bold)) + "Face for `ivy' minibuffer matches numbered 3 modulo 3.") + +(defface ivy-confirm-face + '((t :foreground "ForestGreen" :inherit minibuffer-prompt)) + "Face used by Ivy for a confirmation prompt.") + +(defface ivy-match-required-face + '((t :foreground "red" :inherit minibuffer-prompt)) + "Face used by Ivy for a match required prompt.") + +(defface ivy-subdir + '((t :inherit dired-directory)) + "Face used by Ivy for highlighting subdirs in the alternatives.") + +(defface ivy-org + '((t :inherit org-level-4)) + "Face used by Ivy for highlighting Org buffers in the alternatives.") + +(defface ivy-modified-buffer + '((t :inherit default)) + "Face used by Ivy for highlighting modified file visiting buffers.") + +(defface ivy-modified-outside-buffer + '((t :inherit default)) + "Face used by Ivy for highlighting file visiting buffers modified outside Emacs.") + +(defface ivy-remote + '((((class color) (background light)) + :foreground "#110099") + (((class color) (background dark)) + :foreground "#7B6BFF")) + "Face used by Ivy for highlighting remotes in the alternatives.") + +(defface ivy-virtual + '((t :inherit font-lock-builtin-face)) + "Face used by Ivy for matching virtual buffer names.") + +(defface ivy-action + '((t :inherit font-lock-builtin-face)) + "Face used by Ivy for displaying keys in `ivy-read-action'.") + +(defface ivy-highlight-face + '((t :inherit highlight)) + "Face used by Ivy to highlight certain candidates.") + +(defface ivy-prompt-match + '((t :inherit ivy-current-match)) + "Face used by Ivy for highlighting the selected prompt line.") + +(defface ivy-separator + '((t :inherit font-lock-doc-face)) + "Face for multiline source separator.") + +(defface ivy-grep-info + '((t :inherit compilation-info)) + "Face for highlighting grep information such as file names.") + +(defface ivy-grep-line-number + '((t :inherit compilation-line-number)) + "Face for displaying line numbers in grep messages.") + +(defface ivy-completions-annotations + '((t :inherit completions-annotations)) + "Face for displaying completion annotations.") + +(defface ivy-yanked-word + '((t :inherit highlight)) + "Face used to highlight yanked word.") + +;; Set default customization `:group' to `ivy' for the rest of the file. +(setcdr (assoc load-file-name custom-current-group-alist) 'ivy) + +(defcustom ivy-height 10 + "Number of lines for the minibuffer window. + +See also `ivy-height-alist'." + :type 'integer) + +(defcustom ivy-count-format "%-4d " + "The style to use for displaying the current candidate count for `ivy-read'. +Set this to \"\" to suppress the count visibility. +Set this to \"(%d/%d) \" to display both the index and the count." + :type '(choice + (const :tag "Count disabled" "") + (const :tag "Count matches" "%-4d ") + (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) + +(defcustom ivy-wrap nil + "When non-nil, wrap around after the first and the last candidate." + :type 'boolean) + +(defcustom ivy-display-style (and (fboundp 'add-face-text-property) 'fancy) + "The style for formatting the minibuffer. + +By default, the matched strings are copied as is. + +The fancy display style highlights matching parts of the regexp, +a behavior similar to `swiper'. + +This setting depends on `add-face-text-property' - a C function +available since Emacs 24.4. Fancy style will render poorly in +earlier versions of Emacs." + :type '(choice + (const :tag "Plain" nil) + (const :tag "Fancy" fancy))) + +(defcustom ivy-on-del-error-function #'abort-recursive-edit + "Function to call when deletion fails during completion. +The usual reason for `ivy-backward-delete-char' to fail is when +there is no text left to delete, i.e., when it is called at the +beginning of the minibuffer. +The default setting provides a quick exit from completion." + :type '(choice + (const :tag "Exit completion" abort-recursive-edit) + (const :tag "Do nothing" ignore) + (function :tag "Custom function"))) + +(defcustom ivy-extra-directories '("../" "./") + "Add this to the front of the list when completing file names. +Only \"./\" and \"../\" apply here. They appear in reverse order." + :type '(repeat :tag "Dirs" + (choice + (const :tag "Parent Directory" "../") + (const :tag "Current Directory" "./")))) + +(defcustom ivy-use-virtual-buffers nil + "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.") + +(defvar ivy-display-functions-props + '((ivy-display-function-overlay :cleanup ivy-overlay-cleanup)) + "Map Ivy display functions to their property lists. +Examples of properties include associated `:cleanup' functions.") + +(defcustom ivy-display-functions-alist + '((ivy-completion-in-region . ivy-display-function-overlay) + (t . nil)) + "An alist for customizing where to display the candidates. + +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. + +See also `https://github.com/abo-abo/swiper/wiki/ivy-display-function'." + :type '(alist + :key-type symbol + :value-type (choice + (const :tag "Minibuffer" nil) + (const :tag "LV" ivy-display-function-lv) + (const :tag "Popup" ivy-display-function-popup) + (const :tag "Overlay" ivy-display-function-overlay) + (function :tag "Custom function")))) + +(defvar ivy-completing-read-dynamic-collection nil + "Run `ivy-completing-read' with `:dynamic-collection t`.") + +(defcustom ivy-completing-read-handlers-alist + '((tmm-menubar . completing-read-default) + (tmm-shortcut . completing-read-default) + (bbdb-create . ivy-completing-read-with-empty-string-def) + (auto-insert . ivy-completing-read-with-empty-string-def) + (Info-on-current-buffer . ivy-completing-read-with-empty-string-def) + (Info-follow-reference . ivy-completing-read-with-empty-string-def) + (Info-menu . ivy-completing-read-with-empty-string-def) + (Info-index . ivy-completing-read-with-empty-string-def) + (Info-virtual-index . ivy-completing-read-with-empty-string-def) + (info-display-manual . ivy-completing-read-with-empty-string-def)) + "An alist of handlers to replace `completing-read' in `ivy-mode'." + :type '(alist :key-type symbol :value-type function)) + +(defcustom ivy-height-alist nil + "An alist to customize `ivy-height'. + +It is a list of (CALLER . HEIGHT). CALLER is a caller of +`ivy-read' and HEIGHT is the number of lines displayed. +HEIGHT can also be a function that returns the number of lines." + :type '(alist + :key-type function + :value-type (choice integer function))) + +(defvar ivy-completing-read-ignore-handlers-depth -1 + "Used to avoid infinite recursion. + +If `(minibuffer-depth)' equals this, `ivy-completing-read' will +act as if `ivy-completing-read-handlers-alist' is empty.") + +(defvar ivy-highlight-grep-commands nil + "List of grep-like commands.") + +(defvar ivy--actions-list nil + "A list of extra actions per command.") + +(defun ivy-set-actions (cmd actions) + "Set CMD extra exit points to ACTIONS." + (setq ivy--actions-list + (plist-put ivy--actions-list cmd actions))) + +(defun ivy-add-actions (cmd actions) + "Add extra exit points ACTIONS to CMD. +Existing exit points of CMD are overwritten by those in +ACTIONS that have the same key." + (setq ivy--actions-list + (plist-put ivy--actions-list cmd + (cl-delete-duplicates + (append (plist-get ivy--actions-list cmd) actions) + :key #'car :test #'equal)))) + +(defun ivy--compute-extra-actions (action caller) + "Add extra actions to ACTION based on CALLER." + (let ((extra-actions (cl-delete-duplicates + (append (plist-get ivy--actions-list t) + (plist-get ivy--actions-list this-command) + (plist-get ivy--actions-list caller)) + :key #'car :test #'equal))) + (if extra-actions + (cond ((functionp action) + `(1 + ("o" ,action "default") + ,@extra-actions)) + ((null action) + `(1 + ("o" identity "default") + ,@extra-actions)) + (t + (delete-dups (append action extra-actions)))) + action))) + +(defvar ivy--prompts-list nil) + +(defun ivy-set-prompt (caller prompt-fn) + "Associate CALLER with PROMPT-FN. +PROMPT-FN is a function of no arguments that returns a prompt string." + (setq ivy--prompts-list + (plist-put ivy--prompts-list caller prompt-fn))) + +(defvar ivy--display-transformers-list nil + "A list of str->str transformers per command.") + +(defun ivy-set-display-transformer (cmd transformer) + "Set CMD a displayed candidate TRANSFORMER. + +It's a lambda that takes a string one of the candidates in the +collection and returns a string for display, the same candidate +plus some extra information. + +This lambda is called only on the `ivy-height' candidates that +are about to be displayed, not on the whole collection." + (setq ivy--display-transformers-list + (plist-put ivy--display-transformers-list cmd transformer))) + +(defvar ivy--sources-list nil + "A list of extra sources per command.") + +(defun ivy-set-sources (cmd sources) + "Attach to CMD a list of extra SOURCES. + +Each static source is a function that takes no argument and +returns a list of strings. + +The (original-source) determines the position of the original +dynamic source. + +Extra dynamic sources aren't supported yet. + +Example: + + (defun small-recentf () + (cl-subseq recentf-list 0 20)) + + (ivy-set-sources + 'counsel-locate + '((small-recentf) + (original-source)))" + (setq ivy--sources-list + (plist-put ivy--sources-list cmd sources))) + +(defun ivy--compute-extra-candidates (caller) + (let ((extra-sources (or (plist-get ivy--sources-list caller) + '((original-source)))) + (result nil)) + (dolist (source extra-sources) + (cond ((equal source '(original-source)) + (push source result)) + ((null (cdr source)) + (push (list (car source) (funcall (car source))) result)))) + result)) + +(defvar ivy-current-prefix-arg nil + "Prefix arg to pass to actions. +This is a global variable that is set by ivy functions for use in +action functions.") + +;;* Keymap +(require 'delsel) +(defvar ivy-minibuffer-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-m") 'ivy-done) + (define-key map [down-mouse-1] 'ignore) + (define-key map [mouse-1] 'ivy-mouse-done) + (define-key map [mouse-3] 'ivy-mouse-dispatching-done) + (define-key map (kbd "C-M-m") 'ivy-call) + (define-key map (kbd "C-j") 'ivy-alt-done) + (define-key map (kbd "C-M-j") 'ivy-immediate-done) + (define-key map (kbd "TAB") 'ivy-partial-or-done) + (define-key map [remap next-line] 'ivy-next-line) + (define-key map [remap previous-line] 'ivy-previous-line) + (define-key map (kbd "C-s") 'ivy-next-line-or-history) + (define-key map (kbd "C-r") 'ivy-reverse-i-search) + (define-key map (kbd "SPC") 'self-insert-command) + (define-key map [remap delete-backward-char] 'ivy-backward-delete-char) + (define-key map [remap backward-delete-char-untabify] 'ivy-backward-delete-char) + (define-key map [remap backward-kill-word] 'ivy-backward-kill-word) + (define-key map [remap delete-char] 'ivy-delete-char) + (define-key map [remap forward-char] 'ivy-forward-char) + (define-key map (kbd "") 'ivy-forward-char) + (define-key map [remap kill-word] 'ivy-kill-word) + (define-key map [remap beginning-of-buffer] 'ivy-beginning-of-buffer) + (define-key map [remap end-of-buffer] 'ivy-end-of-buffer) + (define-key map (kbd "M-n") 'ivy-next-history-element) + (define-key map (kbd "M-p") 'ivy-previous-history-element) + (define-key map (kbd "C-g") 'minibuffer-keyboard-quit) + (define-key map [remap scroll-up-command] 'ivy-scroll-up-command) + (define-key map [remap scroll-down-command] 'ivy-scroll-down-command) + (define-key map (kbd "") 'ivy-scroll-up-command) + (define-key map (kbd "") 'ivy-scroll-down-command) + (define-key map (kbd "C-v") 'ivy-scroll-up-command) + (define-key map (kbd "M-v") 'ivy-scroll-down-command) + (define-key map (kbd "C-M-n") 'ivy-next-line-and-call) + (define-key map (kbd "C-M-p") 'ivy-previous-line-and-call) + (define-key map (kbd "M-r") 'ivy-toggle-regexp-quote) + (define-key map (kbd "M-j") 'ivy-yank-word) + (define-key map (kbd "M-i") 'ivy-insert-current) + (define-key map (kbd "C-M-y") 'ivy-insert-current-full) + (define-key map (kbd "C-o") 'hydra-ivy/body) + (define-key map (kbd "M-o") 'ivy-dispatching-done) + (define-key map (kbd "C-M-o") 'ivy-dispatching-call) + (define-key map [remap kill-line] 'ivy-kill-line) + (define-key map [remap kill-whole-line] 'ivy-kill-whole-line) + (define-key map (kbd "S-SPC") 'ivy-restrict-to-matches) + (define-key map [remap kill-ring-save] 'ivy-kill-ring-save) + (define-key map (kbd "C-'") 'ivy-avy) + (define-key map (kbd "C-M-a") 'ivy-read-action) + (define-key map (kbd "C-c C-o") 'ivy-occur) + (define-key map (kbd "C-c C-a") 'ivy-toggle-ignore) + (define-key map (kbd "C-c C-s") 'ivy-rotate-sort) + (define-key map [remap describe-mode] 'ivy-help) + (define-key map "$" 'ivy-magic-read-file-env) + map) + "Keymap used in the minibuffer.") +(autoload 'hydra-ivy/body "ivy-hydra" "" t) + +(defvar ivy-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap switch-to-buffer] + 'ivy-switch-buffer) + (define-key map [remap switch-to-buffer-other-window] + 'ivy-switch-buffer-other-window) + map) + "Keymap for `ivy-mode'.") + +;;* Globals +(cl-defstruct ivy-state + prompt collection + predicate require-match initial-input + history preselect keymap update-fn sort + ;; The frame in which `ivy-read' was called + frame + ;; The window in which `ivy-read' was called + window + ;; The buffer in which `ivy-read' was called + buffer + ;; The value of `ivy-text' to be used by `ivy-occur' + text + action + unwind + re-builder + matcher + ;; When this is non-nil, call it for each input change to get new candidates + dynamic-collection + ;; A lambda that transforms candidates only for display + display-transformer-fn + directory + caller + current + def + ignore + multi-action + extra-props) + +(defvar ivy-last (make-ivy-state) + "The last parameters passed to `ivy-read'. + +This should eventually become a stack so that you could use +`ivy-read' recursively.") + +(defvar ivy-recursive-last nil) + +(defvar ivy-recursive-restore t + "When non-nil, restore the above state when exiting the minibuffer. +This variable is let-bound to nil by functions that take care of +the restoring themselves.") + +(defsubst ivy-set-action (action) + "Set the current `ivy-last' field to ACTION." + (setf (ivy-state-action ivy-last) action)) + +(defvar inhibit-message) + +(defun ivy-thing-at-point () + "Return a string that corresponds to the current thing at point." + (substring-no-properties + (cond + ((use-region-p) + (let* ((beg (region-beginning)) + (end (region-end)) + (eol (save-excursion (goto-char beg) (line-end-position)))) + (buffer-substring-no-properties beg (min end eol)))) + ((thing-at-point 'url)) + ((and (eq (ivy-state-collection ivy-last) #'read-file-name-internal) + (let ((inhibit-message t)) + (run-hook-with-args-until-success 'file-name-at-point-functions)))) + ((let ((s (thing-at-point 'symbol))) + (and (stringp s) + (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s) + (match-string 1 s) + s)))) + ((looking-at "(+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>") + (match-string-no-properties 1)) + (t + "")))) + +(defvar ivy-history nil + "History list of candidates entered in the minibuffer. + +Maximum length of the history list is determined by the value +of `history-length'.") + +(defvar ivy--directory nil + "Current directory when completing file names.") + +(defvar ivy--length 0 + "Store the amount of viable candidates.") + +(defvar ivy-text "" + "Store the user's string as it is typed in.") + +(defvar ivy--index 0 + "Store the index of the current candidate.") + +(defvar ivy--window-index 0 + "Store the index of the current candidate in the minibuffer window. + +This means it's between 0 and `ivy-height'.") + +(defvar ivy-exit nil + "Store `done' if the completion was successfully selected. +Otherwise, store nil.") + +(defvar ivy--all-candidates nil + "Store the candidates passed to `ivy-read'.") + +(defvar ivy--extra-candidates '((original-source)) + "Store candidates added by the extra sources. + +This is an internal-use alist. Each key is a function name, or +original-source (which represents where the current dynamic +candidates should go). + +Each value is an evaluation of the function, in case of static +sources. These values will subsequently be filtered on `ivy-text'. + +This variable is set by `ivy-read' and used by `ivy--set-candidates'.") + +(defcustom ivy-use-ignore-default t + "The default policy for user-configured candidate filtering." + :type '(choice + (const :tag "Ignore ignored always" always) + (const :tag "Ignore ignored when others exist" t) + (const :tag "Don't ignore" nil))) + +(defvar ivy-use-ignore t + "Store policy for user-configured candidate filtering. +This may be changed dynamically by `ivy-toggle-ignore'. +Use `ivy-use-ignore-default' for a permanent configuration.") + +(defvar ivy--default nil + "Default initial input.") + +(defvar ivy--prompt nil + "Store the format-style prompt. +When non-nil, it should contain at least one %d.") + +(defvar ivy--prompt-extra "" + "Temporary modifications to the prompt.") + +(defvar ivy--old-re nil + "Store the old regexp. +Either a string or a list for `ivy-re-match'.") + +(defvar ivy--old-cands nil + "Store the candidates matched by `ivy--old-re'.") + +(defvar ivy--regex-function 'ivy--regex + "Current function for building a regex.") + +(defvar ivy--highlight-function 'ivy--highlight-default + "Current function for formatting the candidates.") + +(defvar ivy--subexps 0 + "Number of groups in the current `ivy--regex'.") + +(defvar ivy--full-length nil + "The total amount of candidates when :dynamic-collection is non-nil.") + +(defvar ivy--old-text "" + "Store old `ivy-text' for dynamic completion.") + +(defvar ivy--trying-to-resume-dynamic-collection nil + "Non-nil if resuming from a dynamic collection. +When non-nil, ivy will wait until the first chunk of asynchronous +candidates has been received before selecting the last +preselected candidate.") + +(defun ivy--set-index-dynamic-collection () + (when ivy--trying-to-resume-dynamic-collection + (let ((preselect-index + (ivy--preselect-index (ivy-state-preselect ivy-last) ivy--all-candidates))) + (when preselect-index + (ivy-set-index preselect-index))) + (setq ivy--trying-to-resume-dynamic-collection nil))) + +(defcustom ivy-case-fold-search-default + (if search-upper-case + 'auto + case-fold-search) + "The default value for `case-fold-search' in Ivy operations. +The special value `auto' means case folding is performed so long +as the entire input string comprises lower-case characters. This +corresponds to the default behaviour of most Emacs search +functionality, e.g. as seen in `isearch'." + :link '(info-link "(emacs)Lax Search") + :type '(choice + (const :tag "Auto" auto) + (const :tag "Always" t) + (const :tag "Never" nil))) + +(defvar ivy-case-fold-search ivy-case-fold-search-default + "Store the current overriding `case-fold-search'.") + +(defvar ivy-more-chars-alist + '((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.") + +(defun ivy-more-chars () + "Return two fake candidates prompting for at least N input. +N is obtained from `ivy-more-chars-alist'." + (let ((diff (- (ivy-alist-setting ivy-more-chars-alist) + (length ivy-text)))) + (when (> diff 0) + (list "" (format "%d chars more" diff))))) + +(defun ivy--case-fold-p (string) + "Return nil if STRING should be matched case-sensitively." + (if (eq ivy-case-fold-search 'auto) + (string= string (downcase string)) + ivy-case-fold-search)) + +(defun ivy--case-fold-string= (s1 s2) + "Like `string=', but obeys `case-fold-search'." + (eq t (compare-strings s1 nil nil s2 nil nil case-fold-search))) + +(eval-and-compile + (unless (fboundp 'defvar-local) + (defmacro defvar-local (var val &optional docstring) + "Define VAR as a buffer-local variable with default value VAL." + (declare (debug defvar) (doc-string 3)) + (list 'progn (list 'defvar var val docstring) + (list 'make-variable-buffer-local (list 'quote var))))) + (unless (fboundp 'setq-local) + (defmacro setq-local (var val) + "Set variable VAR to value VAL in current buffer." + (list 'set (list 'make-local-variable (list 'quote var)) val)))) + +(defmacro ivy-quit-and-run (&rest body) + "Quit the minibuffer and run BODY afterwards." + (declare (indent 0)) + `(progn + (put 'quit 'error-message "") + (run-at-time nil nil + (lambda () + (put 'quit 'error-message "Quit") + (with-demoted-errors "Error: %S" + ,@body))) + (abort-recursive-edit))) + +(defun ivy-exit-with-action (action) + "Quit the minibuffer and call ACTION afterwards." + (ivy-set-action + `(lambda (x) + (funcall ',action x) + (ivy-set-action ',(ivy-state-action ivy-last)))) + (setq ivy-exit 'done) + (exit-minibuffer)) + +(defmacro with-ivy-window (&rest body) + "Execute BODY in the window from which `ivy-read' was called." + (declare (indent 0) + (debug t)) + `(with-selected-window (ivy--get-window ivy-last) + ,@body)) + +(defun ivy--done (text) + "Insert TEXT and exit minibuffer." + (if (member (ivy-state-prompt ivy-last) '("Create directory: " "Make directory: ")) + (ivy-immediate-done) + (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))) + +(defcustom ivy-use-selectable-prompt nil + "When non-nil, make the prompt line selectable like a candidate. + +The prompt line can be selected by calling `ivy-previous-line' when the first +regular candidate is selected. Both actions `ivy-done' and `ivy-alt-done', +when called on a selected prompt, are forwarded to `ivy-immediate-done', which +results to the same as calling `ivy-immediate-done' explicitly when a regular +candidate is selected. + +Note that if `ivy-wrap' is set to t, calling `ivy-previous-line' when the +prompt is selected wraps around to the last candidate, while calling +`ivy-next-line' on the last candidate wraps around to the first +candidate, not the prompt." + :type 'boolean) + +(defvar ivy--use-selectable-prompt nil + "Store the effective `ivy-use-selectable-prompt' for current session.") + +(defun ivy--prompt-selectable-p () + "Return t if the prompt line is selectable." + (and ivy-use-selectable-prompt + (or (memq (ivy-state-require-match ivy-last) + '(nil confirm confirm-after-completion)) + ;; :require-match is t, but "" is in the collection + (let ((coll (ivy-state-collection ivy-last))) + (and (listp coll) + (if (consp (car coll)) + (member '("") coll) + (member "" coll))))))) + +(defun ivy--prompt-selected-p () + "Return t if the prompt line is selected." + (and ivy--use-selectable-prompt + (= ivy--index -1))) + +;;* Commands +(defun ivy-done () + "Exit the minibuffer with the selected candidate." + (interactive) + (if (ivy--prompt-selected-p) + (ivy-immediate-done) + (setq ivy-current-prefix-arg current-prefix-arg) + (delete-minibuffer-contents) + (cond ((or (> ivy--length 0) + ;; the action from `ivy-dispatching-done' may not need a + ;; candidate at all + (eq this-command 'ivy-dispatching-done)) + (ivy--done (ivy-state-current ivy-last))) + ((memq (ivy-state-collection ivy-last) + '(read-file-name-internal internal-complete-buffer)) + (if (or (not (eq confirm-nonexistent-file-or-buffer t)) + (equal " (confirm)" ivy--prompt-extra)) + (ivy--done ivy-text) + (setq ivy--prompt-extra " (confirm)") + (insert ivy-text) + (ivy--exhibit))) + ((memq (ivy-state-require-match ivy-last) + '(nil confirm confirm-after-completion)) + (ivy--done ivy-text)) + (t + (setq ivy--prompt-extra " (match required)") + (insert ivy-text) + (ivy--exhibit))))) + +(defvar ivy-mouse-1-tooltip + "Exit the minibuffer with the selected candidate." + "The doc visible in the tooltip for mouse-1 binding in the minibuffer") +(defvar ivy-mouse-3-tooltip + "Display alternative actions." + "The doc visible in the tooltip for mouse-3 binding in the minibuffer") + +(defun ivy-mouse-offset (event) + "Compute the offset between the candidate at point and the selected one." + (if event + (let* ((line-number-at-point + (max 2 + (line-number-at-pos (posn-point (event-start event))))) + + (line-number-candidate ;; convert to 0 based index + (- line-number-at-point 2)) + (offset + (- line-number-candidate + ivy--window-index))) + offset) + nil)) + +(defun ivy-mouse-done (event) + (interactive "@e") + (let ((offset (ivy-mouse-offset event))) + (when offset + (ivy-next-line offset) + (ivy--exhibit) + (ivy-alt-done)))) + +(defun ivy-mouse-dispatching-done (event) + (interactive "@e") + (let ((offset (ivy-mouse-offset event))) + (when offset + (ivy-next-line offset) + (ivy--exhibit) + (ivy-dispatching-done)))) + +(defvar ivy-read-action-format-function 'ivy-read-action-format-default + "Function used to transform the actions list into a docstring.") + +(defun ivy-read-action-format-default (actions) + "Create a docstring from ACTIONS. + +ACTIONS is a list. Each list item is a list of 3 items: +key (a string), cmd and doc (a string)." + (format "%s\n%s\n" + (if (eq this-command 'ivy-read-action) + "Select action: " + (ivy-state-current ivy-last)) + (mapconcat + (lambda (x) + (format "%s: %s" + (propertize + (car x) + 'face 'ivy-action) + (nth 2 x))) + 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. + +Return nil for `minibuffer-keyboard-quit' or wrong key during the +selection, non-nil otherwise." + (interactive) + (let ((actions (ivy-state-action ivy-last))) + (if (not (ivy--actionp actions)) + t + (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." + (window-resize nil (- ivy-height (window-height)))) + +(defun ivy-dispatching-done () + "Select one of the available actions and call `ivy-done'." + (interactive) + (when (ivy-read-action) + (ivy-done)) + (ivy-shrink-after-dispatching)) + +(defun ivy-dispatching-call () + "Select one of the available actions and call `ivy-call'." + (interactive) + (setq ivy-current-prefix-arg current-prefix-arg) + (let ((actions (copy-sequence (ivy-state-action ivy-last)))) + (unwind-protect + (when (ivy-read-action) + (ivy-call)) + (ivy-set-action actions))) + (ivy-shrink-after-dispatching)) + +(defun ivy-build-tramp-name (x) + "Reconstruct X into a path. +Is is a cons cell, related to `tramp-get-completion-function'." + (let ((user (car x)) + (domain (cadr x))) + (if user + (concat user "@" domain) + domain))) + +(declare-function Info-find-node "info") +(declare-function Info-read-node-name-1 "info") +(declare-function tramp-get-completion-function "tramp") + +(defun ivy-alt-done (&optional arg) + "Exit the minibuffer with the selected candidate. +When ARG is t, exit with current text, ignoring the candidates. +When the current candidate during file name completion is a +directory, continue completion from within that directory instead +of exiting. This function is otherwise like `ivy-done'." + (interactive "P") + (setq ivy-current-prefix-arg current-prefix-arg) + (cond ((or arg + (ivy--prompt-selected-p)) + (ivy-immediate-done)) + (ivy--directory + (ivy--directory-done)) + ((eq (ivy-state-collection ivy-last) #'Info-read-node-name-1) + (if (member (ivy-state-current ivy-last) '("(./)" "(../)")) + (ivy-quit-and-run + (ivy-read "Go to file: " #'read-file-name-internal + :action (lambda (x) + (Info-find-node + (expand-file-name x ivy--directory) + "Top")))) + (ivy-done))) + (t + (ivy-done)))) + +(defvar ivy-auto-select-single-candidate nil + "When non-nil, auto-select the candidate if it is the only one. +When t, it is the same as if the user were prompted and selected the candidate +by calling the default action. This variable has no use unless the collection +contains a single candidate.") + +(defun ivy--directory-enter () + (let (dir) + (when (and + (> ivy--length 0) + (not (string= (ivy-state-current ivy-last) "./")) + (setq dir (ivy-expand-file-if-directory (ivy-state-current ivy-last)))) + (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 (ivy--handle-directory ivy-text))) + (cond + (dir + (let ((inhibit-message t)) + (ivy--cd dir))) + ((ivy--directory-enter)) + ((unless (string= ivy-text "") + (let ((file (expand-file-name + (if (> ivy--length 0) (ivy-state-current ivy-last) ivy-text) + ivy--directory))) + (when (ignore-errors (file-exists-p file)) + (if (file-directory-p file) + (ivy--cd (file-name-as-directory file)) + (ivy-done)) + ivy-text)))) + ((or (and (equal ivy--directory "/") + (string-match-p "\\`[^/]+:.*:.*\\'" ivy-text)) + (string-match-p "\\`/[^/]+:.*:.*\\'" ivy-text)) + (ivy-done)) + ((or (and (equal ivy--directory "/") + (cond ((string-match + "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'" + ivy-text) + (setq ivy-text (ivy-state-current ivy-last))) + ((string-match + "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'" + (ivy-state-current ivy-last)) + (setq ivy-text (ivy-state-current ivy-last))))) + (string-match + "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'" + ivy-text)) + (let ((method (match-string 1 ivy-text)) + (user (match-string 2 ivy-text)) + (rest (match-string 3 ivy-text)) + res) + (dolist (x (tramp-get-completion-function method)) + (setq res (append res (funcall (car x) (cadr x))))) + (setq res (delq nil res)) + (when user + (dolist (x res) + (setcar x user))) + (setq res (delete-dups res)) + (let* ((old-ivy-last ivy-last) + (enable-recursive-minibuffers t) + (host (let ((ivy-auto-select-single-candidate nil)) + (ivy-read "user@host: " + (mapcar #'ivy-build-tramp-name res) + :initial-input rest)))) + (setq ivy-last old-ivy-last) + (when host + (setq ivy--directory "/") + (ivy--cd (concat "/" method ":" host ":")))))) + (t + (ivy-done))))) + +(defun ivy-expand-file-if-directory (file-name) + "Expand FILE-NAME as directory. +When this directory doesn't exist, return nil." + (when (stringp file-name) + (let ((full-name + ;; Ignore host name must not match method "ssh" + (ignore-errors + (file-name-as-directory + (expand-file-name file-name ivy--directory))))) + (when (and full-name (file-directory-p full-name)) + full-name)))) + +(defcustom ivy-tab-space nil + "When non-nil, `ivy-partial-or-done' should insert a space." + :type 'boolean) + +(defun ivy-partial-or-done () + "Complete the minibuffer text as much as possible. +If the text hasn't changed as a result, forward to `ivy-alt-done'." + (interactive) + (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'." + (if (string-prefix-p prefix string) + (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 (ivy--split-spaces ivy-text) (list ""))) + (tail (last parts)) + (postfix (car tail)) + (case-fold-search (ivy--case-fold-p ivy-text)) + (completion-ignore-case case-fold-search) + (new (try-completion (ivy--remove-prefix "^" postfix) + (if (ivy-state-dynamic-collection ivy-last) + ivy--all-candidates + (mapcar (lambda (str) + (let ((i (string-match-p postfix str))) + (and i (substring str i)))) + ivy--old-cands))))) + (cond ((eq new t) nil) + ((string= new ivy-text) nil) + ((string= (car tail) (car (ivy--split-spaces new))) nil) + (new + (delete-region (minibuffer-prompt-end) (point-max)) + (setcar tail + (if (= (string-to-char postfix) ?^) + (concat "^" new) + new)) + (insert + (setq ivy-text + (concat + (mapconcat #'identity parts " ") + (and ivy-tab-space (not (= (length ivy--old-cands) 1)) " ")))) + (ivy--partial-cd-for-single-directory) + t)))) + +(defvar ivy-completion-beg nil + "Completion bounds start.") + +(defvar ivy-completion-end nil + "Completion bounds end.") + +(defun ivy-immediate-done () + "Exit the minibuffer with current input instead of current candidate." + (interactive) + (delete-minibuffer-contents) + (setf (ivy-state-current ivy-last) + (cond ((or (not ivy--directory) + (eq (ivy-state-history ivy-last) 'grep-files-history)) + ivy-text) + ((and (string= ivy-text "") + (eq (ivy-state-collection ivy-last) + #'read-file-name-internal)) + (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)) + (setq ivy-completion-beg ivy-completion-end) + (setq ivy-exit 'done) + (exit-minibuffer)) + +;;;###autoload +(defun ivy-resume () + "Resume the last completion session." + (interactive) + (if (null (ivy-state-action ivy-last)) + (user-error "The last session isn't compatible with `ivy-resume'") + (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)) + (ivy-use-ignore-default (ivy-state-ignore ivy-last))) + (ivy-read + (ivy-state-prompt ivy-last) + (ivy-state-collection ivy-last) + :predicate (ivy-state-predicate ivy-last) + :require-match (ivy-state-require-match ivy-last) + :initial-input ivy-text + :history (ivy-state-history ivy-last) + :preselect (ivy-state-current ivy-last) + :keymap (ivy-state-keymap ivy-last) + :update-fn (ivy-state-update-fn ivy-last) + :sort (ivy-state-sort ivy-last) + :action (ivy-state-action ivy-last) + :unwind (ivy-state-unwind ivy-last) + :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 + "When non-nil, call the current action when `ivy--index' changes.") + +(defun ivy-set-index (index) + "Set `ivy--index' to INDEX." + (setq ivy--index index) + (when ivy-calling + (ivy--exhibit) + (ivy-call))) + +(defun ivy-beginning-of-buffer () + "Select the first completion candidate." + (interactive) + (ivy-set-index 0)) + +(defun ivy-end-of-buffer () + "Select the last completion candidate." + (interactive) + (ivy-set-index (1- ivy--length))) + +(defun ivy-scroll-up-command () + "Scroll the candidates upward by the minibuffer height." + (interactive) + (ivy-set-index (min (1- (+ ivy--index ivy-height)) + (1- ivy--length)))) + +(defun ivy-scroll-down-command () + "Scroll the candidates downward by the minibuffer height." + (interactive) + (ivy-set-index (max (1+ (- ivy--index ivy-height)) + 0))) + +(defun ivy-minibuffer-grow () + "Grow the minibuffer window by 1 line." + (interactive) + (setq-local max-mini-window-height + (cl-incf ivy-height))) + +(defun ivy-minibuffer-shrink () + "Shrink the minibuffer window by 1 line." + (interactive) + (when (> ivy-height 2) + (setq-local max-mini-window-height + (cl-decf ivy-height)) + (window-resize nil -1))) + +(defun ivy-next-line (&optional arg) + "Move cursor vertically down ARG candidates." + (interactive "p") + (setq arg (or arg 1)) + (let ((index (+ ivy--index arg))) + (if (> index (1- ivy--length)) + (if ivy-wrap + (ivy-beginning-of-buffer) + (ivy-set-index (1- ivy--length))) + (ivy-set-index index)))) + +(defun ivy-next-line-or-history (&optional arg) + "Move cursor vertically down ARG candidates. +If the input is empty, select the previous history element instead." + (interactive "p") + (if (string= ivy-text "") + (ivy-previous-history-element 1) + (ivy-next-line arg))) + +(defun ivy-previous-line (&optional arg) + "Move cursor vertically up ARG candidates." + (interactive "p") + (setq arg (or arg 1)) + (let ((index (- ivy--index arg)) + (min-index (if ivy--use-selectable-prompt -1 0))) + (if (< index min-index) + (if ivy-wrap + (ivy-end-of-buffer) + (ivy-set-index min-index)) + (ivy-set-index index)))) + +(defun ivy-previous-line-or-history (arg) + "Move cursor vertically up ARG candidates. +If the input is empty, select the previous history element instead." + (interactive "p") + (when (string= ivy-text "") + (ivy-previous-history-element 1)) + (ivy-previous-line arg)) + +(defun ivy-toggle-calling () + "Flip `ivy-calling'." + (interactive) + (when (setq ivy-calling (not ivy-calling)) + (ivy-call))) + +(defun ivy-toggle-ignore () + "Toggle user-configured candidate filtering." + (interactive) + (setq ivy-use-ignore + (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)) + +(defun ivy--get-action (state) + "Get the action function from STATE." + (let ((action (ivy-state-action state))) + (when action + (if (functionp action) + action + (cadr (nth (car action) action)))))) + +(defun ivy--get-window (state) + "Get the window from STATE." + (if (ivy-state-p state) + (let ((window (ivy-state-window state))) + (if (window-live-p window) + window + (next-window))) + (selected-window))) + +(defun ivy--actionp (x) + "Return non-nil when X is a list of actions." + (and (consp x) (not (memq (car x) '(closure lambda))))) + +(defcustom ivy-action-wrap nil + "When non-nil, `ivy-next-action' and `ivy-prev-action' wrap." + :type 'boolean) + +(defun ivy-next-action () + "When the current action is a list, scroll it forwards." + (interactive) + (let ((action (ivy-state-action ivy-last))) + (when (ivy--actionp action) + (let ((len (1- (length action))) + (idx (car action))) + (if (>= idx len) + (when ivy-action-wrap + (setf (car action) 1)) + (cl-incf (car action))))))) + +(defun ivy-prev-action () + "When the current action is a list, scroll it backwards." + (interactive) + (let ((action (ivy-state-action ivy-last))) + (when (ivy--actionp action) + (if (<= (car action) 1) + (when ivy-action-wrap + (setf (car action) (1- (length action)))) + (cl-decf (car action)))))) + +(defun ivy-action-name () + "Return the name associated with the current action." + (let ((action (ivy-state-action ivy-last))) + (if (ivy--actionp action) + (format "[%d/%d] %s" + (car action) + (1- (length action)) + (nth 2 (nth (car action) action))) + "[1/1] default"))) + +(defvar ivy-inhibit-action nil + "When non-nil, `ivy-call' does nothing. + +Example use: + + (let* ((ivy-inhibit-action t) + (str (ivy-switch-buffer))) + ;; do whatever with str - the corresponding buffer will not be opened + )") + +(defun ivy-recursive-restore () + "Restore the above state when exiting the minibuffer. +See variable `ivy-recursive-restore' for further information." + (when (and ivy-recursive-last + ivy-recursive-restore + (not (eq ivy-last ivy-recursive-last))) + (ivy--reset-state (setq ivy-last ivy-recursive-last)))) + +(defvar ivy-marked-candidates nil + "List of marked candidates. +Use `ivy-mark' to populate this. + +When this list is non-nil at the end of the session, the action +will be called for each element of this list.") + +(defvar ivy-mark-prefix ">" + "Prefix used by `ivy-mark'.") + +(defun ivy-call () + "Call the current action without exiting completion." + (interactive) + ;; Testing with `ivy-with' seems to call `ivy-call' again, + ;; in which case `this-command' is nil; so check for this. + (unless (memq this-command '(nil + ivy-done + ivy-alt-done + ivy-dispatching-done)) + (setq ivy-current-prefix-arg current-prefix-arg)) + (let ((action + (if (functionp ivy-inhibit-action) + ivy-inhibit-action + (and (not ivy-inhibit-action) + (ivy--get-action ivy-last))))) + (when action + (let* ((collection (ivy-state-collection ivy-last)) + (current (ivy-state-current ivy-last)) + (x (cond + ;; Alist type. + ((and (consp (car-safe collection)) + ;; Previously, the cdr of the selected + ;; candidate would be returned. Now, the + ;; whole candidate is returned. + (let ((idx (get-text-property 0 'idx current))) + (if idx + (nth idx collection) + (assoc current collection))))) + (ivy--directory + (expand-file-name current ivy--directory)) + ((equal current "") + ivy-text) + (t + current)))) + (if (eq action #'identity) + (prog1 x + (ivy-recursive-restore)) + (select-window (ivy--get-window ivy-last)) + (set-buffer (ivy-state-buffer ivy-last)) + (prog1 (unwind-protect + (if ivy-marked-candidates + (let ((prefix-len (length ivy-mark-prefix))) + (setq ivy-marked-candidates + (mapcar (lambda (s) (substring s prefix-len)) + ivy-marked-candidates)) + (if (ivy-state-multi-action ivy-last) + (funcall + (ivy-state-multi-action ivy-last) + ivy-marked-candidates) + (dolist (c ivy-marked-candidates) + (let ((default-directory (ivy-state-directory ivy-last))) + (funcall action c))))) + (funcall action x)) + (ivy-recursive-restore)) + (unless (or (eq ivy-exit 'done) + (minibuffer-window-active-p (selected-window)) + (null (active-minibuffer-window))) + (select-window (active-minibuffer-window))))))))) + +(defun ivy-call-and-recenter () + "Call action and recenter window according to the selected candidate." + (interactive) + (ivy-call) + (with-ivy-window + (recenter-top-bottom))) + +(defun ivy-next-line-and-call (&optional arg) + "Move cursor vertically down ARG candidates. +Call the permanent action if possible." + (interactive "p") + (ivy-next-line arg) + (ivy--exhibit) + (ivy-call)) + +(defun ivy-previous-line-and-call (&optional arg) + "Move cursor vertically up ARG candidates. +Call the permanent action if possible." + (interactive "p") + (ivy-previous-line arg) + (ivy--exhibit) + (ivy-call)) + +(defun ivy-previous-history-element (arg) + "Forward to `previous-history-element' with ARG." + (interactive "p") + (previous-history-element arg) + (ivy--cd-maybe) + (move-end-of-line 1) + (ivy--maybe-scroll-history)) + +(defun ivy--insert-symbol-boundaries () + (undo-boundary) + (beginning-of-line) + (insert "\\_<") + (end-of-line) + (insert "\\_>")) + +(defun ivy-next-history-element (arg) + "Forward to `next-history-element' with ARG." + (interactive "p") + (if (and (= minibuffer-history-position 0) + (equal ivy-text "")) + (progn + (when minibuffer-default + (setq ivy--default (car minibuffer-default))) + (insert ivy--default) + (when (and (with-ivy-window (derived-mode-p 'prog-mode)) + (eq (ivy-state-caller ivy-last) 'swiper) + (not (file-exists-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))) + (next-history-element arg)) + (ivy--cd-maybe) + (move-end-of-line 1) + (ivy--maybe-scroll-history)) + +(defvar ivy-ffap-url-functions nil + "List of functions that check if the point is on a URL.") + +(defun ivy--cd-maybe () + "Check if the current input points to a different directory. +If so, move to that directory, while keeping only the file name." + (when ivy--directory + (let ((input (ivy--input)) + url) + (if (setq url (or (ivy-ffap-url-p input) + (with-ivy-window + (cl-reduce + (lambda (a b) + (or a (funcall b))) + ivy-ffap-url-functions + :initial-value nil)))) + (ivy-exit-with-action + (lambda (_) + (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)))) + (if (string= dir ivy--directory) + (progn + (delete-minibuffer-contents) + (insert file)) + (ivy--cd dir) + (insert file))))))) + +(defun ivy--maybe-scroll-history () + "If the selected history element has an index, scroll there." + (let ((idx (ignore-errors + (get-text-property + (minibuffer-prompt-end) + 'ivy-index)))) + (when idx + (ivy--exhibit) + (ivy-set-index idx)))) + +(declare-function tramp-get-completion-methods "tramp") + +(defun ivy--cd (dir) + "When completing file names, move to directory DIR." + (if (null ivy--directory) + (error "Unexpected") + (setq ivy--old-cands nil) + (setq ivy--old-re nil) + (ivy-set-index 0) + (setq ivy--all-candidates + (append + (ivy--sorted-files (setq ivy--directory dir)) + (when (and (string= dir "/") (featurep 'tramp)) + (sort + (mapcar + (lambda (s) (substring s 1)) + (tramp-get-completion-methods "")) + #'string<)))) + (setq ivy-text "") + (setf (ivy-state-directory ivy-last) dir) + (delete-minibuffer-contents))) + +(defun ivy--parent-dir (filename) + "Return parent directory of absolute FILENAME." + (file-name-directory (directory-file-name filename))) + +(defun ivy-backward-delete-char () + "Forward to `delete-backward-char'. +Call `ivy-on-del-error-function' if an error occurs, usually when +there is no more text to delete at the beginning of the +minibuffer." + (interactive) + (if (and ivy--directory (= (minibuffer-prompt-end) (point))) + (progn + (ivy--cd (ivy--parent-dir (expand-file-name ivy--directory))) + (ivy--exhibit)) + (setq prefix-arg current-prefix-arg) + (condition-case nil + (call-interactively #'delete-backward-char) + (error + (when ivy-on-del-error-function + (funcall ivy-on-del-error-function)))))) + +(defun ivy-delete-char (arg) + "Forward to `delete-char' ARG." + (interactive "p") + (unless (eolp) + (delete-char arg))) + +(defun ivy-forward-char (arg) + "Forward to `forward-char' ARG." + (interactive "p") + (unless (eolp) + (forward-char arg))) + +(defun ivy-kill-word (arg) + "Forward to `kill-word' ARG." + (interactive "p") + (unless (eolp) + (kill-word arg))) + +(defun ivy-kill-line () + "Forward to `kill-line'." + (interactive) + (if (eolp) + (kill-region (minibuffer-prompt-end) (point)) + (kill-line))) + +(defun ivy-kill-whole-line () + "Forward to `kill-whole-line'." + (interactive) + (kill-region (minibuffer-prompt-end) (line-end-position))) + +(defun ivy-backward-kill-word () + "Forward to `backward-kill-word'." + (interactive) + (if (and ivy--directory (= (minibuffer-prompt-end) (point))) + (progn + (ivy--cd (ivy--parent-dir (expand-file-name ivy--directory))) + (ivy--exhibit)) + (ignore-errors + (let ((pt (point))) + (forward-word -1) + (delete-region (point) pt))))) + +(defvar ivy--regexp-quote #'regexp-quote + "Store the regexp quoting state.") + +(defun ivy-toggle-regexp-quote () + "Toggle the regexp quoting." + (interactive) + (setq ivy--old-re nil) + (cl-rotatef ivy--regex-function ivy--regexp-quote)) + +(defvar avy-all-windows) +(defvar avy-action) +(defvar avy-keys) +(defvar avy-keys-alist) +(defvar avy-style) +(defvar avy-styles-alist) +(declare-function avy-process "ext:avy") +(declare-function avy--style-fn "ext:avy") + +(defcustom ivy-format-functions-alist + '((t . ivy-format-function-default)) + "An alist of functions that transform the list of candidates into a string. +This string is inserted into the minibuffer." + :type '(alist + :key-type symbol + :value-type + (choice + (const :tag "Default" ivy-format-function-default) + (const :tag "Arrow prefix" ivy-format-function-arrow) + (const :tag "Full line" ivy-format-function-line) + (function :tag "Custom function")))) + +(eval-after-load 'avy + '(add-to-list 'avy-styles-alist '(ivy-avy . pre))) + +(defun ivy--avy-candidates () + (let (candidates) + (save-excursion + (save-restriction + (narrow-to-region + (window-start) + (window-end)) + (goto-char (point-min)) + (forward-line) + (while (< (point) (point-max)) + (push + (cons (point) + (selected-window)) + candidates) + (forward-line)))) + (nreverse candidates))) + +(defun ivy--avy-action (pt) + (when (number-or-marker-p pt) + (let ((bnd (ivy--minibuffer-index-bounds + ivy--index ivy--length ivy-height))) + (ivy--done + (substring-no-properties + (nth (+ (car bnd) (- (line-number-at-pos pt) 2)) ivy--old-cands)))))) + +(defun ivy--avy-handler-function (char) + (let (cmd) + (cond ((memq char '(27 ?\C-g)) + ;; exit silently + (throw 'done 'abort)) + ((memq (setq cmd (lookup-key ivy-minibuffer-map (vector char))) + '(ivy-scroll-up-command + ivy-scroll-down-command)) + (funcall cmd) + (ivy--exhibit) + (throw 'done 'exit)) + ;; ignore wrong key + (t + (throw 'done 'restart))))) + +(defvar avy-handler-function) + +(defun ivy-avy () + "Jump to one of the current ivy candidates." + (interactive) + (unless (require 'avy nil 'noerror) + (error "Package avy isn't installed")) + (let* ((avy-all-windows nil) + (avy-keys (or (cdr (assq 'ivy-avy avy-keys-alist)) + avy-keys)) + (avy-style (or (cdr (assq 'ivy-avy avy-styles-alist)) + avy-style)) + (avy-action #'identity) + (avy-handler-function #'ivy--avy-handler-function) + res) + (while (eq (setq res (avy-process (ivy--avy-candidates))) t)) + (when res + (ivy--avy-action res)))) + +(defun ivy-sort-file-function-default (x y) + "Compare two files X and Y. +Prioritize directories." + (if (get-text-property 0 'dirp x) + (if (get-text-property 0 'dirp y) + (string< (directory-file-name x) (directory-file-name y)) + t) + (if (get-text-property 0 'dirp y) + nil + (string< 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 + '((t . ivy-string<)) + "An alist of sorting functions for each collection function. +Interactive functions that call completion fit in here as well. + +Nil means no sorting, which is useful to turn off the sorting for +functions that have candidates in the natural buffer order, like +`org-refile' or `Man-goto-section'. + +A list can be used to associate multiple sorting functions with a +collection. The car of the list is the current sort +function. This list can be rotated with `ivy-rotate-sort'. + +The entry associated with t is used for all fall-through cases. + +See also `ivy-sort-max-size'." + :type + '(alist + :key-type (choice + (const :tag "Fall-through" t) + (symbol :tag "Collection")) + :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"))))) + +(defun ivy--sort-function (collection) + "Retrieve sort function for COLLECTION from `ivy-sort-functions-alist'." + (let ((entry (cdr (or (assq collection ivy-sort-functions-alist) + (assq (ivy-state-caller ivy-last) ivy-sort-functions-alist) + (assq t ivy-sort-functions-alist))))) + (and (or (functionp entry) + (functionp (setq entry (car-safe entry)))) + entry))) + +(defun ivy-rotate-sort () + "Rotate through sorting functions available for current collection. +This only has an effect if multiple sorting functions are +specified for the current collection in +`ivy-sort-functions-alist'." + (interactive) + (let ((cell (or (assq (ivy-state-collection ivy-last) ivy-sort-functions-alist) + (assq (ivy-state-caller ivy-last) ivy-sort-functions-alist)))) + (when (consp (cdr cell)) + (setcdr cell (nconc (cddr cell) (list (cadr cell)))) + (ivy--reset-state ivy-last)))) + +(defvar ivy-index-functions-alist + '((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 +selected.") + +(defvar ivy-re-builders-alist + '((t . ivy--regex-plus)) + "An alist of regex building functions for each collection function. + +Each key is (in order of priority): +1. The actual collection function, e.g. `read-file-name-internal'. +2. The symbol passed by :caller into `ivy-read'. +3. `this-command'. +4. t. + +Each value is a function that should take a string and return a +valid regex or a regex sequence (see below). + +Possible choices: `ivy--regex', `regexp-quote', +`ivy--regex-plus', `ivy--regex-fuzzy', `ivy--regex-ignore-order'. + +If a function returns a list, it should format like this: +'((\"matching-regexp\" . t) (\"non-matching-regexp\") ...). + +The matches will be filtered in a sequence, you can mix the +regexps that should match and that should not match as you +like.") + +(defvar ivy-highlight-functions-alist + '((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 builder function.") + +(defcustom ivy-initial-inputs-alist + '((org-refile . "^") + (org-agenda-refile . "^") + (org-capture-refile . "^") + (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)))) + +(defcustom ivy-hooks-alist nil + "An alist associating commands to setup functions. +Examples: `toggle-input-method', (lambda () (insert \"^\")), etc. +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) + +(defalias 'ivy--dirname-p + (if (fboundp 'directory-name-p) + #'directory-name-p + (lambda (name) + "Return non-nil if NAME ends with a directory separator." + (string-match-p "/\\'" name)))) + +(defun ivy--sorted-files (dir) + "Return the list of files in DIR. +Directories come first." + (let* ((default-directory dir) + (seq (condition-case nil + (mapcar (lambda (s) (replace-regexp-in-string "\\$\\$" "$" s)) + (all-completions "" #'read-file-name-internal + (ivy-state-predicate ivy-last))) + (error + (directory-files dir)))) + sort-fn) + (setq seq (delete "./" (delete "../" seq))) + (when (eq (setq sort-fn (ivy--sort-function #'read-file-name-internal)) + #'ivy-sort-file-function-default) + (setq seq (mapcar (lambda (x) + (propertize x 'dirp (ivy--dirname-p x))) + seq))) + (when sort-fn + (setq seq (sort seq sort-fn))) + (dolist (dir ivy-extra-directories) + (push dir seq)) + (if (string= dir "/") + (cl-remove-if (lambda (s) (string-match ":$" s)) (delete "../" seq)) + seq))) + +(defun ivy-alist-setting (alist &optional key) + "Return the value associated with KEY in ALIST, using `assq'. +KEY defaults to the last caller of `ivy-read'; if no entry is +found, it falls back to the key t." + (cdr (or (let ((caller (or key (ivy-state-caller ivy-last)))) + (and caller (assq caller alist))) + (assq t alist)))) + +(defun ivy--height (caller) + (let ((v (or (ivy-alist-setting ivy-height-alist caller) + ivy-height))) + (if (integerp v) + v + (if (functionp v) + (funcall v caller) + (error "Unexpected value: %S" v))))) + +(defun ivy--remove-props (str &rest props) + "Return STR with text PROPS destructively removed." + (ignore-errors + (remove-list-of-text-properties 0 (length str) props str)) + str) + +;;** Entry Point +;;;###autoload +(cl-defun ivy-read (prompt collection + &key + predicate require-match initial-input + history preselect def keymap update-fn sort + action multi-action + unwind re-builder matcher + 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. +`ivy-count-format' is prepended to PROMPT during completion. + +COLLECTION is either a list of strings, a function, an alist, or +a hash table, supplied for `minibuffer-completion-table'. + +PREDICATE is applied to filter out the COLLECTION immediately. +This argument is for compatibility with `completing-read'. + +When REQUIRE-MATCH is non-nil, only members of COLLECTION can be +selected. + +If INITIAL-INPUT is non-nil, then insert that input in the +minibuffer initially. + +HISTORY is a name of a variable to hold the completion session +history. + +KEYMAP is composed with `ivy-minibuffer-map'. + +PRESELECT, when non-nil, determines which one of the candidates +matching INITIAL-INPUT to select initially. An integer stands +for the position of the desired candidate in the collection, +counting from zero. Otherwise, use the first occurrence of +PRESELECT in the collection. Comparison is first done with +`equal'. If that fails, and when applicable, match PRESELECT as +a regular expression. + +DEF is for compatibility with `completing-read'. + +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 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 +its only argument. When it's nil, ACTION is called on each marked +candidate. + +UNWIND is a function of no arguments to call before exiting. + +RE-BUILDER is a function transforming input text into a regex +pattern. + +MATCHER is a function which can override how candidates are +filtered based on user input. It takes a regex pattern and a +list of candidates, and returns the list of matching candidates. + +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 + (when (or ivy-recursive-last + (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 + :collection collection + :predicate predicate + :require-match require-match + :initial-input initial-input + :history history + :preselect preselect + :keymap keymap + :update-fn (if (eq update-fn 'auto) + (lambda () + (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) + :multi-action multi-action + :frame (selected-frame) + :window (selected-window) + :buffer (current-buffer) + :unwind unwind + :re-builder re-builder + :matcher matcher + :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) + (unwind-protect + (minibuffer-with-setup-hook + #'ivy--minibuffer-setup + (let* ((hist (or history 'ivy-history)) + (minibuffer-completion-table collection) + (minibuffer-completion-predicate predicate) + (ivy-height (ivy--height caller)) + (resize-mini-windows (unless (display-graphic-p) + 'grow-only))) + (if (and ivy-auto-select-single-candidate + ivy--all-candidates + (null (cdr ivy--all-candidates))) + (progn + (setf (ivy-state-current ivy-last) + (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 + hist)) + (when (eq ivy-exit 'done) + (let ((item (if ivy--directory + (ivy-state-current ivy-last) + ivy-text))) + (unless (equal item "") + (set hist (cons (propertize item 'ivy-index ivy--index) + (delete item + (cdr (symbol-value hist)))))))) + (setq result (ivy-state-current ivy-last)))) + (ivy--cleanup)) + (ivy-call) + (ivy--remove-props (ivy-state-current ivy-last) 'idx) + result)) + +(defun ivy--cleanup () + ;; Fixes a bug in ESS, #1660 + (put 'post-command-hook 'permanent-local nil) + (remove-hook 'post-command-hook #'ivy--queue-exhibit) + (let ((cleanup (ivy--display-function-prop :cleanup)) + (unwind (ivy-state-unwind ivy-last))) + (when (functionp cleanup) + (funcall cleanup)) + (when unwind + (funcall unwind))) + (ivy--pulse-cleanup) + (unless (eq ivy-exit 'done) + (ivy-recursive-restore))) + +(defun ivy--display-function-prop (prop) + "Return PROP associated with current `ivy--display-function'." + (plist-get (cdr (assq ivy--display-function + ivy-display-functions-props)) + prop)) + +(defvar Info-complete-menu-buffer) + +(defun ivy--reset-state (state) + "Reset the ivy to STATE. +This is useful for recursive `ivy-read'." + (setq ivy-marked-candidates nil) + (unless (equal (selected-frame) (ivy-state-frame state)) + (select-window (active-minibuffer-window))) + (let* ((prompt (or (ivy-state-prompt state) "")) + (collection (ivy-state-collection state)) + (predicate (ivy-state-predicate state)) + (history (ivy-state-history state)) + (preselect (ivy-state-preselect state)) + (re-builder (ivy-state-re-builder state)) + (dynamic-collection (ivy-state-dynamic-collection state)) + (require-match (ivy-state-require-match state)) + (caller (or (ivy-state-caller state) this-command)) + (sort (or (ivy-state-sort state) (assoc caller ivy-sort-functions-alist))) + (initial-input + (or (ivy-state-initial-input state) + (let ((init (cdr (assq caller ivy-initial-inputs-alist)))) + (cond ((functionp init) + (funcall init)) + (t + init))))) + (def (ivy-state-def state))) + (setq ivy--extra-candidates (ivy--compute-extra-candidates caller)) + (setq ivy--directory nil) + (setq ivy-case-fold-search ivy-case-fold-search-default) + (setq ivy--regex-function + (or re-builder + (and (functionp collection) + (cdr (assq collection ivy-re-builders-alist))) + (ivy-alist-setting ivy-re-builders-alist) + #'ivy--regex)) + (setq ivy--subexps 0) + (setq ivy--regexp-quote #'regexp-quote) + (setq ivy--old-text "") + (setq ivy--full-length nil) + (setq ivy-text "") + (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)) + (let (coll sort-fn) + (cond ((eq collection #'Info-read-node-name-1) + (setq coll + (if (equal (bound-and-true-p Info-current-file) "dir") + (mapcar (lambda (x) (format "(%s)" x)) + (delete-dups + (all-completions "(" collection predicate))) + (all-completions "" collection predicate)))) + ((eq collection #'read-file-name-internal) + (require 'tramp) + (when (and (equal def initial-input) + (member "./" ivy-extra-directories)) + (setq def nil)) + (setq ivy--directory default-directory) + (when (and initial-input + (not (equal initial-input ""))) + (cond ((file-directory-p initial-input) + (when (equal (file-name-nondirectory initial-input) "") + (setf (ivy-state-preselect state) (setq preselect nil)) + (setq def nil)) + (setq ivy--directory (file-name-as-directory initial-input)) + (setq initial-input nil) + (when preselect + (let ((preselect-directory + (file-name-directory preselect))) + (when (and preselect-directory + (not (equal + (expand-file-name + preselect-directory) + (expand-file-name ivy--directory)))) + (setf (ivy-state-preselect state) + (setq preselect nil)))))) + ((ignore-errors + (file-exists-p (file-name-directory initial-input))) + (setq ivy--directory (file-name-directory initial-input)) + (setf (ivy-state-preselect state) + (file-name-nondirectory initial-input))))) + (require 'dired) + (when preselect + (let ((preselect-directory (ivy--parent-dir preselect))) + (when (and preselect-directory + (not (string= preselect-directory + default-directory))) + (setq ivy--directory preselect-directory)) + (setq preselect (file-relative-name preselect + preselect-directory)) + (setf (ivy-state-preselect state) preselect))) + (setq sort nil) + (setq coll (ivy--sorted-files ivy--directory)) + (when initial-input + (unless (or require-match + (equal initial-input default-directory) + (equal initial-input "")) + (setq coll (cons initial-input coll))) + (when (or (not (ivy-state-action ivy-last)) + (equal (ivy--get-action ivy-last) 'identity)) + (setq initial-input nil)))) + ((eq collection #'internal-complete-buffer) + (setq prompt + (replace-regexp-in-string "RET to end" "C-M-j to end" prompt)) + (setq coll (ivy--buffer-list + "" + (and ivy-use-virtual-buffers + (member caller '(ivy-switch-buffer + ivy-switch-buffer-other-window + counsel-switch-buffer))) + predicate))) + (dynamic-collection + (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))) + (setq collection (sort (copy-sequence collection) sort-fn)) + (setq sort nil)) + (setf (ivy-state-collection ivy-last) collection) + (setq coll (let ((i -1)) + (mapcar (lambda (x) + (propertize x 'idx (cl-incf i))) + (all-completions "" collection))))) + ((or (functionp collection) + (byte-code-function-p collection) + (vectorp collection) + (hash-table-p collection) + (and (listp collection) (symbolp (car collection)))) + (let ((Info-complete-menu-buffer + ;; FIXME: This is a temporary workaround for issue #1803. + (or (bound-and-true-p Info-complete-menu-buffer) + (ivy-state-buffer state)))) + (setq coll (all-completions "" collection predicate)))) + (t + (setq coll (all-completions "" collection predicate)))) + (unless (ivy-state-dynamic-collection ivy-last) + (setq coll (delete "" coll))) + (when def + (cond ((stringp (car-safe def)) + (setq coll (cl-union def coll :test #'equal))) + ((and (stringp def) (not (member def coll))) + (push def coll)))) + (when (and sort + (or (functionp collection) + (not (eq history 'org-refile-history))) + (setq sort-fn (ivy--sort-function + (if (functionp collection) collection caller))) + (null (nthcdr ivy-sort-max-size coll))) + (setq coll (sort (copy-sequence coll) sort-fn))) + (setq coll (ivy--set-candidates coll)) + (setq ivy--old-re nil) + (setq ivy--old-cands nil) + (when initial-input + ;; Needed for anchor to work + (setq ivy--old-cands coll) + (setq ivy--old-cands (ivy--filter initial-input coll))) + (unless (setq ivy--trying-to-resume-dynamic-collection + (and preselect dynamic-collection)) + (when (integerp preselect) + (setq ivy--old-re "") + (ivy-set-index preselect))) + (setq ivy--all-candidates coll) + (unless (integerp preselect) + (ivy-set-index (or + (and dynamic-collection + ivy--index) + (and preselect + (ivy--preselect-index + preselect + (if initial-input + ivy--old-cands + coll))) + 0)))) + (setq ivy-exit nil) + (setq ivy--default + (if (region-active-p) + (buffer-substring (region-beginning) (region-end)) + (ivy-thing-at-point))) + (setq ivy--prompt (ivy-add-prompt-count (ivy--quote-format-string prompt))) + (setq ivy--use-selectable-prompt (ivy--prompt-selectable-p)) + (setf (ivy-state-initial-input ivy-last) initial-input))) + +(defun ivy-add-prompt-count (prompt) + "Add count information to PROMPT." + (cond ((null ivy-count-format) + (error + "`ivy-count-format' can't be nil. Set it to \"\" instead")) + ((string-match "%d.*\\(%d\\)" ivy-count-format) + (let* ((w (1+ (floor (log (max 1 (length ivy--all-candidates)) 10)))) + (s (replace-match (format "%%-%dd" w) t t ivy-count-format 1))) + (string-match "%d" s) + (concat (replace-match (format "%%%dd" w) t t s) + prompt))) + ((string-match-p "%.*d" ivy-count-format) + (concat ivy-count-format prompt)) + (ivy--directory + prompt) + (t + prompt))) + +(defun ivy--quote-format-string (str) + "Make STR suitable for `format' with no extra arguments." + (replace-regexp-in-string "%" "%%" str t t)) + +;;;###autoload +(defun ivy-completing-read (prompt collection + &optional predicate require-match initial-input + history def inherit-input-method) + "Read a string in the minibuffer, with completion. + +This interface conforms to `completing-read' and can be used for +`completing-read-function'. + +PROMPT is a string that normally ends in a colon and a space. +COLLECTION is either a list of strings, an alist, an obarray, or a hash table. +PREDICATE limits completion to a subset of COLLECTION. +REQUIRE-MATCH is a boolean value. See `completing-read'. +INITIAL-INPUT is a string inserted into the minibuffer initially. +HISTORY is a list of previously selected inputs. +DEF is the default value. +INHERIT-INPUT-METHOD is currently ignored." + (let ((handler + (and (< ivy-completing-read-ignore-handlers-depth (minibuffer-depth)) + (assq this-command ivy-completing-read-handlers-alist)))) + (if handler + (let ((completion-in-region-function #'completion--in-region) + (ivy-completing-read-ignore-handlers-depth (1+ (minibuffer-depth)))) + (funcall (cdr handler) + prompt collection + predicate require-match + initial-input history + def inherit-input-method)) + ;; See the doc of `completing-read'. + (when (consp history) + (when (numberp (cdr history)) + (setq initial-input (nth (1- (cdr history)) + (symbol-value (car history))))) + (setq history (car history))) + (when (consp def) + (setq def (car def))) + (let ((str (ivy-read + prompt collection + :predicate predicate + :require-match (and collection require-match) + :initial-input (cond ((consp initial-input) + (car initial-input)) + ((and (stringp initial-input) + (not (eq collection #'read-file-name-internal)) + (string-match-p "\\+" initial-input)) + (replace-regexp-in-string + "\\+" "\\\\+" initial-input)) + (t + initial-input)) + :preselect def + :def def + :history history + :keymap nil + :dynamic-collection ivy-completing-read-dynamic-collection + :caller (if (and collection (symbolp collection)) + collection + this-command)))) + (if (string= str "") + ;; For `completing-read' compat, return the first element of + ;; DEFAULT, if it is a list; "", if DEFAULT is nil; or DEFAULT. + (or def "") + str))))) + +(defun ivy-completing-read-with-empty-string-def + (prompt collection + &optional predicate require-match initial-input + history def inherit-input-method) + "Same as `ivy-completing-read' but with different handling of DEF. + +Specifically, if DEF is nil, it is treated the same as if DEF was +the empty string. This mimics the behavior of +`completing-read-default'. This function can therefore be used in +place of `ivy-completing-read' for commands that rely on this +behavior." + (ivy-completing-read + 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 (require 'multiple-cursors-core nil t) + (mc/all-fake-cursors))) + (pt (point)) + (beg ivy-completion-beg) + (end ivy-completion-end)) + (when beg + (delete-region beg end)) + (setq ivy-completion-beg (point)) + (insert (substring-no-properties str)) + (completion--done str 'exact) + (setq ivy-completion-end (point)) + (save-excursion + (dolist (cursor fake-cursors) + (goto-char (overlay-start cursor)) + (delete-region (+ (point) (- beg pt)) + (+ (point) (- end pt))) + (insert (substring-no-properties str)) + ;; manually move the fake cursor + (move-overlay cursor (point) (1+ (point))) + (set-marker (overlay-get cursor 'point) (point)) + (set-marker (overlay-get cursor 'mark) (point))))))) + +(defun ivy-completion-common-length (str) + "Return the amount of characters that match in STR. + +`completion-all-completions' computes this and returns the result +via text properties. + +The first non-matching part is propertized: +- either with: (face (completions-first-difference)) +- or: (font-lock-face completions-first-difference)." + (let ((char-property-alias-alist '((face font-lock-face))) + (i (1- (length str)))) + (catch 'done + (while (>= i 0) + (when (equal (get-text-property i 'face str) + '(completions-first-difference)) + (throw 'done i)) + (cl-decf i)) + (throw 'done (length str))))) + +(defun ivy-completion-in-region (start end collection &optional predicate) + "An Ivy function suitable for `completion-in-region-function'. +The function completes the text between START and END using COLLECTION. +PREDICATE (a function called with no arguments) says when to exit. +See `completion-in-region' for further information." + (let* ((enable-recursive-minibuffers t) + (str (buffer-substring-no-properties start end)) + (completion-ignore-case (ivy--case-fold-p str)) + (comps + (completion-all-completions str collection predicate (- end start)))) + (cond ((null comps) + (message "No matches")) + ((progn + (nconc comps nil) + (and (null (cdr comps)) + (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) + "") + ((let ((str-len (length str))) + (when (> len str-len) + (setq len str-len) + str))) + (t + (substring str (- len)))))) + (setq ivy--old-re nil) + (unless (ivy--filter initial comps) + (setq initial nil)) + (delete-region (- end len) end) + (setq ivy-completion-beg (- end len)) + (setq ivy-completion-end ivy-completion-beg) + (if (null (cdr comps)) + (progn + (unless (minibuffer-window-active-p (selected-window)) + (setf (ivy-state-window ivy-last) (selected-window))) + (ivy-completion-in-region-action + (substring-no-properties (car comps)))) + (dolist (s comps) + ;; Remove face `completions-first-difference'. + (ivy--remove-props s 'face)) + (ivy-read (format "(%s): " str) comps + ;; Predicate was already applied by + ;; `completion-all-completions'. + :predicate nil + :initial-input initial + :action #'ivy-completion-in-region-action + :unwind (lambda () + (unless (eq ivy-exit 'done) + (goto-char ivy-completion-beg) + (when initial + (insert initial)))) + :caller 'ivy-completion-in-region) + t)))))) + +(defun ivy-completion-in-region-prompt () + "Prompt function for `ivy-completion-in-region'. +See `ivy-set-prompt'." + (and (window-minibuffer-p (ivy-state-window ivy-last)) + (ivy-add-prompt-count (ivy-state-prompt ivy-last)))) + +(ivy-set-prompt #'ivy-completion-in-region #'ivy-completion-in-region-prompt) + +(defcustom ivy-do-completion-in-region t + "When non-nil `ivy-mode' will set `completion-in-region-function'." + :type 'boolean) + +;;;###autoload +(define-minor-mode ivy-mode + "Toggle Ivy mode on or off. +Turn Ivy mode on if ARG is positive, off otherwise. +Turning on Ivy mode sets `completing-read-function' to +`ivy-completing-read'. + +Global bindings: +\\{ivy-mode-map} + +Minibuffer bindings: +\\{ivy-minibuffer-map}" + :group 'ivy + :global t + :keymap ivy-mode-map + :lighter " ivy" + (if ivy-mode + (progn + (setq completing-read-function 'ivy-completing-read) + (when ivy-do-completion-in-region + (setq completion-in-region-function 'ivy-completion-in-region))) + (setq completing-read-function 'completing-read-default) + (setq completion-in-region-function 'completion--in-region))) + +(defun ivy--preselect-index (preselect candidates) + "Return the index of PRESELECT in CANDIDATES." + (cond ((integerp 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)))) + +;;* Implementation +;;** Regex +(defun ivy-re-match (re-seq str) + "Return non-nil if RE-SEQ is matched by STR. + +RE-SEQ is a list of (RE . MATCH-P). + +RE is a regular expression. + +MATCH-P is t when RE should match STR and nil when RE should not +match STR. + +Each element of RE-SEQ must match for the function to return true. + +This concept is used to generalize regular expressions for +`ivy--regex-plus' and `ivy--regex-ignore-order'." + (let ((res t) + re) + (while (and res (setq re (pop re-seq))) + (setq res + (if (cdr re) + (string-match-p (car re) str) + (not (string-match-p (car re) str))))) + res)) + +(defvar ivy--regex-hash + (make-hash-table :test #'equal) + "Store pre-computed regex.") + +(defun ivy--split (str) + "Split STR into list of substrings bounded by spaces. +Single spaces act as splitting points. Consecutive spaces +\"quote\" their preceding spaces, i.e., guard them from being +split. This allows the literal interpretation of N spaces by +inputting N+1 spaces. Any substring not constituting a valid +regexp is passed to `regexp-quote'." + (let ((len (length str)) + start0 + (start1 0) + res s + match-len) + (while (and (string-match " +" str start1) + (< start1 len)) + (if (and (> (match-beginning 0) 2) + (string= "[^" (substring + str + (- (match-beginning 0) 2) + (match-beginning 0)))) + (progn + (setq start0 start1) + (setq start1 (match-end 0))) + (setq match-len (- (match-end 0) (match-beginning 0))) + (if (= match-len 1) + (progn + (when start0 + (setq start1 start0) + (setq start0 nil)) + (push (substring str start1 (match-beginning 0)) res) + (setq start1 (match-end 0))) + (setq str (replace-match + (make-string (1- match-len) ?\ ) + nil nil str)) + (setq start0 (or start0 start1)) + (setq start1 (1- (match-end 0)))))) + (if start0 + (push (substring str start0) res) + (setq s (substring str start1)) + (unless (= (length s) 0) + (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." + (let ((hashed (unless greedy + (gethash str ivy--regex-hash)))) + (if hashed + (progn + (setq ivy--subexps (car hashed)) + (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) + (cons + (setq ivy--subexps 0) + (if (string-match-p "\\`\\.[^.]" (car subs)) + (concat "\\." (substring (car subs) 1)) + (car subs))) + (cons + (setq ivy--subexps (length subs)) + (mapconcat + (lambda (x) + (if (string-match-p "\\`\\\\([^?].*\\\\)\\'" x) + x + (format "\\(%s\\)" x))) + subs + (if greedy ".*" ".*?"))))) + ivy--regex-hash))))) + +(defun ivy--regex-p (object) + "Return OBJECT if it is a valid regular expression, else nil." + (ignore-errors (string-match-p object "") object)) + +(defun ivy--regex-or-literal (str) + "If STR isn't a legal regexp, escape it." + (or (ivy--regex-p str) (regexp-quote str))) + +(defun ivy--split-negation (str) + "Split STR into text before and after ! delimiter. +Do not split if the delimiter is escaped as \\!. + +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 "\\(?:\\`\\|[^\\]\\)\\(!\\)")) + (mapcar (lambda (split) + ;; Store "\!" as "!". + (replace-regexp-in-string "\\\\!" "!" split t t)) + (if (string-match delim str) + ;; 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)) + (j (and (string-match delim str (1+ i)) + (match-beginning 1))) + (neg (substring str (1+ i) j))) + (cons (substring str 0 i) + (and (not (string= neg "")) + (list neg)))) + (list str)))))) + +(defun ivy--split-spaces (str) + "Split STR on spaces, unless they're preceded by \\. +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. + (j 0) ; End of last delimiter. + parts) + (while (string-match "\\(\\\\ \\)\\| +" str i) + (setq i (match-end 0)) + (if (not (match-beginning 1)) + ;; Un-escaped space(s). + (let ((delim (match-beginning 0))) + (when (< j delim) + (push (substring str j delim) parts)) + (setq j i)) + ;; Store "\ " as " ". + (setq str (replace-match " " t t str 1)) + (setq i (1- i)))) + (when (< j (length str)) + (push (substring str j) parts)) + (mapcar #'ivy--regex-or-literal (nreverse parts))))) + +(defun ivy--regex-ignore-order (str) + "Re-build regex from STR by splitting at spaces and using ! for negation. + +Examples: +foo -> matches \"foo\" +foo bar -> matches if both \"foo\" and \"bar\" match (any order) +foo !bar -> matches if \"foo\" matches and \"bar\" does not match +foo !bar baz -> matches if \"foo\" matches and neither \"bar\" nor \"baz\" match +foo[a-z] -> matches \"foo[a-z]\" + +Escaping examples: +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))) + (push (cons part t) regex-parts)) + (when (cdr raw-parts) + (dolist (part (ivy--split-spaces (cadr raw-parts))) + (push (cons part nil) regex-parts))) + (if regex-parts (nreverse regex-parts) + ""))) + +(defun ivy--regex-plus (str) + "Build a regex sequence from STR. +Spaces are wild card characters, everything before \"!\" should +match. Everything after \"!\" should not match." + (let ((parts (ivy--split-negation str))) + (cl-case (length parts) + (0 + "") + (1 + (if (= (aref str 0) ?!) + (list (cons "" t) + (list (ivy--regex (car parts)))) + (ivy--regex (car parts)))) + (2 + (cons + (cons (ivy--regex (car parts)) t) + (mapcar #'list (split-string (cadr parts) " " t)))) + (t (error "Unexpected: use only one !"))))) + +(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) + (let ((lst (string-to-list (match-string 2 str)))) + (apply #'concat + (cl-mapcar + #'concat + (cons "" (cdr (mapcar (lambda (c) (format "[^%c\n]*" c)) + lst))) + (mapcar (lambda (x) (format "\\(%s\\)" (regexp-quote (char-to-string x)))) + lst)))) + (match-string 3 str)) + (setq ivy--subexps (length (match-string 2 str)))) + str)) + +(defcustom ivy-fixed-height-minibuffer nil + "When non nil, fix the height of the minibuffer during ivy completion. +This effectively sets the minimum height at this level to `ivy-height' and +tries to ensure that it does not change depending on the number of candidates." + :type 'boolean) + +;;** Rest +(defcustom ivy-truncate-lines t + "Minibuffer setting for `truncate-lines'." + :type 'boolean) + +(defun ivy--minibuffer-setup () + "Setup ivy completion in the minibuffer." + (setq-local mwheel-scroll-up-function 'ivy-next-line) + (setq-local mwheel-scroll-down-function 'ivy-previous-line) + (setq-local completion-show-inline-help nil) + (setq-local line-spacing nil) + (setq-local minibuffer-default-add-function + (lambda () + (list ivy--default))) + (setq-local inhibit-field-text-motion nil) + (setq truncate-lines ivy-truncate-lines) + (setq-local max-mini-window-height ivy-height) + (let ((height (cond ((and ivy-fixed-height-minibuffer + (not (eq (ivy-state-caller ivy-last) + #'ivy-completion-in-region))) + (+ ivy-height (if ivy-add-newline-after-prompt 1 0))) + (ivy-add-newline-after-prompt 2)))) + (when height + (set-window-text-height nil height))) + (add-hook 'post-command-hook #'ivy--queue-exhibit nil t) + (let ((hook (ivy-alist-setting ivy-hooks-alist))) + (when (functionp hook) + (funcall hook)))) + +(defun ivy--input () + "Return the current minibuffer input." + ;; assume one-line minibuffer input + (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." + (save-excursion + (goto-char (minibuffer-prompt-end)) + (delete-region (line-end-position) (point-max)))) + +(defun ivy-cleanup-string (str) + "Destructively remove unwanted text properties from STR." + (ivy--remove-props str 'field)) + +(defvar ivy-set-prompt-text-properties-function + #'ivy-set-prompt-text-properties-default + "Function to set the text properties of the default ivy prompt. +Called with two arguments, PROMPT and PROPS, where PROMPT is the +string to be propertized and PROPS is a plist of default text +properties that may be applied to PROMPT. The function should +return the propertized PROMPT, which may be modified in-place.") + +(defun ivy-set-prompt-text-properties-default (prompt props) + "Propertize (confirm) and (match required) parts of PROMPT. +PROPS is a plist of default text properties to apply to these +parts beyond their respective faces `ivy-confirm-face' and +`ivy-match-required-face'." + (dolist (pair '(("confirm" . ivy-confirm-face) + ("match required" . ivy-match-required-face))) + (let ((i (string-match-p (car pair) prompt))) + (when i + (add-text-properties i (+ i (length (car pair))) + `(face ,(cdr pair) ,@props) + prompt)))) + prompt) + +(defun ivy-prompt () + "Return the current prompt." + (let* ((caller (ivy-state-caller ivy-last)) + (fn (plist-get ivy--prompts-list caller))) + (if fn + (condition-case err + (funcall fn) + (wrong-number-of-arguments + (lwarn 'ivy :error "%s + Prompt function set via `ivy-set-prompt' for caller `%s' + should take no arguments." + (error-message-string err) + caller) + ;; Old behavior. + (funcall fn (ivy-state-prompt ivy-last)))) + ivy--prompt))) + +(defun ivy--insert-prompt () + "Update the prompt according to `ivy--prompt'." + (when (setq ivy--prompt (ivy-prompt)) + (unless (memq this-command '(ivy-done ivy-alt-done ivy-partial-or-done + counsel-find-symbol)) + (setq ivy--prompt-extra "")) + (let (head tail) + (if (string-match "\\(.*?\\)\\(:? ?\\)\\'" ivy--prompt) + (progn + (setq head (match-string 1 ivy--prompt)) + (setq tail (match-string 2 ivy--prompt))) + (setq head ivy--prompt) + (setq tail "")) + (let ((inhibit-read-only t) + (std-props '(front-sticky t rear-nonsticky t field t read-only t)) + (n-str + (concat + (if (and (bound-and-true-p minibuffer-depth-indicate-mode) + (> (minibuffer-depth) 1)) + (format "[%d] " (minibuffer-depth)) + "") + (concat + (if (string-match "%d.*%d" ivy-count-format) + (format head + (1+ ivy--index) + (or (and (ivy-state-dynamic-collection ivy-last) + ivy--full-length) + ivy--length)) + (format head + (or (and (ivy-state-dynamic-collection ivy-last) + ivy--full-length) + ivy--length))) + ivy--prompt-extra + tail))) + (d-str (if ivy--directory + (abbreviate-file-name ivy--directory) + ""))) + (save-excursion + (goto-char (point-min)) + (delete-region (point-min) (minibuffer-prompt-end)) + (let ((len-n (length n-str)) + (len-d (length d-str)) + (ww (window-width))) + (setq n-str + (cond ((> (+ len-n len-d) ww) + (concat n-str "\n" d-str "\n")) + ((> (+ len-n len-d (length ivy-text)) ww) + (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)))) + (while (string-match regex n-str) + (setq n-str (replace-match + (concat (match-string 1 n-str) "\n") + nil t n-str 1)))) + (set-text-properties 0 (length n-str) + `(face minibuffer-prompt ,@std-props) + n-str) + (setq n-str (funcall ivy-set-prompt-text-properties-function + n-str std-props)) + (insert n-str)) + ;; Mark prompt as selected if the user moves there or it is the only + ;; option left. Since the user input stays put, we have to manually + ;; remove the face as well. + (when ivy--use-selectable-prompt + (if (= ivy--index -1) + (ivy-add-face-text-property + (minibuffer-prompt-end) (line-end-position) 'ivy-prompt-match) + (remove-list-of-text-properties + (minibuffer-prompt-end) (line-end-position) '(face)))) + ;; get out of the prompt area + (constrain-to-field nil (point-max)))))) + +(defun ivy--sort-maybe (collection) + "Sort COLLECTION if needed." + (let ((sort (ivy-state-sort ivy-last))) + (if (and sort + (or (functionp sort) + (functionp (setq sort (ivy--sort-function + (ivy-state-collection ivy-last)))))) + (sort (copy-sequence collection) sort) + collection))) + +(defcustom ivy-magic-slash-non-match-action 'ivy-magic-slash-non-match-cd-selected + "Action to take when a slash is added to the end of a non existing directory. +Possible choices are 'ivy-magic-slash-non-match-cd-selected, +'ivy-magic-slash-non-match-create, or nil" + :type '(choice + (const :tag "Use currently selected directory" + ivy-magic-slash-non-match-cd-selected) + (const :tag "Create and use new directory" + ivy-magic-slash-non-match-create) + (const :tag "Do nothing" + nil))) + +(defun ivy--create-and-cd (dir) + "When completing file names, create directory DIR and move there." + (make-directory dir) + (ivy--cd dir)) + +(defun ivy--magic-file-doubleslash-directory () + "Return an appropriate directory for when two slashes are entered." + (let (remote) + (cond + ;; Windows + ((string-match "\\`[[:alpha:]]:/" ivy--directory) + (match-string 0 ivy--directory)) + ;; Remote root if on remote + ((setq remote (file-remote-p ivy--directory)) + (concat remote "/")) + ;; Local root + (t + "/")))) + +(defun ivy--magic-file-slash () + "Handle slash when completing file names." + (when (or (and (eq this-command #'self-insert-command) + (eolp)) + (eq this-command #'ivy-partial-or-done)) + (let ((canonical (expand-file-name ivy-text ivy--directory)) + (magic (not (string= ivy-text "/")))) + (cond ((member ivy-text ivy--all-candidates) + (ivy--cd canonical)) + ((string-match-p "//\\'" ivy-text) + (ivy--cd + (ivy--magic-file-doubleslash-directory))) + ((string-match-p "\\`/ssh:" ivy-text) + (ivy--cd (file-name-directory ivy-text))) + ((string-match "[[:alpha:]]:/\\'" ivy-text) + (let ((drive-root (match-string 0 ivy-text))) + (when (file-exists-p drive-root) + (ivy--cd drive-root)))) + ((and magic (file-directory-p canonical)) + (ivy--cd canonical)) + ((let ((default-directory ivy--directory)) + (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 + 'ivy-magic-slash-non-match-cd-selected) + (eq this-command #'ivy-partial-or-done)))) + (ivy--cd + (expand-file-name (ivy-state-current ivy-last) ivy--directory))) + ((and (eq ivy-magic-slash-non-match-action + 'ivy-magic-slash-non-match-create) + magic) + (ivy--create-and-cd canonical)))))) + +(defun ivy-magic-read-file-env () + "If reading filename, jump to environment variable location." + (interactive) + (if (and ivy--directory + (equal ivy-text "")) + (let* ((cands (cl-loop for pair in process-environment + for (var val) = (split-string pair "=" t) + if (and val (not (equal "" val))) + if (file-exists-p + (if (file-name-absolute-p val) + val + (setq val + (expand-file-name val ivy--directory)))) + collect (cons var val))) + (enable-recursive-minibuffers t) + (x (ivy-read "Env: " cands)) + (path (cdr (assoc x cands)))) + (insert (if (file-accessible-directory-p path) + (file-name-as-directory path) + path)) + (ivy--cd-maybe)) + (insert last-input-event))) + +(defun ivy-make-magic-action (caller key) + "Return a command that does the equivalent of `ivy-read-action' and KEY. +This happens only when the input is empty. +The intention is to bind the result to keys that are typically +bound to `self-insert-command'." + (let* ((alist (assoc key + (plist-get + ivy--actions-list + caller))) + (doc (format "%s (`%S')" + (nth 2 alist) + (nth 1 alist)))) + `(lambda (&optional arg) + ,doc + (interactive "p") + (if (string= "" ivy-text) + (execute-kbd-macro + (kbd ,(concat "M-o " key))) + (self-insert-command arg))))) + +(defcustom ivy-magic-tilde t + "When non-nil, ~ will move home when selecting files. +Otherwise, ~/ will move home." + :type 'boolean) + +(defcustom ivy-dynamic-exhibit-delay-ms 0 + "Delay in ms before dynamic collections are refreshed" + :type 'integer) + +(defvar ivy--exhibit-timer nil) + +(defun ivy--queue-exhibit () + "Insert Ivy completions display, possibly after a timeout for +dynamic collections. +Should be run via minibuffer `post-command-hook'." + (if (and (> ivy-dynamic-exhibit-delay-ms 0) + (ivy-state-dynamic-collection ivy-last)) + (progn + (when ivy--exhibit-timer (cancel-timer ivy--exhibit-timer)) + (setq ivy--exhibit-timer + (run-with-timer + (/ ivy-dynamic-exhibit-delay-ms 1000.0) + nil + 'ivy--exhibit))) + (ivy--exhibit))) + +(defun ivy--magic-tilde-directory (dir) + "Return an appropriate home for DIR for when ~ or ~/ are entered." + (expand-file-name + (let (remote) + (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'." + (when (memq 'ivy--queue-exhibit post-command-hook) + (let ((inhibit-field-text-motion nil)) + (constrain-to-field nil (point-max))) + (setq ivy-text (ivy--input)) + (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) + coll in-progress) + (unless (equal ivy--old-text ivy-text) + (while-no-input + (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 + (and (not (get-process " *counsel*")) + (not in-progress))) + (ivy--set-index-dynamic-collection) + (ivy--insert-minibuffer + (ivy--format ivy--all-candidates)))) + (cond (ivy--directory + (cond ((or (string= "~/" ivy-text) + (and (string= "~" ivy-text) + ivy-magic-tilde)) + (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) + (when (or (and (string-match "\\` " ivy-text) + (not (string-match "\\` " ivy--old-text))) + (and (string-match "\\` " ivy--old-text) + (not (string-match "\\` " ivy-text)))) + (setq ivy--all-candidates + (if (= (string-to-char ivy-text) ?\s) + (ivy--buffer-list " ") + (ivy--buffer-list "" ivy-use-virtual-buffers))) + (setq ivy--old-re nil)))) + (ivy--insert-minibuffer + (with-current-buffer (ivy-state-buffer ivy-last) + (ivy--format + (ivy--filter ivy-text ivy--all-candidates)))) + (setq ivy--old-text ivy-text)))) + +(defun ivy-display-function-fallback (str) + (let ((buffer-undo-list t)) + (save-excursion + (forward-line 1) + (insert str)))) + +(defun ivy--insert-minibuffer (text) + "Insert TEXT into minibuffer with appropriate cleanup." + (let ((resize-mini-windows nil) + (update-fn (ivy-state-update-fn ivy-last)) + (old-mark (marker-position (mark-marker))) + (win (active-minibuffer-window)) + deactivate-mark) + (when win + (with-selected-window win + (ivy--minibuffer-cleanup) + (when update-fn + (funcall update-fn)) + (ivy--insert-prompt) + ;; Do nothing if while-no-input was aborted. + (when (stringp text) + (if ivy--display-function + (funcall ivy--display-function text) + (ivy-display-function-fallback text))) + (ivy--resize-minibuffer-to-fit) + ;; prevent region growing due to text remove/add + (when (region-active-p) + (set-mark old-mark)))))) + +(defun ivy--resize-minibuffer-to-fit () + "Resize the minibuffer window size to fit the text in the minibuffer." + (unless (frame-root-window-p (minibuffer-window)) + (with-selected-window (minibuffer-window) + (if (fboundp 'window-text-pixel-size) + (let ((text-height (cdr (window-text-pixel-size))) + (body-height (window-body-height nil t))) + (when (> text-height body-height) + ;; Note: the size increment needs to be at least + ;; frame-char-height, otherwise resizing won't do + ;; anything. + (let ((delta (max (- text-height body-height) + (frame-char-height)))) + (window-resize nil delta nil t t)))) + (let ((text-height (count-screen-lines)) + (body-height (window-body-height))) + (when (> text-height body-height) + (window-resize nil (- text-height body-height) nil t))))))) + +(defun ivy--add-face (str face) + "Propertize STR with FACE." + (let ((len (length str))) + (condition-case nil + (progn + (colir-blend-face-background 0 len face str) + (let ((foreground (face-foreground face))) + (when foreground + (ivy-add-face-text-property + 0 len (list :foreground foreground) str)))) + (error + (ignore-errors + (font-lock-append-text-property 0 len 'face face str))))) + str) + +(declare-function flx-make-string-cache "ext:flx") +(declare-function flx-score "ext:flx") + +(defvar ivy--flx-cache nil) + +(eval-after-load 'flx + '(setq ivy--flx-cache (flx-make-string-cache))) + +(defun ivy-toggle-case-fold () + "Toggle `case-fold-search' for Ivy operations. + +Instead of modifying `case-fold-search' directly, this command +toggles `ivy-case-fold-search', which can take on more values +than the former, between nil and either `auto' or t. See +`ivy-case-fold-search-default' for the meaning of these values. + +In any Ivy completion session, the case folding starts with +`ivy-case-fold-search-default'." + (interactive) + (setq ivy-case-fold-search + (and (not ivy-case-fold-search) + (or ivy-case-fold-search-default 'auto))) + ;; Reset cache so that the candidate list updates. + (setq ivy--old-re nil)) + +(defun ivy--re-filter (re candidates &optional mkpred) + "Return all RE matching CANDIDATES. +RE is a list of cons cells, with a regexp car and a boolean cdr. +When the cdr is t, the car must match. +Otherwise, the car must not match." + (if (equal re "") + candidates + (ignore-errors + (dolist (re (if (stringp re) (list (cons re t)) re)) + (let* ((re-str (car re)) + (pred + (if mkpred + (funcall mkpred re-str) + (lambda (x) (string-match-p re-str x))))) + (setq candidates + (cl-remove nil candidates + (if (cdr re) :if-not :if) + pred)))) + candidates))) + +(defun ivy--filter (name candidates) + "Return all items that match NAME in CANDIDATES. +CANDIDATES are assumed to be static." + (let ((re (funcall ivy--regex-function name))) + (if (and + ivy--old-re + ivy--old-cands + (equal re ivy--old-re)) + ;; quick caching for "C-n", "C-p" etc. + ivy--old-cands + (let* ((re-str (ivy-re-to-str re)) + (matcher (ivy-state-matcher ivy-last)) + (case-fold-search (ivy--case-fold-p name)) + (cands (cond + ((and ivy--old-re + (stringp re) + (stringp ivy--old-re) + (not (string-match-p "\\\\" ivy--old-re)) + (not (equal ivy--old-re "")) + (memq (cl-search + (if (string-match-p "\\\\)\\'" ivy--old-re) + (substring ivy--old-re 0 -2) + ivy--old-re) + re) + '(0 2)) + ivy--old-cands + (ivy--re-filter re ivy--old-cands))) + (matcher + (funcall matcher re candidates)) + (t + (ivy--re-filter re candidates))))) + (if (memq (cdr (assq (ivy-state-caller ivy-last) + ivy-index-functions-alist)) + '(ivy-recompute-index-swiper + ivy-recompute-index-swiper-async + ivy-recompute-index-swiper-async-backward + ivy-recompute-index-swiper-backward)) + (progn + (ivy--recompute-index name re-str cands) + (setq ivy--old-cands (ivy--sort name cands))) + (setq ivy--old-cands (ivy--sort name cands)) + (ivy--recompute-index name re-str ivy--old-cands)) + (setq ivy--old-re re) + ivy--old-cands)))) + +(defun ivy--set-candidates (x) + "Update `ivy--all-candidates' with X." + (let (res) + (dolist (source ivy--extra-candidates) + (if (equal source '(original-source)) + (if (null res) + (setq res x) + (setq res (append x res))) + (setq ivy--old-re nil) + (setq res (append + (ivy--filter ivy-text (cadr source)) + res)))) + (setq ivy--all-candidates res))) + +(defun ivy--shorter-matches-first (_name cands) + "Sort CANDS according to their length." + (if (< (length cands) ivy-sort-max-size) + (cl-sort + (copy-sequence cands) + (lambda (s1 s2) + (< (length s1) (length s2)))) + cands)) + +(defcustom ivy-sort-matches-functions-alist + '((t . nil) + (ivy-completion-in-region . ivy--shorter-matches-first) + (ivy-switch-buffer . ivy-sort-function-buffer)) + "An alist of functions for sorting matching candidates. + +Unlike `ivy-sort-functions-alist', which is used to sort the +whole collection only once, this alist of functions are used to +sort only matching candidates after each change in input. + +The alist KEY is either a collection function or t to match +previously unmatched collection functions. + +The alist VAL is a sorting function with the signature of +`ivy--prefix-sort'." + :type '(alist + :key-type (choice + (const :tag "Fall-through" t) + (symbol :tag "Collection")) + :value-type + (choice + (const :tag "Don't sort" nil) + (const :tag "Put prefix matches ahead" ivy--prefix-sort) + (function :tag "Custom sort function")))) + +(defun ivy--sort-files-by-date (_name candidates) + "Re-sort CANDIDATES according to file modification date." + (let ((default-directory ivy--directory)) + (sort (copy-sequence candidates) #'file-newer-than-file-p))) + +(defvar ivy--flx-featurep (require 'flx nil 'noerror)) + +(defun ivy--sort (name candidates) + "Re-sort candidates by NAME. +All CANDIDATES are assumed to match NAME." + (let (fun) + (cond ((setq fun (ivy-alist-setting ivy-sort-matches-functions-alist)) + (funcall fun name candidates)) + ((and ivy--flx-featurep + (eq ivy--regex-function 'ivy--regex-fuzzy)) + (ivy--flx-sort name candidates)) + (t + candidates)))) + +(defun ivy--prefix-sort (name candidates) + "Re-sort candidates by NAME. +All CANDIDATES are assumed to match NAME. +Prefix matches to NAME are put ahead of the list." + (if (or (string= name "") + (= (aref name 0) ?^)) + candidates + (let ((re-prefix (concat "\\`" (funcall ivy--regex-function name))) + res-prefix + res-noprefix) + (dolist (s candidates) + (if (string-match-p re-prefix s) + (push s res-prefix) + (push s res-noprefix))) + (nconc + (nreverse res-prefix) + (nreverse res-noprefix))))) + +(defvar ivy--virtual-buffers nil + "Store the virtual buffers alist.") + +(defun ivy-re-to-str (re) + "Transform RE to a string. + +Functions like `ivy--regex-ignore-order' return a cons list. +This function extracts a string from the cons list." + (if (consp re) (caar re) re)) + +(defun ivy-sort-function-buffer (name candidates) + "Re-sort candidates by NAME. +CANDIDATES is a list of buffer names each containing NAME. +Sort open buffers before virtual buffers, and prefix matches +before substring matches." + (if (or (string= name "") + (= (aref name 0) ?^)) + candidates + (let* ((base-re (ivy-re-to-str (funcall ivy--regex-function name))) + (re-star-prefix (concat "\\`\\*" base-re)) + (re-prefix (concat "\\`" base-re)) + res-prefix + res-noprefix + res-virtual-prefix + res-virtual-noprefix) + (dolist (s candidates) + (cond + ((and (assoc s ivy--virtual-buffers) + (or (string-match-p re-star-prefix s) + (string-match-p re-prefix s))) + (push s res-virtual-prefix)) + ((assoc s ivy--virtual-buffers) + (push s res-virtual-noprefix)) + ((or (string-match-p re-star-prefix s) + (string-match-p re-prefix s)) + (push s res-prefix)) + (t + (push s res-noprefix)))) + (nconc + (nreverse res-prefix) + (nreverse res-noprefix) + (nreverse res-virtual-prefix) + (nreverse res-virtual-noprefix))))) + +(defvar ivy-flx-limit 200 + "Used to conditionally turn off flx sorting. + +When the amount of matching candidates exceeds this limit, then +no sorting is done.") + +(defvar ivy--recompute-index-inhibit nil + "When non-nil, `ivy--recompute-index' is a no-op.") + +(defun ivy--recompute-index (name re-str cands) + "Recompute index of selected candidate matching NAME. +RE-STR is the regexp, CANDS are the current candidates." + (let ((caller (ivy-state-caller ivy-last)) + (func (or (ivy-alist-setting ivy-index-functions-alist) + #'ivy-recompute-index-zero)) + (case-fold-search (ivy--case-fold-p name)) + (preselect (ivy-state-preselect ivy-last)) + (current (ivy-state-current ivy-last)) + (empty (string= name ""))) + (unless (or (memq this-command '(ivy-resume ivy-partial-or-done)) + ivy--recompute-index-inhibit) + (ivy-set-index + (if (or (string= name "") + (and (> (length cands) 10000) (eq func #'ivy-recompute-index-zero))) + 0 + (or + (cl-position (ivy--remove-prefix "^" name) + cands + :test #'ivy--case-fold-string=) + (and ivy--directory + (cl-position (concat re-str "/") + cands + :test #'ivy--case-fold-string=)) + (and (eq caller 'ivy-switch-buffer) + (not empty) + 0) + (and (not empty) + (not (eq caller 'swiper)) + (not (and ivy--flx-featurep + (eq ivy--regex-function 'ivy--regex-fuzzy) + ;; Limit to configured number of candidates + (null (nthcdr ivy-flx-limit cands)))) + ;; If there was a preselected candidate, don't try to + ;; keep it selected even if the regexp still matches it. + ;; See issue #1563. See also `ivy--preselect-index', + ;; which this logic roughly mirrors. + (not (or + (and (integerp preselect) + (= ivy--index preselect)) + (equal current preselect) + (and (ivy--regex-p preselect) + (stringp current) + (string-match-p preselect current)))) + ivy--old-cands + (cl-position current cands :test #'equal)) + (funcall func re-str cands))))) + (when (or empty (string= name "^")) + (ivy-set-index + (or (ivy--preselect-index preselect cands) + ivy--index))))) + +(defun ivy-recompute-index-swiper (_re-str cands) + "Recompute index of selected candidate when using `swiper'. +CANDS are the current candidates." + (condition-case nil + (let ((tail (nthcdr ivy--index ivy--old-cands)) + idx) + (if (and tail ivy--old-cands (not (equal "^" ivy--old-re))) + (progn + (while (and tail (null idx)) + ;; Compare with eq to handle equal duplicates in cands + (setq idx (cl-position (pop tail) cands))) + (or + idx + (1- (length cands)))) + (if ivy--old-cands + ivy--index + ;; already in ivy-state-buffer + (let ((n (line-number-at-pos)) + (res 0) + (i 0)) + (dolist (c cands) + (when (eq n (get-text-property 0 'swiper-line-number c)) + (setq res i)) + (cl-incf i)) + res)))) + (error 0))) + +(defun ivy-recompute-index-swiper-backward (re-str cands) + "Recompute index of selected candidate when using `swiper-backward'. +CANDS are the current candidates." + (let ((idx (ivy-recompute-index-swiper re-str cands))) + (if (or (= idx -1) + (<= (get-text-property 0 'swiper-line-number (nth idx cands)) + (line-number-at-pos))) + idx + (- idx 1)))) + +(defun ivy-recompute-index-swiper-async (_re-str cands) + "Recompute index of selected candidate when using `swiper' asynchronously. +CANDS are the current candidates." + (if (null ivy--old-cands) + (let ((ln (with-ivy-window + (line-number-at-pos)))) + (or + ;; closest to current line going forwards + (cl-position-if (lambda (x) + (>= (string-to-number x) ln)) + cands) + ;; closest to current line going backwards + (1- (length cands)))) + (let ((tail (nthcdr ivy--index ivy--old-cands)) + idx) + (if (and tail ivy--old-cands (not (equal "^" ivy--old-re))) + (progn + (while (and tail (null idx)) + ;; Compare with `equal', since the collection is re-created + ;; each time with `split-string' + (setq idx (cl-position (pop tail) cands :test #'equal))) + (or idx 0)) + ivy--index)))) + +(defun ivy-recompute-index-swiper-async-backward (re-str cands) + "Recompute index of selected candidate when using `swiper-backward' +asynchronously. CANDS are the current candidates." + (if (= (length cands) 0) + 0 + (let ((idx (ivy-recompute-index-swiper-async re-str cands))) + (if + (<= (string-to-number (nth idx cands)) + (with-ivy-window (line-number-at-pos))) + idx + (- idx 1))))) + +(defun ivy-recompute-index-zero (_re-str _cands) + "Recompute index of selected candidate. +This function serves as a fallback when nothing else is available." + 0) + +(defcustom ivy-minibuffer-faces + '(ivy-minibuffer-match-face-1 + ivy-minibuffer-match-face-2 + ivy-minibuffer-match-face-3 + ivy-minibuffer-match-face-4) + "List of `ivy' faces for minibuffer group matches." + :type '(repeat :tag "Faces" + (choice + (const ivy-minibuffer-match-face-1) + (const ivy-minibuffer-match-face-2) + (const ivy-minibuffer-match-face-3) + (const ivy-minibuffer-match-face-4) + (face :tag "Other face")))) + +(defun ivy--minibuffer-face (n) + "Return Nth face from `ivy-minibuffer-faces'. +N wraps around, but skips the first element of the list." + (let ((tail (cdr ivy-minibuffer-faces))) + (nth (mod (+ n 2) (length tail)) tail))) + +(defun ivy--flx-propertize (x) + "X is (cons (flx-score STR ...) STR)." + (let ((str (copy-sequence (cdr x))) + (i 0) + (last-j -2)) + (dolist (j (cdar x)) + (unless (eq j (1+ last-j)) + (cl-incf i)) + (setq last-j j) + (ivy-add-face-text-property j (1+ j) (ivy--minibuffer-face i) str)) + str)) + +(defun ivy--flx-sort (name cands) + "Sort according to closeness to string NAME the string list CANDS." + (condition-case nil + (let* ((bolp (= (string-to-char name) ?^)) + ;; An optimized regex for fuzzy matching + ;; "abc" → "^[^a]*a[^b]*b[^c]*c" + (fuzzy-regex (concat "\\`" + (and bolp (regexp-quote (substring name 1 2))) + (mapconcat + (lambda (x) + (setq x (char-to-string x)) + (concat "[^" x "]*" (regexp-quote x))) + (if bolp (substring name 2) name) + ""))) + ;; Strip off the leading "^" for flx matching + (flx-name (if bolp (substring name 1) name)) + cands-left + cands-to-sort) + + ;; Filter out non-matching candidates + (dolist (cand cands) + (when (string-match-p fuzzy-regex cand) + (push cand cands-left))) + + ;; pre-sort the candidates by length before partitioning + (setq cands-left (cl-sort cands-left #'< :key #'length)) + + ;; partition the candidates into sorted and unsorted groups + (dotimes (_ (min (length cands-left) ivy-flx-limit)) + (push (pop cands-left) cands-to-sort)) + + (nconc + ;; Compute all of the flx scores in one pass and sort + (mapcar #'car + (sort (mapcar + (lambda (cand) + (cons cand + (car (flx-score cand flx-name ivy--flx-cache)))) + cands-to-sort) + (lambda (c1 c2) + ;; Break ties by length + (if (/= (cdr c1) (cdr c2)) + (> (cdr c1) + (cdr c2)) + (< (length (car c1)) + (length (car c2))))))) + + ;; Add the unsorted candidates + cands-left)) + (error cands))) + +(defun ivy--truncate-string (str width) + "Truncate STR to WIDTH." + (truncate-string-to-width str width nil nil t)) + +(defun ivy--format-function-generic (selected-fn other-fn cands separator) + "Transform candidates into a string for minibuffer. +SELECTED-FN is called for the selected candidate, OTHER-FN for the others. +Both functions take one string argument each. CANDS is a list of candidates +and SEPARATOR is used to join them." + (let ((i -1)) + (mapconcat + (lambda (str) + (let ((curr (eq (cl-incf i) ivy--window-index))) + (if curr + (funcall selected-fn str) + (funcall other-fn str)))) + cands + separator))) + +(defun ivy-format-function-default (cands) + "Transform CANDS into a string for minibuffer." + (ivy--format-function-generic + (lambda (str) + (ivy--add-face str 'ivy-current-match)) + #'identity + cands + "\n")) + +(defun ivy-format-function-arrow (cands) + "Transform CANDS into a string for minibuffer." + (ivy--format-function-generic + (lambda (str) + (concat "> " (ivy--add-face str 'ivy-current-match))) + (lambda (str) + (concat " " str)) + cands + "\n")) + +(defun ivy-format-function-line (cands) + "Transform CANDS into a string for minibuffer." + (ivy--format-function-generic + (lambda (str) + (ivy--add-face (concat str "\n") 'ivy-current-match)) + (lambda (str) + (concat str "\n")) + cands + "")) + +(defalias 'ivy-add-face-text-property + (if (fboundp 'add-face-text-property) + (lambda (start end face &optional object append) + (add-face-text-property start end face append object)) + (lambda (start end face &optional object append) + (funcall (if append + #'font-lock-append-text-property + #'font-lock-prepend-text-property) + start end 'face face object))) + "Compatibility shim for `add-face-text-property'. +Fall back on `font-lock-prepend-text-property' in Emacs versions +prior to 24.4 (`font-lock-append-text-property' when APPEND is +non-nil). +Note: The usual last two arguments are flipped for convenience.") + +(defun ivy--highlight-ignore-order (str) + "Highlight STR, using the ignore-order method." + (when (consp ivy--old-re) + (let ((i 1)) + (dolist (re ivy--old-re) + (when (string-match (car re) str) + (ivy-add-face-text-property + (match-beginning 0) (match-end 0) + (ivy--minibuffer-face i) + str)) + (cl-incf i)))) + str) + +(defun ivy--highlight-fuzzy (str) + "Highlight STR, using the fuzzy method." + (if (and ivy--flx-featurep + (eq (ivy-alist-setting ivy-re-builders-alist) 'ivy--regex-fuzzy)) + (let ((flx-name (ivy--remove-prefix "^" ivy-text))) + (ivy--flx-propertize + (cons (flx-score str flx-name ivy--flx-cache) str))) + (ivy--highlight-default str))) + +(defun ivy--highlight-default (str) + "Highlight STR, using the default method." + (unless ivy--old-re + (setq ivy--old-re (funcall ivy--regex-function ivy-text))) + (let ((regexps + (if (listp ivy--old-re) + (mapcar #'car (cl-remove-if-not #'cdr ivy--old-re)) + (list ivy--old-re))) + start) + (dolist (re regexps) + (ignore-errors + (while (and (string-match re str start) + (> (- (match-end 0) (match-beginning 0)) 0)) + (setq start (match-end 0)) + (let ((i 0) + (n 0) + prev) + (while (<= i ivy--subexps) + (let ((beg (match-beginning i)) + (end (match-end i))) + (when (and beg end) + (unless (and prev (= prev beg)) + (cl-incf n)) + (let ((face + (cond ((zerop ivy--subexps) + (cadr ivy-minibuffer-faces)) + ((zerop i) + (car ivy-minibuffer-faces)) + (t + (ivy--minibuffer-face n))))) + (ivy-add-face-text-property beg end face str)) + (unless (zerop i) + (setq prev end)))) + (cl-incf i))))))) + str) + +(defun ivy--format-minibuffer-line (str) + "Format line STR for use in minibuffer." + (let* ((str (ivy-cleanup-string (copy-sequence str))) + (str (if (eq ivy-display-style 'fancy) + (if (memq (ivy-state-caller ivy-last) + ivy-highlight-grep-commands) + (let* ((start (if (string-match "\\`[^:]+:\\(?:[^:]+:\\)?" str) + (match-end 0) 0)) + (file (substring str 0 start)) + (match (substring str start))) + (concat file (funcall ivy--highlight-function match))) + (funcall ivy--highlight-function str)) + str)) + (olen (length str)) + (annot (plist-get completion-extra-properties :annotation-function))) + (add-text-properties + 0 olen + '(mouse-face + ivy-minibuffer-match-highlight + help-echo + (format + (if tooltip-mode + "mouse-1: %s\nmouse-3: %s" + "mouse-1: %s mouse-3: %s") + ivy-mouse-1-tooltip ivy-mouse-3-tooltip)) + str) + (when annot + (setq str (concat str (funcall annot str))) + (ivy-add-face-text-property + olen (length str) 'ivy-completions-annotations str)) + str)) + +(defun ivy-read-file-transformer (str) + "Transform candidate STR when reading files." + (if (ivy--dirname-p str) + (propertize str 'face 'ivy-subdir) + str)) + +(defun ivy--minibuffer-index-bounds (idx len wnd-len) + (let* ((half-height (/ wnd-len 2)) + (start (max 0 + (min (- idx half-height) + (- len (1- wnd-len))))) + (end (min (+ start (1- wnd-len)) len))) + (list start end (- idx start)))) + +(defun ivy--format (cands) + "Return a string for CANDS suitable for display in the minibuffer. +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))) + (if (null cands) + (setf (ivy-state-current ivy-last) "") + (let ((cur (nth ivy--index cands))) + (setf (ivy-state-current ivy-last) (if (stringp cur) + (copy-sequence cur) + cur))) + (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)) + (with-ivy-window + (with-current-buffer (ivy-state-buffer ivy-last) + (setq wnd-cands (mapcar transformer-fn wnd-cands))))) + (ivy--wnd-cands-to-str wnd-cands)))) + +(defun ivy--wnd-cands-to-str (wnd-cands) + (let ((str (concat "\n" + (funcall (ivy-alist-setting ivy-format-functions-alist) + (condition-case nil + (mapcar + #'ivy--format-minibuffer-line + wnd-cands) + (error wnd-cands)))))) + (put-text-property 0 (length str) 'read-only nil str) + str)) + +(defvar recentf-list) +(defvar bookmark-alist) + +(defcustom ivy-virtual-abbreviate 'name + "The mode of abbreviation for virtual buffer names." + :type '(choice + (const :tag "Only name" name) + (const :tag "Abbreviated path" abbreviate) + (const :tag "Full path" full) + ;; eventually, uniquify + )) +(declare-function bookmark-maybe-load-default-file "bookmark") +(declare-function bookmark-get-filename "bookmark") + +(defun ivy--virtual-buffers () + "Adapted from `ido-add-virtual-buffers-to-list'." + (require 'bookmark) + (unless recentf-mode + (recentf-mode 1)) + (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))) + (name (cond ((eq ivy-virtual-abbreviate 'name) + (file-name-nondirectory file-name)) + ((eq ivy-virtual-abbreviate 'abbreviate) + (abbreviate-file-name file-name)) + (t + (expand-file-name file-name))))) + (when (equal name "") + (setq name + (if (consp head) + (car head) + (file-name-nondirectory (directory-file-name file-name))))) + (unless (or (equal name "") + (get-file-buffer file-name) + (assoc name virtual-buffers)) + (push (cons (copy-sequence name) file-name) virtual-buffers)))) + (when virtual-buffers + (dolist (comp virtual-buffers) + (put-text-property 0 (length (car comp)) + 'face 'ivy-virtual + (car comp))) + (setq ivy--virtual-buffers (nreverse virtual-buffers)) + (mapcar #'car ivy--virtual-buffers)))) + +(defcustom ivy-ignore-buffers '("\\` ") + "List of regexps or functions matching buffer names to ignore." + :type '(repeat (choice regexp function))) + +(defvar ivy-switch-buffer-faces-alist '((dired-mode . ivy-subdir) + (org-mode . ivy-org)) + "Store face customizations for `ivy-switch-buffer'. +Each KEY is `major-mode', each VALUE is a face name.") + +(defun ivy--buffer-list (str &optional virtual predicate) + "Return the buffers that match STR. +If VIRTUAL is non-nil, add virtual buffers. +If optional argument PREDICATE is non-nil, use it to test each +possible match. See `all-completions' for further information." + (delete-dups + (nconc + (mapcar + (lambda (x) + (let* ((buf (get-buffer x)) + (dir (buffer-local-value 'default-directory buf)) + (face (if (and dir + (ignore-errors + (file-remote-p (abbreviate-file-name dir)))) + 'ivy-remote + (cdr (assq (buffer-local-value 'major-mode buf) + ivy-switch-buffer-faces-alist))))) + (if face + (propertize x 'face face) + x))) + (all-completions str #'internal-complete-buffer predicate)) + (and virtual + (ivy--virtual-buffers))))) + +(defvar ivy-views (and nil + `(("ivy + *scratch* {}" + (vert + (file ,(expand-file-name "ivy.el")) + (buffer "*scratch*"))) + ("swiper + *scratch* {}" + (horz + (file ,(expand-file-name "swiper.el")) + (buffer "*scratch*"))))) + "Store window configurations selectable by `ivy-switch-buffer'. + +The default value is given as an example. + +Each element is a list of (NAME TREE). NAME is a string, it's +recommended to end it with a distinctive snippet e.g. \"{}\" so +that it's easy to distinguish the window configurations. + +TREE is a nested list with the following valid cars: +- vert: split the window vertically +- horz: split the window horizontally +- file: open the specified file +- buffer: open the specified buffer + +TREE can be nested multiple times to have multiple window splits.") + +(defun ivy-default-view-name () + "Return default name for new view." + (let* ((default-view-name + (concat "{} " + (mapconcat #'identity + (sort + (mapcar (lambda (w) + (let* ((b (window-buffer w)) + (f (buffer-file-name b))) + (if f + (file-name-nondirectory f) + (buffer-name b)))) + (window-list)) + #'string-lessp) + " "))) + (view-name-re (concat "\\`" + (regexp-quote default-view-name) + " \\([0-9]+\\)")) + old-view) + (cond ((setq old-view + (cl-find-if + (lambda (x) + (string-match view-name-re (car x))) + ivy-views)) + (format "%s %d" + default-view-name + (1+ (string-to-number + (match-string 1 (car old-view)))))) + ((assoc default-view-name ivy-views) + (concat default-view-name " 1")) + (t + default-view-name)))) + +(defun ivy-push-view (&optional arg) + "Push the current window tree on `ivy-views'. + +When ARG is non-nil, replace a selected item on `ivy-views'. + +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") + (let* ((view (cl-labels + ((ft (tr) + (if (consp tr) + (if (eq (car tr) t) + (cons 'vert + (mapcar #'ft (cddr tr))) + (cons 'horz + (mapcar #'ft (cddr tr)))) + (with-current-buffer (window-buffer tr) + (cond (buffer-file-name + (list 'file buffer-file-name (point))) + ((eq major-mode 'dired-mode) + (list 'file default-directory (point))) + (t + (list 'buffer (buffer-name) (point)))))))) + (ft (car (window-tree))))) + (view-name + (if arg + (ivy-read "Update view: " ivy-views) + (ivy-read "Name view: " nil + :initial-input (ivy-default-view-name))))) + (when view-name + (let ((x (assoc view-name ivy-views))) + (if x + (setcdr x (list view)) + (push (list view-name view) ivy-views)))))) + +(defun ivy-pop-view-action (view) + "Delete VIEW from `ivy-views'." + (setq ivy-views (delete view ivy-views)) + (setq ivy--all-candidates + (delete (car view) ivy--all-candidates)) + (setq ivy--old-cands nil)) + +(defun ivy-pop-view () + "Delete a view to delete from `ivy-views'." + (interactive) + (ivy-read "Pop view: " ivy-views + :preselect (caar ivy-views) + :action #'ivy-pop-view-action + :caller 'ivy-pop-view)) + +(defun ivy-source-views () + "Return the name of the views saved in `ivy-views'." + (mapcar #'car ivy-views)) + +(ivy-set-sources + 'ivy-switch-buffer + '((original-source) + (ivy-source-views))) + +(defun ivy-set-view-recur (view) + "Set VIEW recursively." + (cond ((eq (car view) 'vert) + (let* ((wnd1 (selected-window)) + (wnd2 (split-window-vertically)) + (views (cdr view)) + (v (pop views)) + (temp-wnd)) + (with-selected-window wnd1 + (ivy-set-view-recur v)) + (while (setq v (pop views)) + (with-selected-window wnd2 + (when views + (setq temp-wnd (split-window-vertically))) + (ivy-set-view-recur v) + (when views + (setq wnd2 temp-wnd)))))) + ((eq (car view) 'horz) + (let* ((wnd1 (selected-window)) + (wnd2 (split-window-horizontally)) + (views (cdr view)) + (v (pop views)) + (temp-wnd)) + (with-selected-window wnd1 + (ivy-set-view-recur v)) + (while (setq v (pop views)) + (with-selected-window wnd2 + (when views + (setq temp-wnd (split-window-horizontally))) + (ivy-set-view-recur v) + (when views + (setq wnd2 temp-wnd)))))) + ((eq (car view) 'file) + (let* ((name (nth 1 view)) + (virtual (assoc name ivy--virtual-buffers)) + buffer) + (cond ((setq buffer (get-buffer name)) + (switch-to-buffer buffer nil 'force-same-window)) + (virtual + (find-file (cdr virtual))) + ((file-exists-p name) + (find-file name)))) + (when (and (> (length view) 2) + (numberp (nth 2 view))) + (goto-char (nth 2 view)))) + ((eq (car view) 'buffer) + (switch-to-buffer (nth 1 view)) + (when (and (> (length view) 2) + (numberp (nth 2 view))) + (goto-char (nth 2 view)))) + ((eq (car view) 'sexp) + (eval (nth 1 view))))) + +(defun ivy--switch-buffer-action (buffer) + "Switch to BUFFER. +BUFFER may be a string or nil." + (if (zerop (length buffer)) + (switch-to-buffer + ivy-text nil 'force-same-window) + (let ((virtual (assoc buffer ivy--virtual-buffers)) + (view (assoc buffer ivy-views))) + (cond ((and virtual + (not (get-buffer buffer))) + (find-file (cdr virtual))) + (view + (delete-other-windows) + (let ( + ;; silence "Directory has changed on disk" + (inhibit-message t)) + (ivy-set-view-recur (cadr view)))) + (t + (switch-to-buffer + buffer nil 'force-same-window)))))) + +(defun ivy--switch-buffer-other-window-action (buffer) + "Switch to BUFFER in other window. +BUFFER may be a string or nil." + (if (zerop (length buffer)) + (switch-to-buffer-other-window ivy-text) + (let ((virtual (assoc buffer ivy--virtual-buffers))) + (if (and virtual + (not (get-buffer buffer))) + (find-file-other-window (cdr virtual)) + (switch-to-buffer-other-window buffer))))) + +(defun ivy--rename-buffer-action (buffer) + "Rename BUFFER." + (let ((new-name (read-string "Rename buffer (to new name): "))) + (with-current-buffer buffer + (rename-buffer new-name)))) + +(defun ivy--find-file-action (buffer) + "Find file from BUFFER's directory." + (let* ((virtual (assoc buffer ivy--virtual-buffers)) + (default-directory (if virtual + (file-name-directory (cdr virtual)) + (buffer-local-value 'default-directory + (or (get-buffer buffer) + (current-buffer)))))) + (call-interactively (if (functionp 'counsel-find-file) + #'counsel-find-file + #'find-file)))) + +(defun ivy--kill-buffer-or-virtual (buffer) + (if (get-buffer buffer) + (kill-buffer buffer) + (setq recentf-list (delete + (cdr (assoc buffer ivy--virtual-buffers)) + recentf-list)))) + +(defun ivy--kill-current-candidate () + (setf (ivy-state-preselect ivy-last) ivy--index) + (setq ivy--old-re nil) + (setq ivy--all-candidates (delete (ivy-state-current ivy-last) ivy--all-candidates)) + (let ((ivy--recompute-index-inhibit t)) + (ivy--exhibit))) + +(defun ivy--kill-buffer-action (buffer) + "Kill BUFFER." + (ivy--kill-buffer-or-virtual buffer) + (unless (buffer-live-p (ivy-state-buffer ivy-last)) + (setf (ivy-state-buffer ivy-last) + (with-ivy-window (current-buffer)))) + (ivy--kill-current-candidate)) + +(defvar ivy-switch-buffer-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-k") 'ivy-switch-buffer-kill) + map)) + +(defun ivy-switch-buffer-kill () + "When at end-of-line, kill the current buffer in `ivy-switch-buffer'. +Otherwise, forward to `ivy-kill-line'." + (interactive) + (if (not (eolp)) + (ivy-kill-line) + (ivy--kill-buffer-action + (ivy-state-current ivy-last)))) + +(ivy-set-actions + 'ivy-switch-buffer + '(("f" + ivy--find-file-action + "find file") + ("j" + ivy--switch-buffer-other-window-action + "other window") + ("k" + ivy--kill-buffer-action + "kill") + ("r" + ivy--rename-buffer-action + "rename"))) + +(ivy-set-actions + t + `(("i" ,(lambda (x) (insert (if (stringp x) x (car x)))) "insert") + ("w" ,(lambda (x) (kill-new (if (stringp x) x (car x)))) "copy"))) + +(defun ivy--switch-buffer-matcher (regexp candidates) + "Return REGEXP matching CANDIDATES. +Skip buffers that match `ivy-ignore-buffers'." + (let ((res (ivy--re-filter regexp candidates))) + (if (or (null ivy-use-ignore) + (null ivy-ignore-buffers)) + res + (or (cl-remove-if + (lambda (buf) + (cl-find-if + (lambda (f-or-r) + (if (functionp f-or-r) + (funcall f-or-r buf) + (string-match-p f-or-r buf))) + ivy-ignore-buffers)) + res) + (and (eq ivy-use-ignore t) + res))))) + +(defun ivy-append-face (str face) + "Append to STR the property FACE." + (setq str (copy-sequence str)) + (ivy-add-face-text-property 0 (length str) face str t) + str) + +(defun ivy-switch-buffer-transformer (str) + "Transform candidate STR when switching buffers." + (let ((b (get-buffer str))) + (if (and b (buffer-file-name b)) + (cond + ((and (not (ignore-errors (file-remote-p (buffer-file-name b)))) + (not (verify-visited-file-modtime b))) + (ivy-append-face str 'ivy-modified-outside-buffer)) + ((buffer-modified-p b) + (ivy-append-face str 'ivy-modified-buffer)) + (t str)) + str))) + +(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)))))) + cands))))) + +;;;###autoload +(defun ivy-switch-buffer () + "Switch to another buffer." + (interactive) + (ivy-read "Switch to buffer: " #'internal-complete-buffer + :keymap ivy-switch-buffer-map + :preselect (buffer-name (other-buffer (current-buffer))) + :action #'ivy--switch-buffer-action + :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'." + (interactive) + (let ((ivy-initial-inputs-alist + '((ivy-switch-buffer . "{}")))) + (ivy-switch-buffer))) + +;;;###autoload +(defun ivy-switch-buffer-other-window () + "Switch to another buffer in another window." + (interactive) + (ivy-read "Switch to buffer in other window: " #'internal-complete-buffer + :matcher #'ivy--switch-buffer-matcher + :preselect (buffer-name (other-buffer (current-buffer))) + :action #'ivy--switch-buffer-other-window-action + :keymap ivy-switch-buffer-map + :caller 'ivy-switch-buffer-other-window)) + +(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. +The region to extract is determined by the respective values of +point before and after applying FN to ARGS." + (let (text) + (with-ivy-window + (let ((beg (point)) + (bol (line-beginning-position)) + (eol (line-end-position)) + end) + (unwind-protect + (progn (apply fn args) + (setq end (goto-char (max bol (min (point) eol)))) + (setq text (buffer-substring-no-properties beg end)) + (ivy--pulse-region beg end)) + (unless text + (goto-char beg))))) + (when text + (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. +If optional ARG is non-nil, pull in the next ARG +words (previous if ARG is negative)." + (interactive "p") + (ivy--yank-by #'forward-word arg)) + +(defun ivy-yank-symbol (&optional arg) + "Pull next symbol from buffer into search string. +If optional ARG is non-nil, pull in the next ARG +symbols (previous if ARG is negative)." + (interactive "p") + ;; Emacs < 24.4 compatibility + (unless (fboundp 'forward-symbol) + (require 'thingatpt)) + (ivy--yank-by #'forward-symbol (or arg 1))) + +(defun ivy-yank-char (&optional arg) + "Pull next character from buffer into search string. +If optional ARG is non-nil, pull in the next ARG +characters (previous if ARG is negative)." + (interactive "p") + (ivy--yank-by #'forward-char arg)) + +(defvar ivy--pulse-overlay nil + "Overlay used to highlight yanked word.") + +(defvar ivy--pulse-timer nil + "Timer used to dispose of `ivy--pulse-overlay'.") + +(defcustom ivy-pulse-delay 0.5 + "Number of seconds to display `ivy-yanked-word' highlight. +When nil, disable highlighting." + :type '(choice + (number :tag "Delay in seconds") + (const :tag "Disable" nil))) + +(defun ivy--pulse-region (start end) + "Temporarily highlight text between START and END. +The \"pulse\" duration is determined by `ivy-pulse-delay'." + (when ivy-pulse-delay + (if ivy--pulse-overlay + (let ((ostart (overlay-start ivy--pulse-overlay)) + (oend (overlay-end ivy--pulse-overlay))) + (when (< end start) + (cl-rotatef start end)) + ;; Extend the existing overlay's region to include START..END, + ;; but only if the two regions are contiguous. + (move-overlay ivy--pulse-overlay + (if (= start oend) ostart start) + (if (= end ostart) oend end))) + (setq ivy--pulse-overlay (make-overlay start end)) + (overlay-put ivy--pulse-overlay 'face 'ivy-yanked-word)) + (when ivy--pulse-timer + (cancel-timer ivy--pulse-timer)) + (setq ivy--pulse-timer + (run-at-time ivy-pulse-delay nil #'ivy--pulse-cleanup)))) + +(defun ivy--pulse-cleanup () + "Cancel `ivy--pulse-timer' and delete `ivy--pulse-overlay'." + (when ivy--pulse-timer + (cancel-timer ivy--pulse-timer) + (setq ivy--pulse-timer nil)) + (when ivy--pulse-overlay + (delete-overlay ivy--pulse-overlay) + (setq ivy--pulse-overlay nil))) + +(defun ivy-kill-ring-save () + "Store the current candidates into the kill ring. +If the region is active, forward to `kill-ring-save' instead." + (interactive) + (if (region-active-p) + (call-interactively 'kill-ring-save) + (kill-new + (mapconcat + #'identity + ivy--old-cands + "\n")))) + +(defun ivy-insert-current () + "Make the current candidate into current input. +Don't finish completion." + (interactive) + (delete-minibuffer-contents) + (let ((end (and ivy--directory + (ivy--dirname-p (ivy-state-current ivy-last)) + -1))) + (insert (substring-no-properties + (ivy-state-current ivy-last) 0 end)))) + +(defun ivy-insert-current-full () + "Insert the full Yank the current directory into the minibuffer." + (interactive) + (insert ivy--directory)) + +(defcustom ivy-preferred-re-builders + '((ivy--regex-plus . "ivy") + (ivy--regex-ignore-order . "order") + (ivy--regex-fuzzy . "fuzzy")) + "Alist of preferred re-builders with display names. +This list can be rotated with `ivy-rotate-preferred-builders'." + :type '(alist :key-type function :value-type string)) + +(defun ivy-rotate-preferred-builders () + "Switch to the next re builder in `ivy-preferred-re-builders'." + (interactive) + (when ivy-preferred-re-builders + (setq ivy--old-re nil) + (setq ivy--regex-function + (let ((cell (assq ivy--regex-function ivy-preferred-re-builders))) + (car (or (cadr (memq cell ivy-preferred-re-builders)) + (car ivy-preferred-re-builders))))))) + +(defun ivy-toggle-fuzzy () + "Toggle the re builder between `ivy--regex-fuzzy' and `ivy--regex-plus'." + (interactive) + (setq ivy--old-re nil) + (if (eq ivy--regex-function 'ivy--regex-fuzzy) + (setq ivy--regex-function 'ivy--regex-plus) + (setq ivy--regex-function 'ivy--regex-fuzzy))) + +(defvar ivy--reverse-i-search-symbol nil + "Store the history symbol.") + +(defun ivy-reverse-i-search-kill () + "Remove the current item from history" + (interactive) + (if (not (eolp)) + (ivy-kill-line) + (let ((current (ivy-state-current ivy-last))) + (if (symbolp ivy--reverse-i-search-symbol) + (set + ivy--reverse-i-search-symbol + (delete current (symbol-value ivy--reverse-i-search-symbol))) + (ring-remove + ivy--reverse-i-search-symbol + (ring-member ivy--reverse-i-search-symbol (ivy-state-current ivy-last))))) + (ivy--kill-current-candidate))) + +(defvar ivy-reverse-i-search-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-k") 'ivy-reverse-i-search-kill) + map)) + +(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 HISTORY." + (setq ivy--reverse-i-search-symbol history) + (cond ((symbolp history) + (delete-dups + (copy-sequence (symbol-value history)))) + ((ring-p history) + (delete-dups + (when (> (ring-size history) 0) + (ring-elements history)))) + ((sequencep history) + (delete-dups + (copy-sequence history))) + (t + (error "Expected a symbol, ring, or sequence: %S" history)))) + +(defun ivy-reverse-i-search () + "Enter a recursive `ivy-read' session using the current history. +The selected history element will be inserted into the minibuffer. +\\ +You can also delete an element from history with \\[ivy-reverse-i-search-kill]." + (interactive) + (cond + ((= (minibuffer-depth) 0) + (user-error + "This command is intended to be called with \"C-r\" from `ivy-read'.")) + ;; don't recur + ((and (> (minibuffer-depth) 1) + (eq (ivy-state-caller ivy-last) 'ivy-reverse-i-search))) + (t + (let ((enable-recursive-minibuffers t) + (old-last ivy-last)) + (ivy-read "Reverse-i-search: " + (ivy-history-contents (ivy-state-history ivy-last)) + :keymap ivy-reverse-i-search-map + :action (lambda (x) + (ivy--reset-state + (setq ivy-last old-last)) + (delete-minibuffer-contents) + (insert (substring-no-properties x)) + (ivy--cd-maybe)) + :caller 'ivy-reverse-i-search))))) + +(defun ivy-restrict-to-matches () + "Restrict candidates to current input and erase input." + (interactive) + (delete-minibuffer-contents) + (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 + "Buffer-local value of `ivy-last'. +Can't re-use `ivy-last' because using e.g. `swiper' in the same +buffer would modify `ivy-last'.") + +(defvar ivy-occur-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [mouse-1] 'ivy-occur-click) + (define-key map (kbd "RET") 'ivy-occur-press-and-switch) + (define-key map (kbd "j") 'ivy-occur-next-line) + (define-key map (kbd "k") 'ivy-occur-previous-line) + (define-key map (kbd "h") 'backward-char) + (define-key map (kbd "l") 'forward-char) + (define-key map (kbd "f") 'ivy-occur-press) + (define-key map (kbd "g") 'ivy-occur-revert-buffer) + (define-key map (kbd "a") 'ivy-occur-read-action) + (define-key map (kbd "o") 'ivy-occur-dispatch) + (define-key map (kbd "c") 'ivy-occur-toggle-calling) + (define-key map (kbd "q") 'quit-window) + (define-key map (kbd "R") 'read-only-mode) + (define-key map (kbd "C-d") 'ivy-occur-delete-candidate) + map) + "Keymap for Ivy Occur mode.") + +(defun ivy-occur-toggle-calling () + "Toggle `ivy-calling'." + (interactive) + (if (setq ivy-calling (not ivy-calling)) + (progn + (setq mode-name "Ivy-Occur [calling]") + (ivy-occur-press)) + (setq mode-name "Ivy-Occur")) + (force-mode-line-update)) + +(defun ivy--find-occur-buffer () + (let ((cb (current-buffer))) + (cl-find-if + (lambda (b) + (with-current-buffer b + (and (eq major-mode 'ivy-occur-grep-mode) + (equal cb (ivy-state-buffer ivy-occur-last))))) + (buffer-list)))) + +(defun ivy--select-occur-buffer () + (let* ((ob (ivy--find-occur-buffer)) + (ow (cl-find-if (lambda (w) (equal ob (window-buffer w))) + (window-list)))) + (if ow + (select-window ow) + (pop-to-buffer ob)))) + +(defun ivy-occur-next-line (&optional arg) + "Move the cursor down ARG lines. +When `ivy-calling' isn't nil, call `ivy-occur-press'." + (interactive "p") + (let ((offset (cond ((derived-mode-p 'ivy-occur-grep-mode) 5) + ((derived-mode-p 'ivy-occur-mode) 2)))) + (if offset + (progn + (if (< (line-number-at-pos) offset) + (progn + (goto-char (point-min)) + (forward-line (1- offset))) + (forward-line arg) + (when (eolp) + (forward-line -1))) + (when ivy-calling + (ivy-occur-press))) + (ivy--select-occur-buffer) + (ivy-occur-next-line arg) + (ivy-occur-press-and-switch)))) + +(defun ivy-occur-previous-line (&optional arg) + "Move the cursor up ARG lines. +When `ivy-calling' isn't nil, call `ivy-occur-press'." + (interactive "p") + (let ((offset (cond ((derived-mode-p 'ivy-occur-grep-mode) 5) + ((derived-mode-p 'ivy-occur-mode) 2)))) + (if offset + (progn + (forward-line (- arg)) + (when (< (line-number-at-pos) offset) + (goto-char (point-min)) + (forward-line (1- offset))) + (when ivy-calling + (ivy-occur-press))) + (ivy--select-occur-buffer) + (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]. + +\\{ivy-occur-mode-map}" + (setq-local view-read-only nil)) + +(defvar ivy-occur-grep-mode-map + (let ((map (copy-keymap ivy-occur-mode-map))) + (define-key map (kbd "C-x C-q") 'ivy-wgrep-change-to-wgrep-mode) + (define-key map "w" 'ivy-wgrep-change-to-wgrep-mode) + map) + "Keymap for Ivy Occur Grep mode.") + +(defun ivy-occur-delete-candidate () + (interactive) + (let ((inhibit-read-only t)) + (delete-region (line-beginning-position) + (1+ (line-end-position))))) + +(define-derived-mode ivy-occur-grep-mode grep-mode "Ivy-Occur" + "Major mode for output from \\[ivy-occur]. + +\\{ivy-occur-grep-mode-map}" + (setq-local view-read-only nil) + (when (fboundp 'wgrep-setup) + (wgrep-setup))) + +(defun ivy--starts-with-dotslash (str) + (string-match-p "\\`\\.[/\\]" str)) + +(defun ivy--occur-insert-lines (cands) + "Insert CANDS into `ivy-occur' buffer." + (font-lock-mode -1) + (dolist (cand cands) + (setq cand + (if (string-match "\\`\\(.*:[0-9]+:\\)\\(.*\\)\\'" cand) + (let ((file-and-line (match-string 1 cand)) + (grep-line (match-string 2 cand))) + (concat + (propertize file-and-line 'face 'ivy-grep-info) + (ivy--highlight-fuzzy grep-line))) + (ivy--highlight-fuzzy (copy-sequence cand)))) + (add-text-properties + 0 (length cand) + '(mouse-face + highlight + help-echo "mouse-1: call ivy-action") + cand) + (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. + +The new buffer remembers current action(s). + +While in the *ivy-occur* buffer, selecting a candidate with RET or +a mouse click will call the appropriate action for that candidate. + +There is no limit on the number of *ivy-occur* buffers." + (interactive) + (if (not (window-minibuffer-p)) + (user-error "No completion session is active") + (let* ((caller (ivy-state-caller ivy-last)) + (occur-fn (or (plist-get ivy--occurs-list caller) + #'ivy--occur-default)) + (buffer + (generate-new-buffer + (format "*ivy-occur%s \"%s\"*" + (if caller + (concat " " (prin1-to-string caller)) + "") + ivy-text)))) + (with-current-buffer buffer + (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) + (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 original buffer +is updated, since the line numbers no longer match. + +Calling this function is as if you called `ivy-occur' on the +updated original buffer." + (interactive) + (let ((caller (ivy-state-caller ivy-occur-last)) + (ivy-last ivy-occur-last)) + (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") + +(defun ivy-wgrep-change-to-wgrep-mode () + "Forward to `wgrep-change-to-wgrep-mode'." + (interactive) + (if (require 'wgrep nil 'noerror) + (wgrep-change-to-wgrep-mode) + (error "Package wgrep isn't installed"))) + +(defun ivy-occur-read-action () + "Select one of the available actions as the current one." + (interactive) + (let ((ivy-last ivy-occur-last)) + (ivy-read-action))) + +(defun ivy-occur-dispatch () + "Call one of the available actions on the current item." + (interactive) + (let* ((state-action (ivy-state-action ivy-occur-last)) + (actions (if (symbolp state-action) + state-action + (copy-sequence state-action)))) + (unwind-protect + (progn + (ivy-occur-read-action) + (ivy-occur-press)) + (setf (ivy-state-action ivy-occur-last) actions)))) + +(defun ivy-occur-click (event) + "Execute action for the current candidate. +EVENT gives the mouse position." + (interactive "e") + (let ((window (posn-window (event-end event))) + (pos (posn-point (event-end event)))) + (with-current-buffer (window-buffer window) + (goto-char pos) + (ivy-occur-press)))) + +(declare-function swiper--cleanup "swiper") +(declare-function swiper--add-overlays "swiper") +(defvar ivy-occur-timer nil) + +(defun ivy--occur-press-update-window () + (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))) + (when (buffer-live-p buffer) + (cond ((or (not (window-live-p window)) + (equal window (selected-window))) + (save-selected-window + (setf (ivy-state-window ivy-occur-last) + (display-buffer buffer)))) + ((not (equal (window-buffer window) buffer)) + (with-selected-window window + (switch-to-buffer buffer))))))) + + ((memq (ivy-state-caller ivy-occur-last) + '(counsel-describe-function counsel-describe-variable)) + (setf (ivy-state-window ivy-occur-last) + (selected-window)) + (selected-window)))) + +(defun ivy--occur-press-buffer () + (let ((buffer (ivy-state-buffer ivy-last))) + (if (buffer-live-p buffer) + buffer + (current-buffer)))) + +(defun ivy-occur-press () + "Execute action for the current candidate." + (interactive) + (ivy--occur-press-update-window) + (when (save-excursion + (beginning-of-line) + (looking-at "\\(?:./\\| \\)\\(.*\\)$")) + (let* ((ivy-last ivy-occur-last) + (ivy-text (ivy-state-text ivy-last)) + (str (buffer-substring + (match-beginning 1) + (match-end 1))) + (offset (or (get-text-property 0 'offset str) 0)) + (coll (ivy-state-collection ivy-last)) + (action (ivy--get-action ivy-last)) + (ivy-exit 'done)) + (with-ivy-window + (with-current-buffer (ivy--occur-press-buffer) + (save-restriction + (widen) + (funcall action + (if (and (consp coll) + (consp (car coll))) + (assoc str coll) + (substring str offset))))) + (if (memq (ivy-state-caller ivy-last) + (append '(swiper swiper-isearch) ivy-highlight-grep-commands)) + (with-current-buffer (window-buffer (selected-window)) + (swiper--cleanup) + (swiper--add-overlays + (ivy--regex ivy-text) + (line-beginning-position) + (line-end-position) + (selected-window)) + (when (timerp ivy-occur-timer) + (cancel-timer ivy-occur-timer)) + (setq ivy-occur-timer + (run-at-time 1.0 nil 'swiper--cleanup)))))))) + +(defun ivy-occur-press-and-switch () + "Execute action for the current candidate and switch window." + (interactive) + (ivy-occur-press) + (select-window (ivy--get-window ivy-occur-last))) + +(defun ivy--marked-p () + (member (ivy-state-current ivy-last) ivy-marked-candidates)) + +(defun ivy--unmark (cand) + (setcar (member cand ivy--all-candidates) + (setcar (member cand ivy--old-cands) + (substring cand (length ivy-mark-prefix)))) + (setq ivy-marked-candidates + (delete cand ivy-marked-candidates))) + +(defun ivy--mark (cand) + (let ((marked-cand (concat ivy-mark-prefix cand))) + (setcar (member cand ivy--all-candidates) + (setcar (member cand ivy--old-cands) marked-cand)) + (setq ivy-marked-candidates + (append ivy-marked-candidates (list marked-cand))))) + +(defun ivy-mark () + "Mark the selected candidate and move to the next one. + +In `ivy-call', :action will be called in turn for all marked +candidates. + +However, if :multi-action was supplied to `ivy-read', then it +will be called with `ivy-marked-candidates'. This way, it can +make decisions based on the whole marked list." + (interactive) + (unless (ivy--marked-p) + (ivy--mark (ivy-state-current ivy-last))) + (ivy-next-line)) + +(defun ivy-unmark () + "Unmark the selected candidate and move to the next one." + (interactive) + (when (ivy--marked-p) + (ivy--unmark (ivy-state-current ivy-last))) + (ivy-next-line)) + +(defun ivy-unmark-backward () + "Move to the previous candidate and unmark it." + (interactive) + (ivy-previous-line) + (ivy--exhibit) + (when (ivy--marked-p) + (ivy--unmark (ivy-state-current ivy-last)))) + +(defun ivy-toggle-marks () + "Toggle mark for all narrowed candidates." + (interactive) + (dolist (cand ivy--old-cands) + (if (member cand ivy-marked-candidates) + (ivy--unmark cand) + (ivy--mark cand)))) + +(defconst ivy-help-file (let ((default-directory + (if load-file-name + (file-name-directory load-file-name) + default-directory))) + (if (file-exists-p "ivy-help.org") + (expand-file-name "ivy-help.org") + (if (file-exists-p "doc/ivy-help.org") + (expand-file-name "doc/ivy-help.org")))) + "The file for `ivy-help'.") + +(defvar org-hide-emphasis-markers) + +(defun ivy-help () + "Help for `ivy'." + (interactive) + (let ((buf (get-buffer "*Ivy Help*"))) + (unless buf + (setq buf (get-buffer-create "*Ivy Help*")) + (with-current-buffer buf + (insert-file-contents ivy-help-file) + (org-mode) + (setq-local org-hide-emphasis-markers t) + (view-mode) + (goto-char (point-min)) + (let ((inhibit-message t)) + (org-cycle '(64))))) + (if (eq this-command 'ivy-help) + (switch-to-buffer buf) + (with-ivy-window + (pop-to-buffer buf))) + (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 --git a/elpa/ivy-0.13.1/ivy.info b/elpa/ivy-0.13.1/ivy.info new file mode 100644 index 0000000..caa0fd6 --- /dev/null +++ b/elpa/ivy-0.13.1/ivy.info @@ -0,0 +1,1954 @@ +This is ivy.info, produced by makeinfo version 6.5 from ivy.texi. + +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. + + Copyright (C) 2015-2019 Free Software Foundation, Inc. + + 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". +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Ivy: (ivy). Using Ivy for completion. +END-INFO-DIR-ENTRY + + +File: ivy.info, Node: Top, Next: Introduction, Up: (dir) + +Ivy User Manual +*************** + +* Menu: + +* Introduction:: +* Installation:: +* Getting started:: +* Key bindings:: +* Completion Styles:: +* Customization:: +* Commands:: +* API:: +* Variable Index:: +* Keystroke Index:: + +— 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 ivy-occur:: + +Commands + +* File Name Completion:: +* Buffer Name Completion:: +* Counsel commands:: + +File Name Completion + +* Using TRAMP:: + +API + +* Required arguments for ivy-read:: +* Optional arguments for ivy-read:: +* Example - counsel-describe-function:: +* Example - counsel-locate:: +* Example - ivy-read-with-extra-properties:: + + + +File: ivy.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top + +1 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. + +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. + + +File: ivy.info, Node: Installation, Next: Getting started, Prev: Introduction, Up: Top + +2 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:: + + +File: ivy.info, Node: Installing from Emacs Package Manager, Next: Installing from the Git repository, Up: Installation + +2.1 Installing from Emacs Package Manager +========================================= + +‘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: + + (require 'package) + (add-to-list 'package-archives + '("melpa" . "https://melpa.org/packages/")) + + After this do ‘M-x’ ‘package-refresh-contents’ ‘RET’, followed by +‘M-x’ ‘package-install’ ‘RET’ ‘counsel’ ‘RET’. + + For package manager details, see *note (emacs)Packages::. + + +File: ivy.info, Node: Installing from the Git repository, Prev: Installing from Emacs Package Manager, Up: Installation + +2.2 Installing from the Git repository +====================================== + +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: + + cd ~/git && git clone https://github.com/abo-abo/swiper + cd swiper && make compile + + Second, add these lines to the Emacs init file: + + (add-to-list 'load-path "~/git/swiper/") + (require 'ivy) + + Then, update the code with: + + git pull + make + + +File: ivy.info, Node: Getting started, Next: Key bindings, Prev: Installation, Up: Top + +3 Getting started +***************** + +First enable Ivy completion everywhere: + + (ivy-mode 1) + + Note: ‘ivy-mode’ can be toggled on and off with ‘M-x’ ‘ivy-mode’. + +* Menu: + +* Basic customization:: + + +File: ivy.info, Node: Basic customization, Up: Getting started + +3.1 Basic customization +======================= + +Here are some basic settings particularly useful for new Ivy users: + + (setq ivy-use-virtual-buffers t) + (setq ivy-count-format "(%d/%d) ") + + 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. + + +File: ivy.info, Node: Key bindings, Next: Completion Styles, Prev: Getting started, Up: Top + +4 Key bindings +************** + +* Menu: + +* Global key bindings:: +* Minibuffer key bindings:: + + +File: ivy.info, Node: Global key bindings, Next: Minibuffer key bindings, Up: Key bindings + +4.1 Global key bindings +======================= + +Here is a list of commands that are useful to be bound globally, along +with some sample bindings: + +Ivy-based interface to standard commands +........................................ + + (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) + +Ivy-based interface to shell and system tools +............................................. + + (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) + +Ivy-resume and other commands +............................. + + ‘ivy-resume’ resumes the last Ivy-based completion. + + (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) + + You can also enable ‘counsel-mode’ to make some global key binding +remapping for you. + + +File: ivy.info, Node: Minibuffer key bindings, Prev: Global key bindings, Up: Key bindings + +4.2 Minibuffer key bindings +=========================== + +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’. + +* 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:: + + +File: ivy.info, Node: Key bindings for navigation, Next: Key bindings for single selection action then exit minibuffer, Up: Minibuffer key bindings + +4.2.1 Key bindings for navigation +--------------------------------- + + • ‘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. + + +File: ivy.info, Node: Key bindings for single selection action then exit minibuffer, Next: Key bindings for multiple selections and actions keep minibuffer open, Prev: Key bindings for navigation, Up: Minibuffer key bindings + +4.2.2 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. + +‘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: + + (should + (equal (ivy-with + '(progn + (ivy-read "Test: " '("can do" "can't, sorry" "other")) + ivy-text) + "c ") + "can")) + +‘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’. + + +File: ivy.info, Node: Key bindings for multiple selections and actions keep minibuffer open, Next: Key bindings that alter the minibuffer input, Prev: Key bindings for single selection action then exit minibuffer, Up: Minibuffer key bindings + +4.2.3 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. + +‘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’). + + +File: ivy.info, Node: Key bindings that alter the minibuffer input, Next: Other key bindings, Prev: Key bindings for multiple selections and actions keep minibuffer open, Up: Minibuffer key bindings + +4.2.4 Key bindings that alter the minibuffer input +-------------------------------------------------- + +‘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. + + +File: ivy.info, Node: Other key bindings, Next: Hydra in the minibuffer, Prev: Key bindings that alter the minibuffer input, Up: Minibuffer key bindings + +4.2.5 Other key bindings +------------------------ + +‘M-w’ (‘ivy-kill-ring-save’) +............................ + + Copies selected candidates to the kill ring. + + Copies the region if the region is active. + + +File: ivy.info, Node: Hydra in the minibuffer, Next: Saving the current completion session to a buffer, Prev: Other key bindings, Up: Minibuffer key bindings + +4.2.6 Hydra in the minibuffer +----------------------------- + +‘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. + + +File: ivy.info, Node: Saving the current completion session to a buffer, Prev: Hydra in the minibuffer, Up: Minibuffer key bindings + +4.2.7 Saving the current completion session to a buffer +------------------------------------------------------- + +‘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$*’. + + +File: ivy.info, Node: Completion Styles, Next: Customization, Prev: Key bindings, Up: Top + +5 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 ‘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: + + (setq ivy-re-builders-alist + '((t . ivy--regex-plus))) + + This example shows a custom regex builder assigned to file name +completion: + + (setq ivy-re-builders-alist + '((read-file-name-internal . ivy--regex-fuzzy) + (t . ivy--regex-plus))) + + 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’. + +* Menu: + +* ivy--regex-plus:: +* ivy--regex-ignore-order:: +* ivy--regex-fuzzy:: + + +File: ivy.info, Node: ivy--regex-plus, Next: ivy--regex-ignore-order, Up: Completion Styles + +5.1 ivy–regex-plus +================== + +‘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 + + "\\(for\\).*\\(example\\)" + + 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. + + +File: ivy.info, Node: ivy--regex-ignore-order, Next: ivy--regex-fuzzy, Prev: ivy--regex-plus, Up: Completion Styles + +5.2 ivy–regex-ignore-order +========================== + +‘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"’. + + +File: ivy.info, Node: ivy--regex-fuzzy, Prev: ivy--regex-ignore-order, Up: Completion Styles + +5.3 ivy–regex-fuzzy +=================== + +‘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. + + +File: ivy.info, Node: Customization, Next: Commands, Prev: Completion Styles, Up: Top + +6 Customization +*************** + +* Menu: + +* Faces:: +* Defcustoms:: +* Actions:: +* Packages:: + + +File: ivy.info, Node: Faces, Next: Defcustoms, Up: Customization + +6.1 Faces +========= + +‘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: + + (setq confirm-nonexistent-file-or-buffer t) + + 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: + + (setq ivy-use-virtual-buffers t) + +‘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’. + + +File: ivy.info, Node: Defcustoms, Next: Actions, Prev: Faces, Up: Customization + +6.2 Defcustoms +============== + + -- 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: + + (setq ivy-count-format "") + + To also display the current candidate: + + (setq ivy-count-format "(%d/%d) ") + + 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. + + +File: ivy.info, Node: Actions, Next: Packages, Prev: Defcustoms, Up: Customization + +6.3 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:: + + +File: ivy.info, Node: What are actions?, Next: How can different actions be called?, Up: Actions + +6.3.1 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. + +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. + + (defun ivy-insert-action (x) + (with-ivy-window + (insert x))) + + +File: ivy.info, Node: How can different actions be called?, Next: How to modify the actions list?, Prev: What are actions?, Up: Actions + +6.3.2 How can different actions be called? +------------------------------------------ + + • ‘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. + + +File: ivy.info, Node: How to modify the actions list?, Next: Example - add two actions to each command, Prev: How can different actions be called?, Up: Actions + +6.3.3 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 ‘o’ is +designated for the default command. This way, ‘M-o o’ should be always +equivalent to ‘C-m’. + + +File: ivy.info, Node: Example - add two actions to each command, Next: Example - define a new command with several actions, Prev: How to modify the actions list?, Up: Actions + +6.3.4 Example - add two actions to each command +----------------------------------------------- + +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. + + (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"))) + + Then in any completion session, ‘M-o y’ invokes ‘ivy-yank-action’, +and ‘M-o i’ invokes ‘ivy-copy-to-buffer-action’. + +* Menu: + +* How to undo adding the two actions:: +* How to add actions to a specific command:: + + +File: ivy.info, Node: How to undo adding the two actions, Next: How to add actions to a specific command, Up: Example - add two actions to each command + +6.3.4.1 How to undo adding the two actions +.......................................... + +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: + + (ivy-set-actions t nil) + + +File: ivy.info, Node: How to add actions to a specific command, Prev: How to undo adding the two actions, Up: Example - add two actions to each command + +6.3.4.2 How to add actions to a specific command +................................................ + +Use the command name as the key: + + (ivy-set-actions + 'swiper + '(("i" ivy-copy-to-buffer-action "insert") + ("y" ivy-yank-action "yank"))) + + +File: ivy.info, Node: Example - define a new command with several actions, Prev: Example - add two actions to each command, Up: Actions + +6.3.5 Example - define a new command with several actions +--------------------------------------------------------- + + (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")))) + + 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 ivy-occur:: + + +File: ivy.info, Node: Test the above function with ivy-occur, Up: Example - define a new command with several actions + +6.3.5.1 Test the above function with ‘ivy-occur’ +................................................ + +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... + + +File: ivy.info, Node: Packages, Prev: Actions, Up: Customization + +6.4 Packages +============ + +‘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: + + (setq projectile-completion-system 'ivy) + +‘helm-make’ +........... + + Helm-make requires this setting for ivy completion. + + (setq helm-make-completion-method 'ivy) + +automatically integrated packages +................................. + + Ivy re-uses the following packages if they are installed: ‘avy’, + ‘amx’ or ‘smex’, ‘flx’, and ‘wgrep’. + + +File: ivy.info, Node: Commands, Next: API, Prev: Customization, Up: Top + +7 Commands +********** + +* Menu: + +* File Name Completion:: +* Buffer Name Completion:: +* Counsel commands:: + + +File: ivy.info, Node: File Name Completion, Next: Buffer Name Completion, Up: Commands + +7.1 File Name Completion +======================== + +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. + +* Menu: + +* Using TRAMP:: + + +File: ivy.info, Node: Using TRAMP, Up: File Name Completion + +7.1.1 Using TRAMP +----------------- + +‘~’ (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:/’. + + +File: ivy.info, Node: Buffer Name Completion, Next: Counsel commands, Prev: File Name Completion, Up: Commands + +7.2 Buffer Name Completion +========================== + + -- 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: + + (setq ivy-use-virtual-buffers t) + 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. + + +File: ivy.info, Node: Counsel commands, Prev: Buffer Name Completion, Up: Commands + +7.3 Counsel commands +==================== + +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. + + +File: ivy.info, Node: API, Next: Variable Index, Prev: Commands, Up: Top + +8 API +***** + +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’. + +* Menu: + +* Required arguments for ivy-read:: +* Optional arguments for ivy-read:: +* Example - counsel-describe-function:: +* Example - counsel-locate:: +* Example - ivy-read-with-extra-properties:: + + +File: ivy.info, Node: Required arguments for ivy-read, Next: Optional arguments for ivy-read, Up: API + +8.1 Required arguments for ‘ivy-read’ +===================================== + +‘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’. + + +File: ivy.info, Node: Optional arguments for ivy-read, Next: Example - counsel-describe-function, Prev: Required arguments for ivy-read, Up: API + +8.2 Optional arguments for ‘ivy-read’ +===================================== + +‘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. + + +File: ivy.info, Node: Example - counsel-describe-function, Next: Example - counsel-locate, Prev: Optional arguments for ivy-read, Up: API + +8.3 Example - ‘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 ‘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. + + (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)) + + 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’. + + +File: ivy.info, Node: Example - counsel-locate, Next: Example - ivy-read-with-extra-properties, Prev: Example - counsel-describe-function, Up: API + +8.4 Example - ‘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 ‘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. + + (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)) + + 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. + + +File: ivy.info, Node: Example - ivy-read-with-extra-properties, Prev: Example - counsel-locate, Up: API + +8.5 Example - ‘ivy-read-with-extra-properties’ +============================================== + +This is another example to show how to associate additional values to +each displayed strings. + + (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) + )))) + + 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. + + +File: ivy.info, Node: Variable Index, Next: Keystroke Index, Prev: API, Up: Top + +Variable Index +************** + +[index] +* Menu: + +* ivy-alt-done: Key bindings for single selection action then exit minibuffer. + (line 30) +* ivy-alt-done <1>: File Name Completion. (line 12) +* ivy-avy: Key bindings for single selection action then exit minibuffer. + (line 64) +* ivy-backward-delete-char: File Name Completion. (line 19) +* ivy-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 16) +* ivy-confirm-face: Faces. (line 34) +* ivy-count-format: Defcustoms. (line 6) +* ivy-current-match: Faces. (line 9) +* ivy-dispatching-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 26) +* ivy-dispatching-done: Key bindings for single selection action then exit minibuffer. + (line 24) +* ivy-display-style: Defcustoms. (line 24) +* ivy-done: Key bindings for single selection action then exit minibuffer. + (line 19) +* ivy-extra-directories: File Name Completion. (line 45) +* ivy-height: Key bindings for navigation. + (line 21) +* ivy-immediate-done: Key bindings for single selection action then exit minibuffer. + (line 53) +* ivy-insert-current: Key bindings that alter the minibuffer input. + (line 23) +* ivy-kill-ring-save: Other key bindings. (line 9) +* ivy-match-required-face: Faces. (line 53) +* ivy-minibuffer-grow: Hydra in the minibuffer. + (line 45) +* ivy-minibuffer-map: Minibuffer key bindings. + (line 6) +* ivy-minibuffer-match-face-1: Faces. (line 14) +* ivy-minibuffer-match-face-2: Faces. (line 19) +* ivy-minibuffer-match-face-3: Faces. (line 24) +* ivy-minibuffer-match-face-4: Faces. (line 29) +* ivy-minibuffer-shrink: Hydra in the minibuffer. + (line 50) +* ivy-modified-buffer: Faces. (line 88) +* ivy-modified-outside-buffer: Faces. (line 93) +* ivy-next-action: Hydra in the minibuffer. + (line 60) +* ivy-next-history-element: Key bindings that alter the minibuffer input. + (line 9) +* ivy-next-line-and-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 36) +* ivy-occur: Saving the current completion session to a buffer. + (line 9) +* ivy-occur-click: Saving the current completion session to a buffer. + (line 21) +* ivy-occur-dispatch: Saving the current completion session to a buffer. + (line 41) +* ivy-occur-press: Saving the current completion session to a buffer. + (line 16) +* ivy-occur-read-action: Saving the current completion session to a buffer. + (line 36) +* ivy-on-del-error-function: Defcustoms. (line 31) +* ivy-partial-or-done: Key bindings for single selection action then exit minibuffer. + (line 37) +* ivy-prev-action: Hydra in the minibuffer. + (line 55) +* ivy-previous-history-element: Key bindings that alter the minibuffer input. + (line 18) +* ivy-previous-line-and-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 47) +* ivy-read-action: Hydra in the minibuffer. + (line 65) +* ivy-remote: Faces. (line 71) +* ivy-restrict-to-matches: Key bindings that alter the minibuffer input. + (line 40) +* ivy-resume: Key bindings for multiple selections and actions keep minibuffer open. + (line 55) +* ivy-reverse-i-search: Key bindings that alter the minibuffer input. + (line 48) +* ivy-rotate-preferred-builders: Hydra in the minibuffer. + (line 40) +* ivy-subdir: Faces. (line 66) +* ivy-toggle-calling: Hydra in the minibuffer. + (line 34) +* ivy-toggle-case-fold: Hydra in the minibuffer. + (line 70) +* ivy-toggle-regexp-quote: File Name Completion. (line 41) +* ivy-use-virtual-buffers: Buffer Name Completion. + (line 6) +* ivy-virtual: Faces. (line 76) +* ivy-wrap: Key bindings for navigation. + (line 14) +* ivy-yank-word: Key bindings that alter the minibuffer input. + (line 32) + + +File: ivy.info, Node: Keystroke Index, Prev: Variable Index, Up: Top + +Keystroke Index +*************** + +[index] +* Menu: + +* /: File Name Completion. (line 35) +* / C-j: Using TRAMP. (line 24) +* //: File Name Completion. (line 25) +* // <1>: Using TRAMP. (line 17) +* <: Hydra in the minibuffer. + (line 50) +* >: Hydra in the minibuffer. + (line 45) +* ~: File Name Completion. (line 30) +* ~ <1>: Using TRAMP. (line 9) +* ~~: Using TRAMP. (line 29) +* a: Hydra in the minibuffer. + (line 65) +* a <1>: Saving the current completion session to a buffer. + (line 36) +* c: Hydra in the minibuffer. + (line 34) +* C: Hydra in the minibuffer. + (line 70) +* C-': Key bindings for single selection action then exit minibuffer. + (line 64) +* C-c C-o: Saving the current completion session to a buffer. + (line 9) +* C-j: Key bindings for single selection action then exit minibuffer. + (line 30) +* C-j <1>: File Name Completion. (line 12) +* C-m: Key bindings for single selection action then exit minibuffer. + (line 19) +* C-M-j: Key bindings for single selection action then exit minibuffer. + (line 53) +* C-M-m: Key bindings for multiple selections and actions keep minibuffer open. + (line 16) +* C-M-n: Key bindings for multiple selections and actions keep minibuffer open. + (line 36) +* C-M-o: Key bindings for multiple selections and actions keep minibuffer open. + (line 26) +* C-M-p: Key bindings for multiple selections and actions keep minibuffer open. + (line 47) +* C-o: Hydra in the minibuffer. + (line 9) +* C-r: Key bindings that alter the minibuffer input. + (line 48) +* DEL: File Name Completion. (line 19) +* f: Saving the current completion session to a buffer. + (line 16) +* j: Saving the current completion session to a buffer. + (line 26) +* k: Saving the current completion session to a buffer. + (line 31) +* m: Hydra in the minibuffer. + (line 40) +* M-i: Key bindings that alter the minibuffer input. + (line 23) +* M-j: Key bindings that alter the minibuffer input. + (line 32) +* M-n: Key bindings that alter the minibuffer input. + (line 9) +* M-o: Key bindings for single selection action then exit minibuffer. + (line 24) +* M-p: Key bindings that alter the minibuffer input. + (line 18) +* M-r: File Name Completion. (line 41) +* M-w: Other key bindings. (line 9) +* mouse-1: Saving the current completion session to a buffer. + (line 21) +* o: Saving the current completion session to a buffer. + (line 41) +* q: Saving the current completion session to a buffer. + (line 46) +* RET: Key bindings for single selection action then exit minibuffer. + (line 19) +* RET <1>: Saving the current completion session to a buffer. + (line 16) +* s: Hydra in the minibuffer. + (line 60) +* S-SPC: Key bindings that alter the minibuffer input. + (line 40) +* TAB: Key bindings for single selection action then exit minibuffer. + (line 37) +* w: Hydra in the minibuffer. + (line 55) + + + +Tag Table: +Node: Top1189 +Node: Introduction3100 +Node: Installation5623 +Node: Installing from Emacs Package Manager6073 +Node: Installing from the Git repository7187 +Node: Getting started8007 +Node: Basic customization8314 +Node: Key bindings8909 +Node: Global key bindings9101 +Node: Minibuffer key bindings11575 +Node: Key bindings for navigation12807 +Node: Key bindings for single selection action then exit minibuffer14014 +Node: Key bindings for multiple selections and actions keep minibuffer open16661 +Node: Key bindings that alter the minibuffer input19053 +Node: Other key bindings20998 +Node: Hydra in the minibuffer21376 +Node: Saving the current completion session to a buffer23794 +Node: Completion Styles25206 +Node: ivy--regex-plus26957 +Node: ivy--regex-ignore-order28443 +Node: ivy--regex-fuzzy28811 +Node: Customization29308 +Node: Faces29494 +Node: Defcustoms31923 +Node: Actions33217 +Node: What are actions?33543 +Node: How can different actions be called?34361 +Node: How to modify the actions list?34932 +Node: Example - add two actions to each command35592 +Node: How to undo adding the two actions36551 +Node: How to add actions to a specific command37003 +Node: Example - define a new command with several actions37419 +Node: Test the above function with ivy-occur38307 +Node: Packages39149 +Node: Commands40114 +Node: File Name Completion40299 +Node: Using TRAMP42095 +Node: Buffer Name Completion43597 +Node: Counsel commands44212 +Node: API44859 +Node: Required arguments for ivy-read45457 +Node: Optional arguments for ivy-read45976 +Node: Example - counsel-describe-function49402 +Node: Example - counsel-locate52260 +Node: Example - ivy-read-with-extra-properties56010 +Node: Variable Index57218 +Node: Keystroke Index64265 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/ivy-20210216.1611/colir.el b/elpa/ivy-20210216.1611/colir.el new file mode 100644 index 0000000..9e61273 --- /dev/null +++ b/elpa/ivy-20210216.1611/colir.el @@ -0,0 +1,124 @@ +;;; colir.el --- Color blending library -*- lexical-binding: t -*- + +;; Copyright (C) 2015-2019 Free Software Foundation, Inc. + +;; Author: Oleh Krehel + +;; This file is part of GNU Emacs. + +;; This file 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, 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. + +;; For a full copy of the GNU General Public License +;; see . + +;;; Commentary: + +;; This package solves the problem of adding a face with a background +;; to text which may already have a background. In all conflicting +;; areas, instead of choosing either the original or the new +;; background face, their blended sum is used. +;; +;; The blend mode functions are taken from URL +;; `https://en.wikipedia.org/wiki/Blend_modes'. + +;;; Code: + +(require 'cl-lib) +(require 'color) + +(defcustom colir-compose-method #'colir-compose-alpha + "Select a method to compose two color channels." + :group 'ivy + :type '(radio + (function-item colir-compose-alpha) + (function-item colir-compose-overlay) + (function-item colir-compose-soft-light))) + +(defun colir-compose-soft-light (a b) + "Compose A and B channels." + (if (< b 0.5) + (+ (* 2 a b) (* a a (- 1 b b))) + (+ (* 2 a (- 1 b)) (* (sqrt a) (- (* 2 b) 1))))) + +(defun colir-compose-overlay (a b) + "Compose A and B channels." + (if (< a 0.5) + (* 2 a b) + (- 1 (* 2 (- 1 a) (- 1 b))))) + +(defun colir-compose-alpha (a b &optional alpha gamma) + "Compose A and B channels. +Optional argument ALPHA is a number between 0.0 and 1.0 which corresponds +to the influence of A on the result. Default value is 0.5. +Optional argument GAMMA is used for gamma correction. Default value is 2.2." + (setq alpha (or alpha 0.5)) + (setq gamma (or gamma 2.2)) + (+ (* (expt a gamma) alpha) (* (expt b gamma) (- 1 alpha)))) + +(defun colir-blend (c1 c2) + "Blend the two colors C1 and C2 using `colir-compose-method'. +C1 and C2 are triples of floats in [0.0 1.0] range." + (apply #'color-rgb-to-hex + (cl-mapcar + (if (eq (frame-parameter nil 'background-mode) 'dark) + ;; this method works nicely for dark themes + 'colir-compose-soft-light + colir-compose-method) + c1 c2))) + +(defun colir-color-parse (color) + "Convert string COLOR to triple of floats in [0.0 1.0]." + (if (string-match "#\\([[:xdigit:]]\\{2\\}\\)\\([[:xdigit:]]\\{2\\}\\)\\([[:xdigit:]]\\{2\\}\\)" color) + (mapcar (lambda (v) (/ (string-to-number v 16) 255.0)) + (list (match-string 1 color) (match-string 2 color) (match-string 3 color))) + ;; does not work properly in terminal (maps color to nearest color + ;; from available color palette). + (color-name-to-rgb color))) + +(defun colir--blend-background (start next prevn face object) + (let ((background-prev (face-background prevn))) + (progn + (put-text-property + start next 'face + (if background-prev + (cons `(background-color + . ,(colir-blend + (colir-color-parse background-prev) + (colir-color-parse (face-background face nil t)))) + prevn) + (list face prevn)) + object)))) + +(defun colir-blend-face-background (start end face &optional object) + "Append to the face property of the text from START to END the face FACE. +When the text already has a face with a non-plain background, +blend it with the background of FACE. +Optional argument OBJECT is the string or buffer containing the text. +See also `font-lock-append-text-property'." + (let (next prev prevn) + (while (/= start end) + (setq next (next-single-property-change start 'face object end)) + (setq prev (get-text-property start 'face object)) + (setq prevn (if (listp prev) + (cl-find-if #'atom prev) + prev)) + (cond + ((or (keywordp (car-safe prev)) (consp (car-safe prev))) + (put-text-property start next 'face (cons face prev) object)) + ((facep prevn) + (colir--blend-background start next prevn face object)) + (t + (put-text-property start next 'face face object))) + (setq start next)))) + +(provide 'colir) + +;;; colir.el ends here diff --git a/elpa/ivy-20210216.1611/dir b/elpa/ivy-20210216.1611/dir new file mode 100644 index 0000000..b68b083 --- /dev/null +++ b/elpa/ivy-20210216.1611/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Ivy: (ivy). Using Ivy for completion. diff --git a/elpa/ivy-20210216.1611/elpa.el b/elpa/ivy-20210216.1611/elpa.el new file mode 100644 index 0000000..e49b8d4 --- /dev/null +++ b/elpa/ivy-20210216.1611/elpa.el @@ -0,0 +1,6 @@ +(setq package-user-dir + (expand-file-name + (format "~/.elpa/%s/elpa" + (concat emacs-version (when (getenv "MELPA_STABLE") "-stable"))))) +(package-initialize) +(add-to-list 'load-path default-directory) diff --git a/elpa/ivy-20210216.1611/ivy-autoloads.el b/elpa/ivy-20210216.1611/ivy-autoloads.el new file mode 100644 index 0000000..02ec7e5 --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy-autoloads.el @@ -0,0 +1,166 @@ +;;; ivy-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "colir" "colir.el" (0 0 0 0)) +;;; Generated autoloads from colir.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "colir" '("colir-"))) + +;;;*** + +;;;### (autoloads nil "ivy" "ivy.el" (0 0 0 0)) +;;; Generated autoloads from ivy.el + +(autoload 'ivy-resume "ivy" "\ +Resume the last completion session, or SESSION if non-nil. +With a prefix arg, try to restore a recorded completion session, +if one exists. + +\(fn &optional SESSION)" t nil) + +(autoload 'ivy-read "ivy" "\ +Read a string in the minibuffer, with completion. + +PROMPT is a string, normally ending in a colon and a space. +`ivy-count-format' is prepended to PROMPT during completion. + +COLLECTION is either a list of strings, a function, an alist, or +a hash table, supplied for `minibuffer-completion-table'. + +PREDICATE is applied to filter out the COLLECTION immediately. +This argument is for compatibility with `completing-read'. + +When REQUIRE-MATCH is non-nil, only members of COLLECTION can be +selected. + +If INITIAL-INPUT is non-nil, then insert that input in the +minibuffer initially. + +HISTORY is a name of a variable to hold the completion session +history. + +KEYMAP is composed with `ivy-minibuffer-map'. + +PRESELECT, when non-nil, determines which one of the candidates +matching INITIAL-INPUT to select initially. An integer stands +for the position of the desired candidate in the collection, +counting from zero. Otherwise, use the first occurrence of +PRESELECT in the collection. Comparison is first done with +`equal'. If that fails, and when applicable, match PRESELECT as +a regular expression. + +DEF is for compatibility with `completing-read'. + +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 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 +its only argument. When it's nil, ACTION is called on each marked +candidate. + +UNWIND is a function of no arguments to call before exiting. + +RE-BUILDER is a function transforming input text into a regex +pattern. + +MATCHER is a function which can override how candidates are +filtered based on user input. It takes a regex pattern and a +list of candidates, and returns the list of matching candidates. + +DYNAMIC-COLLECTION is a boolean specifying whether the list of +candidates is updated after each input by calling COLLECTION. + +EXTRA-PROPS is a plist that 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. + +\(fn PROMPT COLLECTION &key PREDICATE REQUIRE-MATCH INITIAL-INPUT HISTORY PRESELECT DEF KEYMAP UPDATE-FN SORT ACTION MULTI-ACTION UNWIND RE-BUILDER MATCHER DYNAMIC-COLLECTION EXTRA-PROPS CALLER)" nil nil) + +(autoload 'ivy-completing-read "ivy" "\ +Read a string in the minibuffer, with completion. + +This interface conforms to `completing-read' and can be used for +`completing-read-function'. + +PROMPT is a string that normally ends in a colon and a space. +COLLECTION is either a list of strings, an alist, an obarray, or a hash table. +PREDICATE limits completion to a subset of COLLECTION. +REQUIRE-MATCH is a boolean value or a symbol. See `completing-read'. +INITIAL-INPUT is a string inserted into the minibuffer initially. +HISTORY is a list of previously selected inputs. +DEF is the default value. +INHERIT-INPUT-METHOD is currently ignored. + +\(fn PROMPT COLLECTION &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HISTORY DEF INHERIT-INPUT-METHOD)" nil nil) + +(defvar ivy-mode nil "\ +Non-nil if Ivy mode is enabled. +See the `ivy-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `ivy-mode'.") + +(custom-autoload 'ivy-mode "ivy" nil) + +(autoload 'ivy-mode "ivy" "\ +Toggle Ivy mode on or off. +Turn Ivy mode on if ARG is positive, off otherwise. +Turning on Ivy mode sets `completing-read-function' to +`ivy-completing-read'. + +Global bindings: +\\{ivy-mode-map} + +Minibuffer bindings: +\\{ivy-minibuffer-map} + +\(fn &optional ARG)" t nil) + +(autoload 'ivy-switch-buffer "ivy" "\ +Switch to another buffer." t nil) + +(autoload 'ivy-switch-view "ivy" "\ +Switch to one of the window views stored by `ivy-push-view'." t nil) + +(autoload 'ivy-switch-buffer-other-window "ivy" "\ +Switch to another buffer in another window." t nil) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ivy" '("ivy-" "with-ivy-window"))) + +;;;*** + +;;;### (autoloads nil "ivy-overlay" "ivy-overlay.el" (0 0 0 0)) +;;; Generated autoloads from ivy-overlay.el + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ivy-overlay" '("ivy-"))) + +;;;*** + +;;;### (autoloads nil nil ("elpa.el" "ivy-faces.el" "ivy-pkg.el") +;;;;;; (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; ivy-autoloads.el ends here diff --git a/elpa/ivy-20210216.1611/ivy-faces.el b/elpa/ivy-20210216.1611/ivy-faces.el new file mode 100644 index 0000000..54492c4 --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy-faces.el @@ -0,0 +1,138 @@ +;;; ivy-faces.el --- Faces for Ivy -*- lexical-binding: t -*- + +;; Copyright (C) 2020 Free Software Foundation, Inc. + +;; Author: Oleh Krehel +;; Keywords: convenience + +;; 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 . + +;;; Commentary: + +;;; Code: + +(defgroup ivy-faces nil + "Font-lock faces for `ivy'." + :group 'ivy + :group 'faces) + +(defface ivy-current-match + '((((class color) (background light)) + :background "#1a4b77" :foreground "white" :extend t) + (((class color) (background dark)) + :background "#65a7e2" :foreground "black" :extend t)) + "Face used by Ivy for highlighting the current match.") + +(defface ivy-minibuffer-match-highlight + '((t :inherit highlight)) + "Face used by Ivy for highlighting the match under the cursor.") + +(defface ivy-minibuffer-match-face-1 + '((((class color) (background light)) + :background "#d3d3d3") + (((class color) (background dark)) + :background "#555555")) + "The background face for `ivy' minibuffer matches.") + +(defface ivy-minibuffer-match-face-2 + '((((class color) (background light)) + :background "#e99ce8" :weight bold) + (((class color) (background dark)) + :background "#777777" :weight bold)) + "Face for `ivy' minibuffer matches numbered 1 modulo 3.") + +(defface ivy-minibuffer-match-face-3 + '((((class color) (background light)) + :background "#bbbbff" :weight bold) + (((class color) (background dark)) + :background "#7777ff" :weight bold)) + "Face for `ivy' minibuffer matches numbered 2 modulo 3.") + +(defface ivy-minibuffer-match-face-4 + '((((class color) (background light)) + :background "#ffbbff" :weight bold) + (((class color) (background dark)) + :background "#8a498a" :weight bold)) + "Face for `ivy' minibuffer matches numbered 3 modulo 3.") + +(defface ivy-confirm-face + '((t :foreground "ForestGreen" :inherit minibuffer-prompt)) + "Face used by Ivy for a confirmation prompt.") + +(defface ivy-match-required-face + '((t :foreground "red" :inherit minibuffer-prompt)) + "Face used by Ivy for a match required prompt.") + +(defface ivy-subdir + '((t :inherit dired-directory)) + "Face used by Ivy for highlighting subdirs in the alternatives.") + +(defface ivy-org + '((t :inherit org-level-4)) + "Face used by Ivy for highlighting Org buffers in the alternatives.") + +(defface ivy-modified-buffer + '((t :inherit default)) + "Face used by Ivy for highlighting modified file visiting buffers.") + +(defface ivy-modified-outside-buffer + '((t :inherit default)) + "Face used by Ivy for highlighting file visiting buffers modified outside Emacs.") + +(defface ivy-remote + '((((class color) (background light)) + :foreground "#110099") + (((class color) (background dark)) + :foreground "#7B6BFF")) + "Face used by Ivy for highlighting remotes in the alternatives.") + +(defface ivy-virtual + '((t :inherit font-lock-builtin-face)) + "Face used by Ivy for matching virtual buffer names.") + +(defface ivy-action + '((t :inherit font-lock-builtin-face)) + "Face used by Ivy for displaying keys in `ivy-read-action'.") + +(defface ivy-highlight-face + '((t :inherit highlight)) + "Face used by Ivy to highlight certain candidates.") + +(defface ivy-prompt-match + '((t :inherit ivy-current-match)) + "Face used by Ivy for highlighting the selected prompt line.") + +(defface ivy-separator + '((t :inherit font-lock-doc-face)) + "Face for multiline source separator.") + +(defface ivy-grep-info + '((t :inherit compilation-info)) + "Face for highlighting grep information such as file names.") + +(defface ivy-grep-line-number + '((t :inherit compilation-line-number)) + "Face for displaying line numbers in grep messages.") + +(defface ivy-completions-annotations + '((t :inherit completions-annotations)) + "Face for displaying completion annotations.") + +(defface ivy-yanked-word + '((t :inherit highlight)) + "Face used to highlight yanked word.") + +(provide 'ivy-faces) + +;;; ivy-faces.el ends here diff --git a/elpa/ivy-20210216.1611/ivy-help.org b/elpa/ivy-20210216.1611/ivy-help.org new file mode 100644 index 0000000..3a94118 --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy-help.org @@ -0,0 +1,138 @@ +* Ivy Generic Help + +=ivy= is an Emacs incremental completion framework. + +- Narrow the list by typing some pattern, +- Multiple patterns are allowed by separating with a space, +- Select with ~C-n~ and ~C-p~, choose with ~RET~. + +** Help + +- ~C-h m~ :: Pop to this generic help buffer. + +** Basic Operations +*** Key bindings for navigation + +- ~C-n~ (=ivy-next-line=) :: next candidate. +- ~C-p~ (=ivy-previous-line=) :: previous candidate. +- ~C-v~ (=ivy-scroll-up-command=) :: next page. +- ~M-v~ (=ivy-scroll-down-command=) :: previous page. +- ~M-<~ (=ivy-beginning-of-buffer=) :: first candidate. +- ~M->~ (=ivy-end-of-buffer=) :: last candidate. + +*** Key bindings for single selection + +When selecting a candidate, an action is called on it. You can think +of an action as a function that takes the selected candidate as an +argument and does something with it. + +Ivy can offer several actions from which to choose. This can be +independently composed with whether you want to end completion when +the action is called. Depending on this, the short term is either +"calling an action" or "exiting with action". + +~C-m~ or ~RET~ (=ivy-done=) - exit with the current action. + +~M-o~ (=ivy-dispatching-done=) - select an action and exit with it. + +~C-j~ (=ivy-alt-done=) - when the candidate is a directory, enter +it. Otherwise, exit with the current action. + +~TAB~ (=ivy-partial-or-done=) - attempt partial completion, extending +the current input as much as possible. ~TAB TAB~ is the same as ~C-j~. + +~C-M-j~ (=ivy-immediate-done=) - exit with the current action, calling +it on the /current input/ instead of the current candidate. This is +useful especially when creating new files or directories - often the +input will match an existing file, which you don't want to select. + +~C-'~ (=ivy-avy=) - select a candidate from the current page with avy +and exit with the current action. + +** Advanced Operations +*** Key bindings for multiple selection + +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=). + +~C-M-n~ (=ivy-next-line-and-call=) combines ~C-n~ and ~C-M-m~. + +~C-M-p~ (=ivy-previous-line-and-call=) combines ~C-p~ and ~C-M-m~. + +~C-M-o~ (=ivy-dispatching-call=) is a non-exiting version of ~M-o~ +(=ivy-dispatching-done=). + +*** Key bindings that alter the minibuffer input + +~M-n~ (=ivy-next-history-element=) select the next history element or +symbol/URL at point. + +~M-p~ (=ivy-previous-history-element=) select the previous history +element. + +~C-r~ (=ivy-reverse-i-search=) start a recursive completion session to +select a history element. + +~M-i~ (=ivy-insert-current=) insert 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=) insert the sub-word at point into the +minibuffer. + +~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. + +*** Other key bindings + +~M-w~ (=ivy-kill-ring-save=) copies the selected candidates to the +kill ring; when the region is active, copies the active region. + +*** Saving the current completion session to a buffer + +~C-c C-o~ (=ivy-occur=) saves the current candidates to a new buffer; +the list is active in the new buffer. + +~RET~ or ~mouse-1~ in the new buffer calls the appropriate action on +the selected candidate. + +Ivy has no limit on the number of active buffers like these. + +Ivy takes care of making these buffer names unique. It applies +descriptive names, for example: =*ivy-occur counsel-describe-variable +"function$*=. + +*** Global key bindings + +=ivy-resume= recalls the state of the completion session just before +its last exit. Useful after an accidental ~C-m~ (=ivy-done=). +Recommended global binding: ~C-c C-r~. + +*** Hydra in the minibuffer + +~C-o~ (=hydra-ivy/body=) invokes Hydra menus with key shortcuts. + +When in Hydra, ~C-o~ or ~i~ resumes editing. + +Hydra reduces key strokes, for example: ~C-n C-n C-n C-n~ is ~C-o +jjjj~ in Hydra. Besides certain shorter keys, Hydra shows useful info +such as case folding and the current action. + +Additionally, here are the keys that are otherwise not bound: + +- ~<~ and ~>~ adjust the height of the minibuffer. +- ~c~ (=ivy-toggle-calling=) - toggle calling the current action each + time a different candidate is selected. +- ~M~ (=ivy-rotate-preferred-builders=) - rotate regex matcher. +- ~w~ and ~s~ scroll the actions list. + +Minibuffer editing is disabled when Hydra is active. diff --git a/elpa/ivy-20210216.1611/ivy-overlay.el b/elpa/ivy-20210216.1611/ivy-overlay.el new file mode 100644 index 0000000..ed77fc0 --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy-overlay.el @@ -0,0 +1,155 @@ +;;; ivy-overlay.el --- Overlay display functions for Ivy -*- lexical-binding: t -*- + +;; Copyright (C) 2016-2019 Free Software Foundation, Inc. + +;; Author: Oleh Krehel +;; Keywords: convenience + +;; 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 . + +;;; Commentary: + +;; This package allows to setup Ivy's completion at point to actually +;; show the candidates and the input at point, instead of in the +;; minibuffer. + +;;; Code: + +(eval-when-compile + (require 'subr-x)) + +(defface ivy-cursor + '((((class color) (background light)) + :background "black" :foreground "white") + (((class color) (background dark)) + :background "white" :foreground "black")) + "Cursor face for inline completion." + :group 'ivy-faces) + +(defvar ivy--old-cursor-type t) + +(defvar ivy-overlay-at nil + "Overlay variable for `ivy-display-function-overlay'.") + +(declare-function ivy--truncate-string "ivy") + +(defun ivy-left-pad (str width) + "Return STR, but with each line indented by WIDTH spaces. +Lines are truncated to the window width." + (let ((padding (make-string width ?\s))) + (mapconcat (lambda (x) + (ivy--truncate-string (concat padding x) + (1- (+ (window-width) + (window-hscroll))))) + (split-string str "\n") + "\n"))) + +(defun ivy-overlay-cleanup () + "Clean up after `ivy-display-function-overlay'." + (when (overlayp ivy-overlay-at) + (delete-overlay ivy-overlay-at) + (setq ivy-overlay-at nil)) + (unless cursor-type + (setq cursor-type ivy--old-cursor-type)) + (when (fboundp 'company-abort) + (company-abort))) + +(defvar ivy-height) + +(defun ivy-overlay-show-after (str) + "Display STR in an overlay at point. + +First, fill each line of STR with spaces to the current column. +Then attach the overlay to the character before point." + (if ivy-overlay-at + (progn + (move-overlay ivy-overlay-at (1- (point)) (line-end-position)) + (overlay-put ivy-overlay-at 'invisible nil)) + (let ((available-height (- (window-height) (count-lines (window-start) (point)) 1))) + (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) + (overlay-put ivy-overlay-at 'priority 9999)) + (overlay-put ivy-overlay-at 'display str) + (overlay-put ivy-overlay-at 'after-string "")) + +(declare-function org-current-level "org") +(declare-function org-at-heading-p "org") +(defvar org-indent-indentation-per-level) +(defvar ivy-height) +(defvar ivy-last) +(defvar ivy-text) +(defvar ivy-completion-beg) +(declare-function ivy--get-window "ivy") +(declare-function ivy-state-current "ivy") +(declare-function ivy-state-window "ivy") + +(defun ivy-overlay-impossible-p (_str) + (or + (and (eq major-mode 'org-mode) + (plist-get (text-properties-at (point)) 'src-block)) + (<= (window-height) (+ ivy-height 2)) + (= (point) (point-min)) + (< (- (+ (window-width) (window-hscroll)) (current-column)) + 30))) + +(defun ivy-display-function-overlay (str) + "Called from the minibuffer, display STR in an overlay in Ivy window. +Hide the minibuffer contents and cursor." + (if (save-selected-window + (select-window (ivy-state-window ivy-last)) + (ivy-overlay-impossible-p str)) + (let ((buffer-undo-list t)) + (save-excursion + (forward-line 1) + (insert str))) + (add-face-text-property (minibuffer-prompt-end) (point-max) + '(:foreground "white")) + (setq cursor-type nil) + (with-selected-window (ivy--get-window ivy-last) + (when cursor-type + (setq ivy--old-cursor-type cursor-type)) + (setq cursor-type nil) + (let ((overlay-str + (apply + #'concat + (buffer-substring (max (point-min) (1- (point))) (point)) + ivy-text + (and (eolp) " ") + (buffer-substring (point) (line-end-position)) + (and (> (length str) 0) + (list "\n" + (ivy-left-pad + (string-remove-prefix "\n" str) + (+ + (if (and (eq major-mode 'org-mode) + (bound-and-true-p org-indent-mode)) + (if (org-at-heading-p) + (1- (org-current-level)) + (* org-indent-indentation-per-level (or (org-current-level) 1))) + 0) + (save-excursion + (when ivy-completion-beg + (goto-char ivy-completion-beg)) + (current-column))))))))) + (let ((cursor-offset (1+ (length ivy-text)))) + (add-face-text-property cursor-offset (1+ cursor-offset) + 'ivy-cursor t overlay-str)) + (ivy-overlay-show-after overlay-str))))) + +(provide 'ivy-overlay) + +;;; ivy-overlay.el ends here diff --git a/elpa/ivy-20210216.1611/ivy-pkg.el b/elpa/ivy-20210216.1611/ivy-pkg.el new file mode 100644 index 0000000..a188e20 --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy-pkg.el @@ -0,0 +1,12 @@ +(define-package "ivy" "20210216.1611" "Incremental Vertical completYon" + '((emacs "24.5")) + :commit "0965e2375e2539fcc62b44b7b8f680d40c0b535a" :authors + '(("Oleh Krehel" . "ohwoeowho@gmail.com")) + :maintainer + '("Oleh Krehel" . "ohwoeowho@gmail.com") + :keywords + '("matching") + :url "https://github.com/abo-abo/swiper") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/elpa/ivy-20210216.1611/ivy.el b/elpa/ivy-20210216.1611/ivy.el new file mode 100644 index 0000000..2c670e6 --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy.el @@ -0,0 +1,5295 @@ +;;; ivy.el --- Incremental Vertical completYon -*- lexical-binding: t -*- + +;; Copyright (C) 2015-2020 Free Software Foundation, Inc. + +;; Author: Oleh Krehel +;; URL: https://github.com/abo-abo/swiper +;; Version: 0.13.0 +;; Package-Requires: ((emacs "24.5")) +;; Keywords: matching + +;; This file is part of GNU Emacs. + +;; This file 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, 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. + +;; For a full copy of the GNU General Public License +;; see . + +;;; Commentary: + +;; This package provides `ivy-read' as an alternative to +;; `completing-read' and similar functions. +;; +;; There's no intricate code to determine the best candidate. +;; Instead, the user can navigate to it with `ivy-next-line' and +;; `ivy-previous-line'. +;; +;; The matching is done by splitting the input text by spaces and +;; re-building it into a regex. +;; So "for example" is transformed into "\\(for\\).*\\(example\\)". + +;;; Code: + +(require 'colir) +(require 'ivy-overlay) +(require 'ivy-faces) + +(require 'cl-lib) +(require 'ring) + +(eval-when-compile + (require 'subr-x)) + +;;* Customization +(defgroup ivy nil + "Incremental vertical completion." + :group 'convenience) + +(defcustom ivy-height 10 + "Number of lines for the minibuffer window. + +See also `ivy-height-alist'." + :type 'integer) + +(defcustom ivy-count-format "%-4d " + "The style to use for displaying the current candidate count for `ivy-read'. +Set this to \"\" to suppress the count visibility. +Set this to \"(%d/%d) \" to display both the index and the count." + :type '(choice + (const :tag "Count disabled" "") + (const :tag "Count matches" "%-4d ") + (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) + +(defcustom ivy-wrap nil + "When non-nil, wrap around after the first and the last candidate." + :type 'boolean) + +(defcustom ivy-display-style 'fancy + "The style for formatting the minibuffer. + +By default, the matched strings are copied as is. + +The fancy display style highlights matching parts of the regexp, +a behavior similar to `swiper'." + :type '(choice + (const :tag "Plain" nil) + (const :tag "Fancy" fancy))) + +(defcustom ivy-on-del-error-function #'abort-recursive-edit + "Function to call when deletion fails during completion. +The usual reason for `ivy-backward-delete-char' to fail is when +there is no text left to delete, i.e., when it is called at the +beginning of the minibuffer. +The default setting provides a quick exit from completion. +Another common option is `ignore', which does nothing." + :type '(choice + (const :tag "Exit completion" abort-recursive-edit) + (const :tag "Do nothing" ignore) + (function :tag "Custom function"))) + +(defcustom ivy-extra-directories '("../" "./") + "Add this to the front of the list when completing file names. +Only \"./\" and \"../\" apply here. They appear in reverse order." + :type '(repeat :tag "Dirs" + (choice + (const :tag "Parent Directory" "../") + (const :tag "Current Directory" "./")))) + +(defcustom ivy-use-virtual-buffers nil + "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.") + +(defvar ivy-display-functions-props + '((ivy-display-function-overlay :cleanup ivy-overlay-cleanup)) + "Map Ivy display functions to their property lists. +Examples of properties include associated `:cleanup' functions.") + +(defcustom ivy-display-functions-alist + '((ivy-completion-in-region . ivy-display-function-overlay) + (t . nil)) + "An alist for customizing where to display the candidates. + +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. + +See also `https://github.com/abo-abo/swiper/wiki/ivy-display-function'." + :type '(alist + :key-type symbol + :value-type (choice + (const :tag "Minibuffer" nil) + (const :tag "LV" ivy-display-function-lv) + (const :tag "Popup" ivy-display-function-popup) + (const :tag "Overlay" ivy-display-function-overlay) + (function :tag "Custom function")))) + +(defvar ivy-completing-read-dynamic-collection nil + "Run `ivy-completing-read' with `:dynamic-collection t`.") + +(defcustom ivy-completing-read-handlers-alist + '((tmm-menubar . completing-read-default) + (tmm-shortcut . completing-read-default) + (bbdb-create . ivy-completing-read-with-empty-string-def) + (auto-insert . ivy-completing-read-with-empty-string-def) + (Info-on-current-buffer . ivy-completing-read-with-empty-string-def) + (Info-follow-reference . ivy-completing-read-with-empty-string-def) + (Info-menu . ivy-completing-read-with-empty-string-def) + (Info-index . ivy-completing-read-with-empty-string-def) + (Info-virtual-index . ivy-completing-read-with-empty-string-def) + (info-display-manual . ivy-completing-read-with-empty-string-def)) + "An alist of handlers to replace `completing-read' in `ivy-mode'." + :type '(alist :key-type symbol :value-type function)) + +(defcustom ivy-height-alist nil + "An alist to customize `ivy-height'. + +It is a list of (CALLER . HEIGHT). CALLER is a caller of +`ivy-read' and HEIGHT is the number of lines displayed. +HEIGHT can also be a function that returns the number of lines." + :type '(alist + :key-type function + :value-type (choice integer function))) + +(defvar ivy-completing-read-ignore-handlers-depth -1 + "Used to avoid infinite recursion. + +If `(minibuffer-depth)' equals this, `ivy-completing-read' will +act as if `ivy-completing-read-handlers-alist' is empty.") + +(defvar ivy-highlight-grep-commands nil + "List of grep-like commands.") + +(defvar ivy--actions-list nil + "A list of extra actions per command.") + +(defun ivy-set-actions (cmd actions) + "Set CMD extra exit points to ACTIONS." + (setq ivy--actions-list + (plist-put ivy--actions-list cmd actions))) + +(defun ivy-add-actions (cmd actions) + "Add extra exit points ACTIONS to CMD. +Existing exit points of CMD are overwritten by those in +ACTIONS that have the same key." + (setq ivy--actions-list + (plist-put ivy--actions-list cmd + (cl-delete-duplicates + (append (plist-get ivy--actions-list cmd) actions) + :key #'car :test #'equal)))) + +(defun ivy--compute-extra-actions (action caller) + "Add extra actions to ACTION based on CALLER." + (let* ((extra-actions (cl-delete-duplicates + (append (plist-get ivy--actions-list t) + (plist-get ivy--actions-list this-command) + (plist-get ivy--actions-list caller)) + :key #'car :test #'equal)) + (override-default (assoc "o" extra-actions))) + (cond (override-default + (cons 1 (cons override-default + (cl-delete "o" extra-actions + :key #'car :test #'equal)))) + ((not extra-actions) + action) + ((functionp action) + `(1 + ("o" ,action "default") + ,@extra-actions)) + ((null action) + `(1 + ("o" identity "default") + ,@extra-actions)) + (t + (cons (car action) + (cl-delete-duplicates (cdr (append action extra-actions)) + :key #'car :test #'equal :from-end t)))))) + +(defvar ivy--prompts-list nil) + +(defun ivy-set-prompt (caller prompt-fn) + "Associate CALLER with PROMPT-FN. +PROMPT-FN is a function of no arguments that returns a prompt string." + (setq ivy--prompts-list + (plist-put ivy--prompts-list caller prompt-fn))) + +(defvar ivy--display-transformers-alist nil + "A list of str->str transformers per command.") + +(defun ivy-set-display-transformer (cmd transformer) + "Set CMD a displayed candidate TRANSFORMER. + +It's a lambda that takes a string one of the candidates in the +collection and returns a string for display, the same candidate +plus some extra information. + +This lambda is called only on the `ivy-height' candidates that +are about to be displayed, not on the whole collection." + (declare (obsolete "Use `ivy-configure' :display-transformer-fn" "<2020-05-20 Wed>")) + (ivy--alist-set 'ivy--display-transformers-alist cmd transformer)) + +(defvar ivy--sources-list nil + "A list of extra sources per command.") + +(defun ivy-set-sources (cmd sources) + "Attach to CMD a list of extra SOURCES. + +Each static source is a function that takes no argument and +returns a list of strings. + +The (original-source) determines the position of the original +dynamic source. + +Extra dynamic sources aren't supported yet. + +Example: + + (defun small-recentf () + (cl-subseq recentf-list 0 20)) + + (ivy-set-sources + 'counsel-locate + '((small-recentf) + (original-source)))" + (setq ivy--sources-list + (plist-put ivy--sources-list cmd sources))) + +(defun ivy--compute-extra-candidates (caller) + (let ((extra-sources (or (plist-get ivy--sources-list caller) + '((original-source)))) + (result nil)) + (dolist (source extra-sources) + (cond ((equal source '(original-source)) + (push source result)) + ((null (cdr source)) + (push (list (car source) (funcall (car source))) result)))) + result)) + +(defvar ivy-current-prefix-arg nil + "Prefix arg to pass to actions. +This is a global variable that is set by ivy functions for use in +action functions.") + +;;* Keymap +(require 'delsel) +(defun ivy-define-key (keymap key def) + "Forward to (`define-key' KEYMAP KEY DEF). +Remove DEF from `counsel-M-x' list." + (put def 'no-counsel-M-x t) + (define-key keymap key def)) + +(defvar ivy-minibuffer-map + (let ((map (make-sparse-keymap))) + (ivy-define-key map (kbd "C-m") 'ivy-done) + (define-key map [down-mouse-1] 'ignore) + (ivy-define-key map [mouse-1] 'ivy-mouse-done) + (ivy-define-key map [mouse-3] 'ivy-mouse-dispatching-done) + (ivy-define-key map (kbd "C-M-m") 'ivy-call) + (ivy-define-key map (kbd "C-j") 'ivy-alt-done) + (ivy-define-key map (kbd "C-M-j") 'ivy-immediate-done) + (ivy-define-key map (kbd "TAB") 'ivy-partial-or-done) + (ivy-define-key map [remap next-line] 'ivy-next-line) + (ivy-define-key map [remap previous-line] 'ivy-previous-line) + (ivy-define-key map (kbd "C-r") 'ivy-reverse-i-search) + (define-key map (kbd "SPC") 'self-insert-command) + (ivy-define-key map [remap delete-backward-char] 'ivy-backward-delete-char) + (ivy-define-key map [remap backward-delete-char-untabify] 'ivy-backward-delete-char) + (ivy-define-key map [remap backward-kill-word] 'ivy-backward-kill-word) + (ivy-define-key map [remap delete-char] 'ivy-delete-char) + (ivy-define-key map [remap forward-char] 'ivy-forward-char) + (ivy-define-key map (kbd "") 'ivy-forward-char) + (ivy-define-key map [remap kill-word] 'ivy-kill-word) + (ivy-define-key map [remap beginning-of-buffer] 'ivy-beginning-of-buffer) + (ivy-define-key map [remap end-of-buffer] 'ivy-end-of-buffer) + (ivy-define-key map (kbd "M-n") 'ivy-next-history-element) + (ivy-define-key map (kbd "M-p") 'ivy-previous-history-element) + (define-key map (kbd "C-g") 'minibuffer-keyboard-quit) + (ivy-define-key map [remap scroll-up-command] 'ivy-scroll-up-command) + (ivy-define-key map [remap scroll-down-command] 'ivy-scroll-down-command) + (ivy-define-key map (kbd "") 'ivy-scroll-up-command) + (ivy-define-key map (kbd "") 'ivy-scroll-down-command) + (ivy-define-key map (kbd "C-v") 'ivy-scroll-up-command) + (ivy-define-key map (kbd "M-v") 'ivy-scroll-down-command) + (ivy-define-key map (kbd "C-M-n") 'ivy-next-line-and-call) + (ivy-define-key map (kbd "C-M-p") 'ivy-previous-line-and-call) + (ivy-define-key map (kbd "M-a") 'ivy-toggle-marks) + (ivy-define-key map (kbd "M-r") 'ivy-toggle-regexp-quote) + (ivy-define-key map (kbd "M-j") 'ivy-yank-word) + (ivy-define-key map (kbd "M-i") 'ivy-insert-current) + (ivy-define-key map (kbd "C-M-y") 'ivy-insert-current-full) + (ivy-define-key map (kbd "C-o") 'hydra-ivy/body) + (ivy-define-key map (kbd "M-o") 'ivy-dispatching-done) + (ivy-define-key map (kbd "C-M-o") 'ivy-dispatching-call) + (ivy-define-key map [remap kill-line] 'ivy-kill-line) + (ivy-define-key map [remap kill-whole-line] 'ivy-kill-whole-line) + (ivy-define-key map (kbd "S-SPC") 'ivy-restrict-to-matches) + (ivy-define-key map [remap kill-ring-save] 'ivy-kill-ring-save) + (ivy-define-key map (kbd "C-M-a") 'ivy-read-action) + (ivy-define-key map (kbd "C-c C-o") 'ivy-occur) + (ivy-define-key map (kbd "C-c C-a") 'ivy-toggle-ignore) + (ivy-define-key map (kbd "C-c C-s") 'ivy-rotate-sort) + (ivy-define-key map [remap describe-mode] 'ivy-help) + (ivy-define-key map "$" 'ivy-magic-read-file-env) + map) + "Keymap used in the minibuffer.") +(autoload 'hydra-ivy/body "ivy-hydra" "" t) +(autoload 'ivy-hydra-read-action "ivy-hydra" "" t) + +(defvar ivy-mode-map + (let ((map (make-sparse-keymap))) + (ivy-define-key map [remap switch-to-buffer] 'ivy-switch-buffer) + (ivy-define-key map [remap switch-to-buffer-other-window] 'ivy-switch-buffer-other-window) + map) + "Keymap for `ivy-mode'.") + +;;* Globals +(cl-defstruct ivy-state + prompt collection + predicate require-match initial-input + history preselect keymap update-fn sort + ;; The frame in which `ivy-read' was called + frame + ;; The window in which `ivy-read' was called + window + ;; The buffer in which `ivy-read' was called + buffer + ;; The value of `ivy-text' to be used by `ivy-occur' + text + action + unwind + re-builder + matcher + ;; When this is non-nil, call it for each input change to get new candidates + dynamic-collection + ;; A lambda that transforms candidates only for display + display-transformer-fn + directory + caller + current + def + ignore + multi-action + extra-props) + +(defvar ivy-last (make-ivy-state) + "The last parameters passed to `ivy-read'. + +This should eventually become a stack so that you could use +`ivy-read' recursively.") + +(defvar ivy--sessions nil + "Alist mapping session symbols to `ivy-state' objects.") + +(defvar ivy-recursive-last nil) + +(defvar ivy-recursive-restore t + "When non-nil, restore the above state when exiting the minibuffer. +This variable is let-bound to nil by functions that take care of +the restoring themselves.") + +(defsubst ivy-set-action (action) + "Set the current `ivy-last' field to ACTION." + (setf (ivy-state-action ivy-last) action)) + +(defvar inhibit-message) + +(defvar ffap-machine-p-known) + +(defun ivy-thing-at-point () + "Return a string that corresponds to the current thing at point." + (substring-no-properties + (cond + ((use-region-p) + (let* ((beg (region-beginning)) + (end (region-end)) + (eol (save-excursion (goto-char beg) (line-end-position)))) + (buffer-substring-no-properties beg (min end eol)))) + ((thing-at-point 'url)) + ((and (eq (ivy-state-collection ivy-last) #'read-file-name-internal) + (let ((inhibit-message t) + (ffap-machine-p-known 'reject)) + (run-hook-with-args-until-success 'file-name-at-point-functions)))) + ((let ((s (thing-at-point 'symbol))) + (and (stringp s) + (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s) + (match-string 1 s) + s)))) + ((looking-at "(+\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>") + (match-string-no-properties 1)) + (t + "")))) + +(defvar ivy-history nil + "History list of candidates entered in the minibuffer. + +Maximum length of the history list is determined by the value +of `history-length'.") + +(defvar ivy--directory nil + "Current directory when completing file names.") + +(defvar ivy--directory-hist nil + "Store the history of directories. +This allows RET to reverse consecutive DEL.") + +(defvar ivy--length 0 + "Store the amount of viable candidates.") + +(defvar ivy-text "" + "Store the user's string as it is typed in.") + +(defvar ivy-regex "" + "Store the regex value that corresponds to `ivy-text'.") + +(defvar ivy--regex-function 'ivy--regex + "Current function for building a regex.") + +(defun ivy-set-text (str) + "Set `ivy-text' to STR." + (setq ivy-text str) + (setq ivy-regex (funcall ivy--regex-function ivy-text))) + +(defvar ivy--index 0 + "Store the index of the current candidate.") + +(defvar ivy--window-index 0 + "Store the index of the current candidate in the minibuffer window. + +This means it's between 0 and `ivy-height'.") + +(defvar ivy-exit nil + "Store `done' if the completion was successfully selected. +Otherwise, store nil.") + +(defvar ivy--all-candidates nil + "Store the candidates passed to `ivy-read'.") + +(defvar ivy--extra-candidates '((original-source)) + "Store candidates added by the extra sources. + +This is an internal-use alist. Each key is a function name, or +original-source (which represents where the current dynamic +candidates should go). + +Each value is an evaluation of the function, in case of static +sources. These values will subsequently be filtered on `ivy-text'. + +This variable is set by `ivy-read' and used by `ivy--set-candidates'.") + +(defcustom ivy-use-ignore-default t + "The default policy for user-configured candidate filtering." + :type '(choice + (const :tag "Ignore ignored always" always) + (const :tag "Ignore ignored when others exist" t) + (const :tag "Don't ignore" nil))) + +(defvar ivy-use-ignore t + "Store policy for user-configured candidate filtering. +This may be changed dynamically by `ivy-toggle-ignore'. +Use `ivy-use-ignore-default' for a permanent configuration.") + +(defvar ivy--default nil + "Default initial input.") + +(defvar ivy--prompt nil + "Store the format-style prompt. +When non-nil, it should contain at least one %d.") + +(defvar ivy--prompt-extra "" + "Temporary modifications to the prompt.") + +(defvar ivy--old-re nil + "Store the old regexp. +Either a string or a list for `ivy-re-match'.") + +(defvar ivy--old-cands nil + "Store the candidates matched by `ivy--old-re'.") + +(defvar ivy--highlight-function 'ivy--highlight-default + "Current function for formatting the candidates.") + +(defvar ivy--subexps 0 + "Number of groups in the current `ivy--regex'.") + +(defvar ivy--full-length nil + "The total amount of candidates when :dynamic-collection is non-nil.") + +(defvar ivy--old-text "" + "Store old `ivy-text' for dynamic completion.") + +(defvar ivy--trying-to-resume-dynamic-collection nil + "Non-nil if resuming from a dynamic collection. +When non-nil, ivy will wait until the first chunk of asynchronous +candidates has been received before selecting the last +preselected candidate.") + +(defun ivy--set-index-dynamic-collection () + (when ivy--trying-to-resume-dynamic-collection + (let ((preselect-index + (ivy--preselect-index (ivy-state-preselect ivy-last) ivy--all-candidates))) + (when preselect-index + (ivy-set-index preselect-index))) + (setq ivy--trying-to-resume-dynamic-collection nil))) + +(defcustom ivy-case-fold-search-default + (if search-upper-case + 'auto + case-fold-search) + "The default value for `case-fold-search' in Ivy operations. +The special value `auto' means case folding is performed so long +as the entire input string comprises lower-case characters. This +corresponds to the default behaviour of most Emacs search +functionality, e.g. as seen in `isearch'." + :link '(info-link "(emacs)Lax Search") + :type '(choice + (const :tag "Auto" auto) + (const :tag "Always" t) + (const :tag "Never" nil))) + +(defvar ivy-case-fold-search ivy-case-fold-search-default + "Store the current overriding `case-fold-search'.") + +(defcustom ivy-more-chars-alist + '((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." + :type '(alist :key-type symbol :value-type integer)) + +(defun ivy-more-chars () + "Return two fake candidates prompting for at least N input. +N is obtained from `ivy-more-chars-alist'." + (let ((diff (- (ivy-alist-setting ivy-more-chars-alist) + (length ivy-text)))) + (when (> diff 0) + (list "" (format "%d chars more" diff))))) + +(defun ivy--case-fold-p (string) + "Return nil if STRING should be matched case-sensitively." + (if (eq ivy-case-fold-search 'auto) + (string= string (downcase string)) + ivy-case-fold-search)) + +(defun ivy--case-fold-string= (s1 s2) + "Like `string=', but obeys `case-fold-search'." + (eq t (compare-strings s1 nil nil s2 nil nil case-fold-search))) + +(defmacro ivy-quit-and-run (&rest body) + "Quit the minibuffer and run BODY afterwards." + (declare (indent 0)) + `(progn + (put 'quit 'error-message "") + (run-at-time nil nil + (lambda () + (put 'quit 'error-message "Quit") + (with-demoted-errors "Error: %S" + ,@body))) + (abort-recursive-edit))) + +(defun ivy-exit-with-action (action &optional exit-code) + "Quit the minibuffer and call ACTION afterwards." + (ivy-set-action + `(lambda (x) + (funcall ',action x) + (ivy-set-action ',(ivy-state-action ivy-last)))) + (setq ivy-exit (or exit-code 'done)) + (exit-minibuffer)) + +(defmacro with-ivy-window (&rest body) + "Execute BODY in the window from which `ivy-read' was called." + (declare (indent 0) + (debug t)) + `(with-selected-window (ivy--get-window ivy-last) + ,@body)) + +(defun ivy--expand-file-name (text) + (cond + ((eq (ivy-state-history ivy-last) 'grep-files-history) + text) + (ivy--directory + (if (and (string-match-p "^/" text) (file-remote-p ivy--directory)) + (let ((parts (split-string ivy--directory ":"))) + (concat (nth 0 parts) ":" (nth 1 parts) ":" text)) + (expand-file-name text ivy--directory))) + (t + text))) + +(defun ivy--done (text) + "Insert TEXT and exit minibuffer." + (if (member (ivy-state-prompt ivy-last) '("Create directory: " "Make directory: ")) + (ivy-immediate-done) + (when (stringp text) + (insert + (setf (ivy-state-current ivy-last) + (ivy--expand-file-name text)))) + (setq ivy-exit 'done) + (exit-minibuffer))) + +(defcustom ivy-use-selectable-prompt nil + "When non-nil, make the prompt line selectable like a candidate. + +The prompt line can be selected by calling `ivy-previous-line' when the first +regular candidate is selected. Both actions `ivy-done' and `ivy-alt-done', +when called on a selected prompt, are forwarded to `ivy-immediate-done', which +results to the same as calling `ivy-immediate-done' explicitly when a regular +candidate is selected. + +Note that if `ivy-wrap' is set to t, calling `ivy-previous-line' when the +prompt is selected wraps around to the last candidate, while calling +`ivy-next-line' on the last candidate wraps around to the first +candidate, not the prompt." + :type 'boolean) + +(defvar ivy--use-selectable-prompt nil + "Store the effective `ivy-use-selectable-prompt' for current session.") + +(defun ivy--prompt-selectable-p () + "Return t if the prompt line is selectable." + (and ivy-use-selectable-prompt + (or (memq (ivy-state-require-match ivy-last) + '(nil confirm confirm-after-completion)) + ;; :require-match is t, but "" is in the collection + (let ((coll (ivy-state-collection ivy-last))) + (and (listp coll) + (if (consp (car coll)) + (member '("") coll) + (member "" coll))))))) + +(defun ivy--prompt-selected-p () + "Return t if the prompt line is selected." + (and ivy--use-selectable-prompt + (= ivy--index -1))) + +;;* Commands +(defun ivy-done () + "Exit the minibuffer with the selected candidate." + (interactive) + (if (ivy--prompt-selected-p) + (ivy-immediate-done) + (setq ivy-current-prefix-arg current-prefix-arg) + (delete-minibuffer-contents) + (cond ((and (= ivy--length 0) + (eq this-command 'ivy-dispatching-done)) + (ivy--done ivy-text)) + ((or (> ivy--length 0) + ;; the action from `ivy-dispatching-done' may not need a + ;; candidate at all + (eq this-command 'ivy-dispatching-done)) + (ivy--done (ivy-state-current ivy-last))) + ((and (memq (ivy-state-collection ivy-last) + '(read-file-name-internal internal-complete-buffer)) + (eq confirm-nonexistent-file-or-buffer t) + (not (string= " (confirm)" ivy--prompt-extra))) + (setq ivy--prompt-extra " (confirm)") + (insert ivy-text) + (ivy--exhibit)) + ((memq (ivy-state-require-match ivy-last) + '(nil confirm confirm-after-completion)) + (ivy--done ivy-text)) + (t + (setq ivy--prompt-extra " (match required)") + (insert ivy-text) + (ivy--exhibit))))) + +(defvar ivy-mouse-1-tooltip + "Exit the minibuffer with the selected candidate." + "The doc visible in the tooltip for mouse-1 binding in the minibuffer.") +(defvar ivy-mouse-3-tooltip + "Display alternative actions." + "The doc visible in the tooltip for mouse-3 binding in the minibuffer.") + +(defun ivy-mouse-offset (event) + "Compute the offset between the candidate at point and the selected one." + (if event + (let* ((line-number-at-point + (max 2 + (line-number-at-pos (posn-point (event-start event))))) + + (line-number-candidate ;; convert to 0 based index + (- line-number-at-point 2)) + (offset + (- line-number-candidate + ivy--window-index))) + offset) + nil)) + +(defun ivy-mouse-done (event) + (interactive "@e") + (let ((offset (ivy-mouse-offset event))) + (when offset + (ivy-next-line offset) + (ivy--exhibit) + (ivy-alt-done)))) + +(defun ivy-mouse-dispatching-done (event) + (interactive "@e") + (let ((offset (ivy-mouse-offset event))) + (when offset + (ivy-next-line offset) + (ivy--exhibit) + (ivy-dispatching-done)))) + +(defcustom ivy-read-action-format-function 'ivy-read-action-format-default + "Function used to transform the actions list into a docstring." + :type '(radio + (function-item ivy-read-action-format-default) + (function-item ivy-read-action-format-columns))) + +(defun ivy-read-action-format-default (actions) + "Create a docstring from ACTIONS. + +ACTIONS is a list. Each list item is a list of 3 items: +key (a string), cmd and doc (a string)." + (format "%s\n%s\n" + (if (eq this-command 'ivy-read-action) + "Select action: " + (ivy-state-current ivy-last)) + (mapconcat + (lambda (x) + (format "%s: %s" + (propertize + (car x) + 'face 'ivy-action) + (nth 2 x))) + actions + "\n"))) + +(defun ivy-read-action-format-columns (actions) + "Create a docstring from ACTIONS, using several columns if needed to preserve `ivy-height'. + +ACTIONS is a list. Each list item is a list of 3 items: key (a +string), cmd and doc (a string)." + (let ((length (length actions)) + (i 0) + (max-rows (- ivy-height 1)) + rows cols col lwidth rwidth) + (while (< i length) + (setq col (cl-subseq actions i (min length (cl-incf i max-rows)))) + (setq lwidth (apply 'max (mapcar (lambda (x) + (length (nth 0 x))) + col))) + (setq rwidth (apply 'max (mapcar (lambda (x) + (length (nth 2 x))) + col))) + (setq col (mapcar (lambda (x) + (format (format "%%%ds: %%-%ds" lwidth rwidth) + (propertize (car x) 'face 'ivy-action) + (nth 2 x))) + col)) + (cond + ((null rows) + (setq rows (length col))) + ((< (length col) rows) + (setq col (append col (make-list (- rows (length col)) ""))))) + (push col cols)) + (format "%s\n%s\n" + (if (eq this-command 'ivy-read-action) + "Select action: " + (ivy-state-current ivy-last)) + (mapconcat 'identity + (apply 'cl-mapcar + (lambda (&rest args) + (mapconcat 'identity args " | ")) + (nreverse cols)) + "\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-hydra-read-action))) + +(defun ivy-read-action () + "Change the action to one of the available ones. + +Return nil for `minibuffer-keyboard-quit' or wrong key during the +selection, non-nil otherwise." + (interactive) + (let ((actions (ivy-state-action ivy-last))) + (if (not (ivy--actionp actions)) + t + (let ((ivy--directory ivy--directory)) + (funcall ivy-read-action-function actions))))) + +(defvar set-message-function) + +(defun ivy-read-action-by-key (actions) + (let* ((set-message-function nil) + (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 (key-description (vector (read-key hint)))))) + (ivy-shrink-after-dispatching) + (cond ((member key '("ESC" "C-g" "M-o")) + nil) + ((null action-idx) + (message "%s is not bound" key) + nil) + (t + (message "") + (setcar actions (1+ action-idx)) + (ivy-set-action actions))))) + +(defvar ivy-marked-candidates nil + "List of marked candidates. +Use `ivy-mark' to populate this. + +When this list is non-nil at the end of the session, the action +will be called for each element of this list.") + +(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) + (let ((ivy-marked-candidates ivy-marked-candidates)) + (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." + (when (window-minibuffer-p) + (window-resize nil (- ivy-height (window-height))))) + +(defun ivy-dispatching-done () + "Select one of the available actions and call `ivy-done'." + (interactive) + (let ((ivy-exit 'ivy-dispatching-done)) + (when (ivy-read-action) + (ivy-done))) + (ivy-shrink-after-dispatching)) + +(defun ivy-dispatching-call () + "Select one of the available actions and call `ivy-call'." + (interactive) + (setq ivy-current-prefix-arg current-prefix-arg) + (let ((actions (copy-sequence (ivy-state-action ivy-last))) + (old-ivy-text ivy-text)) + (unwind-protect + (when (ivy-read-action) + (ivy-set-text old-ivy-text) + (ivy-call)) + (ivy-set-action actions))) + (ivy-shrink-after-dispatching)) + +(defun ivy-build-tramp-name (x) + "Reconstruct X into a path. +Is is a cons cell, related to `tramp-get-completion-function'." + (let ((user (car x)) + (domain (cadr x))) + (if user + (concat user "@" domain) + domain))) + +(declare-function Info-find-node "info") +(declare-function Info-read-node-name-1 "info") +(declare-function tramp-get-completion-function "tramp") + +(defcustom ivy-alt-done-functions-alist nil + "Customize what `ivy-alt-done' does per-collection." + :type '(alist :key-type symbol :value-type function)) + +(defun ivy--completing-fname-p () + (eq 'file (cdr (assoc + 'category + (ignore-errors + (funcall (ivy-state-collection ivy-last) ivy-text nil 'metadata)))))) + +(defun ivy-alt-done (&optional arg) + "Exit the minibuffer with the selected candidate. +When ARG is t, exit with current text, ignoring the candidates. +When the current candidate during file name completion is a +directory, continue completion from within that directory instead +of exiting. This function is otherwise like `ivy-done'." + (interactive "P") + (setq ivy-current-prefix-arg current-prefix-arg) + (let (alt-done-fn) + (cond ((or arg (ivy--prompt-selected-p)) + (ivy-immediate-done)) + ((setq alt-done-fn (ivy-alist-setting ivy-alt-done-functions-alist)) + (funcall alt-done-fn)) + ((ivy--completing-fname-p) + (ivy--directory-done)) + (t + (ivy-done))))) + +(defun ivy--info-alt-done () + (if (member (ivy-state-current ivy-last) '("(./)" "(../)")) + (ivy-quit-and-run + (ivy-read "Go to file: " #'read-file-name-internal + :action (lambda (x) + (Info-find-node + (expand-file-name x ivy--directory) + "Top")))) + (ivy-done))) + +(defvar ivy-auto-select-single-candidate nil + "When non-nil, auto-select the candidate if it is the only one. +When t, it is the same as if the user were prompted and selected the candidate +by calling the default action. This variable has no use unless the collection +contains a single candidate.") + +(defun ivy--directory-enter () + (let (dir) + (when (and + (> ivy--length 0) + (not (string= (ivy-state-current ivy-last) "./")) + (setq dir (ivy-expand-file-if-directory (ivy-state-current ivy-last)))) + (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--tramp-candidates () + (let ((method (match-string 1 ivy-text)) + (user (match-string 2 ivy-text)) + (rest (match-string 3 ivy-text)) + res) + (dolist (x (tramp-get-completion-function method)) + (setq res (append res (funcall (car x) (cadr x))))) + (setq res (delq nil res)) + (when user + (dolist (x res) + (setcar x user))) + (setq res (delete-dups res)) + (let* ((old-ivy-last ivy-last) + (enable-recursive-minibuffers t) + (host (let ((ivy-auto-select-single-candidate nil)) + (ivy-read "user@host: " + (mapcar #'ivy-build-tramp-name res) + :initial-input rest)))) + (setq ivy-last old-ivy-last) + (when host + (setq ivy--directory "/") + (ivy--cd (concat "/" method ":" host ":/")))))) + +(defun ivy--directory-done () + "Handle exit from the minibuffer when completing file names." + (let ((dir (ivy--handle-directory ivy-text))) + (cond ((equal (ivy-state-current ivy-last) (ivy-state-def ivy-last)) + (ivy-done)) + ((and (ivy-state-require-match ivy-last) + (equal ivy-text "") + (null ivy--old-cands)) + (ivy-immediate-done)) + (dir + (let ((inhibit-message t)) + (ivy--cd dir))) + ((ivy--directory-enter)) + ((unless (string= ivy-text "") + ;; Obsolete since 26.1 and removed in 28.1. + (defvar tramp-completion-mode) + (with-no-warnings + (let* ((tramp-completion-mode t) + (file (expand-file-name + (if (> ivy--length 0) (ivy-state-current ivy-last) ivy-text) + ivy--directory))) + (when (ignore-errors (file-exists-p file)) + (if (file-directory-p file) + (ivy--cd (file-name-as-directory file)) + (ivy-done)) + ivy-text))))) + ((or (and (equal ivy--directory "/") + (string-match-p "\\`[^/]+:.*:.*\\'" ivy-text)) + (string-match-p "\\`/[^/]+:.*:.*\\'" ivy-text)) + (ivy-done)) + ((ivy--tramp-prefix-p) + (ivy--tramp-candidates)) + (t + (ivy-done))))) + +(defun ivy--tramp-prefix-p () + (or (and (equal ivy--directory "/") + (cond ((string-match + "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'" + ivy-text) + (save-match-data + (ivy-set-text (ivy-state-current ivy-last)))) + ((string-match + "\\`\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'" + (ivy-state-current ivy-last)) + (save-match-data + (ivy-set-text (ivy-state-current ivy-last)))))) + (string-match + "\\`/\\([^/]+?\\):\\(?:\\(.*\\)@\\)?\\(.*\\)\\'" + ivy-text))) + +(defun ivy-expand-file-if-directory (file-name) + "Expand FILE-NAME as directory. +When this directory doesn't exist, return nil." + (when (stringp file-name) + (let ((full-name + ;; Ignore host name must not match method "ssh" + (ignore-errors + (file-name-as-directory + (expand-file-name file-name ivy--directory))))) + (when (and full-name (file-directory-p full-name)) + full-name)))) + +(defcustom ivy-tab-space nil + "When non-nil, `ivy-partial-or-done' should insert a space." + :type 'boolean) + +(defun ivy-partial-or-done () + "Complete the minibuffer text as much as possible. +If the text hasn't changed as a result, forward to `ivy-alt-done'." + (interactive) + (cond + ((and (numberp 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) + (ivy-set-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--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 + (concat "^" (string-remove-prefix "^" 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 (ivy--split-spaces ivy-text) (list ""))) + (tail (last parts)) + (postfix (car tail)) + (case-fold-search (ivy--case-fold-p ivy-text)) + (completion-ignore-case case-fold-search) + (new (try-completion (string-remove-prefix "^" postfix) + (if (ivy-state-dynamic-collection ivy-last) + ivy--all-candidates + (mapcar (lambda (str) + (let ((i (string-match-p postfix str))) + (and i (substring str i)))) + ivy--old-cands))))) + (cond ((eq new t) nil) + ((string= new ivy-text) nil) + ((string= (car tail) (car (ivy--split-spaces new))) nil) + (new + (delete-region (minibuffer-prompt-end) (point-max)) + (setcar tail + (if (= (string-to-char postfix) ?^) + (concat "^" new) + new)) + (ivy-set-text + (concat + (mapconcat #'identity parts " ") + (and ivy-tab-space (not (= (length ivy--old-cands) 1)) " "))) + (insert ivy-text) + (ivy--partial-cd-for-single-directory) + t)))) + +(defvar ivy-completion-beg nil + "Completion bounds start.") + +(defvar ivy-completion-end nil + "Completion bounds end.") + +(defun ivy-immediate-done () + "Exit the minibuffer with current input instead of current candidate." + (interactive) + (delete-minibuffer-contents) + (setf (ivy-state-current ivy-last) + (cond ((or (not ivy--directory) + (eq (ivy-state-history ivy-last) 'grep-files-history)) + ivy-text) + ((and (string= ivy-text "") + (eq (ivy-state-collection ivy-last) + #'read-file-name-internal)) + (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)) + (setq ivy-completion-beg ivy-completion-end) + (setq ivy-exit 'done) + (exit-minibuffer)) + +(defun ivy--restore-session (&optional session) + "Resume a recorded completion SESSION, if any exists." + (when ivy--sessions + (unless session + (setq session (intern + (let ((ivy-last ivy-last) + ivy--all-candidates + ivy-text) + (ivy-read "Choose ivy session: " + ivy--sessions + :require-match t))))) + (setq ivy-last (or (cdr (assq session ivy--sessions)) + ivy-last))) + (let ((data (plist-get (ivy-state-extra-props ivy-last) :ivy-data))) + (when data + (setq ivy--all-candidates (plist-get data :all-candidates)) + (setq ivy-text (plist-get data :text))))) + +;;;###autoload +(defun ivy-resume (&optional session) + "Resume the last completion session, or SESSION if non-nil. +With a prefix arg, try to restore a recorded completion session, +if one exists." + (interactive) + (when (or current-prefix-arg session) + (ivy--restore-session session)) + + (if (or (null (ivy-state-action ivy-last)) + (eq (ivy--get-action ivy-last) #'identity)) + (user-error "The last session isn't compatible with `ivy-resume'") + (when (memq (ivy-state-caller ivy-last) + '(swiper + swiper-isearch swiper-backward + swiper-isearch-backward + counsel-grep)) + (switch-to-buffer (ivy-state-buffer ivy-last))) + (with-current-buffer (ivy-state-buffer 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) + :predicate (ivy-state-predicate ivy-last) + :require-match (ivy-state-require-match ivy-last) + :initial-input ivy-text + :history (ivy-state-history ivy-last) + :preselect (ivy-state-current ivy-last) + :keymap (ivy-state-keymap ivy-last) + :update-fn (ivy-state-update-fn ivy-last) + :sort (ivy-state-sort ivy-last) + :action (ivy-state-action ivy-last) + :unwind (ivy-state-unwind ivy-last) + :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 + "When non-nil, call the current action when `ivy--index' changes.") + +(defun ivy-set-index (index) + "Set `ivy--index' to INDEX." + (setq ivy--index index) + (when ivy-calling + (ivy--exhibit) + (ivy-call))) + +(defun ivy-beginning-of-buffer () + "Select the first completion candidate." + (interactive) + (ivy-set-index 0)) + +(defun ivy-end-of-buffer () + "Select the last completion candidate." + (interactive) + (ivy-set-index (1- ivy--length))) + +(defun ivy-scroll-up-command () + "Scroll the candidates upward by the minibuffer height." + (interactive) + (ivy-set-index (min (1- (+ ivy--index ivy-height)) + (1- ivy--length)))) + +(defun ivy-scroll-down-command () + "Scroll the candidates downward by the minibuffer height." + (interactive) + (ivy-set-index (max (1+ (- ivy--index ivy-height)) + 0))) + +(defun ivy-next-line (&optional arg) + "Move cursor vertically down ARG candidates." + (interactive "p") + (setq arg (or arg 1)) + (let ((index (+ ivy--index arg))) + (if (> index (1- ivy--length)) + (if ivy-wrap + (ivy-beginning-of-buffer) + (ivy-set-index (1- ivy--length))) + (ivy-set-index index)))) + +(defun ivy-next-line-or-history (&optional arg) + "Move cursor vertically down ARG candidates. +If the input is empty, select the previous history element instead." + (interactive "p") + (let ((orig-index ivy--index)) + (ivy-next-line arg) + (when (and (string= ivy-text "") (= ivy--index orig-index)) + (ivy-previous-history-element 1)))) + +(defun ivy-previous-line (&optional arg) + "Move cursor vertically up ARG candidates." + (interactive "p") + (setq arg (or arg 1)) + (let ((index (- ivy--index arg)) + (min-index (if ivy--use-selectable-prompt -1 0))) + (if (< index min-index) + (if ivy-wrap + (ivy-end-of-buffer) + (ivy-set-index min-index)) + (ivy-set-index index)))) + +(defun ivy-previous-line-or-history (arg) + "Move cursor vertically up ARG candidates. +If the input is empty, select the previous history element instead." + (interactive "p") + (let ((orig-index ivy--index)) + (ivy-previous-line arg) + (when (and (string= ivy-text "") (= ivy--index orig-index)) + (ivy-previous-history-element 1)))) + +(defun ivy-toggle-calling () + "Flip `ivy-calling'." + (interactive) + (when (setq ivy-calling (not ivy-calling)) + (ivy-call))) + +(defun ivy-toggle-ignore () + "Toggle user-configured candidate filtering." + (interactive) + (setq ivy-use-ignore + (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)) + +(defun ivy--get-action (state) + "Get the action function from STATE." + (let ((action (ivy-state-action state))) + (when action + (if (functionp action) + action + (cadr (nth (car action) action)))))) + +(defun ivy--get-multi-action (state) + "Get the multi-action function from STATE." + (let* ((action (ivy-state-action state)) + (multi-action + (and (listp action) + (not (eq (car action) 'lambda)) + (nth 3 (nth (car action) action))))) + (if multi-action + multi-action + (when (eq (car action) 1) + (ivy-state-multi-action state))))) + +(defun ivy--get-window (state) + "Get the window from STATE." + (if (ivy-state-p state) + (let ((window (ivy-state-window state))) + (if (window-live-p window) + window + (next-window))) + (selected-window))) + +(defun ivy--actionp (x) + "Return non-nil when X is a list of actions." + (and (consp x) (not (memq (car x) '(closure lambda))))) + +(defcustom ivy-action-wrap nil + "When non-nil, `ivy-next-action' and `ivy-prev-action' wrap." + :type 'boolean) + +(defun ivy-next-action () + "When the current action is a list, scroll it forwards." + (interactive) + (let ((action (ivy-state-action ivy-last))) + (when (ivy--actionp action) + (let ((len (1- (length action))) + (idx (car action))) + (if (>= idx len) + (when ivy-action-wrap + (setf (car action) 1)) + (cl-incf (car action))))))) + +(defun ivy-prev-action () + "When the current action is a list, scroll it backwards." + (interactive) + (let ((action (ivy-state-action ivy-last))) + (when (ivy--actionp action) + (if (<= (car action) 1) + (when ivy-action-wrap + (setf (car action) (1- (length action)))) + (cl-decf (car action)))))) + +(defun ivy-action-name () + "Return the name associated with the current action." + (let ((action (ivy-state-action ivy-last))) + (if (ivy--actionp action) + (format "[%d/%d] %s" + (car action) + (1- (length action)) + (nth 2 (nth (car action) action))) + "[1/1] default"))) + +(defvar ivy-inhibit-action nil + "When non-nil, `ivy-call' does nothing. + +Example use: + + (let* ((ivy-inhibit-action t) + (str (ivy-switch-buffer))) + ;; do whatever with str - the corresponding buffer will not be opened + )") + +(defun ivy-recursive-restore () + "Restore the above state when exiting the minibuffer. +See variable `ivy-recursive-restore' for further information." + (when (and ivy-recursive-last + ivy-recursive-restore + (not (eq ivy-last ivy-recursive-last))) + (ivy--reset-state (setq ivy-last ivy-recursive-last)))) + +(defvar ivy-mark-prefix ">" + "Prefix used by `ivy-mark'.") + +(defun ivy--call-marked (action) + (let* ((prefix-len (length ivy-mark-prefix)) + (marked-candidates + (mapcar + (lambda (s) + (let ((cand (substring s prefix-len))) + (if ivy--directory + (expand-file-name cand ivy--directory) + cand))) + ivy-marked-candidates)) + (multi-action (ivy--get-multi-action ivy-last))) + (if multi-action + (let ((default-directory (ivy-state-directory ivy-last))) + (funcall multi-action (mapcar #'ivy--call-cand marked-candidates))) + (dolist (c marked-candidates) + (let ((default-directory (ivy-state-directory ivy-last))) + (funcall action (ivy--call-cand c))))))) + +(defun ivy--call-cand (current) + (let ((collection (ivy-state-collection ivy-last))) + (cond + ;; Alist type. + ((and (consp (car-safe collection)) + ;; Previously, the cdr of the selected + ;; candidate would be returned. Now, the + ;; whole candidate is returned. + (let ((idx (get-text-property 0 'idx current))) + (if idx + (progn + (ivy--remove-props current 'idx) + (nth idx collection)) + (assoc current collection))))) + (ivy--directory + (expand-file-name current ivy--directory)) + ((equal current "") + ivy-text) + (t + current)))) + +(defun ivy-call () + "Call the current action without exiting completion." + (interactive) + ;; Testing with `ivy-with' seems to call `ivy-call' again, + ;; in which case `this-command' is nil; so check for this. + (unless (memq this-command '(nil + ivy-done + ivy-alt-done + ivy-dispatching-done)) + (setq ivy-current-prefix-arg current-prefix-arg)) + (let* ((action + (if (functionp ivy-inhibit-action) + ivy-inhibit-action + (and (not ivy-inhibit-action) + (ivy--get-action ivy-last)))) + (current (ivy-state-current ivy-last)) + (x (ivy--call-cand current)) + (res + (cond + ((null action) + current) + (t + (select-window (ivy--get-window ivy-last)) + (set-buffer (ivy-state-buffer ivy-last)) + (prog1 (unwind-protect + (if ivy-marked-candidates + (ivy--call-marked action) + (funcall action x)) + (ivy-recursive-restore)) + (unless (or (eq ivy-exit 'done) + (minibuffer-window-active-p (selected-window)) + (null (active-minibuffer-window))) + (select-window (active-minibuffer-window)))))))) + (if ivy-inhibit-action + res + current))) + +(defun ivy-call-and-recenter () + "Call action and recenter window according to the selected candidate." + (interactive) + (ivy-call) + (with-ivy-window + (recenter-top-bottom))) + +(defun ivy-next-line-and-call (&optional arg) + "Move cursor vertically down ARG candidates. +Call the permanent action if possible." + (interactive "p") + (ivy-next-line arg) + (ivy--exhibit) + (ivy-call)) + +(defun ivy-previous-line-and-call (&optional arg) + "Move cursor vertically up ARG candidates. +Call the permanent action if possible." + (interactive "p") + (ivy-previous-line arg) + (ivy--exhibit) + (ivy-call)) + +(defun ivy-previous-history-element (arg) + "Forward to `previous-history-element' with ARG." + (interactive "p") + (previous-history-element arg) + (ivy--cd-maybe) + (move-end-of-line 1) + (ivy--maybe-scroll-history)) + +(defun ivy--insert-symbol-boundaries () + (undo-boundary) + (beginning-of-line) + (insert "\\_<") + (end-of-line) + (insert "\\_>")) + +(defun ivy-next-history-element (arg) + "Forward to `next-history-element' with ARG." + (interactive "p") + (if (and (= minibuffer-history-position 0) + (equal ivy-text "")) + (progn + (when minibuffer-default + (setq ivy--default (car minibuffer-default))) + (insert ivy--default) + (when (and (with-ivy-window (derived-mode-p 'prog-mode)) + (eq (ivy-state-caller ivy-last) 'swiper) + (not (file-exists-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))) + (next-history-element arg)) + (ivy--cd-maybe) + (move-end-of-line 1) + (ivy--maybe-scroll-history)) + +(defvar ivy-ffap-url-functions nil + "List of functions that check if the point is on a URL.") + +(defun ivy--cd-maybe () + "Check if the current input points to a different directory. +If so, move to that directory, while keeping only the file name." + (when ivy--directory + (let ((input (ivy--input)) + url) + (if (setq url (or (ivy-ffap-url-p input) + (with-ivy-window + (cl-reduce + (lambda (a b) + (or a (funcall b))) + ivy-ffap-url-functions + :initial-value nil)))) + (ivy-exit-with-action + (lambda (_) + (ivy-ffap-url-fetcher url)) + 'no-update-history) + (setq input (expand-file-name input)) + (let ((file (file-name-nondirectory input)) + (dir (expand-file-name (file-name-directory input)))) + (if (string= dir ivy--directory) + (progn + (delete-minibuffer-contents) + (insert file)) + (ivy--cd dir) + (insert file))))))) + +(defun ivy--maybe-scroll-history () + "If the selected history element has an index, scroll there." + (let ((idx (ignore-errors + (get-text-property + (minibuffer-prompt-end) + 'ivy-index)))) + (when idx + (ivy--exhibit) + (ivy-set-index idx)))) + +(declare-function tramp-get-completion-methods "tramp") + +(defun ivy--cd (dir) + "When completing file names, move to directory DIR." + (if (ivy--completing-fname-p) + (progn + (push dir ivy--directory-hist) + (setq ivy--old-cands nil) + (setq ivy--old-re nil) + (ivy-set-index 0) + (setq ivy--all-candidates + (append + (ivy--sorted-files (setq ivy--directory dir)) + (when (and (string= dir "/") (featurep 'tramp)) + (sort + (mapcar + (lambda (s) (substring s 1)) + (tramp-get-completion-methods "")) + #'string<)))) + (ivy-set-text "") + (setf (ivy-state-directory ivy-last) dir) + (delete-minibuffer-contents)) + (error "Unexpected"))) + +(defun ivy--parent-dir (filename) + "Return parent directory of absolute FILENAME." + (file-name-directory (directory-file-name filename))) + +(defun ivy-backward-delete-char () + "Forward to `delete-backward-char'. +Call `ivy-on-del-error-function' if an error occurs, usually when +there is no more text to delete at the beginning of the +minibuffer." + (interactive) + (if (and ivy--directory (= (minibuffer-prompt-end) (point))) + (progn + (ivy--cd (ivy--parent-dir (expand-file-name ivy--directory))) + (ivy--exhibit)) + (setq prefix-arg current-prefix-arg) + (condition-case nil + (call-interactively #'delete-backward-char) + (error + (when ivy-on-del-error-function + (funcall ivy-on-del-error-function)))))) + +(defun ivy-delete-char (arg) + "Forward to `delete-char' ARG." + (interactive "p") + (unless (eolp) + (delete-char arg))) + +(defun ivy-forward-char (arg) + "Forward to `forward-char' ARG." + (interactive "p") + (unless (eolp) + (forward-char arg))) + +(defun ivy-kill-word (arg) + "Forward to `kill-word' ARG." + (interactive "p") + (unless (eolp) + (kill-word arg))) + +(defun ivy-kill-line () + "Forward to `kill-line'." + (interactive) + (if (eolp) + (kill-region (minibuffer-prompt-end) (point)) + (kill-line))) + +(defun ivy-kill-whole-line () + "Forward to `kill-whole-line'." + (interactive) + (kill-region (minibuffer-prompt-end) (line-end-position))) + +(defun ivy-backward-kill-word () + "Forward to `backward-kill-word'." + (interactive) + (if (and ivy--directory (= (minibuffer-prompt-end) (point))) + (progn + (ivy--cd (ivy--parent-dir (expand-file-name ivy--directory))) + (ivy--exhibit)) + (ignore-errors + (let ((pt (point)) + (last-command (if (eq last-command 'ivy-backward-kill-word) + 'kill-region + last-command))) + (forward-word -1) + (kill-region pt (point)))))) + +(defvar ivy--regexp-quote #'regexp-quote + "Store the regexp quoting state.") + +(defun ivy-toggle-regexp-quote () + "Toggle the regexp quoting." + (interactive) + (setq ivy--old-re nil) + (cl-rotatef ivy--regex-function ivy--regexp-quote) + (setq ivy--old-text "") + (setq ivy-regex (funcall ivy--regex-function ivy-text))) + +(defcustom ivy-format-functions-alist + '((t . ivy-format-function-default)) + "An alist of functions that transform the list of candidates into a string. +This string is inserted into the minibuffer." + :type '(alist + :key-type symbol + :value-type + (choice + (const :tag "Default" ivy-format-function-default) + (const :tag "Arrow prefix" ivy-format-function-arrow) + (const :tag "Full line" ivy-format-function-line) + (function :tag "Custom function")))) + +(defun ivy-sort-file-function-default (x y) + "Compare two files X and Y. +Prioritize directories." + (if (get-text-property 0 'dirp x) + (if (get-text-property 0 'dirp y) + (string< (directory-file-name x) (directory-file-name y)) + t) + (if (get-text-property 0 'dirp y) + nil + (string< 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 + '((t . ivy-string<)) + "An alist of sorting functions for each collection function. +Interactive functions that call completion fit in here as well. + +Nil means no sorting, which is useful to turn off the sorting for +functions that have candidates in the natural buffer order, like +`org-refile' or `Man-goto-section'. + +A list can be used to associate multiple sorting functions with a +collection. The car of the list is the current sort +function. This list can be rotated with `ivy-rotate-sort'. + +The entry associated with t is used for all fall-through cases. + +See also `ivy-sort-max-size'." + :type + '(alist + :key-type (choice + (const :tag "Fall-through" t) + (symbol :tag "Collection")) + :value-type (choice + (const :tag "Plain sort" ivy-string<) + (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"))))) + +(defun ivy--sort-function (collection) + "Retrieve sort function for COLLECTION from `ivy-sort-functions-alist'." + (let ((entry (cdr (or (assq collection ivy-sort-functions-alist) + (assq (ivy-state-caller ivy-last) ivy-sort-functions-alist) + (assq t ivy-sort-functions-alist))))) + (and (or (functionp entry) + (functionp (setq entry (car-safe entry)))) + entry))) + +(defun ivy-rotate-sort () + "Rotate through sorting functions available for current collection. +This only has an effect if multiple sorting functions are +specified for the current collection in +`ivy-sort-functions-alist'." + (interactive) + (let ((cell (or (assq (ivy-state-collection ivy-last) ivy-sort-functions-alist) + (assq (ivy-state-caller ivy-last) ivy-sort-functions-alist) + (assq t ivy-sort-functions-alist)))) + (when (consp (cdr cell)) + (setcdr cell (nconc (cddr cell) (list (cadr cell)))) + (ivy--reset-state ivy-last)))) + +(defcustom ivy-index-functions-alist + '((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 +selected." + :type '(alist :key-type symbol :value-type function)) + +(defvar ivy-re-builders-alist + '((t . ivy--regex-plus)) + "An alist of regex building functions for each collection function. + +Each key is (in order of priority): +1. The actual collection function, e.g. `read-file-name-internal'. +2. The symbol passed by :caller into `ivy-read'. +3. `this-command'. +4. t. + +Each value is a function that should take a string and return a +valid regex or a regex sequence (see below). + +Possible choices: `ivy--regex', `regexp-quote', +`ivy--regex-plus', `ivy--regex-fuzzy', `ivy--regex-ignore-order'. + +If a function returns a list, it should format like this: +'((\"matching-regexp\" . t) (\"non-matching-regexp\") ...). + +The matches will be filtered in a sequence, you can mix the +regexps that should match and that should not match as you +like.") + +(defvar ivy-highlight-functions-alist + '((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 builder function.") + +(defcustom ivy-initial-inputs-alist + '((org-refile . "^") + (org-agenda-refile . "^") + (org-capture-refile . "^") + (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)))) + +(defcustom ivy-hooks-alist nil + "An alist associating commands to setup functions. +Examples: `toggle-input-method', (lambda () (insert \"^\")), etc. +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)))) + +(defcustom ivy-unwind-fns-alist nil + "An alist associating commands to their :unwind values." + :type '(alist :key-type symbol :value-type function)) + +(defcustom ivy-init-fns-alist nil + "An alist associating commands to their :init values. +An :init is a function with no arguments. +`ivy-read' calls it to initialize." + :type '(alist :key-type symbol :value-type function)) + +(defun ivy--alist-set (alist-sym key val) + (let ((curr-val (symbol-value alist-sym)) + (customized-val (get alist-sym 'customized-value)) + (default-val (eval (car (get alist-sym 'standard-value))))) + ;; when the value was set by `customize-set-variable', don't touch it + (unless customized-val + ;; only works if the value wasn't customized by the user + (when (or (null default-val) (equal curr-val default-val)) + (let ((cell (assoc key curr-val))) + (if cell + (setcdr cell val) + (set alist-sym (cons (cons key val) + (symbol-value alist-sym))))) + (when default-val + (put alist-sym 'standard-value + (list (list 'quote (symbol-value alist-sym))))))))) + +(declare-function counsel-set-async-exit-code "counsel") + +(defvar ivy--parents-alist nil + "Configure parent caller for child caller. +The child caller inherits and can override the settings of the parent.") + +(cl-defun ivy-configure (caller + &key + parent + initial-input + height + occur + update-fn + init-fn + unwind-fn + index-fn + sort-fn + format-fn + display-fn + display-transformer-fn + alt-done-fn + more-chars + grep-p + exit-codes) + "Configure `ivy-read' params for CALLER." + (declare (indent 1)) + (when parent + (ivy--alist-set 'ivy--parents-alist caller parent)) + (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 init-fn + (ivy--alist-set 'ivy-init-fns-alist caller init-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-fn + (ivy--alist-set 'ivy-display-functions-alist caller display-fn)) + (when display-transformer-fn + (ivy--alist-set 'ivy--display-transformers-alist caller display-transformer-fn)) + (when alt-done-fn + (ivy--alist-set 'ivy-alt-done-functions-alist caller alt-done-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) + +(defalias 'ivy--dirname-p + ;; Added in Emacs 25.1. + (if (fboundp 'directory-name-p) + #'directory-name-p + (lambda (name) + "Return non-nil if NAME ends with a directory separator." + (string-suffix-p "/" name)))) + +(defun ivy--sorted-files (dir) + "Return the list of files in DIR. +Directories come first." + (let* ((default-directory dir) + (seq (condition-case nil + (mapcar (lambda (s) (replace-regexp-in-string "\\$\\$" "$" s)) + (all-completions "" #'read-file-name-internal + (ivy-state-predicate ivy-last))) + (error + (directory-files dir)))) + sort-fn) + (setq seq (delete "./" (delete "../" seq))) + (when (eq (setq sort-fn (ivy--sort-function #'read-file-name-internal)) + #'ivy-sort-file-function-default) + (setq seq (mapcar (lambda (x) + (propertize x 'dirp (ivy--dirname-p x))) + seq))) + (when sort-fn + (setq seq (sort seq sort-fn))) + (dolist (dir ivy-extra-directories) + (push dir seq)) + (if (string= dir "/") + (cl-remove-if (lambda (s) (string-match ":$" s)) (delete "../" seq)) + seq))) + +(defun ivy-alist-setting (alist &optional key) + "Return the value associated with KEY in ALIST, using `assq'. +KEY defaults to the last caller of `ivy-read'; if no entry is +found, it falls back to the key t." + (let ((caller (or key (ivy-state-caller ivy-last)))) + (or + (and caller (cdr (assq caller alist))) + (let ((parent (cdr (assq caller ivy--parents-alist)))) + (when parent + (ivy-alist-setting alist parent))) + (cdr (assq t alist))))) + +(defun ivy--height (caller) + (let ((v (or (ivy-alist-setting ivy-height-alist caller) + ivy-height))) + (if (integerp v) + v + (if (functionp v) + (funcall v caller) + (error "Unexpected value: %S" v))))) + +(defun ivy--remove-props (str &rest props) + "Return STR with text PROPS destructively removed." + (ignore-errors + (remove-list-of-text-properties 0 (length str) props str)) + str) + +(defun ivy--update-prompt (prompt) + (cond ((equal prompt "Keyword, C-h: ") + ;; auto-insert.el + "Keyword (C-M-j to end): ") + (t + ;; misearch.el + (replace-regexp-in-string "RET to end" "C-M-j to end" prompt)))) + +;;** Entry Point +;;;###autoload +(cl-defun ivy-read (prompt collection + &key + predicate require-match initial-input + history preselect def keymap update-fn sort + action multi-action + unwind re-builder matcher + 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. +`ivy-count-format' is prepended to PROMPT during completion. + +COLLECTION is either a list of strings, a function, an alist, or +a hash table, supplied for `minibuffer-completion-table'. + +PREDICATE is applied to filter out the COLLECTION immediately. +This argument is for compatibility with `completing-read'. + +When REQUIRE-MATCH is non-nil, only members of COLLECTION can be +selected. + +If INITIAL-INPUT is non-nil, then insert that input in the +minibuffer initially. + +HISTORY is a name of a variable to hold the completion session +history. + +KEYMAP is composed with `ivy-minibuffer-map'. + +PRESELECT, when non-nil, determines which one of the candidates +matching INITIAL-INPUT to select initially. An integer stands +for the position of the desired candidate in the collection, +counting from zero. Otherwise, use the first occurrence of +PRESELECT in the collection. Comparison is first done with +`equal'. If that fails, and when applicable, match PRESELECT as +a regular expression. + +DEF is for compatibility with `completing-read'. + +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 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 +its only argument. When it's nil, ACTION is called on each marked +candidate. + +UNWIND is a function of no arguments to call before exiting. + +RE-BUILDER is a function transforming input text into a regex +pattern. + +MATCHER is a function which can override how candidates are +filtered based on user input. It takes a regex pattern and a +list of candidates, and returns the list of matching candidates. + +DYNAMIC-COLLECTION is a boolean specifying whether the list of +candidates is updated after each input by calling COLLECTION. + +EXTRA-PROPS is a plist that 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." + (let ((init-fn (ivy-alist-setting ivy-init-fns-alist caller))) + (when init-fn + (funcall init-fn))) + ;; 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 + (when (or ivy-recursive-last + (not (window-minibuffer-p))) + (ivy-alist-setting ivy-display-functions-alist caller)))) + (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 (ivy--update-prompt prompt) + :collection collection + :predicate predicate + :require-match require-match + :initial-input initial-input + :history history + :preselect preselect + :keymap keymap + :update-fn (if (eq update-fn 'auto) + (lambda () + (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) + :multi-action multi-action + :frame (selected-frame) + :window (selected-window) + :buffer (current-buffer) + :unwind unwind + :re-builder re-builder + :matcher matcher + :dynamic-collection dynamic-collection + :display-transformer-fn (ivy-alist-setting ivy--display-transformers-alist caller) + :directory default-directory + :extra-props extra-props + :caller caller + :def def)) + (ivy--reset-state ivy-last) + (unwind-protect + (minibuffer-with-setup-hook + #'ivy--minibuffer-setup + (let* ((hist (or history 'ivy-history)) + (minibuffer-completion-table collection) + (minibuffer-completion-predicate predicate) + (ivy-height (ivy--height caller)) + (resize-mini-windows (unless (display-graphic-p) + 'grow-only))) + (if (and ivy-auto-select-single-candidate + ivy--all-candidates + (null (cdr ivy--all-candidates))) + (progn + (setf (ivy-state-current ivy-last) + (car ivy--all-candidates)) + (setq ivy-exit 'done)) + (condition-case err + (read-from-minibuffer + prompt + (ivy-state-initial-input ivy-last) + (make-composed-keymap keymap ivy-minibuffer-map) + nil + hist) + (error + (unless (equal err '(error "Selecting deleted buffer")) + (signal (car err) (cdr err)))))) + (when (eq ivy-exit 'done) + (ivy--update-history hist)))) + (let ((session (or (plist-get extra-props :session) + (unless (or (minibufferp) + (null (ivy-state-action ivy-last)) + (eq (ivy--get-action ivy-last) #'identity)) + caller)))) + (when session + (setf (ivy-state-extra-props ivy-last) + (plist-put extra-props :ivy-data `(:all-candidates ,ivy--all-candidates + :text ,ivy-text))) + (ivy--alist-set 'ivy--sessions session ivy-last))) + (ivy--cleanup)) + (ivy-call))) + +(defun ivy--update-history (hist) + (let ((item + (if (or (string= ivy-text "") + (eq + (plist-get (ivy-state-extra-props ivy-last) :caller) + 'ivy-completing-read) + (eq (ivy-state-history ivy-last) 'file-name-history)) + (ivy-state-current ivy-last) + ivy-text))) + (cond ((equal item "")) + ((stringp item) + (set hist (cons (propertize item 'ivy-index ivy--index) + (delete item (symbol-value hist)))))))) + +(defun ivy--cleanup () + ;; Fixes a bug in ESS, #1660 + (put 'post-command-hook 'permanent-local nil) + (remove-hook 'post-command-hook #'ivy--queue-exhibit) + (remove-hook 'window-size-change-functions #'ivy--window-size-changed) + (let ((cleanup (ivy--display-function-prop :cleanup)) + (unwind (ivy-state-unwind ivy-last))) + (when (functionp cleanup) + (funcall cleanup)) + (when unwind + (funcall unwind))) + (ivy--pulse-cleanup) + (unless (eq ivy-exit 'done) + (ivy-recursive-restore))) + +(defun ivy--display-function-prop (prop) + "Return PROP associated with current `ivy--display-function'." + (plist-get (cdr (assq ivy--display-function + ivy-display-functions-props)) + prop)) + +(defvar Info-complete-menu-buffer) + +(defun ivy--reset-state (state) + "Reset the ivy to STATE. +This is useful for recursive `ivy-read'." + (setq ivy-marked-candidates nil) + (unless (equal (selected-frame) (ivy-state-frame state)) + (select-window (active-minibuffer-window))) + (let* ((prompt (or (ivy-state-prompt state) "")) + (collection (ivy-state-collection state)) + (predicate (ivy-state-predicate state)) + (history (ivy-state-history state)) + (preselect (ivy-state-preselect state)) + (re-builder (ivy-state-re-builder state)) + (dynamic-collection (ivy-state-dynamic-collection state)) + (require-match (ivy-state-require-match state)) + (caller (or (ivy-state-caller state) this-command)) + (sort (or (ivy-state-sort state) (assoc caller ivy-sort-functions-alist))) + (initial-input + (or (ivy-state-initial-input state) + (let ((init (ivy-alist-setting ivy-initial-inputs-alist caller))) + (if (functionp init) (funcall init) init)))) + (def (ivy-state-def state))) + (when (and (eq caller 'swiper-isearch) (buffer-modified-p)) + (setq preselect nil)) + (setq ivy--extra-candidates (ivy--compute-extra-candidates caller)) + (setq ivy--directory nil) + (setq ivy--directory-hist (list default-directory)) + (setq ivy-case-fold-search ivy-case-fold-search-default) + (setf (ivy-state-re-builder ivy-last) + (setq ivy--regex-function + (or re-builder + (and (functionp collection) + (cdr (assq collection ivy-re-builders-alist))) + (ivy-alist-setting ivy-re-builders-alist) + #'ivy--regex))) + (setq ivy--subexps 0) + (setq ivy--regexp-quote #'regexp-quote) + (setq ivy--old-text "") + (setq ivy--full-length nil) + (ivy-set-text (or initial-input "")) + (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-alist-setting ivy-re-builders-alist) + ivy-highlight-functions-alist)) + #'ivy--highlight-default)) + (let ((ivy-recursive-restore nil) + coll sort-fn) + (cond ((eq collection #'Info-read-node-name-1) + (setq coll + (if (equal (bound-and-true-p Info-current-file) "dir") + (mapcar (lambda (x) (format "(%s)" x)) + (delete-dups + (all-completions "(" collection predicate))) + (all-completions "" collection predicate)))) + ((memq collection '(read-file-name-internal ffap-read-file-or-url-internal)) + (require 'tramp) + (when (and (equal def initial-input) + (member "./" ivy-extra-directories)) + (setq def nil)) + (setq ivy--directory default-directory) + (when (and initial-input + (not (equal initial-input ""))) + (cond ((file-directory-p initial-input) + (when (equal (file-name-nondirectory initial-input) "") + (setf (ivy-state-preselect state) (setq preselect nil)) + (setq def nil)) + (setq ivy--directory (file-name-as-directory initial-input)) + (setq initial-input nil) + (when preselect + (let ((preselect-directory + (file-name-directory preselect))) + (when (and preselect-directory + (not (equal + (expand-file-name + preselect-directory) + (expand-file-name ivy--directory)))) + (setf (ivy-state-preselect state) + (setq preselect nil)))))) + ((ignore-errors + (file-exists-p (file-name-directory initial-input))) + (setq ivy--directory (file-name-directory initial-input)) + (setf (ivy-state-preselect state) + (file-name-nondirectory initial-input))))) + (require 'dired) + (when preselect + (let ((preselect-directory (ivy--parent-dir preselect))) + (when (and preselect-directory + (not (string= preselect-directory + default-directory))) + (setq ivy--directory preselect-directory)) + (setq preselect (file-relative-name preselect + preselect-directory)) + (setf (ivy-state-preselect state) preselect))) + (setq sort nil) + (setq coll (ivy--sorted-files ivy--directory)) + (when initial-input + (unless (or require-match + (equal initial-input default-directory) + (equal initial-input "")) + (setq coll (cons initial-input coll))) + (setq initial-input (file-name-nondirectory initial-input)))) + ((eq collection #'internal-complete-buffer) + (setq coll (ivy--buffer-list + "" + (and ivy-use-virtual-buffers + (member caller '(ivy-switch-buffer + ivy-switch-buffer-other-window + counsel-switch-buffer))) + predicate))) + (dynamic-collection + (setq coll (if (and (eq this-command 'ivy-resume) (not (buffer-modified-p))) + ivy--all-candidates + (ivy--dynamic-collection-cands (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))) + (setq collection (sort (copy-sequence collection) sort-fn)) + (setq sort nil)) + (setf (ivy-state-collection ivy-last) collection) + (setq coll (let ((i -1)) + (mapcar (lambda (x) + (propertize x 'idx (cl-incf i))) + (all-completions "" collection))))) + ((or (functionp collection) + (byte-code-function-p collection) + (vectorp collection) + (hash-table-p collection) + (and (listp collection) (symbolp (car collection)))) + (let ((Info-complete-menu-buffer + ;; FIXME: This is a temporary workaround for issue #1803. + (or (bound-and-true-p Info-complete-menu-buffer) + (ivy-state-buffer state)))) + (setq coll (all-completions "" collection predicate)))) + (t + (setq coll (all-completions "" collection predicate)))) + (unless (ivy-state-dynamic-collection ivy-last) + (setq coll (delete "" coll))) + (when (and sort + (or (functionp collection) + (not (eq history 'org-refile-history))) + (setq sort-fn (ivy--sort-function + (if (functionp collection) collection caller))) + (listp coll) + (null (nthcdr ivy-sort-max-size coll))) + (setq coll (sort (copy-sequence coll) sort-fn))) + (when def + (cond ((stringp (car-safe def)) + (setq coll + (delete-dups + (append def coll)))) + ((and (stringp def) (not (member def coll))) + (push def coll)))) + (setq coll (ivy--set-candidates coll)) + (setq ivy--old-re nil) + (setq ivy--old-cands nil) + (when initial-input + ;; Needed for anchor to work + (setq ivy--old-cands coll) + (setq ivy--old-cands (ivy--filter initial-input coll))) + (unless (setq ivy--trying-to-resume-dynamic-collection + (and preselect dynamic-collection)) + (when (integerp preselect) + (setq ivy--old-re "") + (ivy-set-index preselect))) + (setq ivy--all-candidates coll) + (unless (integerp preselect) + (ivy-set-index (or + (and dynamic-collection + ivy--index) + (and preselect + (ivy--preselect-index + preselect + (if initial-input + ivy--old-cands + coll))) + 0)))) + (setq ivy-exit nil) + (setq ivy--default + (if (region-active-p) + (buffer-substring (region-beginning) (region-end)) + (ivy-thing-at-point))) + (setq ivy--prompt (ivy-add-prompt-count (ivy--quote-format-string prompt))) + (setq ivy--use-selectable-prompt (ivy--prompt-selectable-p)) + (setf (ivy-state-initial-input ivy-last) initial-input))) + +(defun ivy-add-prompt-count (prompt) + "Add count information to PROMPT." + (cond ((null ivy-count-format) + (error "`ivy-count-format' must not be nil; set it to \"\" instead")) + ((string-match "%d.*\\(%d\\)" ivy-count-format) + (let* ((w + (if (listp ivy--all-candidates) + (1+ (floor (log (max 1 (length ivy--all-candidates)) 10))) + 1)) + (s (replace-match (format "%%-%dd" w) t t ivy-count-format 1))) + (string-match "%d" s) + (concat (replace-match (format "%%%dd" w) t t s) + prompt))) + ((string-match-p "%.*d" ivy-count-format) + (concat ivy-count-format prompt)) + (t + prompt))) + +(defun ivy--quote-format-string (str) + "Make STR suitable for `format' with no extra arguments." + (replace-regexp-in-string "%" "%%" str t t)) + +;;;###autoload +(defun ivy-completing-read (prompt collection + &optional predicate require-match initial-input + history def inherit-input-method) + "Read a string in the minibuffer, with completion. + +This interface conforms to `completing-read' and can be used for +`completing-read-function'. + +PROMPT is a string that normally ends in a colon and a space. +COLLECTION is either a list of strings, an alist, an obarray, or a hash table. +PREDICATE limits completion to a subset of COLLECTION. +REQUIRE-MATCH is a boolean value or a symbol. See `completing-read'. +INITIAL-INPUT is a string inserted into the minibuffer initially. +HISTORY is a list of previously selected inputs. +DEF is the default value. +INHERIT-INPUT-METHOD is currently ignored." + (let ((handler + (and (< ivy-completing-read-ignore-handlers-depth (minibuffer-depth)) + (assq this-command ivy-completing-read-handlers-alist)))) + (if handler + (let ((completion-in-region-function #'completion--in-region) + (ivy-completing-read-ignore-handlers-depth (1+ (minibuffer-depth)))) + (funcall (cdr handler) + prompt collection + predicate require-match + initial-input history + def inherit-input-method)) + ;; See the doc of `completing-read'. + (when (consp history) + (when (numberp (cdr history)) + (setq initial-input (nth (1- (cdr history)) + (symbol-value (car history))))) + (setq history (car history))) + (when (consp def) + (setq def (car def))) + (let ((str (ivy-read + prompt collection + :predicate predicate + :require-match (when (and collection require-match) + require-match) + :initial-input (cond ((consp initial-input) + (car initial-input)) + ((and (stringp initial-input) + (not (eq collection #'read-file-name-internal)) + (string-match-p "\\+" initial-input)) + (replace-regexp-in-string + "\\+" "\\\\+" initial-input)) + (t + initial-input)) + :preselect def + :def def + :history history + :keymap nil + :dynamic-collection ivy-completing-read-dynamic-collection + :extra-props '(:caller ivy-completing-read) + :caller (if (and collection (symbolp collection)) + collection + this-command)))) + (if (string= str "") + ;; For `completing-read' compat, return the first element of + ;; DEFAULT, if it is a list; "", if DEFAULT is nil; or DEFAULT. + (or def "") + str))))) + +(defun ivy-completing-read-with-empty-string-def + (prompt collection + &optional predicate require-match initial-input + history def inherit-input-method) + "Same as `ivy-completing-read' but with different handling of DEF. + +Specifically, if DEF is nil, it is treated the same as if DEF was +the empty string. This mimics the behavior of +`completing-read-default'. This function can therefore be used in +place of `ivy-completing-read' for commands that rely on this +behavior." + (ivy-completing-read + 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 (require 'multiple-cursors-core nil t) + (mc/all-fake-cursors))) + (pt (point)) + (beg ivy-completion-beg) + (end ivy-completion-end)) + (when beg + (delete-region beg end)) + (setq ivy-completion-beg (point)) + (insert (substring-no-properties str)) + (completion--done str 'exact) + (setq ivy-completion-end (point)) + (save-excursion + (dolist (cursor fake-cursors) + (goto-char (overlay-start cursor)) + (delete-region (+ (point) (- beg pt)) + (+ (point) (- end pt))) + (insert (substring-no-properties str)) + ;; manually move the fake cursor + (move-overlay cursor (point) (1+ (point))) + (set-marker (overlay-get cursor 'point) (point)) + (set-marker (overlay-get cursor 'mark) (point))))))) + +(defun ivy-completion-common-length (str) + "Return the amount of characters that match in STR. + +`completion-all-completions' computes this and returns the result +via text properties. + +The first non-matching part is propertized: +- either with: (face (completions-first-difference)) +- or: (font-lock-face completions-first-difference)." + (let ((char-property-alias-alist '((face font-lock-face))) + (i (1- (length str)))) + (catch 'done + (while (>= i 0) + (when (equal (get-text-property i 'face str) + '(completions-first-difference)) + (throw 'done i)) + (cl-decf i)) + (throw 'done (length str))))) + +(defun ivy-completion-in-region (start end collection &optional predicate) + "An Ivy function suitable for `completion-in-region-function'. +The function completes the text between START and END using COLLECTION. +PREDICATE (a function called with no arguments) says when to exit. +See `completion-in-region' for further information." + (let* ((enable-recursive-minibuffers t) + (str (buffer-substring-no-properties start end)) + (completion-ignore-case (ivy--case-fold-p str)) + (comps + (completion-all-completions str collection predicate (- end start)))) + (cond ((null comps) + (message "No matches")) + ((progn + (nconc comps nil) + (and (null (cdr comps)) + (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) + "") + ((let ((str-len (length str))) + (when (> len str-len) + (setq len str-len) + str))) + (t + (substring str (- len)))))) + (delete-region (- end len) end) + (setq ivy-completion-beg (- end len)) + (setq ivy-completion-end ivy-completion-beg) + (if (null (cdr comps)) + (progn + (unless (minibuffer-window-active-p (selected-window)) + (setf (ivy-state-window ivy-last) (selected-window))) + (ivy-completion-in-region-action + (substring-no-properties (car comps)))) + (dolist (s comps) + ;; Remove face `completions-first-difference'. + (ivy--remove-props s 'face)) + (setq ivy--old-re nil) + (unless (ivy--filter initial comps) + (setq initial nil) + (setq predicate nil) + (setq collection comps)) + (unless (derived-mode-p #'emacs-lisp-mode) + (setq collection comps) + (setq predicate nil)) + (ivy-read (format "(%s): " str) collection + :predicate predicate + :initial-input (concat + (and (derived-mode-p #'emacs-lisp-mode) + "^") + initial) + :action #'ivy-completion-in-region-action + :unwind (lambda () + (unless (eq ivy-exit 'done) + (goto-char ivy-completion-beg) + (when initial + (insert initial)))) + :caller 'ivy-completion-in-region))) + ;; Return value should be non-nil on valid completion; + ;; see `completion-in-region'. + t)))) + +(defun ivy-completion-in-region-prompt () + "Prompt function for `ivy-completion-in-region'. +See `ivy-set-prompt'." + (and (window-minibuffer-p (ivy-state-window ivy-last)) + (ivy-add-prompt-count (ivy-state-prompt ivy-last)))) + +(ivy-set-prompt #'ivy-completion-in-region #'ivy-completion-in-region-prompt) + +(defcustom ivy-do-completion-in-region t + "When non-nil `ivy-mode' will set `completion-in-region-function'." + :type 'boolean) + +(defvar ivy--old-crf nil + "Store previous value of `completing-read-function'.") + +(defvar ivy--old-cirf nil + "Store previous value of `completion-in-region-function'.") + +;;;###autoload +(define-minor-mode ivy-mode + "Toggle Ivy mode on or off. +Turn Ivy mode on if ARG is positive, off otherwise. +Turning on Ivy mode sets `completing-read-function' to +`ivy-completing-read'. + +Global bindings: +\\{ivy-mode-map} + +Minibuffer bindings: +\\{ivy-minibuffer-map}" + :group 'ivy + :global t + :keymap ivy-mode-map + :lighter " ivy" + (if ivy-mode + (progn + (unless (eq completing-read-function #'ivy-completing-read) + (setq ivy--old-crf completing-read-function) + (setq completing-read-function #'ivy-completing-read)) + (when ivy-do-completion-in-region + (unless (eq completion-in-region-function #'ivy-completion-in-region) + (setq ivy--old-cirf completion-in-region-function) + (setq completion-in-region-function #'ivy-completion-in-region)))) + (when (eq completing-read-function #'ivy-completing-read) + (setq completing-read-function (or ivy--old-crf + #'completing-read-default)) + (setq ivy--old-crf nil)) + (when (eq completion-in-region-function #'ivy-completion-in-region) + (setq completion-in-region-function (or ivy--old-cirf + #'completion--in-region)) + (setq ivy--old-cirf nil)))) + +(defun ivy--preselect-index (preselect candidates) + "Return the index of PRESELECT in CANDIDATES." + (or (cond ((integerp 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))) + 0)) + +;;* Implementation +;;** Regex +(defun ivy-re-match (re-seq str) + "Return non-nil if RE-SEQ is matched by STR. + +RE-SEQ is a list of (RE . MATCH-P). + +RE is a regular expression. + +MATCH-P is t when RE should match STR and nil when RE should not +match STR. + +Each element of RE-SEQ must match for the function to return true. + +This concept is used to generalize regular expressions for +`ivy--regex-plus' and `ivy--regex-ignore-order'." + (let ((res t) + re) + (while (and res (setq re (pop re-seq))) + (setq res + (if (cdr re) + (string-match-p (car re) str) + (not (string-match-p (car re) str))))) + res)) + +(defvar ivy--regex-hash + (make-hash-table :test #'equal) + "Store pre-computed regex.") + +(defvar ivy--input-garbage nil) + +(defun ivy--split (str) + "Split STR into list of substrings bounded by spaces. +Single spaces act as splitting points. Consecutive spaces +\"quote\" their preceding spaces, i.e., guard them from being +split. This allows the literal interpretation of N spaces by +inputting N+1 spaces. Any substring not constituting a valid +regexp is passed to `regexp-quote'." + (let ((len (length str)) + (i 0) + (start 0) + (res nil) + match-len + end + c) + (catch 'break + (while (< i len) + (setq c (aref str i)) + (cond ((= ?\[ c) + (if (setq end (ivy--match-regex-brackets + (substring str i))) + (cl-incf i end) + (setq ivy--input-garbage (substring str i)) + (throw 'break nil))) + ((= ?\\ c) + (if (and (< (1+ i) len) (= ?\( (aref str (1+ i)))) + (progn + (when (> i start) + (push (substring str start i) res)) + (if (eq (string-match "\\\\([^\0]*?\\\\)" str i) i) + (progn + (push (match-string 0 str) res) + (setq i (match-end 0)) + (setq start i)) + (setq ivy--input-garbage (substring str i)) + (throw 'break nil))) + (cl-incf i))) + ((= ?\ c) + (string-match " +" str i) + (setq match-len (- (match-end 0) (match-beginning 0))) + (if (= match-len 1) + (progn + (when (> i start) + (push (substring str start i) res)) + (setq start (1+ i))) + (setq str (replace-match + (make-string (1- match-len) ?\ ) + nil nil str)) + (setq len (length str)) + (cl-incf i (1- match-len))) + (cl-incf i)) + (t + (cl-incf i))))) + (when (< start i) + (push (substring str start) res)) + (mapcar #'ivy--regex-or-literal (nreverse res)))) + +(defun ivy--match-regex-brackets (str) + (let ((len (length str)) + (i 1) + (open-count 1) + c) + (while (and (< i len) + (> open-count 0)) + (setq c (aref str i)) + (cond ((= c ?\[) + (cl-incf open-count)) + ((= c ?\]) + (cl-decf open-count))) + (cl-incf i)) + (when (= open-count 0) + (if (eq (string-match "[+*?]" str i) i) + (match-end 0) + i)))) + +(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." + (let ((hashed (unless greedy + (gethash str ivy--regex-hash)))) + (if hashed + (progn + (setq ivy--subexps (car hashed)) + (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) + (cons + (setq ivy--subexps 0) + (if (string-match-p "\\`\\.[^.]" (car subs)) + (concat "\\." (substring (car subs) 1)) + (car subs))) + (cons + (setq ivy--subexps (length subs)) + (replace-regexp-in-string + "\\.\\*\\??\\\\( " + "\\( " + (mapconcat + (lambda (x) + (if (string-match-p "\\`\\\\([^?][^\0]*\\\\)\\'" x) + x + (format "\\(%s\\)" x))) + subs + (if greedy ".*" ".*?")) + nil t)))) + ivy--regex-hash))))) + +(defun ivy--regex-p (object) + "Return OBJECT if it is a valid regular expression, else nil." + (ignore-errors (string-match-p object "") object)) + +(defun ivy--regex-or-literal (str) + "If STR isn't a legal regexp, escape it." + (or (ivy--regex-p str) (regexp-quote str))) + +(defun ivy--split-negation (str) + "Split STR into text before and after ! delimiter. +Do not split if the delimiter is escaped as \\!. + +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 "\\(?:\\`\\|[^\\]\\)\\(!\\)")) + (mapcar (lambda (split) + ;; Store "\!" as "!". + (replace-regexp-in-string "\\\\!" "!" split t t)) + (if (string-match delim str) + ;; 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)) + (j (and (string-match delim str (1+ i)) + (match-beginning 1))) + (neg (substring str (1+ i) j))) + (cons (substring str 0 i) + (and (not (string= neg "")) + (list neg)))) + (list str)))))) + +(defun ivy--split-spaces (str) + "Split STR on spaces, unless they're preceded by \\. +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. + (j 0) ; End of last delimiter. + parts) + (while (string-match "\\(\\\\ \\)\\| +" str i) + (setq i (match-end 0)) + (if (not (match-beginning 1)) + ;; Un-escaped space(s). + (let ((delim (match-beginning 0))) + (when (< j delim) + (push (substring str j delim) parts)) + (setq j i)) + ;; Store "\ " as " ". + (setq str (replace-match " " t t str 1)) + (setq i (1- i)))) + (when (< j (length str)) + (push (substring str j) parts)) + (mapcar #'ivy--regex-or-literal (nreverse parts))))) + +(defun ivy--regex-ignore-order (str) + "Re-build regex from STR by splitting at spaces and using ! for negation. + +Examples: +foo -> matches \"foo\" +foo bar -> matches if both \"foo\" and \"bar\" match (any order) +foo !bar -> matches if \"foo\" matches and \"bar\" does not match +foo !bar baz -> matches if \"foo\" matches and neither \"bar\" nor \"baz\" match +foo[a-z] -> matches \"foo[a-z]\" + +Escaping examples: +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))) + (push (cons part t) regex-parts)) + (when (cdr raw-parts) + (dolist (part (ivy--split-spaces (cadr raw-parts))) + (push (cons part nil) regex-parts))) + (if regex-parts (nreverse regex-parts) + ""))) + +(defun ivy--regex-plus (str) + "Build a regex sequence from STR. +Spaces are wild card characters, everything before \"!\" should +match. Everything after \"!\" should not match." + (let ((parts (ivy--split-negation str))) + (cl-case (length parts) + (0 + "") + (1 + (if (= (aref str 0) ?!) + (list (cons "" t) + (list (ivy--regex (car parts)))) + (ivy--regex (car parts)))) + (2 + (cons + (cons (ivy--regex (car parts)) t) + (mapcar #'list (split-string (cadr parts) " " t)))) + (t (error "Unexpected: use only one !"))))) + +(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) + (let ((lst (string-to-list (match-string 2 str)))) + (apply #'concat + (cl-mapcar + #'concat + (cons "" (cdr (mapcar (lambda (c) (format "[^%c\n]*" c)) + lst))) + (mapcar (lambda (x) (format "\\(%s\\)" (regexp-quote (char-to-string x)))) + lst)))) + (match-string 3 str)) + (setq ivy--subexps (length (match-string 2 str)))) + str)) + +(defcustom ivy-fixed-height-minibuffer nil + "When non nil, fix the height of the minibuffer during ivy completion. +This effectively sets the minimum height at this level to `ivy-height' and +tries to ensure that it does not change depending on the number of candidates." + :type 'boolean) + +;;** Rest +(defcustom ivy-truncate-lines t + "Minibuffer setting for `truncate-lines'." + :type 'boolean) + +(defun ivy--minibuffer-setup () + "Setup ivy completion in the minibuffer." + (setq-local mwheel-scroll-up-function 'ivy-next-line) + (setq-local mwheel-scroll-down-function 'ivy-previous-line) + (setq-local completion-show-inline-help nil) + (setq-local line-spacing nil) + (setq-local minibuffer-default-add-function + (lambda () + (list ivy--default))) + (setq-local inhibit-field-text-motion nil) + (setq truncate-lines ivy-truncate-lines) + (setq-local max-mini-window-height ivy-height) + (let ((height (cond ((and ivy-fixed-height-minibuffer + (not (eq (ivy-state-caller ivy-last) + #'ivy-completion-in-region))) + (+ ivy-height (if ivy-add-newline-after-prompt 1 0))) + (ivy-add-newline-after-prompt 2)))) + (when height + (set-window-text-height nil height))) + (add-hook 'post-command-hook #'ivy--queue-exhibit nil t) + (add-hook 'window-size-change-functions #'ivy--window-size-changed nil t) + (let ((hook (ivy-alist-setting ivy-hooks-alist))) + (when (functionp hook) + (funcall hook)))) + +(defun ivy--input () + "Return the current minibuffer input." + ;; assume one-line minibuffer input + (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." + (save-excursion + (goto-char (minibuffer-prompt-end)) + (delete-region (line-end-position) (point-max)))) + +(defun ivy-cleanup-string (str) + "Destructively remove unwanted text properties from STR." + (ivy--remove-props str 'field)) + +(defvar ivy-set-prompt-text-properties-function + #'ivy-set-prompt-text-properties-default + "Function to set the text properties of the default ivy prompt. +Called with two arguments, PROMPT and PROPS, where PROMPT is the +string to be propertized and PROPS is a plist of default text +properties that may be applied to PROMPT. The function should +return the propertized PROMPT, which may be modified in-place.") + +(defun ivy-set-prompt-text-properties-default (prompt props) + "Propertize (confirm) and (match required) parts of PROMPT. +PROPS is a plist of default text properties to apply to these +parts beyond their respective faces `ivy-confirm-face' and +`ivy-match-required-face'." + (dolist (pair '(("confirm" . ivy-confirm-face) + ("match required" . ivy-match-required-face))) + (let ((i (string-match-p (car pair) prompt))) + (when i + (add-text-properties i (+ i (length (car pair))) + `(face ,(cdr pair) ,@props) + prompt)))) + prompt) + +(defun ivy-prompt () + "Return the current prompt." + (let* ((caller (ivy-state-caller ivy-last)) + (fn (plist-get ivy--prompts-list caller))) + (if fn + (condition-case err + (funcall fn) + (wrong-number-of-arguments + (lwarn 'ivy :error "%s + Prompt function set via `ivy-set-prompt' for caller `%s' + should take no arguments." + (error-message-string err) + caller) + ;; Old behavior. + (funcall fn (ivy-state-prompt ivy-last)))) + ivy--prompt))) + +(defun ivy--insert-prompt () + "Update the prompt according to `ivy--prompt'." + (when (setq ivy--prompt (ivy-prompt)) + (unless (memq this-command '(ivy-done ivy-alt-done ivy-partial-or-done + counsel-find-symbol)) + (setq ivy--prompt-extra "")) + (let (head tail) + (if (string-match "\\(.*?\\)\\(:? ?\\)\\'" ivy--prompt) + (progn + (setq head (match-string 1 ivy--prompt)) + (setq tail (match-string 2 ivy--prompt))) + (setq head ivy--prompt) + (setq tail "")) + (let ((inhibit-read-only t) + (std-props '(front-sticky t rear-nonsticky t field t read-only t)) + (n-str + (concat + (if (and (bound-and-true-p minibuffer-depth-indicate-mode) + (> (minibuffer-depth) 1)) + (format "[%d] " (minibuffer-depth)) + "") + (concat + (if (string-match "%d.*%d" ivy-count-format) + (format head + (1+ ivy--index) + (or (and (ivy-state-dynamic-collection ivy-last) + ivy--full-length) + ivy--length)) + (format head + (or (and (ivy-state-dynamic-collection ivy-last) + ivy--full-length) + ivy--length))) + ivy--prompt-extra + tail))) + (d-str (if ivy--directory + (abbreviate-file-name ivy--directory) + ""))) + (save-excursion + (goto-char (point-min)) + (delete-region (point-min) (minibuffer-prompt-end)) + (let ((len-n (length n-str)) + (len-d (length d-str)) + (ww (window-width))) + (setq n-str + (cond ((> (+ len-n len-d) ww) + (concat n-str "\n" d-str "\n")) + ((> (+ len-n len-d (length ivy-text)) ww) + (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)))) + (while (string-match regex n-str) + (setq n-str (replace-match + (concat (match-string 1 n-str) "\n") + nil t n-str 1)))) + (set-text-properties 0 (length n-str) + `(face minibuffer-prompt ,@std-props) + n-str) + (setq n-str (funcall ivy-set-prompt-text-properties-function + n-str std-props)) + (insert n-str)) + ;; Mark prompt as selected if the user moves there or it is the only + ;; option left. Since the user input stays put, we have to manually + ;; remove the face as well. + (when ivy--use-selectable-prompt + (if (= ivy--index -1) + (add-face-text-property + (minibuffer-prompt-end) (line-end-position) 'ivy-prompt-match) + (remove-list-of-text-properties + (minibuffer-prompt-end) (line-end-position) '(face)))) + ;; get out of the prompt area + (constrain-to-field nil (point-max)))))) + +(defun ivy--sort-maybe (collection) + "Sort COLLECTION if needed." + (let ((sort (ivy-state-sort ivy-last))) + (if (and sort + (or (functionp sort) + (functionp (setq sort (ivy--sort-function + (ivy-state-collection ivy-last)))))) + (sort (copy-sequence collection) sort) + collection))) + +(defcustom ivy-magic-slash-non-match-action 'ivy-magic-slash-non-match-cd-selected + "Action to take when a slash is added to the end of a non existing directory. +Possible choices are 'ivy-magic-slash-non-match-cd-selected, +'ivy-magic-slash-non-match-create, or nil" + :type '(choice + (const :tag "Use currently selected directory" + ivy-magic-slash-non-match-cd-selected) + (const :tag "Create and use new directory" + ivy-magic-slash-non-match-create) + (const :tag "Do nothing" + nil))) + +(defun ivy--create-and-cd (dir) + "When completing file names, create directory DIR and move there." + (make-directory dir) + (ivy--cd dir)) + +(defun ivy--magic-file-doubleslash-directory () + "Return an appropriate directory for when two slashes are entered." + (let (remote) + (cond + ;; Windows + ;; ((string-match "\\`[[:alpha:]]:/" ivy--directory) + ;; (match-string 0 ivy--directory)) + ;; Remote root if on remote + ((setq remote (file-remote-p ivy--directory)) + (concat remote "/")) + ;; Local root + (t + "/")))) + +(defun ivy--magic-file-slash () + "Handle slash when completing file names." + (when (or (and (eq this-command #'self-insert-command) + (eolp)) + (eq this-command #'ivy-partial-or-done)) + (let ((canonical (expand-file-name ivy-text ivy--directory)) + (magic (not (string= ivy-text "/")))) + (cond ((member ivy-text ivy--all-candidates) + (ivy--cd canonical)) + ((and (eq system-type 'windows-nt) (string= ivy-text "//"))) + ((string-suffix-p "//" ivy-text) + (ivy--cd + (ivy--magic-file-doubleslash-directory))) + ((string-match-p "\\`/ssh:" ivy-text) + (ivy--cd (file-name-directory ivy-text))) + ((string-match "[[:alpha:]]:/\\'" ivy-text) + (let ((drive-root (match-string 0 ivy-text))) + (when (file-exists-p drive-root) + (ivy--cd drive-root)))) + ((and magic (file-directory-p canonical)) + (ivy--cd canonical)) + ((let ((default-directory ivy--directory)) + (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 + 'ivy-magic-slash-non-match-cd-selected) + (eq this-command #'ivy-partial-or-done)))) + (ivy--cd + (expand-file-name (ivy-state-current ivy-last) ivy--directory))) + ((and (eq ivy-magic-slash-non-match-action + 'ivy-magic-slash-non-match-create) + magic) + (ivy--create-and-cd canonical)))))) + +(defun ivy-magic-read-file-env () + "If reading filename, jump to environment variable location." + (interactive) + (if (and ivy--directory + (equal ivy-text "")) + (let* ((cands (cl-loop for pair in process-environment + for (var val) = (split-string pair "=" t) + if (and val (not (equal "" val))) + if (file-exists-p + (if (file-name-absolute-p val) + val + (setq val + (expand-file-name val ivy--directory)))) + collect (cons var val))) + (enable-recursive-minibuffers t) + (x (ivy-read "Env: " cands)) + (path (cdr (assoc x cands)))) + (insert (if (file-accessible-directory-p path) + (file-name-as-directory path) + path)) + (ivy--cd-maybe)) + (insert last-input-event))) + +(defun ivy-make-magic-action (caller key) + "Return a command that does the equivalent of `ivy-read-action' and KEY. +This happens only when the input is empty. +The intention is to bind the result to keys that are typically +bound to `self-insert-command'." + (let* ((alist (assoc key + (plist-get + ivy--actions-list + caller))) + (doc (format "%s (`%S')" + (nth 2 alist) + (nth 1 alist)))) + `(lambda (&optional arg) + ,doc + (interactive "p") + (if (string= "" ivy-text) + (execute-kbd-macro + (kbd ,(concat "M-o " key))) + (self-insert-command arg))))) + +(defcustom ivy-magic-tilde t + "When non-nil, ~ will move home when selecting files. +Otherwise, ~/ will move home." + :type 'boolean) + +(defcustom ivy-dynamic-exhibit-delay-ms 0 + "Delay in ms before dynamic collections are refreshed" + :type 'integer) + +(defvar ivy--exhibit-timer nil) + +(defun ivy--queue-exhibit () + "Insert Ivy completions display, possibly after a timeout for +dynamic collections. +Should be run via minibuffer `post-command-hook'." + (if (and (> ivy-dynamic-exhibit-delay-ms 0) + (ivy-state-dynamic-collection ivy-last)) + (progn + (when ivy--exhibit-timer (cancel-timer ivy--exhibit-timer)) + (setq ivy--exhibit-timer + (run-with-timer + (/ ivy-dynamic-exhibit-delay-ms 1000.0) + nil + 'ivy--exhibit))) + (ivy--exhibit))) + +(defalias 'ivy--file-local-name + (if (fboundp 'file-local-name) + #'file-local-name + (lambda (file) + (or (file-remote-p file 'localname) file))) + "Compatibility shim for `file-local-name'. +The function was added in Emacs 26.1.") + +(defun ivy--magic-tilde-directory (dir) + "Return an appropriate home for DIR for when ~ or ~/ are entered." + (file-name-as-directory + (expand-file-name + (let* ((home (expand-file-name (concat (file-remote-p dir) "~/"))) + (dir-path (ivy--file-local-name dir)) + (home-path (ivy--file-local-name home))) + (if (string= dir-path home-path) + "~" + home))))) + +(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'." + (when (memq 'ivy--queue-exhibit post-command-hook) + (let ((inhibit-field-text-motion nil)) + (constrain-to-field nil (point-max))) + (ivy-set-text (ivy--input)) + (let ((new-minibuffer (ivy--update-minibuffer))) + (when new-minibuffer + (ivy--insert-minibuffer new-minibuffer))) + t)) + +(defun ivy--dynamic-collection-cands (input) + (let ((coll (funcall (ivy-state-collection ivy-last) input))) + (if (listp coll) + (mapcar (lambda (x) (if (consp x) (car x) x)) coll) + coll))) + +(defun ivy--update-minibuffer () + (prog1 + (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) + coll in-progress) + (unless (or (equal ivy--old-text ivy-text) + (eq this-command 'ivy-resume)) + (while-no-input + (setq coll (ivy--dynamic-collection-cands 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)))) + (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 + (and (not (get-process " *counsel*")) + (not in-progress))) + (ivy--set-index-dynamic-collection) + (ivy--format ivy--all-candidates))) + (cond (ivy--directory + (cond ((or (string= "~/" ivy-text) + (and (string= "~" ivy-text) + ivy-magic-tilde)) + (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) + (when (or (and (string-match "\\` " ivy-text) + (not (string-match "\\` " ivy--old-text))) + (and (string-match "\\` " ivy--old-text) + (not (string-match "\\` " ivy-text)))) + (setq ivy--all-candidates + (if (= (string-to-char ivy-text) ?\s) + (ivy--buffer-list " ") + (ivy--buffer-list "" ivy-use-virtual-buffers))) + (setq ivy--old-re nil)))) + (with-current-buffer (ivy-state-buffer ivy-last) + (ivy--format + (ivy--filter ivy-text ivy--all-candidates)))) + (setq ivy--old-text ivy-text))) + +(defun ivy-display-function-fallback (str) + (let ((buffer-undo-list t)) + (save-excursion + (forward-line 1) + (insert str)))) + +(defun ivy--insert-minibuffer (text) + "Insert TEXT into minibuffer with appropriate cleanup." + (let ((resize-mini-windows nil) + (update-fn (ivy-state-update-fn ivy-last)) + (old-mark (marker-position (mark-marker))) + (win (active-minibuffer-window)) + deactivate-mark) + (when win + (with-selected-window win + (ivy--minibuffer-cleanup) + (when update-fn + (funcall update-fn)) + (ivy--insert-prompt) + ;; Do nothing if while-no-input was aborted. + (when (stringp text) + (if ivy--display-function + (funcall ivy--display-function text) + (ivy-display-function-fallback text))) + (ivy--resize-minibuffer-to-fit) + ;; prevent region growing due to text remove/add + (when (region-active-p) + (set-mark old-mark)))))) + +(defvar ivy-auto-shrink-minibuffer nil + "When non-nil and the height < `ivy-height', auto-shrink the minibuffer.") + +(make-obsolete-variable 'ivy-auto-shrink-minibuffer + 'ivy-auto-shrink-minibuffer-alist + "<2020-04-28 Tue>") + +(defcustom ivy-auto-shrink-minibuffer-alist nil + "An alist to configure auto-shrinking of the minibuffer. + +Each key is a caller symbol. When the value is non-nil, and the +height < `ivy-height', auto-shrink the minibuffer." + :type '(alist + :key-type symbol + :value-type boolean)) + +(defun ivy--do-shrink-window () + (let ((h (save-excursion + (goto-char (minibuffer-prompt-end)) + (let ((inhibit-field-text-motion t)) + (line-number-at-pos))))) + (shrink-window (- + (/ (window-body-height nil t) + (frame-char-height)) + ivy--length h)))) + +(defun ivy--resize-minibuffer-to-fit () + "Resize the minibuffer window size to fit the text in the minibuffer." + (unless (or (frame-root-window-p (minibuffer-window)) + (memq this-command '(ivy-read-action + ivy-dispatching-done + ivy-dispatching-call))) + (with-selected-window (minibuffer-window) + (if (fboundp 'window-text-pixel-size) + (let ((text-height (cdr (window-text-pixel-size))) + (body-height (window-body-height nil t))) + (cond ((> text-height body-height) + ;; Note: the size increment needs to be at least + ;; frame-char-height, otherwise resizing won't do + ;; anything. + (let ((delta (max (- text-height body-height) + (frame-char-height)))) + (window-resize nil delta nil t t))) + ((and (or ivy-auto-shrink-minibuffer + (ivy-alist-setting + ivy-auto-shrink-minibuffer-alist)) + (< ivy--length ivy-height)) + (ivy--do-shrink-window)))) + (let ((text-height (count-screen-lines)) + (body-height (window-body-height))) + (when (> text-height body-height) + (window-resize nil (- text-height body-height) nil t))))))) + +(defun ivy--window-size-changed (&rest _) + "Resize ivy window to fit with current frame's size." + (when ivy-mode + (ivy--resize-minibuffer-to-fit))) + +(defun ivy--add-face (str face) + "Propertize STR with FACE." + (let ((len (length str))) + (condition-case nil + (progn + (colir-blend-face-background 0 len face str) + (let ((foreground (face-foreground face))) + (when foreground + (add-face-text-property + 0 len (list :foreground foreground) nil str)))) + (error + (ignore-errors + (font-lock-append-text-property 0 len 'face face str))))) + str) + +(declare-function flx-make-string-cache "ext:flx") +(declare-function flx-score "ext:flx") + +(defvar ivy--flx-cache nil) + +(with-eval-after-load 'flx + (setq ivy--flx-cache (flx-make-string-cache))) + +(defun ivy-toggle-case-fold () + "Toggle `case-fold-search' for Ivy operations. + +Instead of modifying `case-fold-search' directly, this command +toggles `ivy-case-fold-search', which can take on more values +than the former, between nil and either `auto' or t. See +`ivy-case-fold-search-default' for the meaning of these values. + +In any Ivy completion session, the case folding starts with +`ivy-case-fold-search-default'." + (interactive) + (setq ivy-case-fold-search + (and (not ivy-case-fold-search) + (or ivy-case-fold-search-default 'auto))) + ;; Reset cache so that the candidate list updates. + (setq ivy--old-re nil)) + +(defun ivy--re-filter (re candidates &optional mkpred) + "Return all RE matching CANDIDATES. +RE is a list of cons cells, with a regexp car and a boolean cdr. +When the cdr is t, the car must match. +Otherwise, the car must not match." + (if (equal re "") + candidates + (ignore-errors + (dolist (re (if (stringp re) (list (cons re t)) re)) + (let* ((re-str (car re)) + (pred + (if mkpred + (funcall mkpred re-str) + (lambda (x) (string-match-p re-str x))))) + (setq candidates + (cl-remove nil candidates + (if (cdr re) :if-not :if) + pred)))) + candidates))) + +(defun ivy--filter (name candidates) + "Return all items that match NAME in CANDIDATES. +CANDIDATES are assumed to be static." + (let ((re (funcall ivy--regex-function name))) + (if (and + ivy--old-re + ivy--old-cands + (equal re ivy--old-re)) + ;; quick caching for "C-n", "C-p" etc. + ivy--old-cands + (let* ((re-str (ivy-re-to-str re)) + (matcher (ivy-state-matcher ivy-last)) + (case-fold-search (ivy--case-fold-p name)) + (cands (cond + (matcher + (funcall matcher re candidates)) + ((and ivy--old-re + (stringp re) + (stringp ivy--old-re) + (not (string-match-p "\\\\" ivy--old-re)) + (not (equal ivy--old-re "")) + (memq (cl-search + (if (string-match-p "\\\\)\\'" ivy--old-re) + (substring ivy--old-re 0 -2) + ivy--old-re) + re) + '(0 2)) + ivy--old-cands + (ivy--re-filter re ivy--old-cands))) + (t + (ivy--re-filter re candidates))))) + (if (memq (cdr (assq (ivy-state-caller ivy-last) + ivy-index-functions-alist)) + '(ivy-recompute-index-swiper + ivy-recompute-index-swiper-async + ivy-recompute-index-swiper-async-backward + ivy-recompute-index-swiper-backward)) + (progn + (ivy--recompute-index re-str cands) + (setq ivy--old-cands (ivy--sort name cands))) + (setq ivy--old-cands (ivy--sort name cands)) + (ivy--recompute-index re-str ivy--old-cands)) + (setq ivy--old-re re) + ivy--old-cands)))) + +(defun ivy--set-candidates (x) + "Update `ivy--all-candidates' with X." + (let (res + ;; (ivy--recompute-index-inhibit t) + ) + (dolist (source ivy--extra-candidates) + (if (equal source '(original-source)) + (if (null res) + (setq res x) + (setq res (append x res))) + (setq ivy--old-re nil) + (setq res (append + (ivy--filter ivy-text (cadr source)) + res)))) + (setq ivy--all-candidates + (if (cdr ivy--extra-candidates) + (delete-dups res) + res)))) + +(defun ivy--shorter-matches-first (_name cands) + "Sort CANDS according to their length." + (if (nthcdr ivy-sort-max-size cands) + cands + (cl-sort (copy-sequence cands) #'< :key #'length))) + +(defcustom ivy-sort-matches-functions-alist + '((t . nil) + (ivy-completion-in-region . ivy--shorter-matches-first) + (ivy-switch-buffer . ivy-sort-function-buffer)) + "An alist of functions for sorting matching candidates. + +Unlike `ivy-sort-functions-alist', which is used to sort the +whole collection only once, this alist of functions are used to +sort only matching candidates after each change in input. + +The alist KEY is either a collection function or t to match +previously unmatched collection functions. + +The alist VAL is a sorting function with the signature of +`ivy--prefix-sort'." + :type '(alist + :key-type (choice + (const :tag "Fall-through" t) + (symbol :tag "Collection")) + :value-type + (choice + (const :tag "Don't sort" nil) + (const :tag "Put prefix matches ahead" ivy--prefix-sort) + (function :tag "Custom sort function")))) + +(defun ivy--sort-files-by-date (_name candidates) + "Re-sort CANDIDATES according to file modification date." + (let ((default-directory ivy--directory)) + (sort (copy-sequence candidates) #'file-newer-than-file-p))) + +(defvar ivy--flx-featurep (require 'flx nil 'noerror)) + +(defun ivy--sort (name candidates) + "Re-sort candidates by NAME. +All CANDIDATES are assumed to match NAME." + (let (fun) + (cond ((setq fun (ivy-alist-setting ivy-sort-matches-functions-alist)) + (funcall fun name candidates)) + ((and ivy--flx-featurep + (eq ivy--regex-function 'ivy--regex-fuzzy)) + (ivy--flx-sort name candidates)) + (t + candidates)))) + +(defun ivy--prefix-sort (name candidates) + "Re-sort candidates by NAME. +All CANDIDATES are assumed to match NAME. +Prefix matches to NAME are put ahead of the list." + (if (or (string= name "") + (= (aref name 0) ?^)) + candidates + (let ((re-prefix (concat "\\`" (funcall ivy--regex-function name))) + res-prefix + res-noprefix) + (dolist (s candidates) + (if (string-match-p re-prefix s) + (push s res-prefix) + (push s res-noprefix))) + (nconc + (nreverse res-prefix) + (nreverse res-noprefix))))) + +(defvar ivy--virtual-buffers nil + "Store the virtual buffers alist.") + +(defun ivy-re-to-str (re) + "Transform RE to a string. + +Functions like `ivy--regex-ignore-order' return a cons list. +This function extracts a string from the cons list." + (if (consp re) (caar re) re)) + +(defun ivy-sort-function-buffer (name candidates) + "Re-sort candidates by NAME. +CANDIDATES is a list of buffer names each containing NAME. +Sort open buffers before virtual buffers, and prefix matches +before substring matches." + (if (or (string= name "") + (= (aref name 0) ?^)) + candidates + (let* ((base-re (ivy-re-to-str (funcall ivy--regex-function name))) + (re-star-prefix (concat "\\`\\*" base-re)) + (re-prefix (concat "\\`" base-re)) + res-prefix + res-noprefix + res-virtual-prefix + res-virtual-noprefix) + (dolist (s candidates) + (cond + ((and (assoc s ivy--virtual-buffers) + (or (string-match-p re-star-prefix s) + (string-match-p re-prefix s))) + (push s res-virtual-prefix)) + ((assoc s ivy--virtual-buffers) + (push s res-virtual-noprefix)) + ((or (string-match-p re-star-prefix s) + (string-match-p re-prefix s)) + (push s res-prefix)) + (t + (push s res-noprefix)))) + (nconc + (nreverse res-prefix) + (nreverse res-noprefix) + (nreverse res-virtual-prefix) + (nreverse res-virtual-noprefix))))) + +(defvar ivy-flx-limit 200 + "Used to conditionally turn off flx sorting. + +When the amount of matching candidates exceeds this limit, then +no sorting is done.") + +(defvar ivy--recompute-index-inhibit nil + "When non-nil, `ivy--recompute-index' is a no-op.") + +(defun ivy--recompute-index (re-str cands) + "Recompute index of selected candidate matching RE-STR. +CANDS are the current candidates." + (let ((caller (ivy-state-caller ivy-last)) + (func (or (ivy-alist-setting ivy-index-functions-alist) + #'ivy-recompute-index-zero)) + (case-fold-search (ivy--case-fold-p re-str)) + (preselect (ivy-state-preselect ivy-last)) + (current (ivy-state-current ivy-last)) + (empty (string= re-str ""))) + (unless (or (memq this-command '(ivy-resume ivy-partial-or-done)) + ivy--recompute-index-inhibit) + (let ((index (cond + ((or empty (string= re-str "^")) + (ivy--preselect-index preselect cands)) + ((and (> (length cands) 10000) (eq func #'ivy-recompute-index-zero)) + 0) + ((cl-position (string-remove-prefix "^" re-str) + cands + :test #'ivy--case-fold-string=)) + ((and (ivy--completing-fname-p) + (cl-position (concat re-str "/") + cands + :test #'ivy--case-fold-string=))) + ((and (eq caller 'ivy-switch-buffer) + (not empty)) + (or (cl-position current cands :test #'string=) + 0)) + ((and (not empty) + (not (eq caller 'swiper)) + (not (and ivy--flx-featurep + (eq ivy--regex-function 'ivy--regex-fuzzy) + ;; Limit to configured number of candidates + (null (nthcdr ivy-flx-limit cands)))) + ;; If there was a preselected candidate, don't try to + ;; keep it selected even if the regexp still matches it. + ;; See issue #1563. See also `ivy--preselect-index', + ;; which this logic roughly mirrors. + (not (or + (and (integerp preselect) + (= ivy--index preselect)) + (equal current preselect) + (and (ivy--regex-p preselect) + (stringp current) + (string-match-p preselect current)))) + ivy--old-cands + (cl-position current cands :test #'equal))) + ((funcall func re-str cands)) + (t 0)))) + (ivy-set-index index))))) + +(defun ivy-recompute-index-swiper (_re-str cands) + "Recompute index of selected candidate when using `swiper'. +CANDS are the current candidates." + (condition-case nil + (let ((tail (nthcdr ivy--index ivy--old-cands)) + idx) + (if (and tail ivy--old-cands (not (equal "^" ivy--old-re))) + (progn + (while (and tail (null idx)) + ;; Compare with eq to handle equal duplicates in cands + (setq idx (cl-position (pop tail) cands))) + (or + idx + (1- (length cands)))) + (if ivy--old-cands + ivy--index + ;; already in ivy-state-buffer + (let ((n (line-number-at-pos)) + (res 0) + (i 0)) + (dolist (c cands) + (when (eq n (get-text-property 0 'swiper-line-number c)) + (setq res i)) + (cl-incf i)) + res)))) + (error 0))) + +(defun ivy-recompute-index-swiper-backward (re-str cands) + "Recompute index of selected candidate when using `swiper-backward'. +CANDS are the current candidates." + (let ((idx (ivy-recompute-index-swiper re-str cands))) + (if (or (= idx -1) + (<= (get-text-property 0 'swiper-line-number (nth idx cands)) + (line-number-at-pos))) + idx + (- idx 1)))) + +(defun ivy-recompute-index-swiper-async (_re-str cands) + "Recompute index of selected candidate when using `swiper' asynchronously. +CANDS are the current candidates." + (if (null ivy--old-cands) + (let ((ln (with-ivy-window + (line-number-at-pos)))) + (or + ;; closest to current line going forwards + (cl-position-if (lambda (x) + (>= (string-to-number x) ln)) + cands) + ;; closest to current line going backwards + (1- (length cands)))) + (let ((tail (nthcdr ivy--index ivy--old-cands)) + idx) + (if (and tail ivy--old-cands (not (equal "^" ivy--old-re))) + (progn + (while (and tail (null idx)) + ;; Compare with `equal', since the collection is re-created + ;; each time with `split-string' + (setq idx (cl-position (pop tail) cands :test #'equal))) + (or idx 0)) + ivy--index)))) + +(defun ivy-recompute-index-swiper-async-backward (re-str cands) + "Recompute index of selected candidate when using `swiper-backward' +asynchronously. CANDS are the current candidates." + (if (= (length cands) 0) + 0 + (let ((idx (ivy-recompute-index-swiper-async re-str cands))) + (if + (<= (string-to-number (nth idx cands)) + (with-ivy-window (line-number-at-pos))) + idx + (- idx 1))))) + +(defun ivy-recompute-index-zero (_re-str _cands) + "Recompute index of selected candidate. +This function serves as a fallback when nothing else is available." + 0) + +(defcustom ivy-minibuffer-faces + '(ivy-minibuffer-match-face-1 + ivy-minibuffer-match-face-2 + ivy-minibuffer-match-face-3 + ivy-minibuffer-match-face-4) + "List of `ivy' faces for minibuffer group matches." + :type '(repeat :tag "Faces" + (choice + (const ivy-minibuffer-match-face-1) + (const ivy-minibuffer-match-face-2) + (const ivy-minibuffer-match-face-3) + (const ivy-minibuffer-match-face-4) + (face :tag "Other face")))) + +(defun ivy--minibuffer-face (n) + "Return Nth face from `ivy-minibuffer-faces'. +N wraps around, but skips the first element of the list." + (let ((tail (cdr ivy-minibuffer-faces))) + (nth (mod (+ n 2) (length tail)) tail))) + +(defun ivy--flx-propertize (x) + "X is (cons (flx-score STR ...) STR)." + (let ((str (copy-sequence (cdr x))) + (i 0) + (last-j -2)) + (dolist (j (cdar x)) + (unless (eq j (1+ last-j)) + (cl-incf i)) + (setq last-j j) + (add-face-text-property j (1+ j) (ivy--minibuffer-face i) nil str)) + str)) + +(defun ivy--flx-sort (name cands) + "Sort according to closeness to string NAME the string list CANDS." + (condition-case nil + (let* ((bolp (= (string-to-char name) ?^)) + ;; An optimized regex for fuzzy matching + ;; "abc" → "^[^a]*a[^b]*b[^c]*c" + (fuzzy-regex (concat "\\`" + (and bolp (regexp-quote (substring name 1 2))) + (mapconcat + (lambda (x) + (setq x (char-to-string x)) + (concat "[^" x "]*" (regexp-quote x))) + (if bolp (substring name 2) name) + ""))) + ;; Strip off the leading "^" for flx matching + (flx-name (if bolp (substring name 1) name)) + cands-left + cands-to-sort) + + ;; Filter out non-matching candidates + (dolist (cand cands) + (when (string-match-p fuzzy-regex cand) + (push cand cands-left))) + + ;; pre-sort the candidates by length before partitioning + (setq cands-left (cl-sort cands-left #'< :key #'length)) + + ;; partition the candidates into sorted and unsorted groups + (dotimes (_ (min (length cands-left) ivy-flx-limit)) + (push (pop cands-left) cands-to-sort)) + + (nconc + ;; Compute all of the flx scores in one pass and sort + (mapcar #'car + (sort (mapcar + (lambda (cand) + (cons cand + (car (flx-score cand flx-name ivy--flx-cache)))) + cands-to-sort) + (lambda (c1 c2) + ;; Break ties by length + (if (/= (cdr c1) (cdr c2)) + (> (cdr c1) + (cdr c2)) + (< (length (car c1)) + (length (car c2))))))) + + ;; Add the unsorted candidates + cands-left)) + (error cands))) + +(defun ivy--truncate-string (str width) + "Truncate STR to WIDTH." + (truncate-string-to-width str width nil nil t)) + +(defun ivy--format-function-generic (selected-fn other-fn cands separator) + "Transform candidates into a string for minibuffer. +SELECTED-FN is called for the selected candidate, OTHER-FN for the others. +Both functions take one string argument each. CANDS is a list of candidates +and SEPARATOR is used to join them." + (let ((i -1)) + (mapconcat + (lambda (str) + (let ((curr (eq (cl-incf i) ivy--window-index))) + (if curr + (funcall selected-fn str) + (funcall other-fn str)))) + cands + separator))) + +(defun ivy-format-function-default (cands) + "Transform CANDS into a string for minibuffer." + (ivy--format-function-generic + (lambda (str) + (ivy--add-face str 'ivy-current-match)) + #'identity + cands + "\n")) + +(defun ivy-format-function-arrow (cands) + "Transform CANDS into a string for minibuffer." + (ivy--format-function-generic + (lambda (str) + (concat "> " (ivy--add-face str 'ivy-current-match))) + (lambda (str) + (concat " " str)) + cands + "\n")) + +(defun ivy-format-function-line (cands) + "Transform CANDS into a string for minibuffer. +Note that since Emacs 27, `ivy-current-match' needs to have :extend t attribute. +It has it by default, but the current theme also needs to set it." + (ivy--format-function-generic + (lambda (str) + (ivy--add-face (concat str "\n") 'ivy-current-match)) + (lambda (str) + (concat str "\n")) + cands + "")) + +(defun ivy--highlight-ignore-order (str) + "Highlight STR, using the ignore-order method." + (when (consp ivy--old-re) + (let ((i 1)) + (dolist (re ivy--old-re) + (when (string-match (car re) str) + (add-face-text-property + (match-beginning 0) (match-end 0) + (ivy--minibuffer-face i) + nil str)) + (cl-incf i)))) + str) + +(defun ivy--highlight-fuzzy (str) + "Highlight STR, using the fuzzy method." + (if (and ivy--flx-featurep + (eq (ivy-alist-setting ivy-re-builders-alist) 'ivy--regex-fuzzy)) + (let ((flx-name (string-remove-prefix "^" ivy-text))) + (ivy--flx-propertize + (cons (flx-score str flx-name ivy--flx-cache) str))) + (ivy--highlight-default str))) + +(defcustom ivy-use-group-face-if-no-groups t + "If t, and the expression has no subgroups, highlight whole match as a group. + +It will then use the second face (first of the \"group\" faces) +of `ivy-minibuffer-faces'. Otherwise, always use the first face +in this case." + :type 'boolean) + +(defun ivy--highlight-default (str) + "Highlight STR, using the default method." + (unless ivy--old-re + (setq ivy--old-re ivy-regex)) + (let ((regexps + (if (listp ivy--old-re) + (mapcar #'car (cl-remove-if-not #'cdr ivy--old-re)) + (list ivy--old-re))) + start) + (dolist (re regexps) + (ignore-errors + (while (and (string-match re str start) + (> (- (match-end 0) (match-beginning 0)) 0)) + (setq start (match-end 0)) + (let ((i 0) + (n 0) + prev) + (while (<= i ivy--subexps) + (let ((beg (match-beginning i)) + (end (match-end i))) + (when (and beg end) + (unless (or (and prev (= prev beg)) + (zerop i)) + (cl-incf n)) + (let ((face + (cond ((and ivy-use-group-face-if-no-groups + (zerop ivy--subexps)) + (cadr ivy-minibuffer-faces)) + ((zerop i) + (car ivy-minibuffer-faces)) + (t + (ivy--minibuffer-face n))))) + (add-face-text-property beg end face nil str)) + (unless (zerop i) + (setq prev end)))) + (cl-incf i))))))) + str) + +(defun ivy--format-minibuffer-line (str) + "Format line STR for use in minibuffer." + (let* ((str (ivy-cleanup-string (copy-sequence str))) + (str (if (eq ivy-display-style 'fancy) + (if (memq (ivy-state-caller ivy-last) + ivy-highlight-grep-commands) + (let* ((start (if (string-match "\\`[^:]+:\\(?:[^:]+:\\)?" str) + (match-end 0) 0)) + (file (substring str 0 start)) + (match (substring str start))) + (concat file (funcall ivy--highlight-function match))) + (funcall ivy--highlight-function str)) + str)) + (olen (length str)) + (annot (plist-get completion-extra-properties :annotation-function))) + (add-text-properties + 0 olen + '(mouse-face + ivy-minibuffer-match-highlight + help-echo + (format + (if tooltip-mode + "mouse-1: %s\nmouse-3: %s" + "mouse-1: %s mouse-3: %s") + ivy-mouse-1-tooltip ivy-mouse-3-tooltip)) + str) + (when annot + (setq str (concat str (funcall annot str))) + (add-face-text-property + olen (length str) 'ivy-completions-annotations nil str)) + str)) + +(defun ivy-read-file-transformer (str) + "Transform candidate STR when reading files." + (if (ivy--dirname-p str) + (propertize str 'face 'ivy-subdir) + str)) + +(defun ivy--minibuffer-index-bounds (idx len wnd-len) + (let* ((half-height (/ wnd-len 2)) + (start (max 0 + (min (- idx half-height) + (- len (1- wnd-len))))) + (end (min (+ start (1- wnd-len)) len))) + (list start end (- idx start)))) + +(defun ivy--format (cands) + "Return a string for CANDS suitable for display in the minibuffer. +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))) + (if (null cands) + (setf (ivy-state-current ivy-last) "") + (let ((cur (nth ivy--index cands))) + (setf (ivy-state-current ivy-last) (if (stringp cur) + (copy-sequence cur) + cur))) + (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)) + (with-ivy-window + (with-current-buffer (ivy-state-buffer ivy-last) + (setq wnd-cands (mapcar transformer-fn wnd-cands))))) + (ivy--wnd-cands-to-str wnd-cands)))) + +(defun ivy--wnd-cands-to-str (wnd-cands) + (let ((str (concat "\n" + (funcall (ivy-alist-setting ivy-format-functions-alist) + (condition-case nil + (mapcar + #'ivy--format-minibuffer-line + wnd-cands) + (error wnd-cands)))))) + (put-text-property 0 (length str) 'read-only nil str) + str)) + +(defvar recentf-list) +(defvar bookmark-alist) + +(defcustom ivy-virtual-abbreviate 'name + "The mode of abbreviation for virtual buffer names." + :type '(choice + (const :tag "Only name" name) + (const :tag "Abbreviated path" abbreviate) + (const :tag "Full path" full) + ;; eventually, uniquify + )) +(declare-function bookmark-maybe-load-default-file "bookmark") +(declare-function bookmark-get-filename "bookmark") + +(defun ivy--virtual-buffers () + "Adapted from `ido-add-virtual-buffers-to-list'." + (require 'bookmark) + (unless recentf-mode + (recentf-mode 1)) + (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))) + (name (cond ((eq ivy-virtual-abbreviate 'name) + (file-name-nondirectory file-name)) + ((eq ivy-virtual-abbreviate 'abbreviate) + (abbreviate-file-name file-name)) + (t + (expand-file-name file-name))))) + (when (equal name "") + (setq name + (if (consp head) + (car head) + (file-name-nondirectory (directory-file-name file-name))))) + (unless (or (equal name "") + (get-file-buffer file-name) + (assoc name virtual-buffers)) + (push (cons (copy-sequence name) file-name) virtual-buffers)))) + (when virtual-buffers + (dolist (comp virtual-buffers) + (put-text-property 0 (length (car comp)) + 'face 'ivy-virtual + (car comp))) + (setq ivy--virtual-buffers (nreverse virtual-buffers)) + (mapcar #'car ivy--virtual-buffers)))) + +(defcustom ivy-ignore-buffers '("\\` " "\\`\\*tramp/") + "List of regexps or functions matching buffer names to ignore." + :type '(repeat (choice regexp function))) + +(defvar ivy-switch-buffer-faces-alist '((dired-mode . ivy-subdir) + (org-mode . ivy-org)) + "Store face customizations for `ivy-switch-buffer'. +Each KEY is `major-mode', each VALUE is a face name.") + +(defun ivy--buffer-list (str &optional virtual predicate) + "Return the buffers that match STR. +If VIRTUAL is non-nil, add virtual buffers. +If optional argument PREDICATE is non-nil, use it to test each +possible match. See `all-completions' for further information." + (delete-dups + (nconc + (all-completions str #'internal-complete-buffer predicate) + (and virtual + (ivy--virtual-buffers))))) + +(defvar ivy-views (and nil + `(("ivy + *scratch* {}" + (vert + (file ,(expand-file-name "ivy.el")) + (buffer "*scratch*"))) + ("swiper + *scratch* {}" + (horz + (file ,(expand-file-name "swiper.el")) + (buffer "*scratch*"))))) + "Store window configurations selectable by `ivy-switch-buffer'. + +The default value is given as an example. + +Each element is a list of (NAME VIEW). NAME is a string, it's +recommended to end it with a distinctive snippet e.g. \"{}\" so +that it's easy to distinguish the window configurations. + +VIEW is either a TREE or a window-configuration (see +`ivy--get-view-config'). + +TREE is a nested list with the following valid cars: +- vert: split the window vertically +- horz: split the window horizontally +- file: open the specified file +- buffer: open the specified buffer + +TREE can be nested multiple times to have multiple window splits.") + +(defun ivy-default-view-name () + "Return default name for new view." + (let* ((default-view-name + (concat "{} " + (mapconcat #'identity + (sort + (mapcar (lambda (w) + (let* ((b (window-buffer w)) + (f (buffer-file-name b))) + (if f + (file-name-nondirectory f) + (buffer-name b)))) + (window-list)) + #'string-lessp) + " "))) + (view-name-re (concat "\\`" + (regexp-quote default-view-name) + " \\([0-9]+\\)")) + old-view) + (cond ((setq old-view + (cl-find-if + (lambda (x) + (string-match view-name-re (car x))) + ivy-views)) + (format "%s %d" + default-view-name + (1+ (string-to-number + (match-string 1 (car old-view)))))) + ((assoc default-view-name ivy-views) + (concat default-view-name " 1")) + (t + default-view-name)))) + +(defun ivy--get-view-config () + "Get `current-window-configuration' for `ivy-views'." + (dolist (w (window-list)) + (set-window-parameter w 'ivy-view-data + (with-current-buffer (window-buffer w) + (cond (buffer-file-name + (list 'file buffer-file-name (point))) + ((eq major-mode 'dired-mode) + (list 'file default-directory (point))) + (t + (list 'buffer (buffer-name) (point))))))) + (let ((window-persistent-parameters + (append window-persistent-parameters + (list (cons 'ivy-view-data t))))) + (current-window-configuration))) + +(defun ivy-push-view (&optional arg) + "Push the current window tree on `ivy-views'. + +When ARG is non-nil, replace a selected item on `ivy-views'. + +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") + (let* ((view (ivy--get-view-config)) + (view-name + (if arg + (ivy-read "Update view: " ivy-views) + (ivy-read "Name view: " nil + :initial-input (ivy-default-view-name))))) + (when view-name + (let ((x (assoc view-name ivy-views))) + (if x + (setcdr x (list view)) + (push (list view-name view) ivy-views)))))) + +(defun ivy-pop-view-action (view) + "Delete VIEW from `ivy-views'." + (setq ivy-views (delete view ivy-views)) + (setq ivy--all-candidates + (delete (car view) ivy--all-candidates)) + (setq ivy--old-cands nil)) + +(defun ivy-pop-view () + "Delete a view to delete from `ivy-views'." + (interactive) + (ivy-read "Pop view: " ivy-views + :preselect (caar ivy-views) + :action #'ivy-pop-view-action + :caller 'ivy-pop-view)) + +(defun ivy-source-views () + "Return the name of the views saved in `ivy-views'." + (mapcar #'car ivy-views)) + +(ivy-set-sources + 'ivy-switch-buffer + '((original-source) + (ivy-source-views))) + +(defun ivy-set-view-recur (view) + "Set VIEW recursively." + (cond ((window-configuration-p view) + (set-window-configuration view) + (dolist (w (window-list)) + (with-selected-window w + (ivy-set-view-recur + (window-parameter w 'ivy-view-data))))) + ((eq (car view) 'vert) + (let* ((wnd1 (selected-window)) + (wnd2 (split-window-vertically)) + (views (cdr view)) + (v (pop views)) + (temp-wnd)) + (with-selected-window wnd1 + (ivy-set-view-recur v)) + (while (setq v (pop views)) + (with-selected-window wnd2 + (when views + (setq temp-wnd (split-window-vertically))) + (ivy-set-view-recur v) + (when views + (setq wnd2 temp-wnd)))))) + ((eq (car view) 'horz) + (let* ((wnd1 (selected-window)) + (wnd2 (split-window-horizontally)) + (views (cdr view)) + (v (pop views)) + (temp-wnd)) + (with-selected-window wnd1 + (ivy-set-view-recur v)) + (while (setq v (pop views)) + (with-selected-window wnd2 + (when views + (setq temp-wnd (split-window-horizontally))) + (ivy-set-view-recur v) + (when views + (setq wnd2 temp-wnd)))))) + ((eq (car view) 'file) + (let* ((name (nth 1 view)) + (virtual (assoc name ivy--virtual-buffers)) + buffer) + (cond ((setq buffer (get-buffer name)) + (switch-to-buffer buffer nil 'force-same-window)) + (virtual + (find-file (cdr virtual))) + ((file-exists-p name) + (find-file name)))) + (when (and (> (length view) 2) + (numberp (nth 2 view))) + (goto-char (nth 2 view)))) + ((eq (car view) 'buffer) + (switch-to-buffer (nth 1 view)) + (when (and (> (length view) 2) + (numberp (nth 2 view))) + (goto-char (nth 2 view)))) + ((eq (car view) 'sexp) + (eval (nth 1 view))))) + +(defun ivy--switch-buffer-action (buffer) + "Switch to BUFFER. +BUFFER may be a string or nil." + (if (zerop (length buffer)) + (switch-to-buffer + ivy-text nil 'force-same-window) + (let ((virtual (assoc buffer ivy--virtual-buffers)) + (view (assoc buffer ivy-views))) + (cond ((and virtual + (not (get-buffer buffer))) + (find-file (cdr virtual))) + (view + (delete-other-windows) + (let ( + ;; silence "Directory has changed on disk" + (inhibit-message t)) + (ivy-set-view-recur (cadr view)))) + (t + (switch-to-buffer + buffer nil 'force-same-window)))))) + +(defun ivy--switch-buffer-other-window-action (buffer) + "Switch to BUFFER in other window. +BUFFER may be a string or nil." + (if (zerop (length buffer)) + (switch-to-buffer-other-window ivy-text) + (let ((virtual (assoc buffer ivy--virtual-buffers))) + (if (and virtual + (not (get-buffer buffer))) + (find-file-other-window (cdr virtual)) + (switch-to-buffer-other-window buffer))))) + +(defun ivy--rename-buffer-action (buffer) + "Rename BUFFER." + (let ((new-name (read-string "Rename buffer (to new name): "))) + (with-current-buffer buffer + (rename-buffer new-name)))) + +(defun ivy--find-file-action (buffer) + "Find file from BUFFER's directory." + (let* ((virtual (assoc buffer ivy--virtual-buffers)) + (default-directory (if virtual + (file-name-directory (cdr virtual)) + (buffer-local-value 'default-directory + (or (get-buffer buffer) + (current-buffer)))))) + (call-interactively (if (functionp 'counsel-find-file) + #'counsel-find-file + #'find-file)))) + +(defun ivy--kill-buffer-or-virtual (buffer) + (if (get-buffer buffer) + (kill-buffer buffer) + (setq recentf-list (delete + (cdr (assoc buffer ivy--virtual-buffers)) + recentf-list)))) + +(defun ivy--kill-current-candidate () + (setf (ivy-state-preselect ivy-last) ivy--index) + (setq ivy--old-re nil) + (setq ivy--all-candidates (delete (ivy-state-current ivy-last) ivy--all-candidates)) + (let ((ivy--recompute-index-inhibit t)) + (ivy--exhibit))) + +(defun ivy--kill-current-candidate-buffer () + (setf (ivy-state-preselect ivy-last) ivy--index) + (setq ivy--old-re nil) + (setq ivy--all-candidates (ivy--buffer-list "" ivy-use-virtual-buffers nil)) + (let ((ivy--recompute-index-inhibit t)) + (ivy--exhibit))) + +(defun ivy--kill-buffer-action (buffer) + "Kill BUFFER." + (ivy--kill-buffer-or-virtual buffer) + (unless (buffer-live-p (ivy-state-buffer ivy-last)) + (setf (ivy-state-buffer ivy-last) + (with-ivy-window (current-buffer)))) + (ivy--kill-current-candidate-buffer)) + +(defvar ivy-switch-buffer-map + (let ((map (make-sparse-keymap))) + (ivy-define-key map (kbd "C-k") 'ivy-switch-buffer-kill) + map)) + +(defun ivy-switch-buffer-kill () + "When at end-of-line, kill the current buffer in `ivy-switch-buffer'. +Otherwise, forward to `ivy-kill-line'." + (interactive) + (if (not (eolp)) + (ivy-kill-line) + (ivy--kill-buffer-action + (ivy-state-current ivy-last)))) + +(ivy-set-actions + 'ivy-switch-buffer + '(("f" + ivy--find-file-action + "find file") + ("j" + ivy--switch-buffer-other-window-action + "other window") + ("k" + ivy--kill-buffer-action + "kill") + ("r" + ivy--rename-buffer-action + "rename"))) + +(ivy-set-actions + t + '(("i" ivy--action-insert "insert") + ("w" ivy--action-copy "copy"))) + +(defun ivy--trim-grep-line-number (x) + (if (string-match ":[0-9]+:" x) + (substring x (match-end 0)) + x)) + +(defun ivy--action-insert (x) + (insert + (if (stringp x) + (ivy--trim-grep-line-number x) + x (car x)))) + +(defun ivy--action-copy (x) + (kill-new + (if (stringp x) + (ivy--trim-grep-line-number x) + (car x)))) + +(defun ivy--switch-buffer-matcher (regexp candidates) + "Return REGEXP matching CANDIDATES. +Skip buffers that match `ivy-ignore-buffers'." + (if (string-match-p "^:" ivy-text) + (delete-dups + (cl-remove-if-not + (lambda (s) + (let ((b (get-buffer s))) + (and b + (string-match-p regexp (buffer-local-value 'default-directory b)) + (not (string-match-p "^\\*" s))))) + candidates)) + (let ((res (ivy--re-filter regexp candidates))) + (if (or (null ivy-use-ignore) + (null ivy-ignore-buffers)) + res + (or (cl-remove-if + (lambda (buf) + (cl-find-if + (lambda (f-or-r) + (if (functionp f-or-r) + (funcall f-or-r buf) + (string-match-p f-or-r buf))) + ivy-ignore-buffers)) + res) + (and (eq ivy-use-ignore t) + res)))))) + +(defun ivy-append-face (str face) + "Append to STR the property FACE." + (when face + (setq str (copy-sequence str)) + (add-face-text-property 0 (length str) face t str)) + str) + +(defun ivy--remote-buffer-p (buffer) + "Return non-nil if BUFFER object is visiting a remote file. +If that is the case, value is a string identifying the remote +connection." + (let ((dir (buffer-local-value 'default-directory buffer))) + (ignore-errors (file-remote-p dir)))) + +(defun ivy-switch-buffer-transformer (str) + "Transform candidate STR when switching buffers." + (let ((buf (get-buffer str))) + (cond ((not buf) str) + ((let ((remote (ivy--remote-buffer-p buf))) + (when remote + (format "%s (%s)" (ivy-append-face str 'ivy-remote) remote)))) + ((not (verify-visited-file-modtime buf)) + (ivy-append-face str 'ivy-modified-outside-buffer)) + ((buffer-modified-p buf) + (ivy-append-face str 'ivy-modified-buffer)) + (t + (let* ((mode (buffer-local-value 'major-mode buf)) + (face (cdr (assq mode ivy-switch-buffer-faces-alist)))) + (ivy-append-face str face)))))) + +(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)))))) + cands))))) + +;;;###autoload +(defun ivy-switch-buffer () + "Switch to another buffer." + (interactive) + (ivy-read "Switch to buffer: " #'internal-complete-buffer + :keymap ivy-switch-buffer-map + :preselect (buffer-name (other-buffer (current-buffer))) + :action #'ivy--switch-buffer-action + :matcher #'ivy--switch-buffer-matcher + :caller 'ivy-switch-buffer)) + +(ivy-configure 'ivy-switch-buffer + :parent 'internal-complete-buffer + :occur #'ivy-switch-buffer-occur) + +;;;###autoload +(defun ivy-switch-view () + "Switch to one of the window views stored by `ivy-push-view'." + (interactive) + (let ((ivy-initial-inputs-alist + '((ivy-switch-buffer . "{}")))) + (ivy-switch-buffer))) + +;;;###autoload +(defun ivy-switch-buffer-other-window () + "Switch to another buffer in another window." + (interactive) + (ivy-read "Switch to buffer in other window: " #'internal-complete-buffer + :matcher #'ivy--switch-buffer-matcher + :preselect (buffer-name (other-buffer (current-buffer))) + :action #'ivy--switch-buffer-other-window-action + :keymap ivy-switch-buffer-map + :caller 'ivy-switch-buffer-other-window)) + +(ivy-configure 'ivy-switch-buffer-other-window + :parent 'ivy-switch-buffer) + +(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. +The region to extract is determined by the respective values of +point before and after applying FN to ARGS." + (let (text) + (with-ivy-window + (let ((beg (point)) + (bol (line-beginning-position)) + (eol (line-end-position)) + end) + (unwind-protect + (progn (apply fn args) + (setq end (goto-char (max bol (min (point) eol)))) + (setq text (buffer-substring-no-properties beg end)) + (ivy--pulse-region beg end)) + (unless text + (goto-char beg))))) + (when text + (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. +If optional ARG is non-nil, pull in the next ARG +words (previous if ARG is negative)." + (interactive "p") + (ivy--yank-by #'forward-word arg)) + +(defun ivy-yank-symbol (&optional arg) + "Pull next symbol from buffer into search string. +If optional ARG is non-nil, pull in the next ARG +symbols (previous if ARG is negative)." + (interactive "p") + (ivy--yank-by #'forward-symbol (or arg 1))) + +(defun ivy-yank-char (&optional arg) + "Pull next character from buffer into search string. +If optional ARG is non-nil, pull in the next ARG +characters (previous if ARG is negative)." + (interactive "p") + (ivy--yank-by #'forward-char arg)) + +(defvar ivy--pulse-overlay nil + "Overlay used to highlight yanked word.") + +(defvar ivy--pulse-timer nil + "Timer used to dispose of `ivy--pulse-overlay'.") + +(defcustom ivy-pulse-delay 0.5 + "Number of seconds to display `ivy-yanked-word' highlight. +When nil, disable highlighting." + :type '(choice + (number :tag "Delay in seconds") + (const :tag "Disable" nil))) + +(defun ivy--pulse-region (start end) + "Temporarily highlight text between START and END. +The \"pulse\" duration is determined by `ivy-pulse-delay'." + (when ivy-pulse-delay + (if ivy--pulse-overlay + (let ((ostart (overlay-start ivy--pulse-overlay)) + (oend (overlay-end ivy--pulse-overlay))) + (when (< end start) + (cl-rotatef start end)) + ;; Extend the existing overlay's region to include START..END, + ;; but only if the two regions are contiguous. + (move-overlay ivy--pulse-overlay + (if (= start oend) ostart start) + (if (= end ostart) oend end))) + (setq ivy--pulse-overlay (make-overlay start end)) + (overlay-put ivy--pulse-overlay 'face 'ivy-yanked-word)) + (when ivy--pulse-timer + (cancel-timer ivy--pulse-timer)) + (setq ivy--pulse-timer + (run-at-time ivy-pulse-delay nil #'ivy--pulse-cleanup)))) + +(defun ivy--pulse-cleanup () + "Cancel `ivy--pulse-timer' and delete `ivy--pulse-overlay'." + (when ivy--pulse-timer + (cancel-timer ivy--pulse-timer) + (setq ivy--pulse-timer nil)) + (when ivy--pulse-overlay + (delete-overlay ivy--pulse-overlay) + (setq ivy--pulse-overlay nil))) + +(defun ivy-kill-ring-save () + "Store the current candidates into the kill ring. +If the region is active, forward to `kill-ring-save' instead." + (interactive) + (if (region-active-p) + (call-interactively 'kill-ring-save) + (kill-new + (mapconcat + #'identity + ivy--old-cands + "\n")))) + +(defun ivy-insert-current () + "Make the current candidate into current input. +Don't finish completion." + (interactive) + (delete-minibuffer-contents) + (let ((end (and ivy--directory + (ivy--dirname-p (ivy-state-current ivy-last)) + -1))) + (insert (substring-no-properties + (ivy-state-current ivy-last) 0 end)))) + +(defun ivy-insert-current-full () + "Insert the full Yank the current directory into the minibuffer." + (interactive) + (insert ivy--directory)) + +(defcustom ivy-preferred-re-builders + '((ivy--regex-plus . "ivy") + (ivy--regex-ignore-order . "order") + (ivy--regex-fuzzy . "fuzzy")) + "Alist of preferred re-builders with display names. +This list can be rotated with `ivy-rotate-preferred-builders'." + :type '(alist :key-type function :value-type string)) + +(defun ivy-rotate-preferred-builders () + "Switch to the next re builder in `ivy-preferred-re-builders'." + (interactive) + (when ivy-preferred-re-builders + (setq ivy--old-re nil) + (setq ivy--regex-function + (let ((cell (assq ivy--regex-function ivy-preferred-re-builders))) + (car (or (cadr (memq cell ivy-preferred-re-builders)) + (car ivy-preferred-re-builders))))))) + +(defun ivy-toggle-fuzzy () + "Toggle the re builder between `ivy--regex-fuzzy' and `ivy--regex-plus'." + (interactive) + (setq ivy--old-re nil) + (if (eq ivy--regex-function 'ivy--regex-fuzzy) + (setq ivy--regex-function 'ivy--regex-plus) + (setq ivy--regex-function 'ivy--regex-fuzzy))) + +(defun ivy--label-and-delete-dups (entries) + "Label ENTRIES with history indices." + (let ((ht (make-hash-table :test 'equal)) + (idx 0) + entry + accum) + (while (setq entry (pop entries)) + (unless (gethash entry ht) + (puthash entry t ht) + (push `(,entry . ,idx) accum)) + (cl-incf idx)) + (nreverse accum))) + +(defvar ivy--reverse-i-search-symbol nil + "Store the history symbol.") + +(defun ivy-reverse-i-search-kill () + "Remove the current item from history" + (interactive) + (if (not (eolp)) + (ivy-kill-line) + (let ((current (ivy-state-current ivy-last))) + (if (symbolp ivy--reverse-i-search-symbol) + (set + ivy--reverse-i-search-symbol + (delete current (symbol-value ivy--reverse-i-search-symbol))) + (ring-remove + ivy--reverse-i-search-symbol + (ring-member ivy--reverse-i-search-symbol (ivy-state-current ivy-last))))) + (ivy--kill-current-candidate))) + +(defvar ivy-reverse-i-search-map + (let ((map (make-sparse-keymap))) + (ivy-define-key map (kbd "C-k") 'ivy-reverse-i-search-kill) + map)) + +(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 HISTORY." + (setq ivy--reverse-i-search-symbol history) + (cond ((symbolp history) + (ivy--label-and-delete-dups + (copy-sequence (symbol-value history)))) + ((ring-p history) + (ivy--label-and-delete-dups + (when (> (ring-size history) 0) + (ring-elements history)))) + ((sequencep history) + (ivy--label-and-delete-dups + (copy-sequence history))) + (t + (error "Expected a symbol, ring, or sequence: %S" history)))) + +(defun ivy-reverse-i-search () + "Enter a recursive `ivy-read' session using the current history. +The selected history element will be inserted into the minibuffer. +\\ +You can also delete an element from history with \\[ivy-reverse-i-search-kill]." + (interactive) + (cond + ((= (minibuffer-depth) 0) + (user-error + "This command is intended to be called from within `ivy-read'")) + ;; don't recur + ((and (> (minibuffer-depth) 1) + (eq (ivy-state-caller ivy-last) 'ivy-reverse-i-search))) + (t + (let ((enable-recursive-minibuffers t) + (old-last ivy-last)) + (ivy-read "Reverse-i-search: " + (ivy-history-contents (ivy-state-history ivy-last)) + :keymap ivy-reverse-i-search-map + :action (lambda (x) + (ivy--reset-state + (setq ivy-last old-last)) + (delete-minibuffer-contents) + (insert (substring-no-properties (car x))) + (ivy--cd-maybe)) + :caller 'ivy-reverse-i-search))))) + +(defun ivy-restrict-to-matches () + "Restrict candidates to current input and erase input." + (interactive) + (delete-minibuffer-contents) + (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 + "Buffer-local value of `ivy-last'. +Can't re-use `ivy-last' because using e.g. `swiper' in the same +buffer would modify `ivy-last'.") + +(defvar ivy-occur-mode-map + (let ((map (make-sparse-keymap))) + (ivy-define-key map [mouse-1] 'ivy-occur-click) + (ivy-define-key map (kbd "RET") 'ivy-occur-press-and-switch) + (ivy-define-key map (kbd "j") 'ivy-occur-next-line) + (ivy-define-key map (kbd "k") 'ivy-occur-previous-line) + (define-key map (kbd "h") 'backward-char) + (define-key map (kbd "l") 'forward-char) + (ivy-define-key map (kbd "f") 'ivy-occur-press) + (ivy-define-key map (kbd "g") 'ivy-occur-revert-buffer) + (ivy-define-key map (kbd "a") 'ivy-occur-read-action) + (ivy-define-key map (kbd "o") 'ivy-occur-dispatch) + (ivy-define-key map (kbd "c") 'ivy-occur-toggle-calling) + (define-key map (kbd "q") 'quit-window) + (define-key map (kbd "R") 'read-only-mode) + (ivy-define-key map (kbd "C-d") 'ivy-occur-delete-candidate) + map) + "Keymap for Ivy Occur mode.") + +(defun ivy-occur-toggle-calling () + "Toggle `ivy-calling'." + (interactive) + (if (setq ivy-calling (not ivy-calling)) + (progn + (setq mode-name "Ivy-Occur [calling]") + (ivy-occur-press)) + (setq mode-name "Ivy-Occur")) + (force-mode-line-update)) + +(defun ivy--find-occur-buffer () + (let ((cb (current-buffer))) + (cl-find-if + (lambda (b) + (with-current-buffer b + (and (eq major-mode 'ivy-occur-grep-mode) + (equal cb (ivy-state-buffer ivy-occur-last))))) + (buffer-list)))) + +(defun ivy--select-occur-buffer () + (let* ((ob (ivy--find-occur-buffer)) + (ow (cl-find-if (lambda (w) (equal ob (window-buffer w))) + (window-list)))) + (if ow + (select-window ow) + (pop-to-buffer ob)))) + +(defun ivy-occur-next-line (&optional arg) + "Move the cursor down ARG lines. +When `ivy-calling' isn't nil, call `ivy-occur-press'." + (interactive "p") + (let ((offset (cond ((derived-mode-p 'ivy-occur-grep-mode) 5) + ((derived-mode-p 'ivy-occur-mode) 2)))) + (if offset + (progn + (if (< (line-number-at-pos) offset) + (progn + (goto-char (point-min)) + (forward-line (1- offset))) + (forward-line arg) + (when (eolp) + (forward-line -1))) + (when ivy-calling + (ivy-occur-press))) + (ivy--select-occur-buffer) + (ivy-occur-next-line arg) + (ivy-occur-press-and-switch)))) + +(defun ivy-occur-previous-line (&optional arg) + "Move the cursor up ARG lines. +When `ivy-calling' isn't nil, call `ivy-occur-press'." + (interactive "p") + (let ((offset (cond ((derived-mode-p 'ivy-occur-grep-mode) 5) + ((derived-mode-p 'ivy-occur-mode) 2)))) + (if offset + (progn + (forward-line (- arg)) + (when (< (line-number-at-pos) offset) + (goto-char (point-min)) + (forward-line (1- offset))) + (when ivy-calling + (ivy-occur-press))) + (ivy--select-occur-buffer) + (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)))) + ;; The window's point overrides the buffer's point every time it's redisplayed + (dolist (window (get-buffer-window-list nil nil t)) + (set-window-point window (point)))) + +(define-derived-mode ivy-occur-mode fundamental-mode "Ivy-Occur" + "Major mode for output from \\[ivy-occur]. + +\\{ivy-occur-mode-map}" + (setq-local view-read-only nil)) + +(defvar ivy-occur-grep-mode-map + (let ((map (copy-keymap ivy-occur-mode-map))) + (ivy-define-key map (kbd "C-x C-q") 'ivy-wgrep-change-to-wgrep-mode) + (ivy-define-key map "w" 'ivy-wgrep-change-to-wgrep-mode) + map) + "Keymap for Ivy Occur Grep mode.") + +(defun ivy-occur-delete-candidate () + (interactive) + (let ((inhibit-read-only t)) + (delete-region (line-beginning-position) + (1+ (line-end-position))))) + +(define-derived-mode ivy-occur-grep-mode grep-mode "Ivy-Occur" + "Major mode for output from \\[ivy-occur]. + +\\{ivy-occur-grep-mode-map}" + (setq-local view-read-only nil) + (when (fboundp 'wgrep-setup) + (wgrep-setup))) + +(defun ivy--starts-with-dotslash (str) + (string-match-p "\\`\\.[/\\]" str)) + +(defun ivy--occur-insert-lines (cands) + "Insert CANDS into `ivy-occur' buffer." + (font-lock-mode -1) + (dolist (cand cands) + (setq cand + (if (string-match "\\`\\(.*:[0-9]+:\\)\\(.*\\)\\'" cand) + (let ((file-and-line (match-string 1 cand)) + (grep-line (match-string 2 cand))) + (concat + (propertize file-and-line 'face 'ivy-grep-info) + (ivy--highlight-fuzzy grep-line))) + (ivy--highlight-fuzzy (copy-sequence cand)))) + (add-text-properties + 0 (length cand) + '(mouse-face + highlight + help-echo "mouse-1: call ivy-action") + cand) + (insert (if (ivy--starts-with-dotslash 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. + +The new buffer remembers current action(s). + +While in the *ivy-occur* buffer, selecting a candidate with RET or +a mouse click will call the appropriate action for that candidate. + +There is no limit on the number of *ivy-occur* buffers." + (interactive) + (if (not (window-minibuffer-p)) + (user-error "No completion session is active") + (let* ((caller (ivy-state-caller ivy-last)) + (occur-fn (or (plist-get ivy--occurs-list caller) + #'ivy--occur-default)) + (buffer + (generate-new-buffer + (format "*ivy-occur%s \"%s\"*" + (if caller + (concat " " (prin1-to-string caller)) + "") + ivy-text)))) + (with-current-buffer buffer + (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) + (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 original buffer +is updated, since the line numbers no longer match. + +Calling this function is as if you called `ivy-occur' on the +updated original buffer." + (interactive) + (let ((caller (ivy-state-caller ivy-occur-last)) + (ivy-last ivy-occur-last)) + (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") + +(defun ivy-wgrep-change-to-wgrep-mode () + "Forward to `wgrep-change-to-wgrep-mode'." + (interactive) + (if (require 'wgrep nil 'noerror) + (wgrep-change-to-wgrep-mode) + (error "Package wgrep isn't installed"))) + +(defun ivy-occur-read-action () + "Select one of the available actions as the current one." + (interactive) + (let ((ivy-last ivy-occur-last)) + (ivy-read-action))) + +(defun ivy-occur-dispatch () + "Call one of the available actions on the current item." + (interactive) + (let* ((state-action (ivy-state-action ivy-occur-last)) + (actions (if (symbolp state-action) + state-action + (copy-sequence state-action)))) + (unwind-protect + (progn + (ivy-occur-read-action) + (ivy-occur-press)) + (setf (ivy-state-action ivy-occur-last) actions)))) + +(defun ivy-occur-click (event) + "Execute action for the current candidate. +EVENT gives the mouse position." + (interactive "e") + (let ((window (posn-window (event-end event))) + (pos (posn-point (event-end event)))) + (with-current-buffer (window-buffer window) + (goto-char pos) + (ivy-occur-press)))) + +(declare-function swiper--cleanup "swiper") +(declare-function swiper--add-overlays "swiper") +(defvar ivy-occur-timer nil) + +(defun ivy--occur-press-update-window () + (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))) + (when (buffer-live-p buffer) + (cond ((or (not (window-live-p window)) + (equal window (selected-window))) + (save-selected-window + (setf (ivy-state-window ivy-occur-last) + (display-buffer buffer)))) + ((not (equal (window-buffer window) buffer)) + (with-selected-window window + (switch-to-buffer buffer))))))) + + ((memq (ivy-state-caller ivy-occur-last) + '(counsel-describe-function + counsel-describe-variable + counsel-describe-symbol)) + (setf (ivy-state-window ivy-occur-last) + (selected-window)) + (selected-window)))) + +(defun ivy--occur-press-buffer () + (let ((buffer (ivy-state-buffer ivy-last))) + (if (buffer-live-p buffer) + buffer + (current-buffer)))) + +(defun ivy-occur-press () + "Execute action for the current candidate." + (interactive) + (ivy--occur-press-update-window) + (when (save-excursion + (beginning-of-line) + (looking-at "\\(?:.[/\\]\\| \\)\\(.*\\)$")) + (let* ((ivy-last ivy-occur-last) + (ivy-text (ivy-state-text ivy-last)) + (str (buffer-substring + (match-beginning 1) + (match-end 1))) + (offset (or (get-text-property 0 'offset str) 0)) + (coll (ivy-state-collection ivy-last)) + (action (ivy--get-action ivy-last)) + (ivy-exit 'done)) + (with-ivy-window + (with-current-buffer (ivy--occur-press-buffer) + (save-restriction + (widen) + (funcall action + (if (and (consp coll) + (consp (car coll))) + (assoc str coll) + (substring str offset))))) + (if (memq (ivy-state-caller ivy-last) + (append '(swiper swiper-isearch) ivy-highlight-grep-commands)) + (with-current-buffer (window-buffer (selected-window)) + (swiper--cleanup) + (swiper--add-overlays + (ivy--regex ivy-text) + (line-beginning-position) + (line-end-position) + (selected-window)) + (when (timerp ivy-occur-timer) + (cancel-timer ivy-occur-timer)) + (setq ivy-occur-timer + (run-at-time 1.0 nil 'swiper--cleanup)))))))) + +(defun ivy-occur-press-and-switch () + "Execute action for the current candidate and switch window." + (interactive) + (ivy-occur-press) + (select-window (ivy--get-window ivy-occur-last))) + +(defun ivy--marked-p () + (member (ivy-state-current ivy-last) ivy-marked-candidates)) + +(defun ivy--unmark (cand) + (setcar (member cand ivy--all-candidates) + (setcar (member cand ivy--old-cands) + (substring cand (length ivy-mark-prefix)))) + (setq ivy-marked-candidates + (delete cand ivy-marked-candidates))) + +(defun ivy--mark (cand) + (let ((marked-cand (concat ivy-mark-prefix cand))) + (setcar (member cand ivy--all-candidates) + (setcar (member cand ivy--old-cands) marked-cand)) + (setq ivy-marked-candidates + (append ivy-marked-candidates (list marked-cand))))) + +(defun ivy-mark () + "Mark the selected candidate and move to the next one. + +In `ivy-call', :action will be called in turn for all marked +candidates. + +However, if :multi-action was supplied to `ivy-read', then it +will be called with `ivy-marked-candidates'. This way, it can +make decisions based on the whole marked list." + (interactive) + (unless (ivy--marked-p) + (ivy--mark (ivy-state-current ivy-last))) + (ivy-next-line)) + +(defun ivy-unmark () + "Unmark the selected candidate and move to the next one." + (interactive) + (when (ivy--marked-p) + (ivy--unmark (ivy-state-current ivy-last))) + (ivy-next-line)) + +(defun ivy-unmark-backward () + "Move to the previous candidate and unmark it." + (interactive) + (ivy-previous-line) + (ivy--exhibit) + (when (ivy--marked-p) + (ivy--unmark (ivy-state-current ivy-last)))) + +(defun ivy-toggle-marks () + "Toggle mark for all narrowed candidates." + (interactive) + (dolist (cand ivy--old-cands) + (if (member cand ivy-marked-candidates) + (ivy--unmark cand) + (ivy--mark cand)))) + +(defconst ivy-help-file (let ((default-directory + (if load-file-name + (file-name-directory load-file-name) + default-directory))) + (if (file-exists-p "ivy-help.org") + (expand-file-name "ivy-help.org") + (if (file-exists-p "doc/ivy-help.org") + (expand-file-name "doc/ivy-help.org")))) + "The file for `ivy-help'.") + +(defvar org-hide-emphasis-markers) + +(defun ivy-help () + "Help for `ivy'." + (interactive) + (let ((buf (get-buffer "*Ivy Help*")) + (inhibit-read-only t)) + (unless buf + (setq buf (get-buffer-create "*Ivy Help*")) + (cl-letf (((symbol-function #'help-buffer) (lambda () buf))) + (describe-mode)) + (with-current-buffer buf + (goto-char (point-min)) + (insert "* describe-mode\n") + (goto-char (point-min)) + (insert-file-contents ivy-help-file) + (org-mode) + (setq-local org-hide-emphasis-markers t) + (view-mode) + (goto-char (point-min)) + (let ((inhibit-message t)) + (org-cycle '(64))))) + (if (eq this-command 'ivy-help) + (switch-to-buffer buf) + (with-ivy-window + (pop-to-buffer buf))) + (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 + :alt-done-fn #'ivy--directory-done) + +(ivy-configure 'internal-complete-buffer + :display-transformer-fn #'ivy-switch-buffer-transformer) + +(ivy-configure 'Info-read-node-name-1 + :alt-done-fn #'ivy--info-alt-done) + +(provide 'ivy) + +;;; ivy.el ends here diff --git a/elpa/ivy-20210216.1611/ivy.info b/elpa/ivy-20210216.1611/ivy.info new file mode 100644 index 0000000..c1f52aa --- /dev/null +++ b/elpa/ivy-20210216.1611/ivy.info @@ -0,0 +1,1972 @@ +This is ivy.info, produced by makeinfo version 6.5 from ivy.texi. + +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. + + Copyright (C) 2015-2019 Free Software Foundation, Inc. + + 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". + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Ivy: (ivy). Using Ivy for completion. +END-INFO-DIR-ENTRY + + +File: ivy.info, Node: Top, Next: Introduction, Up: (dir) + +Ivy User Manual +*************** + +* Menu: + +* Introduction:: +* Installation:: +* Getting started:: +* Key bindings:: +* Completion Styles:: +* Customization:: +* Commands:: +* API:: +* Variable Index:: +* Keystroke Index:: + +— 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 ivy-occur:: + +Commands + +* File Name Completion:: +* Buffer Name Completion:: +* Counsel commands:: + +File Name Completion + +* Using TRAMP:: + +API + +* Required arguments for ivy-read:: +* Optional arguments for ivy-read:: +* Example - counsel-describe-function:: +* Example - counsel-locate:: +* Example - ivy-read-with-extra-properties:: + + + +File: ivy.info, Node: Introduction, Next: Installation, Prev: Top, Up: Top + +1 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. + +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. + + +File: ivy.info, Node: Installation, Next: Getting started, Prev: Introduction, Up: Top + +2 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:: + + +File: ivy.info, Node: Installing from Emacs Package Manager, Next: Installing from the Git repository, Up: Installation + +2.1 Installing from Emacs Package Manager +========================================= + +‘M-x’ ‘package-install’ ‘RET’ ‘counsel’ ‘RET’ + + Ivy is installed as part of the ‘counsel’ package, which is available +from two different package archives, GNU ELPA and MELPA. For the latest +stable version, use the GNU ELPA archives. For current hourly builds, +use the MELPA archives. + + Ivy is split into three packages: ‘ivy’, ‘swiper’ and ‘counsel’; by +installing ‘counsel’, the other two are brought in as dependencies. If +you are not interested in the extra functionality provided by ‘swiper’ +and ‘counsel’, you can install only ‘ivy’. + + See the code below for adding MELPA to the list of package archives: + + (require 'package) + (add-to-list 'package-archives + '("melpa" . "https://melpa.org/packages/")) + + After this do ‘M-x’ ‘package-refresh-contents’ ‘RET’, followed by +‘M-x’ ‘package-install’ ‘RET’ ‘counsel’ ‘RET’. + + For package manager details, see *note (emacs)Packages::. + + +File: ivy.info, Node: Installing from the Git repository, Prev: Installing from Emacs Package Manager, Up: Installation + +2.2 Installing from the Git repository +====================================== + +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: + + cd ~/git && git clone https://github.com/abo-abo/swiper + cd swiper && make compile + + Second, add these lines to the Emacs init file: + + (add-to-list 'load-path "~/git/swiper/") + (require 'ivy) + + Then, update the code with: + + git pull + make + + +File: ivy.info, Node: Getting started, Next: Key bindings, Prev: Installation, Up: Top + +3 Getting started +***************** + +First enable Ivy completion everywhere: + + (ivy-mode 1) + + Note: ‘ivy-mode’ can be toggled on and off with ‘M-x’ ‘ivy-mode’. + +* Menu: + +* Basic customization:: + + +File: ivy.info, Node: Basic customization, Up: Getting started + +3.1 Basic customization +======================= + +Here are some basic settings particularly useful for new Ivy users: + + (setq ivy-use-virtual-buffers t) + (setq ivy-count-format "(%d/%d) ") + + 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. + + +File: ivy.info, Node: Key bindings, Next: Completion Styles, Prev: Getting started, Up: Top + +4 Key bindings +************** + +* Menu: + +* Global key bindings:: +* Minibuffer key bindings:: + + +File: ivy.info, Node: Global key bindings, Next: Minibuffer key bindings, Up: Key bindings + +4.1 Global key bindings +======================= + +Here is a list of commands that are useful to be bound globally, along +with some sample bindings: + +Ivy-based interface to standard commands +........................................ + + (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) + +Ivy-based interface to shell and system tools +............................................. + + (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) + +Ivy-resume and other commands +............................. + + ‘ivy-resume’ resumes the last Ivy-based completion. + + (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) + + You can also enable ‘counsel-mode’ to make some global key binding +remapping for you. + + +File: ivy.info, Node: Minibuffer key bindings, Prev: Global key bindings, Up: Key bindings + +4.2 Minibuffer key bindings +=========================== + +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’. + +* 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:: + + +File: ivy.info, Node: Key bindings for navigation, Next: Key bindings for single selection action then exit minibuffer, Up: Minibuffer key bindings + +4.2.1 Key bindings for navigation +--------------------------------- + + • ‘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. + + +File: ivy.info, Node: Key bindings for single selection action then exit minibuffer, Next: Key bindings for multiple selections and actions keep minibuffer open, Prev: Key bindings for navigation, Up: Minibuffer key bindings + +4.2.2 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. + +‘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: + + (should + (equal (ivy-with + '(progn + (ivy-read "Test: " '("can do" "can't, sorry" "other")) + ivy-text) + "c ") + "can")) + +‘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’. + + +File: ivy.info, Node: Key bindings for multiple selections and actions keep minibuffer open, Next: Key bindings that alter the minibuffer input, Prev: Key bindings for single selection action then exit minibuffer, Up: Minibuffer key bindings + +4.2.3 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. + + Note that these operations are supported only by completion sessions +that use the ‘ivy-read’ API, rather than the built-in ‘completing-read’. + +‘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’). Use it with + ‘universal-argument’ to resume any previous session. + + +File: ivy.info, Node: Key bindings that alter the minibuffer input, Next: Other key bindings, Prev: Key bindings for multiple selections and actions keep minibuffer open, Up: Minibuffer key bindings + +4.2.4 Key bindings that alter the minibuffer input +-------------------------------------------------- + +‘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. + + +File: ivy.info, Node: Other key bindings, Next: Hydra in the minibuffer, Prev: Key bindings that alter the minibuffer input, Up: Minibuffer key bindings + +4.2.5 Other key bindings +------------------------ + +‘M-w’ (‘ivy-kill-ring-save’) +............................ + + Copies selected candidates to the kill ring. + + Copies the region if the region is active. + + +File: ivy.info, Node: Hydra in the minibuffer, Next: Saving the current completion session to a buffer, Prev: Other key bindings, Up: Minibuffer key bindings + +4.2.6 Hydra in the minibuffer +----------------------------- + +‘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. + + +File: ivy.info, Node: Saving the current completion session to a buffer, Prev: Hydra in the minibuffer, Up: Minibuffer key bindings + +4.2.7 Saving the current completion session to a buffer +------------------------------------------------------- + +‘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$*’. + + +File: ivy.info, Node: Completion Styles, Next: Customization, Prev: Key bindings, Up: Top + +5 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 ‘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: + + (setq ivy-re-builders-alist + '((t . ivy--regex-plus))) + + This example shows a custom regex builder assigned to file name +completion: + + (setq ivy-re-builders-alist + '((read-file-name-internal . ivy--regex-fuzzy) + (t . ivy--regex-plus))) + + 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’. + +* Menu: + +* ivy--regex-plus:: +* ivy--regex-ignore-order:: +* ivy--regex-fuzzy:: + + +File: ivy.info, Node: ivy--regex-plus, Next: ivy--regex-ignore-order, Up: Completion Styles + +5.1 ivy–regex-plus +================== + +‘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 + + "\\(for\\).*\\(example\\)" + + 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. + + +File: ivy.info, Node: ivy--regex-ignore-order, Next: ivy--regex-fuzzy, Prev: ivy--regex-plus, Up: Completion Styles + +5.2 ivy–regex-ignore-order +========================== + +‘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"’. + + +File: ivy.info, Node: ivy--regex-fuzzy, Prev: ivy--regex-ignore-order, Up: Completion Styles + +5.3 ivy–regex-fuzzy +=================== + +‘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. + + +File: ivy.info, Node: Customization, Next: Commands, Prev: Completion Styles, Up: Top + +6 Customization +*************** + +* Menu: + +* Faces:: +* Defcustoms:: +* Actions:: +* Packages:: + + +File: ivy.info, Node: Faces, Next: Defcustoms, Up: Customization + +6.1 Faces +========= + +‘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: + + (setq confirm-nonexistent-file-or-buffer t) + + 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: + + (setq ivy-use-virtual-buffers t) + +‘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’. + + +File: ivy.info, Node: Defcustoms, Next: Actions, Prev: Faces, Up: Customization + +6.2 Defcustoms +============== + + -- 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: + + (setq ivy-count-format "") + + To also display the current candidate: + + (setq ivy-count-format "(%d/%d) ") + + 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. + + Another common option is ‘ignore’, which does nothing. + + +File: ivy.info, Node: Actions, Next: Packages, Prev: Defcustoms, Up: Customization + +6.3 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:: + + +File: ivy.info, Node: What are actions?, Next: How can different actions be called?, Up: Actions + +6.3.1 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. + +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. + + (defun ivy-insert-action (x) + (with-ivy-window + (insert x))) + + +File: ivy.info, Node: How can different actions be called?, Next: How to modify the actions list?, Prev: What are actions?, Up: Actions + +6.3.2 How can different actions be called? +------------------------------------------ + + • ‘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. + + +File: ivy.info, Node: How to modify the actions list?, Next: Example - add two actions to each command, Prev: How can different actions be called?, Up: Actions + +6.3.3 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 ‘o’ is +designated for the default command. This way, ‘M-o o’ should be always +equivalent to ‘C-m’. + + +File: ivy.info, Node: Example - add two actions to each command, Next: Example - define a new command with several actions, Prev: How to modify the actions list?, Up: Actions + +6.3.4 Example - add two actions to each command +----------------------------------------------- + +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. + + (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"))) + + Then in any completion session, ‘M-o y’ invokes ‘ivy-yank-action’, +and ‘M-o i’ invokes ‘ivy-copy-to-buffer-action’. + +* Menu: + +* How to undo adding the two actions:: +* How to add actions to a specific command:: + + +File: ivy.info, Node: How to undo adding the two actions, Next: How to add actions to a specific command, Up: Example - add two actions to each command + +6.3.4.1 How to undo adding the two actions +.......................................... + +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: + + (ivy-set-actions t nil) + + +File: ivy.info, Node: How to add actions to a specific command, Prev: How to undo adding the two actions, Up: Example - add two actions to each command + +6.3.4.2 How to add actions to a specific command +................................................ + +Use the command name as the key: + + (ivy-set-actions + 'swiper + '(("i" ivy-copy-to-buffer-action "insert") + ("y" ivy-yank-action "yank"))) + + +File: ivy.info, Node: Example - define a new command with several actions, Prev: Example - add two actions to each command, Up: Actions + +6.3.5 Example - define a new command with several actions +--------------------------------------------------------- + + (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")))) + + 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 ivy-occur:: + + +File: ivy.info, Node: Test the above function with ivy-occur, Up: Example - define a new command with several actions + +6.3.5.1 Test the above function with ‘ivy-occur’ +................................................ + +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... + + +File: ivy.info, Node: Packages, Prev: Actions, Up: Customization + +6.4 Packages +============ + +‘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: + + (setq projectile-completion-system 'ivy) + +‘helm-make’ +........... + + Helm-make requires this setting for ivy completion. + + (setq helm-make-completion-method 'ivy) + +automatically integrated packages +................................. + + Ivy re-uses the following packages if they are installed: ‘avy’, + ‘amx’ or ‘smex’, ‘flx’, and ‘wgrep’. + + +File: ivy.info, Node: Commands, Next: API, Prev: Customization, Up: Top + +7 Commands +********** + +* Menu: + +* File Name Completion:: +* Buffer Name Completion:: +* Counsel commands:: + + +File: ivy.info, Node: File Name Completion, Next: Buffer Name Completion, Up: Commands + +7.1 File Name Completion +======================== + +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. + +‘C-M-y’ (‘ivy-insert-current-full’) +................................... + + Insert the current full path, in case you want to edit a part of + it. + +‘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. + +* Menu: + +* Using TRAMP:: + + +File: ivy.info, Node: Using TRAMP, Up: File Name Completion + +7.1.1 Using TRAMP +----------------- + +‘~’ (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:/’. + + +File: ivy.info, Node: Buffer Name Completion, Next: Counsel commands, Prev: File Name Completion, Up: Commands + +7.2 Buffer Name Completion +========================== + + -- 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: + + (setq ivy-use-virtual-buffers t) + 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. + + +File: ivy.info, Node: Counsel commands, Prev: Buffer Name Completion, Up: Commands + +7.3 Counsel commands +==================== + +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. + + +File: ivy.info, Node: API, Next: Variable Index, Prev: Commands, Up: Top + +8 API +***** + +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’. + +* Menu: + +* Required arguments for ivy-read:: +* Optional arguments for ivy-read:: +* Example - counsel-describe-function:: +* Example - counsel-locate:: +* Example - ivy-read-with-extra-properties:: + + +File: ivy.info, Node: Required arguments for ivy-read, Next: Optional arguments for ivy-read, Up: API + +8.1 Required arguments for ‘ivy-read’ +===================================== + +‘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’. + + +File: ivy.info, Node: Optional arguments for ivy-read, Next: Example - counsel-describe-function, Prev: Required arguments for ivy-read, Up: API + +8.2 Optional arguments for ‘ivy-read’ +===================================== + +‘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. + + +File: ivy.info, Node: Example - counsel-describe-function, Next: Example - counsel-locate, Prev: Optional arguments for ivy-read, Up: API + +8.3 Example - ‘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 ‘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. + + (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)) + + 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’. + + +File: ivy.info, Node: Example - counsel-locate, Next: Example - ivy-read-with-extra-properties, Prev: Example - counsel-describe-function, Up: API + +8.4 Example - ‘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 ‘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. + + (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)) + + 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. + + +File: ivy.info, Node: Example - ivy-read-with-extra-properties, Prev: Example - counsel-locate, Up: API + +8.5 Example - ‘ivy-read-with-extra-properties’ +============================================== + +This is another example to show how to associate additional values to +each displayed strings. + + (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) + )))) + + 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. + + +File: ivy.info, Node: Variable Index, Next: Keystroke Index, Prev: API, Up: Top + +9 Variable Index +**************** + +[index] +* Menu: + +* ivy-alt-done: Key bindings for single selection action then exit minibuffer. + (line 30) +* ivy-alt-done <1>: File Name Completion. (line 12) +* ivy-avy: Key bindings for single selection action then exit minibuffer. + (line 64) +* ivy-backward-delete-char: File Name Completion. (line 19) +* ivy-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 19) +* ivy-confirm-face: Faces. (line 34) +* ivy-count-format: Defcustoms. (line 6) +* ivy-current-match: Faces. (line 9) +* ivy-dispatching-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 29) +* ivy-dispatching-done: Key bindings for single selection action then exit minibuffer. + (line 24) +* ivy-display-style: Defcustoms. (line 24) +* ivy-done: Key bindings for single selection action then exit minibuffer. + (line 19) +* ivy-extra-directories: File Name Completion. (line 51) +* ivy-height: Key bindings for navigation. + (line 21) +* ivy-immediate-done: Key bindings for single selection action then exit minibuffer. + (line 53) +* ivy-insert-current: Key bindings that alter the minibuffer input. + (line 23) +* ivy-insert-current-full: File Name Completion. (line 41) +* ivy-kill-ring-save: Other key bindings. (line 9) +* ivy-match-required-face: Faces. (line 53) +* ivy-minibuffer-grow: Hydra in the minibuffer. + (line 45) +* ivy-minibuffer-map: Minibuffer key bindings. + (line 6) +* ivy-minibuffer-match-face-1: Faces. (line 14) +* ivy-minibuffer-match-face-2: Faces. (line 19) +* ivy-minibuffer-match-face-3: Faces. (line 24) +* ivy-minibuffer-match-face-4: Faces. (line 29) +* ivy-minibuffer-shrink: Hydra in the minibuffer. + (line 50) +* ivy-modified-buffer: Faces. (line 88) +* ivy-modified-outside-buffer: Faces. (line 93) +* ivy-next-action: Hydra in the minibuffer. + (line 60) +* ivy-next-history-element: Key bindings that alter the minibuffer input. + (line 9) +* ivy-next-line-and-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 39) +* ivy-occur: Saving the current completion session to a buffer. + (line 9) +* ivy-occur-click: Saving the current completion session to a buffer. + (line 21) +* ivy-occur-dispatch: Saving the current completion session to a buffer. + (line 41) +* ivy-occur-press: Saving the current completion session to a buffer. + (line 16) +* ivy-occur-read-action: Saving the current completion session to a buffer. + (line 36) +* ivy-on-del-error-function: Defcustoms. (line 31) +* ivy-partial-or-done: Key bindings for single selection action then exit minibuffer. + (line 37) +* ivy-prev-action: Hydra in the minibuffer. + (line 55) +* ivy-previous-history-element: Key bindings that alter the minibuffer input. + (line 18) +* ivy-previous-line-and-call: Key bindings for multiple selections and actions keep minibuffer open. + (line 50) +* ivy-read-action: Hydra in the minibuffer. + (line 65) +* ivy-remote: Faces. (line 71) +* ivy-restrict-to-matches: Key bindings that alter the minibuffer input. + (line 40) +* ivy-resume: Key bindings for multiple selections and actions keep minibuffer open. + (line 58) +* ivy-reverse-i-search: Key bindings that alter the minibuffer input. + (line 48) +* ivy-rotate-preferred-builders: Hydra in the minibuffer. + (line 40) +* ivy-subdir: Faces. (line 66) +* ivy-toggle-calling: Hydra in the minibuffer. + (line 34) +* ivy-toggle-case-fold: Hydra in the minibuffer. + (line 70) +* ivy-toggle-regexp-quote: File Name Completion. (line 47) +* ivy-use-virtual-buffers: Buffer Name Completion. + (line 6) +* ivy-virtual: Faces. (line 76) +* ivy-wrap: Key bindings for navigation. + (line 14) +* ivy-yank-word: Key bindings that alter the minibuffer input. + (line 32) + + +File: ivy.info, Node: Keystroke Index, Prev: Variable Index, Up: Top + +10 Keystroke Index +****************** + +[index] +* Menu: + +* /: File Name Completion. (line 35) +* / C-j: Using TRAMP. (line 24) +* //: File Name Completion. (line 25) +* // <1>: Using TRAMP. (line 17) +* <: Hydra in the minibuffer. + (line 50) +* >: Hydra in the minibuffer. + (line 45) +* ~: File Name Completion. (line 30) +* ~ <1>: Using TRAMP. (line 9) +* ~~: Using TRAMP. (line 29) +* a: Hydra in the minibuffer. + (line 65) +* a <1>: Saving the current completion session to a buffer. + (line 36) +* c: Hydra in the minibuffer. + (line 34) +* C: Hydra in the minibuffer. + (line 70) +* C-': Key bindings for single selection action then exit minibuffer. + (line 64) +* C-c C-o: Saving the current completion session to a buffer. + (line 9) +* C-j: Key bindings for single selection action then exit minibuffer. + (line 30) +* C-j <1>: File Name Completion. (line 12) +* C-m: Key bindings for single selection action then exit minibuffer. + (line 19) +* C-M-j: Key bindings for single selection action then exit minibuffer. + (line 53) +* C-M-m: Key bindings for multiple selections and actions keep minibuffer open. + (line 19) +* C-M-n: Key bindings for multiple selections and actions keep minibuffer open. + (line 39) +* C-M-o: Key bindings for multiple selections and actions keep minibuffer open. + (line 29) +* C-M-p: Key bindings for multiple selections and actions keep minibuffer open. + (line 50) +* C-M-y: File Name Completion. (line 41) +* C-o: Hydra in the minibuffer. + (line 9) +* C-r: Key bindings that alter the minibuffer input. + (line 48) +* DEL: File Name Completion. (line 19) +* f: Saving the current completion session to a buffer. + (line 16) +* j: Saving the current completion session to a buffer. + (line 26) +* k: Saving the current completion session to a buffer. + (line 31) +* m: Hydra in the minibuffer. + (line 40) +* M-i: Key bindings that alter the minibuffer input. + (line 23) +* M-j: Key bindings that alter the minibuffer input. + (line 32) +* M-n: Key bindings that alter the minibuffer input. + (line 9) +* M-o: Key bindings for single selection action then exit minibuffer. + (line 24) +* M-p: Key bindings that alter the minibuffer input. + (line 18) +* M-r: File Name Completion. (line 47) +* M-w: Other key bindings. (line 9) +* mouse-1: Saving the current completion session to a buffer. + (line 21) +* o: Saving the current completion session to a buffer. + (line 41) +* q: Saving the current completion session to a buffer. + (line 46) +* RET: Key bindings for single selection action then exit minibuffer. + (line 19) +* RET <1>: Saving the current completion session to a buffer. + (line 16) +* s: Hydra in the minibuffer. + (line 60) +* S-SPC: Key bindings that alter the minibuffer input. + (line 40) +* TAB: Key bindings for single selection action then exit minibuffer. + (line 37) +* w: Hydra in the minibuffer. + (line 55) + + + +Tag Table: +Node: Top1190 +Node: Introduction3101 +Node: Installation5624 +Node: Installing from Emacs Package Manager6074 +Node: Installing from the Git repository7284 +Node: Getting started8104 +Node: Basic customization8411 +Node: Key bindings9006 +Node: Global key bindings9198 +Node: Minibuffer key bindings11672 +Node: Key bindings for navigation12904 +Node: Key bindings for single selection action then exit minibuffer14111 +Node: Key bindings for multiple selections and actions keep minibuffer open16758 +Node: Key bindings that alter the minibuffer input19379 +Node: Other key bindings21324 +Node: Hydra in the minibuffer21702 +Node: Saving the current completion session to a buffer24120 +Node: Completion Styles25532 +Node: ivy--regex-plus27283 +Node: ivy--regex-ignore-order28769 +Node: ivy--regex-fuzzy29137 +Node: Customization29634 +Node: Faces29820 +Node: Defcustoms32249 +Node: Actions33608 +Node: What are actions?33934 +Node: How can different actions be called?34752 +Node: How to modify the actions list?35323 +Node: Example - add two actions to each command35983 +Node: How to undo adding the two actions36942 +Node: How to add actions to a specific command37394 +Node: Example - define a new command with several actions37810 +Node: Test the above function with ivy-occur38698 +Node: Packages39540 +Node: Commands40505 +Node: File Name Completion40690 +Node: Using TRAMP42647 +Node: Buffer Name Completion44149 +Node: Counsel commands44764 +Node: API45411 +Node: Required arguments for ivy-read46009 +Node: Optional arguments for ivy-read46528 +Node: Example - counsel-describe-function49954 +Node: Example - counsel-locate52812 +Node: Example - ivy-read-with-extra-properties56562 +Node: Variable Index57770 +Node: Keystroke Index64894 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/elpa/language-id-0.10/language-id-autoloads.el b/elpa/language-id-0.12/language-id-autoloads.el similarity index 100% rename from elpa/language-id-0.10/language-id-autoloads.el rename to elpa/language-id-0.12/language-id-autoloads.el diff --git a/elpa/language-id-0.10/language-id-pkg.el b/elpa/language-id-0.12/language-id-pkg.el similarity index 60% rename from elpa/language-id-0.10/language-id-pkg.el rename to elpa/language-id-0.12/language-id-pkg.el index f88bc07..528a5fb 100644 --- a/elpa/language-id-0.10/language-id-pkg.el +++ b/elpa/language-id-0.12/language-id-pkg.el @@ -1,2 +1,2 @@ -;;; Generated package description from /home/raphael/.emacs.d/elpa/language-id-0.10/language-id.el -*- no-byte-compile: t -*- -(define-package "language-id" "0.10" "Library to work with programming language identifiers" '((emacs "24") (cl-lib "0.5")) :commit "3f0ad28202207c266bd8fc7904b224db69ceccf6" :authors '(("Lassi Kortela" . "lassi@lassi.io")) :maintainer '("Lassi Kortela" . "lassi@lassi.io") :keywords '("languages" "util") :url "https://github.com/lassik/emacs-language-id") +;;; Generated package description from /home/raphael/.emacs.d/elpa/language-id-0.12/language-id.el -*- no-byte-compile: t -*- +(define-package "language-id" "0.12" "Library to work with programming language identifiers" '((emacs "24") (cl-lib "0.5")) :commit "2c99ce29b86fc635649f4e89723912dc1cc4f36c" :authors '(("Lassi Kortela" . "lassi@lassi.io")) :maintainer '("Lassi Kortela" . "lassi@lassi.io") :keywords '("languages" "util") :url "https://github.com/lassik/emacs-language-id") diff --git a/elpa/language-id-0.10/language-id.el b/elpa/language-id-0.12/language-id.el similarity index 95% rename from elpa/language-id-0.10/language-id.el rename to elpa/language-id-0.12/language-id.el index f8a2306..c5db246 100644 --- a/elpa/language-id-0.10/language-id.el +++ b/elpa/language-id-0.12/language-id.el @@ -2,9 +2,9 @@ ;; ;; Author: Lassi Kortela ;; URL: https://github.com/lassik/emacs-language-id -;; Package-Version: 0.10 -;; Package-Commit: 3f0ad28202207c266bd8fc7904b224db69ceccf6 -;; Version: 0.10 +;; Package-Version: 0.12 +;; Package-Commit: 2c99ce29b86fc635649f4e89723912dc1cc4f36c +;; Version: 0.12 ;; Package-Requires: ((emacs "24") (cl-lib "0.5")) ;; Keywords: languages util ;; SPDX-License-Identifier: ISC @@ -70,6 +70,13 @@ (web-mode-engine "none") (language-id--file-name-extension ".ts"))) + ;; ReScript needs to come before Reason because in reason-mode + ;; we can tell them apart by file name extension only. + ("ReScript" + (reason-mode + (language-id--file-name-extension ".res"))) + ("Reason" reason-mode) + ;; vue-html-mode is derived from html-mode. ("Vue" vue-mode @@ -83,6 +90,7 @@ ("Bazel" bazel-mode) ("BibTeX" bibtex-mode) ("C" c-mode) + ("C#" csharp-mode) ("C++" c++-mode) ("Cabal Config" haskell-cabal-mode) ("Clojure" clojurescript-mode clojurec-mode clojure-mode) @@ -136,7 +144,6 @@ ("Python" python-mode) ("R" ess-r-mode (ess-mode (ess-dialect "R"))) ("Racket" racket-mode) - ("Reason" reason-mode) ("Ruby" enh-ruby-mode ruby-mode) ("Rust" rust-mode rustic-mode) ("Scala" scala-mode) diff --git a/elpa/markdown-mode-20210123.1547/markdown-mode-pkg.el b/elpa/markdown-mode-20210123.1547/markdown-mode-pkg.el deleted file mode 100644 index 467d994..0000000 --- a/elpa/markdown-mode-20210123.1547/markdown-mode-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from /home/raphael/.emacs.d/elpa/markdown-mode-20210123.1547/markdown-mode.el -*- no-byte-compile: t -*- -(define-package "markdown-mode" "20210123.1547" "Major mode for Markdown-formatted text" '((emacs "25.1")) :commit "779a4c637719f5a192c128ed60ecffed3ff1760c" :authors '(("Jason R. Blevins" . "jblevins@xbeta.org")) :maintainer '("Jason R. Blevins" . "jblevins@xbeta.org") :keywords '("markdown" "github flavored markdown" "itex") :url "https://jblevins.org/projects/markdown-mode/") diff --git a/elpa/markdown-mode-20210123.1547/markdown-mode-autoloads.el b/elpa/markdown-mode-20210216.852/markdown-mode-autoloads.el similarity index 100% rename from elpa/markdown-mode-20210123.1547/markdown-mode-autoloads.el rename to elpa/markdown-mode-20210216.852/markdown-mode-autoloads.el diff --git a/elpa/markdown-mode-20210216.852/markdown-mode-pkg.el b/elpa/markdown-mode-20210216.852/markdown-mode-pkg.el new file mode 100644 index 0000000..1d7be5e --- /dev/null +++ b/elpa/markdown-mode-20210216.852/markdown-mode-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from /home/raphael/.emacs.d/elpa/markdown-mode-20210216.852/markdown-mode.el -*- no-byte-compile: t -*- +(define-package "markdown-mode" "20210216.852" "Major mode for Markdown-formatted text" '((emacs "25.1")) :commit "377ce39ffe69f058994ac4e98bde8cfb58661406" :authors '(("Jason R. Blevins" . "jblevins@xbeta.org")) :maintainer '("Jason R. Blevins" . "jblevins@xbeta.org") :keywords '("markdown" "github flavored markdown" "itex") :url "https://jblevins.org/projects/markdown-mode/") diff --git a/elpa/markdown-mode-20210123.1547/markdown-mode.el b/elpa/markdown-mode-20210216.852/markdown-mode.el similarity index 98% rename from elpa/markdown-mode-20210123.1547/markdown-mode.el rename to elpa/markdown-mode-20210216.852/markdown-mode.el index 37b1b54..4073763 100644 --- a/elpa/markdown-mode-20210123.1547/markdown-mode.el +++ b/elpa/markdown-mode-20210216.852/markdown-mode.el @@ -7,8 +7,8 @@ ;; Maintainer: Jason R. Blevins ;; Created: May 24, 2007 ;; Version: 2.5-dev -;; Package-Version: 20210123.1547 -;; Package-Commit: 779a4c637719f5a192c128ed60ecffed3ff1760c +;; Package-Version: 20210216.852 +;; Package-Commit: 377ce39ffe69f058994ac4e98bde8cfb58661406 ;; Package-Requires: ((emacs "25.1")) ;; Keywords: Markdown, GitHub Flavored Markdown, itex ;; URL: https://jblevins.org/projects/markdown-mode/ @@ -50,6 +50,8 @@ (defvar flyspell-generic-check-word-predicate) (defvar electric-pair-pairs) +(declare-function project-roots "project") + ;;; Constants ================================================================= @@ -245,6 +247,22 @@ This is the default search behavior of Ikiwiki." :safe 'booleanp :package-version '(markdown-mode . "2.2")) +(defcustom markdown-wiki-link-search-type nil + "Searching type for markdown wiki link. + +sub-directories: search for wiki link targets in sub directories +parent-directories: search for wiki link targets in parent directories +project: search for wiki link targets under project root" + :group 'markdown + :type '(set + (const :tag "search wiki link from subdirectories" sub-directories) + (const :tag "search wiki link from parent directories" parent-directories) + (const :tag "search wiki link under project root" project)) + :package-version '(markdown-mode . "2.5")) + +(make-obsolete-variable 'markdown-wiki-link-search-subdirectories 'markdown-wiki-link-search-type "2.5") +(make-obsolete-variable 'markdown-wiki-link-search-parent-directories 'markdown-wiki-link-search-type "2.5") + (defcustom markdown-wiki-link-fontify-missing nil "When non-nil, change wiki link face according to existence of target files. This is expensive because it requires checking for the file each time the buffer @@ -4419,6 +4437,49 @@ at the beginning of the block." do (progn (when lang (markdown-gfm-add-used-language lang)) (goto-char (next-single-property-change (point) prop))))))) +(defun markdown-insert-foldable-block () + "Insert details disclosure element to make content foldable. +If a region is active, wrap this region with the disclosure +element. More detais here 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details'." + (interactive) + (let ((details-open-tag "
") + (details-close-tag "
") + (summary-open-tag "") + (summary-close-tag " ")) + (if (use-region-p) + (let* ((b (region-beginning)) + (e (region-end)) + (indent (progn (goto-char b) (current-indentation)))) + (goto-char e) + ;; if we're on a blank line, don't newline, otherwise the tags + ;; should go on its own line + (unless (looking-back "\n" nil) + (newline)) + (indent-to indent) + (insert details-close-tag) + (markdown-ensure-blank-line-after) + (goto-char b) + ;; if we're on a blank line, insert the quotes here, otherwise + ;; add a new line first + (unless (looking-at-p "\n") + (newline) + (forward-line -1)) + (markdown-ensure-blank-line-before) + (indent-to indent) + (insert details-open-tag "\n") + (insert summary-open-tag summary-close-tag) + (search-backward summary-close-tag)) + (let ((indent (current-indentation))) + (delete-horizontal-space :backward-only) + (markdown-ensure-blank-line-before) + (indent-to indent) + (insert details-open-tag "\n") + (insert summary-open-tag summary-close-tag "\n") + (insert details-close-tag) + (indent-to indent) + (markdown-ensure-blank-line-after) + (search-backward summary-close-tag))))) + ;;; Footnotes ================================================================= @@ -5164,6 +5225,7 @@ Assumes match data is available for `markdown-regex-italic'." (propertize "C = GFM code" 'face 'markdown-code-face) ", " (propertize "pre" 'face 'markdown-pre-face) ", " (propertize "footnote" 'face 'markdown-footnote-text-face) ", " + (propertize "F = foldable" 'face 'markdown-bold-face) ", " (propertize "q = blockquote" 'face 'markdown-blockquote-face) ", " (propertize "h & 1-6 = heading" 'face 'markdown-header-face) ", " (propertize "- = hr" 'face 'markdown-hr-face) ", " @@ -5197,6 +5259,7 @@ Assumes match data is available for `markdown-regex-italic'." (define-key map (kbd "c") 'markdown-insert-code) (define-key map (kbd "C") 'markdown-insert-gfm-code-block) (define-key map (kbd "f") 'markdown-insert-footnote) + (define-key map (kbd "F") 'markdown-insert-foldable-block) (define-key map (kbd "h") 'markdown-insert-header-dwim) (define-key map (kbd "H") 'markdown-insert-header-setext-dwim) (define-key map (kbd "i") 'markdown-insert-italic) @@ -5508,6 +5571,7 @@ See also `markdown-mode-map'.") ["GFM Code Block" markdown-insert-gfm-code-block] ["Edit Code Block" markdown-edit-code-block :enable (markdown-code-block-at-point-p)] + ["Foldable Block" markdown-insert-foldable-block] "---" ["Blockquote Region" markdown-blockquote-region] ["Preformatted Region" markdown-pre-region] @@ -7832,6 +7896,29 @@ The location of the alias component depends on the value of (match-string-no-properties 3) (or (match-string-no-properties 5) (match-string-no-properties 3)))) +(defun markdown--wiki-link-search-types () + (let ((ret (and markdown-wiki-link-search-type + (cl-copy-list markdown-wiki-link-search-type)))) + (when (and markdown-wiki-link-search-subdirectories + (not (memq 'sub-directories markdown-wiki-link-search-type))) + (push 'sub-directories ret)) + (when (and markdown-wiki-link-search-parent-directories + (not (memq 'parent-directories markdown-wiki-link-search-type))) + (push 'parent-directories ret)) + ret)) + +(defun markdown--project-root () + (or (cl-loop for dir in '(".git" ".hg" ".svn") + when (locate-dominating-file default-directory dir) + return it) + (progn + (require 'project) + (let ((project (project-current t))) + (with-no-warnings + (if (fboundp 'project-root) + (project-root project) + (car (project-roots project)))))))) + (defun markdown-convert-wiki-link-to-filename (name) "Generate a filename from the wiki link NAME. Spaces in NAME are replaced with `markdown-link-space-sub-char'. @@ -7841,35 +7928,43 @@ directory first, then in subdirectories if `markdown-wiki-link-search-subdirectories' is non-nil, and then in parent directories if `markdown-wiki-link-search-parent-directories' is non-nil." - (let* ((basename (replace-regexp-in-string - "[[:space:]\n]" markdown-link-space-sub-char name)) - (basename (if (derived-mode-p 'gfm-mode) - (concat (upcase (substring basename 0 1)) - (downcase (substring basename 1 nil))) - basename)) - directory extension default candidates dir) - (when buffer-file-name - (setq directory (file-name-directory buffer-file-name) - extension (file-name-extension buffer-file-name))) - (setq default (concat basename - (when extension (concat "." extension)))) - (cond - ;; Look in current directory first. - ((or (null buffer-file-name) - (file-exists-p default)) - default) - ;; Possibly search in subdirectories, next. - ((and markdown-wiki-link-search-subdirectories - (setq candidates - (directory-files-recursively - directory (concat "^" default "$")))) - (car candidates)) - ;; Possibly search in parent directories as a last resort. - ((and markdown-wiki-link-search-parent-directories - (setq dir (locate-dominating-file directory default))) - (concat dir default)) - ;; If nothing is found, return default in current directory. - (t default)))) + (save-match-data + ;; This function must not overwrite match data(PR #590) + (let* ((basename (replace-regexp-in-string + "[[:space:]\n]" markdown-link-space-sub-char name)) + (basename (if (derived-mode-p 'gfm-mode) + (concat (upcase (substring basename 0 1)) + (downcase (substring basename 1 nil))) + basename)) + (search-types (markdown--wiki-link-search-types)) + directory extension default candidates dir) + (when buffer-file-name + (setq directory (file-name-directory buffer-file-name) + extension (file-name-extension buffer-file-name))) + (setq default (concat basename + (when extension (concat "." extension)))) + (cond + ;; Look in current directory first. + ((or (null buffer-file-name) + (file-exists-p default)) + default) + ;; Possibly search in subdirectories, next. + ((and (memq 'sub-directories search-types) + (setq candidates + (directory-files-recursively + directory (concat "^" default "$")))) + (car candidates)) + ;; Possibly search in parent directories as a last resort. + ((and (memq 'parent-directories search-types) + (setq dir (locate-dominating-file directory default))) + (concat dir default)) + ((and (memq 'project search-types) + (setq candidates + (directory-files-recursively + (markdown--project-root) (concat "^" default "$")))) + (car candidates)) + ;; If nothing is found, return default in current directory. + (t default))))) (defun markdown-follow-wiki-link (name &optional other) "Follow the wiki link NAME. @@ -9204,15 +9299,23 @@ Create new table lines if required." (unless (markdown-table-at-point-p) (user-error "Not at a table")) (markdown-table-align) - (when (markdown-table-hline-at-point-p) (end-of-line 1)) + (when (markdown-table-hline-at-point-p) (beginning-of-line 1)) (condition-case nil (progn (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin)) + ;; When this function is called while in the first cell in a + ;; table, the point will now be at the beginning of a line. In + ;; this case, we need to move past one additional table + ;; boundary, the end of the table on the previous line. + (when (= (point) (line-beginning-position)) + (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin))) (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin))) (error (user-error "Cannot move to previous table cell"))) - (while (looking-at "|\\([-:]\\|[ \t]*$\\)") - (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin))) - (when (looking-at "| ?") (goto-char (match-end 0)))) + (when (looking-at "\\(?:^\\|[^\\]\\)| ?") (goto-char (match-end 0))) + + ;; This may have dropped point on the hline. + (when (markdown-table-hline-at-point-p) + (markdown-table-backward-cell))) (defun markdown-table-transpose () "Transpose table at point. diff --git a/elpa/nginx-mode-1.1.9/nginx-mode-autoloads.el b/elpa/nginx-mode-1.1.9/nginx-mode-autoloads.el new file mode 100644 index 0000000..201ced8 --- /dev/null +++ b/elpa/nginx-mode-1.1.9/nginx-mode-autoloads.el @@ -0,0 +1,36 @@ +;;; nginx-mode-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "nginx-mode" "nginx-mode.el" (0 0 0 0)) +;;; Generated autoloads from nginx-mode.el + +(autoload 'nginx-mode "nginx-mode" "\ +Major mode for highlighting nginx config files. + +The variable nginx-indent-level controls the amount of indentation. +\\{nginx-mode-map} + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("nginx\\.conf\\'" . nginx-mode)) + +(add-to-list 'auto-mode-alist '("/nginx/.+\\.conf\\'" . nginx-mode)) + +(add-to-list 'magic-fallback-mode-alist '("\\(?:.*\n\\)*\\(?:http\\|server\\|location .+\\|upstream .+\\)[ \n\11]+{" . nginx-mode)) + +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "nginx-mode" '("nginx-"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; nginx-mode-autoloads.el ends here diff --git a/elpa/nginx-mode-1.1.9/nginx-mode-pkg.el b/elpa/nginx-mode-1.1.9/nginx-mode-pkg.el new file mode 100644 index 0000000..73a4eee --- /dev/null +++ b/elpa/nginx-mode-1.1.9/nginx-mode-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from /home/raphael/.emacs.d/elpa/nginx-mode-1.1.9/nginx-mode.el -*- no-byte-compile: t -*- +(define-package "nginx-mode" "1.1.9" "major mode for editing nginx config files" 'nil :commit "a2bab83c2eb233d57d76b236e7c141c2ccc97005" :authors '(("Andrew J Cosgriff" . "andrew@cosgriff.name")) :maintainer '("Andrew J Cosgriff" . "andrew@cosgriff.name") :keywords '("languages" "nginx")) diff --git a/elpa/nginx-mode-1.1.9/nginx-mode.el b/elpa/nginx-mode-1.1.9/nginx-mode.el new file mode 100644 index 0000000..c285d31 --- /dev/null +++ b/elpa/nginx-mode-1.1.9/nginx-mode.el @@ -0,0 +1,203 @@ +;;; nginx-mode.el --- major mode for editing nginx config files + +;; Copyright 2010 Andrew J Cosgriff + +;; Author: Andrew J Cosgriff +;; Maintainer: Andrew J Cosgriff +;; Created: 15 Oct 2010 +;; Version: 1.1.9 +;; Package-Version: 1.1.9 +;; Package-Commit: a2bab83c2eb233d57d76b236e7c141c2ccc97005 +;; Keywords: languages, nginx + +;; available from http://github.com/ajc/nginx-mode + +;; 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 2, 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 . + +;;; Commentary: + +;; This is a quick mode for editing Nginx config files, as I didn't find +;; anything else around that did quite this much. + +;; Many thanks to the authors of puppet-mode.el, from where I found a +;; useful indentation function that I've modified to suit this situation. + +;; Put this file into your load-path and the following into your ~/.emacs: +;; (require 'nginx-mode) + +;;; Code: + + +;;;;########################################################################## +;;;; User Options, Variables +;;;;########################################################################## + +(defcustom nginx-indent-level 4 + "*Indentation of Nginx statements." + :type 'integer :group 'nginx) + +(defcustom nginx-indent-tabs-mode nil + "*Indentation can insert tabs in nginx mode if this is non-nil." + :type 'boolean :group 'nginx) + +(defvar nginx-mode-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?# "< b" table) + (modify-syntax-entry ?\n "> b" table) + table) + "Syntax table for `nginx-mode'.") + +(defvar nginx-font-lock-keywords + (list '("^\\([ \t]+\\)?\\([A-Za-z09_]+\\)" 2 font-lock-keyword-face t) + ;; uncomment the next one if you want your eyes to bleed + ;; (it'll highlight parentheses and curly braces) + ;;'("\\(\{\\|\}\\|\(\\|\)\\)" . font-lock-pseudo-keyword-face) + '("^\\([ \t]+\\)?rewrite[ \t]+.+[ \t]+\\(permanent\\|redirect\\|break\\|last\\);$" 2 font-lock-function-name-face) + '("\\(\$[0-9]+\\)[^0-9]" 1 font-lock-constant-face) + '("\$[A-Za-z0-9_\-]+" . font-lock-variable-name-face) + '("[ \t]+\\(on\\|off\\);$" 1 font-lock-constant-face) + '("[A-Za-z0-9_\-]+\\([ \t]+[^ \t\n]+\\)?[ \t]+\\([^ \t\n]+\\)[ \t]+{" 2 font-lock-function-name-face))) + + +;;;;########################################################################## +;;;; Code +;;;;########################################################################## + +(defun nginx-block-indent () + "If point is in a block, return the indentation of the first line of that +block (the line containing the opening brace). Used to set the indentation +of the closing brace of a block." + (save-excursion + (save-match-data + (let ((opoint (point)) + (apoint (search-backward "{" nil t))) + (when apoint + ;; This is a bit of a hack and doesn't allow for strings. We really + ;; want to parse by sexps at some point. + (let ((close-braces (count-matches "}" apoint opoint)) + (open-braces 0)) + (while (and apoint (> close-braces open-braces)) + (setq apoint (search-backward "{" nil t)) + (when apoint + (setq close-braces (count-matches "}" apoint opoint)) + (setq open-braces (1+ open-braces))))) + (if apoint + (current-indentation) + nil)))))) + + +(defun nginx-comment-line-p () + "Return non-nil iff this line is a comment." + (save-excursion + (save-match-data + (beginning-of-line) + (looking-at "^\\s-*#")))) + +(defun nginx-indent-line () + "Indent current line as nginx code." + (interactive) + (beginning-of-line) + (if (bobp) + (indent-line-to 0) ; First line is always non-indented + (let ((not-indented t) + (block-indent (nginx-block-indent)) + cur-indent) + (cond + ((and (looking-at "^\\s-*}\\s-*$") block-indent) + ;; This line contains a closing brace and we're at the inner + ;; block, so we should indent it matching the indentation of + ;; the opening brace of the block. + (setq cur-indent block-indent)) + (t + ;; Otherwise, we did not start on a block-ending-only line. + (save-excursion + ;; Iterate backwards until we find an indentation hint + (while not-indented + (forward-line -1) + (cond + ;; Comment lines are ignored unless we're at the start of the + ;; buffer. + ((nginx-comment-line-p) + (if (bobp) + (setq not-indented nil))) + + ;; Brace or paren on a line by itself will already be indented to + ;; the right level, so we can cheat and stop there. + ((looking-at "^\\s-*}\\s-*") + (setq cur-indent (current-indentation)) + (setq not-indented nil)) + + ;; Indent by one level more than the start of our block. We lose + ;; if there is more than one block opened and closed on the same + ;; line but it's still unbalanced; hopefully people don't do that. + ((looking-at "^.*{[^\n}]*$") + (setq cur-indent (+ (current-indentation) nginx-indent-level)) + (setq not-indented nil)) + + ;; Start of buffer. + ((bobp) + (setq not-indented nil))))))) + + ;; We've figured out the indentation, so do it. + (if (and cur-indent (> cur-indent 0)) + (indent-line-to cur-indent) + (indent-line-to 0))))) + + +(defvar nginx-mode-map + (let + ((map (make-sparse-keymap))) + (define-key map "\C-j" 'newline-and-indent) + (define-key map "\C-m" 'newline-and-indent) + map) + "Keymap for editing nginx config files.") + +;;;###autoload +(define-derived-mode nginx-mode prog-mode "Nginx" + "Major mode for highlighting nginx config files. + +The variable nginx-indent-level controls the amount of indentation. +\\{nginx-mode-map}" + :syntax-table nginx-mode-syntax-table + + (use-local-map nginx-mode-map) + + (set (make-local-variable 'comment-start) "# ") + (set (make-local-variable 'comment-start-skip) "#+ *") + (set (make-local-variable 'comment-end) "") + (set (make-local-variable 'comment-auto-fill-only-comments) t) + + (set (make-local-variable 'indent-line-function) 'nginx-indent-line) + (set (make-local-variable 'indent-tabs-mode) nginx-indent-tabs-mode) + (set (make-local-variable 'require-final-newline) t) + (set (make-local-variable 'paragraph-ignore-fill-prefix) t) + (set (make-local-variable 'paragraph-start) "\f\\|[ ]*$\\|#$") + (set (make-local-variable 'paragraph-separate) "\\([ \f]*\\|#\\)$") + + (set (make-local-variable 'font-lock-defaults) + '(nginx-font-lock-keywords nil))) + +;;;###autoload +(add-to-list 'auto-mode-alist '("nginx\\.conf\\'" . nginx-mode)) +;;;###autoload +(add-to-list 'auto-mode-alist '("/nginx/.+\\.conf\\'" . nginx-mode)) +;;;###autoload +(add-to-list + 'magic-fallback-mode-alist + '("\\(?:.*\n\\)*\\(?:http\\|server\\|location .+\\|upstream .+\\)[ \n\t]+{" + . nginx-mode)) + +(provide 'nginx-mode) + +;;; nginx-mode.el ends here diff --git a/elpa/request-20201026.2324/request-pkg.el b/elpa/request-20201026.2324/request-pkg.el deleted file mode 100755 index 81d00bb..0000000 --- a/elpa/request-20201026.2324/request-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from /data/data/com.termux/files/home/.emacs.d/elpa/request-20201026.2324/request.el -*- no-byte-compile: t -*- -(define-package "request" "20201026.2324" "Compatible layer for URL request in Emacs" '((emacs "24.4")) :commit "0183da84cb45eb94da996cd2eab714ef0d7504cc" :authors '(("Takafumi Arakaki ")) :maintainer '("Takafumi Arakaki ") :url "https://github.com/tkf/emacs-request") diff --git a/elpa/request-20201026.2324/request-autoloads.el b/elpa/request-20210214.37/request-autoloads.el old mode 100755 new mode 100644 similarity index 100% rename from elpa/request-20201026.2324/request-autoloads.el rename to elpa/request-20210214.37/request-autoloads.el diff --git a/elpa/request-20210214.37/request-pkg.el b/elpa/request-20210214.37/request-pkg.el new file mode 100644 index 0000000..ad70584 --- /dev/null +++ b/elpa/request-20210214.37/request-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from /home/raphael/.emacs.d/elpa/request-20210214.37/request.el -*- no-byte-compile: t -*- +(define-package "request" "20210214.37" "Compatible layer for URL request" '((emacs "24.4")) :commit "accd430ee706f5b10fb20003b06bd8209bcdaa82" :authors '(("Takafumi Arakaki ")) :maintainer '("Takafumi Arakaki ") :url "https://github.com/tkf/emacs-request") diff --git a/elpa/request-20201026.2324/request.el b/elpa/request-20210214.37/request.el old mode 100755 new mode 100644 similarity index 79% rename from elpa/request-20201026.2324/request.el rename to elpa/request-20210214.37/request.el index 6531cea..cbab6c8 --- a/elpa/request-20201026.2324/request.el +++ b/elpa/request-20210214.37/request.el @@ -1,4 +1,4 @@ -;;; request.el --- Compatible layer for URL request in Emacs -*- lexical-binding: t; -*- +;;; request.el --- Compatible layer for URL request -*- lexical-binding: t; -*- ;; Copyright (C) 2012 Takafumi Arakaki ;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2012 @@ -6,10 +6,10 @@ ;; Author: Takafumi Arakaki ;; URL: https://github.com/tkf/emacs-request -;; Package-Version: 20201026.2324 -;; Package-Commit: 0183da84cb45eb94da996cd2eab714ef0d7504cc +;; Package-Version: 20210214.37 +;; Package-Commit: accd430ee706f5b10fb20003b06bd8209bcdaa82 ;; Package-Requires: ((emacs "24.4")) -;; Version: 0.3.2 +;; Version: 0.3.3 ;; This file is NOT part of GNU Emacs. @@ -25,21 +25,15 @@ ;; You should have received a copy of the GNU General Public License ;; along with request.el. -;; If not, see . +;; If not, see . ;;; Commentary: -;; Request.el is a HTTP request library with multiple backends. It -;; supports url.el which is shipped with Emacs and curl command line -;; program. User can use curl when s/he has it, as curl is more reliable -;; than url.el. Library author can use request.el to avoid imposing -;; external dependencies such as curl to users while giving richer -;; experience for users who have curl. - -;; Following functions are adapted from GNU Emacs source code. -;; Free Software Foundation holds the copyright of them. -;; * `request--process-live-p' -;; * `request--url-default-expander' +;; Uses ``curl`` as its backend or Emacs's native ``url.el`` library if +;; ``curl`` is not found. +;; +;; The default encoding for requests is ``utf-8``. Please explicitly specify +;; ``:encoding 'binary`` for binary data. ;;; Code: @@ -52,16 +46,14 @@ (require 'mail-utils) (require 'autorevert) (require 'auth-source) +(require 'mailheader) (defgroup request nil "Compatible layer for URL request in Emacs." :group 'comm :prefix "request-") -(defconst request-version "0.3.0") - - -;;; Customize variables +(defconst request-version "0.3.3") (defcustom request-storage-directory (concat (file-name-as-directory user-emacs-directory) "request") @@ -73,10 +65,10 @@ :type 'string) (defcustom request-curl-options nil - "curl command options. + "List of curl command options. -List of strings that will be passed to every curl invocation. You can pass -extra options here, like setting the proxy." +List of strings that will be passed to every curl invocation. +You can pass extra options here, like setting the proxy." :type '(repeat string)) (defcustom request-backend (if (executable-find request-curl) @@ -89,14 +81,11 @@ Automatically set to `curl' if curl command is found." (defcustom request-timeout nil "Default request timeout in second. -`nil' means no timeout." +nil means no timeout." :type '(choice (integer :tag "Request timeout seconds") (boolean :tag "No timeout" nil))) -(defcustom request-temp-prefix "emacs-request" - "Prefix for temporary files created by Request." - :type 'string - :risky t) +(make-obsolete-variable 'request-temp-prefix nil "0.3.3") (defcustom request-log-level -1 "Logging level for request. @@ -123,41 +112,12 @@ See `request-log-level'." (const :tag "Level TRACE" trace) (const :tag "Level BLATHER" blather))) - -;;; Utilities - -(defun request--safe-apply (function &rest arguments) - "Apply FUNCTION with ARGUMENTS, suppressing any errors." - (condition-case nil - (apply #'apply function arguments) - ((debug error)))) - -(defun request--safe-call (function &rest arguments) - (request--safe-apply function arguments)) - -;; (defun request--url-no-cache (url) -;; "Imitate `cache=false' of `jQuery.ajax'. -;; See: http://api.jquery.com/jQuery.ajax/" -;; ;; FIXME: parse URL before adding ?_=TIME. -;; (concat url (format-time-string "?_=%s"))) - (defmacro request--document-function (function docstring) "Document FUNCTION with DOCSTRING. Use this for defstruct accessor etc." (declare (indent defun) (doc-string 2)) `(put ',function 'function-documentation ,docstring)) -(defun request--process-live-p (process) - "Copied from `process-live-p' for backward compatibility (Emacs < 24). -Adapted from lisp/subr.el. -FSF holds the copyright of this function: - Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2012 - Free Software Foundation, Inc." - (memq (process-status process) '(run open listen connect stop))) - - -;;; Logging - (defconst request--log-level-def '(;; debugging (blather . 60) (trace . 50) (debug . 40) @@ -167,43 +127,29 @@ FSF holds the copyright of this function: (warn . 10) (error . 0)) "Named logging levels.") -(defun request--log-level-as-int (level) - (if (integerp level) - level - (or (cdr (assq level request--log-level-def)) - 0))) - (defvar request-log-buffer-name " *request-log*") -(defun request--log-buffer () - (get-buffer-create request-log-buffer-name)) - (defmacro request-log (level fmt &rest args) + "Main logging function at warning LEVEL in FMT with ARGS." (declare (indent 1)) - `(let ((level (request--log-level-as-int ,level)) - (log-level (request--log-level-as-int request-log-level)) - (msg-level (request--log-level-as-int request-message-level))) - (when (<= level (max log-level msg-level)) - (let ((msg (format "[%s] %s" ,level - (condition-case err - (format ,fmt ,@args) - (error (format " -!!! Logging error while executing: -%S -!!! Error: -%S" - ',args err)))))) - (when (<= level log-level) - (with-current-buffer (request--log-buffer) - (setq buffer-read-only t) - (let ((inhibit-read-only t)) - (goto-char (point-max)) - (insert msg "\n")))) - (when (<= level msg-level) - (message "%s" msg)))))) - - -;;; HTTP specific utilities + `(cl-flet ((log-level-as-int + (level) + (if (integerp level) + level + (or (cdr (assq level request--log-level-def)) 0)))) + (let ((level (log-level-as-int ,level)) + (log-level (log-level-as-int request-log-level)) + (msg-level (log-level-as-int request-message-level))) + (when (<= level (max log-level msg-level)) + (let ((msg (format "[%s] %s" ,level (format ,fmt ,@args)))) + (when (<= level log-level) + (with-current-buffer (get-buffer-create request-log-buffer-name) + (setq buffer-read-only t) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert msg "\n")))) + (when (<= level msg-level) + (message "%s" msg))))))) (defconst request--url-unreserved-chars '(?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z @@ -215,7 +161,7 @@ This is used for making `request--urlencode-alist' RFC 3986 compliant for older Emacs versions.") (defun request--urlencode-alist (alist) - ;; FIXME: make monkey patching `url-unreserved-chars' optional + "Hexify ALIST fields according to RFC3986." (let ((url-unreserved-chars request--url-unreserved-chars)) (cl-loop for sep = "" then "&" for (k . v) in alist @@ -224,8 +170,6 @@ for older Emacs versions.") concat "=" concat (url-hexify-string (format "%s" v))))) - -;;; Header parser (defun request--parse-response-at-point () "Parse the first header line such as \"HTTP/1.1 200 OK\"." @@ -234,21 +178,19 @@ for older Emacs versions.") :code (string-to-number (match-string 2))))) (defun request--goto-next-body (&optional noerror) + "Scan forward to next blank line allowing NOERROR if missing." (re-search-forward "^\r\n" nil noerror)) - -;;; Response object - (cl-defstruct request-response "A structure holding all relevant information of a request." status-code history data error-thrown symbol-status url done-p settings ;; internal variables - -buffer -raw-header -timer -backend -tempfiles) + -buffer -raw-header -timer -backend) (defmacro request--document-response (function docstring) - (declare (indent defun) - (doc-string 2)) + "Append to FUNCTION's DOCSTRING some more canned verbiage." + (declare (indent defun) (doc-string 2)) `(request--document-function ,function ,(concat docstring " .. This is an accessor for `request-response' object. @@ -313,8 +255,7 @@ Examples:: (request-response-header response \"content-type\") ; => \"text/html; charset=utf-8\" (request-response-header response - \"unknown-field\") ; => nil -" + \"unknown-field\") ; => nil" (let ((raw-header (request-response--raw-header response))) (when raw-header (with-temp-buffer @@ -324,11 +265,23 @@ Examples:: ;; separated value [#rfc2616-sec4]_. (mail-fetch-field field-name nil t))))) ;; .. [#rfc2616-sec4] RFC2616 says this is the right thing to do -;; (see http://tools.ietf.org/html/rfc2616.html#section-4.2). +;; (see https://tools.ietf.org/html/rfc2616.html#section-4.2). ;; Python's requests module does this too. - -;;; Backend dispatcher +(defun request-response-headers (response) + "Return RESPONSE headers as an alist. +I would have chosen a function name that wasn't so suggestive that +`headers` is a member of the `request-response` struct, but +as there's already precedent with `request-response-header', I +hew to consistency." + (let ((raw-header (request-response--raw-header response))) + (when raw-header + raw-header + (with-temp-buffer + (save-excursion (insert raw-header)) + (when (save-excursion (request--parse-response-at-point)) + (forward-line)) + (mail-header-extract-no-properties))))) (defconst request--backend-alist '((url-retrieve @@ -358,38 +311,26 @@ let's stick to manual dispatch for now.") (assoc-default method (or (assoc-default request-backend request--backend-alist) - (error "%S is not valid `request-backend'." request-backend)))) + (error "%S is not valid `request-backend'" request-backend)))) - -;;; Cookie (defun request-cookie-string (host &optional localpart secure) - "Return cookie string (like `document.cookie'). - + "Lookup HOST LOCALPART SECURE in cookie jar as`document.cookie` string. Example:: - (request-cookie-string \"127.0.0.1\" \"/\") ; => \"key=value; key2=value2\" -" + (request-cookie-string \"127.0.0.1\" \"/\") ; => \"key=value; key2=value2\"" (mapconcat (lambda (nv) (concat (car nv) "=" (cdr nv))) (request-cookie-alist host localpart secure) "; ")) (defun request-cookie-alist (host &optional localpart secure) - "Return cookies as an alist. + "Lookup HOST LOCALPART SECURE in cookie jar as alist. Example:: - (request-cookie-alist \"127.0.0.1\" \"/\") ; => ((\"key\" . \"value\") ...) -" + (request-cookie-alist \"127.0.0.1\" \"/\") ; => ((\"key\" . \"value\") ...)" (funcall (request--choose-backend 'get-cookies) host localpart secure)) - -;;; Main - -(cl-defun request-default-error-callback (url &key symbol-status - &allow-other-keys) - (request-log 'error - "request-default-error-callback: %s %s" url symbol-status)) (cl-defun request (url &rest settings &key @@ -401,9 +342,7 @@ Example:: (sync nil) (response (make-request-response)) &allow-other-keys) - "Send request to URL. - -Request.el has a single entry point. It is `request'. + "Main entry requesting URL with property list SETTINGS as follow. ==================== ======================================================== Keyword argument Explanation @@ -420,7 +359,7 @@ ERROR (function) called on error COMPLETE (function) called on both success and error TIMEOUT (number) timeout in second STATUS-CODE (alist) map status code (int) to callback -SYNC (bool) If `t', wait until request is done. Default is `nil'. +SYNC (bool) If non-nil, wait until request is done. Default is nil. ==================== ======================================================== @@ -497,7 +436,7 @@ Example FILES argument:: support FILES in pure elisp by making furl.el_ another backend. Contributions are welcome. - .. _furl.el: http://code.google.com/p/furl-el/ + .. _furl.el: https://code.google.com/p/furl-el/ * PARSER function @@ -518,7 +457,7 @@ objects to plist instead of alist, wrap `json-read' by `lambda' like this.:: (request - \"http://...\" + \"https://...\" :parser (lambda () (let ((json-object-type 'plist)) (json-read))) @@ -541,7 +480,7 @@ relatively small value. Due to limitation of `url-retrieve-synchronously', response slots `request-response-error-thrown', `request-response-history' and -`request-response-url' are unknown (always `nil') when using +`request-response-url' are unknown (always nil) when using synchronous request with `url-retrieve' backend. * Note @@ -549,15 +488,18 @@ synchronous request with `url-retrieve' backend. API of `request' is somewhat mixture of jQuery.ajax_ (Javascript) and requests.request_ (Python). -.. _jQuery.ajax: http://api.jquery.com/jQuery.ajax/ -.. _requests.request: http://docs.python-requests.org -" +.. _jQuery.ajax: https://api.jquery.com/jQuery.ajax/ +.. _requests.request: https://docs.python-requests.org" (declare (indent defun)) ;; FIXME: support CACHE argument (if possible) ;; (unless cache ;; (setq url (request--url-no-cache url))) (unless error - (setq error (apply-partially #'request-default-error-callback url)) + (setq error (cl-function + (lambda (&rest args &key symbol-status &allow-other-keys) + (request-log 'error + "request-default-error-callback: %s %s" + url symbol-status)))) (setq settings (plist-put settings :error error))) (unless (or (stringp data) (null data) @@ -582,7 +524,7 @@ and requests.request_ (Python). response) (defun request--clean-header (response) - "Strip off carriage returns in the header of REQUEST." + "Strip off carriage return in the header of RESPONSE." (let* ((buffer (request-response--buffer response)) (backend (request-response--backend response)) ;; FIXME: a workaround when `url-http-clean-headers' fails... @@ -603,8 +545,7 @@ and requests.request_ (Python). (replace-match ""))))))) (defun request--cut-header (response) - "Cut the first header part in the buffer of RESPONSE and move it to -raw-header slot." + "Move the header to the raw-header slot of RESPONSE object." (let ((buffer (request-response--buffer response))) (when (buffer-live-p buffer) (with-current-buffer buffer @@ -621,8 +562,7 @@ raw-header slot." (or (file-remote-p file 'localname) file)) (defun request--parse-data (response encoding parser) - "For buffer held by RESPONSE, first decode via user's ENCODING elective, -then send to PARSER." + "In RESPONSE buffer, decode via ENCODING, then send to PARSER." (let ((buffer (request-response--buffer response))) (when (buffer-live-p buffer) (with-current-buffer buffer @@ -645,15 +585,18 @@ then send to PARSER." status-code response encoding &allow-other-keys) + "Parse BUFFER according to PARSER. +Delegate to callbacks SUCCESS, ERROR, and COMPLETE the STATUS-CODE of +RESPONSE via ENCODING." (request-log 'debug "request--callback: UNPARSED\n%s" (when (buffer-live-p buffer) (with-current-buffer buffer (buffer-string)))) - - ;; Sometimes BUFFER given as the argument is different from the - ;; buffer already set in RESPONSE. That's why it is reset here. - ;; FIXME: Refactor how BUFFER is passed around. + ;; Reset RESPONSE buffer to argument BUFFER. (setf (request-response--buffer response) buffer) - (request-response--cancel-timer response) + (cl-symbol-macrolet ((timer (request-response--timer response))) + (when timer + (cancel-timer timer) + (setq timer nil))) (cl-symbol-macrolet ((error-thrown (request-response-error-thrown response)) (symbol-status (request-response-symbol-status response)) @@ -693,32 +636,26 @@ then send to PARSER." (name (if success-p "success" "error"))) (when cb (request-log 'debug "request--callback: executing %s" name) - (request--safe-apply cb args))) - + (apply cb args))) (let ((cb (cdr (assq (request-response-status-code response) status-code)))) (when cb (request-log 'debug "request--callback: executing status-code") - (request--safe-apply cb args))) - + (apply cb args))) (when complete (request-log 'debug "request--callback: executing complete") - (request--safe-apply complete args))) - - (setq done-p t) + (apply complete args))) - ;; Remove temporary files - ;; FIXME: Make tempfile cleanup more reliable. It is possible - ;; callback is never called. - (request--safe-delete-files (request-response--tempfiles response)))) + (setq done-p t))) (cl-defun request-response--timeout-callback (response) + "If RESPONSE times out, ensure `request--callback' gets called." (setf (request-response-symbol-status response) 'timeout) (setf (request-response-error-thrown response) '(error . ("Timeout"))) (let* ((buffer (request-response--buffer response)) (proc (and (buffer-live-p buffer) (get-buffer-process buffer)))) (if proc - ;; This will call `request--callback': + ;; This implicitly calls `request--callback'! (funcall (request--choose-backend 'terminate-process) proc) (cl-symbol-macrolet ((done-p (request-response-done-p response))) (unless done-p @@ -733,13 +670,6 @@ then send to PARSER." (request-response-settings response)) (setq done-p t)))))) -(defun request-response--cancel-timer (response) - (cl-symbol-macrolet ((timer (request-response--timer response))) - (when timer - (cancel-timer timer) - (setq timer nil)))) - - (defun request-abort (response) "Abort request for RESPONSE (the object returned by `request'). Note that this function invoke ERROR and COMPLETE callbacks. @@ -752,18 +682,15 @@ associated process is exited." (unless symbol-status ; should I use done-p here? (setq symbol-status 'abort) (setq done-p t) - (when (and - (processp process) ; process can be nil when buffer is killed - (request--process-live-p process)) + (when (process-live-p process) (funcall (request--choose-backend 'terminate-process) process)))))) - -;;; Backend: `url-retrieve' (cl-defun request--url-retrieve-preprocess-settings (&rest settings &key type data files headers &allow-other-keys) + "Augment SETTINGS with properties TYPE DATA FILES HEADERS." (when files - (error "`url-retrieve' backend does not support FILES.")) + (error "`url-retrieve' backend does not support FILES")) (when (and (equal type "POST") data (not (assoc-string "Content-Type" headers t))) @@ -775,6 +702,10 @@ associated process is exited." &key type data timeout response &allow-other-keys &aux headers) + "Internal workhorse querying URL via curl. +SETTINGS is a property list with keys (some optional) such as GET or POST TYPE, +DATA for posting fields, TIMEOUT in seconds, RESPONSE a mandatory struct. +HEADERS needs to be assigned after SETTINGS is preprocessed." (setq settings (apply #'request--url-retrieve-preprocess-settings settings)) (setq headers (plist-get settings :headers)) (let* ((url-request-extra-headers headers) @@ -791,6 +722,9 @@ associated process is exited." (cl-defun request--url-retrieve-callback (status &rest settings &key response url &allow-other-keys) + "Ensure `request--callback' gets called for STATUS. +SETTINGS should include RESPONSE and URL properties which +inform any necessary redirect or history recording logic." (when (featurep 'url-http) (setf (request-response-status-code response) url-http-response-status)) (let ((redirect (plist-get status :redirect))) @@ -810,20 +744,21 @@ associated process is exited." do (let ((r (make-request-response :-backend 'url-retrieve))) (setf (request-response-url r) v) (push r (request-response-history response)))) - (cl-symbol-macrolet ((error-thrown (request-response-error-thrown response)) (status-error (plist-get status :error))) (when status-error (request-log 'warn "request--url-retrieve-callback: %s" status-error) (unless error-thrown (setq error-thrown status-error)))) - (apply #'request--callback (current-buffer) settings)) (cl-defun request--url-retrieve-sync (url &rest settings &key type data timeout response &allow-other-keys &aux headers) + "Internal synchronous retrieve of URL. +SETTINGS include typical TYPE DATA TIMEOUT RESPONSE properties. +HEADERS needs to be assigned after SETTINGS is preprocessed." (setq settings (apply #'request--url-retrieve-preprocess-settings settings)) (setq headers (plist-get settings :headers)) (let* ((url-request-extra-headers headers) @@ -852,13 +787,11 @@ associated process is exited." response) (defun request--url-retrieve-get-cookies (host localpart secure) + "Retrieve cookies corresponding to HOST LOCALPART SECURE." (mapcar (lambda (c) (cons (url-cookie-name c) (url-cookie-value c))) (url-cookie-retrieve host localpart secure))) - -;;; Backend: curl - (defvar request--curl-cookie-jar nil "Override what the function `request--curl-cookie-jar' returns. Currently it is used only for testing.") @@ -898,16 +831,17 @@ Currently it is used only for testing.") "\\n(:num-redirects %{num_redirects} :url-effective %{url_effective})" "\\n(:num-redirects %{num_redirects} :url-effective \"%{url_effective}\")")) -(defun request--curl-mkdir-for-cookie-jar () - (ignore-errors - (make-directory (file-name-directory (request--curl-cookie-jar)) t))) - (cl-defun request--curl-command - (url &key type data headers response files* unix-socket encoding auth + (url &key type data headers files unix-socket auth &allow-other-keys &aux (cookie-jar (convert-standard-filename (expand-file-name (request--curl-cookie-jar))))) - "BUG: Simultaneous requests are a known cause of cookie-jar corruption." + "Internal command cobbler for curl to URL. +TYPE, DATA, HEADERS, FILES, UNIX-SOCKET, AUTH are as described in `request'. +COOKIE-JAR is the file location for the netscape cookie jar, usually +in the request subdirectory of `user-emacs-directory'. + +BUG: Simultaneous requests are a known cause of cookie-jar corruption." (append (list request-curl "--silent" "--location" @@ -930,33 +864,34 @@ Currently it is used only for testing.") request-curl-options (when (plist-get (request--curl-capabilities) :compression) (list "--compressed")) (when unix-socket (list "--unix-socket" unix-socket)) - (cl-loop for (name filename path mime-type) in files* + (cl-loop with stdin-p = data + for (name . item) in files collect "--form" - collect (format "%s=@%s;filename=%s%s" name - (request-untrampify-filename path) filename - (if mime-type - (format ";type=%s" mime-type) - ""))) + collect + (apply #'format "%s=@%s;filename=%s%s" + (cond ((stringp item) + (list name item (file-name-nondirectory item) "")) + ((bufferp item) + (if stdin-p + (error (concat "request--curl-command: " + "only one buffer or data entry permitted")) + (setq stdin-p t)) + (list name "-" (buffer-name item) "")) + ((listp item) + (unless (plist-get (cdr item) :file) + (if stdin-p + (error (concat "request--curl-command: " + "only one buffer or data entry permitted")) + (setq stdin-p t))) + (list name (or (plist-get (cdr item) :file) "-") (car item) + (if (plist-get item :mime-type) + (format ";type=%s" (plist-get item :mime-type)) + ""))) + (t (error (concat "request--curl-command: " + "%S not string, buffer, or list") + item))))) (when data - (let ((tempfile (request--make-temp-file))) - (push tempfile (request-response--tempfiles response)) - ;; We dynamic-let the global `buffer-file-coding-system' to `no-conversion' - ;; in case the user-configured `encoding' doesn't fly. - ;; If we do not dynamic-let the global, `select-safe-coding-system' would - ;; plunge us into an undesirable interactive dialogue. - (let ((buffer-file-coding-system-orig - (default-value 'buffer-file-coding-system)) - (select-safe-coding-system-accept-default-p - (lambda (&rest _) t))) - (unwind-protect - (progn - (setf (default-value 'buffer-file-coding-system) 'no-conversion) - (with-temp-file tempfile - (setq-local buffer-file-coding-system encoding) - (insert data))) - (setf (default-value 'buffer-file-coding-system) - buffer-file-coding-system-orig))) - (list "--data-binary" (concat "@" (request-untrampify-filename tempfile))))) + (split-string "--data-binary @-")) (when type (if (equal "head" (downcase type)) (list "--head") (list "--request" type))) @@ -965,83 +900,15 @@ Currently it is used only for testing.") collect (format "%s: %s" k v)) (list url))) -(defun request--curl-normalize-files-1 (files get-temp-file) - (cl-loop for (name . item) in files - collect - (cl-destructuring-bind - (filename &key file buffer data mime-type) - (cond - ((stringp item) (list (file-name-nondirectory item) :file item)) - ((bufferp item) (list (buffer-name item) :buffer item)) - (t item)) - (unless (= (cl-loop for v in (list file buffer data) if v sum 1) 1) - (error "Only one of :file/:buffer/:data must be given. Got: %S" - (cons name item))) - (cond - (file - (list name filename file mime-type)) - (buffer - (let ((tf (funcall get-temp-file))) - (with-current-buffer buffer - (write-region (point-min) (point-max) tf nil 'silent)) - (list name filename tf mime-type))) - (data - (let ((tf (funcall get-temp-file))) - (with-temp-buffer - (erase-buffer) - (insert data) - (write-region (point-min) (point-max) tf nil 'silent)) - (list name filename tf mime-type))))))) - - -(declare-function tramp-get-remote-tmpdir "tramp") -(declare-function tramp-dissect-file-name "tramp") - -(defun request--make-temp-file () - "Create a temporary file." - (if (file-remote-p default-directory) - (let ((temporary-file-directory - (tramp-get-remote-tmpdir (tramp-dissect-file-name default-directory)))) - (make-temp-file request-temp-prefix)) - (make-temp-file request-temp-prefix))) - -(defun request--curl-normalize-files (files) - "Change FILES into a list of (NAME FILENAME PATH MIME-TYPE). -This is to make `request--curl-command' cleaner by converting -FILES to a homogeneous list. It returns a list (FILES* TEMPFILES) -where FILES* is a converted FILES and TEMPFILES is a list of -temporary file paths." - (let (tempfiles noerror) - (unwind-protect - (let* ((get-temp-file (lambda () - (let ((tf (request--make-temp-file))) - (push tf tempfiles) - tf))) - (files* (request--curl-normalize-files-1 files get-temp-file))) - (setq noerror t) - (list files* tempfiles)) - (unless noerror - ;; Remove temporary files only when an error occurs - (request--safe-delete-files tempfiles))))) - -(defun request--safe-delete-files (files) - "Remove FILES but do not raise error when failed to do so." - (mapc (lambda (f) (condition-case err - (delete-file f) - (error (request-log 'error - "request--safe-delete-files: %s %s" - f (error-message-string err))))) - files)) - (defun request--install-timeout (timeout response) - "Out-of-band trigger after TIMEOUT seconds to prevent hangs." + "Out-of-band trigger after TIMEOUT seconds to forestall a hung RESPONSE." (when (numberp timeout) (setf (request-response--timer response) (run-at-time timeout nil #'request-response--timeout-callback response)))) (defun request--curl-occlude-secret (command) - "Simple regex filter on anything looking like a secret." + "Simple regex filter on anything looking like a secret in COMMAND." (let ((matched (string-match (concat (regexp-quote "--user") "\\s-*\\(\\S-+\\)") command))) (if matched @@ -1049,9 +916,19 @@ temporary file paths." command))) (cl-defun request--curl (url &rest settings - &key files timeout response encoding semaphore + &key data files timeout response encoding semaphore &allow-other-keys) - "cURL-based request backend. + "Internal workhorse querying URL via curl. + +SETTINGS is a property list with keys (some optional) such as DATA for +posting fields, FILES containing one or more lists of the form + (NAME . FILENAME) + (NAME . BUFFER) + (NAME . (FILENAME :buffer BUFFER)) + (NAME . (FILENAME :data DATA)) +with NAME and FILENAME defined by curl(1)'s overwrought `--form` switch format, +TIMEOUT in seconds, RESPONSE a mandatory struct, ENCODING, and SEMAPHORE, +an internal semaphore. Redirection handling strategy ----------------------------- @@ -1064,29 +941,57 @@ This number is used for removing extra headers and parse location header from the last redirection header. Sexp at the end of buffer and extra headers for redirects are -removed from the buffer before it is shown to the parser function. -" - (request--curl-mkdir-for-cookie-jar) - (let* (;; Use pipe instead of pty. Otherwise, curl process hangs. - (process-connection-type nil) - ;; Avoid starting program in non-existing directory. +removed from the buffer before it is shown to the parser function." + (ignore-errors + (make-directory (file-name-directory (request--curl-cookie-jar)) t)) + (let* (process-connection-type ;; pipe, not pty, else curl hangs (home-directory (or (file-remote-p default-directory) "~/")) (default-directory (expand-file-name home-directory)) (buffer (generate-new-buffer " *request curl*")) - (command (cl-destructuring-bind - (files* tempfiles) - (request--curl-normalize-files files) - (setf (request-response--tempfiles response) tempfiles) - (apply #'request--curl-command url :files* files* - :response response :encoding encoding settings))) - (proc (apply #'start-process "request curl" buffer command))) + (command (apply #'request--curl-command url settings)) + (proc (apply #'start-process "request curl" buffer command)) + (file-items (mapcar #'cdr files)) + (file-buffer (or (cl-some (lambda (item) + (when (bufferp item) item)) + file-items) + (cl-some (lambda (item) + (and (listp item) + (plist-get (cdr item) :buffer))) + file-items))) + (file-data (cl-some (lambda (item) + (and (listp item) + (plist-get (cdr item) :data))) + file-items))) (request--install-timeout timeout response) (request-log 'debug "request--curl: %s" - (request--curl-occlude-secret (mapconcat 'identity command " "))) + (request--curl-occlude-secret (mapconcat #'identity command " "))) (setf (request-response--buffer response) buffer) (process-put proc :request-response response) (set-process-coding-system proc 'no-conversion 'no-conversion) (set-process-query-on-exit-flag proc nil) + (when (or data file-buffer file-data) + ;; We dynamic-let the global `buffer-file-coding-system' to `no-conversion' + ;; in case the user-configured `encoding' doesn't fly. + ;; If we do not dynamic-let the global, `select-safe-coding-system' would + ;; plunge us into an undesirable interactive dialogue. + (let* ((buffer-file-coding-system-orig + (default-value 'buffer-file-coding-system)) + (select-safe-coding-system-accept-default-p + (lambda (&rest _) t))) + (unwind-protect + (progn + (setf (default-value 'buffer-file-coding-system) 'no-conversion) + (with-temp-buffer + (setq-local buffer-file-coding-system encoding) + (insert (or data + (when file-buffer + (with-current-buffer file-buffer + (buffer-substring-no-properties (point-min) (point-max)))) + file-data)) + (process-send-region proc (point-min) (point-max)) + (process-send-eof proc))) + (setf (default-value 'buffer-file-coding-system) + buffer-file-coding-system-orig)))) (let ((callback-2 (apply-partially #'request--curl-callback url))) (if semaphore (set-process-sentinel proc (lambda (&rest args) @@ -1113,7 +1018,7 @@ See also `request--curl-write-out-template'." "secure" "version" "expires") "\\|") "Uninterested keys in cookie. -See \"set-cookie-av\" in http://www.ietf.org/rfc/rfc2965.txt") +See \"set-cookie-av\" in https://www.ietf.org/rfc/rfc2965.txt") (defun request--consume-100-continue () "Remove \"HTTP/* 100 Continue\" header at the point." @@ -1135,7 +1040,8 @@ See \"set-cookie-av\" in http://www.ietf.org/rfc/rfc2965.txt") (delete-region (point) (progn (request--goto-next-body) (point))))) (defun request--curl-preprocess (&optional url) - "Pre-process current buffer before showing it to user." + "Pre-process current buffer before showing it to user. +Curl switches need to be adjusted if URL is a file://." (let (history) (cl-destructuring-bind (&key num-redirects url-effective) (if (request-url-file-p url) @@ -1185,6 +1091,8 @@ START-URL is the URL requested." do (setf (request-response-url response) url))) (defun request--curl-callback (url proc event) + "Ensure `request--callback' gets called after curl to URL finishes. +See info entries on sentinels regarding PROC and EVENT." (let* ((buffer (process-buffer proc)) (response (process-get proc :request-response)) (settings (request-response-settings response))) @@ -1220,19 +1128,20 @@ START-URL is the URL requested." auto-revert--buffers-by-watch-descriptor (when (boundp 'auto-revert-notify-watch-descriptor-hash-list) auto-revert-notify-watch-descriptor-hash-list)))) - (when desc + (when (and desc table) (let ((buffers (delq (current-buffer) (gethash desc table)))) (if buffers (puthash desc buffers table) (remhash desc table))) (condition-case nil ;; ignore-errors doesn't work for me, sorry - (file-notify-rm-watch desc) + (file-notify-rm-watch desc) (error)) (remove-hook 'kill-buffer-hook #'auto-revert-notify-rm-watch t))) (setq auto-revert-notify-watch-descriptor nil auto-revert-notify-modified-p nil)) (cl-defun request--curl-sync (url &rest settings &key response &allow-other-keys) + "Internal synchronous curl call to URL with SETTINGS bespeaking RESPONSE." (let (finished) (prog1 (apply #'request--curl url :semaphore (lambda (&rest _) (setq finished t)) @@ -1250,7 +1159,7 @@ START-URL is the URL requested." (cl-loop with iter = 0 until (or (>= iter maxiter) finished) do (accept-process-output nil interval) - unless (request--process-live-p proc) + unless (process-live-p proc) do (cl-incf iter) end finally (when (>= iter maxiter) @@ -1259,12 +1168,10 @@ START-URL is the URL requested." (request-log 'error m))))))))) (defun request--curl-get-cookies (host localpart secure) + "Return entry for HOST LOCALPART SECURE in cookie jar." (request--netscape-get-cookies (request--curl-cookie-jar) host localpart secure)) - -;;; Netscape cookie.txt parser - (defun request--netscape-cookie-parse () "Parse Netscape/Mozilla cookie format." (goto-char (point-min)) @@ -1292,6 +1199,7 @@ START-URL is the URL requested." value)))) (defun request--netscape-filter-cookies (cookies host localpart secure) + "Filter COOKIES for entries containing HOST LOCALPART SECURE." (cl-loop for (domain _flag path secure-1 _http-only _expiration name value) in cookies when (and (equal domain host) (equal path localpart) @@ -1299,6 +1207,7 @@ START-URL is the URL requested." collect (cons name value))) (defun request--netscape-get-cookies (filename host localpart secure) + "Get cookies from FILENAME corresponding to HOST LOCALPART SECURE." (when (file-readable-p filename) (with-temp-buffer (erase-buffer) diff --git a/elpa/ssh-config-mode-20210123.1051/ssh-config-keywords.txt b/elpa/ssh-config-mode-20210217.1051/ssh-config-keywords.txt similarity index 97% rename from elpa/ssh-config-mode-20210123.1051/ssh-config-keywords.txt rename to elpa/ssh-config-mode-20210217.1051/ssh-config-keywords.txt index 5d603a3..1360ed6 100644 --- a/elpa/ssh-config-mode-20210123.1051/ssh-config-keywords.txt +++ b/elpa/ssh-config-mode-20210217.1051/ssh-config-keywords.txt @@ -39,8 +39,8 @@ HashKnownHosts Host HostKeyAlgorithms HostKeyAlias +HostbasedAcceptedAlgorithms HostbasedAuthentication -HostbasedKeyTypes Hostname IPQoS IdentitiesOnly @@ -66,6 +66,7 @@ NumberOfPasswordPrompts PKCS11Provider PasswordAuthentication PermitLocalCommand +PermitRemoteOpen Port PreferredAuthentications ProxyCommand diff --git a/elpa/ssh-config-mode-20210123.1051/ssh-config-mode-autoloads.el b/elpa/ssh-config-mode-20210217.1051/ssh-config-mode-autoloads.el similarity index 100% rename from elpa/ssh-config-mode-20210123.1051/ssh-config-mode-autoloads.el rename to elpa/ssh-config-mode-20210217.1051/ssh-config-mode-autoloads.el diff --git a/elpa/ssh-config-mode-20210123.1051/ssh-config-mode-pkg.el b/elpa/ssh-config-mode-20210217.1051/ssh-config-mode-pkg.el similarity index 61% rename from elpa/ssh-config-mode-20210123.1051/ssh-config-mode-pkg.el rename to elpa/ssh-config-mode-20210217.1051/ssh-config-mode-pkg.el index 76b1ac8..52ae2a8 100644 --- a/elpa/ssh-config-mode-20210123.1051/ssh-config-mode-pkg.el +++ b/elpa/ssh-config-mode-20210217.1051/ssh-config-mode-pkg.el @@ -1,4 +1,4 @@ -(define-package "ssh-config-mode" "20210123.1051" "Mode for fontification of ~/.ssh/config" 'nil :commit "3639241d0e435e622049e6e72866da6b8b201241" :authors +(define-package "ssh-config-mode" "20210217.1051" "Mode for fontification of ~/.ssh/config" 'nil :commit "820f60af17e71898303f4f3c2576f0619528a492" :authors '(("Harley Gorrell" . "harley@panix.com")) :maintainer '("Harley Gorrell" . "harley@panix.com") diff --git a/elpa/ssh-config-mode-20210123.1051/ssh-config-mode.el b/elpa/ssh-config-mode-20210217.1051/ssh-config-mode.el similarity index 100% rename from elpa/ssh-config-mode-20210123.1051/ssh-config-mode.el rename to elpa/ssh-config-mode-20210217.1051/ssh-config-mode.el