commit 9f30a6b1a417cebe795956a7eef44b8cd9b71557 (HEAD, refs/remotes/origin/master) Author: Stefan Monnier Date: Mon Sep 28 23:14:03 2020 -0400 * src/eval.c (Fapply): Simplify last change diff --git a/src/eval.c b/src/eval.c index c34c11828c..0b23905207 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2383,14 +2383,10 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) Lisp_Object fun = args[0]; USE_SAFE_ALLOCA; - if (nargs == 1) - /* Special case: FUN is really a list of (FUNCTION . ARGS). */ - return CALLN (Fapply, CAR (fun), CDR (fun)); - ptrdiff_t numargs = list_length (spread_arg); if (numargs == 0) - return Ffuncall (nargs - 1, args); + return Ffuncall (max (1, nargs - 1), args); else if (numargs == 1) { args [nargs - 1] = XCAR (spread_arg); commit 9f1ca64ffe2f0c3045acffc41c95d26a84959eca Author: Michael Albinus Date: Mon Sep 28 14:47:46 2020 +0200 Improve D-Bus monitor * lisp/net/dbus.el (dbus-monitor-method-call) (dbus-monitor-method-return, dbus-monitor-error) (dbus-monitor-signal): New defconsts. (dbus-monitor-goto-serial): New defun. (dbus-monitor-handler): Use them. Add timestamp. Make also links between D-Bus messages with the same serial. diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index b1bea55d98..fec9d3c7ab 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -2036,6 +2036,28 @@ either a method name, a signal name, or an error name." ;; Return the object. (list key key1))) +(defconst dbus-monitor-method-call + (propertize "method-call" 'face 'font-lock-function-name-face) + "Text to be inserted for D-Bus method-call in monitor.") + +(defconst dbus-monitor-method-return + (propertize "method-return" 'face 'font-lock-function-name-face) + "Text to be inserted for D-Bus method-return in monitor.") + +(defconst dbus-monitor-error (propertize "error" 'face 'font-lock-warning-face) + "Text to be inserted for D-Bus error in monitor.") + +(defconst dbus-monitor-signal + (propertize "signal" 'face 'font-lock-type-face) + "Text to be inserted for D-Bus signal in monitor.") + +(defun dbus-monitor-goto-serial () + "Goto D-Bus message with the same serial number." + (interactive) + (when (mouse-event-p last-input-event) (mouse-set-point last-input-event)) + (when-let ((point (get-text-property (point) 'dbus-serial))) + (goto-char point))) + (defun dbus-monitor-handler (&rest _args) "Default handler for the \"org.freedesktop.DBus.Monitoring.BecomeMonitor\" interface. It will be applied for all objects created by @@ -2045,6 +2067,9 @@ It will be applied for all objects created by ;; Move forward and backward between messages. (local-set-key [?n] #'forward-paragraph) (local-set-key [?p] #'backward-paragraph) + ;; Follow serial links. + (local-set-key (kbd "RET") #'dbus-monitor-goto-serial) + (local-set-key [mouse-2] #'dbus-monitor-goto-serial) (let* ((inhibit-read-only t) (point (point)) (eobp (eobp)) @@ -2056,20 +2081,47 @@ It will be applied for all objects created by (path (dbus-event-path-name event)) (interface (dbus-event-interface-name event)) (member (dbus-event-member-name event)) - (arguments (dbus-event-arguments event))) + (arguments (dbus-event-arguments event)) + (time (time-to-seconds (current-time)))) (save-excursion + ;; Check for matching method-call. + (goto-char (point-max)) + (when (and (or (= type dbus-message-type-method-return) + (= type dbus-message-type-error)) + (re-search-backward + (format + (concat + "^method-call time=\\(\\S-+\\) " + ".*sender=%s .*serial=\\(%d\\) ") + destination serial) + nil 'noerror)) + (setq serial + (propertize + (match-string 2) 'dbus-serial (match-beginning 0) + 'help-echo "RET, mouse-1, mouse-2: goto method-call" + 'face 'link 'follow-link 'mouse-face 'mouse-face 'highlight) + time (format "%f (%f)" time (- time (read (match-string 1))))) + (set-text-properties + (match-beginning 2) (match-end 2) + `(dbus-serial ,(point-max) + help-echo + ,(format + "RET, mouse-1, mouse-2: goto %s" + (if (= type dbus-message-type-error) "error" "method-return")) + face link follow-link mouse-face mouse-face highlight))) + ;; Insert D-Bus message. (goto-char (point-max)) (insert (format (concat - "%s sender=%s -> destination=%s serial=%s " + "%s time=%s sender=%s -> destination=%s serial=%s " "path=%s interface=%s member=%s\n") (cond - ((= type dbus-message-type-method-call) "method-call") - ((= type dbus-message-type-method-return) "method-return") - ((= type dbus-message-type-error) "error") - ((= type dbus-message-type-signal) "signal")) - sender destination serial path interface member)) + ((= type dbus-message-type-method-call) dbus-monitor-method-call) + ((= type dbus-message-type-method-return) dbus-monitor-method-return) + ((= type dbus-message-type-error) dbus-monitor-error) + ((= type dbus-message-type-signal) dbus-monitor-signal)) + time sender destination serial path interface member)) (dolist (arg arguments) (pp (dbus-flatten-types arg) (current-buffer))) (insert "\n") commit 27e1649977dfc65a7d9987070100f7da3c5c97a6 Author: Earl Date: Mon Sep 28 14:16:22 2020 +0200 Suggest region contents in highlight-regexp when region active * lisp/hi-lock.el (hi-lock-face-buffer): Use the region in the prompt if the region is active in transient-mark-mode (bug#43641). diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index c386b7c801..1c55a23764 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -484,7 +484,13 @@ the major mode specifies support for Font Lock." (interactive (list (hi-lock-regexp-okay - (read-regexp "Regexp to highlight" 'regexp-history-last)) + (read-regexp "Regexp to highlight" + (if (use-region-p) + (prog1 + (buffer-substring (region-beginning) + (region-end)) + (deactivate-mark)) + 'regexp-history-last))) (hi-lock-read-face-name) current-prefix-arg)) (or (facep face) (setq face 'hi-yellow)) commit 3a95f4fc12df0a570ad413e099a22bf901b7346d Author: Harald Jörg Date: Mon Sep 28 14:13:01 2020 +0200 cperl-mode: Add compatibility for Emacs 26.1 * lisp/progmodes/cperl-mode.el (cperl--time-convert): New compatibility helper for time-convert (available in Emacs 27.1) (cperl--format-prompt): New compatibility helper for format-prompt (available in Emacs 28) (cperl-info-on-command): use cperl--format-prompt (cperl-perldoc): use cperl--format-prompt (cperl-time-fontification): use cperl--time-convert (bug#43652) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index 6313d015e9..c62fbab059 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -7,6 +7,7 @@ ;; Jonathan Rockway ;; Maintainer: emacs-devel@gnu.org ;; Keywords: languages, Perl +;; Package-Requires: ((emacs "26.1")) ;; This file is part of GNU Emacs. @@ -75,6 +76,26 @@ ;;; Code: +;;; Compatibility with older versions (for publishing on ELPA) +;; The following helpers allow cperl-mode.el to work with older +;; versions of Emacs. +;; +;; Whenever the minimum version is bumped (see "Package-Requires" +;; above), please eliminate the corresponding compatibility-helpers. +;; Whenever you create a new compatibility-helper, please add it here. + +;; Available in Emacs 27.1: time-convert +(defalias 'cperl--time-convert + (if (fboundp 'time-convert) 'time-convert + 'encode-time)) + +;; Available in Emacs 28: format-prompt +(defalias 'cperl--format-prompt + (if (fboundp 'format-prompt) 'format-prompt + (lambda (msg default) + (if default (format "%s (default %s): " msg default) + (concat msg ": "))))) + (eval-when-compile (require 'cl-lib)) (defvar msb-menu-cond) @@ -6126,7 +6147,7 @@ Customized by setting variables `cperl-shrink-wrap-info-frame', (interactive (let* ((default (cperl-word-at-point)) (read (read-string - (format-prompt "Find doc for Perl function" default)))) + (cperl--format-prompt "Find doc for Perl function" default)))) (list (if (equal read "") default read)))) @@ -8085,7 +8106,7 @@ the appropriate statement modifier." (interactive (list (let* ((default-entry (cperl-word-at-point)) (input (read-string - (format-prompt "perldoc entry" default-entry)))) + (cperl--format-prompt "perldoc entry" default-entry)))) (if (string= input "") (if (string= default-entry "") (error "No perldoc args given") @@ -8312,7 +8333,7 @@ start with default arguments, then refine the slowdown regions." (or l (setq l 1)) (or step (setq step 500)) (or lim (setq lim 40)) - (let* ((timems (function (lambda () (car (time-convert nil 1000))))) + (let* ((timems (function (lambda () (car (cperl--time-convert nil 1000))))) (tt (funcall timems)) (c 0) delta tot) (goto-char (point-min)) (forward-line (1- l)) commit eaf224f88d988d7c8facddf884cc9e2eb192bed8 Author: Alex Bochannek Date: Mon Sep 28 14:09:07 2020 +0200 Repad the Face header in Gnus * lisp/gnus/gnus-fun.el (gnus-convert-face-to-png): Use it. * lisp/gnus/gnus-util.el (gnus-base64-repad): New function (bug#43441). diff --git a/lisp/gnus/gnus-fun.el b/lisp/gnus/gnus-fun.el index c95449762e..2461fd45fd 100644 --- a/lisp/gnus/gnus-fun.el +++ b/lisp/gnus/gnus-fun.el @@ -205,11 +205,12 @@ different input formats." (defun gnus-convert-face-to-png (face) "Convert FACE (which is base64-encoded) to a PNG. The PNG is returned as a string." - (mm-with-unibyte-buffer - (insert face) - (ignore-errors - (base64-decode-region (point-min) (point-max))) - (buffer-string))) + (let ((face (gnus-base64-repad face))) + (mm-with-unibyte-buffer + (insert face) + (ignore-errors + (base64-decode-region (point-min) (point-max))) + (buffer-string)))) ;;;###autoload (defun gnus-convert-png-to-face (file) diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el index aa9f137e20..f8126906b8 100644 --- a/lisp/gnus/gnus-util.el +++ b/lisp/gnus/gnus-util.el @@ -1343,6 +1343,53 @@ forbidden in URL encoding." (setq tmp (concat tmp str)) tmp)) +(defun gnus-base64-repad (str &optional reject-newlines line-length) + "Take a base 64-encoded string and return it padded correctly. +Existing padding is ignored. + +If any combination of CR and LF characters are present and +REJECT-NEWLINES is nil, remove them; otherwise raise an error. +If LINE-LENGTH is set and the string (or any line in the string +if REJECT-NEWLINES is nil) is longer than that number, raise an +error. Common line length for input characters are 76 plus CRLF +(RFC 2045 MIME), 64 plus CRLF (RFC 1421 PEM), and 1000 including +CRLF (RFC 5321 SMTP)." + ;; RFC 4648 specifies that: + ;; - three 8-bit inputs make up a 24-bit group + ;; - the 24-bit group is broken up into four 6-bit values + ;; - each 6-bit value is mapped to one character of the base 64 alphabet + ;; - if the final 24-bit quantum is filled with only 8 bits the output + ;; will be two base 64 characters followed by two "=" padding characters + ;; - if the final 24-bit quantum is filled with only 16 bits the output + ;; will be three base 64 character followed by one "=" padding character + ;; + ;; RFC 4648 section 3 considerations: + ;; - if reject-newlines is nil (default), concatenate multi-line + ;; input (3.1, 3.3) + ;; - if line-length is set, error on input exceeding the limit (3.1) + ;; - reject characters outside base encoding (3.3, also section 12) + (let ((splitstr (split-string str "[\r\n]" t))) + (when (and reject-newlines (> (length splitstr) 1)) + (error "Invalid Base64 string")) + (dolist (substr splitstr) + (when (and line-length (> (length substr) line-length)) + (error "Base64 string exceeds line-length")) + (when (string-match "[^A-Za-z0-9+/=]" substr) + (error "Invalid Base64 string"))) + (let* ((str (string-join splitstr)) + (len (length str))) + (when (string-match "=" str) + (setq len (match-beginning 0))) + (concat + (substring str 0 len) + (make-string (/ + (- 24 + (pcase (mod (* len 6) 24) + (`0 24) + (n n))) + 6) + ?=))))) + (defun gnus-make-predicate (spec) "Transform SPEC into a function that can be called. SPEC is a predicate specifier that contains stuff like `or', `and', diff --git a/test/lisp/gnus/gnus-util-tests.el b/test/lisp/gnus/gnus-util-tests.el index 7eadb0de71..ed33be46a3 100644 --- a/test/lisp/gnus/gnus-util-tests.el +++ b/test/lisp/gnus/gnus-util-tests.el @@ -25,6 +25,65 @@ (require 'ert) (require 'gnus-util) +(ert-deftest gnus-string> () + ;; Failure paths + (should-error (gnus-string> "" 1) + :type 'wrong-type-argument) + (should-error (gnus-string> "") + :type 'wrong-number-of-arguments) + + ;; String tests + (should (gnus-string> "def" "abc")) + (should (gnus-string> 'def 'abc)) + (should (gnus-string> "abc" "DEF")) + (should (gnus-string> "abc" 'DEF)) + (should (gnus-string> "αβγ" "abc")) + (should (gnus-string> "אבג" "αβγ")) + (should (gnus-string> nil "")) + (should (gnus-string> "abc" "")) + (should (gnus-string> "abc" "ab")) + (should-not (gnus-string> "abc" "abc")) + (should-not (gnus-string> "abc" "def")) + (should-not (gnus-string> "DEF" "abc")) + (should-not (gnus-string> 'DEF "abc")) + (should-not (gnus-string> "123" "abc")) + (should-not (gnus-string> "" ""))) + +(ert-deftest gnus-string< () + ;; Failure paths + (should-error (gnus-string< "" 1) + :type 'wrong-type-argument) + (should-error (gnus-string< "") + :type 'wrong-number-of-arguments) + + ;; String tests + (setq case-fold-search nil) + (should (gnus-string< "abc" "def")) + (should (gnus-string< 'abc 'def)) + (should (gnus-string< "DEF" "abc")) + (should (gnus-string< "DEF" 'abc)) + (should (gnus-string< "abc" "αβγ")) + (should (gnus-string< "αβγ" "אבג")) + (should (gnus-string< "" nil)) + (should (gnus-string< "" "abc")) + (should (gnus-string< "ab" "abc")) + (should-not (gnus-string< "abc" "abc")) + (should-not (gnus-string< "def" "abc")) + (should-not (gnus-string< "abc" "DEF")) + (should-not (gnus-string< "abc" 'DEF)) + (should-not (gnus-string< "abc" "123")) + (should-not (gnus-string< "" "")) + + ;; gnus-string< checks case-fold-search + (setq case-fold-search t) + (should (gnus-string< "abc" "DEF")) + (should (gnus-string< "abc" 'GHI)) + (should (gnus-string< 'abc "DEF")) + (should (gnus-string< 'GHI 'JKL)) + (should (gnus-string< "abc" "ΑΒΓ")) + (should-not (gnus-string< "ABC" "abc")) + (should-not (gnus-string< "def" "ABC"))) + (ert-deftest gnus-subsetp () ;; False for non-lists. (should-not (gnus-subsetp "1" "1")) @@ -73,4 +132,43 @@ (should (equal '("1") (gnus-setdiff '(2 "1" 2) '(2)))) (should (equal '("1" "1") (gnus-setdiff '(2 "1" 2 "1") '(2))))) +(ert-deftest gnus-base64-repad () + (should-error (gnus-base64-repad "" nil nil nil) + :type 'wrong-number-of-arguments) + (should-error (gnus-base64-repad 1) + :type 'wrong-type-argument) + + ;; RFC4648 test vectors + (should (equal "" (gnus-base64-repad ""))) + (should (equal "Zg==" (gnus-base64-repad "Zg=="))) + (should (equal "Zm8=" (gnus-base64-repad "Zm8="))) + (should (equal "Zm9v" (gnus-base64-repad "Zm9v"))) + (should (equal "Zm9vYg==" (gnus-base64-repad "Zm9vYg=="))) + (should (equal "Zm9vYmE=" (gnus-base64-repad "Zm9vYmE="))) + (should (equal "Zm9vYmFy" (gnus-base64-repad "Zm9vYmFy"))) + + (should (equal "Zm8=" (gnus-base64-repad "Zm8"))) + (should (equal "Zg==" (gnus-base64-repad "Zg"))) + (should (equal "Zg==" (gnus-base64-repad "Zg===="))) + + (should-error (gnus-base64-repad " ") + :type 'error) + (should-error (gnus-base64-repad "Zg== ") + :type 'error) + (should-error (gnus-base64-repad "Z?\x00g==") + :type 'error) + ;; line-length + (should-error (gnus-base64-repad "Zg====" nil 4) + :type 'error) + ;; reject-newlines + (should-error (gnus-base64-repad "Zm9v\r\nYmFy" t) + :type 'error) + (should (equal "Zm9vYmFy" (gnus-base64-repad "Zm9vYmFy" t))) + (should (equal "Zm9vYmFy" (gnus-base64-repad "Zm9v\r\nYmFy" nil))) + (should (equal "Zm9vYmFy" (gnus-base64-repad "Zm9v\r\nYmFy\n" nil))) + (should-error (gnus-base64-repad "Zm9v\r\n YmFy\r\n" nil) + :type 'error) + (should-error (gnus-base64-repad "Zm9v\r\nYmFy" nil 3) + :type 'error)) + ;;; gnustest-gnus-util.el ends here commit 232382415d1ff8fdbcb7789e5829c297e6525020 Author: Jan Tatarik Date: Mon Sep 28 13:08:32 2020 +0200 Fix Gnus parsing of weekly recurring icalendar events * lisp/gnus/gnus-icalendar.el (gnus-icalendar-event:recurring-interval): Fix parsing of weekly recurring events (bug#43669). Example: in the absence of explicit INTERVAL value in the calendar event, a weekly event with occurrences scheduled for Mondays and Wednesdays should receive the default recurring interval of "1" and the org mode timestamp repeater should be "+1w". Due to a bug in the current code we receive "WEEKLY" and "+WEEKLYw" instead. The patch fixes the issue. diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el index f624b9d032..7d4fa6c35c 100644 --- a/lisp/gnus/gnus-icalendar.el +++ b/lisp/gnus/gnus-icalendar.el @@ -134,11 +134,11 @@ (cl-defmethod gnus-icalendar-event:recurring-interval ((event gnus-icalendar-event)) "Return recurring interval of EVENT." (let ((rrule (gnus-icalendar-event:recur event)) - (default-interval 1)) + (default-interval "1")) - (string-match "INTERVAL=\\([[:digit:]]+\\)" rrule) - (or (match-string 1 rrule) - default-interval))) + (if (string-match "INTERVAL=\\([[:digit:]]+\\)" rrule) + (match-string 1 rrule) + default-interval))) (cl-defmethod gnus-icalendar-event:recurring-days ((event gnus-icalendar-event)) "Return, when available, the week day numbers on which the EVENT recurs." diff --git a/test/lisp/gnus/gnus-icalendar-tests.el b/test/lisp/gnus/gnus-icalendar-tests.el index be23c90af3..dd265b4fa9 100644 --- a/test/lisp/gnus/gnus-icalendar-tests.el +++ b/test/lisp/gnus/gnus-icalendar-tests.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2020 Free Software Foundation, Inc. -;; Author: Jan Tatarik +;; Author: Jan Tatarik ;; Keywords: ;; This file is part of GNU Emacs. @@ -69,7 +69,7 @@ BEGIN:VEVENT DTSTART;TZID=America/New_York:20201208T090000 DTEND;TZID=America/New_York:20201208T100000 DTSTAMP:20200728T182853Z -ORGANIZER;CN=Company Events:mailto:liveintent.com_3bm6fh805bme9uoeliqcle1sa +ORGANIZER;CN=Company Events:mailto:anoncompany.com_3bm6fh805bme9uoeliqcle1sa g@group.calendar.google.com UID:iipdt88slddpeu7hheuu09sfmd@google.com X-MICROSOFT-CDO-OWNERAPPTID:-362490173 @@ -96,7 +96,7 @@ END:VCALENDAR (should (not (gnus-icalendar-event:recurring-p event))) (should (string= (gnus-icalendar-event:start event) "2020-12-08 15:00")) (with-slots (organizer summary description location end-time uid rsvp participation-type) event - (should (string= organizer "liveintent.com_3bm6fh805bme9uoeliqcle1sag@group.calendar.google.com")) + (should (string= organizer "anoncompany.com_3bm6fh805bme9uoeliqcle1sag@group.calendar.google.com")) (should (string= summary "Townhall | All Company Meeting")) (should (string= description "In this meeting, we will cover topics from product and engineering presentations and demos to new hire announcements to watching the late")) (should (string= location "New York-22-Town Hall Space (250) [Chrome Box]")) @@ -182,55 +182,78 @@ END:VCALENDAR" (list "Mark Hershberger")))) <2020-07-30 15:00-15:30 +1w>"))) (setenv "TZ" tz)))) +(ert-deftest gnus-icalendary-weekly-byday () + "" + (let ((tz (getenv "TZ")) + (event (gnus-icalendar-tests--get-ical-event "\ +BEGIN:VCALENDAR +PRODID:-//Google Inc//Google Calendar 70.9054//EN +VERSION:2.0 +CALSCALE:GREGORIAN +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:Europe/Berlin +X-LIC-LOCATION:Europe/Berlin +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=Europe/Berlin:20200915T140000 +DTEND;TZID=Europe/Berlin:20200915T143000 +RRULE:FREQ=WEEKLY;BYDAY=FR,MO,TH,TU,WE +DTSTAMP:20200915T120627Z +ORGANIZER;CN=anon@anoncompany.com:mailto:anon@anoncompany.com +UID:7b6g3m7iftuo90ei4ul00feqn_R20200915T120000@google.com +ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;RSVP=TRUE + ;CN=participant@anoncompany.com;X-NUM-GUESTS=0:mailto:participant@anoncompany.com +CREATED:20200325T095723Z +DESCRIPTION:Coffee talk +LAST-MODIFIED:20200915T120623Z +LOCATION: +SEQUENCE:0 +STATUS:CONFIRMED +SUMMARY:Casual coffee talk +TRANSP:OPAQUE +END:VEVENT +END:VCALENDAR" (list "participant@anoncompany.com")))) -;; (VCALENDAR nil -;; ((PRODID nil "Zimbra-Calendar-Provider") -;; (VERSION nil "2.0") -;; (METHOD nil "REQUEST")) -;; ((VTIMEZONE nil -;; ((TZID nil "America/New_York")) -;; ((STANDARD nil -;; ((DTSTART nil "16010101T020000") -;; (TZOFFSETTO nil "-0500") -;; (TZOFFSETFROM nil "-0400") -;; (RRULE nil "FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=11;BYDAY=1SU") -;; (TZNAME nil "EST")) -;; nil) -;; (DAYLIGHT nil -;; ((DTSTART nil "16010101T020000") -;; (TZOFFSETTO nil "-0400") -;; (TZOFFSETFROM nil "-0500") -;; (RRULE nil "FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=3;BYDAY=2SU") -;; (TZNAME nil "EDT")) -;; nil))) -;; (VEVENT nil -;; ((UID nil "903a5415-9067-4f63-b499-1b6205f49c88") -;; (RRULE nil "FREQ=DAILY;UNTIL=20200825T035959Z;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR") -;; (SUMMARY nil "appointment every weekday, start jul 24, 2020, end aug 24, 2020") -;; (ATTENDEE -;; (CN "Mark Hershberger" ROLE "REQ-PARTICIPANT" PARTSTAT "NEEDS-ACTION" CN "Mark A. Hershberger") -;; "mailto:mah nichework.com") -;; (DTSTART -;; (TZID "America/New_York") -;; "20200724T090000") -;; (DTEND -;; (TZID "America/New_York") -;; "20200724T093000") -;; (STATUS nil "CONFIRMED") -;; (CLASS nil "PUBLIC") -;; (X-MICROSOFT-CDO-INTENDEDSTATUS nil "BUSY") -;; (TRANSP nil "OPAQUE") -;; (LAST-MODIFIED nil "20200719T150815Z") -;; (DTSTAMP nil "20200719T150815Z") -;; (SEQUENCE nil "0") -;; (DESCRIPTION nil "The following is a new meeting request:")) -;; ((VALARM nil -;; ((ACTION nil "DISPLAY") -;; (TRIGGER -;; (RELATED "START") -;; "-PT5M") -;; (DESCRIPTION nil "Reminder")) -;; nil))))) + (unwind-protect + (progn + ;; Use this form so as not to rely on system tz database. + ;; Eg hydra.nixos.org. + (setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3") + (should (eq (eieio-object-class event) 'gnus-icalendar-event-request)) + (should (gnus-icalendar-event:recurring-p event)) + (should (string= (gnus-icalendar-event:recurring-interval event) "1")) + (should (string= (gnus-icalendar-event:start event) "2020-09-15 14:00")) + (with-slots (organizer summary description location end-time uid rsvp participation-type) event + (should (string= organizer "anon@anoncompany.com")) + (should (string= summary "Casual coffee talk")) + (should (string= description "Coffee talk")) + (should (string= location "")) + (should (string= (format-time-string "%Y-%m-%d %H:%M" end-time) "2020-09-15 14:30")) + (should (string= uid "7b6g3m7iftuo90ei4ul00feqn_R20200915T120000@google.com")) + (should rsvp) + (should (eq participation-type 'required))) + (should (equal (sort (gnus-icalendar-event:recurring-days event) #'<) '(1 2 3 4 5))) + (should (string= (gnus-icalendar-event:org-timestamp event) "<2020-09-15 14:00-14:30 +1w> +<2020-09-16 14:00-14:30 +1w> +<2020-09-17 14:00-14:30 +1w> +<2020-09-18 14:00-14:30 +1w> +<2020-09-21 14:00-14:30 +1w>"))) + (setenv "TZ" tz)))) (provide 'gnus-icalendar-tests) ;;; gnus-icalendar-tests.el ends here commit fc1e8b3659c10c6dadb273a73525e19a4edc4bc4 Author: Mattias Engdegård Date: Mon Sep 28 12:04:49 2020 +0200 ; * etc/NEWS: Put related items together and fix grammar diff --git a/etc/NEWS b/etc/NEWS index 61618af780..10b99f413b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1455,13 +1455,7 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el. +++ *** New function 'string-search'. This function takes two string parameters and returns the position of -the first instance of the first string in the latter. - -+++ -*** New function 'process-lines-ignore-status'. -This is like 'process-lines', but does not signal an error if the -return status is non-zero. 'process-lines-handling-status' has also -been added, and takes a callback to handle the return status. +the first instance of the former string in the latter. +++ *** New function 'string-replace'. @@ -1469,6 +1463,12 @@ This function works along the line of 'replace-regexp-in-string', but matching on strings instead of regexps, and does not change the global match state. ++++ +*** New function 'process-lines-ignore-status'. +This is like 'process-lines', but does not signal an error if the +return status is non-zero. 'process-lines-handling-status' has also +been added, and takes a callback to handle the return status. + --- *** 'ascii' is now a coding system alias for 'us-ascii'. commit f679bcbb39ae26adcfb7e62794fcc03595b7436d Author: Mattias Engdegård Date: Mon Sep 28 12:04:10 2020 +0200 ; * doc/lispref/searching.texi (Search and Replace): Rephrase diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi index b4fec6d1fd..592b876644 100644 --- a/doc/lispref/searching.texi +++ b/doc/lispref/searching.texi @@ -2567,10 +2567,10 @@ of matching @var{regexp} against a substring of @var{string}. @end defun @defun string-replace fromstring tostring instring -This function returns a string equal to @var{instring} where any -occurrences of @var{fromstring} have been replaced with -@var{tostring}. It may return one of its arguments. -Case is significant, and text properties are ignored. +This function replaces all occurrences of @var{fromstring} with +@var{tostring} in @var{instring} and returns the result. It may +return one of its arguments unchanged, a constant string or a new +string. Case is significant, and text properties are ignored. @end defun If you want to write a command along the lines of @code{query-replace},