branch: externals/m-buffer
commit 8210f4147d329c30727f2f54dcd8f06e881b74e3
Author: Phillip Lord <[email protected]>
Commit: Phillip Lord <[email protected]>
Move dev to test.
Added Makefile
Added travis.
---
.travis.yml | 20 +
Makefile | 10 +
run-tests.sh | 3 +
test/dash.el | 1412 ++++++++++++++++++++++++++++++++++
test/line-start.txt | 6 +
{dev => test}/m-buffer-test.el | 90 ++-
{dev => test}/match-data.txt | 0
dev/.nosearch => test/test-helper.el | 0
{dev => test}/with-temp-buffer.txt | 0
9 files changed, 1517 insertions(+), 24 deletions(-)
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..463cf9dc83
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,20 @@
+language: emacs-lisp
+before_install:
+ - if [ "$EMACS" = 'emacs-snapshot' ]; then
+ sudo add-apt-repository -y ppa:cassou/emacs &&
+ sudo apt-get update -qq &&
+ sudo apt-get install -qq
+ emacs-snapshot-el emacs-snapshot-gtk emacs-snapshot;
+ fi
+ - if [ "$EMACS" = 'emacs24' ]; then
+ sudo add-apt-repository -y ppa:cassou/emacs &&
+ sudo apt-get update -qq &&
+ sudo apt-get install -qq
+ emacs24 emacs24-el emacs24-common-non-dfsg;
+ fi
+env:
+ - EMACS=emacs
+ - EMACS=emacs24
+ - EMACS=emacs-snapshot
+script:
+ ./run-tests.sh
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..b75accb842
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+EMACS ?= emacs
+CASK ?= cask
+
+all: test
+
+test:
+ ./run-tests.sh
+
+
+.PHONY: test
diff --git a/run-tests.sh b/run-tests.sh
new file mode 100755
index 0000000000..74441aad5c
--- /dev/null
+++ b/run-tests.sh
@@ -0,0 +1,3 @@
+## run in subdir because test files there there
+emacs -batch -l ./test/dash.el -l m-buffer.el -l ./test/m-buffer-test.el \
+ -f ert-run-tests-batch-and-exit
diff --git a/test/dash.el b/test/dash.el
new file mode 100644
index 0000000000..4d4ef4ea0d
--- /dev/null
+++ b/test/dash.el
@@ -0,0 +1,1412 @@
+;;; dash.el --- A modern list library for Emacs
+
+;; Copyright (C) 2012 Magnar Sveen
+
+;; Author: Magnar Sveen <[email protected]>
+;; Version: 2.5.0
+;; Keywords: lists
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A modern list api for Emacs.
+;;
+;; See documentation on https://github.com/magnars/dash.el#functions
+
+;;; Code:
+
+(defgroup dash ()
+ "Customize group for dash.el"
+ :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: Sets CDR to the cons of CAR and CDR."
+ `(setq ,cdr (cons ,car ,cdr)))
+
+(defmacro !cdr (list)
+ "Destructive: Sets LIST to the cdr of LIST."
+ `(setq ,list (cdr ,list)))
+
+(defmacro --each (list &rest body)
+ "Anaphoric form of `-each'."
+ (declare (debug (form body))
+ (indent 1))
+ (let ((l (make-symbol "list")))
+ `(let ((,l ,list)
+ (it-index 0))
+ (while ,l
+ (let ((it (car ,l)))
+ ,@body)
+ (setq it-index (1+ it-index))
+ (!cdr ,l)))))
+
+(defun -each (list fn)
+ "Calls FN with every item in LIST. Returns nil, used for side-effects only."
+ (--each list (funcall fn it)))
+
+(put '-each 'lisp-indent-function 1)
+
+(defmacro --each-while (list pred &rest body)
+ "Anaphoric form of `-each-while'."
+ (declare (debug (form sexp body))
+ (indent 2))
+ (let ((l (make-symbol "list"))
+ (c (make-symbol "continue")))
+ `(let ((,l ,list)
+ (,c t))
+ (while (and ,l ,c)
+ (let ((it (car ,l)))
+ (if (not ,pred) (setq ,c nil) ,@body))
+ (!cdr ,l)))))
+
+(defun -each-while (list pred fn)
+ "Calls FN with every item in LIST while (PRED item) is non-nil.
+Returns nil, used for side-effects only."
+ (--each-while list (funcall pred it) (funcall fn it)))
+
+(put '-each-while 'lisp-indent-function 2)
+
+(defmacro --dotimes (num &rest body)
+ "Repeatedly executes BODY (presumably for side-effects) with `it` bound to
integers from 0 through n-1."
+ (declare (debug (integerp body))
+ (indent 1))
+ `(let ((it 0))
+ (while (< it ,num)
+ ,@body
+ (setq it (1+ it)))))
+
+(defun -dotimes (num fn)
+ "Repeatedly calls FN (presumably for side-effects) passing in integers from
0 through n-1."
+ (--dotimes num (funcall fn it)))
+
+(put '-dotimes 'lisp-indent-function 1)
+
+(defun -map (fn list)
+ "Returns a new list consisting of the result of applying FN to the items in
LIST."
+ (mapcar fn list))
+
+(defmacro --map (form list)
+ "Anaphoric form of `-map'."
+ (declare (debug (sexp form)))
+ `(mapcar (lambda (it) ,form) ,list))
+
+(defmacro --reduce-from (form initial-value list)
+ "Anaphoric form of `-reduce-from'."
+ (declare (debug (sexp form form)))
+ `(let ((acc ,initial-value))
+ (--each ,list (setq acc ,form))
+ acc))
+
+(defun -reduce-from (fn initial-value list)
+ "Returns 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, returns INITIAL-VALUE and
+FN is not called.
+
+In the anaphoric form `--reduce-from', the accumulated value is
+exposed as `acc`."
+ (--reduce-from (funcall fn acc it) initial-value list))
+
+(defmacro --reduce (form list)
+ "Anaphoric form of `-reduce'."
+ (declare (debug (sexp form)))
+ (let ((lv (make-symbol "list-value")))
+ `(let ((,lv ,list))
+ (if ,lv
+ (--reduce-from ,form (car ,lv) (cdr ,lv))
+ (let (acc it) ,form)))))
+
+(defun -reduce (fn list)
+ "Returns 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, FN must accept no arguments as well, and
+reduce returns the result of calling FN with no arguments. If
+LIST has only 1 item, it is returned and FN is not called.
+
+In the anaphoric form `--reduce', the accumulated value is
+exposed as `acc`."
+ (if list
+ (-reduce-from fn (car list) (cdr list))
+ (funcall 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.
+
+Note: this function works the same as `-reduce-from' but the
+operation associates from right instead of from left."
+ (if (not list) initial-value
+ (funcall fn (car list) (-reduce-r-from fn initial-value (cdr list)))))
+
+(defmacro --reduce-r-from (form initial-value list)
+ "Anaphoric version of `-reduce-r-from'."
+ (declare (debug (sexp form form)))
+ `(-reduce-r-from (lambda (&optional it acc) ,form) ,initial-value ,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, FN must
+accept no arguments as well, and reduce returns the result of
+calling FN with no arguments. If LIST has only 1 item, it is
+returned and FN is not called.
+
+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."
+ (cond
+ ((not list) (funcall fn))
+ ((not (cdr list)) (car list))
+ (t (funcall fn (car list) (-reduce-r fn (cdr list))))))
+
+(defmacro --reduce-r (form list)
+ "Anaphoric version of `-reduce-r'."
+ (declare (debug (sexp form)))
+ `(-reduce-r (lambda (&optional it acc) ,form) ,list))
+
+(defmacro --filter (form list)
+ "Anaphoric form of `-filter'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each ,list (when ,form (!cons it ,r)))
+ (nreverse ,r))))
+
+(defun -filter (pred list)
+ "Returns a new list of the items in LIST for which PRED returns a non-nil
value.
+
+Alias: `-select'"
+ (--filter (funcall pred it) list))
+
+(defalias '-select '-filter)
+(defalias '--select '--filter)
+
+(defmacro --remove (form list)
+ "Anaphoric form of `-remove'."
+ (declare (debug (sexp form)))
+ `(--filter (not ,form) ,list))
+
+(defun -remove (pred list)
+ "Returns a new list of the items in LIST for which PRED returns nil.
+
+Alias: `-reject'"
+ (--remove (funcall pred it) list))
+
+(defalias '-reject '-remove)
+(defalias '--reject '--remove)
+
+(defmacro --keep (form list)
+ "Anaphoric form of `-keep'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result"))
+ (m (make-symbol "mapped")))
+ `(let (,r)
+ (--each ,list (let ((,m ,form)) (when ,m (!cons ,m ,r))))
+ (nreverse ,r))))
+
+(defun -keep (fn list)
+ "Returns a new list of the non-nil results of applying FN to the items in
LIST."
+ (--keep (funcall fn it) list))
+
+(defmacro --map-when (pred rep list)
+ "Anaphoric form of `-map-when'."
+ (declare (debug (sexp sexp form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each ,list (!cons (if ,pred ,rep it) ,r))
+ (nreverse ,r))))
+
+(defmacro --map-indexed (form list)
+ "Anaphoric form of `-map-indexed'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each ,list
+ (!cons ,form ,r))
+ (nreverse ,r))))
+
+(defun -map-indexed (fn list)
+ "Returns 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 `it-index`."
+ (--map-indexed (funcall fn it-index it) list))
+
+(defun -map-when (pred rep list)
+ "Returns a new list where the elements in LIST that does 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."
+ (--map-when (funcall pred it) (funcall rep it) list))
+
+(defalias '--replace-where '--map-when)
+(defalias '-replace-where '-map-when)
+
+(defun -flatten (l)
+ "Takes a nested list L and returns its contents as a single, flat list."
+ (if (and (listp l) (listp (cdr l)))
+ (-mapcat '-flatten l)
+ (list l)))
+
+(defun -concat (&rest lists)
+ "Returns a new list with the concatenation of the elements in the supplied
LISTS."
+ (apply 'append lists))
+
+(defmacro --mapcat (form list)
+ "Anaphoric form of `-mapcat'."
+ (declare (debug (sexp form)))
+ `(apply 'append (--map ,form ,list)))
+
+(defun -mapcat (fn list)
+ "Returns the concatenation of the result of mapping FN over LIST.
+Thus function FN should return a list."
+ (--mapcat (funcall fn it) list))
+
+(defun -cons* (&rest args)
+ "Makes 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."
+ (-reduce-r 'cons args))
+
+(defun -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."
+ (-concat list (list elem) elements))
+
+(defmacro --first (form list)
+ "Anaphoric form of `-first'."
+ (declare (debug (sexp form)))
+ (let ((n (make-symbol "needle")))
+ `(let (,n)
+ (--each-while ,list (not ,n)
+ (when ,form (setq ,n it)))
+ ,n)))
+
+(defun -first (pred list)
+ "Returns 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'."
+ (--first (funcall pred it) list))
+
+(defmacro --last (form list)
+ "Anaphoric form of `-last'."
+ (declare (debug (sexp form)))
+ (let ((n (make-symbol "needle")))
+ `(let (,n)
+ (--each ,list
+ (when ,form (setq ,n it)))
+ ,n)))
+
+(defun -last (pred list)
+ "Return the last x in LIST where (PRED x) is non-nil, else nil."
+ (--last (funcall pred it) list))
+
+(defalias '-first-item 'car
+ "Returns the first item of LIST, or nil on an empty list.")
+
+(defun -last-item (list)
+ "Returns the first item of LIST, or nil on an empty list."
+ (car (last list)))
+
+(defmacro --count (pred list)
+ "Anaphoric form of `-count'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result")))
+ `(let ((,r 0))
+ (--each ,list (when ,pred (setq ,r (1+ ,r))))
+ ,r)))
+
+(defun -count (pred list)
+ "Counts the number of items in LIST where (PRED item) is non-nil."
+ (--count (funcall pred it) list))
+
+(defun ---truthy? (val)
+ (not (null val)))
+
+(defmacro --any? (form list)
+ "Anaphoric form of `-any?'."
+ (declare (debug (sexp form)))
+ `(---truthy? (--first ,form ,list)))
+
+(defun -any? (pred list)
+ "Returns t if (PRED x) is non-nil for any x in LIST, else nil.
+
+Alias: `-some?'"
+ (--any? (funcall pred it) list))
+
+(defalias '-some? '-any?)
+(defalias '--some? '--any?)
+
+(defalias '-any-p '-any?)
+(defalias '--any-p '--any?)
+(defalias '-some-p '-any?)
+(defalias '--some-p '--any?)
+
+(defmacro --all? (form list)
+ "Anaphoric form of `-all?'."
+ (declare (debug (sexp form)))
+ (let ((a (make-symbol "all")))
+ `(let ((,a t))
+ (--each-while ,list ,a (setq ,a ,form))
+ (---truthy? ,a))))
+
+(defun -all? (pred list)
+ "Returns t if (PRED x) is non-nil for all x in LIST, else nil.
+
+Alias: `-every?'"
+ (--all? (funcall pred it) list))
+
+(defalias '-every? '-all?)
+(defalias '--every? '--all?)
+
+(defalias '-all-p '-all?)
+(defalias '--all-p '--all?)
+(defalias '-every-p '-all?)
+(defalias '--every-p '--all?)
+
+(defmacro --none? (form list)
+ "Anaphoric form of `-none?'."
+ (declare (debug (sexp form)))
+ `(--all? (not ,form) ,list))
+
+(defun -none? (pred list)
+ "Returns t if (PRED x) is nil for all x in LIST, else nil."
+ (--none? (funcall pred it) list))
+
+(defalias '-none-p '-none?)
+(defalias '--none-p '--none?)
+
+(defmacro --only-some? (form list)
+ "Anaphoric form of `-only-some?'."
+ (declare (debug (sexp form)))
+ (let ((y (make-symbol "yes"))
+ (n (make-symbol "no")))
+ `(let (,y ,n)
+ (--each-while ,list (not (and ,y ,n))
+ (if ,form (setq ,y t) (setq ,n t)))
+ (---truthy? (and ,y ,n)))))
+
+(defun -only-some? (pred list)
+ "Returns `t` if there is a mix of items in LIST that matches and does not
match PRED.
+Returns `nil` both if all items match the predicate, and if none of the items
match the predicate."
+ (--only-some? (funcall pred it) list))
+
+(defalias '-only-some-p '-only-some?)
+(defalias '--only-some-p '--only-some?)
+
+(defun -slice (list from &optional to)
+ "Return copy of LIST, starting from index FROM to index TO.
+FROM or TO may be negative."
+ (let ((length (length list))
+ (new-list nil)
+ (index 0))
+ ;; to defaults to the end of the list
+ (setq to (or to length))
+ ;; handle negative indices
+ (when (< from 0)
+ (setq from (mod from length)))
+ (when (< to 0)
+ (setq to (mod to length)))
+
+ ;; iterate through the list, keeping the elements we want
+ (while (< index to)
+ (when (>= index from)
+ (!cons (car list) new-list))
+ (!cdr list)
+ (setq index (1+ index)))
+ (nreverse new-list)))
+
+(defun -take (n list)
+ "Returns a new list of the first N items in LIST, or all items if there are
fewer than N."
+ (let (result)
+ (--dotimes n
+ (when list
+ (!cons (car list) result)
+ (!cdr list)))
+ (nreverse result)))
+
+(defun -drop (n list)
+ "Returns the tail of LIST without the first N items."
+ (--dotimes n (!cdr list))
+ list)
+
+(defmacro --take-while (form list)
+ "Anaphoric form of `-take-while'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result")))
+ `(let (,r)
+ (--each-while ,list ,form (!cons it ,r))
+ (nreverse ,r))))
+
+(defun -take-while (pred list)
+ "Returns a new list of successive items from LIST while (PRED item) returns
a non-nil value."
+ (--take-while (funcall pred it) list))
+
+(defmacro --drop-while (form list)
+ "Anaphoric form of `-drop-while'."
+ (declare (debug (sexp form)))
+ (let ((l (make-symbol "list")))
+ `(let ((,l ,list))
+ (while (and ,l (let ((it (car ,l))) ,form))
+ (!cdr ,l))
+ ,l)))
+
+(defun -drop-while (pred list)
+ "Returns the tail of LIST starting from the first item for which (PRED item)
returns nil."
+ (--drop-while (funcall pred it) list))
+
+(defun -split-at (n list)
+ "Returns a list of ((-take N LIST) (-drop N LIST)), in no more than one pass
through the list."
+ (let (result)
+ (--dotimes n
+ (when list
+ (!cons (car list) result)
+ (!cdr list)))
+ (list (nreverse result) list)))
+
+(defun -rotate (n list)
+ "Rotate LIST N places to the right. With N negative, rotate to the left.
+The time complexity is O(n)."
+ (if (> n 0)
+ (append (last list n) (butlast list n))
+ (append (-drop (- n) list) (-take (- n) list))))
+
+(defun -insert-at (n x list)
+ "Returns a list with X inserted into LIST at position N."
+ (let ((split-list (-split-at n list)))
+ (nconc (car split-list) (cons x (cadr split-list)))))
+
+(defun -replace-at (n x list)
+ "Return a list with element at Nth position in LIST replaced with X."
+ (let ((split-list (-split-at n list)))
+ (nconc (car split-list) (cons x (cdr (cadr split-list))))))
+
+(defun -update-at (n func list)
+ "Return a list with element at Nth position in LIST replaced with `(func
(nth n list))`."
+ (let ((split-list (-split-at n list)))
+ (nconc (car split-list) (cons (funcall func (car (cadr split-list))) (cdr
(cadr split-list))))))
+
+(defmacro --update-at (n form list)
+ "Anaphoric version of `-update-at'."
+ (declare (debug (integerp sexp form)))
+ `(-update-at ,n (lambda (it) ,form) ,list))
+
+(defun -remove-at (n list)
+ "Return a list with element at Nth position in LIST removed."
+ (-remove-at-indices (list n) list))
+
+(defun -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."
+ (let* ((indices (-sort '< indices))
+ (diffs (cons (car indices) (-map '1- (-zip-with '- (cdr indices)
indices))))
+ r)
+ (--each diffs
+ (let ((split (-split-at it list)))
+ (!cons (car split) r)
+ (setq list (cdr (cadr split)))))
+ (!cons list r)
+ (apply '-concat (nreverse r))))
+
+(defmacro --split-with (pred list)
+ "Anaphoric form of `-split-with'."
+ (declare (debug (sexp form)))
+ (let ((l (make-symbol "list"))
+ (r (make-symbol "result"))
+ (c (make-symbol "continue")))
+ `(let ((,l ,list)
+ (,r nil)
+ (,c t))
+ (while (and ,l ,c)
+ (let ((it (car ,l)))
+ (if (not ,pred)
+ (setq ,c nil)
+ (!cons it ,r)
+ (!cdr ,l))))
+ (list (nreverse ,r) ,l))))
+
+(defun -split-with (pred list)
+ "Returns a list of ((-take-while PRED LIST) (-drop-while PRED LIST)), in no
more than one pass through the list."
+ (--split-with (funcall pred it) list))
+
+(defmacro --separate (form list)
+ "Anaphoric form of `-separate'."
+ (declare (debug (sexp form)))
+ (let ((y (make-symbol "yes"))
+ (n (make-symbol "no")))
+ `(let (,y ,n)
+ (--each ,list (if ,form (!cons it ,y) (!cons it ,n)))
+ (list (nreverse ,y) (nreverse ,n)))))
+
+(defun -separate (pred list)
+ "Returns 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."
+ (when (< step 1)
+ (error "Step must be a positive number, or you're looking at some juicy
infinite loops."))
+ (let ((result nil)
+ (len 0))
+ (while list
+ (!cons (-take n list) result)
+ (setq list (-drop step list)))
+ result))
+
+(defun -partition-all-in-steps (n step list)
+ "Returns 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."
+ (nreverse (---partition-all-in-steps-reversed n step list)))
+
+(defun -partition-in-steps (n step list)
+ "Returns 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."
+ (let ((result (---partition-all-in-steps-reversed n step list)))
+ (while (and result (< (length (car result)) n))
+ (!cdr result))
+ (nreverse result)))
+
+(defun -partition-all (n list)
+ "Returns a new list with the items in LIST grouped into N-sized sublists.
+The last group may contain less than N items."
+ (-partition-all-in-steps n n list))
+
+(defun -partition (n list)
+ "Returns 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-in-steps n n list))
+
+(defmacro --partition-by (form list)
+ "Anaphoric form of `-partition-by'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result"))
+ (s (make-symbol "sublist"))
+ (v (make-symbol "value"))
+ (n (make-symbol "new-value"))
+ (l (make-symbol "list")))
+ `(let ((,l ,list))
+ (when ,l
+ (let* ((,r nil)
+ (it (car ,l))
+ (,s (list it))
+ (,v ,form)
+ (,l (cdr ,l)))
+ (while ,l
+ (let* ((it (car ,l))
+ (,n ,form))
+ (unless (equal ,v ,n)
+ (!cons (nreverse ,s) ,r)
+ (setq ,s nil)
+ (setq ,v ,n))
+ (!cons it ,s)
+ (!cdr ,l)))
+ (!cons (nreverse ,s) ,r)
+ (nreverse ,r))))))
+
+(defun -partition-by (fn list)
+ "Applies FN to each item in LIST, splitting it each time FN returns a new
value."
+ (--partition-by (funcall fn it) list))
+
+(defmacro --partition-by-header (form list)
+ "Anaphoric form of `-partition-by-header'."
+ (declare (debug (sexp form)))
+ (let ((r (make-symbol "result"))
+ (s (make-symbol "sublist"))
+ (h (make-symbol "header-value"))
+ (b (make-symbol "seen-body?"))
+ (n (make-symbol "new-value"))
+ (l (make-symbol "list")))
+ `(let ((,l ,list))
+ (when ,l
+ (let* ((,r nil)
+ (it (car ,l))
+ (,s (list it))
+ (,h ,form)
+ (,b nil)
+ (,l (cdr ,l)))
+ (while ,l
+ (let* ((it (car ,l))
+ (,n ,form))
+ (if (equal ,h ,n)
+ (when ,b
+ (!cons (nreverse ,s) ,r)
+ (setq ,s nil)
+ (setq ,b nil))
+ (setq ,b t))
+ (!cons it ,s)
+ (!cdr ,l)))
+ (!cons (nreverse ,s) ,r)
+ (nreverse ,r))))))
+
+(defun -partition-by-header (fn list)
+ "Applies FN to the first item in LIST. That is the header
+ value. Applies 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 (funcall fn it) list))
+
+(defmacro --group-by (form list)
+ "Anaphoric form of `-group-by'."
+ (declare (debug (sexp form)))
+ (let ((l (make-symbol "list"))
+ (v (make-symbol "value"))
+ (k (make-symbol "key"))
+ (r (make-symbol "result")))
+ `(let ((,l ,list)
+ ,r)
+ ;; Convert `list' to an alist and store it in `r'.
+ (while ,l
+ (let* ((,v (car ,l))
+ (it ,v)
+ (,k ,form)
+ (kv (assoc ,k ,r)))
+ (if kv
+ (setcdr kv (cons ,v (cdr kv)))
+ (push (list ,k ,v) ,r))
+ (setq ,l (cdr ,l))))
+ ;; Reverse lists in each group.
+ (let ((rest ,r))
+ (while rest
+ (let ((kv (car rest)))
+ (setcdr kv (nreverse (cdr kv))))
+ (setq rest (cdr rest))))
+ ;; Reverse order of keys.
+ (nreverse ,r))))
+
+(defun -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 (funcall fn it) list))
+
+(defun -interpose (sep list)
+ "Returns a new list of all elements in LIST separated by SEP."
+ (let (result)
+ (when list
+ (!cons (car list) result)
+ (!cdr list))
+ (while list
+ (setq result (cons (car list) (cons sep result)))
+ (!cdr list))
+ (nreverse result)))
+
+(defun -interleave (&rest lists)
+ "Returns a new list of the first item in each list, then the second etc."
+ (let (result)
+ (while (-none? 'null lists)
+ (--each lists (!cons (car it) result))
+ (setq lists (-map 'cdr lists)))
+ (nreverse result)))
+
+(defmacro --zip-with (form list1 list2)
+ "Anaphoric form of `-zip-with'.
+
+The elements in list1 is bound as `it`, the elements in list2 as `other`."
+ (declare (debug (sexp form form)))
+ (let ((r (make-symbol "result"))
+ (l1 (make-symbol "list1"))
+ (l2 (make-symbol "list2")))
+ `(let ((,r nil)
+ (,l1 ,list1)
+ (,l2 ,list2))
+ (while (and ,l1 ,l2)
+ (let ((it (car ,l1))
+ (other (car ,l2)))
+ (!cons ,form ,r)
+ (!cdr ,l1)
+ (!cdr ,l2)))
+ (nreverse ,r))))
+
+(defun -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 `it`,
+and the elements from LIST2 as `other`."
+ (--zip-with (funcall fn it other) list1 list2))
+
+(defun -zip (list1 list2)
+ "Zip the two lists together. Return the list where elements
+are cons pairs with car being element from LIST1 and cdr being
+element from LIST2. The length of the returned list is the
+length of the shorter one."
+ (-zip-with 'cons list1 list2))
+
+(defun -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."
+ (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
+such element."
+ (car (-elem-indices elem list)))
+
+(defun -elem-indices (elem list)
+ "Return the indices of all elements in LIST equal to the query
+element ELEM, in ascending order."
+ (-find-indices (-partial 'equal elem) list))
+
+(defun -find-indices (pred list)
+ "Return the indices of all elements in LIST satisfying the
+predicate PRED, in ascending order."
+ (let ((i 0))
+ (apply 'append (--map-indexed (when (funcall pred it) (list it-index))
list))))
+
+(defmacro --find-indices (form list)
+ "Anaphoric version of `-find-indices'."
+ (declare (debug (sexp form)))
+ `(-find-indices (lambda (it) ,form) ,list))
+
+(defun -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."
+ (car (-find-indices pred list)))
+
+(defmacro --find-index (form list)
+ "Anaphoric version of `-find-index'."
+ (declare (debug (sexp form)))
+ `(-find-index (lambda (it) ,form) ,list))
+
+(defun -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."
+ (-last-item (-find-indices pred list)))
+
+(defmacro --find-last-index (form list)
+ "Anaphoric version of `-find-last-index'."
+ `(-find-last-index (lambda (it) ,form) ,list))
+
+(defun -select-by-indices (indices list)
+ "Return a list whose elements are elements from LIST selected
+as `(nth i list)` for all i from INDICES."
+ (let (r)
+ (--each indices
+ (!cons (nth it list) r))
+ (nreverse r)))
+
+(defmacro -> (x &optional form &rest more)
+ "Threads the expr through the forms. Inserts 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, inserts the first form as the
+second item in second form, etc."
+ (cond
+ ((null form) x)
+ ((null more) (if (listp form)
+ `(,(car form) ,x ,@(cdr form))
+ (list form x)))
+ (:else `(-> (-> ,x ,form) ,@more))))
+
+(defmacro ->> (x form &rest more)
+ "Threads the expr through the forms. Inserts 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, inserts the first form as the
+last item in second form, etc."
+ (if (null more)
+ (if (listp form)
+ `(,(car form) ,@(cdr form) ,x)
+ (list form x))
+ `(->> (->> ,x ,form) ,@more)))
+
+(defmacro --> (x form &rest more)
+ "Threads the expr through the forms. Inserts X at the position
+signified by the token `it' in the first form. If there are more
+forms, inserts the first form at the position signified by `it'
+in in second form, etc."
+ (if (null more)
+ (if (listp form)
+ (--map-when (eq it 'it) x form)
+ (list form x))
+ `(--> (--> ,x ,form) ,@more)))
+
+(put '-> 'lisp-indent-function 1)
+(put '->> 'lisp-indent-function 1)
+(put '--> 'lisp-indent-function 1)
+
+(defun -grade-up (comparator list)
+ "Grades 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))))
+
+(defun -grade-down (comparator list)
+ "Grades 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))))
+
+(defmacro -when-let (var-val &rest body)
+ "If VAL evaluates to non-nil, bind it to VAR and execute body.
+VAR-VAL should be a (VAR VAL) pair."
+ (declare (debug ((symbolp form) body))
+ (indent 1))
+ (let ((var (car var-val))
+ (val (cadr var-val)))
+ `(let ((,var ,val))
+ (when ,var
+ ,@body))))
+
+(defmacro -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 (corresponding to bindings of `let*')."
+ (declare (debug ((&rest (symbolp form)) body))
+ (indent 1))
+ (if (= (length vars-vals) 1)
+ `(-when-let ,(car vars-vals)
+ ,@body)
+ `(-when-let ,(car vars-vals)
+ (-when-let* ,(cdr vars-vals)
+ ,@body))))
+
+(defmacro --when-let (val &rest body)
+ "If VAL evaluates to non-nil, bind it to `it' and execute
+body."
+ (declare (debug (form body))
+ (indent 1))
+ `(let ((it ,val))
+ (when it
+ ,@body)))
+
+(defmacro -if-let (var-val then &rest else)
+ "If VAL evaluates to non-nil, bind it to VAR and do THEN,
+otherwise do ELSE. VAR-VAL should be a (VAR VAL) pair."
+ (declare (debug ((symbolp form) form body))
+ (indent 2))
+ (let ((var (car var-val))
+ (val (cadr var-val)))
+ `(let ((,var ,val))
+ (if ,var ,then ,@else))))
+
+(defmacro -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 (corresponding to the bindings of `let*')."
+ (declare (debug ((&rest (symbolp form)) form body))
+ (indent 2))
+ (let ((first-pair (car vars-vals))
+ (rest (cdr vars-vals)))
+ (if (= (length vars-vals) 1)
+ `(-if-let ,first-pair ,then ,@else)
+ `(-if-let ,first-pair
+ (-if-let* ,rest ,then ,@else)
+ ,@else))))
+
+(defmacro --if-let (val then &rest else)
+ "If VAL evaluates to non-nil, bind it to `it' and do THEN,
+otherwise do ELSE."
+ (declare (debug (form form body))
+ (indent 2))
+ `(let ((it ,val))
+ (if it ,then ,@else)))
+
+(defun -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'"
+ (let (result)
+ (--each list (unless (-contains? result it) (!cons it result)))
+ (nreverse result)))
+
+(defun -union (list list2)
+ "Return a new list containing the elements of LIST1 and elements of LIST2
that are not in LIST1.
+The test for equality is done with `equal',
+or with `-compare-fn' if that's non-nil."
+ (let (result)
+ (--each list (!cons it result))
+ (--each list2 (unless (-contains? result it) (!cons it result)))
+ (nreverse result)))
+
+(defalias '-uniq '-distinct)
+
+(defun -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."
+ (--filter (-contains? list2 it) list))
+
+(defun -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."
+ (--filter (not (-contains? list2 it)) list))
+
+(defvar -compare-fn nil
+ "Tests for equality use this function or `equal' if this is nil.
+It should only be set using dynamic scope with a let, like:
+(let ((-compare-fn =)) (-union numbers1 numbers2 numbers3)")
+
+(defun -contains? (list element)
+ "Return whether LIST contains ELEMENT.
+The test for equality is done with `equal',
+or with `-compare-fn' if that's non-nil."
+ (not
+ (null
+ (cond
+ ((null -compare-fn) (member element list))
+ ((eq -compare-fn 'eq) (memq element list))
+ ((eq -compare-fn 'eql) (memql element list))
+ (t
+ (let ((lst list))
+ (while (and lst
+ (not (funcall -compare-fn element (car lst))))
+ (setq lst (cdr lst)))
+ lst))))))
+
+(defalias '-contains-p '-contains?)
+
+(defun -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."
+ (let ((length-a (length list))
+ (length-b (length list2)))
+ (and
+ (= length-a length-b)
+ (= length-a (length (-intersection list list2))))))
+
+(defalias '-same-items-p '-same-items?)
+
+(defun -sort (comparator list)
+ "Sort LIST, stably, comparing elements using COMPARATOR.
+Returns 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 (copy-sequence list) comparator))
+
+(defmacro --sort (form list)
+ "Anaphoric form of `-sort'."
+ (declare (debug (sexp form)))
+ `(-sort (lambda (it other) ,form) ,list))
+
+(defun -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."
+ (let ((arg (car args)))
+ (if (listp arg) arg args)))
+
+(defun -repeat (n x)
+ "Return a list with X repeated N times.
+Returns nil if N is less than 1."
+ (let (ret)
+ (--dotimes n (!cons x ret))
+ ret))
+
+(defun -sum (list)
+ "Return the sum of LIST."
+ (apply '+ list))
+
+(defun -product (list)
+ "Return the product of LIST."
+ (apply '* list))
+
+(defun -max (list)
+ "Return the largest value from LIST of numbers or markers."
+ (apply 'max list))
+
+(defun -min (list)
+ "Return the smallest value from LIST of numbers or markers."
+ (apply 'min list))
+
+(defun -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' which can transform the values before
+comparing them."
+ (--reduce (if (funcall comparator it acc) it acc) list))
+
+(defun -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' which can transform the values before
+comparing them."
+ (--reduce (if (funcall comparator it acc) acc it) list))
+
+(defmacro --max-by (form list)
+ "Anaphoric version of `-max-by'.
+
+The items for the comparator form are exposed as \"it\" and \"other\"."
+ (declare (debug (sexp form)))
+ `(-max-by (lambda (it other) ,form) ,list))
+
+(defmacro --min-by (form list)
+ "Anaphoric version of `-min-by'.
+
+The items for the comparator form are exposed as \"it\" and \"other\"."
+ (declare (debug (sexp form)))
+ `(-min-by (lambda (it other) ,form) ,list))
+
+(defun -cons-pair? (con)
+ "Return non-nil if CON is true cons pair.
+That is (A . B) where B is not a list."
+ (and (listp con)
+ (not (listp (cdr con)))))
+
+(defun -cons-to-list (con)
+ "Convert a cons pair to a list with `car' and `cdr' of the pair
respectively."
+ (list (car con) (cdr con)))
+
+(defun -value-to-list (val)
+ "Convert a value to a list.
+
+If the value is a cons pair, make a list with two elements, `car'
+and `cdr' of the pair respectively.
+
+If the value is anything else, wrap it in a list."
+ (cond
+ ((-cons-pair? val) (-cons-to-list val))
+ (t (list val))))
+
+(defun -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'.
+
+This is the same as calling `-tree-reduce-from' after `-tree-map'
+but is twice as fast as it only traverse the structure once."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) (funcall fn tree))
+ ((listp tree)
+ (-reduce-r-from folder init-value (mapcar (lambda (x)
(-tree-mapreduce-from fn folder init-value x)) tree)))
+ (t (funcall fn tree))))
+
+(defmacro --tree-mapreduce-from (form folder init-value tree)
+ "Anaphoric form of `-tree-mapreduce-from'."
+ (declare (debug (sexp sexp form form)))
+ `(-tree-mapreduce-from (lambda (it) ,form) (lambda (it acc) ,folder)
,init-value ,tree))
+
+(defun -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'.
+
+This is the same as calling `-tree-reduce' after `-tree-map'
+but is twice as fast as it only traverse the structure once."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) (funcall fn tree))
+ ((listp tree)
+ (-reduce-r folder (mapcar (lambda (x) (-tree-mapreduce fn folder x))
tree)))
+ (t (funcall fn tree))))
+
+(defmacro --tree-mapreduce (form folder tree)
+ "Anaphoric form of `-tree-mapreduce'."
+ (declare (debug (sexp sexp form)))
+ `(-tree-mapreduce (lambda (it) ,form) (lambda (it acc) ,folder) ,tree))
+
+(defun -tree-map (fn tree)
+ "Apply FN to each element of TREE while preserving the tree structure."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) (funcall fn tree))
+ ((listp tree)
+ (mapcar (lambda (x) (-tree-map fn x)) tree))
+ (t (funcall fn tree))))
+
+(defmacro --tree-map (form tree)
+ "Anaphoric form of `-tree-map'."
+ (declare (debug (sexp form)))
+ `(-tree-map (lambda (it) ,form) ,tree))
+
+(defun -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."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) tree)
+ ((listp tree)
+ (-reduce-r-from fn init-value (mapcar (lambda (x) (-tree-reduce-from fn
init-value x)) tree)))
+ (t tree)))
+
+(defmacro --tree-reduce-from (form init-value tree)
+ "Anaphoric form of `-tree-reduce-from'."
+ (declare (debug (sexp form form)))
+ `(-tree-reduce-from (lambda (it acc) ,form) ,init-value ,tree))
+
+(defun -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' for how exactly are lists of zero or one element handled."
+ (cond
+ ((not tree) nil)
+ ((-cons-pair? tree) tree)
+ ((listp tree)
+ (-reduce-r fn (mapcar (lambda (x) (-tree-reduce fn x)) tree)))
+ (t tree)))
+
+(defmacro --tree-reduce (form tree)
+ "Anaphoric form of `-tree-reduce'."
+ (declare (debug (sexp form)))
+ `(-tree-reduce (lambda (it acc) ,form) ,tree))
+
+(defun -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."
+ (-tree-map 'identity list))
+
+(defun dash-enable-font-lock ()
+ "Add syntax highlighting to dash functions, macros and magic values."
+ (eval-after-load "lisp-mode"
+ '(progn
+ (let ((new-keywords '(
+ "-each"
+ "--each"
+ "-each-while"
+ "--each-while"
+ "-dotimes"
+ "--dotimes"
+ "-map"
+ "--map"
+ "-reduce-from"
+ "--reduce-from"
+ "-reduce"
+ "--reduce"
+ "-reduce-r-from"
+ "--reduce-r-from"
+ "-reduce-r"
+ "--reduce-r"
+ "-filter"
+ "--filter"
+ "-select"
+ "--select"
+ "-remove"
+ "--remove"
+ "-reject"
+ "--reject"
+ "-keep"
+ "--keep"
+ "-map-indexed"
+ "--map-indexed"
+ "-map-when"
+ "--map-when"
+ "-replace-where"
+ "--replace-where"
+ "-flatten"
+ "-concat"
+ "-mapcat"
+ "--mapcat"
+ "-cons*"
+ "-snoc"
+ "-first"
+ "--first"
+ "-last"
+ "--last"
+ "-first-item"
+ "-last-item"
+ "-count"
+ "--count"
+ "-any?"
+ "--any?"
+ "-some?"
+ "--some?"
+ "-any-p"
+ "--any-p"
+ "-some-p"
+ "--some-p"
+ "-all?"
+ "--all?"
+ "-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"
+ "-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"
+ "-separate"
+ "--separate"
+ "-partition-all-in-steps"
+ "-partition-in-steps"
+ "-partition-all"
+ "-partition"
+ "-partition-by"
+ "--partition-by"
+ "-partition-by-header"
+ "--partition-by-header"
+ "-group-by"
+ "--group-by"
+ "-interpose"
+ "-interleave"
+ "-zip-with"
+ "--zip-with"
+ "-zip"
+ "-partial"
+ "-elem-index"
+ "-elem-indices"
+ "-find-indices"
+ "--find-indices"
+ "-find-index"
+ "--find-index"
+ "-find-last-index"
+ "--find-last-index"
+ "-select-by-indices"
+ "-grade-up"
+ "-grade-down"
+ "->"
+ "->>"
+ "-->"
+ "-when-let"
+ "-when-let*"
+ "--when-let"
+ "-if-let"
+ "-if-let*"
+ "--if-let"
+ "-distinct"
+ "-uniq"
+ "-union"
+ "-intersection"
+ "-difference"
+ "-contains?"
+ "-contains-p"
+ "-same-items?"
+ "-same-items-p"
+ "-sort"
+ "--sort"
+ "-list"
+ "-repeat"
+ "-sum"
+ "-product"
+ "-max"
+ "-min"
+ "-max-by"
+ "--max-by"
+ "-min-by"
+ "--min-by"
+ "-cons-pair?"
+ "-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"
+ "-clone"
+ "-rpartial"
+ "-juxt"
+ "-applify"
+ "-on"
+ "-flip"
+ "-const"
+ "-cut"
+ "-orfn"
+ "-andfn"
+ ))
+ (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)))))))
+
+(provide 'dash)
+;;; dash.el ends here
diff --git a/test/line-start.txt b/test/line-start.txt
new file mode 100644
index 0000000000..89c7014ce0
--- /dev/null
+++ b/test/line-start.txt
@@ -0,0 +1,6 @@
+
+
+1
+1
+22
+22
diff --git a/dev/m-buffer-test.el b/test/m-buffer-test.el
similarity index 55%
rename from dev/m-buffer-test.el
rename to test/m-buffer-test.el
index eab3e8aaaf..5cf8ebca7f 100644
--- a/dev/m-buffer-test.el
+++ b/test/m-buffer-test.el
@@ -17,75 +17,88 @@
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-(require 'm-buffer)
-
;;; Code:
-(defmacro with-temp-buffer-of-file (file &rest body)
+(defvar m-buffer-test-path
+ (directory-file-name
+ (file-name-directory
+ (or load-file-name
+ (buffer-file-name
+ (get-buffer "m-buffer-test.el"))))))
+
+(defmacro m-buffer-wtb-of-file (file &rest body)
"Run BODY in a temp buffer with the contents of FILE inserted."
`(with-temp-buffer
- (insert-file-contents ,file)
+ (insert-file-contents
+ (concat m-buffer-test-path "/"
+ ,file))
,@body))
(ert-deftest m-with-temp-buffer-of-file ()
+ "Test my test macro."
(should
(equal
"one\ntwo\nthree\n"
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"with-temp-buffer.txt"
(buffer-string)))))
+(ert-deftest m-buffer-loaded ()
+ "Has m-buffer loaded at all?"
+ (should
+ (fboundp 'm-buffer-match-data)))
+
(ert-deftest m-buffer-matches ()
(should
(= 3
(length
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
- (m-buffer-matches-data
+ (m-buffer-match-data
(current-buffer)
"^one$")))))
(should
(-every?
'markerp
(-flatten
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
- (m-buffer-matches-data
+ (m-buffer-match-data
(current-buffer)
"^one$"))))))
-(ert-deftest m-buffer-matches-beginning ()
+(ert-deftest m-buffer-match-beginning ()
(should
(-every?
'markerp
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
- (m-buffer-matches-beginning
+ (m-buffer-match-beginning
(current-buffer)
"^one$")))))
-(ert-deftest m-buffer-matches-beginning-pos ()
+
+(ert-deftest m-buffer-match-beginning-pos ()
(should
(equal
'(1 9 17)
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
- (m-buffer-matches-beginning-pos
+ (m-buffer-match-beginning-pos
(current-buffer)
"^one$")))))
(ert-deftest m-buffer-nil-markers ()
(should
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
(-all?
(lambda (marker)
(and
(marker-position marker)
(marker-buffer marker)))
- (m-buffer-matches-beginning (current-buffer) "^one$"))))
+ (m-buffer-match-beginning (current-buffer) "^one$"))))
(should
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
(-all?
(lambda (marker)
@@ -93,19 +106,48 @@
(not (marker-position marker))
(not (marker-buffer marker))))
(m-buffer-nil-markers
- (m-buffer-matches-beginning (current-buffer) "^one$"))))))
+ (m-buffer-match-beginning (current-buffer) "^one$"))))))
(ert-deftest replace-matches ()
(should
(equal
"three\ntwo\nthree\ntwo\nthree\ntwo\n"
- (with-temp-buffer-of-file
+ (m-buffer-wtb-of-file
"match-data.txt"
- (m-buffer-replace-matches
- (m-buffer-matches-data
+ (m-buffer-replace-match
+ (m-buffer-match-data
(current-buffer) "^one$") "three")
(buffer-string)))))
-(provide 'm-buffer-test)
+(ert-deftest page-matches ()
+ (should
+ (not
+ (m-buffer-wtb-of-file
+ "match-data.txt"
+ (m-buffer-page-match (current-buffer))))))
+
+(ert-deftest paragraph-separate ()
+ (should
+ (m-buffer-paragraph-separate (current-buffer))))
+
+(ert-deftest line-start ()
+ (should
+ (equal
+ '(1 2 3 5 7 10 13)
+ (m-buffer-wtb-of-file
+ "line-start.txt"
+ (m-buffer-markers-to-pos
+ (m-buffer-line-start (current-buffer)))))))
+
+(ert-deftest line-end ()
+ (should
+ (equal
+ '(1 2 4 6 9 12 13)
+ (m-buffer-wtb-of-file
+ "line-start.txt"
+ (m-buffer-markers-to-pos
+ (m-buffer-line-end (current-buffer)))))))
+
+
;;; m-buffer-test.el ends here
diff --git a/dev/match-data.txt b/test/match-data.txt
similarity index 100%
rename from dev/match-data.txt
rename to test/match-data.txt
diff --git a/dev/.nosearch b/test/test-helper.el
similarity index 100%
rename from dev/.nosearch
rename to test/test-helper.el
diff --git a/dev/with-temp-buffer.txt b/test/with-temp-buffer.txt
similarity index 100%
rename from dev/with-temp-buffer.txt
rename to test/with-temp-buffer.txt