aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2019-07-31 19:45:06 +0200
committerMattias EngdegÄrd2019-08-06 13:38:47 +0200
commitc676444a43e4634c1f98ec286b5bd9e46b23216b (patch)
tree8381c0ef5720a92b845808e8e885f6b5976ee0a1
parent1d8b5bc8dd543ada2f3c46436e43ea27faa3cd0e (diff)
downloademacs-c676444a43e4634c1f98ec286b5bd9e46b23216b.tar.gz
emacs-c676444a43e4634c1f98ec286b5bd9e46b23216b.zip
Add conditional operator xor to subr.el
Suggested by Oleh Krehel and implemented by Basil Contovounesios in the following thread: https://lists.gnu.org/archive/html/emacs-devel/2019-07/msg00547.html * lisp/array.el (xor): Move unused function from here... * lisp/subr.el: ...to here, and improve. * lisp/gnus/spam.el (spam-xor): * lisp/play/5x5.el (5x5-xor): * lisp/proced.el (proced-xor): * lisp/progmodes/idlwave.el (idlwave-xor): * lisp/vc/diff-mode.el (diff-xor): Define as obsolete aliases of, and replace all uses with, xor. * lisp/jsonrpc.el: Remove unused dependency on array.el. * lisp/org/org.el (org-xor): Move from here... * lisp/org/org-compat.el (org-xor): ...to here, as a compatibility shim for xor. * lisp/progmodes/idlw-shell.el (idlwave-shell-enable-all-bp): * lisp/simple.el (exchange-point-and-mark): * lisp/windmove.el (windmove-display-in-direction): Use xor. * lisp/strokes.el (strokes-xor): Remove commented-out xor implementation. * doc/lispref/control.texi (Control Structures): Extend menu entry for new combining condition. (Combining Conditions): * etc/NEWS (Lisp Changes): Document xor. * test/lisp/subr-tests.el (subr-test-xor): New test.
-rw-r--r--doc/lispref/control.texi15
-rw-r--r--etc/NEWS7
-rw-r--r--lisp/array.el5
-rw-r--r--lisp/gnus/spam.el6
-rw-r--r--lisp/jsonrpc.el1
-rw-r--r--lisp/org/org-compat.el8
-rw-r--r--lisp/org/org.el4
-rw-r--r--lisp/play/5x5.el8
-rw-r--r--lisp/proced.el11
-rw-r--r--lisp/progmodes/idlw-shell.el2
-rw-r--r--lisp/progmodes/idlwave.el25
-rw-r--r--lisp/simple.el3
-rw-r--r--lisp/strokes.el6
-rw-r--r--lisp/subr.el8
-rw-r--r--lisp/vc/diff-mode.el12
-rw-r--r--lisp/windmove.el2
-rw-r--r--test/lisp/subr-tests.el7
17 files changed, 72 insertions, 58 deletions
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index e98daf66e98..31948fa079f 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -38,7 +38,7 @@ structure constructs (@pxref{Macros}).
38@menu 38@menu
39* Sequencing:: Evaluation in textual order. 39* Sequencing:: Evaluation in textual order.
40* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}. 40* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}.
41* Combining Conditions:: @code{and}, @code{or}, @code{not}. 41* Combining Conditions:: @code{and}, @code{or}, @code{not}, and friends.
42* Pattern-Matching Conditional:: How to use @code{pcase} and friends. 42* Pattern-Matching Conditional:: How to use @code{pcase} and friends.
43* Iteration:: @code{while} loops. 43* Iteration:: @code{while} loops.
44* Generators:: Generic sequences and coroutines. 44* Generators:: Generic sequences and coroutines.
@@ -298,8 +298,8 @@ For example:
298@section Constructs for Combining Conditions 298@section Constructs for Combining Conditions
299@cindex combining conditions 299@cindex combining conditions
300 300
301 This section describes three constructs that are often used together 301 This section describes constructs that are often used together with
302with @code{if} and @code{cond} to express complicated conditions. The 302@code{if} and @code{cond} to express complicated conditions. The
303constructs @code{and} and @code{or} can also be used individually as 303constructs @code{and} and @code{or} can also be used individually as
304kinds of multiple conditional constructs. 304kinds of multiple conditional constructs.
305 305
@@ -419,6 +419,15 @@ This is not completely equivalent because it can evaluate @var{arg1} or
419@var{arg3})} never evaluates any argument more than once. 419@var{arg3})} never evaluates any argument more than once.
420@end defspec 420@end defspec
421 421
422@defun xor condition1 condition2
423This function returns the boolean exclusive-or of @var{condition1} and
424@var{condition2}. That is, @code{xor} returns @code{nil} if either
425both arguments are @code{nil}, or both are non-@code{nil}. Otherwise,
426it returns the value of that argument which is non-@code{nil}.
427
428Note that in contrast to @code{or}, both arguments are always evaluated.
429@end defun
430
422@node Pattern-Matching Conditional 431@node Pattern-Matching Conditional
423@section Pattern-Matching Conditional 432@section Pattern-Matching Conditional
424@cindex pcase 433@cindex pcase
diff --git a/etc/NEWS b/etc/NEWS
index a078bcebfc1..818875f7a03 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2512,6 +2512,13 @@ parameter to control descending into subdirectories, and a
2512FOLLOW-SYMLINK parameter to say that symbolic links that point to 2512FOLLOW-SYMLINK parameter to say that symbolic links that point to
2513other directories should be followed. 2513other directories should be followed.
2514 2514
2515+++
2516** New function 'xor' returns the boolean exclusive-or of its args.
2517The function was previously defined in array.el, but has been moved to
2518subr.el so that it is available by default. It now always returns the
2519non-nil argument when the other is nil. Several duplicates of 'xor'
2520in other packages are now obsolete aliases of 'xor'.
2521
2515 2522
2516* Changes in Emacs 27.1 on Non-Free Operating Systems 2523* Changes in Emacs 27.1 on Non-Free Operating Systems
2517 2524
diff --git a/lisp/array.el b/lisp/array.el
index 2fffe0197e8..965e97ff553 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -740,11 +740,6 @@ of `array-rows-numbered'."
740 ((> index limit) limit) 740 ((> index limit) limit)
741 (t index))) 741 (t index)))
742 742
743(defun xor (pred1 pred2)
744 "Return the logical exclusive or of predicates PRED1 and PRED2."
745 (and (or pred1 pred2)
746 (not (and pred1 pred2))))
747
748(defun current-line () 743(defun current-line ()
749 "Return the current buffer line at point. The first line is 0." 744 "Return the current buffer line at point. The first line is 0."
750 (count-lines (point-min) (line-beginning-position))) 745 (count-lines (point-min) (line-beginning-position)))
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index d752bf0efee..f990e0cba16 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -708,9 +708,7 @@ finds ham or spam.")
708 "Clear the `spam-caches' entry for a check." 708 "Clear the `spam-caches' entry for a check."
709 (remhash symbol spam-caches)) 709 (remhash symbol spam-caches))
710 710
711(defun spam-xor (a b) 711(define-obsolete-function-alias 'spam-xor 'xor "27.1")
712 "Logical A xor B."
713 (and (or a b) (not (and a b))))
714 712
715(defun spam-set-difference (list1 list2) 713(defun spam-set-difference (list1 list2)
716 "Return a set difference of LIST1 and LIST2. 714 "Return a set difference of LIST1 and LIST2.
@@ -2550,7 +2548,7 @@ With a non-nil REMOVE, remove the ADDRESSES."
2550 (goto-char (point-min)) 2548 (goto-char (point-min))
2551 (dolist (article articles) 2549 (dolist (article articles)
2552 (insert (spam-get-article-as-string article))) 2550 (insert (spam-get-article-as-string article)))
2553 (let* ((arg (if (spam-xor unregister article-is-spam-p) 2551 (let* ((arg (if (xor unregister article-is-spam-p)
2554 "-spam" 2552 "-spam"
2555 "-good")) 2553 "-good"))
2556 (status 2554 (status
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 0fffee68664..85fd40ecd26 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -43,7 +43,6 @@
43(require 'warnings) 43(require 'warnings)
44(require 'pcase) 44(require 'pcase)
45(require 'ert) ; to escape a `condition-case-unless-debug' 45(require 'ert) ; to escape a `condition-case-unless-debug'
46(require 'array) ; xor
47 46
48 47
49;;; Public API 48;;; Public API
diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el
index 062bb4c5ca9..bb927fedf93 100644
--- a/lisp/org/org-compat.el
+++ b/lisp/org/org-compat.el
@@ -362,6 +362,14 @@ use of this function is for the stuck project list."
362 362
363;;; Miscellaneous functions 363;;; Miscellaneous functions
364 364
365;; `xor' was added in Emacs 27.1.
366(defalias 'org-xor
367 (if (fboundp 'xor)
368 #'xor
369 (lambda (a b)
370 "Exclusive or."
371 (if a (not b) b))))
372
365(defun org-version-check (version feature level) 373(defun org-version-check (version feature level)
366 (let* ((v1 (mapcar 'string-to-number (split-string version "[.]"))) 374 (let* ((v1 (mapcar 'string-to-number (split-string version "[.]")))
367 (v2 (mapcar 'string-to-number (split-string emacs-version "[.]"))) 375 (v2 (mapcar 'string-to-number (split-string emacs-version "[.]")))
diff --git a/lisp/org/org.el b/lisp/org/org.el
index e4c075f8cdd..336c413c8c7 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -10068,10 +10068,6 @@ Note: this function also decodes single byte encodings like
10068 (char-to-string (string-to-number byte 16))) 10068 (char-to-string (string-to-number byte 16)))
10069 (cdr (split-string hex "%")) "")) 10069 (cdr (split-string hex "%")) ""))
10070 10070
10071(defun org-xor (a b)
10072 "Exclusive or."
10073 (if a (not b) b))
10074
10075(defun org-fixup-message-id-for-http (s) 10071(defun org-fixup-message-id-for-http (s)
10076 "Replace special characters in a message id, so it can be used in an http query." 10072 "Replace special characters in a message id, so it can be used in an http query."
10077 (when (string-match "%" s) 10073 (when (string-match "%" s)
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 28748cc3514..c5d46591231 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -435,8 +435,8 @@ should return a grid vector array that is the new solution."
435 (dotimes (y 5x5-grid-size) 435 (dotimes (y 5x5-grid-size)
436 (dotimes (x 5x5-grid-size) 436 (dotimes (x 5x5-grid-size)
437 (5x5-set-cell xored y x 437 (5x5-set-cell xored y x
438 (5x5-xor (5x5-cell current y x) 438 (xor (5x5-cell current y x)
439 (5x5-cell best y x))))) 439 (5x5-cell best y x)))))
440 (5x5-mutate-solution xored))) 440 (5x5-mutate-solution xored)))
441 441
442(defun 5x5-mutate-solution (solution) 442(defun 5x5-mutate-solution (solution)
@@ -931,9 +931,7 @@ lest."
931 931
932;; Support functions 932;; Support functions
933 933
934(defun 5x5-xor (x y) 934(define-obsolete-function-alias '5x5-xor 'xor "27.1")
935 "Boolean exclusive-or of X and Y."
936 (and (or x y) (not (and x y))))
937 935
938(defun 5x5-y-or-n-p (prompt) 936(defun 5x5-y-or-n-p (prompt)
939 "5x5 wrapper for `y-or-n-p' which respects the `5x5-hassle-me' setting." 937 "5x5 wrapper for `y-or-n-p' which respects the `5x5-hassle-me' setting."
diff --git a/lisp/proced.el b/lisp/proced.el
index db8bdb5ac80..24bc321f434 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -1194,10 +1194,7 @@ Return `equal' if T1 equals T2. Return nil otherwise."
1194 1194
1195;;; Sorting 1195;;; Sorting
1196 1196
1197(defsubst proced-xor (b1 b2) 1197(define-obsolete-function-alias 'proced-xor 'xor "27.1")
1198 "Return the logical exclusive or of args B1 and B2."
1199 (and (or b1 b2)
1200 (not (and b1 b2))))
1201 1198
1202(defun proced-sort-p (p1 p2) 1199(defun proced-sort-p (p1 p2)
1203 "Predicate for sorting processes P1 and P2." 1200 "Predicate for sorting processes P1 and P2."
@@ -1208,8 +1205,8 @@ Return `equal' if T1 equals T2. Return nil otherwise."
1208 (k2 (cdr (assq (car sorter) (cdr p2))))) 1205 (k2 (cdr (assq (car sorter) (cdr p2)))))
1209 ;; if the attributes are undefined, we should really abort sorting 1206 ;; if the attributes are undefined, we should really abort sorting
1210 (if (and k1 k2) 1207 (if (and k1 k2)
1211 (proced-xor (funcall (nth 1 sorter) k1 k2) 1208 (xor (funcall (nth 1 sorter) k1 k2)
1212 (nth 2 sorter)))) 1209 (nth 2 sorter))))
1213 (let ((sort-list proced-sort-internal) sorter predicate k1 k2) 1210 (let ((sort-list proced-sort-internal) sorter predicate k1 k2)
1214 (catch 'done 1211 (catch 'done
1215 (while (setq sorter (pop sort-list)) 1212 (while (setq sorter (pop sort-list))
@@ -1219,7 +1216,7 @@ Return `equal' if T1 equals T2. Return nil otherwise."
1219 (if (and k1 k2) 1216 (if (and k1 k2)
1220 (funcall (nth 1 sorter) k1 k2))) 1217 (funcall (nth 1 sorter) k1 k2)))
1221 (if (not (eq predicate 'equal)) 1218 (if (not (eq predicate 'equal))
1222 (throw 'done (proced-xor predicate (nth 2 sorter))))) 1219 (throw 'done (xor predicate (nth 2 sorter)))))
1223 (eq t predicate))))) 1220 (eq t predicate)))))
1224 1221
1225(defun proced-sort (process-alist sorter descend) 1222(defun proced-sort (process-alist sorter descend)
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index 188ec012cf7..e4f46bf8825 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -2604,7 +2604,7 @@ If ENABLE is non-nil, enable them instead."
2604 (let ((bpl (or bpl idlwave-shell-bp-alist)) disabled modified) 2604 (let ((bpl (or bpl idlwave-shell-bp-alist)) disabled modified)
2605 (while bpl 2605 (while bpl
2606 (setq disabled (idlwave-shell-bp-get (car bpl) 'disabled)) 2606 (setq disabled (idlwave-shell-bp-get (car bpl) 'disabled))
2607 (when (idlwave-xor (not disabled) (eq enable 'enable)) 2607 (when (xor (not disabled) (eq enable 'enable))
2608 (idlwave-shell-toggle-enable-current-bp 2608 (idlwave-shell-toggle-enable-current-bp
2609 (car bpl) (if (eq enable 'enable) 'enable 'disable) no-update) 2609 (car bpl) (if (eq enable 'enable) 'enable 'disable) no-update)
2610 (push (car bpl) modified)) 2610 (push (car bpl) modified))
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index 614d73e23b7..1b4b55c94f3 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -8813,9 +8813,8 @@ routines, and may have been scanned."
8813 8813
8814;; FIXME: Dynamically scoped vars need to use the `idlwave-' prefix. 8814;; FIXME: Dynamically scoped vars need to use the `idlwave-' prefix.
8815;; (defvar type) 8815;; (defvar type)
8816(defmacro idlwave-xor (a b) 8816
8817 `(and (or ,a ,b) 8817(define-obsolete-function-alias 'idlwave-xor 'xor "27.1")
8818 (not (and ,a ,b))))
8819 8818
8820(defun idlwave-routine-entry-compare (a b) 8819(defun idlwave-routine-entry-compare (a b)
8821 "Compare two routine info entries for sorting. 8820 "Compare two routine info entries for sorting.
@@ -8919,17 +8918,17 @@ This expects NAME TYPE IDLWAVE-TWIN-CLASS to be bound to the right values."
8919 ;; Now: follow JD's ideas about sorting. Looks really simple now, 8918 ;; Now: follow JD's ideas about sorting. Looks really simple now,
8920 ;; doesn't it? The difficult stuff is hidden above... 8919 ;; doesn't it? The difficult stuff is hidden above...
8921 (cond 8920 (cond
8922 ((idlwave-xor asysp bsysp) asysp) ; System entries first 8921 ((xor asysp bsysp) asysp) ; System entries first
8923 ((idlwave-xor aunresp bunresp) bunresp) ; Unresolved last 8922 ((xor aunresp bunresp) bunresp) ; Unresolved last
8924 ((and idlwave-sort-prefer-buffer-info 8923 ((and idlwave-sort-prefer-buffer-info
8925 (idlwave-xor abufp bbufp)) abufp) ; Buffers before non-buffers 8924 (xor abufp bbufp)) abufp) ; Buffers before non-buffers
8926 ((idlwave-xor acompp bcompp) acompp) ; Compiled entries 8925 ((xor acompp bcompp) acompp) ; Compiled entries
8927 ((idlwave-xor apathp bpathp) apathp) ; Library before non-library 8926 ((xor apathp bpathp) apathp) ; Library before non-library
8928 ((idlwave-xor anamep bnamep) anamep) ; Correct file names first 8927 ((xor anamep bnamep) anamep) ; Correct file names first
8929 ((and idlwave-twin-class anamep bnamep ; both file names match -> 8928 ((and idlwave-twin-class anamep bnamep ; both file names match ->
8930 (idlwave-xor adefp bdefp)) bdefp) ; __define after __method 8929 (xor adefp bdefp)) bdefp) ; __define after __method
8931 ((> anpath bnpath) t) ; Who is first on path? 8930 ((> anpath bnpath) t) ; Who is first on path?
8932 (t nil)))) ; Default 8931 (t nil)))) ; Default
8933 8932
8934(defun idlwave-routine-source-file (source) 8933(defun idlwave-routine-source-file (source)
8935 (if (nth 2 source) 8934 (if (nth 2 source)
diff --git a/lisp/simple.el b/lisp/simple.el
index 26b82479ff1..da20de4ad9c 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -5857,8 +5857,7 @@ mode temporarily."
5857 (goto-char omark) 5857 (goto-char omark)
5858 (cond (temp-highlight 5858 (cond (temp-highlight
5859 (setq-local transient-mark-mode (cons 'only transient-mark-mode))) 5859 (setq-local transient-mark-mode (cons 'only transient-mark-mode)))
5860 ((or (and arg (region-active-p)) ; (xor arg (not (region-active-p))) 5860 ((xor arg (not (region-active-p)))
5861 (not (or arg (region-active-p))))
5862 (deactivate-mark)) 5861 (deactivate-mark))
5863 (t (activate-mark))) 5862 (t (activate-mark)))
5864 nil)) 5863 nil))
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 0c671c43ac2..6edf58c7b6b 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -1524,12 +1524,6 @@ Encode/decode your strokes with \\[strokes-encode-buffer],
1524 (or (eq char ?\s) 1524 (or (eq char ?\s)
1525 (eq char ?*))) 1525 (eq char ?*)))
1526 1526
1527;;(defsubst strokes-xor (a b) ### Should I make this an inline function? ###
1528;; "T if one and only one of A and B is non-nil; otherwise, returns nil.
1529;;NOTE: Don't use this as a numeric xor since it treats all non-nil
1530;; values as t including `0' (zero)."
1531;; (eq (null a) (not (null b))))
1532
1533(defsubst strokes-xpm-encode-length-as-string (length) 1527(defsubst strokes-xpm-encode-length-as-string (length)
1534 "Given some LENGTH in [0,62) do a fast lookup of its encoding." 1528 "Given some LENGTH in [0,62) do a fast lookup of its encoding."
1535 (aref strokes-base64-chars length)) 1529 (aref strokes-base64-chars length))
diff --git a/lisp/subr.el b/lisp/subr.el
index 518575f6b4a..b22db65bb64 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -209,6 +209,14 @@ value of last one, or nil if there are none.
209 (declare (indent 1) (debug t)) 209 (declare (indent 1) (debug t))
210 (cons 'if (cons cond (cons nil body)))) 210 (cons 'if (cons cond (cons nil body))))
211 211
212(defsubst xor (cond1 cond2)
213 "Return the boolean exclusive-or of COND1 and COND2.
214If only one of the arguments is non-nil, return it; otherwise
215return nil."
216 (declare (pure t) (side-effect-free error-free))
217 (cond ((not cond1) cond2)
218 ((not cond2) cond1)))
219
212(defmacro dolist (spec &rest body) 220(defmacro dolist (spec &rest body)
213 "Loop over a list. 221 "Loop over a list.
214Evaluate BODY with VAR bound to each car from LIST, in turn. 222Evaluate BODY with VAR bound to each car from LIST, in turn.
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 81662cafeda..c4812e81d40 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1771,7 +1771,7 @@ Whitespace differences are ignored."
1771 (if (> (- (car forw) orig) (- orig (car back))) back forw) 1771 (if (> (- (car forw) orig) (- orig (car back))) back forw)
1772 (or back forw)))) 1772 (or back forw))))
1773 1773
1774(defsubst diff-xor (a b) (if a (if (not b) a) b)) 1774(define-obsolete-function-alias 'diff-xor 'xor "27.1")
1775 1775
1776(defun diff-find-source-location (&optional other-file reverse noprompt) 1776(defun diff-find-source-location (&optional other-file reverse noprompt)
1777 "Find current diff location within the source file. 1777 "Find current diff location within the source file.
@@ -1791,7 +1791,7 @@ SRC and DST are the two variants of text as returned by `diff-hunk-text'.
1791 SRC is the variant that was found in the buffer. 1791 SRC is the variant that was found in the buffer.
1792SWITCHED is non-nil if the patch is already applied." 1792SWITCHED is non-nil if the patch is already applied."
1793 (save-excursion 1793 (save-excursion
1794 (let* ((other (diff-xor other-file diff-jump-to-old-file)) 1794 (let* ((other (xor other-file diff-jump-to-old-file))
1795 (char-offset (- (point) (diff-beginning-of-hunk t))) 1795 (char-offset (- (point) (diff-beginning-of-hunk t)))
1796 ;; Check that the hunk is well-formed. Otherwise diff-mode and 1796 ;; Check that the hunk is well-formed. Otherwise diff-mode and
1797 ;; the user may disagree on what constitutes the hunk 1797 ;; the user may disagree on what constitutes the hunk
@@ -1917,7 +1917,7 @@ With a prefix argument, REVERSE the hunk."
1917 (insert (car new))) 1917 (insert (car new)))
1918 ;; Display BUF in a window 1918 ;; Display BUF in a window
1919 (set-window-point (display-buffer buf) (+ (car pos) (cdr new))) 1919 (set-window-point (display-buffer buf) (+ (car pos) (cdr new)))
1920 (diff-hunk-status-msg line-offset (diff-xor switched reverse) nil) 1920 (diff-hunk-status-msg line-offset (xor switched reverse) nil)
1921 (when diff-advance-after-apply-hunk 1921 (when diff-advance-after-apply-hunk
1922 (diff-hunk-next)))))) 1922 (diff-hunk-next))))))
1923 1923
@@ -1929,7 +1929,7 @@ With a prefix argument, try to REVERSE the hunk."
1929 (pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,switched) 1929 (pcase-let ((`(,buf ,line-offset ,pos ,src ,_dst ,switched)
1930 (diff-find-source-location nil reverse))) 1930 (diff-find-source-location nil reverse)))
1931 (set-window-point (display-buffer buf) (+ (car pos) (cdr src))) 1931 (set-window-point (display-buffer buf) (+ (car pos) (cdr src)))
1932 (diff-hunk-status-msg line-offset (diff-xor reverse switched) t))) 1932 (diff-hunk-status-msg line-offset (xor reverse switched) t)))
1933 1933
1934 1934
1935(defun diff-kill-applied-hunks () 1935(defun diff-kill-applied-hunks ()
@@ -1966,7 +1966,7 @@ revision of the file otherwise."
1966 (pop-to-buffer buf) 1966 (pop-to-buffer buf)
1967 (goto-char (+ (car pos) (cdr src))) 1967 (goto-char (+ (car pos) (cdr src)))
1968 (when buffer (next-error-found buffer (current-buffer))) 1968 (when buffer (next-error-found buffer (current-buffer)))
1969 (diff-hunk-status-msg line-offset (diff-xor reverse switched) t)))) 1969 (diff-hunk-status-msg line-offset (xor reverse switched) t))))
1970 1970
1971 1971
1972(defun diff-current-defun () 1972(defun diff-current-defun ()
@@ -2376,7 +2376,7 @@ fixed, visit it in a buffer."
2376 (interactive "P") 2376 (interactive "P")
2377 (save-excursion 2377 (save-excursion
2378 (goto-char (point-min)) 2378 (goto-char (point-min))
2379 (let* ((other (diff-xor other-file diff-jump-to-old-file)) 2379 (let* ((other (xor other-file diff-jump-to-old-file))
2380 (modified-buffers nil) 2380 (modified-buffers nil)
2381 (style (save-excursion 2381 (style (save-excursion
2382 (when (re-search-forward diff-hunk-header-re nil t) 2382 (when (re-search-forward diff-hunk-header-re nil t)
diff --git a/lisp/windmove.el b/lisp/windmove.el
index ab47565dfae..f5f51480db2 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -592,7 +592,7 @@ select the window with a displayed buffer, and the meaning of
592the prefix argument is reversed. 592the prefix argument is reversed.
593When `switch-to-buffer-obey-display-actions' is non-nil, 593When `switch-to-buffer-obey-display-actions' is non-nil,
594`switch-to-buffer' commands are also supported." 594`switch-to-buffer' commands are also supported."
595 (let* ((no-select (not (eq (consp arg) windmove-display-no-select))) ; xor 595 (let* ((no-select (xor (consp arg) windmove-display-no-select))
596 (old-window (or (minibuffer-selected-window) (selected-window))) 596 (old-window (or (minibuffer-selected-window) (selected-window)))
597 (new-window) 597 (new-window)
598 (minibuffer-depth (minibuffer-depth)) 598 (minibuffer-depth (minibuffer-depth))
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 0023680738d..b3c04cdc9a8 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -125,6 +125,13 @@
125 (should (equal (macroexpand-all '(when a b c d)) 125 (should (equal (macroexpand-all '(when a b c d))
126 '(if a (progn b c d))))) 126 '(if a (progn b c d)))))
127 127
128(ert-deftest subr-test-xor ()
129 "Test `xor'."
130 (should-not (xor nil nil))
131 (should (eq (xor nil 'true) 'true))
132 (should (eq (xor 'true nil) 'true))
133 (should-not (xor t t)))
134
128(ert-deftest subr-test-version-parsing () 135(ert-deftest subr-test-version-parsing ()
129 (should (equal (version-to-list ".5") '(0 5))) 136 (should (equal (version-to-list ".5") '(0 5)))
130 (should (equal (version-to-list "0.9 alpha1") '(0 9 -3 1))) 137 (should (equal (version-to-list "0.9 alpha1") '(0 9 -3 1)))