commit eb98afaf354288c583ceb2fbdd647841d5c76b2d (HEAD, refs/remotes/origin/master) Author: Lars Ingebrigtsen Date: Sun Dec 27 09:22:02 2020 +0100 Fix up length_internal with degenerate length inputs * src/fns.c (length_internal): Protect against edge conditions. diff --git a/src/fns.c b/src/fns.c index 0fded92aeb..6aad119d1f 100644 --- a/src/fns.c +++ b/src/fns.c @@ -159,14 +159,14 @@ EMACS_INT length_internal (Lisp_Object sequence, int len) if (len < 0xffff) while (CONSP (sequence)) { - if (--len == 0) + if (--len <= 0) return -1; sequence = XCDR (sequence); } /* Signal an error on circular lists. */ else FOR_EACH_TAIL (sequence) - if (--len == 0) + if (--len <= 0) return -1; return len; } @@ -210,6 +210,9 @@ counted. */) CHECK_FIXNUM (length); EMACS_INT len = XFIXNUM (length); + if (len < 0) + return Qnil; + if (CONSP (sequence)) return length_internal (sequence, len + 1) == 1? Qt: Qnil; else diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 3486c745bf..e66dad44a1 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -1025,6 +1025,17 @@ (should (length= "abc" 3)) (should-not (length= "abc" 4)) + (should-not (length< (list 1 2 3) -1)) + (should-not (length< (list 1 2 3) 0)) + (should-not (length< (list 1 2 3) -10)) + + (should (length> (list 1 2 3) -1)) + (should (length> (list 1 2 3) 0)) + + (should-not (length= (list 1 2 3) -1)) + (should-not (length= (list 1 2 3) 0)) + (should-not (length= (list 1 2 3) 1)) + (should-error (let ((list (list 1))) (setcdr list list) commit 80420faf4921ffe5e9d4c4f9595941acf3156e50 Author: Daniel Martín Date: Sun Dec 27 09:04:56 2020 +0100 Improve "find definition" in *Help* buffers * lisp/emacs-lisp/find-func.el (find-function-search-for-symbol): If our regexp algorithm could not find a location for the symbol definition, resort to find-function--search-by-expanding-macros. * test/lisp/emacs-lisp/find-func-tests.el: Add a automatic test for a function and variable generated by a macro. * etc/NEWS: Advertise the improved functionality (bug#45443). diff --git a/etc/NEWS b/etc/NEWS index 9ae8cc91d6..4f072df31c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -114,6 +114,12 @@ choosing a group, or clicking a button in the "*Help*" buffers when looking at the doc string of a function that belongs to one of these groups. +--- +** Improved "find definition" feature of *Help* buffers. +Now clicking on the link to find the definition of functions generated +by 'cl-defstruct', or variables generated by 'define-derived-mode', +for example, will go to the exact place where they are defined. + ** New variable 'redisplay-skip-initial-frame' to enable batch redisplay tests. Setting it to nil forces the redisplay to do its job even in the initial frame used in batch mode. diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index 074e7db295..7796a72ecf 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -389,7 +389,70 @@ The search is done in the source for library LIBRARY." (progn (beginning-of-line) (cons (current-buffer) (point))) - (cons (current-buffer) nil))))))))) + ;; If the regexp search didn't find the location of + ;; the symbol (for example, because it is generated by + ;; a macro), try a slightly more expensive search that + ;; expands macros until it finds the symbol. + (cons (current-buffer) + (find-function--search-by-expanding-macros + (current-buffer) symbol type)))))))))) + +(defun find-function--try-macroexpand (form) + "Try to macroexpand FORM in full or partially. +This is a best-effort operation in which if macroexpansion fails, +this function returns FORM as is." + (ignore-errors + (or + (macroexpand-all form) + (macroexpand-1 form) + form))) + +(defun find-function--any-subform-p (form pred) + "Walk FORM and apply PRED to its subexpressions. +Return t if any PRED returns t." + (cond + ((not (consp form)) nil) + ((funcall pred form) t) + (t + (cl-destructuring-bind (left-child . right-child) form + (or + (find-function--any-subform-p left-child pred) + (find-function--any-subform-p right-child pred)))))) + +(defun find-function--search-by-expanding-macros (buf symbol type) + "Expand macros in BUF to search for the definition of SYMBOL of TYPE." + (catch 'found + (with-current-buffer buf + (save-excursion + (goto-char (point-min)) + (condition-case nil + (while t + (let ((form (read (current-buffer))) + (expected-symbol-p + (lambda (form) + (cond + ((null type) + ;; Check if a given form is a `defalias' to + ;; SYM, the function name we are searching + ;; for. All functions in Emacs Lisp + ;; ultimately expand to a `defalias' form + ;; after several steps of macroexpansion. + (and (eq (car-safe form) 'defalias) + (equal (car-safe (cdr form)) + `(quote ,symbol)))) + ((eq type 'defvar) + ;; Variables generated by macros ultimately + ;; expand to `defvar'. + (and (eq (car-safe form) 'defvar) + (eq (car-safe (cdr form)) symbol))) + (t nil))))) + (when (find-function--any-subform-p + (find-function--try-macroexpand form) + expected-symbol-p) + ;; We want to return the location at the beginning + ;; of the macro, so move back one sexp. + (throw 'found (progn (backward-sexp) (point)))))) + (end-of-file nil)))))) (defun find-function-library (function &optional lisp-only verbose) "Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION. diff --git a/test/lisp/emacs-lisp/find-func-tests.el b/test/lisp/emacs-lisp/find-func-tests.el index d77eb6757f..03df4bb9ff 100644 --- a/test/lisp/emacs-lisp/find-func-tests.el +++ b/test/lisp/emacs-lisp/find-func-tests.el @@ -43,5 +43,15 @@ (concat data-directory (kbd "n x / TAB RET")) (read-library-name))))) +;; Avoid a byte-compilation warning that may confuse people reading +;; the result of the following test. +(declare-function compilation--message->loc nil "compile") + +(ert-deftest find-func-tests--locate-macro-generated-symbols () ;bug#45443 + (should (cdr (find-function-search-for-symbol + #'compilation--message->loc nil "compile"))) + (should (cdr (find-function-search-for-symbol + 'c-mode-hook 'defvar "cc-mode")))) + (provide 'find-func-tests) ;;; find-func-tests.el ends here commit 0f790464d547dd57a857d88dab309b286067ac45 Author: Lars Ingebrigtsen Date: Sun Dec 27 09:00:23 2020 +0100 Add new predicates for sequence lengths * doc/lispref/sequences.texi (Sequence Functions): Document them. * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Mark them as side-effect-free. * lisp/emacs-lisp/shortdoc.el (list): Mention them. * src/fns.c (Flength): Mention them in the doc string. (length_internal): New function. (Flength_less, Flength_greater, Flength_equal): New defuns. (syms_of_fns): Sym them. diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index 952834bd4e..57b49847e7 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -116,6 +116,21 @@ If you need to compute the width of a string on display, you should use since @code{length} only counts the number of characters, but does not account for the display width of each character. +@defun length< sequence length +Return non-@code{nil} if @var{sequence} is shorter than @var{length}. +This may be more efficient than computing the length of @var{sequence} +if @var{sequence} is a long list. +@end defun + +@defun length> sequence length +Return non-@code{nil} if @var{sequence} is longer than @var{length}. +@end defun + +@defun length= sequence length +Return non-@code{nil} if the length of @var{sequence} is equal to +@var{length}. +@end defun + @defun elt sequence index @anchor{Definition of elt} @cindex elements of sequences diff --git a/etc/NEWS b/etc/NEWS index d24d8b1f0a..9ae8cc91d6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1460,6 +1460,12 @@ that makes it a valid button. ** Miscellaneous ++++ +*** New predicate functions 'length<', 'length>' and 'length='. +Using these functions may be more efficient than using 'length' (if +the length of a (long) list is being computed just to compare this +length to a number). + --- *** 'remove-hook' is now an interactive command. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 469bbe6c7c..0eee6e9d01 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1169,7 +1169,9 @@ hash-table-count int-to-string intern-soft isnan keymap-parent - lax-plist-get ldexp length line-beginning-position line-end-position + lax-plist-get ldexp + length length< length> length= + line-beginning-position line-end-position local-variable-if-set-p local-variable-p locale-info log log10 logand logb logcount logior lognot logxor lsh make-byte-code make-list make-string make-symbol marker-buffer max diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 9d183e0d4e..c6259f8971 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -618,6 +618,12 @@ There can be any number of :example/:result elements." "Data About Lists" (length :eval (length '(a b c))) + (length< + :eval (lenth< '(a b c) 1)) + (length> + :eval (lenth> '(a b c) 1)) + (length= + :eval (lenth> '(a b c) 3)) (safe-length :eval (safe-length '(a b c)))) diff --git a/src/fns.c b/src/fns.c index 646c3ed083..0fded92aeb 100644 --- a/src/fns.c +++ b/src/fns.c @@ -105,9 +105,14 @@ list_length (Lisp_Object list) DEFUN ("length", Flength, Slength, 1, 1, 0, doc: /* Return the length of vector, list or string SEQUENCE. A byte-code function object is also allowed. + If the string contains multibyte characters, this is not necessarily the number of bytes in the string; it is the number of characters. -To get the number of bytes, use `string-bytes'. */) +To get the number of bytes, use `string-bytes'. + +If the length of a list is being computed to compare to a (small) +number, the `string<', `string>' and `string=' functions may be more +efficient. */) (Lisp_Object sequence) { EMACS_INT val; @@ -145,6 +150,72 @@ least the number of distinct elements. */) return make_fixnum (len); } +static inline +EMACS_INT length_internal (Lisp_Object sequence, int len) +{ + /* If LENGTH is short (arbitrarily chosen cut-off point), use a + fast loop that doesn't care about whether SEQUENCE is + circular or not. */ + if (len < 0xffff) + while (CONSP (sequence)) + { + if (--len == 0) + return -1; + sequence = XCDR (sequence); + } + /* Signal an error on circular lists. */ + else + FOR_EACH_TAIL (sequence) + if (--len == 0) + return -1; + return len; +} + +DEFUN ("length<", Flength_less, Slength_less, 2, 2, 0, + doc: /* Return non-nil if SEQUENCE is shorter than LENGTH. +See `length' for allowed values of SEQUENCE and how elements are +counted. */) + (Lisp_Object sequence, Lisp_Object length) +{ + CHECK_FIXNUM (length); + EMACS_INT len = XFIXNUM (length); + + if (CONSP (sequence)) + return length_internal (sequence, len) == -1? Qnil: Qt; + else + return XFIXNUM (Flength (sequence)) < len? Qt: Qnil; +} + +DEFUN ("length>", Flength_greater, Slength_greater, 2, 2, 0, + doc: /* Return non-nil if SEQUENCE is longer than LENGTH. +See `length' for allowed values of SEQUENCE and how elements are +counted. */) + (Lisp_Object sequence, Lisp_Object length) +{ + CHECK_FIXNUM (length); + EMACS_INT len = XFIXNUM (length); + + if (CONSP (sequence)) + return length_internal (sequence, len + 1) == -1? Qt: Qnil; + else + return XFIXNUM (Flength (sequence)) > len? Qt: Qnil; +} + +DEFUN ("length=", Flength_equal, Slength_equal, 2, 2, 0, + doc: /* Return non-nil if SEQUENCE is equal to LENGTH. +See `length' for allowed values of SEQUENCE and how elements are +counted. */) + (Lisp_Object sequence, Lisp_Object length) +{ + CHECK_FIXNUM (length); + EMACS_INT len = XFIXNUM (length); + + if (CONSP (sequence)) + return length_internal (sequence, len + 1) == 1? Qt: Qnil; + else + return XFIXNUM (Flength (sequence)) == len? Qt: Qnil; +} + DEFUN ("proper-list-p", Fproper_list_p, Sproper_list_p, 1, 1, 0, doc: /* Return OBJECT's length if it is a proper list, nil otherwise. A proper list is neither circular nor dotted (i.e., its last cdr is nil). */ @@ -5721,6 +5792,9 @@ this variable. */); defsubr (&Srandom); defsubr (&Slength); defsubr (&Ssafe_length); + defsubr (&Slength_less); + defsubr (&Slength_greater); + defsubr (&Slength_equal); defsubr (&Sproper_list_p); defsubr (&Sstring_bytes); defsubr (&Sstring_distance); diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index eaa569e0d9..3486c745bf 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -999,3 +999,33 @@ (object-intervals (current-buffer))) '((0 1 (foo 1)) (1 2 (zot 3 foo 1)) (2 4 (zot 3 bar 2)) (4 5 (bar 2)) (5 6 nil))))) + +(ert-deftest length-equals-tests () + (should-not (length< (list 1 2 3) 2)) + (should-not (length< (list 1 2 3) 3)) + (should (length< (list 1 2 3) 4)) + + (should-not (length< "abc" 2)) + (should-not (length< "abc" 3)) + (should (length< "abc" 4)) + + (should (length> (list 1 2 3) 2)) + (should-not (length> (list 1 2 3) 3)) + (should-not (length> (list 1 2 3) 4)) + + (should (length> "abc" 2)) + (should-not (length> "abc" 3)) + (should-not (length> "abc" 4)) + + (should-not (length= (list 1 2 3) 2)) + (should (length= (list 1 2 3) 3)) + (should-not (length= (list 1 2 3) 4)) + + (should-not (length= "abc" 2)) + (should (length= "abc" 3)) + (should-not (length= "abc" 4)) + + (should-error + (let ((list (list 1))) + (setcdr list list) + (length< list #x1fffe)))) commit 714ca849ba658405ddde698cdc5836c4c9b289ca Author: Lars Ingebrigtsen Date: Sat Dec 26 23:13:29 2020 +0100 Improve the edebug-form-data doc string * lisp/emacs-lisp/edebug.el (edebug-form-data): Doc string clarification (bug#42776). diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index f242e922bd..8e5ece3605 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -592,7 +592,7 @@ already is one.)" "A list of entries associating symbols with buffer regions. Each entry is an `edebug--form-data' struct with fields: SYMBOL, BEGIN-MARKER, and END-MARKER. The markers -are at the beginning and end of an entry level form and SYMBOL is +are at the beginning and end of an instrumented form and SYMBOL is a symbol that holds all edebug related information for the form on its property list. commit 4b2ca6bfc079c66cfcf39f2f36dc139012787535 Author: Stefan Monnier Date: Sat Dec 26 12:21:17 2020 -0500 * lisp/forms.el (forms--run-functions): New function (forms--intuit-from-file, forms-save-buffer): Use it. (forms-mode): Use it to fix regression. Remove always-true test. Fix incorrect uses of `fboundp`. (forms--iif-hook): Use `add-hook`. (forms--iif-post-command-hook): Use `remove-hook` and fix typo. (forms--debug): Use `mapconcat`. diff --git a/lisp/forms.el b/lisp/forms.el index 8974f99ef5..b8638bc6e2 100644 --- a/lisp/forms.el +++ b/lisp/forms.el @@ -436,6 +436,14 @@ Also, initial position is at last record." (defvar read-file-filter) ; bound in forms--intuit-from-file +;; The code used to use `run-hooks' but in a way that's actually +;; incompatible with hooks (and with lexical scoping), so this function +;; approximates the actual behavior that `run-hooks' provided. +(defun forms--run-functions (functions) + (if (functionp functions) + (funcall functions) + (mapc #'funcall functions))) + ;;;###autoload (defun forms-mode (&optional primary) ;; FIXME: use define-derived-mode @@ -547,8 +555,6 @@ Commands: Equivalent keys in read-only mode: "`forms-multi-line' is equal to `forms-field-sep'"))) (error (concat "Forms control file error: " "`forms-multi-line' must be nil or a one-character string")))) - (or (fboundp 'set-text-properties) - (setq forms-use-text-properties nil)) ;; Validate and process forms-format-list. ;;(message "forms: pre-processing format list...") @@ -568,12 +574,12 @@ Commands: Equivalent keys in read-only mode: ;; Check if record filters are defined. (if (and forms-new-record-filter - (not (fboundp forms-new-record-filter))) + (not (functionp forms-new-record-filter))) (error (concat "Forms control file error: " "`forms-new-record-filter' is not a function"))) (if (and forms-modified-record-filter - (not (fboundp forms-modified-record-filter))) + (not (functionp forms-modified-record-filter))) (error (concat "Forms control file error: " "`forms-modified-record-filter' is not a function"))) @@ -647,7 +653,7 @@ Commands: Equivalent keys in read-only mode: (with-current-buffer forms--file-buffer (let ((inhibit-read-only t) (file-modified (buffer-modified-p))) - (mapc #'funcall read-file-filter) + (forms--run-functions read-file-filter) (if (not file-modified) (set-buffer-modified-p nil))) (if write-file-filter (add-hook 'write-file-functions write-file-filter nil t))) @@ -875,8 +881,7 @@ Commands: Equivalent keys in read-only mode: (list 'face forms--rw-face 'front-sticky '(face)))) ;; Enable `post-command-hook' to restore the properties. - (setq post-command-hook - (append (list 'forms--iif-post-command-hook) post-command-hook))) + (add-hook 'post-command-hook #'forms--iif-post-command-hook)) ;; No action needed. Clear marker. (setq forms--iif-start nil))) @@ -885,8 +890,7 @@ Commands: Equivalent keys in read-only mode: "`post-command-hook' function for read-only segments." ;; Disable `post-command-hook'. - (setq post-command-hook - (delq 'forms--iif-hook-post-command-hook post-command-hook)) + (remove-hook 'post-command-hook #'forms--iif-post-command-hook) ;; Restore properties. (if forms--iif-start @@ -916,7 +920,7 @@ Commands: Equivalent keys in read-only mode: (if forms-use-text-properties `(lambda (arg) (let ((inhibit-read-only t)) - ,@(apply 'append + ,@(apply #'append (mapcar #'forms--make-format-elt-using-text-properties forms-format-list)) ;; Prevent insertion before the first text. @@ -929,7 +933,7 @@ Commands: Equivalent keys in read-only mode: '(rear-nonsticky nil))) (setq forms--iif-start nil)) `(lambda (arg) - ,@(apply 'append + ,@(apply #'append (mapcar #'forms--make-format-elt forms-format-list))))) ;; We have tallied the number of markers and dynamic texts, @@ -1100,7 +1104,7 @@ Commands: Equivalent keys in read-only mode: `(lambda nil (let (here) (goto-char (point-min)) - ,@(apply 'append + ,@(apply #'append (mapcar #'forms--make-parser-elt (append forms-format-list (list nil))))))))) @@ -1219,7 +1223,7 @@ Commands: Equivalent keys in read-only mode: (setq the-record (with-current-buffer forms--file-buffer (let ((inhibit-read-only t)) - (run-hooks 'read-file-filter)) + (forms--run-functions read-file-filter)) (goto-char (point-min)) (forms--get-record))) @@ -1427,7 +1431,7 @@ Commands: Equivalent keys in read-only mode: ;; ;; We have our own revert function - use it. (make-local-variable 'revert-buffer-function) - (setq revert-buffer-function 'forms--revert-buffer) + (setq revert-buffer-function #'forms--revert-buffer) t) @@ -1900,7 +1904,7 @@ after writing out the data." ;; Write file hooks are run via write-file-functions. ;; (if write-file-filter ;; (save-excursion - ;; (run-hooks 'write-file-filter))) + ;; (forms--run-functions write-file-filter))) ;; If they have a write-file-filter, force the buffer to be ;; saved even if it doesn't seem to be changed. First, they @@ -1912,7 +1916,7 @@ after writing out the data." (save-buffer args) (if read-file-filter (save-excursion - (run-hooks 'read-file-filter))) + (forms--run-functions read-file-filter))) (set-buffer-modified-p nil))) ;; Make sure we end up with the same record number as we started. ;; Since read-file-filter may perform arbitrary transformations on @@ -2037,20 +2041,19 @@ Usage: (setq forms-number-of-fields (defun forms--debug (&rest args) "Internal debugging routine." (if forms--debug - (let ((ret nil)) - (while args - (let ((el (car-safe args))) - (setq args (cdr-safe args)) - (if (stringp el) - (setq ret (concat ret el)) - (setq ret (concat ret (prin1-to-string el) " = ")) - (if (boundp el) - (let ((vel (eval el))) - (setq ret (concat ret (prin1-to-string vel) "\n"))) - (setq ret (concat ret "" "\n"))) - (if (fboundp el) - (setq ret (concat ret (prin1-to-string (symbol-function el)) - "\n")))))) + (let ((ret + (mapconcat + (lambda (el) + (if (stringp el) el + (concat (prin1-to-string el) " = " + (if (boundp el) + (prin1-to-string (eval el)) + "") + "\n" + (if (fboundp el) + (concat (prin1-to-string (symbol-function el)) + "\n"))))) + args ""))) (with-current-buffer (get-buffer-create "*forms-mode debug*") (if (zerop (buffer-size)) (emacs-lisp-mode)) commit 25fb44fad15743cd7725aa73681c2652d5a23b09 Author: Eli Zaretskii Date: Sat Dec 26 15:01:52 2020 +0200 Fix test/src/process-tests on MS-Windows * src/process.c (network_lookup_address_info_1) [WINDOWSNT]: Initialize winsock. diff --git a/src/process.c b/src/process.c index 98b575fc86..28ab15c903 100644 --- a/src/process.c +++ b/src/process.c @@ -4512,6 +4512,12 @@ network_lookup_address_info_1 (Lisp_Object host, const char *service, if (STRING_MULTIBYTE (host) && SBYTES (host) != SCHARS (host)) error ("Non-ASCII hostname %s detected, please use puny-encode-domain", SSDATA (host)); + +#ifdef WINDOWSNT + /* Ensure socket support is loaded if available. */ + init_winsock (TRUE); +#endif + ret = getaddrinfo (SSDATA (host), service, hints, res); if (ret) { commit fd658b810056d41fad9edeba8bdba0594fc87867 Author: Michael Albinus Date: Sat Dec 26 12:39:10 2020 +0100 Rename Tramp method "media" to "mtp" (Bug#45402) * doc/misc/tramp.texi (Quick Start Guide, GVFS-based methods): Rename "media" to "mtp". (Bug#45402) * etc/NEWS: Rename Tramp method "media" to "mtp". Fix typos. * lisp/net/tramp-gvfs.el (tramp-gvfs-methods, tramp-media-methods) (tramp-gvfs-activation-uri) (tramp-gvfs-handler-volumeadded-volumeremoved) (tramp-get-media-devices, top): Rename "media" to "mtp". (Bug#45402) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index dd350f10c0..2133dfec35 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -558,8 +558,8 @@ of the local file name is the share exported by the remote host, @cindex method @option{davs} @cindex @option{dav} method @cindex @option{davs} method -@cindex method @option{media} -@cindex @option{media} method +@cindex method @option{mtp} +@cindex @option{mtp} method On systems, which have installed @acronym{GVFS, the GNOME Virtual File System}, its offered methods could be used by @value{tramp}. Examples @@ -567,7 +567,7 @@ are @file{@trampfn{sftp,user@@host,/path/to/file}}, @file{@trampfn{afp,user@@host,/path/to/file}} (accessing Apple's AFP file system), @file{@trampfn{dav,user@@host,/path/to/file}}, @file{@trampfn{davs,user@@host,/path/to/file}} (for WebDAV shares) and -@file{@trampfn{media,device,/path/to/file}} (for media devices). +@file{@trampfn{mtp,device,/path/to/file}} (for media devices). @anchor{Quick Start Guide: GNOME Online Accounts based methods} @@ -1246,13 +1246,13 @@ Since Google Drive uses cryptic blob file names internally, could produce unexpected behavior in case two files in the same directory have the same @code{display-name}, such a situation must be avoided. -@item @option{media} -@cindex method @option{media} -@cindex @option{media} method +@item @option{mtp} +@cindex method @option{mtp} +@cindex @option{mtp} method @cindex media Media devices, like cell phones, tablets, cameras, can be accessed via -the @option{media} method. Just the device name is needed in order to +the @option{mtp} method. Just the device name is needed in order to specify the host in the file name. However, the device must already be connected via USB, before accessing it. Possible device names are visible via host name completion, @ref{File name completion}. @@ -1263,7 +1263,7 @@ different parts of their file system. @value{tramp} does not require a host name as part of the remote file name when a single media device is connected. @value{tramp} instead -uses @file{@trampfn{media,,}} as the default name. +uses @file{@trampfn{mtp,,}} as the default name. @item @option{nextcloud} @cindex method @option{nextcloud} @@ -1289,7 +1289,7 @@ that for security reasons refuse @command{ssh} connections. @defopt tramp-gvfs-methods This user option is a list of external methods for @acronym{GVFS}@. By default, this list includes @option{afp}, @option{dav}, -@option{davs}, @option{gdrive}, @option{media}, @option{nextcloud} and +@option{davs}, @option{gdrive}, @option{mtp}, @option{nextcloud} and @option{sftp}. Other methods to include are @option{ftp}, @option{http}, @option{https} and @option{smb}. These methods are not intended to be used directly as @acronym{GVFS}-based method. Instead, diff --git a/etc/NEWS b/etc/NEWS index a320acb5fa..d24d8b1f0a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -384,7 +384,7 @@ If your mouse or trackpad supports it, you can now scroll tabs when the mouse pointer is in the tab line by scrolling left or right. --- -*** New tab-line faces and options +*** New tab-line faces and options. The face 'tab-line-tab-special' is used for tabs whose buffers are special, i.e. not file-backed. The face 'tab-line-tab-inactive-alternate' is used to display inactive tabs @@ -890,7 +890,7 @@ preferred over the eudcb-mab.el backend. ** Tramp +++ -*** New connection method "media", which allows accessing media devices +*** New connection method "mtp", which allows accessing media devices like cell phones, tablets or cameras. +++ @@ -1465,7 +1465,7 @@ that makes it a valid button. --- *** New user option 'authinfo-hide-elements'. -This can be set to nil to inhibit hiding passwords in .authinfo files. +This can be set to nil to inhibit hiding passwords in ".authinfo" files. +++ *** A number of new string manipulation functions have been added. @@ -2009,7 +2009,7 @@ used in. +++ ** 'truncate-string-ellipsis' now uses '…' by default. Modes that use 'truncate-string-to-width' with non-nil, non-string -argument 'ellipsis', will now indicate truncation using '…' when +argument ELLIPSIS, will now indicate truncation using '…' when the selected frame can display it, and using "..." otherwise. +++ @@ -2046,7 +2046,7 @@ of its file argument. +++ ** New utility function 'directory-empty-p'. -This predicate tests whether a given filename is an accessible +This predicate tests whether a given file name is an accessible directory and whether it contains no other directories or files. +++ @@ -2221,7 +2221,7 @@ Until it is solved you could ignore such errors by performing +++ ** Buffers can now be created with certain hooks disabled. The functions 'get-buffer-create' and 'generate-new-buffer' accept a -new optional argument 'inhibit-buffer-hooks'. If non-nil, the new +new optional argument INHIBIT-BUFFER-HOOKS. If non-nil, the new buffer does not run the hooks 'kill-buffer-hook', 'kill-buffer-query-functions', and 'buffer-list-update-hook'. This avoids slowing down internal or temporary buffers that are never @@ -2231,9 +2231,9 @@ presented to users or passed on to other applications. ** 'start-process-shell-command' and 'start-file-process-shell-command' do not support the old calling conventions any longer. -** Functions operating on local filenames now check that the filenames +** Functions operating on local file names now check that the file names don't contain any NUL bytes. This avoids subtle bugs caused by -silently using only the part of the filename until the first NUL byte. +silently using only the part of the file name until the first NUL byte. ** New coding-systems for EBCDIC variants. New coding-systems 'ibm256', 'ibm273', 'ibm274', 'ibm277', 'ibm278', diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 1722c53be0..fa1a90bc84 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -49,12 +49,12 @@ ;; The user option `tramp-gvfs-methods' contains the list of supported ;; connection methods. Per default, these are "afp", "dav", "davs", -;; "gdrive", "media", "nextcloud" and "sftp". +;; "gdrive", "mtp", "nextcloud" and "sftp". ;; "gdrive" and "nextcloud" connection methods require a respective ;; account in GNOME Online Accounts, with enabled "Files" service. -;; The "media" connection method is responsible for media devices, +;; The "mtp" connection method is responsible for media devices, ;; like cell phones, tablets, cameras etc. The device must already be ;; connected via USB, before accessing it. @@ -131,7 +131,7 @@ ;;;###tramp-autoload (defcustom tramp-gvfs-methods - '("afp" "dav" "davs" "gdrive" "media" "nextcloud" "sftp") + '("afp" "dav" "davs" "gdrive" "mtp" "nextcloud" "sftp") "List of methods for remote files, accessed with GVFS." :group 'tramp :version "28.1" @@ -142,7 +142,7 @@ (const "gdrive") (const "http") (const "https") - (const "media") + (const "mtp") (const "nextcloud") (const "sftp") (const "smb")))) @@ -159,7 +159,7 @@ ;;;###tramp-autoload (defvar tramp-media-methods '("afc" "gphoto2" "mtp") - "List of GVFS methods which are covered by the \"media\" method. + "List of GVFS methods which are covered by the \"mtp\" method. They are checked during start up via `tramp-gvfs-interface-remotevolumemonitor'.") @@ -1639,7 +1639,7 @@ ID-FORMAT valid values are `string' and `integer'." (if (tramp-tramp-file-p filename) (with-parsed-tramp-file-name filename nil ;; Ensure that media devices are cached. - (when (string-equal method "media") + (when (string-equal method "mtp") (tramp-get-media-device v)) (with-tramp-connection-property v "activation-uri" (setq localname "/") @@ -1649,7 +1649,7 @@ ID-FORMAT valid values are `string' and `integer'." (setq method "davs" localname (concat (tramp-gvfs-get-remote-prefix v) localname))) - (when (string-equal "media" method) + (when (string-equal "mtp" method) (when-let ((media (tramp-get-connection-property v "media-device" nil))) (setq method (tramp-media-device-method media) @@ -2058,7 +2058,7 @@ and \"org.gtk.Private.RemoteVolumeMonitor.VolumeRemoved\" signals." (uri (url-generic-parse-url (nth 5 volume))) (method (url-type uri)) (vec (make-tramp-file-name - :method "media" + :method "mtp" ;; A host name cannot contain spaces. :host (tramp-compat-string-replace " " "_" (nth 1 volume)))) (media (make-tramp-media-device @@ -2363,7 +2363,7 @@ VEC is used only for traces." tramp-gvfs-interface-remotevolumemonitor "List"))) (let* ((uri (url-generic-parse-url (nth 5 volume))) (vec (make-tramp-file-name - :method "media" + :method "mtp" ;; A host name cannot contain spaces. :host (tramp-compat-string-replace " " "_" (nth 1 volume)))) (media (make-tramp-media-device @@ -2376,12 +2376,12 @@ VEC is used only for traces." (tramp-set-connection-property vec "media-device" media) (tramp-set-connection-property media "vector" vec)))) - ;; Adapt default host name, supporting /media:: when possible. + ;; Adapt default host name, supporting /mtp:: when possible. (setq tramp-default-host-alist (append - `(("media" nil ,(if (= (length devices) 1) (car devices) ""))) + `(("mtp" nil ,(if (= (length devices) 1) (car devices) ""))) (delete - (assoc "media" tramp-default-host-alist) + (assoc "mtp" tramp-default-host-alist) tramp-default-host-alist))))) (defun tramp-parse-media-names (service) @@ -2498,7 +2498,7 @@ This uses \"avahi-browse\" in case D-Bus is not enabled in Avahi." ;; Add completion functions for media devices. (tramp-get-media-devices nil) (tramp-set-completion-function - "media" + "mtp" (mapcar (lambda (method) `(tramp-parse-media-names ,(format "_%s._tcp" method))) tramp-media-methods)))) commit f9264a3878ba6366aacdf80e3ebba3ba799415a6 Author: emacs-f Date: Tue Dec 8 18:22:30 2020 -0500 Avoid missing email messages due to rmail-spam-filter * lisp/mail/rmail-spam-filter.el (rsf--rmail-last-seen-message): New function. (rmail-spam-filter, rmail-get-new-mail-filter-spam): Call 'rsf--rmail-last-seen-message' instead of 'rmail-first-unseen-message'. (Bug#45128) Copyright-paperwork-exempt: yes diff --git a/lisp/mail/rmail-spam-filter.el b/lisp/mail/rmail-spam-filter.el index db51848259..4d8c9267f3 100644 --- a/lisp/mail/rmail-spam-filter.el +++ b/lisp/mail/rmail-spam-filter.el @@ -214,6 +214,16 @@ the cdr is set to t. Else, the car is set to nil." ;; rule means this cannot be spam. (setcar result nil))))) +;; Don't spuriously advance to the next unseen message while +;; prompting, because that causes it to then be missed while actually +;; reading mail afterwards! Call this instead of +;; rmail-first-unseen-message. +(defun rsf--rmail-last-seen-message () + (max 1 + ;; 'rmail-first-unseen-message' can return nil in a completely + ;; empty buffer. + (1- (or (rmail-first-unseen-message) 1)))) + (defun rmail-spam-filter (msg) "Return nil if message number MSG is spam based on `rsf-definitions-alist'. If spam, optionally output message to a file `rsf-file' and delete @@ -327,8 +337,7 @@ it from rmail file. Called for each new message retrieved by (if (and (car maybe-spam) (cdr maybe-spam)) ;; Temporarily set rmail-current-message in order to output ;; and delete the spam msg if needed: - (let ((rmail-current-message msg) ; FIXME does this do anything? - (action (cdr (assq 'action + (let ((action (cdr (assq 'action (nth num-element rsf-definitions-alist)))) (newfile (not (file-exists-p rsf-file)))) ;; Check action item in rsf-definitions-alist and do it. @@ -337,7 +346,7 @@ it from rmail file. Called for each new message retrieved by ;; Else the prompt to write a new file leaves the raw ;; mbox buffer visible. (and newfile - (rmail-show-message (rmail-first-unseen-message) t)) + (rmail-show-message (rsf--rmail-last-seen-message) t)) (rmail-output rsf-file) ;; Swap back, else rmail-get-new-mail-1 gets confused. (when newfile @@ -377,7 +386,7 @@ This is called at the end of `rmail-get-new-mail-1' if there is new mail." (sleep-for rsf-sleep-after-message)) (when (> nspam 0) ;; Otherwise sleep or expunge prompt leaves raw mbox buffer showing. - (rmail-show-message (or (rmail-first-unseen-message) 1) t) + (rmail-show-message (or (rsf--rmail-last-seen-message) 1) t) (unwind-protect (progn (if rsf-beep (ding t)) commit b3c9af9061e09efd94a1f5bd58aed69800da237d Author: Zajcev Evgeny Date: Thu Dec 17 01:04:09 2020 +0300 Improvements for `:base-uri' svg image property * src/image.c (svg_load): Use ENCODE_FILE for `:base-uri' * doc/lispref/display.texi (SVG Images): Add more documentation for `:base-uri' diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 2b3119ea59..949fd8987c 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5904,7 +5904,13 @@ string containing the image data as raw bytes. @var{image-type} should be a To @var{svg} add an embedded (raster) image placed at @var{relative-filename}. @var{relative-filename} is searched inside @code{file-name-directory} of the @code{:base-uri} svg image property. -This improves the performance of embedding large images. +@code{:base-uri} specifies a (possibly non-existing) file name of the +svg image to be created, thus all the embedded files are searched +relatively to the @code{:base-uri} filename's directory. If +@code{:base-uri} is ommited, then filename from where svg image is +loaded is used. Using @code{:base-uri} improves the performance of +embedding large images, comparing to @code{svg-embed}, because all the +work is done directly by librsvg. @lisp ;; Embeding /tmp/subdir/rms.jpg and /tmp/another/rms.jpg diff --git a/src/image.c b/src/image.c index 29cd189f17..e99ba09f51 100644 --- a/src/image.c +++ b/src/image.c @@ -9803,8 +9803,9 @@ svg_load (struct frame *f, struct image *img) } /* If the file was slurped into memory properly, parse it. */ if (!STRINGP (base_uri)) - base_uri = ENCODE_FILE (file); - success_p = svg_load_image (f, img, contents, size, SSDATA (base_uri)); + base_uri = file; + success_p = svg_load_image (f, img, contents, size, + SSDATA (ENCODE_FILE (base_uri))); xfree (contents); } /* Else it's not a file, it's a Lisp object. Load the image from a @@ -9822,7 +9823,8 @@ svg_load (struct frame *f, struct image *img) if (!STRINGP (base_uri)) base_uri = BVAR (current_buffer, filename); success_p = svg_load_image (f, img, SSDATA (data), SBYTES (data), - (NILP (base_uri) ? NULL : SSDATA (base_uri))); + (STRINGP (base_uri) ? + SSDATA (ENCODE_FILE (base_uri)) : NULL)); } return success_p;