commit c88a3be8087ad0165415aa87c01f868a7433cb21 (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Mon Apr 20 22:26:30 2020 -0700 Fix string-to-multibyte overlong sequence bug * src/character.h (MULTIBYTE_LENGTH, MULTIBYTE_LENGTH_NO_CHECK): Remove, replacing with ... (multibyte_length): ... this new function. All callers changed. The new function rejects overlong multibyte forms. * test/src/buffer-tests.el (buffer-multibyte-overlong-sequences): New test. diff --git a/src/buffer.c b/src/buffer.c index 5398414e6e..53b3bd960c 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -2634,8 +2634,7 @@ current buffer is cleared. */) if (ASCII_CHAR_P (*p)) p++, pos++; else if (EQ (flag, Qt) - && ! CHAR_BYTE8_HEAD_P (*p) - && (bytes = MULTIBYTE_LENGTH (p, pend)) > 0) + && 0 < (bytes = multibyte_length (p, pend, true, false))) p += bytes, pos += bytes; else { diff --git a/src/character.c b/src/character.c index 303c83ccec..da09e77e13 100644 --- a/src/character.c +++ b/src/character.c @@ -486,7 +486,7 @@ multibyte_chars_in_text (const unsigned char *ptr, ptrdiff_t nbytes) while (ptr < endp) { - int len = MULTIBYTE_LENGTH (ptr, endp); + int len = multibyte_length (ptr, endp, true, true); if (len == 0) emacs_abort (); @@ -508,7 +508,6 @@ parse_str_as_multibyte (const unsigned char *str, ptrdiff_t len, ptrdiff_t *nchars, ptrdiff_t *nbytes) { const unsigned char *endp = str + len; - int n; ptrdiff_t chars = 0, bytes = 0; if (len >= MAX_MULTIBYTE_LENGTH) @@ -516,8 +515,8 @@ parse_str_as_multibyte (const unsigned char *str, ptrdiff_t len, const unsigned char *adjusted_endp = endp - MAX_MULTIBYTE_LENGTH; while (str < adjusted_endp) { - if (! CHAR_BYTE8_HEAD_P (*str) - && (n = MULTIBYTE_LENGTH_NO_CHECK (str)) > 0) + int n = multibyte_length (str, NULL, false, false); + if (0 < n) str += n, bytes += n; else str++, bytes += 2; @@ -526,8 +525,8 @@ parse_str_as_multibyte (const unsigned char *str, ptrdiff_t len, } while (str < endp) { - if (! CHAR_BYTE8_HEAD_P (*str) - && (n = MULTIBYTE_LENGTH (str, endp)) > 0) + int n = multibyte_length (str, endp, true, false); + if (0 < n) str += n, bytes += n; else str++, bytes += 2; @@ -554,20 +553,25 @@ str_as_multibyte (unsigned char *str, ptrdiff_t len, ptrdiff_t nbytes, unsigned char *p = str, *endp = str + nbytes; unsigned char *to; ptrdiff_t chars = 0; - int n; if (nbytes >= MAX_MULTIBYTE_LENGTH) { unsigned char *adjusted_endp = endp - MAX_MULTIBYTE_LENGTH; - while (p < adjusted_endp - && ! CHAR_BYTE8_HEAD_P (*p) - && (n = MULTIBYTE_LENGTH_NO_CHECK (p)) > 0) - p += n, chars++; + while (p < adjusted_endp) + { + int n = multibyte_length (p, NULL, false, false); + if (n <= 0) + break; + p += n, chars++; + } + } + while (true) + { + int n = multibyte_length (p, endp, true, false); + if (n <= 0) + break; + p += n, chars++; } - while (p < endp - && ! CHAR_BYTE8_HEAD_P (*p) - && (n = MULTIBYTE_LENGTH (p, endp)) > 0) - p += n, chars++; if (nchars) *nchars = chars; if (p == endp) @@ -584,8 +588,8 @@ str_as_multibyte (unsigned char *str, ptrdiff_t len, ptrdiff_t nbytes, unsigned char *adjusted_endp = endp - MAX_MULTIBYTE_LENGTH; while (p < adjusted_endp) { - if (! CHAR_BYTE8_HEAD_P (*p) - && (n = MULTIBYTE_LENGTH_NO_CHECK (p)) > 0) + int n = multibyte_length (p, NULL, false, false); + if (0 < n) { while (n--) *to++ = *p++; @@ -601,8 +605,8 @@ str_as_multibyte (unsigned char *str, ptrdiff_t len, ptrdiff_t nbytes, } while (p < endp) { - if (! CHAR_BYTE8_HEAD_P (*p) - && (n = MULTIBYTE_LENGTH (p, endp)) > 0) + int n = multibyte_length (p, endp, true, false); + if (0 < n) { while (n--) *to++ = *p++; diff --git a/src/character.h b/src/character.h index 81320dedd1..4887473b27 100644 --- a/src/character.h +++ b/src/character.h @@ -31,15 +31,19 @@ INLINE_HEADER_BEGIN /* character code 1st byte byte sequence -------------- -------- ------------- 0-7F 00..7F 0xxxxxxx - 80-7FF C2..DF 110xxxxx 10xxxxxx - 800-FFFF E0..EF 1110xxxx 10xxxxxx 10xxxxxx - 10000-1FFFFF F0..F7 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - 200000-3FFF7F F8 11111000 1000xxxx 10xxxxxx 10xxxxxx 10xxxxxx + 80-7FF C2..DF 110yyyyx 10xxxxxx + 800-FFFF E0..EF 1110yyyy 10yxxxxx 10xxxxxx + 10000-1FFFFF F0..F7 11110yyy 10yyxxxx 10xxxxxx 10xxxxxx + 200000-3FFF7F F8 11111000 1000yxxx 10xxxxxx 10xxxxxx 10xxxxxx 3FFF80-3FFFFF C0..C1 1100000x 10xxxxxx (for eight-bit-char) 400000-... invalid invalid 1st byte 80..BF 10xxxxxx - F9..FF 11111xxx (xxx != 000) + F9..FF 11111yyy + + In each bit pattern, 'x' and 'y' each represent a single bit of the + character code payload, and least one 'y' must be a 1 bit. + In the 5-byte sequence, the 22-bit payload cannot exceed 3FFF7F. */ /* Maximum character code ((1 << CHARACTERBITS) - 1). */ @@ -284,7 +288,7 @@ CHAR_HEAD_P (int byte) } /* How many bytes a character that starts with BYTE occupies in a - multibyte form. Unlike MULTIBYTE_LENGTH below, this function does not + multibyte form. Unlike multibyte_length, this function does not validate the multibyte form, but looks only at its first byte. */ INLINE int BYTES_BY_CHAR_HEAD (int byte) @@ -297,44 +301,54 @@ BYTES_BY_CHAR_HEAD (int byte) } -/* The byte length of multibyte form at unibyte string P ending at - PEND. If the string doesn't point to a valid multibyte form, - return 0. Unlike BYTES_BY_CHAR_HEAD, this macro validates the - multibyte form. */ +/* The byte length of the multibyte form at the unibyte string P, + ending at PEND if CHECK, and without a length check if !CHECK. + If ALLOW_8BIT, allow multibyte forms of eight-bit characters. + If the string doesn't point to a valid multibyte form, return 0. + Unlike BYTES_BY_CHAR_HEAD, this function validates the multibyte form. */ INLINE int -MULTIBYTE_LENGTH (unsigned char const *p, unsigned char const *pend) -{ - return (! (p < pend) ? 0 - : ! (p[0] & 0x80) ? 1 - : ! (p + 1 < pend && (p[1] & 0xC0) == 0x80) ? 0 - : (p[0] & 0xE0) == 0xC0 ? 2 - : ! (p + 2 < pend && (p[2] & 0xC0) == 0x80) ? 0 - : (p[0] & 0xF0) == 0xE0 ? 3 - : ! (p + 3 < pend && (p[3] & 0xC0) == 0x80) ? 0 - : (p[0] & 0xF8) == 0xF0 ? 4 - : ! (p + 4 < pend && (p[4] & 0xC0) == 0x80) ? 0 - : p[0] == 0xF8 && (p[1] & 0xF0) == 0x80 ? 5 - : 0); -} - - -/* Like MULTIBYTE_LENGTH, but don't check the ending address. The - multibyte form is still validated, unlike BYTES_BY_CHAR_HEAD. */ +multibyte_length (unsigned char const *p, unsigned char const *pend, + bool check, bool allow_8bit) +{ + if (!check || p < pend) + { + unsigned char c = p[0]; + if (c < 0x80) + return 1; + if (!check || p + 1 < pend) + { + /* The 'unsigned int' avoids int overflow in the 5-byte case. */ + unsigned int d = p[1]; + + if (TRAILING_CODE_P (d)) + { + if (allow_8bit ? (c & 0xE0) == 0xC0 : 0xC2 <= c && c <= 0xDF) + return 2; + if ((!check || p + 2 < pend) + && TRAILING_CODE_P (p[2])) + { + if ((c & 0xF0) == 0xE0 && ((c & 0x0F) | (d & 0x20))) + return 3; + if ((!check || p + 3 < pend) && TRAILING_CODE_P (p[3])) + { + if ((c & 0xF8) == 0xF0 && ((c & 0x07) | (d & 0x30))) + return 4; + if (c == 0xF8 && (!check || p + 4 < pend) + && TRAILING_CODE_P (p[4])) + { + unsigned int w = ((d << 24) + (p[2] << 16) + + (p[3] << 8) + p[4]); + if (0x88808080 <= w && w <= 0x8FBFBDBF) + return 5; + } + } + } + } + } + } -INLINE int -MULTIBYTE_LENGTH_NO_CHECK (unsigned char const *p) -{ - return (!(p[0] & 0x80) ? 1 - : (p[1] & 0xC0) != 0x80 ? 0 - : (p[0] & 0xE0) == 0xC0 ? 2 - : (p[2] & 0xC0) != 0x80 ? 0 - : (p[0] & 0xF0) == 0xE0 ? 3 - : (p[3] & 0xC0) != 0x80 ? 0 - : (p[0] & 0xF8) == 0xF0 ? 4 - : (p[4] & 0xC0) != 0x80 ? 0 - : p[0] == 0xF8 && (p[1] & 0xF0) == 0x80 ? 5 - : 0); + return 0; } diff --git a/src/coding.c b/src/coding.c index 716b0d9979..34f36d5a86 100644 --- a/src/coding.c +++ b/src/coding.c @@ -7670,15 +7670,17 @@ consume_chars (struct coding_system *coding, Lisp_Object translation_table, if (! multibytep) { - int bytes; - if (coding->encoder == encode_coding_raw_text || coding->encoder == encode_coding_ccl) c = *src++, pos++; - else if ((bytes = MULTIBYTE_LENGTH (src, src_end)) > 0) - c = STRING_CHAR_ADVANCE_NO_UNIFY (src), pos += bytes; else - c = BYTE8_TO_CHAR (*src), src++, pos++; + { + int bytes = multibyte_length (src, src_end, true, true); + if (0 < bytes) + c = STRING_CHAR_ADVANCE_NO_UNIFY (src), pos += bytes; + else + c = BYTE8_TO_CHAR (*src), src++, pos++; + } } else c = STRING_CHAR_ADVANCE_NO_UNIFY (src), pos++; @@ -7727,7 +7729,7 @@ consume_chars (struct coding_system *coding, Lisp_Object translation_table, for (i = 1; i < to_nchars; i++) *buf++ = XFIXNUM (AREF (trans, i)); for (i = 1; i < from_nchars; i++, pos++) - src += MULTIBYTE_LENGTH_NO_CHECK (src); + src += multibyte_length (src, NULL, false, true); } } diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 1c356698f6..6e87cb9489 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -1313,4 +1313,18 @@ with parameters from the *Messages* buffer modification." (ovshould nonempty-eob-end 4 5) (ovshould empty-eob 5 5))))) +(ert-deftest buffer-multibyte-overlong-sequences () + (dolist (uni '("\xE0\x80\x80" + "\xF0\x80\x80\x80" + "\xF8\x8F\xBF\xBF\x80")) + (let ((multi (string-to-multibyte uni))) + (should + (string-equal + multi + (with-temp-buffer + (set-buffer-multibyte nil) + (insert uni) + (set-buffer-multibyte t) + (buffer-string))))))) + ;;; buffer-tests.el ends here commit 856d9378a49ec9ec1af2ea74fb9309fe4c39cd1d Author: Juri Linkov Date: Tue Apr 21 02:48:22 2020 +0300 * lisp/hi-lock.el (hi-lock--regexps-at-point): Use proper-list-p, not consp. diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index bf79e48f85..08d82173e4 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -567,8 +567,9 @@ in which case the highlighting will not update as you type." (let* ((faces-after (get-text-property (point) 'face)) (faces-before (unless (bobp) (get-text-property (1- (point)) 'face))) - (faces-after (if (consp faces-after) faces-after (list faces-after))) - (faces-before (if (consp faces-before) faces-before (list faces-before))) + ;; Use proper-list-p to handle faces like (foreground-color . "red3") + (faces-after (if (proper-list-p faces-after) faces-after (list faces-after))) + (faces-before (if (proper-list-p faces-before) faces-before (list faces-before))) (faces (mapcar #'hi-lock-keyword->face hi-lock-interactive-patterns)) (face-after (seq-some (lambda (face) (car (memq face faces))) faces-after)) commit ec248719327f6efc1c250259d6b6f1da02d3b363 Author: Eric Abrahamsen Date: Mon Apr 20 11:25:40 2020 -0700 Remove unnecessary lambda quoting * lisp/gnus/nntp.el (nntp-open-connection): Buffer has lexical-binding turned on. diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el index 6be6d11a48..02d90603b4 100644 --- a/lisp/gnus/nntp.el +++ b/lisp/gnus/nntp.el @@ -1247,8 +1247,8 @@ If SEND-IF-FORCE, only send authinfo to the server if the (and nntp-connection-timeout (run-at-time nntp-connection-timeout nil - `(lambda () - (nntp-kill-buffer ,pbuffer))))) + (lambda () + (nntp-kill-buffer pbuffer))))) (process (condition-case err (let ((coding-system-for-read 'binary) commit 60b97442f7fc42d029325f5cbcb6a8670dd15078 Author: Eli Zaretskii Date: Mon Apr 20 19:29:58 2020 +0300 Remove workaround from w32image.c * src/w32image.c (w32_load_image): Remove a workaround for a bug that is not needed anymore. This error was happening because GDI+ functions were called as CDECL, not as STDCALL. diff --git a/src/w32image.c b/src/w32image.c index 085a5db3ab..8d39a09dc7 100644 --- a/src/w32image.c +++ b/src/w32image.c @@ -447,8 +447,6 @@ w32_load_image (struct frame *f, struct image *img, if (delay >= 0) metadata = Fcons (Qdelay, Fcons (make_float (delay), metadata)); } - else if (status == Win32Error) /* FIXME! */ - status = Ok; } if (status == Ok) commit 477b9eaf45da1ebc4f2117d69df3571f0bf61e47 Merge: 80f04b5d7c 05089a4d65 Author: Glenn Morris Date: Mon Apr 20 07:50:19 2020 -0700 Merge from origin/emacs-27 05089a4d65 (origin/emacs-27) Tweak wording re constant variables a1040861f1 Tweak setcar-related wording 751510f865 * lisp/image-mode.el: Add prefix key 's' and reduce depend... 9261a219ec * doc/emacs/windows.texi (Window Convenience): Decribe mor... e1d42da0d6 Fix mutability glitches reported by Drew Adams 5805df74f5 Improve mutability doc dca35b31d0 Improve mutability documentation 81e7d7f111 Document that quoting yields constants 5734339f40 * doc/lispref/keymaps.texi (Extended Menu Items, Easy Menu... 14a570afae Remove #' and function quoting from lambda forms in manual d5ec18c66b * src/regex-emacs.c (re_match_2_internal): Rework comment ... 4df8a61117 Add new node "Image Mode" to Emacs Manual. d7d5ee6c57 ; Fix a typo in cmdargs.texi (bug#40701) 5e9db48fbe * doc/lispref/display.texi (Customizing Bitmaps): Fix typo. eebfb72c90 Document constant vs mutable objects better 6c187ed6b0 Improve documentation of 'sort-lines' 52288f4b66 Mention 'spam-stat-process-directory-age' in the documenta... 067b070598 ; Fix some typos and doc issues (bug#40695) # Conflicts: # etc/NEWS commit 80f04b5d7c817977a365a999693443c4e04e5223 Author: Stefan Kangas Date: Mon Apr 20 09:08:09 2020 +0200 * lisp/cdl.el: Use lexical binding. diff --git a/lisp/cdl.el b/lisp/cdl.el index adc05f1bb5..c8025a9f53 100644 --- a/lisp/cdl.el +++ b/lisp/cdl.el @@ -1,4 +1,4 @@ -;;; cdl.el --- Common Data Language (CDL) utility functions for GNU Emacs +;;; cdl.el --- Common Data Language (CDL) utility functions for GNU Emacs -*- lexical-binding: t -*- ;; Copyright (C) 1993, 2001-2020 Free Software Foundation, Inc. commit 18d09058983961f80920b61fe343736082940163 Author: Stefan Kangas Date: Mon Apr 20 07:00:06 2020 +0200 Silence byte-compiler after my previous commit * lisp/autoarg.el (autoarg-kp-digits): Silence byte-compiler. diff --git a/lisp/autoarg.el b/lisp/autoarg.el index eba7a187fa..d41527775f 100644 --- a/lisp/autoarg.el +++ b/lisp/autoarg.el @@ -59,9 +59,8 @@ ;; (define-key autoarg-mode-map [?\r] 'autoarg-terminate) (defvar autoarg-kp-digits - (let (alist) - (dotimes (i 10 alist) - (push (cons (intern (format "kp-%d" i)) i) alist)))) + (mapcar (lambda (i) (cons (intern (format "kp-%d" i)) i)) + (reverse (number-sequence 0 9)))) (defun autoarg-kp-digit-argument (arg) "Part of the numeric argument for the next command, like `digit-argument'." commit 05089a4d65831c5e873956f5f2d92a3d5672d405 Author: Paul Eggert Date: Sun Apr 19 19:52:53 2020 -0700 Tweak wording re constant variables * doc/lispref/objects.texi (Constants and Mutability): Tweak. Problem reported by Michael Heerdegen (Bug#40693#44). diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index b45eb7ad8a..abd258eb53 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -2400,7 +2400,8 @@ literal @code{"aaa"} yields a constant string, whereas the function call @code{(make-string 3 ?a)} yields a mutable string that can be changed via later calls to @code{aset}. - Modifying a constant symbol signals an error (@pxref{Constant Variables}). + Trying to modify a constant variable signals an error +(@pxref{Constant Variables}). A program should not attempt to modify other types of constants because the resulting behavior is undefined: the Lisp interpreter might or might not detect the error, and if it does not detect the error the commit a1040861f118881004f59866111f64cd0ae03b7a Author: Paul Eggert Date: Sun Apr 19 16:46:47 2020 -0700 Tweak setcar-related wording * doc/lispref/eval.texi (Self-Evaluating Forms): Change “primitives” to “operations”. Problem reported by Štěpán Němec in: https://lists.gnu.org/r/emacs-devel/2020-04/msg01146.html diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi index f33c2faac1..021604c514 100644 --- a/doc/lispref/eval.texi +++ b/doc/lispref/eval.texi @@ -160,7 +160,7 @@ contents unchanged. A self-evaluating form yields constant conses, vectors and strings, and you should not attempt to modify their contents via @code{setcar}, @code{aset} or -similar primitives. The Lisp interpreter might unify the constants +similar operations. The Lisp interpreter might unify the constants yielded by your program's self-evaluating forms, so that these constants might share structure. @xref{Constants and Mutability}. commit 751510f8659e49c94ab7981c3abc8fb421bf9ba9 Author: Juri Linkov Date: Mon Apr 20 02:07:43 2020 +0300 * lisp/image-mode.el: Add prefix key 's' and reduce dependency on ImageMagick. * lisp/image-mode.el (image-mode-map): Regroup existing keybindings and add new ones with the prefix key 's'. Remove condition ":visible (eq image-type 'imagemagick)" from menu. (image-toggle-display-image): Don't rotate again after user rotated manually. (image-transform-check-size): Remove check for imagemagick. (image-transform-properties, image-transform-set-scale) (image-transform-fit-to-height, image-transform-fit-to-width) (image-transform-set-rotation, image-transform-reset): Remove mentions of ImageMagick from docstrings since these commands now work without ImageMagick. diff --git a/etc/NEWS b/etc/NEWS index bca2037c17..091c831e9d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3556,6 +3556,8 @@ name to the kill ring. With a prefix argument, 'image-rotate' now rotates the image at point 90 degrees counter-clockwise, instead of the default clockwise. +*** 'image-mode' has a new key prefix 's' for transformation commands. + ** Modules --- diff --git a/lisp/image-mode.el b/lisp/image-mode.el index 22d7d91314..fbce1193cd 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -418,24 +418,40 @@ call." (defvar image-mode-map (let ((map (make-sparse-keymap))) + + ;; Toggling keys (define-key map "\C-c\C-c" 'image-toggle-display) (define-key map "\C-c\C-x" 'image-toggle-hex-display) - (define-key map (kbd "SPC") 'image-scroll-up) - (define-key map (kbd "S-SPC") 'image-scroll-down) - (define-key map (kbd "DEL") 'image-scroll-down) - (define-key map (kbd "RET") 'image-toggle-animation) + + ;; Transformation keys + (define-key map "sf" 'image-mode-fit-frame) + (define-key map "sh" 'image-transform-fit-to-height) + (define-key map "sw" 'image-transform-fit-to-width) + (define-key map "sr" 'image-transform-set-rotation) + (define-key map "s0" 'image-transform-reset) + (define-key map "ss" 'image-transform-set-scale) + + ;; Multi-frame keys + (define-key map (kbd "RET") 'image-toggle-animation) (define-key map "F" 'image-goto-frame) (define-key map "f" 'image-next-frame) (define-key map "b" 'image-previous-frame) - (define-key map "n" 'image-next-file) - (define-key map "p" 'image-previous-file) (define-key map "a+" 'image-increase-speed) (define-key map "a-" 'image-decrease-speed) (define-key map "a0" 'image-reset-speed) (define-key map "ar" 'image-reverse-speed) + + ;; File keys + (define-key map "n" 'image-next-file) + (define-key map "p" 'image-previous-file) (define-key map "w" 'image-mode-copy-file-name-as-kill) (define-key map "m" 'image-mode-mark-file) (define-key map "u" 'image-mode-unmark-file) + + ;; Scrolling keys + (define-key map (kbd "SPC") 'image-scroll-up) + (define-key map (kbd "S-SPC") 'image-scroll-down) + (define-key map (kbd "DEL") 'image-scroll-down) (define-key map [remap forward-char] 'image-forward-hscroll) (define-key map [remap backward-char] 'image-backward-hscroll) (define-key map [remap right-char] 'image-forward-hscroll) @@ -452,6 +468,7 @@ call." (define-key map [remap move-end-of-line] 'image-eol) (define-key map [remap beginning-of-buffer] 'image-bob) (define-key map [remap end-of-buffer] 'image-eob) + (easy-menu-define image-mode-menu map "Menu for Image mode." '("Image" ["Show as Text" image-toggle-display :active t @@ -459,17 +476,15 @@ call." ["Show as Hex" image-toggle-hex-display :active t :help "Show image as hex"] "--" + ["Fit Frame to Image" image-mode-fit-frame :active t + :help "Resize frame to match image"] ["Fit to Window Height" image-transform-fit-to-height - :visible (eq image-type 'imagemagick) :help "Resize image to match the window height"] ["Fit to Window Width" image-transform-fit-to-width - :visible (eq image-type 'imagemagick) :help "Resize image to match the window width"] ["Rotate Image..." image-transform-set-rotation - :visible (eq image-type 'imagemagick) :help "Rotate the image"] ["Reset Transformations" image-transform-reset - :visible (eq image-type 'imagemagick) :help "Reset all image transformations"] "--" ["Show Thumbnails" @@ -486,9 +501,6 @@ call." :active buffer-file-name :help "Copy the current file name to the kill ring"] "--" - ["Fit Frame to Image" image-mode-fit-frame :active t - :help "Resize frame to match image"] - "--" ["Animate Image" image-toggle-animation :style toggle :selected (let ((image (image-get-display-property))) (and image (image-animate-timer image))) @@ -767,11 +779,12 @@ was inserted." props image) ;; Get the rotation data from the file, if any. - (setq image-transform-rotation - (or (exif-orientation - (ignore-error exif-error - (exif-parse-buffer))) - 0.0)) + (when (zerop image-transform-rotation) ; don't reset modified value + (setq image-transform-rotation + (or (exif-orientation + (ignore-error exif-error + (exif-parse-buffer))) + 0.0))) ;; :scale 1: If we do not set this, create-image will apply ;; default scaling based on font size. @@ -1250,8 +1263,7 @@ Do this for an image of type `imagemagick' to make sure that the elisp code matches the way ImageMagick computes the bounding box of a rotated image." (when (and (not (numberp image-transform-resize)) - (boundp 'image-type) - (eq image-type 'imagemagick)) + (boundp 'image-type)) (let ((size (image-display-size (image-get-display-property) t))) (cond ((eq image-transform-resize 'fit-width) (cl-assert (= (car size) @@ -1268,10 +1280,7 @@ of a rotated image." "Return rescaling/rotation properties for image SPEC. These properties are determined by the Image mode variables `image-transform-resize' and `image-transform-rotation'. The -return value is suitable for appending to an image spec. - -Rescaling and rotation properties only take effect if Emacs is -compiled with ImageMagick support." +return value is suitable for appending to an image spec." (setq image-transform-scale 1.0) (when (or image-transform-resize (/= image-transform-rotation 0.0)) @@ -1302,41 +1311,32 @@ compiled with ImageMagick support." (list :rotation image-transform-rotation)))))) (defun image-transform-set-scale (scale) - "Prompt for a number, and resize the current image by that amount. -This command has no effect unless Emacs is compiled with -ImageMagick support." + "Prompt for a number, and resize the current image by that amount." (interactive "nScale: ") (setq image-transform-resize scale) (image-toggle-display-image)) (defun image-transform-fit-to-height () - "Fit the current image to the height of the current window. -This command has no effect unless Emacs is compiled with -ImageMagick support." + "Fit the current image to the height of the current window." (interactive) (setq image-transform-resize 'fit-height) (image-toggle-display-image)) (defun image-transform-fit-to-width () - "Fit the current image to the width of the current window. -This command has no effect unless Emacs is compiled with -ImageMagick support." + "Fit the current image to the width of the current window." (interactive) (setq image-transform-resize 'fit-width) (image-toggle-display-image)) (defun image-transform-set-rotation (rotation) "Prompt for an angle ROTATION, and rotate the image by that amount. -ROTATION should be in degrees. This command has no effect unless -Emacs is compiled with ImageMagick support." +ROTATION should be in degrees." (interactive "nRotation angle (in degrees): ") (setq image-transform-rotation (float (mod rotation 360))) (image-toggle-display-image)) (defun image-transform-reset () - "Display the current image with the default size and rotation. -This command has no effect unless Emacs is compiled with -ImageMagick support." + "Display the current image with the default size and rotation." (interactive) (setq image-transform-resize nil image-transform-rotation 0.0 commit 9261a219ec20340b3323015b756ef023901aed43 Author: Juri Linkov Date: Mon Apr 20 01:57:32 2020 +0300 * doc/emacs/windows.texi (Window Convenience): Decribe more windmove features. * doc/emacs/windows.texi (Window Convenience): Add descriptions of windmove-display-default-keybindings, windmove-delete-default-keybindings, windmove-swap-states-in-direction. * etc/NEWS: Regroup to move some parts closer to related sections. diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index 2e07a98f57..910ef8fd88 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -586,13 +586,25 @@ buffer. @xref{Follow Mode}. @cindex directional window selection @findex windmove-right @findex windmove-default-keybindings +@findex windmove-display-default-keybindings +@findex windmove-delete-default-keybindings +@findex windmove-swap-states-in-direction The Windmove package defines commands for moving directionally between neighboring windows in a frame. @kbd{M-x windmove-right} selects the window immediately to the right of the currently selected -one, and similarly for the left, up, and down -counterparts. @w{@kbd{M-x windmove-default-keybindings}} binds these -commands to @kbd{S-right} etc.; doing so disables shift selection for -those keys (@pxref{Shift Selection}). +one, and similarly for the left, up, and down counterparts. +@w{@kbd{M-x windmove-default-keybindings}} binds these commands to +@kbd{S-right} etc.; doing so disables shift selection for those keys +(@pxref{Shift Selection}). In the same way as keybindings can be +defined for commands that select windows directionally, you can use +@w{@kbd{M-x windmove-display-default-keybindings}} to define +keybindings for commands that specify in what direction to display the +window for the buffer that the next command is going to display. +Also there is @w{@kbd{M-x windmove-delete-default-keybindings}} to +define keybindings for commands that delete windows directionally, and +@w{@kbd{M-x windmove-swap-states-in-direction}} that define +keybindings for commands that swap the window contents of the selected +window with the window in the specified direction. The command @kbd{M-x compare-windows} lets you compare the text shown in different windows. @xref{Comparing Files}. diff --git a/etc/NEWS b/etc/NEWS index def1bce29a..bca2037c17 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -934,7 +934,7 @@ back, customize 'follow-hide-ghost-cursors' to nil. *** 'windmove-create-window' when non-nil makes a new window. This happens upon moving off the edge of the frame. ---- ++++ *** Windmove supports directional window display and selection. The new command 'windmove-display-default-keybindings' binds default keys with provided modifiers (by default, Shift-Meta) to the commands @@ -948,7 +948,7 @@ display the buffer in the same window, for example, 'S-M-0 C-h e' displays the "*Messages*" buffer in the same window. 'S-M-t C-h C-n' displays NEWS in a new tab. ---- ++++ *** Windmove also supports directional window deletion. The new command 'windmove-delete-default-keybindings' binds default keys with provided prefix (by default, 'C-x') and modifiers (by default, @@ -958,7 +958,7 @@ With a prefix arg 'C-u', also kills the buffer in that window. With 'M-0', deletes the selected window and selects the window that was in the specified direction. ---- ++++ *** New command 'windmove-swap-states-in-direction' binds default keys to the commands that swap the states of the selected window with the window in the specified direction. @@ -1011,10 +1011,6 @@ remapped to these, respectively. ** Dired ---- -*** On systems that support suid/guid files, Dired now fontifies the -permissions of such files with a special face 'dired-set-id'. - +++ *** New command 'dired-create-empty-file'. @@ -1026,10 +1022,6 @@ It is by default bound to '* N'. *** The marking commands now report how many files were marked by the command itself, not how many files are marked in total. ---- -*** A new face, 'dired-special', is used to highlight sockets, named -pipes, block devices and character devices. - +++ *** The new user option 'dired-create-destination-dirs' controls whether 'dired-do-copy' and 'dired-rename-file' should create non-existent @@ -1047,6 +1039,14 @@ Dired performs file renaming using underlying version control system. *** Zstandard compression is now supported for 'dired-do-compress' and 'dired-do-compress-to'. +--- +*** On systems that support suid/guid files, Dired now fontifies the +permissions of such files with a special face 'dired-set-id'. + +--- +*** A new face, 'dired-special', is used to highlight sockets, named +pipes, block devices and character devices. + ** Find-Dired --- @@ -1068,12 +1068,6 @@ script. The default is nil. *** New command 'log-edit-generate-changelog-from-diff', bound to 'C-c C-w'. This generates ChangeLog entries from the VC fileset diff. ---- -*** 'vc-dir' now shows a button allowing you to hide the stash list. -Controlled by user option 'vc-git-show-stash'. Default t means show -the entire list as before. An integer value limits the list length -(but still allows you to show the entire list via the button). - +++ *** Recording ChangeLog entries doesn't require an actual file. If a ChangeLog file doesn't exist, and if the new user option @@ -1084,9 +1078,11 @@ still be used if it exists.) Set the user option to nil to get the previous behavior of always creating a buffer that visits a ChangeLog file. ---- -*** New user option 'vc-find-revision-no-save'. -With non-nil, 'vc-find-revision' doesn't write the created buffer to file. ++++ +*** The new 'd' command ('vc-dir-clean-files') in 'vc-dir-mode' +buffers will delete the marked files (or if no files are marked, the +file under point). This command does not notify the VC backend, and +is mostly useful for unregistered files. --- *** 'vc-dir-ignore' now takes a prefix argument to ignore all marked files. @@ -1101,6 +1097,12 @@ This new user option allows customizing the default arguments passed to When some files are marked, only those are stashed. When no files are marked, all modified files are stashed, as before. +--- +*** 'vc-dir' now shows a button allowing you to hide the stash list. +Controlled by user option 'vc-git-show-stash'. Default t means show +the entire list as before. An integer value limits the list length +(but still allows you to show the entire list via the button). + --- *** 'vc-git-stash' is now bound to 'C' in the stash headers. @@ -1133,25 +1135,19 @@ you invoke 'C-x v m' ('vc-merge'). instead of revision numbers as completion candidates when it prompts for a revision. -+++ -*** 'C-u C-x v D' ('vc-root-version-diff') prompts for two revisions -and compares their entire trees. - --- *** New user option 'vc-hg-revert-switches'. It specifies switches to pass to Hg's 'revert' command. ++++ +*** 'C-u C-x v D' ('vc-root-version-diff') prompts for two revisions +and compares their entire trees. + --- *** 'C-x v M D' ('vc-diff-mergebase') and 'C-x v M L' ('vc-log-mergebase') print diffs and logs between the merge base (common ancestor) of two given revisions. -+++ -*** The new 'd' command ('vc-dir-clean-files') in 'vc-dir-mode' -buffers will delete the marked files (or if no files are marked, the -file under point). This command does not notify the VC backend, and -is mostly useful for unregistered files. - +++ *** New command 'vc-log-search' asks for a pattern, searches it in the revision log, and displays matched log entries in the @@ -1169,6 +1165,10 @@ ID, and shows its log entry together with the diffs introduced by the revision's commit. (For some less capable VCSes, only the log entry is shown.) +--- +*** New user option 'vc-find-revision-no-save'. +With non-nil, 'vc-find-revision' doesn't write the created buffer to file. + --- *** 'C-x v =' can now mimic Magit's diff format. Set the new user option 'diff-font-lock-prettify' to t for that, see commit e1d42da0d686e93534ee2abebe79bff95f18cb4d Author: Paul Eggert Date: Sun Apr 19 15:09:02 2020 -0700 Fix mutability glitches reported by Drew Adams See Bug#40693#32. * doc/lispref/eval.texi (Self-Evaluating Forms, Backquote): Say that these yield constant conses, vectors and strings, not constant symbols. * doc/lispref/objects.texi (Constants and Mutability): Say that an attempt to modify a constant variable signals an error, instead of saying that it has undefined behavior. diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi index deb288943a..f33c2faac1 100644 --- a/doc/lispref/eval.texi +++ b/doc/lispref/eval.texi @@ -158,8 +158,8 @@ contents unchanged. @end group @end example - A self-evaluating form yields a constant, and you should not attempt -to modify the constant's contents via @code{setcar}, @code{aset} or + A self-evaluating form yields constant conses, vectors and strings, and you +should not attempt to modify their contents via @code{setcar}, @code{aset} or similar primitives. The Lisp interpreter might unify the constants yielded by your program's self-evaluating forms, so that these constants might share structure. @xref{Constants and Mutability}. @@ -704,8 +704,8 @@ Here are some examples: @end example If a subexpression of a backquote construct has no substitutions or -splices, it acts like @code{quote} in that it yields a constant that -should not be modified. +splices, it acts like @code{quote} in that it yields constant conses, +vectors and strings that should not be modified. @node Eval @section Eval diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index 98b001afd2..b45eb7ad8a 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -2395,17 +2395,19 @@ somewhere else. Although numbers are always constants and markers are always mutable, some types contain both constant and mutable members. These -types include conses, vectors, and strings. For example, the string +types include conses, vectors, strings, and symbols. For example, the string literal @code{"aaa"} yields a constant string, whereas the function call @code{(make-string 3 ?a)} yields a mutable string that can be changed via later calls to @code{aset}. - A program should not attempt to modify a constant because the + Modifying a constant symbol signals an error (@pxref{Constant Variables}). +A program should not attempt to modify other types of constants because the resulting behavior is undefined: the Lisp interpreter might or might not detect the error, and if it does not detect the error the interpreter can behave unpredictably thereafter. Another way to put -this is that mutable objects are safe to change, whereas constants are -not safely mutable: if you try to change a constant your program might +this is that although mutable objects are safe to change and constant +symbols reliably reject attempts to change them, other constants are +not safely mutable: if you try to change one your program might behave as you expect but it might crash or worse. This problem occurs with types that have both constant and mutable members, and that have mutators like @code{setcar} and @code{aset} that are valid on mutable commit 5805df74f5b919a3f67f3f7d31d6e600e1564e4e Author: Paul Eggert Date: Sun Apr 19 13:22:10 2020 -0700 Improve mutability doc See Eli Zaretskii’s suggestions (Bug#40671#33). * doc/lispref/lists.texi (Setcar, Setcdr, Rearrangement): * doc/lispref/sequences.texi (Sequence Functions) (Array Functions): Add commentary to examples. * doc/lispref/lists.texi (Sets And Lists): Revert change to delq example. diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index f1acc85616..1125af7bec 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -911,7 +911,7 @@ value @var{object}. For example: @example @group -(setq x (list 1 2)) +(setq x (list 1 2)) ; @r{Create a mutable list.} @result{} (1 2) @end group @group @@ -931,7 +931,7 @@ these lists. Here is an example: @example @group -;; @r{Create two lists that are partly shared.} +;; @r{Create two mutable lists that are partly shared.} (setq x1 (list 'a 'b 'c)) @result{} (a b c) (setq x2 (cons 'z (cdr x1))) @@ -1022,11 +1022,11 @@ reached via the @sc{cdr}. @example @group -(setq x (list 1 2 3)) +(setq x (list 1 2 3)) ; @r{Create a mutable list.} @result{} (1 2 3) @end group @group -(setcdr x '(4)) +(setcdr x '(4)) ; @r{Modify the list's tail to be a constant list.} @result{} (4) @end group @group @@ -1135,11 +1135,11 @@ Unlike @code{append} (@pxref{Building Lists}), the @var{lists} are @example @group -(setq x (list 1 2 3)) +(setq x (list 1 2 3)) ; @r{Create a mutable list.} @result{} (1 2 3) @end group @group -(nconc x '(4 5)) +(nconc x '(4 5)) ; @r{Modify the list's tail to be a constant list.} @result{} (1 2 3 4 5) @end group @group @@ -1267,9 +1267,7 @@ after those elements. For example: @example @group -(equal - (delq 'a (list 'a 'b 'c)) - (cdr (list 'a 'b 'c))) +(delq 'a '(a b c)) @equiv{} (cdr '(a b c)) @end group @end example diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 62d60156fb..1cb0d05cc7 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -183,11 +183,11 @@ for other ways to copy sequences. @example @group -(setq bar (list 1 2)) +(setq bar (list 1 2)) ; @r{Create a mutable list.} @result{} (1 2) @end group @group -(setq x (vector 'foo bar)) +(setq x (vector 'foo bar)) ; @r{Create a mutable vector.} @result{} [foo (1 2)] @end group @group @@ -278,7 +278,7 @@ Unlike @code{reverse} the original @var{sequence} may be modified. @example @group -(setq x (list 'a 'b 'c)) +(setq x (list 'a 'b 'c)) ; @r{Create a mutable list.} @result{} (a b c) @end group @group @@ -320,7 +320,7 @@ presented graphically: For the vector, it is even simpler because you don't need setq: @example -(setq x (copy-sequence [1 2 3 4])) +(setq x (copy-sequence [1 2 3 4])) ; @r{Create a mutable vector.} @result{} [1 2 3 4] (nreverse x) @result{} [4 3 2 1] @@ -374,7 +374,7 @@ appears in a different position in the list due to the change of @example @group -(setq nums (list 1 3 2 6 5 4 0)) +(setq nums (list 1 3 2 6 5 4 0)) ; @r{Create a mutable list.} @result{} (1 3 2 6 5 4 0) @end group @group @@ -1228,7 +1228,7 @@ This function sets the @var{index}th element of @var{array} to be @example @group -(setq w (vector 'foo 'bar 'baz)) +(setq w (vector 'foo 'bar 'baz)) ; @r{Create a mutable vector.} @result{} [foo bar baz] (aset w 0 'fu) @result{} fu @@ -1262,6 +1262,7 @@ each element of @var{array} is @var{object}. It returns @var{array}. @example @group +;; @r{Create a mutable vector and then fill it with zeros.} (setq a (copy-sequence [a b c d e f g])) @result{} [a b c d e f g] (fillarray a 0) @@ -1270,6 +1271,7 @@ a @result{} [0 0 0 0 0 0 0] @end group @group +;; @r{Create a mutable string and then fill it with "-".} (setq s (copy-sequence "When in the course")) @result{} "When in the course" (fillarray s ?-) commit dca35b31d0a58efdcc698faf90493b96fa8e1406 Author: Paul Eggert Date: Sun Apr 19 12:00:49 2020 -0700 Improve mutability documentation This change was inspired by comments from Štěpán Němec in: https://lists.gnu.org/r/emacs-devel/2020-04/msg01063.html * doc/lispref/objects.texi (Lisp Data Types): Mention mutability. (Constants and mutability): New section. * doc/lispintro/emacs-lisp-intro.texi (Lists diagrammed) (Indent Tabs Mode): Improve wording. * doc/lispref/eval.texi (Self-Evaluating Forms): Say that they return constants. * doc/lispref/lists.texi (Sets And Lists): Fix memql mistake/confusion that I recently introduced. diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 630676d978..ea16d9ef15 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -9557,7 +9557,7 @@ part of which is the address of the next pair. The very last box points to the symbol @code{nil}, which marks the end of the list. @need 1200 -When a variable is set to a list via @code{setq}, +When a variable is set to a list with an operation such as @code{setq}, it stores the address of the first box in the variable. Thus, evaluation of the expression @@ -17140,7 +17140,7 @@ The following turns off Indent Tabs mode: @end smallexample Note that this line uses @code{setq-default} rather than the -@code{setq} that we have seen before. The @code{setq-default} +@code{setq} that we have seen before; @code{setq-default} sets values only in buffers that do not have their own local values for the variable. diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi index cfd96f7aa6..bba1b63115 100644 --- a/doc/lispref/elisp.texi +++ b/doc/lispref/elisp.texi @@ -297,6 +297,7 @@ Lisp Data Types * Circular Objects:: Read syntax for circular structure. * Type Predicates:: Tests related to types. * Equality Predicates:: Tests of equality between any two objects. +* Constants and Mutability:: Whether an object's value can change. Programming Types diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi index 46cfab164b..deb288943a 100644 --- a/doc/lispref/eval.texi +++ b/doc/lispref/eval.texi @@ -158,6 +158,12 @@ contents unchanged. @end group @end example + A self-evaluating form yields a constant, and you should not attempt +to modify the constant's contents via @code{setcar}, @code{aset} or +similar primitives. The Lisp interpreter might unify the constants +yielded by your program's self-evaluating forms, so that these +constants might share structure. @xref{Constants and Mutability}. + It is common to write numbers, characters, strings, and even vectors in Lisp code, taking advantage of the fact that they self-evaluate. However, it is quite unusual to do this for types that lack a read @@ -559,6 +565,7 @@ and vectors.) @defspec quote object This special form returns @var{object}, without evaluating it. The returned value is a constant, and should not be modified. +@xref{Constants and Mutability}. @end defspec @cindex @samp{'} for quoting diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index c2771b0165..f1acc85616 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -866,16 +866,15 @@ foo ;; @r{@code{foo} was changed.} @node Modifying Lists @section Modifying Existing List Structure @cindex destructive list operations -@cindex constant lists @cindex mutable lists You can modify the @sc{car} and @sc{cdr} contents of a cons cell with the primitives @code{setcar} and @code{setcdr}. These are destructive operations because they change existing list structure. -Destructive operations should be applied only to @dfn{mutable} lists, +Destructive operations should be applied only to mutable lists, that is, lists constructed via @code{cons}, @code{list} or similar operations. Lists created by quoting are constants and should not be -changed by destructive operations. +changed by destructive operations. @xref{Constants and Mutability}. @cindex CL note---@code{rplaca} vs @code{setcar} @quotation @@ -1169,9 +1168,9 @@ x @end group @end example -However, the other arguments (all but the last) must be mutable lists. +However, the other arguments (all but the last) should be mutable lists. -A common pitfall is to use a quoted constant list as a non-last +A common pitfall is to use a constant list as a non-last argument to @code{nconc}. If you do this, the resulting behavior is undefined. It is possible that your program will change each time you run it! Here is what might happen (though this @@ -1359,12 +1358,12 @@ Compare this with @code{memq}: @example @group -(memql 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} are @code{eql}.} +(memql 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} must be @code{eql}.} @result{} (1.2 1.3) @end group @group -(memq (list 2) '((1) (2))) ; @r{@code{(list 2)} and @code{(2)} are not @code{eq}.} - @result{} nil +(memq 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} need not be @code{eq}.} + @result{} nil ; @r{... or it might be @code{(1.2 1.3)}.} @end group @end example @end defun @@ -1628,6 +1627,7 @@ keys may not be symbols: '(("simple leaves" . oak) ("compound leaves" . horsechestnut))) +;; @r{The @code{copy-sequence} means the keys are not @code{eq}.} (assq (copy-sequence "simple leaves") leaves) @result{} nil (assoc (copy-sequence "simple leaves") leaves) diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index 1c4e7e4d4e..98b001afd2 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -46,6 +46,10 @@ you store in it, type and all. (Actually, a small number of Emacs Lisp variables can only take on values of a certain type. @xref{Variables with Restricted Values}.) + Some Lisp objects are @dfn{constant}: their values never change. +Others are @dfn{mutable}: their values can be changed via destructive +operations that involve side effects. + This chapter describes the purpose, printed representation, and read syntax of each of the standard types in GNU Emacs Lisp. Details on how to use these types can be found in later chapters. @@ -59,6 +63,7 @@ to use these types can be found in later chapters. * Circular Objects:: Read syntax for circular structure. * Type Predicates:: Tests related to types. * Equality Predicates:: Tests of equality between any two objects. +* Constants and Mutability:: Whether an object's value can change. @end menu @node Printed Representation @@ -2373,3 +2378,43 @@ that for two strings to be equal, they have the same text properties. @end group @end example @end defun + +@node Constants and Mutability +@section Constants and Mutability +@cindex constants +@cindex mutable objects + + Some Lisp objects are constant: their values never change. +For example, you can create a new integer by calculating one, but you +cannot modify the value of an existing integer. + + Other Lisp objects are mutable: their values can be changed +via destructive operations involving side effects. For example, an +existing marker can be changed by moving the marker to point to +somewhere else. + + Although numbers are always constants and markers are always +mutable, some types contain both constant and mutable members. These +types include conses, vectors, and strings. For example, the string +literal @code{"aaa"} yields a constant string, whereas the function +call @code{(make-string 3 ?a)} yields a mutable string that can be +changed via later calls to @code{aset}. + + A program should not attempt to modify a constant because the +resulting behavior is undefined: the Lisp interpreter might or might +not detect the error, and if it does not detect the error the +interpreter can behave unpredictably thereafter. Another way to put +this is that mutable objects are safe to change, whereas constants are +not safely mutable: if you try to change a constant your program might +behave as you expect but it might crash or worse. This problem occurs +with types that have both constant and mutable members, and that have +mutators like @code{setcar} and @code{aset} that are valid on mutable +objects but hazardous on constants. + + When the same constant occurs multiple times in a program, the Lisp +interpreter might save time or space by reusing existing constants or +constant components. For example, @code{(eq "abc" "abc")} returns +@code{t} if the interpreter creates only one instance of the string +constant @code{"abc"}, and returns @code{nil} if it creates two +instances. Lisp programs should be written so that they work +regardless of whether this optimization is in use. diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 7a3f26e584..62d60156fb 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -1249,7 +1249,7 @@ x The @var{array} should be mutable; that is, it should not be a constant, such as the constants created via quoting or via self-evaluating forms. -@xref{Self-Evaluating Forms}. +@xref{Constants and Mutability}. If @var{array} is a string and @var{object} is not a character, a @code{wrong-type-argument} error results. The function converts a @@ -1306,10 +1306,10 @@ same way in Lisp input. A vector, like a string or a number, is considered a constant for evaluation: the result of evaluating it is the same vector. This does -not evaluate or even examine the elements of the vector. Vectors -written with square brackets are constants and should not be modified -via @code{aset} or other destructive operations. -@xref{Self-Evaluating Forms}. +not evaluate or even examine the elements of the vector. +@xref{Self-Evaluating Forms}. Vectors written with square brackets +are constants and should not be modified via @code{aset} or other +destructive operations. @xref{Constants and Mutability}. Here are examples illustrating these principles: diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 3acbf538dc..a4c9c2549c 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -384,6 +384,7 @@ usual value is @w{@code{"[ \f\t\n\r\v]+"}}. You can alter the contents of a mutable string via operations described in this section. However, you should not try to use these operations to alter the contents of a constant string. +@xref{Constants and Mutability}. The most basic way to alter the contents of an existing string is with @code{aset} (@pxref{Array Functions}). @code{(aset @var{string} commit 81e7d7f111872c9f2aaf8885db50a22ed746d7b5 Author: Paul Eggert Date: Sun Apr 19 09:37:51 2020 -0700 Document that quoting yields constants * doc/lispref/eval.texi (Quoting, Backquote): Mention that quoted expressions yield a constant (Bug#40693). diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi index f6f36ed342..46cfab164b 100644 --- a/doc/lispref/eval.texi +++ b/doc/lispref/eval.texi @@ -558,6 +558,7 @@ and vectors.) @defspec quote object This special form returns @var{object}, without evaluating it. +The returned value is a constant, and should not be modified. @end defspec @cindex @samp{'} for quoting @@ -612,10 +613,12 @@ only part of a list, while computing and substituting other parts. @dfn{Backquote constructs} allow you to quote a list, but selectively evaluate elements of that list. In the simplest case, it -is identical to the special form @code{quote} +is identical to the special form @iftex +@code{quote}. @end iftex @ifnottex +@code{quote} (described in the previous section; @pxref{Quoting}). @end ifnottex For example, these two forms yield identical results: @@ -693,6 +696,9 @@ Here are some examples: @end group @end example +If a subexpression of a backquote construct has no substitutions or +splices, it acts like @code{quote} in that it yields a constant that +should not be modified. @node Eval @section Eval commit 423089d18b6a8528dc3c70dce28c7011680e18be Author: Eli Zaretskii Date: Sun Apr 19 21:09:20 2020 +0300 Rework how GDI+ functions are loaded dynamically in w32image.c * src/w32image.c: Define correct WINGDIPAPI typedefs for GDI+ functions. We cannot use DEF_DLL_FN, since that is for functions with C calling conventions, whereas GDI+ functions are __stdcall. (gdiplus_init): Load functions from DLL manually, not via LOAD_DLL_FN, as the latter is for __cdecl functions. (w32_frame_delay): Initialize delay with a negative value, as zero is a valid delay. diff --git a/src/w32image.c b/src/w32image.c index 31c9b852ac..085a5db3ab 100644 --- a/src/w32image.c +++ b/src/w32image.c @@ -40,28 +40,47 @@ along with GNU Emacs. If not, see . */ #ifdef WINDOWSNT -DEF_DLL_FN (GpStatus, GdiplusStartup, - (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *)); -DEF_DLL_FN (VOID, GdiplusShutdown, (ULONG_PTR)); -DEF_DLL_FN (GpStatus, GdipGetPropertyItemSize, - (GpImage *, PROPID, UINT *)); -DEF_DLL_FN (GpStatus, GdipGetPropertyItem, - (GpImage *, PROPID, UINT, PropertyItem *)); -DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsCount, (GpImage *, UINT *)); -DEF_DLL_FN (GpStatus, GdipImageGetFrameDimensionsList, - (GpImage *, GUID *, UINT)); -DEF_DLL_FN (GpStatus, GdipImageGetFrameCount, - (GpImage *, GDIPCONST GUID *, UINT *)); -DEF_DLL_FN (GpStatus, GdipImageSelectActiveFrame, - (GpImage*, GDIPCONST GUID *, UINT)); -DEF_DLL_FN (GpStatus, GdipCreateBitmapFromFile, (WCHAR *, GpBitmap **)); -DEF_DLL_FN (GpStatus, GdipCreateBitmapFromStream, (IStream *, GpBitmap **)); -DEF_DLL_FN (IStream *, SHCreateMemStream, (const BYTE *pInit, UINT cbInit)); -DEF_DLL_FN (GpStatus, GdipCreateHBITMAPFromBitmap, - (GpBitmap *, HBITMAP *, ARGB)); -DEF_DLL_FN (GpStatus, GdipDisposeImage, (GpImage *)); -DEF_DLL_FN (GpStatus, GdipGetImageHeight, (GpImage *, UINT *)); -DEF_DLL_FN (GpStatus, GdipGetImageWidth, (GpImage *, UINT *)); +typedef GpStatus (WINGDIPAPI *GdiplusStartup_Proc) + (ULONG_PTR *, GdiplusStartupInput *, GdiplusStartupOutput *); +typedef VOID (WINGDIPAPI *GdiplusShutdown_Proc) (ULONG_PTR); +typedef GpStatus (WINGDIPAPI *GdipGetPropertyItemSize_Proc) + (GpImage *, PROPID, UINT *); +typedef GpStatus (WINGDIPAPI *GdipGetPropertyItem_Proc) + (GpImage *, PROPID, UINT, PropertyItem *); +typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsCount_Proc) + (GpImage *, UINT *); +typedef GpStatus (WINGDIPAPI *GdipImageGetFrameDimensionsList_Proc) + (GpImage *, GUID *, UINT); +typedef GpStatus (WINGDIPAPI *GdipImageGetFrameCount_Proc) + (GpImage *, GDIPCONST GUID *, UINT *); +typedef GpStatus (WINGDIPAPI *GdipImageSelectActiveFrame_Proc) + (GpImage*, GDIPCONST GUID *, UINT); +typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromFile_Proc) + (WCHAR *, GpBitmap **); +typedef GpStatus (WINGDIPAPI *GdipCreateBitmapFromStream_Proc) + (IStream *, GpBitmap **); +typedef IStream * (WINAPI *SHCreateMemStream_Proc) (const BYTE *, UINT); +typedef GpStatus (WINGDIPAPI *GdipCreateHBITMAPFromBitmap_Proc) + (GpBitmap *, HBITMAP *, ARGB); +typedef GpStatus (WINGDIPAPI *GdipDisposeImage_Proc) (GpImage *); +typedef GpStatus (WINGDIPAPI *GdipGetImageHeight_Proc) (GpImage *, UINT *); +typedef GpStatus (WINGDIPAPI *GdipGetImageWidth_Proc) (GpImage *, UINT *); + +GdiplusStartup_Proc fn_GdiplusStartup; +GdiplusShutdown_Proc fn_GdiplusShutdown; +GdipGetPropertyItemSize_Proc fn_GdipGetPropertyItemSize; +GdipGetPropertyItem_Proc fn_GdipGetPropertyItem; +GdipImageGetFrameDimensionsCount_Proc fn_GdipImageGetFrameDimensionsCount; +GdipImageGetFrameDimensionsList_Proc fn_GdipImageGetFrameDimensionsList; +GdipImageGetFrameCount_Proc fn_GdipImageGetFrameCount; +GdipImageSelectActiveFrame_Proc fn_GdipImageSelectActiveFrame; +GdipCreateBitmapFromFile_Proc fn_GdipCreateBitmapFromFile; +GdipCreateBitmapFromStream_Proc fn_GdipCreateBitmapFromStream; +SHCreateMemStream_Proc fn_SHCreateMemStream; +GdipCreateHBITMAPFromBitmap_Proc fn_GdipCreateHBITMAPFromBitmap; +GdipDisposeImage_Proc fn_GdipDisposeImage; +GdipGetImageHeight_Proc fn_GdipGetImageHeight; +GdipGetImageWidth_Proc fn_GdipGetImageWidth; static bool gdiplus_init (void) @@ -72,33 +91,73 @@ gdiplus_init (void) && (shlwapi_lib = w32_delayed_load (Qshlwapi)))) return false; - LOAD_DLL_FN (gdiplus_lib, GdiplusStartup); - LOAD_DLL_FN (gdiplus_lib, GdiplusShutdown); - LOAD_DLL_FN (gdiplus_lib, GdipGetPropertyItemSize); - LOAD_DLL_FN (gdiplus_lib, GdipGetPropertyItem); - LOAD_DLL_FN (gdiplus_lib, GdipImageGetFrameDimensionsCount); - LOAD_DLL_FN (gdiplus_lib, GdipImageGetFrameDimensionsList); - LOAD_DLL_FN (gdiplus_lib, GdipImageGetFrameCount); - LOAD_DLL_FN (gdiplus_lib, GdipImageSelectActiveFrame); - LOAD_DLL_FN (gdiplus_lib, GdipCreateBitmapFromFile); - LOAD_DLL_FN (gdiplus_lib, GdipCreateBitmapFromStream); - LOAD_DLL_FN (gdiplus_lib, GdipCreateHBITMAPFromBitmap); - LOAD_DLL_FN (gdiplus_lib, GdipDisposeImage); - LOAD_DLL_FN (gdiplus_lib, GdipGetImageHeight); - LOAD_DLL_FN (gdiplus_lib, GdipGetImageWidth); + fn_GdiplusStartup = (GdiplusStartup_Proc) + get_proc_addr (gdiplus_lib, "GdiplusStartup"); + if (!fn_GdiplusStartup) + return false; + fn_GdiplusShutdown = (GdiplusShutdown_Proc) + get_proc_addr (gdiplus_lib, "GdiplusShutdown"); + if (!fn_GdiplusShutdown) + return false; + fn_GdipGetPropertyItemSize = (GdipGetPropertyItemSize_Proc) + get_proc_addr (gdiplus_lib, "GdipGetPropertyItemSize"); + if (!fn_GdipGetPropertyItemSize) + return false; + fn_GdipGetPropertyItem = (GdipGetPropertyItem_Proc) + get_proc_addr (gdiplus_lib, "GdipGetPropertyItem"); + if (!fn_GdipGetPropertyItem) + return false; + fn_GdipImageGetFrameDimensionsCount = (GdipImageGetFrameDimensionsCount_Proc) + get_proc_addr (gdiplus_lib, "GdipImageGetFrameDimensionsCount"); + if (!fn_GdipImageGetFrameDimensionsCount) + return false; + fn_GdipImageGetFrameDimensionsList = (GdipImageGetFrameDimensionsList_Proc) + get_proc_addr (gdiplus_lib, "GdipImageGetFrameDimensionsList"); + if (!fn_GdipImageGetFrameDimensionsList) + return false; + fn_GdipImageGetFrameCount = (GdipImageGetFrameCount_Proc) + get_proc_addr (gdiplus_lib, "GdipImageGetFrameCount"); + if (!fn_GdipImageGetFrameCount) + return false; + fn_GdipImageSelectActiveFrame = (GdipImageSelectActiveFrame_Proc) + get_proc_addr (gdiplus_lib, "GdipImageSelectActiveFrame"); + if (!fn_GdipImageSelectActiveFrame) + return false; + fn_GdipCreateBitmapFromFile = (GdipCreateBitmapFromFile_Proc) + get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromFile"); + if (!fn_GdipCreateBitmapFromFile) + return false; + fn_GdipCreateBitmapFromStream = (GdipCreateBitmapFromStream_Proc) + get_proc_addr (gdiplus_lib, "GdipCreateBitmapFromStream"); + if (!fn_GdipCreateBitmapFromStream) + return false; + fn_GdipCreateHBITMAPFromBitmap = (GdipCreateHBITMAPFromBitmap_Proc) + get_proc_addr (gdiplus_lib, "GdipCreateHBITMAPFromBitmap"); + if (!fn_GdipCreateHBITMAPFromBitmap) + return false; + fn_GdipDisposeImage = (GdipDisposeImage_Proc) + get_proc_addr (gdiplus_lib, "GdipDisposeImage"); + if (!fn_GdipDisposeImage) + return false; + fn_GdipGetImageHeight = (GdipGetImageHeight_Proc) + get_proc_addr (gdiplus_lib, "GdipGetImageHeight"); + if (!fn_GdipGetImageHeight) + return false; + fn_GdipGetImageWidth = (GdipGetImageWidth_Proc) + get_proc_addr (gdiplus_lib, "GdipGetImageWidth"); + if (!fn_GdipGetImageWidth) + return false; /* LOAD_DLL_FN (shlwapi_lib, SHCreateMemStream); */ /* The following terrible kludge is required to use native image API on Windows before Vista, because SHCreateMemStream was not exported by name in those versions, only by ordinal number. */ - fn_SHCreateMemStream = - (W32_PFN_SHCreateMemStream) get_proc_addr (shlwapi_lib, - "SHCreateMemStream"); + fn_SHCreateMemStream = (SHCreateMemStream_Proc) + get_proc_addr (shlwapi_lib, "SHCreateMemStream"); if (!fn_SHCreateMemStream) { - fn_SHCreateMemStream = - (W32_PFN_SHCreateMemStream) get_proc_addr (shlwapi_lib, - MAKEINTRESOURCEA (12)); + fn_SHCreateMemStream = (SHCreateMemStream_Proc) + get_proc_addr (shlwapi_lib, MAKEINTRESOURCEA (12)); if (!fn_SHCreateMemStream) return false; } @@ -293,7 +352,7 @@ w32_select_active_frame (GpBitmap *pBitmap, int frame, int *nframes, status = GdipImageGetFrameDimensionsCount (pBitmap, &count); frameCount = *nframes = 0; - *delay = 0.0; + *delay = -1.0; if (count) { /* The following call will fill pDimensionIDs[0] with the commit 3f8b771da96f9a55dd5ed322104135a0c2c6f2e4 Author: Eli Zaretskii Date: Sun Apr 19 19:38:53 2020 +0300 Don't use Gnulib's explicit_bzero on MS-Windows This is a preventive change, since Gnulib was recently changed its explicit_bzero to call SecureZeroMemory on MS-Windows, disregarding systems older than XP, which didn't have it. * src/w32.c (explicit_bzero): New function. * nt/mingw-cfg.site (ac_cv_func_explicit_bzero): Avoid using the Gnulib replacement for explicit_bzero. * nt/inc/ms-w32.h (explicit_bzero): Add prototype. diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h index 1cce2c3062..cbe35ea105 100644 --- a/nt/inc/ms-w32.h +++ b/nt/inc/ms-w32.h @@ -440,6 +440,7 @@ extern int alarm (int); extern int sys_kill (pid_t, int); +extern void explicit_bzero (void *, size_t); /* For integration with MSDOS support. */ #define getdisk() (_getdrive () - 1) diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site index 2271eef98d..2e898c745e 100644 --- a/nt/mingw-cfg.site +++ b/nt/mingw-cfg.site @@ -109,6 +109,7 @@ ac_cv_func_futimens=not-needed gl_cv_func_futimens_works="not-needed-so-yes" ac_cv_func_utimensat=yes gl_cv_func_utimensat_works=yes +ac_cv_func_explicit_bzero=yes # Aliased to _commit in ms-w32.h ac_cv_func_fsync=yes ac_cv_func_fdatasync=yes diff --git a/src/w32.c b/src/w32.c index 42c832a593..0f69e652a5 100644 --- a/src/w32.c +++ b/src/w32.c @@ -2370,6 +2370,26 @@ srandom (int seed) iz = rand () % RAND_MAX_Z; } +/* Emulate explicit_bzero. This is to avoid using the Gnulib version, + because it calls SecureZeroMemory at will, disregarding systems + older than Windows XP, which didn't have that function. We want to + avoid having that function as dependency in builds that need to + support systems older than Windows XP, otherwise Emacs will refuse + to start on those systems. */ +void +explicit_bzero (void *buf, size_t len) +{ +#if _WIN32_WINNT >= 0x0501 + /* We are compiling for XP or newer, most probably with MinGW64. + We can use SecureZeroMemory. */ + SecureZeroMemory (buf, len); +#else + memset (buf, 0, len); + /* Compiler barrier. */ + asm volatile ("" ::: "memory"); +#endif +} + /* Return the maximum length in bytes of a multibyte character sequence encoded in the current ANSI codepage. This is required to correctly walk the encoded file names one character at a time. */ commit 5734339f4017836a2b171071056a320899a7c8e5 Author: Stefan Monnier Date: Sun Apr 19 11:19:03 2020 -0400 * doc/lispref/keymaps.texi (Extended Menu Items, Easy Menu) <:key-sequence>: Clarify the documentation further diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 4db9969767..1e81fb1dc5 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -2223,14 +2223,11 @@ right value for selecting that button. Clicking on the button should set the variable so that the button you clicked on becomes selected. @item :key-sequence @var{key-sequence} -This property specifies which key sequence is likely to be bound to the -same command invoked by this menu item. If you specify a correct key -sequence, that sequence will be preferred over others. - -If you specify an incorrect key sequence, it has no effect; before Emacs -displays @var{key-sequence} in the menu, it verifies that -@var{key-sequence} is really equivalent to this menu item. Specifying -@code{nil} for @var{key-sequence} is equivalent to the +This property specifies which key sequence to display as keyboard equivalent. +Before Emacs displays @var{key-sequence} in the menu, it verifies that +@var{key-sequence} is really equivalent to this menu item, so it only +has an effect if you specify a correct key sequence. +Specifying @code{nil} for @var{key-sequence} is equivalent to the @code{:key-sequence} attribute being absent. @item :keys @var{string} @@ -2913,17 +2910,17 @@ the following: @table @code @item :keys @var{keys} -@var{keys} is a keyboard equivalent to the menu item (a string). This -is normally not needed, as keyboard equivalents are computed +@var{keys} is a string to display as keyboard equivalent to the menu item. +This is normally not needed, as keyboard equivalents are computed automatically. @var{keys} is expanded with @code{substitute-command-keys} before it is displayed (@pxref{Keys in Documentation}). @item :key-sequence @var{keys} -@var{keys} is a hint for speeding up Emacs's first display of the -menu. It should be @code{nil} if you know that the menu item has no keyboard -equivalent; otherwise it should be a string or vector specifying a -keyboard equivalent for the menu item. +@var{keys} is a hint indicating which key sequence to display as +keyboard equivalent, in case the command is bound to several key sequences. +It has no effect if @var{keys} is not bound to same command as this +menu item. @item :active @var{enable} @var{enable} is an expression; if it evaluates to @code{nil}, the item commit 14a570afaeb9c01bafdb5dd922d8077810e63d16 Author: Mattias Engdegård Date: Sun Apr 19 12:40:43 2020 +0200 Remove #' and function quoting from lambda forms in manual * doc/lispref/abbrevs.texi (Abbrev Expansion): * doc/lispref/backups.texi (Reverting): * doc/lispref/functions.texi (Mapping Functions): * doc/lispref/help.texi (Accessing Documentation): * doc/lispref/sequences.texi (Char-Tables): * doc/lispref/syntax.texi (Categories): * doc/lispref/text.texi (Sorting): Remove function quoting from lambda in examples where it still occurs, since examples should follow our best style and be consistent. diff --git a/doc/lispref/abbrevs.texi b/doc/lispref/abbrevs.texi index 6689b560c7..575be187d3 100644 --- a/doc/lispref/abbrevs.texi +++ b/doc/lispref/abbrevs.texi @@ -370,9 +370,9 @@ definitions of @code{local-abbrev-table} and @code{text-mode-abbrev-table}. (funcall expand)))) (add-hook 'foo-mode-hook - #'(lambda () - (add-function :around (local 'abbrev-expand-function) - #'foo-mode-abbrev-expand-function))) + (lambda () + (add-function :around (local 'abbrev-expand-function) + #'foo-mode-abbrev-expand-function))) @end smallexample @node Standard Abbrev Tables diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi index b7318a99b8..4ed1a10fcf 100644 --- a/doc/lispref/backups.texi +++ b/doc/lispref/backups.texi @@ -807,7 +807,7 @@ If you just want to automatically auto-revert every @example (setq-local buffer-stale-function - #'(lambda (&optional noconfirm) 'fast)) + (lambda (&optional noconfirm) 'fast)) @end example @noindent diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index f31bacaed7..bc8ec0ef1b 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -970,7 +970,7 @@ string. @end group @group -(mapconcat (function (lambda (x) (format "%c" (1+ x)))) +(mapconcat (lambda (x) (format "%c" (1+ x))) "HAL-8000" "") @result{} "IBM.9111" diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi index eea1fd2e8f..9b3c4fcb23 100644 --- a/doc/lispref/help.texi +++ b/doc/lispref/help.texi @@ -175,49 +175,47 @@ All symbols that have PATTERN in their name are described in the *Help* buffer." (interactive "sDescribe symbols matching: ") (let ((describe-func - (function - (lambda (s) + (lambda (s) @end group @group - ;; @r{Print description of symbol.} - (if (fboundp s) ; @r{It is a function.} - (princ - (format "%s\t%s\n%s\n\n" s - (if (commandp s) - (let ((keys (where-is-internal s))) - (if keys - (concat - "Keys: " - (mapconcat 'key-description - keys " ")) - "Keys: none")) - "Function") + ;; @r{Print description of symbol.} + (if (fboundp s) ; @r{It is a function.} + (princ + (format "%s\t%s\n%s\n\n" s + (if (commandp s) + (let ((keys (where-is-internal s))) + (if keys + (concat + "Keys: " + (mapconcat 'key-description + keys " ")) + "Keys: none")) + "Function") @end group @group - (or (documentation s) - "not documented")))) + (or (documentation s) + "not documented")))) - (if (boundp s) ; @r{It is a variable.} + (if (boundp s) ; @r{It is a variable.} @end group @group - (princ - (format "%s\t%s\n%s\n\n" s - (if (custom-variable-p s) - "Option " "Variable") + (princ + (format "%s\t%s\n%s\n\n" s + (if (custom-variable-p s) + "Option " "Variable") @end group @group - (or (documentation-property - s 'variable-documentation) - "not documented"))))))) + (or (documentation-property + s 'variable-documentation) + "not documented")))))) sym-list) @end group @group ;; @r{Build a list of symbols that match pattern.} - (mapatoms (function - (lambda (sym) - (if (string-match pattern (symbol-name sym)) - (setq sym-list (cons sym sym-list)))))) + (mapatoms (lambda (sym) + (if (string-match pattern (symbol-name sym)) + (setq sym-list (cons sym sym-list))))) @end group @group diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index f6faf9448c..7a3f26e584 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -1572,14 +1572,14 @@ For example, here is how to examine the elements of the syntax table: @example (let (accumulator) (map-char-table - #'(lambda (key value) - (setq accumulator - (cons (list - (if (consp key) - (list (car key) (cdr key)) - key) - value) - accumulator))) + (lambda (key value) + (setq accumulator + (cons (list + (if (consp key) + (list (car key) (cdr key)) + key) + value) + accumulator))) (syntax-table)) accumulator) @result{} diff --git a/doc/lispref/syntax.texi b/doc/lispref/syntax.texi index ad45a8edaf..9eb99a0ac9 100644 --- a/doc/lispref/syntax.texi +++ b/doc/lispref/syntax.texi @@ -1118,9 +1118,9 @@ bidi-class}). ;; 'bidi-class' Unicode property is R, AL, or RLO -- ;; these have a right-to-left directionality. (map-char-table - #'(lambda (key val) - (if (memq val '(R AL RLO)) - (modify-category-entry key ?R category-table))) + (lambda (key val) + (if (memq val '(R AL RLO)) + (modify-category-entry key ?R category-table))) uniprop-table) category-table)) @end example diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index fe3d48b3ff..58424a4231 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -2073,11 +2073,10 @@ its @code{sort-subr} call looks like this: @example @group (sort-subr reverse - (function - (lambda () - (while (and (not (eobp)) - (looking-at paragraph-separate)) - (forward-line 1)))) + (lambda () + (while (and (not (eobp)) + (looking-at paragraph-separate)) + (forward-line 1))) 'forward-paragraph) @end group @end example commit d5ec18c66bdefb492826eab0d60e818d5bac7238 Author: Stefan Monnier Date: Sat Apr 18 23:01:43 2020 -0400 * src/regex-emacs.c (re_match_2_internal): Rework comment in last change Explain why we don't need to worry about Lisp modifying the buffer. * src/syntax.c (parse_sexp_propertize): Fix name in error message. diff --git a/src/regex-emacs.c b/src/regex-emacs.c index f456b49539..5e23fc94e4 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -3959,9 +3959,11 @@ re_match_2_internal (struct re_pattern_buffer *bufp, /* Prevent shrinking and relocation of buffer text if GC happens while we are inside this function. The calls to - UPDATE_SYNTAX_TABLE_* macros can trigger GC if they call Lisp, - and we have C pointers to buffer text that must not become - invalid as result of GC. */ + UPDATE_SYNTAX_TABLE_* macros can call Lisp (via + `internal--syntax-propertize`); these calls are careful to defend against + buffer modifications, but even with no modifications, the buffer text may + be relocated during GC by `compact_buffer` which would invalidate + our C pointers to buffer text. */ if (!current_buffer->text->inhibit_shrinking) { record_unwind_protect_ptr (unwind_re_match, current_buffer); diff --git a/src/syntax.c b/src/syntax.c index e24b98da32..a79ab86336 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -480,10 +480,10 @@ parse_sexp_propertize (ptrdiff_t charpos) safe_call1 (Qinternal__syntax_propertize, make_fixnum (min (zv, 1 + charpos))); if (modiffs != CHARS_MODIFF) - error ("parse-sexp-propertize-function modified the buffer!"); + error ("internal--syntax-propertize modified the buffer!"); if (syntax_propertize__done <= charpos && syntax_propertize__done < zv) - error ("parse-sexp-propertize-function did not move" + error ("internal--syntax-propertize did not move" " syntax-propertize--done"); SETUP_SYNTAX_TABLE (charpos, 1); } commit 4df8a6111710a68197451879f2a966ae34a90db8 Author: Juri Linkov Date: Sun Apr 19 02:43:06 2020 +0300 Add new node "Image Mode" to Emacs Manual. * doc/emacs/dired.texi (Image-Dired): Add xref to "Image Mode". * doc/emacs/emacs.texi (Top): Add new node "Image Mode" to menu. * doc/emacs/files.texi (Files): Add new node "Image Mode" to menu. (File Conveniences): Split part of node to new node "Image Mode". * doc/emacs/frames.texi (Mouse Commands): Add xref to "Image Mode". * doc/emacs/misc.texi (Embedded WebKit Widgets): Rename xref from "File Conveniences" to "Image Mode". diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index fba4389094..d514414180 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -1416,7 +1416,8 @@ C-c}. Image-Dired is a facility for browsing image files. It provides viewing the images either as thumbnails or in full size, either inside Emacs -or through an external viewer. +or through an external viewer. This is different from Image mode +(@pxref{Image Mode}) for visiting an image file in the Emacs buffer. @kindex C-t d @r{(Image-Dired)} @findex image-dired-display-thumbs diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 6ef4ca63ae..60f2be9a51 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -455,7 +455,8 @@ File Handling * Remote Files:: Accessing files on other machines. * Quoted File Names:: Quoting special characters in file names. * File Name Cache:: Completion against a list of files you often use. -* File Conveniences:: Convenience Features for Finding Files. +* File Conveniences:: Convenience features for finding files. +* Image Mode:: Viewing image files. * Filesets:: Handling sets of files. Saving Files diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index a89b16b3f6..7d57555ce3 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -38,7 +38,8 @@ on file directories. * Remote Files:: Accessing files on other machines. * Quoted File Names:: Quoting special characters in file names. * File Name Cache:: Completion against a list of files you often use. -* File Conveniences:: Convenience Features for Finding Files. +* File Conveniences:: Convenience features for finding files. +* Image Mode:: Viewing image files. * Filesets:: Handling sets of files. @end menu @@ -2088,8 +2089,7 @@ of the cache with the @code{file-cache-display} command. @section Convenience Features for Finding Files In this section, we introduce some convenient facilities for finding -recently-opened files, reading file names from a buffer, and viewing -image files. +recently-opened files, reading file names from a buffer. @findex recentf-mode @vindex recentf-mode @@ -2108,6 +2108,9 @@ point. Partial Completion mode offers other features extending @code{find-file}, which can be used with @code{ffap}. @xref{Completion Options}. +@node Image Mode +@section Viewing Image Files + @findex image-mode @findex image-toggle-display @findex image-next-file diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index 7a583b96bb..94218424d3 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -227,8 +227,9 @@ left. If you'd like to reverse the direction of horizontal scrolling, customize the variable @code{mouse-wheel-flip-direction} to a non-@code{nil} value. -When the mouse pointer is over an image, scrolling the mouse wheel -with the @key{Ctrl} modifier scales the image under the mouse pointer. +When the mouse pointer is over an image in Image mode, @pxref{Image Mode}, +scrolling the mouse wheel with the @key{Ctrl} modifier scales the image +under the mouse pointer. @node Word and Line Mouse diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 294430aa18..a15aa17a66 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -2883,7 +2883,7 @@ if there is an active region (@pxref{Mark}), the default URL comes from the region instead, after removing any whitespace from it. The command then creates a new buffer with the embedded browser showing the specified URL. The buffer is put in the Xwidget-WebKit mode -(similar to Image mode, @pxref{File Conveniences}), which provides +(similar to Image mode, @pxref{Image Mode}), which provides one-key commands for scrolling the widget, changing its size, and reloading it. Type @w{@kbd{C-h b}} in that buffer to see the key bindings. diff --git a/etc/NEWS b/etc/NEWS index 4485bf9165..def1bce29a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3515,6 +3515,10 @@ functions. *** 'image-mode' now uses this library to automatically rotate images according to the orientation in the Exif data, if any. +*** In 'image-mode' the image is resized automatically to fit in window. +The image will resize upon first display and whenever the window's +dimensions change. + --- *** New library image-converter. If you need to view exotic image formats for which Emacs doesn't have commit d7d5ee6c579f5aad59ad0c1e3bf489fca90f4aeb Author: Štěpán Němec Date: Sat Apr 18 23:28:40 2020 +0200 ; Fix a typo in cmdargs.texi (bug#40701) diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi index d3fda285f2..850a802753 100644 --- a/doc/emacs/cmdargs.texi +++ b/doc/emacs/cmdargs.texi @@ -340,7 +340,7 @@ initialization file (@pxref{Resources}). @opindex --quick Start Emacs with minimum customizations. This is similar to using @samp{-q}, @samp{--no-site-file}, @samp{--no-site-lisp}, -@samp{--no-x-resources}, and @samp{--no-splash} together.. +@samp{--no-x-resources}, and @samp{--no-splash} together. @item -daemon @opindex -daemon commit 5e9db48fbefcc3a3d44acbdcba307f377638d178 Author: Paul Eggert Date: Sat Apr 18 12:59:50 2020 -0700 * doc/lispref/display.texi (Customizing Bitmaps): Fix typo. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 85e42d331d..4e73afeaf9 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -4361,7 +4361,7 @@ height. @end defun @defun destroy-fringe-bitmap bitmap -This function destroy the fringe bitmap identified by @var{bitmap}. +This function destroys the fringe bitmap identified by @var{bitmap}. If @var{bitmap} identifies a standard fringe bitmap, it actually restores the standard definition of that bitmap, instead of eliminating it entirely. commit eebfb72c906755c0a80d92c11deee7ac9faf5f4b Author: Paul Eggert Date: Sat Apr 18 12:59:17 2020 -0700 Document constant vs mutable objects better This patch builds on a suggested patch by Mattias Engdegård and on further comments by Eli Zaretskii. Original bug report by Kevin Vigouroux (Bug#40671). * doc/lispintro/emacs-lisp-intro.texi (set & setq, Review) (setcar, Lists diagrammed, Mail Aliases, Indent Tabs Mode): setq is a special form, not a function or command. * doc/lispintro/emacs-lisp-intro.texi (setcar): * doc/lispref/lists.texi (Modifying Lists, Rearrangement): * doc/lispref/sequences.texi (Sequence Functions) (Array Functions, Vectors): * doc/lispref/strings.texi (String Basics, Modifying Strings): Mention mutable vs constant objects. * doc/lispintro/emacs-lisp-intro.texi (setcar, setcdr) (kill-new function, cons & search-fwd Review): * doc/lispref/edebug.texi (Printing in Edebug): * doc/lispref/keymaps.texi (Changing Key Bindings): * doc/lispref/lists.texi (Setcar, Setcdr, Rearrangement) (Sets And Lists, Association Lists, Plist Access): * doc/lispref/sequences.texi (Sequence Functions) (Array Functions): * doc/lispref/strings.texi (Text Comparison): Fix examples so that they do not try to change constants. diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index bd688070a3..630676d978 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -2329,7 +2329,7 @@ area. @cindex @samp{bind} defined There are several ways by which a variable can be given a value. One of -the ways is to use either the function @code{set} or the function +the ways is to use either the function @code{set} or the special form @code{setq}. Another way is to use @code{let} (@pxref{let}). (The jargon for this process is to @dfn{bind} a variable to a value.) @@ -4517,7 +4517,7 @@ number; it will be printed as the character with that @sc{ascii} code. @item setq @itemx set -The @code{setq} function sets the value of its first argument to the +The @code{setq} special form sets the value of its first argument to the value of the second argument. The first argument is automatically quoted by @code{setq}. It does the same for succeeding pairs of arguments. Another function, @code{set}, takes only two arguments and @@ -7317,11 +7317,21 @@ which leave the original list as it was. One way to find out how this works is to experiment. We will start with the @code{setcar} function. @need 1200 +@cindex constant lists +@cindex mutable lists First, we can make a list and then set the value of a variable to the -list, using the @code{setq} function. Here is a list of animals: +list, using the @code{setq} special form. Because we intend to use +@code{setcar} to change the list, this @code{setq} should not use the +quoted form @code{'(antelope giraffe lion tiger)}, as that would yield +a list that is part of the program and bad things could happen if we +tried to change part of the program while running it. Generally +speaking an Emacs Lisp program's components should be constant (or +unchanged) while the program is running. So we instead construct an +animal list that is @dfn{mutable} (or changeable) by using the +@code{list} function, as follows: @smallexample -(setq animals '(antelope giraffe lion tiger)) +(setq animals (list 'antelope 'giraffe 'lion 'tiger)) @end smallexample @noindent @@ -7398,7 +7408,7 @@ To see how this works, set the value of the variable to a list of domesticated animals by evaluating the following expression: @smallexample -(setq domesticated-animals '(horse cow sheep goat)) +(setq domesticated-animals (list 'horse 'cow 'sheep 'goat)) @end smallexample @need 1200 @@ -8846,7 +8856,7 @@ and then find the value of @code{trees}: @smallexample @group -(setq trees '(maple oak pine birch)) +(setq trees (list 'maple 'oak 'pine 'birch)) @result{} (maple oak pine birch) @end group @@ -9366,7 +9376,7 @@ For example: @smallexample @group -(setq triple '(1 2 3)) +(setq triple (list 1 2 3)) (setcar triple '37) @@ -9547,7 +9557,7 @@ part of which is the address of the next pair. The very last box points to the symbol @code{nil}, which marks the end of the list. @need 1200 -When a variable is set to a list with a function such as @code{setq}, +When a variable is set to a list via @code{setq}, it stores the address of the first box in the variable. Thus, evaluation of the expression @@ -17092,7 +17102,7 @@ reminders. @cindex Mail aliases @noindent -This @code{setq} command sets the value of the variable +This @code{setq} sets the value of the variable @code{mail-aliases} to @code{t}. Since @code{t} means true, the line says, in effect, ``Yes, use mail aliases.'' @@ -17130,8 +17140,8 @@ The following turns off Indent Tabs mode: @end smallexample Note that this line uses @code{setq-default} rather than the -@code{setq} command that we have seen before. The @code{setq-default} -command sets values only in buffers that do not have their own local +@code{setq} that we have seen before. The @code{setq-default} +sets values only in buffers that do not have their own local values for the variable. @ifinfo diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi index 8be8307c75..ec76e83db1 100644 --- a/doc/lispref/edebug.texi +++ b/doc/lispref/edebug.texi @@ -858,7 +858,7 @@ to a non-@code{nil} value. Here is an example of code that creates a circular structure: @example -(setq a '(x y)) +(setq a (list 'x 'y)) (setcar a a) @end example diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index c6a02d721f..4db9969767 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1441,10 +1441,10 @@ Here is an example showing a keymap before and after substitution: @smallexample @group -(setq map '(keymap - (?1 . olddef-1) - (?2 . olddef-2) - (?3 . olddef-1))) +(setq map (list 'keymap + (cons ?1 olddef-1) + (cons ?2 olddef-2) + (cons ?3 olddef-1))) @result{} (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1)) @end group diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index 27fa5385e3..c2771b0165 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -866,10 +866,16 @@ foo ;; @r{@code{foo} was changed.} @node Modifying Lists @section Modifying Existing List Structure @cindex destructive list operations +@cindex constant lists +@cindex mutable lists You can modify the @sc{car} and @sc{cdr} contents of a cons cell with the primitives @code{setcar} and @code{setcdr}. These are destructive operations because they change existing list structure. +Destructive operations should be applied only to @dfn{mutable} lists, +that is, lists constructed via @code{cons}, @code{list} or similar +operations. Lists created by quoting are constants and should not be +changed by destructive operations. @cindex CL note---@code{rplaca} vs @code{setcar} @quotation @@ -906,7 +912,7 @@ value @var{object}. For example: @example @group -(setq x '(1 2)) +(setq x (list 1 2)) @result{} (1 2) @end group @group @@ -927,7 +933,7 @@ these lists. Here is an example: @example @group ;; @r{Create two lists that are partly shared.} -(setq x1 '(a b c)) +(setq x1 (list 'a 'b 'c)) @result{} (a b c) (setq x2 (cons 'z (cdr x1))) @result{} (z b c) @@ -1017,7 +1023,7 @@ reached via the @sc{cdr}. @example @group -(setq x '(1 2 3)) +(setq x (list 1 2 3)) @result{} (1 2 3) @end group @group @@ -1037,7 +1043,7 @@ the @sc{cdr} of the first cons cell: @example @group -(setq x1 '(a b c)) +(setq x1 (list 'a 'b 'c)) @result{} (a b c) (setcdr x1 (cdr (cdr x1))) @result{} (c) @@ -1069,7 +1075,7 @@ of this list. @example @group -(setq x1 '(a b c)) +(setq x1 (list 'a 'b 'c)) @result{} (a b c) (setcdr x1 (cons 'd (cdr x1))) @result{} (d b c) @@ -1130,7 +1136,7 @@ Unlike @code{append} (@pxref{Building Lists}), the @var{lists} are @example @group -(setq x '(1 2 3)) +(setq x (list 1 2 3)) @result{} (1 2 3) @end group @group @@ -1150,7 +1156,7 @@ list: @example @group -(setq x '(1 2 3)) +(setq x (list 1 2 3)) @result{} (1 2 3) @end group @group @@ -1163,11 +1169,13 @@ x @end group @end example -However, the other arguments (all but the last) must be lists. +However, the other arguments (all but the last) must be mutable lists. A common pitfall is to use a quoted constant list as a non-last -argument to @code{nconc}. If you do this, your program will change -each time you run it! Here is what happens: +argument to @code{nconc}. If you do this, the resulting behavior +is undefined. It is possible that your program will change +each time you run it! Here is what might happen (though this +is not guaranteed to happen): @smallexample @group @@ -1260,7 +1268,9 @@ after those elements. For example: @example @group -(delq 'a '(a b c)) @equiv{} (cdr '(a b c)) +(equal + (delq 'a (list 'a 'b 'c)) + (cdr (list 'a 'b 'c))) @end group @end example @@ -1270,7 +1280,7 @@ removing it involves changing the @sc{cdr}s (@pxref{Setcdr}). @example @group -(setq sample-list '(a b c (4))) +(setq sample-list (list 'a 'b 'c '(4))) @result{} (a b c (4)) @end group @group @@ -1303,12 +1313,12 @@ into the variable that held the original list: (setq flowers (delq 'rose flowers)) @end example -In the following example, the @code{(4)} that @code{delq} attempts to match -and the @code{(4)} in the @code{sample-list} are not @code{eq}: +In the following example, the @code{(list 4)} that @code{delq} attempts to match +and the @code{(4)} in the @code{sample-list} are @code{equal} but not @code{eq}: @example @group -(delq '(4) sample-list) +(delq (list 4) sample-list) @result{} (a c (4)) @end group @end example @@ -1324,7 +1334,7 @@ of @code{list}. @example @group -(setq sample-list '(a b c a b c)) +(setq sample-list (list 'a 'b 'c 'a 'b 'c)) @result{} (a b c a b c) @end group @group @@ -1353,7 +1363,7 @@ Compare this with @code{memq}: @result{} (1.2 1.3) @end group @group -(memq 1.2 '(1.1 1.2 1.3)) ; @r{@code{1.2} and @code{1.2} are not @code{eq}.} +(memq (list 2) '((1) (2))) ; @r{@code{(list 2)} and @code{(2)} are not @code{eq}.} @result{} nil @end group @end example @@ -1373,11 +1383,11 @@ Compare this with @code{memq}: @example @group -(member '(2) '((1) (2))) ; @r{@code{(2)} and @code{(2)} are @code{equal}.} +(member (list 2) '((1) (2))) ; @r{@code{(list 2)} and @code{(2)} are @code{equal}.} @result{} ((2)) @end group @group -(memq '(2) '((1) (2))) ; @r{@code{(2)} and @code{(2)} are not @code{eq}.} +(memq (list 2) '((1) (2))) ; @r{@code{(list 2)} and @code{(2)} are not @code{eq}.} @result{} nil @end group @group @@ -1407,7 +1417,7 @@ For example: @example @group -(setq l '((2) (1) (2))) +(setq l (list '(2) '(1) '(2))) (delete '(2) l) @result{} ((1)) l @@ -1416,7 +1426,7 @@ l ;; @r{write @code{(setq l (delete '(2) l))}.} @end group @group -(setq l '((2) (1) (2))) +(setq l (list '(2) '(1) '(2))) (delete '(1) l) @result{} ((2) (2)) l @@ -1618,9 +1628,9 @@ keys may not be symbols: '(("simple leaves" . oak) ("compound leaves" . horsechestnut))) -(assq "simple leaves" leaves) +(assq (copy-sequence "simple leaves") leaves) @result{} nil -(assoc "simple leaves" leaves) +(assoc (copy-sequence "simple leaves") leaves) @result{} ("simple leaves" . oak) @end smallexample @end defun @@ -1759,7 +1769,7 @@ correct results, use the return value of @code{assq-delete-all} rather than looking at the saved value of @var{alist}. @example -(setq alist '((foo 1) (bar 2) (foo 3) (lose 4))) +(setq alist (list '(foo 1) '(bar 2) '(foo 3) '(lose 4))) @result{} ((foo 1) (bar 2) (foo 3) (lose 4)) (assq-delete-all 'foo alist) @result{} ((bar 2) (lose 4)) @@ -1926,7 +1936,7 @@ function returns the modified property list, so you can store that back in the place where you got @var{plist}. For example, @example -(setq my-plist '(bar t foo 4)) +(setq my-plist (list 'bar t 'foo 4)) @result{} (bar t foo 4) (setq my-plist (plist-put my-plist 'foo 69)) @result{} (bar t foo 69) diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 1a3a04f680..f6faf9448c 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -183,7 +183,7 @@ for other ways to copy sequences. @example @group -(setq bar '(1 2)) +(setq bar (list 1 2)) @result{} (1 2) @end group @group @@ -278,7 +278,7 @@ Unlike @code{reverse} the original @var{sequence} may be modified. @example @group -(setq x '(a b c)) +(setq x (list 'a 'b 'c)) @result{} (a b c) @end group @group @@ -320,7 +320,7 @@ presented graphically: For the vector, it is even simpler because you don't need setq: @example -(setq x [1 2 3 4]) +(setq x (copy-sequence [1 2 3 4])) @result{} [1 2 3 4] (nreverse x) @result{} [4 3 2 1] @@ -330,7 +330,7 @@ x Note that unlike @code{reverse}, this function doesn't work with strings. Although you can alter string data by using @code{aset}, it is strongly -encouraged to treat strings as immutable. +encouraged to treat strings as immutable even when they are mutable. @end defun @@ -374,11 +374,11 @@ appears in a different position in the list due to the change of @example @group -(setq nums '(1 3 2 6 5 4 0)) +(setq nums (list 1 3 2 6 5 4 0)) @result{} (1 3 2 6 5 4 0) @end group @group -(sort nums '<) +(sort nums #'<) @result{} (0 1 2 3 4 5 6) @end group @group @@ -396,7 +396,7 @@ of @code{sort} and use that. Most often we store the result back into the variable that held the original list: @example -(setq nums (sort nums '<)) +(setq nums (sort nums #'<)) @end example For the better understanding of what stable sort is, consider the following @@ -1228,7 +1228,7 @@ This function sets the @var{index}th element of @var{array} to be @example @group -(setq w [foo bar baz]) +(setq w (vector 'foo 'bar 'baz)) @result{} [foo bar baz] (aset w 0 'fu) @result{} fu @@ -1237,7 +1237,8 @@ w @end group @group -(setq x "asdfasfd") +;; @r{@code{copy-sequence} creates a mutable string.} +(setq x (copy-sequence "asdfasfd")) @result{} "asdfasfd" (aset x 3 ?Z) @result{} 90 @@ -1246,6 +1247,10 @@ x @end group @end example +The @var{array} should be mutable; that is, it should not be a constant, +such as the constants created via quoting or via self-evaluating forms. +@xref{Self-Evaluating Forms}. + If @var{array} is a string and @var{object} is not a character, a @code{wrong-type-argument} error results. The function converts a unibyte string to multibyte if necessary to insert a character. @@ -1257,7 +1262,7 @@ each element of @var{array} is @var{object}. It returns @var{array}. @example @group -(setq a [a b c d e f g]) +(setq a (copy-sequence [a b c d e f g])) @result{} [a b c d e f g] (fillarray a 0) @result{} [0 0 0 0 0 0 0] @@ -1265,7 +1270,7 @@ a @result{} [0 0 0 0 0 0 0] @end group @group -(setq s "When in the course") +(setq s (copy-sequence "When in the course")) @result{} "When in the course" (fillarray s ?-) @result{} "------------------" @@ -1301,7 +1306,9 @@ same way in Lisp input. A vector, like a string or a number, is considered a constant for evaluation: the result of evaluating it is the same vector. This does -not evaluate or even examine the elements of the vector. +not evaluate or even examine the elements of the vector. Vectors +written with square brackets are constants and should not be modified +via @code{aset} or other destructive operations. @xref{Self-Evaluating Forms}. Here are examples illustrating these principles: diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 14cabc5d79..3acbf538dc 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -51,10 +51,8 @@ by a distinguished character code. operate on them with the general array and sequence functions documented in @ref{Sequences Arrays Vectors}. For example, you can access or change individual characters in a string using the functions @code{aref} -and @code{aset} (@pxref{Array Functions}). However, note that -@code{length} should @emph{not} be used for computing the width of a -string on display; use @code{string-width} (@pxref{Size of Displayed -Text}) instead. +and @code{aset} (@pxref{Array Functions}). However, you should not +try to change the contents of constant strings (@pxref{Modifying Strings}). There are two text representations for non-@acronym{ASCII} characters in Emacs strings (and in buffers): unibyte and multibyte. @@ -89,6 +87,9 @@ copy them into buffers. @xref{Character Type}, and @ref{String Type}, for information about the syntax of characters and strings. @xref{Non-ASCII Characters}, for functions to convert between text representations and to encode and decode character codes. +Also, note that @code{length} should @emph{not} be used for computing +the width of a string on display; use @code{string-width} (@pxref{Size +of Displayed Text}) instead. @node Predicates for Strings @section Predicates for Strings @@ -380,6 +381,10 @@ usual value is @w{@code{"[ \f\t\n\r\v]+"}}. @cindex modifying strings @cindex string modification + You can alter the contents of a mutable string via operations +described in this section. However, you should not try to use these +operations to alter the contents of a constant string. + The most basic way to alter the contents of an existing string is with @code{aset} (@pxref{Array Functions}). @code{(aset @var{string} @var{idx} @var{char})} stores @var{char} into @var{string} at index @@ -591,7 +596,7 @@ for sorting (@pxref{Sequence Functions}): @example @group -(sort '("11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp) +(sort (list "11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp) @result{} ("11" "1 1" "1.1" "12" "1 2" "1.2") @end group @end example @@ -608,7 +613,7 @@ systems. The @var{locale} value of @code{"POSIX"} or @code{"C"} lets @example @group -(sort '("11" "12" "1 1" "1 2" "1.1" "1.2") +(sort (list "11" "12" "1 1" "1 2" "1.1" "1.2") (lambda (s1 s2) (string-collate-lessp s1 s2 "POSIX"))) @result{} ("1 1" "1 2" "1.1" "1.2" "11" "12") @end group commit 6c187ed6b0a2b103ebb55a5f037073c8c31492b3 Author: Eli Zaretskii Date: Sat Apr 18 19:26:30 2020 +0300 Improve documentation of 'sort-lines' * lisp/sort.el (sort-lines): Clarify the interactive invocation. (Bug#40697) diff --git a/lisp/sort.el b/lisp/sort.el index e4ff2afb3d..de0e1b9519 100644 --- a/lisp/sort.el +++ b/lisp/sort.el @@ -198,7 +198,8 @@ as start and end positions), and with `string<' otherwise." ;;;###autoload (defun sort-lines (reverse beg end) - "Sort lines in region alphabetically; argument means descending order. + "Sort lines in region alphabetically; REVERSE non-nil means descending order. +Interactively, REVERSE is the prefix argument, and BEG and END are the region. Called from a program, there are three arguments: REVERSE (non-nil means reverse order), BEG and END (region to sort). The variable `sort-fold-case' determines whether alphabetic case affects commit 52288f4b66c0a4ac8ad90c6612e651f63d33c706 Author: Štěpán Němec Date: Wed Jul 31 09:51:09 2019 +0200 Mention 'spam-stat-process-directory-age' in the documentation I was at a loss as to why my attempt to set up spam-stat seemed to have no effect, only to find (digging in the code) that it was ignoring most of the sample files due to this undocumented variable. * doc/misc/gnus.texi (Creating a spam-stat dictionary): Document the variable 'spam-stat-process-directory-age'. (bug#39780) diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 27180f3fed..c8ac7f0a7c 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -25674,6 +25674,13 @@ Create non-spam statistics for every file in this directory. Every file is treated as one non-spam mail. @end defun +@defvar spam-stat-process-directory-age +Maximum age of files to be processed, in days. Without this filter, +re-training spam-stat with several thousand messages could take a long +time. The default is 90, but you might want to set this to a bigger +value during the initial training. +@end defvar + Usually you would call @code{spam-stat-process-spam-directory} on a directory such as @file{~/Mail/mail/spam} (this usually corresponds to the group @samp{nnml:mail.spam}), and you would call commit 067b0705986572e42687334c4eaf32988f22f680 Author: Štěpán Němec Date: Sun Mar 1 18:50:14 2020 +0100 ; Fix some typos and doc issues (bug#40695) diff --git a/ChangeLog.3 b/ChangeLog.3 index c5bc7b3120..7f6000fc55 100644 --- a/ChangeLog.3 +++ b/ChangeLog.3 @@ -11660,7 +11660,7 @@ Mention the Emacs exit code in batch mode * doc/lispref/os.texi (Batch Mode): Mention what the exit code is - if an error is signalled (bug#31552). + if an error is signaled (bug#31552). 2019-10-12 Kaushal Modi @@ -15059,7 +15059,7 @@ * lisp/image/exif.el (exif-parse-buffer): New function. (exif-orientation): Ditto. - (exif-error): New error symbol, and adjust all error signalling to + (exif-error): New error symbol, and adjust all error signaling to only use that signal. 2019-09-22 Andreas Schwab @@ -25100,7 +25100,7 @@ * lisp/json.el (json-read): Try to clarify what's returned (bug#34242). (json-encode): Refer to `json-read' about what the input is and - say what error is signalled. + say what error is signaled. 2019-07-09 Lars Ingebrigtsen @@ -26971,7 +26971,7 @@ help-C-file-name shouldn't error out if we can't find the name * lisp/help-fns.el (help-C-file-name): Make help-C-file-name - return nil instead of signalling an error if we can't find the + return nil instead of signaling an error if we can't find the file name (bug#17250). 2019-06-26 Stefan Monnier @@ -34107,7 +34107,7 @@ Remove unused internal function completion-pcm--optimize-pattern * lisp/minibuffer.el (completion-pcm--optimize-pattern): Remove - unused internal function (that signalled a compilation warning). + unused internal function (that signaled a compilation warning). 2019-05-16 Stefan Monnier @@ -40134,10 +40134,10 @@ 2019-03-30 Mattias Engdegård - Release regexp before signalling overflow error + Release regexp before signaling overflow error * src/search.c (looking_at_1, search_buffer_re): Unfreeze the regexp - buffer before signalling a matcher overflow, since the error + buffer before signaling a matcher overflow, since the error processing may require quite some regexp use as well (Bug#34910). 2019-03-30 Mattias Engdegård @@ -88604,7 +88604,7 @@ Tweak Fdocumentation's error for an undefined function * src/doc.c (Fdocumentation): Restore the pre-25 behavior - of signalling a void-function error for an undefined function. + of signaling a void-function error for an undefined function. This seems cleaner than Emacs 25's "invalid-function: nil" error, which was (probably) an unintended consequence of changes to Findirect_function. diff --git a/admin/notes/bug-triage b/admin/notes/bug-triage index 2974eee179..87fb471c70 100644 --- a/admin/notes/bug-triage +++ b/admin/notes/bug-triage @@ -81,7 +81,7 @@ the ones that are not reproducible on the current release. * New bug triage process The goal of the new bug triage process is similar to the backlog triage process, -except that the focus is on prioritizing the bug, and making sure it is has +except that the focus is on prioritizing the bug, and making sure it has necessary information for others to act on. For each new bug, ask the following questions: diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi index 3665faf3a8..dc643e19a4 100644 --- a/doc/emacs/fixit.texi +++ b/doc/emacs/fixit.texi @@ -201,8 +201,8 @@ sentences and paragraphs, respectively. These commands work like A numeric argument to a transpose command serves as a repeat count: it tells the transpose command to move the character (or word or expression or line) before or containing point across several other -characters (or words or expressions or lines). For example, @kbd{C-u -3 C-t} moves the character before point forward across three other +characters (or words or expressions or lines). For example, @w{@kbd{C-u +3 C-t}} moves the character before point forward across three other characters. It would change @samp{f@point{}oobar} into @samp{oobf@point{}ar}. This is equivalent to repeating @kbd{C-t} three times. @kbd{C-u - 4 M-t} moves the word before point backward @@ -304,10 +304,10 @@ region; @pxref{Disabled Transient Mark}.) @cindex spell-checking the active region Similarly, the command @kbd{M-x ispell} performs spell-checking in the region if one is active, or in the entire buffer otherwise. The -commands @kbd{M-x ispell-buffer} and @kbd{M-x ispell-region} +commands @w{@kbd{M-x ispell-buffer}} and @w{@kbd{M-x ispell-region}} explicitly perform spell-checking on the entire buffer or the region respectively. To check spelling in an email message you are writing, -use @kbd{M-x ispell-message}; that command checks the whole buffer, +use @w{@kbd{M-x ispell-message}}; that command checks the whole buffer, except for material that is indented or appears to be cited from other messages. @xref{Sending Mail}. @@ -365,8 +365,8 @@ wildcard. @item C-g @itemx X Quit interactive spell-checking, leaving point at the word that was -being checked. You can restart checking again afterward with @kbd{C-u -M-$}. +being checked. You can restart checking again afterward with @w{@kbd{C-u +M-$}}. @item x Quit interactive spell-checking and move point back to where it was @@ -384,8 +384,8 @@ Show the list of options. (@code{ispell-complete-word}) performs in-buffer completion based on spelling correction. Insert the beginning of a word, and then type @kbd{M-@key{TAB}}; this shows a list of completions. (If your -window manager intercepts @kbd{M-@key{TAB}}, type @kbd{@key{ESC} -@key{TAB}} or @kbd{C-M-i}.) Each completion is listed with a digit or +window manager intercepts @kbd{M-@key{TAB}}, type @w{@kbd{@key{ESC} +@key{TAB}}} or @kbd{C-M-i}.) Each completion is listed with a digit or character; type that digit or character to choose it. @cindex @code{ispell} program @@ -393,7 +393,7 @@ character; type that digit or character to choose it. Once started, the spell-checker subprocess continues to run, waiting for something to do, so that subsequent spell-checking commands complete more quickly. If you want to get rid of the -process, use @kbd{M-x ispell-kill-ispell}. This is not usually +process, use @w{@kbd{M-x ispell-kill-ispell}}. This is not usually necessary, since the process uses no processor time except when you do spelling correction. @@ -406,7 +406,7 @@ the standard dictionary and your personal dictionary. The standard dictionary is specified by the variable @code{ispell-local-dictionary} or, if that is @code{nil}, by the variable @code{ispell-dictionary}. If both are @code{nil}, the spelling program's default dictionary is -used. The command @kbd{M-x ispell-change-dictionary} sets the +used. The command @w{@kbd{M-x ispell-change-dictionary}} sets the standard dictionary for the buffer and then restarts the subprocess, so that it will use a different standard dictionary. Your personal dictionary is specified by the variable @@ -428,8 +428,8 @@ dictionary. @findex flyspell-mode Flyspell mode is a minor mode that performs automatic spell-checking of the text you type as you type it. When it finds a word that it -does not recognize, it highlights that word. Type @kbd{M-x -flyspell-mode} to toggle Flyspell mode in the current buffer. To +does not recognize, it highlights that word. Type @w{@kbd{M-x +flyspell-mode}} to toggle Flyspell mode in the current buffer. To enable Flyspell mode in all text mode buffers, add @code{flyspell-mode} to @code{text-mode-hook}. @xref{Hooks}. Note that, as Flyspell mode needs to check each word across which you move, @@ -445,14 +445,14 @@ it with @kbd{mouse-2} (@code{flyspell-correct-word}) to display a menu of possible corrections and actions. In addition, @kbd{C-.} or @kbd{@key{ESC}-@key{TAB}} (@code{flyspell-auto-correct-word}) will propose various successive corrections for the word at point, and -@kbd{C-c $} (@code{flyspell-correct-word-before-point}) will pop up a +@w{@kbd{C-c $}} (@code{flyspell-correct-word-before-point}) will pop up a menu of possible corrections. Of course, you can always correct the misspelled word by editing it manually in any way you like. @findex flyspell-prog-mode Flyspell Prog mode works just like ordinary Flyspell mode, except that it only checks words in comments and string constants. This -feature is useful for editing programs. Type @kbd{M-x -flyspell-prog-mode} to enable or disable this mode in the current +feature is useful for editing programs. Type @w{@kbd{M-x +flyspell-prog-mode}} to enable or disable this mode in the current buffer. To enable this mode in all programming mode buffers, add @code{flyspell-prog-mode} to @code{prog-mode-hook} (@pxref{Hooks}). diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 2b25d6023c..85e42d331d 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6929,7 +6929,7 @@ end of the buffer continues from the other end. If is displayed. Any button with a non-@code{nil} @code{skip} property is skipped over. Returns the button found, and signals an error if no buttons can be found. If @var{no-error} in non-@code{nil}, return nil -instead of signalling the error. +instead of signaling the error. @end deffn @deffn Command backward-button n &optional wrap display-message @@ -6941,7 +6941,7 @@ end of the buffer continues from the other end. If is displayed. Any button with a non-@code{nil} @code{skip} property is skipped over. Returns the button found, and signals an error if no buttons can be found. If @var{no-error} in non-@code{nil}, return nil -instead of signalling the error. +instead of signaling the error. @end deffn @defun next-button pos &optional count-current diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index 5cf67ba647..f31bacaed7 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -2287,7 +2287,7 @@ function) as a generalized variable. @var{setter} can be a symbol in which case it will be passed to @code{gv-define-simple-setter}, or it can be of the form @code{(lambda (@var{arg}) @var{body})} in which case that function will additionally have access to the macro (or function)'s arguments and it will -passed to @code{gv-define-setter}. +be passed to @code{gv-define-setter}. @end table diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 92aaf24b85..92684c8993 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -2616,7 +2616,7 @@ if it is non-@code{nil}; this can be overridden by binding This variable is non-@code{nil} when Emacs is running in batch mode. @end defvar -If Emacs exits due to signalling an error in batch mode, the exit +If Emacs exits due to signaling an error in batch mode, the exit status of the Emacs command is non-zero: @example diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index ffdf952b08..fe3d48b3ff 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -4679,7 +4679,7 @@ expanded when the header line is computed. To do this, the above. @var{specification} is an alist that has elements where the @code{car} is a character and the @code{cdr} is the substitution. -If @code{ONLY-PRESENT} is @code{nil}, errors will be signalled if a +If @code{ONLY-PRESENT} is @code{nil}, errors will be signaled if a format character has been used that's not present in @var{specification}. If it's non-@code{nil}, that format specification is left verbatim in the result. @@ -5725,7 +5725,7 @@ made within the @code{combine-after-change-calls} body. @code{after-change-functions} within the body of a @code{combine-after-change-calls} form. -@strong{Warning:} if the changes you combine occur in widely scattered +@strong{Warning:} If the changes you combine occur in widely scattered parts of the buffer, this will still work, but it is not advisable, because it may lead to inefficient behavior for some change hook functions. diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h index d64bb46e9d..01ca648905 100644 --- a/lib/ieee754.in.h +++ b/lib/ieee754.in.h @@ -67,7 +67,7 @@ union ieee754_float #endif /* Little endian. */ } ieee; - /* This format makes it easier to see if a NaN is a signalling NaN. */ + /* This format makes it easier to see if a NaN is a signaling NaN. */ struct { #if __BYTE_ORDER == __BIG_ENDIAN @@ -118,7 +118,7 @@ union ieee754_double #endif /* Little endian. */ } ieee; - /* This format makes it easier to see if a NaN is a signalling NaN. */ + /* This format makes it easier to see if a NaN is a signaling NaN. */ struct { #if __BYTE_ORDER == __BIG_ENDIAN diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 73bbc2fe18..688f8cfa4d 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -677,7 +677,7 @@ Each element is (INDEX . VALUE)") (byte-defop 112 1 byte-current-buffer) (byte-defop 113 0 byte-set-buffer) (byte-defop 114 0 byte-save-current-buffer - "To make a binding to record the current buffer") + "to make a binding to record the current buffer") (byte-defop 115 0 byte-set-mark-OBSOLETE) (byte-defop 116 1 byte-interactive-p-OBSOLETE) diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index fa5d1cff41..797493743c 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -2133,7 +2133,7 @@ buffer, otherwise stop after the first error." (checkdoc-ispell-init) (unless checkdoc-spellcheck-documentation-flag ;; this happens when (checkdoc-ispell-init) can't start `ispell-program-name' - (user-error "No spellchecker installed: check the variable `ispell-program-name'.")) + (user-error "No spellchecker installed: check the variable `ispell-program-name'")) (save-excursion (skip-chars-forward "^a-zA-Z") (let (word sym case-fold-search err word-beginning word-end) diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 9edd85e36b..d56f4151df 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -776,7 +776,7 @@ The result of the body appears to the compiler as a quoted constant." "Eval EXPR and choose among clauses on that value. Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared against each key in each KEYLIST; the corresponding BODY -is evaluated. If no clause succeeds, cl-case returns nil. A +is evaluated. If no clause succeeds, this macro returns nil. A single non-nil atom may be used in place of a KEYLIST of one atom. A KEYLIST of t or `otherwise' is allowed only in the final clause, and matches if no other keys match. Key values are @@ -815,10 +815,10 @@ compared by `eql'. ;;;###autoload (defmacro cl-typecase (expr &rest clauses) - "Evals EXPR, chooses among clauses on that value. + "Eval EXPR and choose among clauses on that value. Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, -cl-typecase returns nil. A TYPE of t or `otherwise' is allowed only in the +this macro returns nil. A TYPE of t or `otherwise' is allowed only in the final clause, and matches if no other keys match. \n(fn EXPR (TYPE BODY...)...)" (declare (indent 1) @@ -2707,7 +2707,7 @@ pairs for that slot. Supported keywords for slots are: - `:read-only': If this has a non-nil value, that slot cannot be set via `setf'. - `:documentation': this is a docstring describing the slot. -- `:type': the type of the field; currently unused. +- `:type': the type of the field; currently only used for documentation. \(fn NAME &optional DOCSTRING &rest SLOTS)" (declare (doc-string 2) (indent 1) diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el index 7dd3cbd1a2..f68c0faf09 100644 --- a/lisp/emacs-lisp/elp.el +++ b/lisp/emacs-lisp/elp.el @@ -238,7 +238,7 @@ FUNSYM must be a symbol of a defined function." ;; The info vector data structure is a 2 element vector. The 0th ;; element is the call-count, i.e. the total number of times this ;; function has been entered. This value is bumped up on entry to - ;; the function so that non-local exists are still recorded. TBD: + ;; the function so that non-local exits are still recorded. TBD: ;; I haven't tested non-local exits at all, so no guarantees. ;; ;; The 1st element is the total amount of time in seconds that has diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el index 8a9b01d580..26ab2679e2 100644 --- a/lisp/emacs-lisp/generator.el +++ b/lisp/emacs-lisp/generator.el @@ -59,7 +59,7 @@ ;; This raw form of iteration is general, but a bit awkward to use, so ;; this library also provides some convenience functions: ;; -;; `iter-do' is like `cl-do', except that instead of walking a list, +;; `iter-do' is like `dolist', except that instead of walking a list, ;; it walks an iterator. `cl-loop' is also extended with a new ;; keyword, `iter-by', that iterates over an iterator. ;; @@ -67,7 +67,7 @@ ;;; Implementation: ;; -;; The internal cps transformation code uses the cps- namespace. +;; The internal CPS transformation code uses the cps- namespace. ;; Iteration functions use the `iter-' namespace. Generator functions ;; are somewhat less efficient than conventional elisp routines, ;; although we try to avoid CPS transformation on forms that do not @@ -89,13 +89,13 @@ `(gensym (format ,fmt ,@args))) (defvar cps--dynamic-wrappers '(identity) - "List of transformer functions to apply to atomic forms we -evaluate in CPS context.") + "List of functions to apply to atomic forms. +These are transformer functions applied to atomic forms evaluated +in CPS context.") (defconst cps-standard-special-forms '(setq setq-default throw interactive) - "List of special forms that we treat just like ordinary - function applications." ) + "List of special forms treated just like ordinary function applications." ) (defun cps--trace-funcall (func &rest args) (message "%S: args=%S" func args) @@ -118,17 +118,15 @@ evaluate in CPS context.") (error "%s not supported in generators" ,function))) (defmacro cps--with-value-wrapper (wrapper &rest body) - "Continue generating CPS code with an atomic-form wrapper -to the current stack of such wrappers. WRAPPER is a function that -takes a form and returns a wrapped form. + "Evaluate BODY with WRAPPER added to the stack of atomic-form wrappers. +WRAPPER is a function that takes an atomic form and returns a wrapped form. Whenever we generate an atomic form (i.e., a form that can't `iter-yield'), we first (before actually inserting that form in our generated code) pass that form through all the transformer functions. We use this facility to wrap forms that can transfer control flow non-locally in goo that diverts this control flow to -the CPS state machinery. -" +the CPS state machinery." (declare (indent 1)) `(let ((cps--dynamic-wrappers (cons @@ -153,7 +151,7 @@ DYNAMIC-VAR bound to STATIC-VAR." ,@body)) (defun cps--add-state (kind body) - "Create a new CPS state with body BODY and return the state's name." + "Create a new CPS state of KIND with BODY and return the state's name." (declare (indent 1)) (let* ((state (cps--gensym "cps-state-%s-" kind))) (push (list state body cps--cleanup-function) cps--states) @@ -170,14 +168,12 @@ DYNAMIC-VAR bound to STATIC-VAR." (and (fboundp handler) handler))) (defvar cps-inhibit-atomic-optimization nil - "When non-nil, always rewrite forms into cps even when they -don't yield.") + "When non-nil, always rewrite forms into CPS even when they don't yield.") (defvar cps--yield-seen) (defun cps--atomic-p (form) - "Return whether the given form never yields." - + "Return nil if FORM can yield, non-nil otherwise." (and (not cps-inhibit-atomic-optimization) (let* ((cps--yield-seen)) (ignore (macroexpand-all @@ -649,8 +645,8 @@ modified copy." (defun iter-yield (value) "When used inside a generator, yield control to caller. The caller of `iter-next' receives VALUE, and the next call to -`iter-next' resumes execution at the previous -`iter-yield' point." +`iter-next' resumes execution with the form immediately following this +`iter-yield' call." (identity value) (error "`iter-yield' used outside a generator")) diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index b43e53b9d2..065a968877 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el @@ -38,7 +38,7 @@ ;; ;; Instead, we use here a higher-order approach: instead ;; of a 5-tuple, a place-expander returns a function. -;; If you think about types, the old approach return things of type +;; If you think about types, the old approach returns things of type ;; {vars: List Var, values: List Exp, ;; stores: List Var, getter: Exp, setter: Exp} ;; whereas the new approach returns a function of type diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index fbbd389bf9..fa857cd4c6 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -535,7 +535,7 @@ This will generate compile-time constants from BINDINGS." ;; Support backtrace mode. (defconst lisp-el-font-lock-keywords-for-backtraces lisp-el-font-lock-keywords - "Default highlighting from Emacs Lisp mod used in Backtrace mode.") + "Default highlighting from Emacs Lisp mode used in Backtrace mode.") (defconst lisp-el-font-lock-keywords-for-backtraces-1 lisp-el-font-lock-keywords-1 "Subdued highlighting from Emacs Lisp mode used in Backtrace mode.") (defconst lisp-el-font-lock-keywords-for-backtraces-2 diff --git a/lisp/image/exif.el b/lisp/image/exif.el index 065456dc31..6aeb52c726 100644 --- a/lisp/image/exif.el +++ b/lisp/image/exif.el @@ -95,7 +95,7 @@ mirrored or not.") "Parse FILE (a JPEG file) and return the Exif data, if any. The return value is a list of Exif items. -If the data is invalid, an `exif-error' is signalled." +If the data is invalid, an `exif-error' is signaled." (with-temp-buffer (set-buffer-multibyte nil) (insert-file-contents-literally file) @@ -105,7 +105,7 @@ If the data is invalid, an `exif-error' is signalled." "Parse BUFFER (which should be a JPEG file) and return the Exif data, if any. The return value is a list of Exif items. -If the data is invalid, an `exif-error' is signalled." +If the data is invalid, an `exif-error' is signaled." (setq buffer (or buffer (current-buffer))) (with-current-buffer buffer (if enable-multibyte-characters diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el index caa5747817..5cc10b1315 100644 --- a/lisp/international/mule-util.el +++ b/lisp/international/mule-util.el @@ -75,7 +75,7 @@ unless the display width of STR is equal to or less than the display width of ELLIPSIS. If it is non-nil and not a string, then ELLIPSIS defaults to `truncate-string-ellipsis'. -If ELLIPSIS-TEXT-PROPERTY in non-nil, a too-long string will not +If ELLIPSIS-TEXT-PROPERTY is non-nil, a too-long string will not be truncated, but instead the elided parts will be covered by a `display' text property showing the ellipsis." (or start-column diff --git a/lisp/json.el b/lisp/json.el index 18d7fda882..ac323dac29 100644 --- a/lisp/json.el +++ b/lisp/json.el @@ -735,7 +735,7 @@ you will get the following structure returned: OBJECT should have a structure like one returned by `json-read'. If an error is detected during encoding, an error based on -`json-error' is signalled." +`json-error' is signaled." (cond ((memq object (list t json-null json-false)) (json-encode-keyword object)) ((stringp object) (json-encode-string object)) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index b81f778eb4..f6e2b236f3 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -163,8 +163,8 @@ perform completion, no matter what ACTION is. If ACTION is `metadata' or a list where the first element is `boundaries', return nil. If ACTION is nil, this function works -like `try-completion'; if it's t, this function works like -`all-completion'; and any other values makes it work like +like `try-completion'; if it is t, this function works like +`all-completion'; and any other value makes it work like `test-completion'." (cond ((functionp collection) (funcall collection string predicate action)) diff --git a/lisp/obsolete/cl.el b/lisp/obsolete/cl.el index 1da4289b69..20bffffd78 100644 --- a/lisp/obsolete/cl.el +++ b/lisp/obsolete/cl.el @@ -509,7 +509,7 @@ This method shows how to handle `setf's to places of the form ARGLIST, as if NAME were going to be expanded as a macro, then the BODY forms are executed and must return a list of five elements: a temporary-variables list, a value-forms list, a store-variables list -\(of length one), a store-form, and an access- form. +\(of length one), a store-form, and an access-form. See `gv-define-expander', and `gv-define-setter' for better and simpler ways to define setf-methods." diff --git a/lisp/startup.el b/lisp/startup.el index 5af264e3ef..bff10003f8 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -352,11 +352,11 @@ Setting `init-file-user' does not prevent Emacs from loading (defcustom site-run-file (purecopy "site-start") "File containing site-wide run-time initializations. -This file is loaded at run-time before `~/.emacs'. It contains inits -that need to be in place for the entire site, but which, due to their -higher incidence of change, don't make sense to put into Emacs's +This file is loaded at run-time before `user-init-file'. It contains +inits that need to be in place for the entire site, but which, due to +their higher incidence of change, don't make sense to put into Emacs's dump file. Thus, the run-time load order is: 1. file described in -this variable, if non-nil; 2. `~/.emacs'; 3. `default.el'. +this variable, if non-nil; 2. `user-init-file'; 3. `default.el'. Don't use the `site-start.el' file for things some users may not like. Put them in `default.el' instead, so that users can more easily diff --git a/lisp/subr.el b/lisp/subr.el index a744cfddfd..33194e4ffa 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -385,7 +385,7 @@ entry to the debugger, even when `debug-on-error' is non-nil. This can be overridden by `debug-ignored-errors'. To signal with MESSAGE without interpreting format characters -like `%', `\\=`' and `\\='', use (error \"%s\" MESSAGE). +like `%', `\\=`' and `\\='', use (user-error \"%s\" MESSAGE). In Emacs, the convention is that error messages start with a capital letter but *do not* end with a period. Please follow this convention for the sake of consistency." @@ -3290,7 +3290,7 @@ alternatives." (defun function-get (f prop &optional autoload) "Return the value of property PROP of function F. -If AUTOLOAD is non-nil and F is autoloaded, try to autoload it +If AUTOLOAD is non-nil and F is autoloaded, try to load it in the hope that it will set PROP. If AUTOLOAD is `macro', do it only if it's an autoloaded macro." (let ((val nil)) @@ -4997,7 +4997,7 @@ The properties used on SYMBOL are `composefunc', `sendfunc', (defun backtrace-frames (&optional base) "Collect all frames of current backtrace into a list. If non-nil, BASE should be a function, and frames before its -nearest activation frames are discarded." +nearest activation frame are discarded." (let ((frames nil)) (mapbacktrace (lambda (&rest frame) (push frame frames)) (or base 'backtrace-frames)) diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index a9fbd2f04c..65f61644b6 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -800,8 +800,8 @@ Otherwise returns the library directory name, if that is defined." (defun ispell-create-debug-buffer (&optional append) "Create an ispell debug buffer for debugging output. -If APPEND is non-nil, append the info to previous buffer if exists, -otherwise is reset. Returns name of ispell debug buffer. +If APPEND is non-nil, add output to the old buffer if it exists, +otherwise the buffer is erased first. Returns the debug buffer. See `ispell-buffer-with-debug' for an example of use." (let ((ispell-debug-buffer (get-buffer-create "*ispell-debug*"))) (with-current-buffer ispell-debug-buffer @@ -812,7 +812,7 @@ See `ispell-buffer-with-debug' for an example of use." ispell-debug-buffer)) (defsubst ispell-print-if-debug (format &rest args) - "Print message using FORMAT and ARGS to `ispell-debug-buffer' buffer if enabled." + "Print message using FORMAT and ARGS to `ispell-debug-buffer' if enabled." (if (boundp 'ispell-debug-buffer) (with-current-buffer ispell-debug-buffer (goto-char (point-max)) @@ -3618,8 +3618,8 @@ Returns the sum SHIFT due to changes in word replacements." ;;;###autoload (defun ispell-buffer-with-debug (&optional append) - "`ispell-buffer' with some output sent to `ispell-debug-buffer' buffer. -If APPEND is non-n il, append the info to previous buffer if exists." + "`ispell-buffer' with some output sent to `ispell-debug-buffer'. +If APPEND is non-nil, don't erase previous debugging output." (interactive) (let ((ispell-debug-buffer (ispell-create-debug-buffer append))) (ispell-buffer))) diff --git a/src/eval.c b/src/eval.c index 78a787c4ff..014905ce6d 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1229,7 +1229,7 @@ The car of a handler may be a list of condition names instead of a single condition name; then it handles all of them. If the special condition name `debug' is present in this list, it allows another condition in the list to run the debugger if `debug-on-error' and the -other usual mechanisms says it should (otherwise, `condition-case' +other usual mechanisms say it should (otherwise, `condition-case' suppresses the debugger). When a handler handles an error, control returns to the `condition-case' diff --git a/src/lread.c b/src/lread.c index af7480a976..f9a8cb3e1a 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4919,7 +4919,7 @@ features required. Each entry has the form `(provide . FEATURE)', `(defface . SYMBOL)', `(define-type . SYMBOL)', `(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'. Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry, -and means that SYMBOL was an autoload before this file redefined it +and mean that SYMBOL was an autoload before this file redefined it as a function. In addition, entries may also be single symbols, which means that symbol was defined by `defvar' or `defconst'. diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el index 63c4c32d45..6c08023d4f 100644 --- a/test/lisp/jsonrpc-tests.el +++ b/test/lisp/jsonrpc-tests.el @@ -114,7 +114,7 @@ (condition-case err (progn (jsonrpc-request conn 'delete-directory "~/tmp") - (ert-fail "A `jsonrpc-error' should have been signalled!")) + (ert-fail "A `jsonrpc-error' should have been signaled!")) (jsonrpc-error (should (= -32601 (cdr (assoc 'jsonrpc-error-code (cdr err))))))))) @@ -124,7 +124,7 @@ (condition-case err (progn (jsonrpc-request conn '+ ["a" 2]) - (ert-fail "A `jsonrpc-error' should have been signalled!")) + (ert-fail "A `jsonrpc-error' should have been signaled!")) (jsonrpc-error (should (= -32603 (cdr (assoc 'jsonrpc-error-code (cdr err))))))))) diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el index 6673ac4b4e..5d85fc74e5 100644 --- a/test/src/thread-tests.el +++ b/test/src/thread-tests.el @@ -112,7 +112,7 @@ (should-error (thread-join (current-thread)))) (ert-deftest threads-join-error () - "Test of error signalling from `thread-join'." + "Test of error signaling from `thread-join'." :tags '(:unstable) (skip-unless (featurep 'threads)) (let ((thread (make-thread #'threads-call-error)))