diff options
| author | Mattias EngdegÄrd | 2019-07-31 19:45:06 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2019-08-06 13:38:47 +0200 |
| commit | c676444a43e4634c1f98ec286b5bd9e46b23216b (patch) | |
| tree | 8381c0ef5720a92b845808e8e885f6b5976ee0a1 | |
| parent | 1d8b5bc8dd543ada2f3c46436e43ea27faa3cd0e (diff) | |
| download | emacs-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.texi | 15 | ||||
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/array.el | 5 | ||||
| -rw-r--r-- | lisp/gnus/spam.el | 6 | ||||
| -rw-r--r-- | lisp/jsonrpc.el | 1 | ||||
| -rw-r--r-- | lisp/org/org-compat.el | 8 | ||||
| -rw-r--r-- | lisp/org/org.el | 4 | ||||
| -rw-r--r-- | lisp/play/5x5.el | 8 | ||||
| -rw-r--r-- | lisp/proced.el | 11 | ||||
| -rw-r--r-- | lisp/progmodes/idlw-shell.el | 2 | ||||
| -rw-r--r-- | lisp/progmodes/idlwave.el | 25 | ||||
| -rw-r--r-- | lisp/simple.el | 3 | ||||
| -rw-r--r-- | lisp/strokes.el | 6 | ||||
| -rw-r--r-- | lisp/subr.el | 8 | ||||
| -rw-r--r-- | lisp/vc/diff-mode.el | 12 | ||||
| -rw-r--r-- | lisp/windmove.el | 2 | ||||
| -rw-r--r-- | test/lisp/subr-tests.el | 7 |
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 |
| 302 | with @code{if} and @code{cond} to express complicated conditions. The | 302 | @code{if} and @code{cond} to express complicated conditions. The |
| 303 | constructs @code{and} and @code{or} can also be used individually as | 303 | constructs @code{and} and @code{or} can also be used individually as |
| 304 | kinds of multiple conditional constructs. | 304 | kinds 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 | ||
| 423 | This function returns the boolean exclusive-or of @var{condition1} and | ||
| 424 | @var{condition2}. That is, @code{xor} returns @code{nil} if either | ||
| 425 | both arguments are @code{nil}, or both are non-@code{nil}. Otherwise, | ||
| 426 | it returns the value of that argument which is non-@code{nil}. | ||
| 427 | |||
| 428 | Note 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 |
| @@ -2512,6 +2512,13 @@ parameter to control descending into subdirectories, and a | |||
| 2512 | FOLLOW-SYMLINK parameter to say that symbolic links that point to | 2512 | FOLLOW-SYMLINK parameter to say that symbolic links that point to |
| 2513 | other directories should be followed. | 2513 | other directories should be followed. |
| 2514 | 2514 | ||
| 2515 | +++ | ||
| 2516 | ** New function 'xor' returns the boolean exclusive-or of its args. | ||
| 2517 | The function was previously defined in array.el, but has been moved to | ||
| 2518 | subr.el so that it is available by default. It now always returns the | ||
| 2519 | non-nil argument when the other is nil. Several duplicates of 'xor' | ||
| 2520 | in 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. | ||
| 214 | If only one of the arguments is non-nil, return it; otherwise | ||
| 215 | return 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. |
| 214 | Evaluate BODY with VAR bound to each car from LIST, in turn. | 222 | Evaluate 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. |
| 1792 | SWITCHED is non-nil if the patch is already applied." | 1792 | SWITCHED 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 | |||
| 592 | the prefix argument is reversed. | 592 | the prefix argument is reversed. |
| 593 | When `switch-to-buffer-obey-display-actions' is non-nil, | 593 | When `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))) |