commit 22579baf62fc5e6a4f0482172eb7a4e71d6fbcda (HEAD, refs/remotes/origin/master) Author: Nicolas Petton Date: Mon Oct 26 22:23:02 2015 +0100 * lisp/emacs-lisp/map.el: Better docstrings. diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el index cc437e0..5ef51f1 100644 --- a/lisp/emacs-lisp/map.el +++ b/lisp/emacs-lisp/map.el @@ -45,12 +45,12 @@ (require 'seq) (pcase-defmacro map (&rest args) - "pcase pattern matching map elements. + "Build a `pcase' pattern matching map elements. -Matches if the object is a map (list, hash-table or array), and -each PATTERN matches the corresponding elements of the map. +The `pcase' pattern will match each element of PATTERN against +the corresponding elements of the map. -Supernumerary elements of the map are ignored if fewer ARGS are +Extra elements of the map are ignored if fewer ARGS are given, and the match does not fail. ARGS can be a list of the form (KEY PAT), in which case KEY in an @@ -92,7 +92,7 @@ Return RESULT if non-nil or the result of evaluation of the form." (t (error "Unsupported map: %s" ,map-var))))) (defun map-elt (map key &optional default) - "Perform a lookup in MAP of KEY and return its associated value. + "Lookup KEY in MAP and return its associated value. If KEY is not found, return DEFAULT which defaults to nil. If MAP is a list, `eql' is used to lookup KEY. @@ -122,7 +122,7 @@ MAP can be a list, hash-table or array." default))) (defmacro map-put (map key value) - "In MAP, associate KEY with VALUE and return MAP. + "Associate KEY with VALUE in MAP and return MAP. If KEY is already present in MAP, replace the associated value with VALUE. @@ -133,8 +133,9 @@ MAP can be a list, hash-table or array." ,map))) (defmacro map-delete (map key) - "In MAP, delete the key KEY if present and return MAP. -If MAP is an array, store nil at the index KEY. + "Delete KEY from MAP and return MAP. +No error is signaled if KEY is not a key of MAP. If MAP is an +array, store nil at the index KEY. MAP can be a list, hash-table or array." (declare (debug t)) @@ -245,7 +246,7 @@ MAP can be a list, hash-table or array." (arrayp map))) (defun map-empty-p (map) - "Return non-nil is MAP is empty. + "Return non-nil if MAP is empty. MAP can be a list, hash-table or array." (map--dispatch map @@ -254,7 +255,7 @@ MAP can be a list, hash-table or array." :hash-table (zerop (hash-table-count map)))) (defun map-contains-key (map key &optional testfn) - "Return non-nil if MAP contain the key KEY, nil otherwise. + "Return non-nil if MAP contain KEY, nil otherwise. Equality is defined by TESTFN if non-nil or by `equal' if nil. MAP can be a list, hash-table or array." @@ -284,7 +285,7 @@ MAP can be a list, hash-table or array." t)) (defun map-merge (type &rest maps) - "Merge into a map of type TYPE all the key/value pairs in the maps MAPS. + "Merge into a map of type TYPE all the key/value pairs in MAPS. MAP can be a list, hash-table or array." (let (result) commit 5a9842c933483716a92f2c4410ce58ca829a594f Author: Nicolas Petton Date: Mon Oct 26 22:16:27 2015 +0100 * lisp/emacs-lisp/seq.el: Better docstrings. diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 05e5378..d0c2d24 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -61,10 +61,10 @@ (defmacro seq-doseq (spec &rest body) "Loop over a sequence. -Similar to `dolist' but can be applied to lists, strings, and vectors. - Evaluate BODY with VAR bound to each element of SEQUENCE, in turn. +Similar to `dolist' but can be applied to lists, strings, and vectors. + \(fn (VAR SEQUENCE) BODY...)" (declare (indent 1) (debug ((symbolp form &optional form) body))) `(seq-do (lambda (,(car spec)) @@ -72,18 +72,18 @@ Evaluate BODY with VAR bound to each element of SEQUENCE, in turn. ,(cadr spec))) (pcase-defmacro seq (&rest patterns) - "pcase pattern matching sequence elements. + "Build a `pcase' pattern that matches elements of SEQUENCE. -Matches if the object is a sequence (list, string or vector), and -each PATTERN matches the corresponding element of the sequence. +The `pcase' pattern will match each element of PATTERNS against the +corresponding element of SEQUENCE. -Supernumerary elements of the sequence are ignored if fewer -PATTERNS are given, and the match does not fail." +Extra elements of the sequence are ignored if fewer PATTERNS are +given, and the match does not fail." `(and (pred seq-p) ,@(seq--make-pcase-bindings patterns))) (defmacro seq-let (args sequence &rest body) - "Bind the variables in ARGS to the elements of SEQUENCE then evaluate BODY. + "Bind the variables in ARGS to the elements of SEQUENCE, then evaluate BODY. ARGS can also include the `&rest' marker followed by a variable name to be bound to the rest of SEQUENCE." @@ -94,7 +94,7 @@ name to be bound to the rest of SEQUENCE." ;;; Basic seq functions that have to be implemented by new sequence types (cl-defgeneric seq-elt (sequence n) - "Return the element of SEQUENCE at index N." + "Return Nth element of SEQUENCE." (elt sequence n)) ;; Default gv setters for `seq-elt'. @@ -107,7 +107,7 @@ name to be bound to the rest of SEQUENCE." (setcar (nthcdr n sequence) store)) (cl-defgeneric seq-length (sequence) - "Return the length of SEQUENCE." + "Return the number of elements of SEQUENCE." (length sequence)) (cl-defgeneric seq-do (function sequence) @@ -126,11 +126,13 @@ Return SEQUENCE." (copy-sequence sequence)) (cl-defgeneric seq-subseq (sequence start &optional end) - "Return the subsequence of SEQUENCE from START to END. -If END is omitted, it defaults to the length of the sequence. -If START or END is negative, it counts from the end. -Signal an error if START or END are outside of the sequence (i.e -too large if positive or too small if negative)." + "Return the sequence of elements of SEQUENCE from START to END. +END is inclusive. + +If END is omitted, it defaults to the length of the sequence. If +START or END is negative, it counts from the end. Signal an +error if START or END are outside of the sequence (i.e too large +if positive or too small if negative)." (cl-subseq sequence start end)) @@ -147,7 +149,7 @@ too large if positive or too small if negative)." (mapcar function sequence)) (cl-defgeneric seq-drop (sequence n) - "Return a subsequence of SEQUENCE without its first N elements. + "Remove the first N elements of SEQUENCE and return the result. The result is a sequence of the same type as SEQUENCE. If N is a negative integer or zero, SEQUENCE is returned." @@ -157,7 +159,7 @@ If N is a negative integer or zero, SEQUENCE is returned." (seq-subseq sequence (min n length) length)))) (cl-defgeneric seq-take (sequence n) - "Return a subsequence of SEQUENCE with its first N elements. + "Take the first N elements of SEQUENCE and return the result. The result is a sequence of the same type as SEQUENCE. If N is a negative integer or zero, an empty sequence is @@ -165,13 +167,15 @@ returned." (seq-subseq sequence 0 (min (max n 0) (seq-length sequence)))) (cl-defgeneric seq-drop-while (pred sequence) - "Return a sequence from the first element for which (PRED element) is nil in SEQUENCE. -The result is a sequence of the same type as SEQUENCE." + "Remove the successive elements of SEQUENCE for which PRED returns non-nil. +PRED is a function of one argument. The result is a sequence of +the same type as SEQUENCE." (seq-drop sequence (seq--count-successive pred sequence))) (cl-defgeneric seq-take-while (pred sequence) - "Return the successive elements for which (PRED element) is non-nil in SEQUENCE. -The result is a sequence of the same type as SEQUENCE." + "Take the successive elements of SEQUENCE for which PRED returns non-nil. +PRED is a function of one argument. The result is a sequence of +the same type as SEQUENCE." (seq-take sequence (seq--count-successive pred sequence))) (cl-defgeneric seq-empty-p (sequence) @@ -179,7 +183,7 @@ The result is a sequence of the same type as SEQUENCE." (= 0 (seq-length sequence))) (cl-defgeneric seq-sort (pred sequence) - "Return a sorted sequence comparing using PRED the elements of SEQUENCE. + "Sort SEQUENCE using PRED as comparison function. The result is a sequence of the same type as SEQUENCE." (let ((result (seq-sort pred (append sequence nil)))) (seq-into result (type-of sequence)))) @@ -188,7 +192,7 @@ The result is a sequence of the same type as SEQUENCE." (sort (seq-copy list) pred)) (cl-defgeneric seq-reverse (sequence) - "Return the reversed shallow copy of SEQUENCE." + "Return a sequence with elements of SEQUENCE in reverse order." (let ((result '())) (seq-map (lambda (elt) (push elt result)) @@ -200,7 +204,7 @@ The result is a sequence of the same type as SEQUENCE." (reverse sequence)) (cl-defgeneric seq-concatenate (type &rest sequences) - "Concatenate, into a sequence of type TYPE, the sequences SEQUENCES. + "Concatenate SEQUENCES into a single sequence of type TYPE. TYPE must be one of following symbols: vector, string or list. \n(fn TYPE SEQUENCE...)" @@ -217,8 +221,9 @@ of sequence." sequence) (cl-defgeneric seq-into (sequence type) - "Convert SEQUENCE into a sequence of type TYPE. -TYPE can be one of the following symbols: vector, string or list." + "Concatenate the elements of SEQUENCE into a sequence of type TYPE. +TYPE can be one of the following symbols: vector, string or +list." (pcase type (`vector (vconcat sequence)) (`string (concat sequence)) commit 7637849321a5bf3db8213ab23c38131a78e37dc9 Author: Nicolas Petton Date: Mon Oct 26 21:51:30 2015 +0100 * lisp/emacs-lisp/seq.el: Rename all seq argumentss to sequence. diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index f5189c7..05e5378 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -63,9 +63,9 @@ "Loop over a sequence. Similar to `dolist' but can be applied to lists, strings, and vectors. -Evaluate BODY with VAR bound to each element of SEQ, in turn. +Evaluate BODY with VAR bound to each element of SEQUENCE, in turn. -\(fn (VAR SEQ) BODY...)" +\(fn (VAR SEQUENCE) BODY...)" (declare (indent 1) (debug ((symbolp form &optional form) body))) `(seq-do (lambda (,(car spec)) ,@body) @@ -82,284 +82,284 @@ PATTERNS are given, and the match does not fail." `(and (pred seq-p) ,@(seq--make-pcase-bindings patterns))) -(defmacro seq-let (args seq &rest body) - "Bind the variables in ARGS to the elements of SEQ then evaluate BODY. +(defmacro seq-let (args sequence &rest body) + "Bind the variables in ARGS to the elements of SEQUENCE then evaluate BODY. ARGS can also include the `&rest' marker followed by a variable -name to be bound to the rest of SEQ." +name to be bound to the rest of SEQUENCE." (declare (indent 2) (debug t)) - `(pcase-let ((,(seq--make-pcase-patterns args) ,seq)) + `(pcase-let ((,(seq--make-pcase-patterns args) ,sequence)) ,@body)) -;;; Basic seq functions that have to be implemented by new seq types -(cl-defgeneric seq-elt (seq n) - "Return the element of SEQ at index N." - (elt seq n)) +;;; Basic seq functions that have to be implemented by new sequence types +(cl-defgeneric seq-elt (sequence n) + "Return the element of SEQUENCE at index N." + (elt sequence n)) ;; Default gv setters for `seq-elt'. ;; It can be a good idea for new sequence implementations to provide a ;; "gv-setter" for `seq-elt'. -(cl-defmethod (setf seq-elt) (store (seq array) n) - (aset seq n store)) +(cl-defmethod (setf seq-elt) (store (sequence array) n) + (aset sequence n store)) -(cl-defmethod (setf seq-elt) (store (seq cons) n) - (setcar (nthcdr n seq) store)) +(cl-defmethod (setf seq-elt) (store (sequence cons) n) + (setcar (nthcdr n sequence) store)) -(cl-defgeneric seq-length (seq) - "Return the length of the sequence SEQ." - (length seq)) +(cl-defgeneric seq-length (sequence) + "Return the length of SEQUENCE." + (length sequence)) -(cl-defgeneric seq-do (function seq) - "Apply FUNCTION to each element of SEQ, presumably for side effects. -Return SEQ." - (mapc function seq)) +(cl-defgeneric seq-do (function sequence) + "Apply FUNCTION to each element of SEQUENCE, presumably for side effects. +Return SEQUENCE." + (mapc function sequence)) (defalias 'seq-each #'seq-do) -(cl-defgeneric seq-p (seq) - "Return non-nil if SEQ is a sequence, nil otherwise." - (sequencep seq)) +(cl-defgeneric seq-p (sequence) + "Return non-nil if SEQUENCE is a sequence, nil otherwise." + (sequencep sequence)) -(cl-defgeneric seq-copy (seq) - "Return a shallow copy of SEQ." - (copy-sequence seq)) +(cl-defgeneric seq-copy (sequence) + "Return a shallow copy of SEQUENCE." + (copy-sequence sequence)) -(cl-defgeneric seq-subseq (seq start &optional end) - "Return the subsequence of SEQ from START to END. +(cl-defgeneric seq-subseq (sequence start &optional end) + "Return the subsequence of SEQUENCE from START to END. If END is omitted, it defaults to the length of the sequence. If START or END is negative, it counts from the end. Signal an error if START or END are outside of the sequence (i.e too large if positive or too small if negative)." - (cl-subseq seq start end)) + (cl-subseq sequence start end)) -(cl-defgeneric seq-map (function seq) - "Return the result of applying FUNCTION to each element of SEQ." +(cl-defgeneric seq-map (function sequence) + "Return the result of applying FUNCTION to each element of SEQUENCE." (let (result) (seq-do (lambda (elt) (push (funcall function elt) result)) - seq) + sequence) (nreverse result))) ;; faster implementation for sequences (sequencep) -(cl-defmethod seq-map (function (seq sequence)) - (mapcar function seq)) +(cl-defmethod seq-map (function (sequence sequence)) + (mapcar function sequence)) -(cl-defgeneric seq-drop (seq n) - "Return a subsequence of SEQ without its first N elements. -The result is a sequence of the same type as SEQ. +(cl-defgeneric seq-drop (sequence n) + "Return a subsequence of SEQUENCE without its first N elements. +The result is a sequence of the same type as SEQUENCE. -If N is a negative integer or zero, SEQ is returned." +If N is a negative integer or zero, SEQUENCE is returned." (if (<= n 0) - seq - (let ((length (seq-length seq))) - (seq-subseq seq (min n length) length)))) + sequence + (let ((length (seq-length sequence))) + (seq-subseq sequence (min n length) length)))) -(cl-defgeneric seq-take (seq n) - "Return a subsequence of SEQ with its first N elements. -The result is a sequence of the same type as SEQ. +(cl-defgeneric seq-take (sequence n) + "Return a subsequence of SEQUENCE with its first N elements. +The result is a sequence of the same type as SEQUENCE. If N is a negative integer or zero, an empty sequence is returned." - (seq-subseq seq 0 (min (max n 0) (seq-length seq)))) + (seq-subseq sequence 0 (min (max n 0) (seq-length sequence)))) -(cl-defgeneric seq-drop-while (pred seq) - "Return a sequence from the first element for which (PRED element) is nil in SEQ. -The result is a sequence of the same type as SEQ." - (seq-drop seq (seq--count-successive pred seq))) +(cl-defgeneric seq-drop-while (pred sequence) + "Return a sequence from the first element for which (PRED element) is nil in SEQUENCE. +The result is a sequence of the same type as SEQUENCE." + (seq-drop sequence (seq--count-successive pred sequence))) -(cl-defgeneric seq-take-while (pred seq) - "Return the successive elements for which (PRED element) is non-nil in SEQ. -The result is a sequence of the same type as SEQ." - (seq-take seq (seq--count-successive pred seq))) +(cl-defgeneric seq-take-while (pred sequence) + "Return the successive elements for which (PRED element) is non-nil in SEQUENCE. +The result is a sequence of the same type as SEQUENCE." + (seq-take sequence (seq--count-successive pred sequence))) -(cl-defgeneric seq-empty-p (seq) - "Return non-nil if the sequence SEQ is empty, nil otherwise." - (= 0 (seq-length seq))) +(cl-defgeneric seq-empty-p (sequence) + "Return non-nil if the SEQUENCE is empty, nil otherwise." + (= 0 (seq-length sequence))) -(cl-defgeneric seq-sort (pred seq) - "Return a sorted sequence comparing using PRED the elements of SEQ. -The result is a sequence of the same type as SEQ." - (let ((result (seq-sort pred (append seq nil)))) - (seq-into result (type-of seq)))) +(cl-defgeneric seq-sort (pred sequence) + "Return a sorted sequence comparing using PRED the elements of SEQUENCE. +The result is a sequence of the same type as SEQUENCE." + (let ((result (seq-sort pred (append sequence nil)))) + (seq-into result (type-of sequence)))) (cl-defmethod seq-sort (pred (list list)) (sort (seq-copy list) pred)) -(cl-defgeneric seq-reverse (seq) - "Return the reversed shallow copy of SEQ." +(cl-defgeneric seq-reverse (sequence) + "Return the reversed shallow copy of SEQUENCE." (let ((result '())) (seq-map (lambda (elt) (push elt result)) - seq) - (seq-into result (type-of seq)))) + sequence) + (seq-into result (type-of sequence)))) ;; faster implementation for sequences (sequencep) -(cl-defmethod seq-reverse ((seq sequence)) - (reverse seq)) +(cl-defmethod seq-reverse ((sequence sequence)) + (reverse sequence)) -(cl-defgeneric seq-concatenate (type &rest seqs) - "Concatenate, into a sequence of type TYPE, the sequences SEQS. +(cl-defgeneric seq-concatenate (type &rest sequences) + "Concatenate, into a sequence of type TYPE, the sequences SEQUENCES. TYPE must be one of following symbols: vector, string or list. \n(fn TYPE SEQUENCE...)" - (apply #'cl-concatenate type (seq-map #'seq-into-sequence seqs))) + (apply #'cl-concatenate type (seq-map #'seq-into-sequence sequences))) -(cl-defgeneric seq-into-sequence (seq) - "Convert SEQ into a sequence. +(cl-defgeneric seq-into-sequence (sequence) + "Convert SEQUENCE into a sequence. -The default implementation is to signal an error if SEQ is not a +The default implementation is to signal an error if SEQUENCE is not a sequence, specific functions should be implemented for new types -of seq." - (unless (sequencep seq) - (error "Cannot convert %S into a sequence" seq)) - seq) +of sequence." + (unless (sequencep sequence) + (error "Cannot convert %S into a sequence" sequence)) + sequence) -(cl-defgeneric seq-into (seq type) - "Convert the sequence SEQ into a sequence of type TYPE. +(cl-defgeneric seq-into (sequence type) + "Convert SEQUENCE into a sequence of type TYPE. TYPE can be one of the following symbols: vector, string or list." (pcase type - (`vector (vconcat seq)) - (`string (concat seq)) - (`list (append seq nil)) + (`vector (vconcat sequence)) + (`string (concat sequence)) + (`list (append sequence nil)) (_ (error "Not a sequence type name: %S" type)))) -(cl-defgeneric seq-filter (pred seq) - "Return a list of all the elements for which (PRED element) is non-nil in SEQ." +(cl-defgeneric seq-filter (pred sequence) + "Return a list of all the elements for which (PRED element) is non-nil in SEQUENCE." (let ((exclude (make-symbol "exclude"))) (delq exclude (seq-map (lambda (elt) (if (funcall pred elt) elt exclude)) - seq)))) + sequence)))) -(cl-defgeneric seq-remove (pred seq) - "Return a list of all the elements for which (PRED element) is nil in SEQ." +(cl-defgeneric seq-remove (pred sequence) + "Return a list of all the elements for which (PRED element) is nil in SEQUENCE." (seq-filter (lambda (elt) (not (funcall pred elt))) - seq)) + sequence)) -(cl-defgeneric seq-reduce (function seq initial-value) - "Reduce the function FUNCTION across SEQ, starting with INITIAL-VALUE. +(cl-defgeneric seq-reduce (function sequence initial-value) + "Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE. Return the result of calling FUNCTION with INITIAL-VALUE and the -first element of SEQ, then calling FUNCTION with that result and -the second element of SEQ, then with that result and the third -element of SEQ, etc. +first element of SEQUENCE, then calling FUNCTION with that result and +the second element of SEQUENCE, then with that result and the third +element of SEQUENCE, etc. -If SEQ is empty, return INITIAL-VALUE and FUNCTION is not called." - (if (seq-empty-p seq) +If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called." + (if (seq-empty-p sequence) initial-value (let ((acc initial-value)) - (seq-doseq (elt seq) + (seq-doseq (elt sequence) (setq acc (funcall function acc elt))) acc))) -(cl-defgeneric seq-every-p (pred seq) - "Return non-nil if (PRED element) is non-nil for all elements of the sequence SEQ." +(cl-defgeneric seq-every-p (pred sequence) + "Return non-nil if (PRED element) is non-nil for all elements of SEQUENCE." (catch 'seq--break - (seq-doseq (elt seq) + (seq-doseq (elt sequence) (or (funcall pred elt) (throw 'seq--break nil))) t)) -(cl-defgeneric seq-some (pred seq) - "Return the first value for which if (PRED element) is non-nil for in SEQ." +(cl-defgeneric seq-some (pred sequence) + "Return the first value for which if (PRED element) is non-nil for in SEQUENCE." (catch 'seq--break - (seq-doseq (elt seq) + (seq-doseq (elt sequence) (let ((result (funcall pred elt))) (when result (throw 'seq--break result)))) nil)) -(cl-defgeneric seq-find (pred seq &optional default) - "Return the first element for which (PRED element) is non-nil in SEQ. +(cl-defgeneric seq-find (pred sequence &optional default) + "Return the first element for which (PRED element) is non-nil in SEQUENCE. If no element is found, return DEFAULT. Note that `seq-find' has an ambiguity if the found element is identical to DEFAULT, as it cannot be known if an element was found or not." (catch 'seq--break - (seq-doseq (elt seq) + (seq-doseq (elt sequence) (when (funcall pred elt) (throw 'seq--break elt))) default)) -(cl-defgeneric seq-count (pred seq) - "Return the number of elements for which (PRED element) is non-nil in SEQ." +(cl-defgeneric seq-count (pred sequence) + "Return the number of elements for which (PRED element) is non-nil in SEQUENCE." (let ((count 0)) - (seq-doseq (elt seq) + (seq-doseq (elt sequence) (when (funcall pred elt) (setq count (+ 1 count)))) count)) -(cl-defgeneric seq-contains (seq elt &optional testfn) - "Return the first element in SEQ that is equal to ELT. +(cl-defgeneric seq-contains (sequence elt &optional testfn) + "Return the first element in SEQUENCE that is equal to ELT. Equality is defined by TESTFN if non-nil or by `equal' if nil." (seq-some (lambda (e) (funcall (or testfn #'equal) elt e)) - seq)) + sequence)) -(cl-defgeneric seq-position (seq elt &optional testfn) - "Return the index of the first element in SEQ that is equal to ELT. +(cl-defgeneric seq-position (sequence elt &optional testfn) + "Return the index of the first element in SEQUENCE that is equal to ELT. Equality is defined by TESTFN if non-nil or by `equal' if nil." (let ((index 0)) (catch 'seq--break - (seq-doseq (e seq) + (seq-doseq (e sequence) (when (funcall (or testfn #'equal) e elt) (throw 'seq--break index)) (setq index (1+ index))) nil))) -(cl-defgeneric seq-uniq (seq &optional testfn) - "Return a list of the elements of SEQ with duplicates removed. +(cl-defgeneric seq-uniq (sequence &optional testfn) + "Return a list of the elements of SEQUENCE with duplicates removed. TESTFN is used to compare elements, or `equal' if TESTFN is nil." (let ((result '())) - (seq-doseq (elt seq) + (seq-doseq (elt sequence) (unless (seq-contains result elt testfn) (setq result (cons elt result)))) (nreverse result))) -(cl-defgeneric seq-mapcat (function seq &optional type) - "Concatenate the result of applying FUNCTION to each element of SEQ. +(cl-defgeneric seq-mapcat (function sequence &optional type) + "Concatenate the result of applying FUNCTION to each element of SEQUENCE. The result is a sequence of type TYPE, or a list if TYPE is nil." (apply #'seq-concatenate (or type 'list) - (seq-map function seq))) + (seq-map function sequence))) -(cl-defgeneric seq-partition (seq n) - "Return a list of the elements of SEQ grouped into sub-sequences of length N. +(cl-defgeneric seq-partition (sequence n) + "Return a list of the elements of SEQUENCE grouped into sub-sequences of length N. The last sequence may contain less than N elements. If N is a negative integer or 0, nil is returned." (unless (< n 1) (let ((result '())) - (while (not (seq-empty-p seq)) - (push (seq-take seq n) result) - (setq seq (seq-drop seq n))) + (while (not (seq-empty-p sequence)) + (push (seq-take sequence n) result) + (setq sequence (seq-drop sequence n))) (nreverse result)))) -(cl-defgeneric seq-intersection (seq1 seq2 &optional testfn) - "Return a list of the elements that appear in both SEQ1 and SEQ2. +(cl-defgeneric seq-intersection (sequence1 sequence2 &optional testfn) + "Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2. Equality is defined by TESTFN if non-nil or by `equal' if nil." (seq-reduce (lambda (acc elt) - (if (seq-contains seq2 elt testfn) + (if (seq-contains sequence2 elt testfn) (cons elt acc) acc)) - (seq-reverse seq1) + (seq-reverse sequence1) '())) -(cl-defgeneric seq-difference (seq1 seq2 &optional testfn) - "Return a list of the elements that appear in SEQ1 but not in SEQ2. +(cl-defgeneric seq-difference (sequence1 sequence2 &optional testfn) + "Return a list of the elements that appear in SEQUENCE1 but not in SEQUENCE2. Equality is defined by TESTFN if non-nil or by `equal' if nil." (seq-reduce (lambda (acc elt) - (if (not (seq-contains seq2 elt testfn)) + (if (not (seq-contains sequence2 elt testfn)) (cons elt acc) acc)) - (seq-reverse seq1) + (seq-reverse sequence1) '())) -(cl-defgeneric seq-group-by (function seq) - "Apply FUNCTION to each element of SEQ. -Separate the elements of SEQ into an alist using the results as +(cl-defgeneric seq-group-by (function sequence) + "Apply FUNCTION to each element of SEQUENCE. +Separate the elements of SEQUENCE into an alist using the results as keys. Keys are compared using `equal'." (seq-reduce (lambda (acc elt) @@ -369,25 +369,25 @@ keys. Keys are compared using `equal'." (setcdr cell (push elt (cdr cell))) (push (list key elt) acc)) acc)) - (seq-reverse seq) + (seq-reverse sequence) nil)) -(cl-defgeneric seq-min (seq) - "Return the smallest element of SEQ. -SEQ must be a sequence of numbers or markers." - (apply #'min (seq-into seq 'list))) +(cl-defgeneric seq-min (sequence) + "Return the smallest element of SEQUENCE. +SEQUENCE must be a sequence of numbers or markers." + (apply #'min (seq-into sequence 'list))) -(cl-defgeneric seq-max (seq) - "Return the largest element of SEQ. -SEQ must be a sequence of numbers or markers." - (apply #'max (seq-into seq 'list))) +(cl-defgeneric seq-max (sequence) + "Return the largest element of SEQUENCE. +SEQUENCE must be a sequence of numbers or markers." + (apply #'max (seq-into sequence 'list))) -(defun seq--count-successive (pred seq) - "Return the number of successive elements for which (PRED element) is non-nil in SEQ." +(defun seq--count-successive (pred sequence) + "Return the number of successive elements for which (PRED element) is non-nil in SEQUENCE." (let ((n 0) - (len (seq-length seq))) + (len (seq-length sequence))) (while (and (< n len) - (funcall pred (seq-elt seq n))) + (funcall pred (seq-elt sequence n))) (setq n (+ 1 n))) n)) @@ -419,10 +419,10 @@ SEQ must be a sequence of numbers or markers." args))) ;; TODO: make public? -(defun seq--elt-safe (seq n) - "Return element of SEQ at the index N. +(defun seq--elt-safe (sequence n) + "Return element of SEQUENCE at the index N. If no element is found, return nil." - (ignore-errors (seq-elt seq n))) + (ignore-errors (seq-elt sequence n))) ;;; Optimized implementations for lists commit 5c86118b4ba818ed1fd48258f884f95d98674693 Author: Phillip Lord Date: Mon Oct 26 20:27:16 2015 +0000 * lisp/emacs-lisp/ert.el: Print results without newline escaping diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 2eba021..21c1f1b 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -64,7 +64,7 @@ (require 'ewoc) (require 'find-func) (require 'help) - +(require 'pp) ;;; UI customization options. @@ -1300,7 +1300,8 @@ EXPECTEDP specifies whether the result was expected." (defun ert--pp-with-indentation-and-newline (object) "Pretty-print OBJECT, indenting it to the current column of point. Ensures a final newline is inserted." - (let ((begin (point))) + (let ((begin (point)) + (pp-escape-newlines nil)) (pp object (current-buffer)) (unless (bolp) (insert "\n")) (save-excursion commit 93dba9c2d7fd511fd7deba2e172cd54a73314d0b Author: Stephen Leake Date: Mon Oct 26 14:38:59 2015 -0500 Clarify that load-path contents should be directory file names * doc/lispref/files.texi (Directory Names): Define and use "directory file name". Recommend `expand-file-name'. * src/lread.c (load-path): Fix doc string; elements are directory file names. diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index ca8abe5..65a97a4 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -2038,32 +2038,35 @@ forward slash (@samp{/}) character. @node Directory Names @subsection Directory Names @cindex directory name +@cindex directory file name @cindex file name of directory A @dfn{directory name} is the name of a directory. A directory is -actually a kind of file, so it has a file name, which is related to -the directory name but not identical to it. (This is not quite the -same as the usual Unix terminology.) These two different names for -the same entity are related by a syntactic transformation. On GNU and -Unix systems, this is simple: a directory name ends in a slash, -whereas the directory's name as a file lacks that slash. On MS-DOS -the relationship is more complicated. - - The difference between a directory name and its name as a file is +actually a kind of file, so it has a file name (called the +@dfn{directory file name}, which is related to the directory name but +not identical to it. (This is not quite the same as the usual Unix +terminology.) These two different names for the same entity are +related by a syntactic transformation. On GNU and Unix systems, this +is simple: a directory name ends in a slash, whereas the directory +file name lacks that slash. On MS-DOS the relationship is more +complicated. + + The difference between directory name and directory file name is subtle but crucial. When an Emacs variable or function argument is -described as being a directory name, a file name of a directory is not +described as being a directory name, a directory file name is not acceptable. When @code{file-name-directory} returns a string, that is always a directory name. - The following two functions convert between directory names and file -names. They do nothing special with environment variable substitutions -such as @samp{$HOME}, and the constructs @samp{~}, @samp{.} and @samp{..}. + The following two functions convert between directory names and +directory file names. They do nothing special with environment +variable substitutions such as @samp{$HOME}, and the constructs +@samp{~}, @samp{.} and @samp{..}. @defun file-name-as-directory filename This function returns a string representing @var{filename} in a form -that the operating system will interpret as the name of a directory. On -most systems, this means appending a slash to the string (if it does not -already end in one). +that the operating system will interpret as the name of a directory (a +directory name). On most systems, this means appending a slash to the +string (if it does not already end in one). @example @group @@ -2074,10 +2077,10 @@ already end in one). @end defun @defun directory-file-name dirname -This function returns a string representing @var{dirname} in a form that -the operating system will interpret as the name of a file. On most -systems, this means removing the final slash (or backslash) from the -string. +This function returns a string representing @var{dirname} in a form +that the operating system will interpret as the name of a file (a +directory file name). On most systems, this means removing the final +slash (or backslash) from the string. @example @group @@ -2119,6 +2122,13 @@ Don't try concatenating a slash by hand, as in because this is not portable. Always use @code{file-name-as-directory}. + To avoid the issues mentioned above, or if the @var{dirname} value +might be nil (for example, from an element of @code{load-path}), use: + +@example +(expand-file-name @var{relfile} @var{dirname}) +@end example + To convert a directory name to its abbreviation, use this function: diff --git a/src/lread.c b/src/lread.c index a98fa61..1119f3f 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4479,8 +4479,10 @@ were read in. */); DEFVAR_LISP ("load-path", Vload_path, doc: /* List of directories to search for files to load. -Each element is a string (directory name) or nil (meaning `default-directory'). -Initialized during startup as described in Info node `(elisp)Library Search'. */); +Each element is a string (directory file name) or nil (meaning +`default-directory'). Initialized during startup as described in Info +node `(elisp)Library Search'. Use `directory-file-name' when adding items +to this path. */); DEFVAR_LISP ("load-suffixes", Vload_suffixes, doc: /* List of suffixes for (compiled or source) Emacs Lisp files. commit c9fb8954bc72c9e362f7bf71b3457882887cb182 Author: Eli Zaretskii Date: Mon Oct 26 21:25:10 2015 +0200 Fix simple-test.el test * test/automated/simple-test.el (simple-test--dummy-buffer): Make sure indentation doesn't use TABs, otherwise the 6th test might fail. diff --git a/test/automated/simple-test.el b/test/automated/simple-test.el index a9c4d67..8da575d 100644 --- a/test/automated/simple-test.el +++ b/test/automated/simple-test.el @@ -26,6 +26,7 @@ (debug t)) `(with-temp-buffer (emacs-lisp-mode) + (setq indent-tabs-mode nil) (insert "(a b") (save-excursion (insert " c d)")) ,@body commit 3f828dc76be74e3587af74b5b3e3458f67f2b7ba Author: Mark Oteiza Date: Sat Oct 10 22:43:44 2015 -0400 * lisp/net/eww.el (eww-bookmark-prepare): Use truncate-string-to-width. `substring' does not account for full width characters. diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 6a31549..5748e88 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -1501,7 +1501,7 @@ If CHARSET is nil then use UTF-8." (setq start (point) title (plist-get bookmark :title)) (when (> (length title) width) - (setq title (substring title 0 width))) + (setq title (truncate-string-to-width title width))) (insert (format format title (plist-get bookmark :url)) "\n") (put-text-property start (1+ start) 'eww-bookmark bookmark)) (goto-char (point-min)))) commit 0d9c67236cab3ffe9a8f1276e93a32e437c09bfc Author: Michael Albinus Date: Mon Oct 26 16:46:48 2015 +0100 Further work on `stopped' events in filenotify.el * doc/lispref/os.texi (File Notifications): Rework examples. * lisp/filenotify.el (file-notify--rm-descriptor): Optional parameter. (file-notify--rm-descriptor, file-notify-callback): Improve check for sending `stopped' event. (file-notify-add-watch): Check for more events for `inotify'. * test/automated/file-notify-tests.el (file-notify--test-expected-events): New defvar. (file-notify--test-with-events): Use it. (file-notify--test-cleanup): Make it more robust when deleting directories. (file-notify--test-event-test): Check also for watched directories. (file-notify--test-event-handler): Suppress temporary .#files. (file-notify-test02-events, file-notify-test04-file-validity): Rework `stopped' events. (file-notify-test05-dir-validity): Wait for events when appropriate. diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 0160de8..7050df8 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -2697,6 +2697,11 @@ watch library. Otherwise, the actions @code{deleted} and (rename-file "/tmp/foo" "/tmp/bla") @result{} Event (35025468 renamed "/tmp/foo" "/tmp/bla") @end group + +@group +(delete-file "/tmp/bla") + @result{} Event (35025468 deleted "/tmp/bla") +@end group @end example @end defun @@ -2718,15 +2723,15 @@ also makes it invalid. @example @group -(setq desc (file-notify-add-watch - "/tmp/foo" '(change) 'my-notify-callback)) - @result{} 35025468 +(make-directory "/tmp/foo") + @result{} nil @end group @group -(write-region "foo" nil "/tmp/foo") - @result{} Event (35025468 created "/tmp/foo") - Event (35025468 changed "/tmp/foo") +(setq desc + (file-notify-add-watch + "/tmp/foo" '(change) 'my-notify-callback)) + @result{} 35025468 @end group @group @@ -2735,8 +2740,32 @@ also makes it invalid. @end group @group -(delete-file "/tmp/foo") - @result{} Event (35025468 deleted "/tmp/foo") +(write-region "bla" nil "/tmp/foo/bla") + @result{} Event (35025468 created "/tmp/foo/.#bla") + Event (35025468 created "/tmp/foo/bla") + Event (35025468 changed "/tmp/foo/bla") + Event (35025468 changed "/tmp/foo/.#bla") +@end group + +@group +;; Deleting a file in the directory doesn't invalidate the watch. +(delete-file "/tmp/foo/bla") + @result{} Event (35025468 deleted "/tmp/foo/bla") +@end group + +@group +(write-region "bla" nil "/tmp/foo/bla") + @result{} Event (35025468 created "/tmp/foo/.#bla") + Event (35025468 created "/tmp/foo/bla") + Event (35025468 changed "/tmp/foo/bla") + Event (35025468 changed "/tmp/foo/.#bla") +@end group + +@group +;; Deleting the directory invalidates the watch. +(delete-directory "/tmp/foo" 'recursive) + @result{} Event (35025468 deleted "/tmp/foo/bla") + Event (35025468 deleted "/tmp/foo") Event (35025468 stopped "/tmp/foo") @end group diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 55d9028..6a180a8 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -48,32 +48,33 @@ The value in the hash table is a list Several values for a given DIR happen only for `inotify', when different files from the same directory are watched.") -(defun file-notify--rm-descriptor (descriptor) +(defun file-notify--rm-descriptor (descriptor &optional what) "Remove DESCRIPTOR from `file-notify-descriptors'. DESCRIPTOR should be an object returned by `file-notify-add-watch'. -If it is registered in `file-notify-descriptors', a stopped event is sent." +If it is registered in `file-notify-descriptors', a stopped event is sent. +WHAT is a file or directory name to be removed, needed just for `inotify'." (let* ((desc (if (consp descriptor) (car descriptor) descriptor)) (file (if (consp descriptor) (cdr descriptor))) (registered (gethash desc file-notify-descriptors)) (dir (car registered))) - (when (consp registered) + (when (and (consp registered) (or (null what) (string-equal dir what))) ;; Send `stopped' event. (dolist (entry (cdr registered)) - (funcall (cdr entry) - `(,(file-notify--descriptor desc) stopped - ,(or (and (stringp (car entry)) - (expand-file-name (car entry) dir)) - dir)))) + (funcall (cdr entry) + `(,(file-notify--descriptor desc) stopped + ,(or (and (stringp (car entry)) + (expand-file-name (car entry) dir)) + dir)))) ;; Modify `file-notify-descriptors'. (if (not file) - (remhash desc file-notify-descriptors) - (setcdr registered - (delete (assoc file (cdr registered)) (cdr registered))) - (if (null (cdr registered)) - (remhash desc file-notify-descriptors) - (puthash desc registered file-notify-descriptors)))))) + (remhash desc file-notify-descriptors) + (setcdr registered + (delete (assoc file (cdr registered)) (cdr registered))) + (if (null (cdr registered)) + (remhash desc file-notify-descriptors) + (puthash desc registered file-notify-descriptors)))))) ;; This function is used by `gfilenotify', `inotify' and `w32notify' events. ;;;###autoload @@ -85,6 +86,7 @@ If EVENT is a filewatch event, call its callback. It has the format Otherwise, signal a `file-notify-error'." (interactive "e") + ;;(message "file-notify-handle-event %S" event) (if (and (eq (car event) 'file-notify) (>= (length event) 3)) (funcall (nth 2 event) (nth 1 event)) @@ -224,6 +226,7 @@ EVENT is the cadr of the event in `file-notify-handle-event' (setq pending-event nil)) ;; Check for stopped. + ;;(message "file-notify-callback %S %S" file registered) (setq stopped (or @@ -232,7 +235,9 @@ EVENT is the cadr of the event in `file-notify-handle-event' (memq action '(deleted renamed)) (= (length (cdr registered)) 1) (string-equal - (or (file-name-nondirectory file) "") (car (cadr registered)))))) + (file-name-nondirectory file) + (or (file-name-nondirectory (car registered)) + (car (cadr registered))))))) ;; Apply callback. (when (and action @@ -257,7 +262,7 @@ EVENT is the cadr of the event in `file-notify-handle-event' ;; Modify `file-notify-descriptors'. (when stopped - (file-notify--rm-descriptor (file-notify--descriptor desc)))))) + (file-notify--rm-descriptor (file-notify--descriptor desc) file))))) ;; `gfilenotify' and `w32notify' return a unique descriptor for every ;; `file-notify-add-watch', while `inotify' returns a unique @@ -324,8 +329,8 @@ FILE is the name of the file whose event is being reported." (setq desc (funcall handler 'file-notify-add-watch dir flags callback)) - ;; Check, whether Emacs has been compiled with file - ;; notification support. + ;; Check, whether Emacs has been compiled with file notification + ;; support. (unless file-notify--library (signal 'file-notify-error '("No file notification package available"))) @@ -344,7 +349,8 @@ FILE is the name of the file whose event is being reported." (setq l-flags (cond - ((eq file-notify--library 'inotify) '(create modify move delete)) + ((eq file-notify--library 'inotify) + '(create delete delete-self modify move-self move)) ((eq file-notify--library 'w32notify) '(file-name directory-name size last-write-time))))) (when (memq 'attribute-change flags) diff --git a/test/automated/file-notify-tests.el b/test/automated/file-notify-tests.el index 56b4f69..472c692 100644 --- a/test/automated/file-notify-tests.el +++ b/test/automated/file-notify-tests.el @@ -61,6 +61,8 @@ (defvar file-notify--test-results nil) (defvar file-notify--test-event nil) (defvar file-notify--test-events nil) +(defvar file-notify--test-expected-events nil) + (defun file-notify--test-timeout () "Timeout to wait for arriving events, in seconds." (if (file-remote-p temporary-file-directory) 6 3)) @@ -71,12 +73,12 @@ (when (and file-notify--test-tmpfile (file-exists-p file-notify--test-tmpfile)) - (if (directory-name-p file-notify--test-tmpfile) + (if (file-directory-p file-notify--test-tmpfile) (delete-directory file-notify--test-tmpfile 'recursive) (delete-file file-notify--test-tmpfile))) (when (and file-notify--test-tmpfile1 (file-exists-p file-notify--test-tmpfile1)) - (if (directory-name-p file-notify--test-tmpfile1) + (if (file-directory-p file-notify--test-tmpfile1) (delete-directory file-notify--test-tmpfile1 'recursive) (delete-file file-notify--test-tmpfile1))) (when (file-remote-p temporary-file-directory) @@ -87,7 +89,8 @@ file-notify--test-tmpfile1 nil file-notify--test-desc nil file-notify--test-results nil - file-notify--test-events nil) + file-notify--test-events nil + file-notify--test-expected-events nil) (when file-notify--test-event (error "file-notify--test-event should not be set but bound dynamically"))) @@ -226,13 +229,16 @@ being the result.") "Ert test function to be called by `file-notify--test-event-handler'. We cannot pass arguments, so we assume that `file-notify--test-event' is bound somewhere." - ;;(message "Event %S" file-notify--test-event) ;; Check the descriptor. (should (equal (car file-notify--test-event) file-notify--test-desc)) ;; Check the file name. (should - (string-equal (file-notify--event-file-name file-notify--test-event) - file-notify--test-tmpfile)) + (or (string-equal (file-notify--event-file-name file-notify--test-event) + file-notify--test-tmpfile) + (string-equal (directory-file-name + (file-name-directory + (file-notify--event-file-name file-notify--test-event))) + file-notify--test-tmpfile))) ;; Check the second file name if exists. (when (eq (nth 1 file-notify--test-event) 'renamed) (should @@ -247,10 +253,15 @@ and the event to `file-notify--test-events'." (let* ((file-notify--test-event event) (result (ert-run-test (make-ert-test :body 'file-notify--test-event-test)))) - (setq file-notify--test-events - (append file-notify--test-events `(,file-notify--test-event)) - file-notify--test-results - (append file-notify--test-results `(,result))))) + ;; Do not add temporary files, this would confuse the checks. + (unless (string-match + (regexp-quote ".#") + (file-notify--event-file-name file-notify--test-event)) + ;;(message "file-notify--test-event-handler %S" file-notify--test-event) + (setq file-notify--test-events + (append file-notify--test-events `(,file-notify--test-event)) + file-notify--test-results + (append file-notify--test-results `(,result)))))) (defun file-notify--test-make-temp-name () "Create a temporary file name for test." @@ -270,6 +281,8 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (declare (indent 2)) (let ((outer (make-symbol "outer"))) `(let ((,outer file-notify--test-events)) + (setq file-notify--test-expected-events + (append file-notify--test-expected-events ,events)) (let (file-notify--test-events) ,@body (file-notify--wait-for-events @@ -281,21 +294,47 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (ert-deftest file-notify-test02-events () "Check file creation/change/removal notifications." (skip-unless (file-notify--test-local-enabled)) + + (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) + file-notify--test-tmpfile1 (file-notify--test-make-temp-name)) + (unwind-protect (progn - ;; Check creation, change, and deletion. - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-tmpfile1 (file-notify--test-make-temp-name) - file-notify--test-desc + ;; Check creation, change and deletion. + (setq file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile '(change) 'file-notify--test-event-handler)) (file-notify--test-with-events - (file-notify--test-timeout) '(created changed deleted stopped) + (file-notify--test-timeout) '(created changed deleted) (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) (delete-file file-notify--test-tmpfile)) - (file-notify-rm-watch file-notify--test-desc) + ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. + (let (file-notify--test-events) + (file-notify-rm-watch file-notify--test-desc)) + + ;; Check creation, change and deletion. There must be a + ;; `stopped' event when deleting the directory. It doesn't + ;; work for w32notify. + (unless (eq file-notify--library 'w32notify) + (make-directory file-notify--test-tmpfile) + (setq file-notify--test-desc + (file-notify-add-watch + file-notify--test-tmpfile + '(change) 'file-notify--test-event-handler)) + (file-notify--test-with-events + (file-notify--test-timeout) + ;; There are two `deleted' events, for the file and for + ;; the directory. + '(created changed deleted deleted stopped) + (write-region + "any text" nil (expand-file-name "foo" file-notify--test-tmpfile) + nil 'no-message) + (delete-directory file-notify--test-tmpfile 'recursive)) + ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. + (let (file-notify--test-events) + (file-notify-rm-watch file-notify--test-desc))) ;; Check copy. (setq file-notify--test-desc @@ -308,8 +347,8 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." ;; w32notify does not distinguish between `changed' and ;; `attribute-changed'. (if (eq file-notify--library 'w32notify) - '(created changed changed deleted stopped) - '(created changed deleted stopped)) + '(created changed changed deleted) + '(created changed deleted)) (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) (copy-file file-notify--test-tmpfile file-notify--test-tmpfile1) @@ -319,7 +358,9 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (set-file-times file-notify--test-tmpfile '(0 0)) (delete-file file-notify--test-tmpfile) (delete-file file-notify--test-tmpfile1)) - (file-notify-rm-watch file-notify--test-desc) + ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. + (let (file-notify--test-events) + (file-notify-rm-watch file-notify--test-desc)) ;; Check rename. (setq file-notify--test-desc @@ -328,13 +369,15 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." '(change) 'file-notify--test-event-handler)) (should file-notify--test-desc) (file-notify--test-with-events - (file-notify--test-timeout) '(created changed renamed stopped) + (file-notify--test-timeout) '(created changed renamed) (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) (rename-file file-notify--test-tmpfile file-notify--test-tmpfile1) ;; After the rename, we won't get events anymore. (delete-file file-notify--test-tmpfile1)) - (file-notify-rm-watch file-notify--test-desc) + ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. + (let (file-notify--test-events) + (file-notify-rm-watch file-notify--test-desc)) ;; Check attribute change. It doesn't work for w32notify. (unless (eq file-notify--library 'w32notify) @@ -359,29 +402,16 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (set-file-times file-notify--test-tmpfile '(0 0)) (read-event nil nil 0.1) (delete-file file-notify--test-tmpfile)) - (file-notify-rm-watch file-notify--test-desc)) + ;; `file-notify-rm-watch' fires the `stopped' event. Suppress it. + (let (file-notify--test-events) + (file-notify-rm-watch file-notify--test-desc))) ;; Check the global sequence again just to make sure that ;; `file-notify--test-events' has been set correctly. - (should (equal - (mapcar #'cadr file-notify--test-events) - (if (eq file-notify--library 'w32notify) - '(created changed deleted stopped - created changed changed deleted stopped - created changed renamed stopped) - (if (file-remote-p temporary-file-directory) - '(created changed deleted stopped - created changed deleted stopped - created changed renamed stopped - attribute-changed attribute-changed - attribute-changed stopped) - '(created changed deleted stopped - created changed deleted stopped - created changed renamed stopped - attribute-changed attribute-changed stopped))))) + (should (equal (mapcar #'cadr file-notify--test-events) + file-notify--test-expected-events)) (should file-notify--test-results) (dolist (result file-notify--test-results) - ;;(message "%s" (ert-test-result-messages result)) (when (ert-test-failed-p result) (ert-fail (cadr (ert-test-result-with-condition-condition result)))))) @@ -463,41 +493,16 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." file-notify--test-tmpfile '(change) #'file-notify--test-event-handler)) (file-notify--test-with-events - (file-notify--test-timeout) '(created changed) + (file-notify--test-timeout) '(created changed deleted) (should (file-notify-valid-p file-notify--test-desc)) (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (should (file-notify-valid-p file-notify--test-desc))) - ;; After removing the watch, the descriptor must not be valid + (delete-file file-notify--test-tmpfile)) + ;; After deleting the file, the descriptor is still valid. + (should (file-notify-valid-p file-notify--test-desc)) + ;; After removing the watch, the descriptor must not be valid ;; anymore. (file-notify-rm-watch file-notify--test-desc) - (file-notify--wait-for-events - (file-notify--test-timeout) - (not (file-notify-valid-p file-notify--test-desc))) - (should-not (file-notify-valid-p file-notify--test-desc))) - - ;; Cleanup. - (file-notify--test-cleanup)) - - (unwind-protect - (progn - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) - file-notify--test-desc - (file-notify-add-watch - file-notify--test-tmpfile - '(change) #'file-notify--test-event-handler)) - (file-notify--test-with-events - (file-notify--test-timeout) '(created changed) - (should (file-notify-valid-p file-notify--test-desc)) - (write-region - "any text" nil file-notify--test-tmpfile nil 'no-message) - (should (file-notify-valid-p file-notify--test-desc))) - ;; After deleting the file, the descriptor must not be valid - ;; anymore. - (delete-file file-notify--test-tmpfile) - (file-notify--wait-for-events - (file-notify--test-timeout) - (not (file-notify-valid-p file-notify--test-desc))) (should-not (file-notify-valid-p file-notify--test-desc))) ;; Cleanup. @@ -506,26 +511,23 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (unwind-protect ;; The batch-mode operation of w32notify is fragile (there's no ;; input threads to send the message to). - (unless (and noninteractive (eq file-notify--library 'w32notify)) - (let ((temporary-file-directory (make-temp-file - "file-notify-test-parent" t))) + ;(unless (and noninteractive (eq file-notify--library 'w32notify)) + (unless (eq file-notify--library 'w32notify) + (let ((temporary-file-directory + (make-temp-file "file-notify-test-parent" t))) (setq file-notify--test-tmpfile (file-notify--test-make-temp-name) file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile '(change) #'file-notify--test-event-handler)) (file-notify--test-with-events - (file-notify--test-timeout) '(created changed) + (file-notify--test-timeout) '(created changed deleted stopped) (should (file-notify-valid-p file-notify--test-desc)) (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) - (should (file-notify-valid-p file-notify--test-desc))) - ;; After deleting the parent, the descriptor must not be - ;; valid anymore. - (delete-directory temporary-file-directory t) - (file-notify--wait-for-events - (file-notify--test-timeout) - (not (file-notify-valid-p file-notify--test-desc))) + (delete-directory temporary-file-directory t)) + ;; After deleting the parent directory, the descriptor must + ;; not be valid anymore. (should-not (file-notify-valid-p file-notify--test-desc)))) ;; Cleanup. @@ -540,8 +542,8 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (unwind-protect (progn - (setq file-notify--test-tmpfile (file-name-as-directory - (file-notify--test-make-temp-name))) + (setq file-notify--test-tmpfile + (file-name-as-directory (file-notify--test-make-temp-name))) (make-directory file-notify--test-tmpfile) (setq file-notify--test-desc (file-notify-add-watch @@ -551,6 +553,9 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." ;; After removing the watch, the descriptor must not be valid ;; anymore. (file-notify-rm-watch file-notify--test-desc) + (file-notify--wait-for-events + (file-notify--test-timeout) + (not (file-notify-valid-p file-notify--test-desc))) (should-not (file-notify-valid-p file-notify--test-desc))) ;; Cleanup. @@ -560,8 +565,8 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." ;; The batch-mode operation of w32notify is fragile (there's no ;; input threads to send the message to). (unless (and noninteractive (eq file-notify--library 'w32notify)) - (setq file-notify--test-tmpfile (file-name-as-directory - (file-notify--test-make-temp-name))) + (setq file-notify--test-tmpfile + (file-name-as-directory (file-notify--test-make-temp-name))) (make-directory file-notify--test-tmpfile) (setq file-notify--test-desc (file-notify-add-watch @@ -589,5 +594,10 @@ Don't wait longer than TIMEOUT seconds for the events to be delivered." (ert-run-tests-interactively "^file-notify-") (ert-run-tests-batch "^file-notify-"))) +;; TODO: + +;; * It does not work yet for local gfilenotify and remote inotifywait. +;; * For w32notify, no stopped events arrive when a directory is removed. + (provide 'file-notify-tests) ;;; file-notify-tests.el ends here commit 934bfb933f4981b2edaa208186e2f8781ab6cb9f Author: Artur Malabarba Date: Mon Oct 26 10:05:09 2015 +0000 * src/keyboard.c (post-command-hook): Shorten docstring diff --git a/src/keyboard.c b/src/keyboard.c index 4ea0f97..8512078 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -11385,13 +11385,9 @@ If an unhandled error happens in running this hook, the function in which the error occurred is unconditionally removed, since otherwise the error might happen repeatedly and make Emacs nonfunctional. -It is usually a bad idea to use this hook for expensive processing. -If unavoidable, `while-no-input' can be used avoid making Emacs -unresponsive while the user types. Furthermore, this hook is run -before redisplay, so the effect of the executed command won't be -displayed on the buffer until after the hook has finished (giving the -impression that Emacs is hanging). You can call `redisplay' inside -`while-no-input' to avoid this. +It is a bad idea to use this hook for expensive processing. If +unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to +avoid making Emacs unresponsive while the user types. See also `pre-command-hook'. */); Vpost_command_hook = Qnil;