commit dc8bffba5a4c3befcae2659d19ff90d5fd2b129f (HEAD, refs/remotes/origin/master)
Author: Stefan Kangas
Date: Fri Oct 23 05:25:22 2020 +0200
* lisp/emacs-lisp/pcase.el: Add "extensions" to keyword header.
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 09c48d095c..e603900b09 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -3,7 +3,7 @@
;; Copyright (C) 2010-2020 Free Software Foundation, Inc.
;; Author: Stefan Monnier
-;; Keywords:
+;; Keywords: extensions
;; This file is part of GNU Emacs.
commit 558065531beaaae78810508f267415c6953e8e47
Merge: ed502406bf 420023a6f0
Author: Stefan Kangas
Date: Fri Oct 23 00:33:19 2020 +0200
Merge branch 'scratch/substitute-command-keys'
commit ed502406bfeb87b3ee23661cacf04285634d8036
Author: Juri Linkov
Date: Thu Oct 22 23:09:24 2020 +0300
* etc/HELLO: Use JavaScript for Javanese script (bug#43887)
diff --git a/etc/HELLO b/etc/HELLO
index 06c1c433b0..3c1fd63fb7 100644
--- a/etc/HELLO
+++ b/etc/HELLO
@@ -59,7 +59,7 @@ Gujarati (ગુજરાતી) નમસ્તે
unicodeInuktitut (ᐃᓄᒃᑎᑐᑦ) ᐊᐃ
latin-iso8859-1Italian (italiano) Ciao / Buon giorno
-unicodeJavanese (ꦧꦱꦗꦮ) System.out.println("ꦱꦸꦒꦼꦁꦱꦶꦪꦁ");
+unicodeJavanese (ꦧꦱꦗꦮ) console.log("ꦱꦸꦒꦼꦁꦱꦶꦪꦁ");
mule-unicode-0100-24ffKannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ
Khmer (ភាសាខ្មែរ) ជំរាបសួរ
laoLao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ
commit b42481e22eb1c1adfcef419d45bf9733837684cb
Author: Alan Third
Date: Mon Oct 19 21:19:57 2020 +0100
Fix SVG image dimension calculations (bug#44065)
* src/image.c (svg_load_image): Calculate the image size by using the
viewBox size and applying it to the image.
* etc/PROBLEMS: Describe the problem with librsvg 2.45 and below.
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index 41d5ea1bb7..8ed92ab75e 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -181,6 +181,10 @@ Configure checks for the correct version, but this problem could occur
if a binary built against a shared libungif is run on a system with an
older version.
+** SVG images may be cropped incorrectly with librsvg 2.45 and below.
+Librsvg 2.46 and above have improved geometry code which Emacs is able
+to take advantage of.
+
** Emacs aborts inside the function 'tparam1'.
This can happen if Emacs was built without terminfo support, but the
diff --git a/src/image.c b/src/image.c
index 25d5af8a8d..5f6d9f4c44 100644
--- a/src/image.c
+++ b/src/image.c
@@ -9736,7 +9736,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
ptrdiff_t size, char *filename)
{
RsvgHandle *rsvg_handle;
- RsvgDimensionData dimension_data;
+ double viewbox_width, viewbox_height;
GError *err = NULL;
GdkPixbuf *pixbuf;
int width;
@@ -9789,15 +9789,38 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
#endif
/* Get the image dimensions. */
+#if LIBRSVG_CHECK_VERSION (2, 46, 0)
+ RsvgRectangle zero_rect, viewbox;
+
+ rsvg_handle_get_geometry_for_layer (rsvg_handle, NULL,
+ &zero_rect, &viewbox,
+ NULL, NULL);
+ viewbox_width = viewbox.x + viewbox.width;
+ viewbox_height = viewbox.y + viewbox.height;
+#else
+ /* The function used above to get the geometry of the visible area
+ of the SVG are only available in librsvg 2.46 and above, so in
+ certain circumstances this code path can result in some parts of
+ the SVG being cropped. */
+ RsvgDimensionData dimension_data;
+
rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
+ viewbox_width = dimension_data.width;
+ viewbox_height = dimension_data.height;
+#endif
+ compute_image_size (viewbox_width, viewbox_height, img->spec,
+ &width, &height);
+
+ if (! check_image_size (f, width, height))
+ {
+ image_size_error ();
+ goto rsvg_error;
+ }
+
/* We are now done with the unmodified data. */
g_object_unref (rsvg_handle);
- /* Calculate the final image size. */
- compute_image_size (dimension_data.width, dimension_data.height,
- img->spec, &width, &height);
-
/* Wrap the SVG data in another SVG. This allows us to set the
width and height, as well as modify the foreground and background
colors. */
@@ -9820,7 +9843,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
"xmlns:xi=\"http://www.w3.org/2001/XInclude\" "
"style=\"color: #%06X; fill: currentColor;\" "
"width=\"%d\" height=\"%d\" preserveAspectRatio=\"none\" "
- "viewBox=\"0 0 %d %d\">"
+ "viewBox=\"0 0 %f %f\">"
""
""
"";
@@ -9845,8 +9868,9 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
if (!wrapped_contents
|| buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
foreground & 0xFFFFFF, width, height,
- dimension_data.width, dimension_data.height,
- background & 0xFFFFFF, SSDATA (encoded_contents)))
+ viewbox_width, viewbox_height,
+ background & 0xFFFFFF,
+ SSDATA (encoded_contents)))
goto rsvg_error;
wrapped_size = strlen (wrapped_contents);
@@ -9887,12 +9911,6 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
if (err) goto rsvg_error;
#endif
- rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
- if (! check_image_size (f, dimension_data.width, dimension_data.height))
- {
- image_size_error ();
- goto rsvg_error;
- }
/* We can now get a valid pixel buffer from the svg file, if all
went ok. */
commit 87239f0a5c613dc716328e129bf79b69979b8a12
Author: Alan Third
Date: Thu Oct 22 19:47:17 2020 +0100
Fix crash when no face is defined (bug#44058, bug#43973)
* src/nsterm.m (ns_clear_under_internal_border): If face is null,
don't try drawing anything.
diff --git a/src/nsterm.m b/src/nsterm.m
index a702a051d0..fa38350a2f 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3048,6 +3048,12 @@ so some key presses (TAB) are swallowed by the system. */
if (!face)
face = FRAME_DEFAULT_FACE (f);
+ /* Sometimes with new frames we reach this point and have no
+ face. I'm not sure why we have a live frame but no face, so
+ just give up. */
+ if (!face)
+ return;
+
ns_focus (f, &frame_rect, 1);
[ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
for (int i = 0; i < 4 ; i++)
commit 8c7a55531b400dd3d9aa1dacd2bac3ee06b56ff1
Author: Stefan Kangas
Date: Thu Oct 22 20:32:32 2020 +0200
Remove incorrect use of decode-coding-string
* test/lisp/emacs-lisp/bindat-tests.el
(bindat-test-pack/multibyte-string-fails)
(bindat-test-unpack/multibyte-string-fails): Don't use
decode-coding-string.
Problem pointed out by Stefan Monnier .
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
index 0fb1955695..842ef10bc5 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -97,10 +97,10 @@
[192 168 1 100]))))))
(ert-deftest bindat-test-pack/multibyte-string-fails ()
- (should-error (bindat-pack nil nil (decode-coding-string "ö" 'utf-8))))
+ (should-error (bindat-pack nil nil "ö")))
(ert-deftest bindat-test-unpack/multibyte-string-fails ()
- (should-error (bindat-unpack nil (decode-coding-string "ö" 'utf-8))))
+ (should-error (bindat-unpack nil "ö")))
(ert-deftest bindat-test-format-vector ()
(should (equal (bindat-format-vector [1 2 3] "%d" "x" 2) "1x2"))
commit b572308fbf095da3bd7382d3b1c8f952a51ce3ac
Author: Andreas Schwab
Date: Thu Oct 22 20:07:24 2020 +0200
eww: don't add keymap to without href
* lisp/net/eww.el (eww-tag-a): Only add keymap if the href
attribute is present. (Bug#44147)
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index fd9fe98439..53835bb544 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -695,11 +695,12 @@ Currently this means either text/html or application/xhtml+xml."
(eww-handle-link dom)
(let ((start (point)))
(shr-tag-a dom)
- (put-text-property start (point)
- 'keymap
- (if (mm-images-in-region-p start (point))
- eww-image-link-keymap
- eww-link-keymap))))
+ (if (dom-attr dom 'href)
+ (put-text-property start (point)
+ 'keymap
+ (if (mm-images-in-region-p start (point))
+ eww-image-link-keymap
+ eww-link-keymap)))))
(defun eww--limit-string-pixelwise (string pixels)
(if (not pixels)
commit f6d138979626951a035a6ecf90b77637b06ad6fc
Author: Stefan Kangas
Date: Thu Oct 22 18:28:21 2020 +0200
Add missed file needed by time-tests.el
* test/lisp/time-resources/non-empty: New file. This file is needed
by time-tests.el but was missed when it was committed.
diff --git a/test/lisp/time-resources/non-empty b/test/lisp/time-resources/non-empty
new file mode 100644
index 0000000000..86f5704d8e
--- /dev/null
+++ b/test/lisp/time-resources/non-empty
@@ -0,0 +1 @@
+This file should be non-empty.
commit 30dba74e77baa31af32bc7044146d69965220ad7
Author: Mattias Engdegård
Date: Thu Oct 22 18:31:31 2020 +0200
; * lisp/progmodes/fortran.el: Call 'eval' with lexical binding.
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index 206d1f2a05..d84c379565 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -502,7 +502,8 @@ This is used to fontify fixed-format Fortran comments."
;; line-length will indeed be ignored (and will result in a string that
;; leaks into subsequent lines).
(,(format "^[^CcDd\\*\t\n].\\{%d\\}\\(.+\\)" (1- line-length))
- (1 "<")))))
+ (1 "<")))
+ t))
(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
"Default expressions to highlight in Fortran mode.")
commit a090e5fe0855587fd122151794757dbf04dc7c73
Author: Mattias Engdegård
Date: Thu Oct 22 18:26:24 2020 +0200
Remove useless uses of bindat-get-field
* lisp/progmodes/gdb-mi.el (gdb-var-list-children-handler)
(gdb-edit-register-value): bindat-get-field with a single argument is
identity; remove.
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 79df97080d..9e8af84a60 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1317,7 +1317,7 @@ With arg, enter name of variable to be watched in the minibuffer."
(defun gdb-var-list-children-handler (varnum)
(let* ((var-list nil)
- (output (bindat-get-field (gdb-json-partial-output "child")))
+ (output (gdb-json-partial-output "child"))
(children (bindat-get-field output 'children)))
(catch 'child-already-watched
(dolist (var gdb-var-list)
@@ -4395,8 +4395,7 @@ member."
(save-excursion
(if event (posn-set-point (event-end event)))
(beginning-of-line)
- (let* ((var (bindat-get-field
- (get-text-property (point) 'gdb-register-name)))
+ (let* ((var (get-text-property (point) 'gdb-register-name))
(value (read-string (format "New value (%s): " var))))
(gud-basic-call
(concat "-gdb-set variable $" var " = " value)))))
commit 754a2f11b8a80e2d01693cf3df42d8d0a871dbea
Author: Stefan Kangas
Date: Thu Oct 22 18:23:40 2020 +0200
Add tests for perl-mode.el
* test/lisp/progmodes/perl-mode-tests.el: New file.
diff --git a/test/lisp/progmodes/perl-mode-tests.el b/test/lisp/progmodes/perl-mode-tests.el
new file mode 100644
index 0000000000..a2ea972c10
--- /dev/null
+++ b/test/lisp/progmodes/perl-mode-tests.el
@@ -0,0 +1,33 @@
+;;; perl-mode-tests --- Test for perl-mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see .
+
+;;; Code:
+
+(require 'perl-mode)
+
+;;;; Re-use cperl-mode tests
+
+(defvar cperl-test-mode)
+(setq cperl-test-mode #'perl-mode)
+(load-file (expand-file-name "cperl-mode-tests.el"
+ (file-truename
+ (file-name-directory (or load-file-name
+ buffer-file-name)))))
+
+;;; perl-mode-tests.el ends here
commit e9d0f36248bf75d2fd8433db45b189483e1ddcba
Merge: 6342264ef7 997ebf91dd
Author: Ulf Jasper
Date: Thu Oct 22 17:47:29 2020 +0200
Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs into master
commit 6342264ef74bdc5d649d6baaaa986d54d3aa11fe
Author: Ulf Jasper
Date: Thu Oct 22 17:45:59 2020 +0200
Move test data for icalendar tests to separate files.
* test/lisp/calendar/icalendar-tests.el
(icalendar-tests--data-dir, icalendar-tests--get-file-contents):
New.
(icalendar-tests--test-import, icalendar-tests--do-test-import):
Read input and expected results from files.
(icalendar-import-non-recurring, icalendar-import-rrule)
(icalendar-import-duration, icalendar-import-bug-6766)
(icalendar-import-bug-24199, icalendar-import-bug-33277)
(icalendar-import-multiple-vcalendars, icalendar-import-with-uid)
(icalendar-import-with-timezone, icalendar-real-world): Move test
data (input and expected result) to separate files.
* test/calendar/icalendar/*
New files containing test data for icalendar tests.
diff --git a/test/data/icalendar/import-bug-11473.diary-european b/test/data/icalendar/import-bug-11473.diary-european
new file mode 100644
index 0000000000..97348ae049
--- /dev/null
+++ b/test/data/icalendar/import-bug-11473.diary-european
@@ -0,0 +1,10 @@
+&15/5/2012 15:00-15:30 Query
+ Desc:
+ Whassup?
+
+
+ Location: phone
+ Organizer: MAILTO:a.luser@foo.com
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
diff --git a/test/data/icalendar/import-bug-11473.ics b/test/data/icalendar/import-bug-11473.ics
new file mode 100644
index 0000000000..bc3a6c69fb
--- /dev/null
+++ b/test/data/icalendar/import-bug-11473.ics
@@ -0,0 +1,54 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft Exchange Server 2007
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
+BEGIN:STANDARD
+DTSTART:16010101T030000
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+ORGANIZER;CN="A. Luser":MAILTO:a.luser@foo.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Luser, Oth
+ er":MAILTO:other.luser@foo.com
+DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
+SUMMARY;LANGUAGE=en-US:Query
+DTSTART;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"
+ :20120515T150000
+DTEND;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna":2
+ 0120515T153000
+UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
+ 010000000575268034ECDB649A15349B1BF240F15
+RECURRENCE-ID;TZID="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
+ ienna":20120515T170000
+CLASS:PUBLIC
+PRIORITY:5
+DTSTAMP:20120514T153645Z
+TRANSP:OPAQUE
+STATUS:CONFIRMED
+SEQUENCE:15
+LOCATION;LANGUAGE=en-US:phone
+X-MICROSOFT-CDO-APPT-SEQUENCE:15
+X-MICROSOFT-CDO-OWNERAPPTID:1907632092
+X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-INSTTYPE:3
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT15M
+END:VALARM
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git a/test/data/icalendar/import-bug-22092.diary-american b/test/data/icalendar/import-bug-22092.diary-american
new file mode 100644
index 0000000000..392345fe0a
--- /dev/null
+++ b/test/data/icalendar/import-bug-22092.diary-american
@@ -0,0 +1,6 @@
+&12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/data/icalendar/import-bug-22092.diary-european b/test/data/icalendar/import-bug-22092.diary-european
new file mode 100644
index 0000000000..6a64cf6a8e
--- /dev/null
+++ b/test/data/icalendar/import-bug-22092.diary-european
@@ -0,0 +1,6 @@
+&8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/data/icalendar/import-bug-22092.diary-iso b/test/data/icalendar/import-bug-22092.diary-iso
new file mode 100644
index 0000000000..e0fadbf94d
--- /dev/null
+++ b/test/data/icalendar/import-bug-22092.diary-iso
@@ -0,0 +1,6 @@
+&2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes -
+ Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
+ Location: Stavanger-Sola
+ Organizer: noreply@norwegian.no
+ Class: PUBLIC
+ UID: RFCALITEM1
diff --git a/test/data/icalendar/import-bug-22092.ics b/test/data/icalendar/import-bug-22092.ics
new file mode 100644
index 0000000000..4a4c679da9
--- /dev/null
+++ b/test/data/icalendar/import-bug-22092.ics
@@ -0,0 +1,30 @@
+BEGIN:VCALENDAR
+PRODID:-//www.norwegian.no//iCalendar MIMEDIR//EN
+VERSION:2.0
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:RFCALITEM1
+SEQUENCE:1512040950
+DTSTAMP:20141204T095043Z
+ORGANIZER:noreply@norwegian.no
+DTSTART:20141208T173000Z
+
+DTEND:20141208T215500Z
+
+LOCATION:Stavanger-Sola
+
+DESCRIPTION:Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
+
+X-ALT-DESC;FMTTYPE=text/html:Reisereferanse
+SUMMARY:Norwegian til Tromsoe-Langnes -
+
+CATEGORIES:Appointment
+
+
+PRIORITY:5
+
+CLASS:PUBLIC
+
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-bug-24199.diary-american b/test/data/icalendar/import-bug-24199.diary-american
new file mode 100644
index 0000000000..b3308f1fcf
--- /dev/null
+++ b/test/data/icalendar/import-bug-24199.diary-american
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 1 6 2016)) (not (diary-date 2 3 2016)) (not (diary-date 3 2 2016)) (not (diary-date 5 4 2016)) (not (diary-date 6 1 2016)) (diary-float t 3 1) (diary-block 12 2 2015 1 1 9999)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/data/icalendar/import-bug-24199.diary-european b/test/data/icalendar/import-bug-24199.diary-european
new file mode 100644
index 0000000000..acba714b52
--- /dev/null
+++ b/test/data/icalendar/import-bug-24199.diary-european
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 6 1 2016)) (not (diary-date 3 2 2016)) (not (diary-date 2 3 2016)) (not (diary-date 4 5 2016)) (not (diary-date 1 6 2016)) (diary-float t 3 1) (diary-block 2 12 2015 1 1 9999)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/data/icalendar/import-bug-24199.diary-iso b/test/data/icalendar/import-bug-24199.diary-iso
new file mode 100644
index 0000000000..2c18395dea
--- /dev/null
+++ b/test/data/icalendar/import-bug-24199.diary-iso
@@ -0,0 +1,5 @@
+&%%(and (not (diary-date 2016 1 6)) (not (diary-date 2016 2 3)) (not (diary-date 2016 3 2)) (not (diary-date 2016 5 4)) (not (diary-date 2016 6 1)) (diary-float t 3 1) (diary-block 2015 12 2 9999 1 1)) 12:46-16:00 Summary
+ Desc: Desc
+ Location: Loc
+ Class: DEFAULT
+ UID: 9188710a-08a7-4061-bae3-d4cf4972599a
diff --git a/test/data/icalendar/import-bug-24199.ics b/test/data/icalendar/import-bug-24199.ics
new file mode 100644
index 0000000000..a307c2da3c
--- /dev/null
+++ b/test/data/icalendar/import-bug-24199.ics
@@ -0,0 +1,25 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:Summary
+DESCRIPTION:Desc
+LOCATION:Loc
+DTSTART:20151202T124600
+DTEND:20151202T160000
+RRULE:FREQ=MONTHLY;BYDAY=1WE;INTERVAL=1
+EXDATE:20160106T114600Z
+EXDATE:20160203T114600Z
+EXDATE:20160302T114600Z
+EXDATE:20160504T104600Z
+EXDATE:20160601T104600Z
+CLASS:DEFAULT
+TRANSP:OPAQUE
+BEGIN:VALARM
+ACTION:DISPLAY
+TRIGGER;VALUE=DURATION:-PT3H
+END:VALARM
+LAST-MODIFIED:20160805T191040Z
+UID:9188710a-08a7-4061-bae3-d4cf4972599a
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-bug-33277.diary-american b/test/data/icalendar/import-bug-33277.diary-american
new file mode 100644
index 0000000000..c546fa9a97
--- /dev/null
+++ b/test/data/icalendar/import-bug-33277.diary-american
@@ -0,0 +1 @@
+&11/5/2018 21:00 event with same start/end time
diff --git a/test/data/icalendar/import-bug-33277.diary-european b/test/data/icalendar/import-bug-33277.diary-european
new file mode 100644
index 0000000000..28e5396053
--- /dev/null
+++ b/test/data/icalendar/import-bug-33277.diary-european
@@ -0,0 +1 @@
+&5/11/2018 21:00 event with same start/end time
diff --git a/test/data/icalendar/import-bug-33277.diary-iso b/test/data/icalendar/import-bug-33277.diary-iso
new file mode 100644
index 0000000000..faa7aeafeb
--- /dev/null
+++ b/test/data/icalendar/import-bug-33277.diary-iso
@@ -0,0 +1 @@
+&2018/11/5 21:00 event with same start/end time
diff --git a/test/data/icalendar/import-bug-33277.ics b/test/data/icalendar/import-bug-33277.ics
new file mode 100644
index 0000000000..a4122a2800
--- /dev/null
+++ b/test/data/icalendar/import-bug-33277.ics
@@ -0,0 +1,15 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART:20181105T200000Z
+DTSTAMP:20181105T181652Z
+DESCRIPTION:
+LAST-MODIFIED:20181105T181646Z
+LOCATION:
+SEQUENCE:0
+SUMMARY:event with same start/end time
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-bug-6766.diary-american b/test/data/icalendar/import-bug-6766.diary-american
new file mode 100644
index 0000000000..30deea9911
--- /dev/null
+++ b/test/data/icalendar/import-bug-6766.diary-american
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 2010)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/data/icalendar/import-bug-6766.diary-european b/test/data/icalendar/import-bug-6766.diary-european
new file mode 100644
index 0000000000..ba16c02305
--- /dev/null
+++ b/test/data/icalendar/import-bug-6766.diary-european
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 2010)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/data/icalendar/import-bug-6766.diary-iso b/test/data/icalendar/import-bug-6766.diary-iso
new file mode 100644
index 0000000000..7794e586f3
--- /dev/null
+++ b/test/data/icalendar/import-bug-6766.diary-iso
@@ -0,0 +1,7 @@
+&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 21)) 11:30-12:00 Scrum
+ Status: CONFIRMED
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1262
+&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) Tues + Thurs thinking
+ Class: PUBLIC
+ UID: 8814e3f9-7482-408f-996c-3bfe486a1263
diff --git a/test/data/icalendar/import-bug-6766.ics b/test/data/icalendar/import-bug-6766.ics
new file mode 100644
index 0000000000..451391be02
--- /dev/null
+++ b/test/data/icalendar/import-bug-6766.ics
@@ -0,0 +1,28 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+CLASS:PUBLIC
+DTEND;TZID=America/New_York:20100421T120000
+DTSTAMP:20100525T141214Z
+DTSTART;TZID=America/New_York:20100421T113000
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,TH,FR
+SEQUENCE:1
+STATUS:CONFIRMED
+SUMMARY:Scrum
+TRANSP:OPAQUE
+UID:8814e3f9-7482-408f-996c-3bfe486a1262
+END:VEVENT
+BEGIN:VEVENT
+CLASS:PUBLIC
+DTSTAMP:20100525T141214Z
+DTSTART;VALUE=DATE:20100422
+DTEND;VALUE=DATE:20100423
+RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH
+SEQUENCE:1
+SUMMARY:Tues + Thurs thinking
+TRANSP:OPAQUE
+UID:8814e3f9-7482-408f-996c-3bfe486a1263
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-duration-2.diary-american b/test/data/icalendar/import-duration-2.diary-american
new file mode 100644
index 0000000000..56f41d6ad9
--- /dev/null
+++ b/test/data/icalendar/import-duration-2.diary-american
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001)) Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/data/icalendar/import-duration-2.diary-european b/test/data/icalendar/import-duration-2.diary-european
new file mode 100644
index 0000000000..999102ab6b
--- /dev/null
+++ b/test/data/icalendar/import-duration-2.diary-european
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001)) Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/data/icalendar/import-duration-2.diary-iso b/test/data/icalendar/import-duration-2.diary-iso
new file mode 100644
index 0000000000..393937e6cd
--- /dev/null
+++ b/test/data/icalendar/import-duration-2.diary-iso
@@ -0,0 +1,3 @@
+&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29)) Urlaub
+ Class: PUBLIC
+ UID: 20041127T183329Z-18215-1001-4536-49109@andromeda
diff --git a/test/data/icalendar/import-duration-2.ics b/test/data/icalendar/import-duration-2.ics
new file mode 100644
index 0000000000..eb8a03ba36
--- /dev/null
+++ b/test/data/icalendar/import-duration-2.ics
@@ -0,0 +1,17 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:20041127T183329Z-18215-1001-4536-49109@andromeda
+DTSTAMP:20041127T183315Z
+LAST-MODIFIED:20041127T183329
+SUMMARY:Urlaub
+DTSTART;VALUE=DATE:20011221
+DTEND;VALUE=DATE:20011221
+RRULE:FREQ=DAILY;UNTIL=20011229;INTERVAL=1;WKST=SU
+CLASS:PUBLIC
+SEQUENCE:1
+CREATED:20041127T183329
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-duration.diary-american b/test/data/icalendar/import-duration.diary-american
new file mode 100644
index 0000000000..268736a8cd
--- /dev/null
+++ b/test/data/icalendar/import-duration.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-block 2 17 2005 2 23 2005)) duration
diff --git a/test/data/icalendar/import-duration.diary-european b/test/data/icalendar/import-duration.diary-european
new file mode 100644
index 0000000000..7d852ddcd3
--- /dev/null
+++ b/test/data/icalendar/import-duration.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-block 17 2 2005 23 2 2005)) duration
diff --git a/test/data/icalendar/import-duration.diary-iso b/test/data/icalendar/import-duration.diary-iso
new file mode 100644
index 0000000000..5d3a714284
--- /dev/null
+++ b/test/data/icalendar/import-duration.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-block 2005 2 17 2005 2 23)) duration
diff --git a/test/data/icalendar/import-duration.ics b/test/data/icalendar/import-duration.ics
new file mode 100644
index 0000000000..67f5c73571
--- /dev/null
+++ b/test/data/icalendar/import-duration.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20050217
+SUMMARY:duration
+DURATION:P7D
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-multiple-vcalendars.diary-american b/test/data/icalendar/import-multiple-vcalendars.diary-american
new file mode 100644
index 0000000000..d1b1992a02
--- /dev/null
+++ b/test/data/icalendar/import-multiple-vcalendars.diary-american
@@ -0,0 +1,4 @@
+&7/23/2011 event-1
+&7/24/2011 event-2
+&7/25/2011 event-3a
+&7/25/2011 event-3b
diff --git a/test/data/icalendar/import-multiple-vcalendars.diary-european b/test/data/icalendar/import-multiple-vcalendars.diary-european
new file mode 100644
index 0000000000..f068354220
--- /dev/null
+++ b/test/data/icalendar/import-multiple-vcalendars.diary-european
@@ -0,0 +1,4 @@
+&23/7/2011 event-1
+&24/7/2011 event-2
+&25/7/2011 event-3a
+&25/7/2011 event-3b
diff --git a/test/data/icalendar/import-multiple-vcalendars.diary-iso b/test/data/icalendar/import-multiple-vcalendars.diary-iso
new file mode 100644
index 0000000000..5685e4708a
--- /dev/null
+++ b/test/data/icalendar/import-multiple-vcalendars.diary-iso
@@ -0,0 +1,4 @@
+&2011/7/23 event-1
+&2011/7/24 event-2
+&2011/7/25 event-3a
+&2011/7/25 event-3b
diff --git a/test/data/icalendar/import-multiple-vcalendars.ics b/test/data/icalendar/import-multiple-vcalendars.ics
new file mode 100644
index 0000000000..69a02c09b1
--- /dev/null
+++ b/test/data/icalendar/import-multiple-vcalendars.ics
@@ -0,0 +1,21 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110723
+SUMMARY:event-1
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110724
+SUMMARY:event-2
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110725
+SUMMARY:event-3a
+END:VEVENT
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20110725
+SUMMARY:event-3b
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-non-recurring-1.diary-american b/test/data/icalendar/import-non-recurring-1.diary-american
new file mode 100644
index 0000000000..780e3a8ce6
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-1.diary-american
@@ -0,0 +1 @@
+&9/19/2003 09:00-11:30 non-recurring
diff --git a/test/data/icalendar/import-non-recurring-1.diary-european b/test/data/icalendar/import-non-recurring-1.diary-european
new file mode 100644
index 0000000000..7e0cd21b78
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-1.diary-european
@@ -0,0 +1 @@
+&19/9/2003 09:00-11:30 non-recurring
diff --git a/test/data/icalendar/import-non-recurring-1.diary-iso b/test/data/icalendar/import-non-recurring-1.diary-iso
new file mode 100644
index 0000000000..c731128661
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-1.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 09:00-11:30 non-recurring
diff --git a/test/data/icalendar/import-non-recurring-1.ics b/test/data/icalendar/import-non-recurring-1.ics
new file mode 100644
index 0000000000..cd471efc86
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-1.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-non-recurring-all-day.diary-american b/test/data/icalendar/import-non-recurring-all-day.diary-american
new file mode 100644
index 0000000000..1d4bb6a337
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-all-day.diary-american
@@ -0,0 +1 @@
+&9/19/2003 non-recurring allday
diff --git a/test/data/icalendar/import-non-recurring-all-day.diary-european b/test/data/icalendar/import-non-recurring-all-day.diary-european
new file mode 100644
index 0000000000..b56c7f4e17
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-all-day.diary-european
@@ -0,0 +1 @@
+&19/9/2003 non-recurring allday
diff --git a/test/data/icalendar/import-non-recurring-all-day.diary-iso b/test/data/icalendar/import-non-recurring-all-day.diary-iso
new file mode 100644
index 0000000000..f1c70ab34c
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-all-day.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 non-recurring allday
diff --git a/test/data/icalendar/import-non-recurring-all-day.ics b/test/data/icalendar/import-non-recurring-all-day.ics
new file mode 100644
index 0000000000..4efa8ffa13
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-all-day.ics
@@ -0,0 +1,9 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:non-recurring allday
+DTSTART;VALUE=DATE-TIME:20030919
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-non-recurring-another-example.diary-american b/test/data/icalendar/import-non-recurring-another-example.diary-american
new file mode 100644
index 0000000000..2eb8c0ab68
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-another-example.diary-american
@@ -0,0 +1,4 @@
+&11/23/2004 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git a/test/data/icalendar/import-non-recurring-another-example.diary-european b/test/data/icalendar/import-non-recurring-another-example.diary-european
new file mode 100644
index 0000000000..394eae8bb7
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-another-example.diary-european
@@ -0,0 +1,4 @@
+&23/11/2004 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git a/test/data/icalendar/import-non-recurring-another-example.diary-iso b/test/data/icalendar/import-non-recurring-another-example.diary-iso
new file mode 100644
index 0000000000..5e8bdf417d
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-another-example.diary-iso
@@ -0,0 +1,4 @@
+&2004/11/23 14:45-15:45 another example
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 6161a312-3902-11d9-b512-f764153bb28b
diff --git a/test/data/icalendar/import-non-recurring-another-example.ics b/test/data/icalendar/import-non-recurring-another-example.ics
new file mode 100644
index 0000000000..b145e41879
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-another-example.ics
@@ -0,0 +1,23 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :6161a312-3902-11d9-b512-f764153bb28b
+SUMMARY
+ :another example
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T144500
+DTEND
+ :20041123T154500
+DTSTAMP
+ :20041118T013641Z
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-non-recurring-block.diary-american b/test/data/icalendar/import-non-recurring-block.diary-american
new file mode 100644
index 0000000000..b22234229c
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-block.diary-american
@@ -0,0 +1,4 @@
+&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git a/test/data/icalendar/import-non-recurring-block.diary-european b/test/data/icalendar/import-non-recurring-block.diary-european
new file mode 100644
index 0000000000..8043482442
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-block.diary-european
@@ -0,0 +1,4 @@
+&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git a/test/data/icalendar/import-non-recurring-block.diary-iso b/test/data/icalendar/import-non-recurring-block.diary-iso
new file mode 100644
index 0000000000..e0f1896114
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-block.diary-iso
@@ -0,0 +1,4 @@
+&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
diff --git a/test/data/icalendar/import-non-recurring-block.ics b/test/data/icalendar/import-non-recurring-block.ics
new file mode 100644
index 0000000000..0c52ba3d66
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-block.ics
@@ -0,0 +1,16 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:748f2da0-0d9b-11d8-97af-b4ec8686ea61
+SUMMARY:Sommerferien
+STATUS:TENTATIVE
+CLASS:PRIVATE
+X-MOZILLA-ALARM-DEFAULT-UNITS:Minuten
+X-MOZILLA-RECUR-DEFAULT-INTERVAL:0
+DTSTART;VALUE=DATE:20040719
+DTEND;VALUE=DATE:20040828
+DTSTAMP:20031103T011641Z
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-non-recurring-folded-summary.diary-american b/test/data/icalendar/import-non-recurring-folded-summary.diary-american
new file mode 100644
index 0000000000..2954d0c4fd
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-folded-summary.diary-american
@@ -0,0 +1,4 @@
+&11/23/2004 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git a/test/data/icalendar/import-non-recurring-folded-summary.diary-european b/test/data/icalendar/import-non-recurring-folded-summary.diary-european
new file mode 100644
index 0000000000..7745fc811b
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-folded-summary.diary-european
@@ -0,0 +1,4 @@
+&23/11/2004 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git a/test/data/icalendar/import-non-recurring-folded-summary.diary-iso b/test/data/icalendar/import-non-recurring-folded-summary.diary-iso
new file mode 100644
index 0000000000..8c19a95ed2
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-folded-summary.diary-iso
@@ -0,0 +1,4 @@
+&2004/11/23 14:00-14:30 folded summary
+ Status: TENTATIVE
+ Class: PRIVATE
+ UID: 04979712-3902-11d9-93dd-8f9f4afe08da
diff --git a/test/data/icalendar/import-non-recurring-folded-summary.ics b/test/data/icalendar/import-non-recurring-folded-summary.ics
new file mode 100644
index 0000000000..e3ecee9dae
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-folded-summary.ics
@@ -0,0 +1,25 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :04979712-3902-11d9-93dd-8f9f4afe08da
+SUMMARY
+ :folded summary
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T140000
+DTEND
+ :20041123T143000
+DTSTAMP
+ :20041118T013430Z
+LAST-MODIFIED
+ :20041118T013640Z
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-non-recurring-long-summary.diary-american b/test/data/icalendar/import-non-recurring-long-summary.diary-american
new file mode 100644
index 0000000000..84cd464c56
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-long-summary.diary-american
@@ -0,0 +1 @@
+&9/19/2003 long summary
diff --git a/test/data/icalendar/import-non-recurring-long-summary.diary-european b/test/data/icalendar/import-non-recurring-long-summary.diary-european
new file mode 100644
index 0000000000..5d6524202c
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-long-summary.diary-european
@@ -0,0 +1 @@
+&19/9/2003 long summary
diff --git a/test/data/icalendar/import-non-recurring-long-summary.diary-iso b/test/data/icalendar/import-non-recurring-long-summary.diary-iso
new file mode 100644
index 0000000000..d2300522d9
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-long-summary.diary-iso
@@ -0,0 +1 @@
+&2003/9/19 long summary
diff --git a/test/data/icalendar/import-non-recurring-long-summary.ics b/test/data/icalendar/import-non-recurring-long-summary.ics
new file mode 100644
index 0000000000..39ae02f10c
--- /dev/null
+++ b/test/data/icalendar/import-non-recurring-long-summary.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:long
+ summary
+DTSTART;VALUE=DATE:20030919
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-real-world-2003-05-29.diary-american b/test/data/icalendar/import-real-world-2003-05-29.diary-american
new file mode 100644
index 0000000000..e6c8712d25
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-05-29.diary-american
@@ -0,0 +1,6 @@
+&5/9/2003 07:00-12:00 On-Site Interview
+ Desc: 10:30am - Blah
+ Location: Cccc
+ Organizer: MAILTO:aaaaaaa@aaaaaaa.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
diff --git a/test/data/icalendar/import-real-world-2003-05-29.diary-european b/test/data/icalendar/import-real-world-2003-05-29.diary-european
new file mode 100644
index 0000000000..cecca070a5
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-05-29.diary-european
@@ -0,0 +1,6 @@
+&9/5/2003 07:00-12:00 On-Site Interview
+ Desc: 10:30am - Blah
+ Location: Cccc
+ Organizer: MAILTO:aaaaaaa@aaaaaaa.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
diff --git a/test/data/icalendar/import-real-world-2003-05-29.ics b/test/data/icalendar/import-real-world-2003-05-29.ics
new file mode 100644
index 0000000000..decc8df545
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-05-29.ics
@@ -0,0 +1,54 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft CDO for Microsoft Exchange
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Kolkata, Chennai, Mumbai, New Delhi
+X-MICROSOFT-CDO-TZID:23
+BEGIN:STANDARD
+DTSTART:16010101T000000
+TZOFFSETFROM:+0530
+TZOFFSETTO:+0530
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T000000
+TZOFFSETFROM:+0530
+TZOFFSETTO:+0530
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20030509T043439Z
+DTSTART;TZID="Kolkata, Chennai, Mumbai, New Delhi":20030509T103000
+SUMMARY:On-Site Interview
+UID:040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000
+ 010000000DB823520692542408ED02D7023F9DFF9
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Xxxxx
+ xxx Xxxxxxxxxxxx":MAILTO:xxxxxxxx@xxxxxxx.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Yyyyyyy Y
+ yyyy":MAILTO:yyyyyyy@yyyyyyy.com
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="Zzzz Zzzz
+ zz":MAILTO:zzzzzz@zzzzzzz.com
+ORGANIZER;CN="Aaaaaa Aaaaa":MAILTO:aaaaaaa@aaaaaaa.com
+LOCATION:Cccc
+DTEND;TZID="Kolkata, Chennai, Mumbai, New Delhi":20030509T153000
+DESCRIPTION:10:30am - Blah
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030509T043439Z
+LAST-MODIFIED:20030509T043459Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:126441427
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-real-world-2003-06-18a.diary-american b/test/data/icalendar/import-real-world-2003-06-18a.diary-american
new file mode 100644
index 0000000000..f2c914184e
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-06-18a.diary-american
@@ -0,0 +1,6 @@
+&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
+ Desc: 753 Zeichen hier radiert
+ Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
+ Organizer: MAILTO:xxx@xxxxx.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/data/icalendar/import-real-world-2003-06-18a.diary-european b/test/data/icalendar/import-real-world-2003-06-18a.diary-european
new file mode 100644
index 0000000000..89cff58af4
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-06-18a.diary-european
@@ -0,0 +1,6 @@
+&23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
+ Desc: 753 Zeichen hier radiert
+ Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
+ Organizer: MAILTO:xxx@xxxxx.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/data/icalendar/import-real-world-2003-06-18a.ics b/test/data/icalendar/import-real-world-2003-06-18a.ics
new file mode 100644
index 0000000000..6bb5b05af1
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-06-18a.ics
@@ -0,0 +1,36 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20030618T195512Z
+DTSTART;TZID="Mountain Time (US & Canada)":20030623T110000
+SUMMARY:Dress Rehearsal for XXXX-XXXX
+UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
+ 0100000007C3A6D65EE726E40B7F3D69A23BD567E
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN="AAAAA,AAA
+ AA (A-AAAAAAA,ex1)":MAILTO:aaaaa_aaaaa@aaaaa.com
+ORGANIZER;CN="ABCD,TECHTRAINING
+ (A-Americas,exgen1)":MAILTO:xxx@xxxxx.com
+LOCATION:555 or TN 555-5555 ID 5555 & NochWas (see below)
+DTEND;TZID="Mountain Time (US & Canada)":20030623T120000
+DESCRIPTION:753 Zeichen hier radiert
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030618T195518Z
+LAST-MODIFIED:20030618T195527Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:1022519251
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-real-world-2003-06-18b.diary-american b/test/data/icalendar/import-real-world-2003-06-18b.diary-american
new file mode 100644
index 0000000000..2c0774cdd8
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-06-18b.diary-american
@@ -0,0 +1,6 @@
+&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
+ Desc: Viele Zeichen standen hier früher
+ Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
+ Organizer: MAILTO:bbb@bbbbb.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/data/icalendar/import-real-world-2003-06-18b.diary-european b/test/data/icalendar/import-real-world-2003-06-18b.diary-european
new file mode 100644
index 0000000000..95aac16869
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-06-18b.diary-european
@@ -0,0 +1,6 @@
+&23/6/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
+ Desc: Viele Zeichen standen hier früher
+ Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
+ Organizer: MAILTO:bbb@bbbbb.com
+ Status: CONFIRMED
+ UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
diff --git a/test/data/icalendar/import-real-world-2003-06-18b.ics b/test/data/icalendar/import-real-world-2003-06-18b.ics
new file mode 100644
index 0000000000..1523135adf
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2003-06-18b.ics
@@ -0,0 +1,55 @@
+BEGIN:VCALENDAR
+METHOD:REQUEST
+PRODID:Microsoft CDO for Microsoft Exchange
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Mountain Time (US & Canada)
+X-MICROSOFT-CDO-TZID:12
+BEGIN:STANDARD
+DTSTART:16010101T020000
+TZOFFSETFROM:-0600
+TZOFFSETTO:-0700
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:16010101T020000
+TZOFFSETFROM:-0700
+TZOFFSETTO:-0600
+RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=4;BYDAY=1SU
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20030618T230323Z
+DTSTART;TZID="Mountain Time (US & Canada)":20030623T090000
+SUMMARY:Updated: Dress Rehearsal for ABC01-15
+UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
+ 0100000007C3A6D65EE726E40B7F3D69A23BD567E
+ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;X-REPLYTIME=20030618T20
+ 0700Z;RSVP=TRUE;CN="AAAAA,AAAAAA
+\(A-AAAAAAA,ex1)":MAILTO:aaaaaa_aaaaa@aaaaa
+ .com
+ORGANIZER;CN="ABCD,TECHTRAINING
+\(A-Americas,exgen1)":MAILTO:bbb@bbbbb.com
+LOCATION:123 or TN 123-1234 ID abcd & SonstWo (see below)
+DTEND;TZID="Mountain Time (US & Canada)":20030623T100000
+DESCRIPTION:Viele Zeichen standen hier früher
+SEQUENCE:0
+PRIORITY:5
+CLASS:
+CREATED:20030618T230326Z
+LAST-MODIFIED:20030618T230335Z
+STATUS:CONFIRMED
+TRANSP:OPAQUE
+X-MICROSOFT-CDO-BUSYSTATUS:BUSY
+X-MICROSOFT-CDO-INSTTYPE:0
+X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
+X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
+X-MICROSOFT-CDO-IMPORTANCE:1
+X-MICROSOFT-CDO-OWNERAPPTID:1022519251
+BEGIN:VALARM
+ACTION:DISPLAY
+DESCRIPTION:REMINDER
+TRIGGER;RELATED=START:-PT00H15M00S
+END:VALARM
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git a/test/data/icalendar/import-real-world-2004-11-19.diary-american b/test/data/icalendar/import-real-world-2004-11-19.diary-american
new file mode 100644
index 0000000000..a986f700ba
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2004-11-19.diary-american
@@ -0,0 +1,19 @@
+&11/23/2004 14:00-14:30 Jjjjj & Wwwww
+ Status: TENTATIVE
+ Class: PRIVATE
+&11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
+ Status: TENTATIVE
+ Class: PRIVATE
+&11/23/2004 11:00-12:00 Hhhhhhhh
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 14 11 12 2004)) 14:00-18:30 MMM Aaaaaaaaa
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-block 11 19 2004 11 19 2004)) Rrrr/Cccccc ii Aaaaaaaa
+ Desc: Vvvvv Rrrr aaa Cccccc
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 7 11 1 2004)) Wwww aa hhhh
+ Status: TENTATIVE
+ Class: PRIVATE
diff --git a/test/data/icalendar/import-real-world-2004-11-19.diary-european b/test/data/icalendar/import-real-world-2004-11-19.diary-european
new file mode 100644
index 0000000000..cbfe99eb8e
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2004-11-19.diary-european
@@ -0,0 +1,19 @@
+&23/11/2004 14:00-14:30 Jjjjj & Wwwww
+ Status: TENTATIVE
+ Class: PRIVATE
+&23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
+ Status: TENTATIVE
+ Class: PRIVATE
+&23/11/2004 11:00-12:00 Hhhhhhhh
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 14 12 11 2004)) 14:00-18:30 MMM Aaaaaaaaa
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-block 19 11 2004 19 11 2004)) Rrrr/Cccccc ii Aaaaaaaa
+ Desc: Vvvvv Rrrr aaa Cccccc
+ Status: TENTATIVE
+ Class: PRIVATE
+&%%(and (diary-cyclic 7 1 11 2004)) Wwww aa hhhh
+ Status: TENTATIVE
+ Class: PRIVATE
diff --git a/test/data/icalendar/import-real-world-2004-11-19.ics b/test/data/icalendar/import-real-world-2004-11-19.ics
new file mode 100644
index 0000000000..9edb682fca
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2004-11-19.ics
@@ -0,0 +1,120 @@
+BEGIN:VCALENDAR
+VERSION
+ :2.0
+PRODID
+ :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
+BEGIN:VEVENT
+SUMMARY
+ :Jjjjj & Wwwww
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T140000
+DTEND
+ :20041123T143000
+DTSTAMP
+ :20041118T013430Z
+LAST-MODIFIED
+ :20041118T013640Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :BB Aaaaaaaa Bbbbb
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T144500
+DTEND
+ :20041123T154500
+DTSTAMP
+ :20041118T013641Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Hhhhhhhh
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ :20041123T110000
+DTEND
+ :20041123T120000
+DTSTAMP
+ :20041118T013831Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :MMM Aaaaaaaaa
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+X-MOZILLA-RECUR-DEFAULT-INTERVAL
+ :2
+RRULE
+ :FREQ=WEEKLY;INTERVAL=2;BYDAY=FR
+DTSTART
+ :20041112T140000
+DTEND
+ :20041112T183000
+DTSTAMP
+ :20041118T014117Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Rrrr/Cccccc ii Aaaaaaaa
+DESCRIPTION
+ :Vvvvv Rrrr aaa Cccccc
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+DTSTART
+ ;VALUE=DATE
+ :20041119
+DTEND
+ ;VALUE=DATE
+ :20041120
+DTSTAMP
+ :20041118T013107Z
+LAST-MODIFIED
+ :20041118T014203Z
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY
+ :Wwww aa hhhh
+STATUS
+ :TENTATIVE
+CLASS
+ :PRIVATE
+X-MOZILLA-ALARM-DEFAULT-LENGTH
+ :0
+RRULE
+ :FREQ=WEEKLY;INTERVAL=1;BYDAY=MO
+DTSTART
+ ;VALUE=DATE
+ :20041101
+DTEND
+ ;VALUE=DATE
+ :20041102
+DTSTAMP
+ :20041118T014045Z
+LAST-MODIFIED
+ :20041118T023846Z
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-real-world-2005-02-07.diary-american b/test/data/icalendar/import-real-world-2005-02-07.diary-american
new file mode 100644
index 0000000000..ce7d835d96
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2005-02-07.diary-american
@@ -0,0 +1,5 @@
+&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
+ Desc: abcdef
+ Status: CONFIRMED
+ Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
diff --git a/test/data/icalendar/import-real-world-2005-02-07.diary-european b/test/data/icalendar/import-real-world-2005-02-07.diary-european
new file mode 100644
index 0000000000..3a52b0ab27
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2005-02-07.diary-european
@@ -0,0 +1,5 @@
+&%%(and (diary-block 6 2 2005 6 2 2005)) Waitangi Day
+ Desc: abcdef
+ Status: CONFIRMED
+ Class: PRIVATE
+ UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
diff --git a/test/data/icalendar/import-real-world-2005-02-07.ics b/test/data/icalendar/import-real-world-2005-02-07.ics
new file mode 100644
index 0000000000..9eec71fe75
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2005-02-07.ics
@@ -0,0 +1,26 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID
+ :b60d398e-1dd1-11b2-a159-cf8cb05139f4
+SUMMARY
+ :Waitangi Day
+DESCRIPTION
+ :abcdef
+CATEGORIES
+ :Public Holiday
+STATUS
+ :CONFIRMED
+CLASS
+ :PRIVATE
+DTSTART
+ ;VALUE=DATE
+ :20050206
+DTEND
+ ;VALUE=DATE
+ :20050207
+DTSTAMP
+ :20050128T011209Z
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-real-world-2005-03-01.diary-american b/test/data/icalendar/import-real-world-2005-03-01.diary-american
new file mode 100644
index 0000000000..23c93d45d9
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2005-03-01.diary-american
@@ -0,0 +1,2 @@
+&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
diff --git a/test/data/icalendar/import-real-world-2005-03-01.diary-european b/test/data/icalendar/import-real-world-2005-03-01.diary-european
new file mode 100644
index 0000000000..106e9f3cdd
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2005-03-01.diary-european
@@ -0,0 +1,2 @@
+&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
+ UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
diff --git a/test/data/icalendar/import-real-world-2005-03-01.ics b/test/data/icalendar/import-real-world-2005-03-01.ics
new file mode 100644
index 0000000000..ed9faa9b0b
--- /dev/null
+++ b/test/data/icalendar/import-real-world-2005-03-01.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20050217
+SUMMARY:Hhhhhh Aaaaa ii Aaaaaaaa
+UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
+DTSTAMP:20050118T210335Z
+DURATION:P7D
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-real-world-no-dst.diary-american b/test/data/icalendar/import-real-world-no-dst.diary-american
new file mode 100644
index 0000000000..290edb8876
--- /dev/null
+++ b/test/data/icalendar/import-real-world-no-dst.diary-american
@@ -0,0 +1,4 @@
+&11/16/2014 04:30-05:30 NoDST
+ Desc: Test event from timezone without DST
+ Location: Everywhere
+ UID: 20141116T171439Z-678877132@marudot.com
diff --git a/test/data/icalendar/import-real-world-no-dst.diary-european b/test/data/icalendar/import-real-world-no-dst.diary-european
new file mode 100644
index 0000000000..c56b7a6547
--- /dev/null
+++ b/test/data/icalendar/import-real-world-no-dst.diary-european
@@ -0,0 +1,4 @@
+&16/11/2014 04:30-05:30 NoDST
+ Desc: Test event from timezone without DST
+ Location: Everywhere
+ UID: 20141116T171439Z-678877132@marudot.com
diff --git a/test/data/icalendar/import-real-world-no-dst.ics b/test/data/icalendar/import-real-world-no-dst.ics
new file mode 100644
index 0000000000..5f147af4f3
--- /dev/null
+++ b/test/data/icalendar/import-real-world-no-dst.ics
@@ -0,0 +1,26 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//www.marudot.com//iCal Event Maker
+X-WR-CALNAME:Test
+CALSCALE:GREGORIAN
+BEGIN:VTIMEZONE
+TZID:Asia/Tehran
+TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tehran
+X-LIC-LOCATION:Asia/Tehran
+BEGIN:STANDARD
+TZOFFSETFROM:+0330
+TZOFFSETTO:+0330
+TZNAME:IRST
+DTSTART:19700101T000000
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+DTSTAMP:20141116T171439Z
+UID:20141116T171439Z-678877132@marudot.com
+DTSTART;TZID="Asia/Tehran":20141116T070000
+DTEND;TZID="Asia/Tehran":20141116T080000
+SUMMARY:NoDST
+DESCRIPTION:Test event from timezone without DST
+LOCATION:Everywhere
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git a/test/data/icalendar/import-rrule-anniversary.diary-american b/test/data/icalendar/import-rrule-anniversary.diary-american
new file mode 100644
index 0000000000..7b86b554dd
--- /dev/null
+++ b/test/data/icalendar/import-rrule-anniversary.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 8 15 2004)) Maria Himmelfahrt
diff --git a/test/data/icalendar/import-rrule-anniversary.diary-european b/test/data/icalendar/import-rrule-anniversary.diary-european
new file mode 100644
index 0000000000..3b82ec09fd
--- /dev/null
+++ b/test/data/icalendar/import-rrule-anniversary.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 15 8 2004)) Maria Himmelfahrt
diff --git a/test/data/icalendar/import-rrule-anniversary.diary-iso b/test/data/icalendar/import-rrule-anniversary.diary-iso
new file mode 100644
index 0000000000..7fc99478d4
--- /dev/null
+++ b/test/data/icalendar/import-rrule-anniversary.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 2004 8 15)) Maria Himmelfahrt
diff --git a/test/data/icalendar/import-rrule-anniversary.ics b/test/data/icalendar/import-rrule-anniversary.ics
new file mode 100644
index 0000000000..2996f49416
--- /dev/null
+++ b/test/data/icalendar/import-rrule-anniversary.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTART;VALUE=DATE:20040815
+DTEND;VALUE=DATE:20040816
+SUMMARY:Maria Himmelfahrt
+RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-count-bi-weekly.diary-american b/test/data/icalendar/import-rrule-count-bi-weekly.diary-american
new file mode 100644
index 0000000000..84b6d10995
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-bi-weekly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 9 19 2003) (diary-block 9 19 2003 10 31 2003)) 09:00-11:30 rrule count bi-weekly 3 times
diff --git a/test/data/icalendar/import-rrule-count-bi-weekly.diary-european b/test/data/icalendar/import-rrule-count-bi-weekly.diary-european
new file mode 100644
index 0000000000..0bebdf8872
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-bi-weekly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 19 9 2003) (diary-block 19 9 2003 31 10 2003)) 09:00-11:30 rrule count bi-weekly 3 times
diff --git a/test/data/icalendar/import-rrule-count-bi-weekly.diary-iso b/test/data/icalendar/import-rrule-count-bi-weekly.diary-iso
new file mode 100644
index 0000000000..11429081ab
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-bi-weekly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 14 2003 9 19) (diary-block 2003 9 19 2003 10 31)) 09:00-11:30 rrule count bi-weekly 3 times
diff --git a/test/data/icalendar/import-rrule-count-bi-weekly.ics b/test/data/icalendar/import-rrule-count-bi-weekly.ics
new file mode 100644
index 0000000000..888b85bb33
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-bi-weekly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count bi-weekly 3 times
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-count-daily-long.diary-american b/test/data/icalendar/import-rrule-count-daily-long.diary-american
new file mode 100644
index 0000000000..23fe9fcaf3
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-long.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 10 2 2003)) 09:00-11:30 rrule count daily long
diff --git a/test/data/icalendar/import-rrule-count-daily-long.diary-european b/test/data/icalendar/import-rrule-count-daily-long.diary-european
new file mode 100644
index 0000000000..0d4ab66905
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-long.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 2 10 2003)) 09:00-11:30 rrule count daily long
diff --git a/test/data/icalendar/import-rrule-count-daily-long.diary-iso b/test/data/icalendar/import-rrule-count-daily-long.diary-iso
new file mode 100644
index 0000000000..8cecda5c87
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-long.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 10 2)) 09:00-11:30 rrule count daily long
diff --git a/test/data/icalendar/import-rrule-count-daily-long.ics b/test/data/icalendar/import-rrule-count-daily-long.ics
new file mode 100644
index 0000000000..73df19a819
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-long.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count daily long
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;COUNT=14;INTERVAL=1
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-count-daily-short.diary-american b/test/data/icalendar/import-rrule-count-daily-short.diary-american
new file mode 100644
index 0000000000..d69bb08c31
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-short.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 9 19 2003)) 09:00-11:30 rrule count daily short
diff --git a/test/data/icalendar/import-rrule-count-daily-short.diary-european b/test/data/icalendar/import-rrule-count-daily-short.diary-european
new file mode 100644
index 0000000000..33a1ce4cf5
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-short.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 19 9 2003)) 09:00-11:30 rrule count daily short
diff --git a/test/data/icalendar/import-rrule-count-daily-short.diary-iso b/test/data/icalendar/import-rrule-count-daily-short.diary-iso
new file mode 100644
index 0000000000..a06bcba0dc
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-short.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 9 19)) 09:00-11:30 rrule count daily short
diff --git a/test/data/icalendar/import-rrule-count-daily-short.ics b/test/data/icalendar/import-rrule-count-daily-short.ics
new file mode 100644
index 0000000000..92ffe8be65
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-daily-short.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count daily short
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;COUNT=1;INTERVAL=1
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-count-every-second-month.diary-american b/test/data/icalendar/import-rrule-count-every-second-month.diary-american
new file mode 100644
index 0000000000..4ce8ef842f
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-month.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 5 19 2004)) 09:00-11:30 rrule count every second month
diff --git a/test/data/icalendar/import-rrule-count-every-second-month.diary-european b/test/data/icalendar/import-rrule-count-every-second-month.diary-european
new file mode 100644
index 0000000000..09ec375629
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-month.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 5 2004)) 09:00-11:30 rrule count every second month
diff --git a/test/data/icalendar/import-rrule-count-every-second-month.diary-iso b/test/data/icalendar/import-rrule-count-every-second-month.diary-iso
new file mode 100644
index 0000000000..ae6feb70d4
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-month.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 5 19)) 09:00-11:30 rrule count every second month
diff --git a/test/data/icalendar/import-rrule-count-every-second-month.ics b/test/data/icalendar/import-rrule-count-every-second-month.ics
new file mode 100644
index 0000000000..3b27b66549
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-month.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count every second month
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-count-every-second-year.diary-american b/test/data/icalendar/import-rrule-count-every-second-year.diary-american
new file mode 100644
index 0000000000..99543aa959
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-year.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2011)) 09:00-11:30 rrule count every second year
diff --git a/test/data/icalendar/import-rrule-count-every-second-year.diary-european b/test/data/icalendar/import-rrule-count-every-second-year.diary-european
new file mode 100644
index 0000000000..3b330886ce
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-year.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2011)) 09:00-11:30 rrule count every second year
diff --git a/test/data/icalendar/import-rrule-count-every-second-year.diary-iso b/test/data/icalendar/import-rrule-count-every-second-year.diary-iso
new file mode 100644
index 0000000000..16af52ea91
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-year.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2011 9 19)) 09:00-11:30 rrule count every second year
diff --git a/test/data/icalendar/import-rrule-count-every-second-year.ics b/test/data/icalendar/import-rrule-count-every-second-year.ics
new file mode 100644
index 0000000000..ce21c34d09
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-every-second-year.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count every second year
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=5
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-rrule-count-monthly.diary-american b/test/data/icalendar/import-rrule-count-monthly.diary-american
new file mode 100644
index 0000000000..ad5ca0b0ed
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-monthly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 19 2004)) 09:00-11:30 rrule count monthly
diff --git a/test/data/icalendar/import-rrule-count-monthly.diary-european b/test/data/icalendar/import-rrule-count-monthly.diary-european
new file mode 100644
index 0000000000..709de3a3fd
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-monthly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 1 2004)) 09:00-11:30 rrule count monthly
diff --git a/test/data/icalendar/import-rrule-count-monthly.diary-iso b/test/data/icalendar/import-rrule-count-monthly.diary-iso
new file mode 100644
index 0000000000..9fc2a2def9
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-monthly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 1 19)) 09:00-11:30 rrule count monthly
diff --git a/test/data/icalendar/import-rrule-count-monthly.ics b/test/data/icalendar/import-rrule-count-monthly.ics
new file mode 100644
index 0000000000..3391ca2425
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-monthly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count monthly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;INTERVAL=1;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-count-yearly.diary-american b/test/data/icalendar/import-rrule-count-yearly.diary-american
new file mode 100644
index 0000000000..8c1f95b0c0
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-yearly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2007)) 09:00-11:30 rrule count yearly
diff --git a/test/data/icalendar/import-rrule-count-yearly.diary-european b/test/data/icalendar/import-rrule-count-yearly.diary-european
new file mode 100644
index 0000000000..e216e224ea
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-yearly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2007)) 09:00-11:30 rrule count yearly
diff --git a/test/data/icalendar/import-rrule-count-yearly.diary-iso b/test/data/icalendar/import-rrule-count-yearly.diary-iso
new file mode 100644
index 0000000000..3801192ee6
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-yearly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2007 9 19)) 09:00-11:30 rrule count yearly
diff --git a/test/data/icalendar/import-rrule-count-yearly.ics b/test/data/icalendar/import-rrule-count-yearly.ics
new file mode 100644
index 0000000000..d8569933e0
--- /dev/null
+++ b/test/data/icalendar/import-rrule-count-yearly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule count yearly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=5
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-daily-two-day.diary-american b/test/data/icalendar/import-rrule-daily-two-day.diary-american
new file mode 100644
index 0000000000..495fca5f8d
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-two-day.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily
diff --git a/test/data/icalendar/import-rrule-daily-two-day.diary-european b/test/data/icalendar/import-rrule-daily-two-day.diary-european
new file mode 100644
index 0000000000..61db14ab24
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-two-day.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily
diff --git a/test/data/icalendar/import-rrule-daily-two-day.diary-iso b/test/data/icalendar/import-rrule-daily-two-day.diary-iso
new file mode 100644
index 0000000000..0e0a4b1978
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-two-day.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily
diff --git a/test/data/icalendar/import-rrule-daily-two-day.ics b/test/data/icalendar/import-rrule-daily-two-day.ics
new file mode 100644
index 0000000000..8c9cb3b284
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-two-day.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-rrule-daily-with-exceptions.diary-american b/test/data/icalendar/import-rrule-daily-with-exceptions.diary-american
new file mode 100644
index 0000000000..83e5f582d5
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-with-exceptions.diary-american
@@ -0,0 +1 @@
+&%%(and (not (diary-date 9 25 2003)) (not (diary-date 9 21 2003)) (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily with exceptions
diff --git a/test/data/icalendar/import-rrule-daily-with-exceptions.diary-european b/test/data/icalendar/import-rrule-daily-with-exceptions.diary-european
new file mode 100644
index 0000000000..a3c7fdd417
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-with-exceptions.diary-european
@@ -0,0 +1 @@
+&%%(and (not (diary-date 25 9 2003)) (not (diary-date 21 9 2003)) (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily with exceptions
diff --git a/test/data/icalendar/import-rrule-daily-with-exceptions.diary-iso b/test/data/icalendar/import-rrule-daily-with-exceptions.diary-iso
new file mode 100644
index 0000000000..88b4c892d1
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-with-exceptions.diary-iso
@@ -0,0 +1 @@
+&%%(and (not (diary-date 2003 9 25)) (not (diary-date 2003 9 21)) (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily with exceptions
diff --git a/test/data/icalendar/import-rrule-daily-with-exceptions.ics b/test/data/icalendar/import-rrule-daily-with-exceptions.ics
new file mode 100644
index 0000000000..5284bf42d8
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily-with-exceptions.ics
@@ -0,0 +1,12 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily with exceptions
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;INTERVAL=2
+EXDATE:20030921,20030925
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-daily.diary-american b/test/data/icalendar/import-rrule-daily.diary-american
new file mode 100644
index 0000000000..9213270fa4
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 9 19 2003)) 09:00-11:30 rrule daily
diff --git a/test/data/icalendar/import-rrule-daily.diary-european b/test/data/icalendar/import-rrule-daily.diary-european
new file mode 100644
index 0000000000..2c70cd7da5
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 19 9 2003)) 09:00-11:30 rrule daily
diff --git a/test/data/icalendar/import-rrule-daily.diary-iso b/test/data/icalendar/import-rrule-daily.diary-iso
new file mode 100644
index 0000000000..b201cb4430
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 1 2003 9 19)) 09:00-11:30 rrule daily
diff --git a/test/data/icalendar/import-rrule-daily.ics b/test/data/icalendar/import-rrule-daily.ics
new file mode 100644
index 0000000000..6d013b0b4f
--- /dev/null
+++ b/test/data/icalendar/import-rrule-daily.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule daily
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=DAILY;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-monthly-no-end.diary-american b/test/data/icalendar/import-rrule-monthly-no-end.diary-american
new file mode 100644
index 0000000000..bc5453fe42
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-no-end.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 1 9999)) 09:00-11:30 rrule monthly no end
diff --git a/test/data/icalendar/import-rrule-monthly-no-end.diary-european b/test/data/icalendar/import-rrule-monthly-no-end.diary-european
new file mode 100644
index 0000000000..f071519701
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-no-end.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 1 1 9999)) 09:00-11:30 rrule monthly no end
diff --git a/test/data/icalendar/import-rrule-monthly-no-end.diary-iso b/test/data/icalendar/import-rrule-monthly-no-end.diary-iso
new file mode 100644
index 0000000000..3709e93333
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-no-end.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 9999 1 1)) 09:00-11:30 rrule monthly no end
diff --git a/test/data/icalendar/import-rrule-monthly-no-end.ics b/test/data/icalendar/import-rrule-monthly-no-end.ics
new file mode 100644
index 0000000000..b871658600
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-no-end.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule monthly no end
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-monthly-with-end.diary-american b/test/data/icalendar/import-rrule-monthly-with-end.diary-american
new file mode 100644
index 0000000000..638ab8b232
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-with-end.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-date t 19 t) (diary-block 9 19 2003 8 19 2005)) 09:00-11:30 rrule monthly with end
diff --git a/test/data/icalendar/import-rrule-monthly-with-end.diary-european b/test/data/icalendar/import-rrule-monthly-with-end.diary-european
new file mode 100644
index 0000000000..c70cde25f3
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-with-end.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 8 2005)) 09:00-11:30 rrule monthly with end
diff --git a/test/data/icalendar/import-rrule-monthly-with-end.diary-iso b/test/data/icalendar/import-rrule-monthly-with-end.diary-iso
new file mode 100644
index 0000000000..ee51a2142a
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-with-end.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-date t t 19) (diary-block 2003 9 19 2005 8 19)) 09:00-11:30 rrule monthly with end
diff --git a/test/data/icalendar/import-rrule-monthly-with-end.ics b/test/data/icalendar/import-rrule-monthly-with-end.ics
new file mode 100644
index 0000000000..d8a1fe2e5a
--- /dev/null
+++ b/test/data/icalendar/import-rrule-monthly-with-end.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule monthly with end
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=MONTHLY;UNTIL=20050819;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-weekly.diary-american b/test/data/icalendar/import-rrule-weekly.diary-american
new file mode 100644
index 0000000000..d8bf2eba10
--- /dev/null
+++ b/test/data/icalendar/import-rrule-weekly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 9 19 2003)) 09:00-11:30 rrule weekly
diff --git a/test/data/icalendar/import-rrule-weekly.diary-european b/test/data/icalendar/import-rrule-weekly.diary-european
new file mode 100644
index 0000000000..e368fde970
--- /dev/null
+++ b/test/data/icalendar/import-rrule-weekly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 19 9 2003)) 09:00-11:30 rrule weekly
diff --git a/test/data/icalendar/import-rrule-weekly.diary-iso b/test/data/icalendar/import-rrule-weekly.diary-iso
new file mode 100644
index 0000000000..49cd9d8ace
--- /dev/null
+++ b/test/data/icalendar/import-rrule-weekly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-cyclic 7 2003 9 19)) 09:00-11:30 rrule weekly
diff --git a/test/data/icalendar/import-rrule-weekly.ics b/test/data/icalendar/import-rrule-weekly.ics
new file mode 100644
index 0000000000..c3f0b8ae93
--- /dev/null
+++ b/test/data/icalendar/import-rrule-weekly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule weekly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=WEEKLY;
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-rrule-yearly.diary-american b/test/data/icalendar/import-rrule-yearly.diary-american
new file mode 100644
index 0000000000..a54780b969
--- /dev/null
+++ b/test/data/icalendar/import-rrule-yearly.diary-american
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly
diff --git a/test/data/icalendar/import-rrule-yearly.diary-european b/test/data/icalendar/import-rrule-yearly.diary-european
new file mode 100644
index 0000000000..a4bd81d6f2
--- /dev/null
+++ b/test/data/icalendar/import-rrule-yearly.diary-european
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly
diff --git a/test/data/icalendar/import-rrule-yearly.diary-iso b/test/data/icalendar/import-rrule-yearly.diary-iso
new file mode 100644
index 0000000000..65a7abe034
--- /dev/null
+++ b/test/data/icalendar/import-rrule-yearly.diary-iso
@@ -0,0 +1 @@
+&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly
diff --git a/test/data/icalendar/import-rrule-yearly.ics b/test/data/icalendar/import-rrule-yearly.ics
new file mode 100644
index 0000000000..21cca097f7
--- /dev/null
+++ b/test/data/icalendar/import-rrule-yearly.ics
@@ -0,0 +1,11 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+SUMMARY:rrule yearly
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+RRULE:FREQ=YEARLY;INTERVAL=2
+END:VEVENT
+END:VCALENDAR
+
diff --git a/test/data/icalendar/import-with-timezone.diary-iso b/test/data/icalendar/import-with-timezone.diary-iso
new file mode 100644
index 0000000000..f99b59213e
--- /dev/null
+++ b/test/data/icalendar/import-with-timezone.diary-iso
@@ -0,0 +1,2 @@
+&2012/1/15 15:00-15:30 standardtime
+&2012/12/15 11:00-11:30 daylightsavingtime
diff --git a/test/data/icalendar/import-with-timezone.ics b/test/data/icalendar/import-with-timezone.ics
new file mode 100644
index 0000000000..110a9835e4
--- /dev/null
+++ b/test/data/icalendar/import-with-timezone.ics
@@ -0,0 +1,27 @@
+BEGIN:VCALENDAR
+BEGIN:VTIMEZONE
+TZID:fictional, nonexistent, arbitrary
+BEGIN:STANDARD
+DTSTART:20100101T000000
+TZOFFSETFROM:+0200
+TZOFFSETTO:-0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20101201T000000
+TZOFFSETFROM:-0200
+TZOFFSETTO:+0200
+RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+SUMMARY:standardtime
+DTSTART;TZID="fictional, nonexistent, arbitrary":20120115T120000
+DTEND;TZID="fictional, nonexistent, arbitrary":20120115T123000
+END:VEVENT
+BEGIN:VEVENT
+SUMMARY:daylightsavingtime
+DTSTART;TZID="fictional, nonexistent, arbitrary":20121215T120000
+DTEND;TZID="fictional, nonexistent, arbitrary":20121215T123000
+END:VEVENT
+END:VCALENDAR
diff --git a/test/data/icalendar/import-with-uid.diary-american b/test/data/icalendar/import-with-uid.diary-american
new file mode 100644
index 0000000000..9b2f06afc2
--- /dev/null
+++ b/test/data/icalendar/import-with-uid.diary-american
@@ -0,0 +1,2 @@
+&9/19/2003 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/data/icalendar/import-with-uid.diary-european b/test/data/icalendar/import-with-uid.diary-european
new file mode 100644
index 0000000000..95db4d4015
--- /dev/null
+++ b/test/data/icalendar/import-with-uid.diary-european
@@ -0,0 +1,2 @@
+&19/9/2003 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/data/icalendar/import-with-uid.diary-iso b/test/data/icalendar/import-with-uid.diary-iso
new file mode 100644
index 0000000000..d372e5a3d1
--- /dev/null
+++ b/test/data/icalendar/import-with-uid.diary-iso
@@ -0,0 +1,2 @@
+&2003/9/19 09:00-11:30 non-recurring
+ UID: 1234567890uid
diff --git a/test/data/icalendar/import-with-uid.ics b/test/data/icalendar/import-with-uid.ics
new file mode 100644
index 0000000000..db412d9d9f
--- /dev/null
+++ b/test/data/icalendar/import-with-uid.ics
@@ -0,0 +1,10 @@
+BEGIN:VCALENDAR
+PRODID:-//Emacs//NONSGML icalendar.el//EN
+VERSION:2.0
+BEGIN:VEVENT
+UID:1234567890uid
+SUMMARY:non-recurring
+DTSTART;VALUE=DATE-TIME:20030919T090000
+DTEND;VALUE=DATE-TIME:20030919T113000
+END:VEVENT
+END:VCALENDAR
diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el
index bce7de769e..5143c78632 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -51,6 +51,20 @@
(replace-regexp-in-string "[ \t\n]+\\'" ""
(replace-regexp-in-string "\\`[ \t\n]+" "" string)))
+(defconst icalendar-tests--data-dir
+ (expand-file-name "test/data/icalendar" source-directory))
+
+(defun icalendar-tests--get-file-contents (filename)
+ "Return contents of file in test data directory named FILENAME."
+ (with-temp-buffer
+ (let ((f1 (expand-file-name filename icalendar-tests--data-dir))
+ (f2 (expand-file-name filename "../../data/icalendar"))
+ (coding-system-for-read 'raw-text)
+ (inhibit-eol-conversion t))
+ (insert-file-contents-literally
+ (if (file-exists-p f1) f1 f2))
+ (buffer-string))))
+
;; ======================================================================
;; Tests of functions
;; ======================================================================
@@ -963,13 +977,16 @@ END:VALARM
;; Import tests
;; ======================================================================
-(defun icalendar-tests--test-import (input expected-iso expected-european
- expected-american)
+(defun icalendar-tests--test-import (filename expected-iso expected-european
+ expected-american)
"Perform import test.
-Argument INPUT icalendar event string.
-Argument EXPECTED-ISO expected iso style diary string.
-Argument EXPECTED-EUROPEAN expected european style diary string.
-Argument EXPECTED-AMERICAN expected american style diary string.
+Argument FILENAME ics file to import.
+Argument EXPECTED-ISO diary-file containing expected
+iso-calendar-style result.
+Argument EXPECTED-EUROPEAN diary-file containing expected
+european-calendar-style result.
+Argument EXPECTED-AMERICAN diary-file containing expected
+american-calendar-style result.
During import test the timezone is set to Central European Time."
(let ((timezone (getenv "TZ")))
(unwind-protect
@@ -978,14 +995,7 @@ During import test the timezone is set to Central European Time."
;; Eg hydra.nixos.org.
(setenv "TZ" "CET-1CEST,M3.5.0/2,M10.5.0/3")
(with-temp-buffer
- (if (string-match "^BEGIN:VCALENDAR" input)
- (insert input)
- (insert "BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML icalendar.el//EN\n")
- (insert "VERSION:2.0\nBEGIN:VEVENT\n")
- (insert input)
- (unless (eq (char-before) ?\n)
- (insert "\n"))
- (insert "END:VEVENT\nEND:VCALENDAR\n"))
+ (insert (icalendar-tests--get-file-contents filename))
(let ((icalendar-import-format "%s%d%l%o%t%u%c%U")
(icalendar-import-format-summary "%s")
(icalendar-import-format-location "\n Location: %s")
@@ -998,26 +1008,29 @@ During import test the timezone is set to Central European Time."
calendar-date-style)
(when expected-iso
(setq calendar-date-style 'iso)
- (icalendar-tests--do-test-import input expected-iso))
+ (icalendar-tests--do-test-import
+ (icalendar-tests--get-file-contents expected-iso)))
(when expected-european
(setq calendar-date-style 'european)
- (icalendar-tests--do-test-import input expected-european))
+ (icalendar-tests--do-test-import
+ (icalendar-tests--get-file-contents expected-european)))
(when expected-american
(setq calendar-date-style 'american)
- (icalendar-tests--do-test-import input expected-american)))))
+ (icalendar-tests--do-test-import
+ (icalendar-tests--get-file-contents expected-american))))))
(setenv "TZ" timezone))))
-(defun icalendar-tests--do-test-import (_input expected-output)
+(defun icalendar-tests--do-test-import (expected-output)
"Actually perform import test.
-Argument INPUT input icalendar string.
-Argument EXPECTED-OUTPUT expected diary string."
+Argument EXPECTED-OUTPUT file containing expected diary string."
(let ((temp-file (make-temp-file "icalendar-test-diary")))
;; Test the Catch-the-mysterious-coding-header logic below.
;; Ruby-mode adds an after-save-hook which inserts the header!
;; (save-excursion
;; (find-file temp-file)
;; (ruby-mode))
- (icalendar-import-buffer temp-file t t)
+ (let ((coding-system-for-write 'raw-text))
+ (icalendar-import-buffer temp-file t t))
(save-excursion
(find-file temp-file)
;; Check for the mysterious "# coding: ..." header, remove it
@@ -1045,452 +1058,135 @@ Argument EXPECTED-OUTPUT expected diary string."
(ert-deftest icalendar-import-non-recurring ()
"Perform standard import tests."
- (icalendar-tests--test-import
- "SUMMARY:non-recurring
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000"
- "&2003/9/19 09:00-11:30 non-recurring\n"
- "&19/9/2003 09:00-11:30 non-recurring\n"
- "&9/19/2003 09:00-11:30 non-recurring\n")
- (icalendar-tests--test-import
- "SUMMARY:non-recurring allday
-DTSTART;VALUE=DATE-TIME:20030919"
- "&2003/9/19 non-recurring allday\n"
- "&19/9/2003 non-recurring allday\n"
- "&9/19/2003 non-recurring allday\n")
- (icalendar-tests--test-import
- ;; Checkdoc removes trailing blanks. Therefore: format!
- (format "%s\n%s\n%s" "SUMMARY:long " " summary"
- "DTSTART;VALUE=DATE:20030919")
- "&2003/9/19 long summary\n"
- "&19/9/2003 long summary\n"
- "&9/19/2003 long summary\n")
- (icalendar-tests--test-import
- "UID:748f2da0-0d9b-11d8-97af-b4ec8686ea61
-SUMMARY:Sommerferien
-STATUS:TENTATIVE
-CLASS:PRIVATE
-X-MOZILLA-ALARM-DEFAULT-UNITS:Minuten
-X-MOZILLA-RECUR-DEFAULT-INTERVAL:0
-DTSTART;VALUE=DATE:20040719
-DTEND;VALUE=DATE:20040828
-DTSTAMP:20031103T011641Z
-"
- "&%%(and (diary-block 2004 7 19 2004 8 27)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-"
- "&%%(and (diary-block 19 7 2004 27 8 2004)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-"
- "&%%(and (diary-block 7 19 2004 8 27 2004)) Sommerferien
- Status: TENTATIVE
- Class: PRIVATE
- UID: 748f2da0-0d9b-11d8-97af-b4ec8686ea61
-")
- (icalendar-tests--test-import
- "UID
- :04979712-3902-11d9-93dd-8f9f4afe08da
-SUMMARY
- :folded summary
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T140000
-DTEND
- :20041123T143000
-DTSTAMP
- :20041118T013430Z
-LAST-MODIFIED
- :20041118T013640Z
-"
- "&2004/11/23 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
- "&23/11/2004 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n"
- "&11/23/2004 14:00-14:30 folded summary
- Status: TENTATIVE
- Class: PRIVATE
- UID: 04979712-3902-11d9-93dd-8f9f4afe08da\n")
-
- (icalendar-tests--test-import
- "UID
- :6161a312-3902-11d9-b512-f764153bb28b
-SUMMARY
- :another example
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T144500
-DTEND
- :20041123T154500
-DTSTAMP
- :20041118T013641Z
-"
- "&2004/11/23 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
- "&23/11/2004 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"
- "&11/23/2004 14:45-15:45 another example
- Status: TENTATIVE
- Class: PRIVATE
- UID: 6161a312-3902-11d9-b512-f764153bb28b\n"))
+ (icalendar-tests--test-import "import-non-recurring-1.ics"
+ "import-non-recurring-1.diary-iso"
+ "import-non-recurring-1.diary-european"
+ "import-non-recurring-1.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-all-day.ics"
+ "import-non-recurring-all-day.diary-iso"
+ "import-non-recurring-all-day.diary-european"
+ "import-non-recurring-all-day.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-long-summary.ics"
+ "import-non-recurring-long-summary.diary-iso"
+ "import-non-recurring-long-summary.diary-european"
+ "import-non-recurring-long-summary.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-block.ics"
+ "import-non-recurring-block.diary-iso"
+ "import-non-recurring-block.diary-european"
+ "import-non-recurring-block.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-folded-summary.ics"
+ "import-non-recurring-folded-summary.diary-iso"
+ "import-non-recurring-folded-summary.diary-european"
+ "import-non-recurring-folded-summary.diary-american")
+ (icalendar-tests--test-import "import-non-recurring-another-example.ics"
+ "import-non-recurring-another-example.diary-iso"
+ "import-non-recurring-another-example.diary-european"
+ "import-non-recurring-another-example.diary-american"))
+
(ert-deftest icalendar-import-rrule ()
- (icalendar-tests--test-import
- "SUMMARY:rrule daily
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;
-"
- "&%%(and (diary-cyclic 1 2003 9 19)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 1 19 9 2003)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 1 9 19 2003)) 09:00-11:30 rrule daily\n")
- ;; RRULE examples
- (icalendar-tests--test-import
- "SUMMARY:rrule daily
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;INTERVAL=2
-"
- "&%%(and (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily\n"
- "&%%(and (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule daily with exceptions
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;INTERVAL=2
-EXDATE:20030921,20030925
-"
- "&%%(and (not (diary-date 2003 9 25)) (not (diary-date 2003 9 21)) (diary-cyclic 2 2003 9 19)) 09:00-11:30 rrule daily with exceptions\n"
- "&%%(and (not (diary-date 25 9 2003)) (not (diary-date 21 9 2003)) (diary-cyclic 2 19 9 2003)) 09:00-11:30 rrule daily with exceptions\n"
- "&%%(and (not (diary-date 9 25 2003)) (not (diary-date 9 21 2003)) (diary-cyclic 2 9 19 2003)) 09:00-11:30 rrule daily with exceptions\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule weekly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=WEEKLY;
-"
- "&%%(and (diary-cyclic 7 2003 9 19)) 09:00-11:30 rrule weekly\n"
- "&%%(and (diary-cyclic 7 19 9 2003)) 09:00-11:30 rrule weekly\n"
- "&%%(and (diary-cyclic 7 9 19 2003)) 09:00-11:30 rrule weekly\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule monthly no end
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 9999 1 1)) 09:00-11:30 rrule monthly no end\n"
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 1 1 9999)) 09:00-11:30 rrule monthly no end\n"
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 1 9999)) 09:00-11:30 rrule monthly no end\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule monthly with end
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;UNTIL=20050819;
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2005 8 19)) 09:00-11:30 rrule monthly with end\n"
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 8 2005)) 09:00-11:30 rrule monthly with end\n"
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 8 19 2005)) 09:00-11:30 rrule monthly with end\n")
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20040815
-DTEND;VALUE=DATE:20040816
-SUMMARY:Maria Himmelfahrt
-RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8
-"
- "&%%(and (diary-anniversary 2004 8 15)) Maria Himmelfahrt\n"
- "&%%(and (diary-anniversary 15 8 2004)) Maria Himmelfahrt\n"
- "&%%(and (diary-anniversary 8 15 2004)) Maria Himmelfahrt\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule yearly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=2
-"
- "&%%(and (diary-anniversary 2003 9 19)) 09:00-11:30 rrule yearly\n" ;FIXME
- "&%%(and (diary-anniversary 19 9 2003)) 09:00-11:30 rrule yearly\n" ;FIXME
- "&%%(and (diary-anniversary 9 19 2003)) 09:00-11:30 rrule yearly\n") ;FIXME
- (icalendar-tests--test-import
- "SUMMARY:rrule count daily short
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;COUNT=1;INTERVAL=1
-"
- "&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 9 19)) 09:00-11:30 rrule count daily short\n"
- "&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 19 9 2003)) 09:00-11:30 rrule count daily short\n"
- "&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 9 19 2003)) 09:00-11:30 rrule count daily short\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count daily long
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=DAILY;COUNT=14;INTERVAL=1
-"
- "&%%(and (diary-cyclic 1 2003 9 19) (diary-block 2003 9 19 2003 10 2)) 09:00-11:30 rrule count daily long\n"
- "&%%(and (diary-cyclic 1 19 9 2003) (diary-block 19 9 2003 2 10 2003)) 09:00-11:30 rrule count daily long\n"
- "&%%(and (diary-cyclic 1 9 19 2003) (diary-block 9 19 2003 10 2 2003)) 09:00-11:30 rrule count daily long\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count bi-weekly 3 times
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=2
-"
- "&%%(and (diary-cyclic 14 2003 9 19) (diary-block 2003 9 19 2003 10 31)) 09:00-11:30 rrule count bi-weekly 3 times\n"
- "&%%(and (diary-cyclic 14 19 9 2003) (diary-block 19 9 2003 31 10 2003)) 09:00-11:30 rrule count bi-weekly 3 times\n"
- "&%%(and (diary-cyclic 14 9 19 2003) (diary-block 9 19 2003 10 31 2003)) 09:00-11:30 rrule count bi-weekly 3 times\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count monthly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;INTERVAL=1;COUNT=5
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 1 19)) 09:00-11:30 rrule count monthly\n"
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 1 2004)) 09:00-11:30 rrule count monthly\n"
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 1 19 2004)) 09:00-11:30 rrule count monthly\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count every second month
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=5
-"
- "&%%(and (diary-date t t 19) (diary-block 2003 9 19 2004 5 19)) 09:00-11:30 rrule count every second month\n" ;FIXME
- "&%%(and (diary-date 19 t t) (diary-block 19 9 2003 19 5 2004)) 09:00-11:30 rrule count every second month\n" ;FIXME
- "&%%(and (diary-date t 19 t) (diary-block 9 19 2003 5 19 2004)) 09:00-11:30 rrule count every second month\n") ;FIXME
- (icalendar-tests--test-import
- "SUMMARY:rrule count yearly
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=1;COUNT=5
-"
- "&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2007 9 19)) 09:00-11:30 rrule count yearly\n"
- "&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2007)) 09:00-11:30 rrule count yearly\n"
- "&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2007)) 09:00-11:30 rrule count yearly\n")
- (icalendar-tests--test-import
- "SUMMARY:rrule count every second year
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000
-RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=5
-"
- "&%%(and (diary-date t 9 19) (diary-block 2003 9 19 2011 9 19)) 09:00-11:30 rrule count every second year\n" ;FIXME!!!
- "&%%(and (diary-date 19 9 t) (diary-block 19 9 2003 19 9 2011)) 09:00-11:30 rrule count every second year\n" ;FIXME!!!
- "&%%(and (diary-date 9 19 t) (diary-block 9 19 2003 9 19 2011)) 09:00-11:30 rrule count every second year\n") ;FIXME!!!
-)
+ (icalendar-tests--test-import "import-rrule-daily.ics"
+ "import-rrule-daily.diary-iso"
+ "import-rrule-daily.diary-european"
+ "import-rrule-daily.diary-american")
+ (icalendar-tests--test-import "import-rrule-daily-two-day.ics"
+ "import-rrule-daily-two-day.diary-iso"
+ "import-rrule-daily-two-day.diary-european"
+ "import-rrule-daily-two-day.diary-american")
+ (icalendar-tests--test-import "import-rrule-daily-with-exceptions.ics"
+ "import-rrule-daily-with-exceptions.diary-iso"
+ "import-rrule-daily-with-exceptions.diary-european"
+ "import-rrule-daily-with-exceptions.diary-american")
+ (icalendar-tests--test-import "import-rrule-weekly.ics"
+ "import-rrule-weekly.diary-iso"
+ "import-rrule-weekly.diary-european"
+ "import-rrule-weekly.diary-american")
+ (icalendar-tests--test-import "import-rrule-monthly-no-end.ics"
+ "import-rrule-monthly-no-end.diary-iso"
+ "import-rrule-monthly-no-end.diary-european"
+ "import-rrule-monthly-no-end.diary-american")
+ (icalendar-tests--test-import "import-rrule-monthly-with-end.ics"
+ "import-rrule-monthly-with-end.diary-iso"
+ "import-rrule-monthly-with-end.diary-european"
+ "import-rrule-monthly-with-end.diary-american")
+ (icalendar-tests--test-import "import-rrule-anniversary.ics"
+ "import-rrule-anniversary.diary-iso"
+ "import-rrule-anniversary.diary-european"
+ "import-rrule-anniversary.diary-american")
+ (icalendar-tests--test-import "import-rrule-yearly.ics"
+ "import-rrule-yearly.diary-iso"
+ "import-rrule-yearly.diary-european"
+ "import-rrule-yearly.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-daily-short.ics"
+ "import-rrule-count-daily-short.diary-iso"
+ "import-rrule-count-daily-short.diary-european"
+ "import-rrule-count-daily-short.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-daily-long.ics"
+ "import-rrule-count-daily-long.diary-iso"
+ "import-rrule-count-daily-long.diary-european"
+ "import-rrule-count-daily-long.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-monthly.ics"
+ "import-rrule-count-monthly.diary-iso"
+ "import-rrule-count-monthly.diary-european"
+ "import-rrule-count-monthly.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-every-second-month.ics"
+ "import-rrule-count-every-second-month.diary-iso"
+ "import-rrule-count-every-second-month.diary-european"
+ "import-rrule-count-every-second-month.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-yearly.ics"
+ "import-rrule-count-yearly.diary-iso"
+ "import-rrule-count-yearly.diary-european"
+ "import-rrule-count-yearly.diary-american")
+ (icalendar-tests--test-import "import-rrule-count-every-second-year.ics"
+ "import-rrule-count-every-second-year.diary-iso"
+ "import-rrule-count-every-second-year.diary-european"
+ "import-rrule-count-every-second-year.diary-american")
+ )
(ert-deftest icalendar-import-duration ()
- ;; duration
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20050217
-SUMMARY:duration
-DURATION:P7D
-"
- "&%%(and (diary-block 2005 2 17 2005 2 23)) duration\n"
- "&%%(and (diary-block 17 2 2005 23 2 2005)) duration\n"
- "&%%(and (diary-block 2 17 2005 2 23 2005)) duration\n")
- (icalendar-tests--test-import
- "UID:20041127T183329Z-18215-1001-4536-49109@andromeda
-DTSTAMP:20041127T183315Z
-LAST-MODIFIED:20041127T183329
-SUMMARY:Urlaub
-DTSTART;VALUE=DATE:20011221
-DTEND;VALUE=DATE:20011221
-RRULE:FREQ=DAILY;UNTIL=20011229;INTERVAL=1;WKST=SU
-CLASS:PUBLIC
-SEQUENCE:1
-CREATED:20041127T183329
-"
- "&%%(and (diary-cyclic 1 2001 12 21) (diary-block 2001 12 21 2001 12 29)) Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
- "&%%(and (diary-cyclic 1 21 12 2001) (diary-block 21 12 2001 29 12 2001)) Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"
- "&%%(and (diary-cyclic 1 12 21 2001) (diary-block 12 21 2001 12 29 2001)) Urlaub
- Class: PUBLIC
- UID: 20041127T183329Z-18215-1001-4536-49109@andromeda\n"))
+ (icalendar-tests--test-import "import-duration.ics"
+ "import-duration.diary-iso"
+ "import-duration.diary-european"
+ "import-duration.diary-american")
+ ;; duration-2: this is actually an rrule test
+ (icalendar-tests--test-import "import-duration-2.ics"
+ "import-duration-2.diary-iso"
+ "import-duration-2.diary-european"
+ "import-duration-2.diary-american"))
(ert-deftest icalendar-import-bug-6766 ()
;;bug#6766 -- multiple byday values in a weekly rrule
- (icalendar-tests--test-import
-"CLASS:PUBLIC
-DTEND;TZID=America/New_York:20100421T120000
-DTSTAMP:20100525T141214Z
-DTSTART;TZID=America/New_York:20100421T113000
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,TH,FR
-SEQUENCE:1
-STATUS:CONFIRMED
-SUMMARY:Scrum
-TRANSP:OPAQUE
-UID:8814e3f9-7482-408f-996c-3bfe486a1262
-END:VEVENT
-BEGIN:VEVENT
-CLASS:PUBLIC
-DTSTAMP:20100525T141214Z
-DTSTART;VALUE=DATE:20100422
-DTEND;VALUE=DATE:20100423
-RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,TH
-SEQUENCE:1
-SUMMARY:Tues + Thurs thinking
-TRANSP:OPAQUE
-UID:8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 2010 4 21)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 2010 4 22)) Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 21 4 2010)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 22 4 2010)) Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"
-"&%%(and (memq (calendar-day-of-week date) '(1 3 4 5)) (diary-cyclic 1 4 21 2010)) 11:30-12:00 Scrum
- Status: CONFIRMED
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1262
-&%%(and (memq (calendar-day-of-week date) '(2 4)) (diary-cyclic 1 4 22 2010)) Tues + Thurs thinking
- Class: PUBLIC
- UID: 8814e3f9-7482-408f-996c-3bfe486a1263
-"))
+ (icalendar-tests--test-import "import-bug-6766.ics"
+ "import-bug-6766.diary-iso"
+ "import-bug-6766.diary-european"
+ "import-bug-6766.diary-american"))
(ert-deftest icalendar-import-bug-24199 ()
;;bug#24199 -- monthly rule with byday-clause
- (icalendar-tests--test-import
-"
-SUMMARY:Summary
-DESCRIPTION:Desc
-LOCATION:Loc
-DTSTART:20151202T124600
-DTEND:20151202T160000
-RRULE:FREQ=MONTHLY;BYDAY=1WE;INTERVAL=1
-EXDATE:20160106T114600Z
-EXDATE:20160203T114600Z
-EXDATE:20160302T114600Z
-EXDATE:20160504T104600Z
-EXDATE:20160601T104600Z
-CLASS:DEFAULT
-TRANSP:OPAQUE
-BEGIN:VALARM
-ACTION:DISPLAY
-TRIGGER;VALUE=DURATION:-PT3H
-END:VALARM
-LAST-MODIFIED:20160805T191040Z
-UID:9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 2016 1 6)) (not (diary-date 2016 2 3)) (not (diary-date 2016 3 2)) (not (diary-date 2016 5 4)) (not (diary-date 2016 6 1)) (diary-float t 3 1) (diary-block 2015 12 2 9999 1 1)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 6 1 2016)) (not (diary-date 3 2 2016)) (not (diary-date 2 3 2016)) (not (diary-date 4 5 2016)) (not (diary-date 1 6 2016)) (diary-float t 3 1) (diary-block 2 12 2015 1 1 9999)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-"&%%(and (not (diary-date 1 6 2016)) (not (diary-date 2 3 2016)) (not (diary-date 3 2 2016)) (not (diary-date 5 4 2016)) (not (diary-date 6 1 2016)) (diary-float t 3 1) (diary-block 12 2 2015 1 1 9999)) 12:46-16:00 Summary
- Desc: Desc
- Location: Loc
- Class: DEFAULT
- UID: 9188710a-08a7-4061-bae3-d4cf4972599a
-"
-))
+ (icalendar-tests--test-import "import-bug-24199.ics"
+ "import-bug-24199.diary-iso"
+ "import-bug-24199.diary-european"
+ "import-bug-24199.diary-american"))
(ert-deftest icalendar-import-bug-33277 ()
;;bug#33277 -- start time equals end time
- (icalendar-tests--test-import
- "DTSTART:20181105T200000Z
-DTSTAMP:20181105T181652Z
-DESCRIPTION:
-LAST-MODIFIED:20181105T181646Z
-LOCATION:
-SEQUENCE:0
-SUMMARY:event with same start/end time
-TRANSP:OPAQUE
-"
-
- "&2018/11/5 21:00 event with same start/end time\n"
- "&5/11/2018 21:00 event with same start/end time\n"
- "&11/5/2018 21:00 event with same start/end time\n"
- ))
+ (icalendar-tests--test-import "import-bug-33277.ics"
+ "import-bug-33277.diary-iso"
+ "import-bug-33277.diary-european"
+ "import-bug-33277.diary-american"))
(ert-deftest icalendar-import-multiple-vcalendars ()
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20110723
-SUMMARY:event-1
-"
- "&2011/7/23 event-1\n"
- "&23/7/2011 event-1\n"
- "&7/23/2011 event-1\n")
-
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0\nBEGIN:VEVENT
-DTSTART;VALUE=DATE:20110723
-SUMMARY:event-1
-END:VEVENT
-END:VCALENDAR
-BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110724
-SUMMARY:event-2
-END:VEVENT
-END:VCALENDAR
-BEGIN:VCALENDAR
-PRODID:-//Emacs//NONSGML icalendar.el//EN
-VERSION:2.0
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110725
-SUMMARY:event-3a
-END:VEVENT
-BEGIN:VEVENT
-DTSTART;VALUE=DATE:20110725
-SUMMARY:event-3b
-END:VEVENT
-END:VCALENDAR
-"
- "&2011/7/23 event-1\n&2011/7/24 event-2\n&2011/7/25 event-3a\n&2011/7/25 event-3b\n"
- "&23/7/2011 event-1\n&24/7/2011 event-2\n&25/7/2011 event-3a\n&25/7/2011 event-3b\n"
- "&7/23/2011 event-1\n&7/24/2011 event-2\n&7/25/2011 event-3a\n&7/25/2011 event-3b\n"))
+ (icalendar-tests--test-import "import-multiple-vcalendars.ics"
+ "import-multiple-vcalendars.diary-iso"
+ "import-multiple-vcalendars.diary-european"
+ "import-multiple-vcalendars.diary-american"))
(ert-deftest icalendar-import-with-uid ()
"Perform import test with uid."
- (icalendar-tests--test-import
- "UID:1234567890uid
-SUMMARY:non-recurring
-DTSTART;VALUE=DATE-TIME:20030919T090000
-DTEND;VALUE=DATE-TIME:20030919T113000"
- "&2003/9/19 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
- "&19/9/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"
- "&9/19/2003 09:00-11:30 non-recurring\n UID: 1234567890uid\n"))
+ (icalendar-tests--test-import "import-with-uid.ics"
+ "import-with-uid.diary-iso"
+ "import-with-uid.diary-european"
+ "import-with-uid.diary-american"))
(ert-deftest icalendar-import-with-timezone ()
;; This is known to fail on MS-Windows, because the test assumes
@@ -1499,42 +1195,13 @@ DTEND;VALUE=DATE-TIME:20030919T113000"
:failed
:passed)
;; bug#11473
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-BEGIN:VTIMEZONE
-TZID:fictional, nonexistent, arbitrary
-BEGIN:STANDARD
-DTSTART:20100101T000000
-TZOFFSETFROM:+0200
-TZOFFSETTO:-0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=01
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:20101201T000000
-TZOFFSETFROM:-0200
-TZOFFSETTO:+0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-SUMMARY:standardtime
-DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20120115T120000
-DTEND;TZID=\"fictional, nonexistent, arbitrary\":20120115T123000
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY:daylightsavingtime
-DTSTART;TZID=\"fictional, nonexistent, arbitrary\":20121215T120000
-DTEND;TZID=\"fictional, nonexistent, arbitrary\":20121215T123000
-END:VEVENT
-END:VCALENDAR"
- ;; "standardtime" begins first sunday in january and is 4 hours behind CET
- ;; "daylightsavingtime" begins first sunday in november and is 1 hour before CET
- "&2012/1/15 15:00-15:30 standardtime
-&2012/12/15 11:00-11:30 daylightsavingtime
-"
- nil
- nil)
- )
+ ;; "standardtime" begins first sunday in january and is 4 hours behind CET
+ ;; "daylightsavingtime" begins first sunday in november and is 1 hour before CET
+ (icalendar-tests--test-import "import-with-timezone.ics"
+ "import-with-timezone.diary-iso"
+ nil
+ nil))
+
;; ======================================================================
;; Cycle
;; ======================================================================
@@ -1632,237 +1299,27 @@ SUMMARY:and diary-anniversary
:failed
:passed)
;; 2003-05-29
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft CDO for Microsoft Exchange
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:Kolkata, Chennai, Mumbai, New Delhi
-X-MICROSOFT-CDO-TZID:23
-BEGIN:STANDARD
-DTSTART:16010101T000000
-TZOFFSETFROM:+0530
-TZOFFSETTO:+0530
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T000000
-TZOFFSETFROM:+0530
-TZOFFSETTO:+0530
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20030509T043439Z
-DTSTART;TZID=\"Kolkata, Chennai, Mumbai, New Delhi\":20030509T103000
-SUMMARY:On-Site Interview
-UID:040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000
- 010000000DB823520692542408ED02D7023F9DFF9
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Xxxxx
- xxx Xxxxxxxxxxxx\":MAILTO:xxxxxxxx@xxxxxxx.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Yyyyyyy Y
- yyyy\":MAILTO:yyyyyyy@yyyyyyy.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Zzzz Zzzz
- zz\":MAILTO:zzzzzz@zzzzzzz.com
-ORGANIZER;CN=\"Aaaaaa Aaaaa\":MAILTO:aaaaaaa@aaaaaaa.com
-LOCATION:Cccc
-DTEND;TZID=\"Kolkata, Chennai, Mumbai, New Delhi\":20030509T153000
-DESCRIPTION:10:30am - Blah
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030509T043439Z
-LAST-MODIFIED:20030509T043459Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:126441427
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
- nil
- "&9/5/2003 07:00-12:00 On-Site Interview
- Desc: 10:30am - Blah
- Location: Cccc
- Organizer: MAILTO:aaaaaaa@aaaaaaa.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
-"
- "&5/9/2003 07:00-12:00 On-Site Interview
- Desc: 10:30am - Blah
- Location: Cccc
- Organizer: MAILTO:aaaaaaa@aaaaaaa.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E0080000000080B6DE661216C301000000000000000010000000DB823520692542408ED02D7023F9DFF9
-")
+ (icalendar-tests--test-import "import-real-world-2003-05-29.ics"
+ nil
+ "import-real-world-2003-05-29.diary-european"
+ "import-real-world-2003-05-29.diary-american")
;; created with http://apps.marudot.com/ical/
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-VERSION:2.0
-PRODID:-//www.marudot.com//iCal Event Maker
-X-WR-CALNAME:Test
-CALSCALE:GREGORIAN
-BEGIN:VTIMEZONE
-TZID:Asia/Tehran
-TZURL:http://tzurl.org/zoneinfo-outlook/Asia/Tehran
-X-LIC-LOCATION:Asia/Tehran
-BEGIN:STANDARD
-TZOFFSETFROM:+0330
-TZOFFSETTO:+0330
-TZNAME:IRST
-DTSTART:19700101T000000
-END:STANDARD
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20141116T171439Z
-UID:20141116T171439Z-678877132@marudot.com
-DTSTART;TZID=\"Asia/Tehran\":20141116T070000
-DTEND;TZID=\"Asia/Tehran\":20141116T080000
-SUMMARY:NoDST
-DESCRIPTION:Test event from timezone without DST
-LOCATION:Everywhere
-END:VEVENT
-END:VCALENDAR"
- nil
- "&16/11/2014 04:30-05:30 NoDST
- Desc: Test event from timezone without DST
- Location: Everywhere
- UID: 20141116T171439Z-678877132@marudot.com
-"
- "&11/16/2014 04:30-05:30 NoDST
- Desc: Test event from timezone without DST
- Location: Everywhere
- UID: 20141116T171439Z-678877132@marudot.com
-")
-
+ (icalendar-tests--test-import "import-real-world-no-dst.ics"
+ nil
+ "import-real-world-no-dst.diary-european"
+ "import-real-world-no-dst.diary-american")
;; 2003-06-18 a
- (icalendar-tests--test-import
- "DTSTAMP:20030618T195512Z
-DTSTART;TZID=\"Mountain Time (US & Canada)\":20030623T110000
-SUMMARY:Dress Rehearsal for XXXX-XXXX
-UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
- 0100000007C3A6D65EE726E40B7F3D69A23BD567E
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"AAAAA,AAA
- AA (A-AAAAAAA,ex1)\":MAILTO:aaaaa_aaaaa@aaaaa.com
-ORGANIZER;CN=\"ABCD,TECHTRAINING
- (A-Americas,exgen1)\":MAILTO:xxx@xxxxx.com
-LOCATION:555 or TN 555-5555 ID 5555 & NochWas (see below)
-DTEND;TZID=\"Mountain Time (US & Canada)\":20030623T120000
-DESCRIPTION:753 Zeichen hier radiert
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030618T195518Z
-LAST-MODIFIED:20030618T195527Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:1022519251
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM"
- nil
- "&23/6/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
- Desc: 753 Zeichen hier radiert
- Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
- Organizer: MAILTO:xxx@xxxxx.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-"
- "&6/23/2003 11:00-12:00 Dress Rehearsal for XXXX-XXXX
- Desc: 753 Zeichen hier radiert
- Location: 555 or TN 555-5555 ID 5555 & NochWas (see below)
- Organizer: MAILTO:xxx@xxxxx.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-")
+ (icalendar-tests--test-import "import-real-world-2003-06-18a.ics"
+ nil
+ "import-real-world-2003-06-18a.diary-european"
+ "import-real-world-2003-06-18a.diary-american")
;; 2003-06-18 b -- uses timezone
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft CDO for Microsoft Exchange
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:Mountain Time (US & Canada)
-X-MICROSOFT-CDO-TZID:12
-BEGIN:STANDARD
-DTSTART:16010101T020000
-TZOFFSETFROM:-0600
-TZOFFSETTO:-0700
-RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=10;BYDAY=-1SU
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T020000
-TZOFFSETFROM:-0700
-TZOFFSETTO:-0600
-RRULE:FREQ=YEARLY;WKST=MO;INTERVAL=1;BYMONTH=4;BYDAY=1SU
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-DTSTAMP:20030618T230323Z
-DTSTART;TZID=\"Mountain Time (US & Canada)\":20030623T090000
-SUMMARY:Updated: Dress Rehearsal for ABC01-15
-UID:040000008200E00074C5B7101A82E00800000000608AA7DA9835C301000000000000000
- 0100000007C3A6D65EE726E40B7F3D69A23BD567E
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;X-REPLYTIME=20030618T20
- 0700Z;RSVP=TRUE;CN=\"AAAAA,AAAAAA
-\(A-AAAAAAA,ex1)\":MAILTO:aaaaaa_aaaaa@aaaaa
- .com
-ORGANIZER;CN=\"ABCD,TECHTRAINING
-\(A-Americas,exgen1)\":MAILTO:bbb@bbbbb.com
-LOCATION:123 or TN 123-1234 ID abcd & SonstWo (see below)
-DTEND;TZID=\"Mountain Time (US & Canada)\":20030623T100000
-DESCRIPTION:Viele Zeichen standen hier früher
-SEQUENCE:0
-PRIORITY:5
-CLASS:
-CREATED:20030618T230326Z
-LAST-MODIFIED:20030618T230335Z
-STATUS:CONFIRMED
-TRANSP:OPAQUE
-X-MICROSOFT-CDO-BUSYSTATUS:BUSY
-X-MICROSOFT-CDO-INSTTYPE:0
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-OWNERAPPTID:1022519251
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT00H15M00S
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
- nil
- "&23/6/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
- Desc: Viele Zeichen standen hier früher
- Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
- Organizer: MAILTO:bbb@bbbbb.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-"
- "&6/23/2003 17:00-18:00 Updated: Dress Rehearsal for ABC01-15
- Desc: Viele Zeichen standen hier früher
- Location: 123 or TN 123-1234 ID abcd & SonstWo (see below)
- Organizer: MAILTO:bbb@bbbbb.com
- Status: CONFIRMED
- UID: 040000008200E00074C5B7101A82E00800000000608AA7DA9835C3010000000000000000100000007C3A6D65EE726E40B7F3D69A23BD567E
-")
+ (icalendar-tests--test-import "import-real-world-2003-06-18b.ics"
+ nil
+ "import-real-world-2003-06-18b.diary-european"
+ "import-real-world-2003-06-18b.diary-american")
;; export 2004-10-28 block entries
(icalendar-tests--test-export
nil
@@ -2078,169 +1535,10 @@ DTEND;VALUE=DATE-TIME:20041012T150000
SUMMARY:Tue: [2004-10-12] q1")
;; 2004-11-19
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-VERSION
- :2.0
-PRODID
- :-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN
-BEGIN:VEVENT
-SUMMARY
- :Jjjjj & Wwwww
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T140000
-DTEND
- :20041123T143000
-DTSTAMP
- :20041118T013430Z
-LAST-MODIFIED
- :20041118T013640Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :BB Aaaaaaaa Bbbbb
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T144500
-DTEND
- :20041123T154500
-DTSTAMP
- :20041118T013641Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Hhhhhhhh
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- :20041123T110000
-DTEND
- :20041123T120000
-DTSTAMP
- :20041118T013831Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :MMM Aaaaaaaaa
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-X-MOZILLA-RECUR-DEFAULT-INTERVAL
- :2
-RRULE
- :FREQ=WEEKLY;INTERVAL=2;BYDAY=FR
-DTSTART
- :20041112T140000
-DTEND
- :20041112T183000
-DTSTAMP
- :20041118T014117Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Rrrr/Cccccc ii Aaaaaaaa
-DESCRIPTION
- :Vvvvv Rrrr aaa Cccccc
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-DTSTART
- ;VALUE=DATE
- :20041119
-DTEND
- ;VALUE=DATE
- :20041120
-DTSTAMP
- :20041118T013107Z
-LAST-MODIFIED
- :20041118T014203Z
-END:VEVENT
-BEGIN:VEVENT
-SUMMARY
- :Wwww aa hhhh
-STATUS
- :TENTATIVE
-CLASS
- :PRIVATE
-X-MOZILLA-ALARM-DEFAULT-LENGTH
- :0
-RRULE
- :FREQ=WEEKLY;INTERVAL=1;BYDAY=MO
-DTSTART
- ;VALUE=DATE
- :20041101
-DTEND
- ;VALUE=DATE
- :20041102
-DTSTAMP
- :20041118T014045Z
-LAST-MODIFIED
- :20041118T023846Z
-END:VEVENT
-END:VCALENDAR
-"
- nil
- "&23/11/2004 14:00-14:30 Jjjjj & Wwwww
- Status: TENTATIVE
- Class: PRIVATE
-&23/11/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
- Status: TENTATIVE
- Class: PRIVATE
-&23/11/2004 11:00-12:00 Hhhhhhhh
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 14 12 11 2004)) 14:00-18:30 MMM Aaaaaaaaa
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-block 19 11 2004 19 11 2004)) Rrrr/Cccccc ii Aaaaaaaa
- Desc: Vvvvv Rrrr aaa Cccccc
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 7 1 11 2004)) Wwww aa hhhh
- Status: TENTATIVE
- Class: PRIVATE
-"
- "&11/23/2004 14:00-14:30 Jjjjj & Wwwww
- Status: TENTATIVE
- Class: PRIVATE
-&11/23/2004 14:45-15:45 BB Aaaaaaaa Bbbbb
- Status: TENTATIVE
- Class: PRIVATE
-&11/23/2004 11:00-12:00 Hhhhhhhh
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 14 11 12 2004)) 14:00-18:30 MMM Aaaaaaaaa
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-block 11 19 2004 11 19 2004)) Rrrr/Cccccc ii Aaaaaaaa
- Desc: Vvvvv Rrrr aaa Cccccc
- Status: TENTATIVE
- Class: PRIVATE
-&%%(and (diary-cyclic 7 11 1 2004)) Wwww aa hhhh
- Status: TENTATIVE
- Class: PRIVATE
-")
+ (icalendar-tests--test-import "import-real-world-2004-11-19.ics"
+ nil
+ "import-real-world-2004-11-19.diary-european"
+ "import-real-world-2004-11-19.diary-american")
;; 2004-09-09 pg
(icalendar-tests--test-export
@@ -2270,53 +1568,16 @@ DTEND;VALUE=DATE-TIME:20041102T163000
SUMMARY:Zahnarzt")
;; 2005-02-07 lt
- (icalendar-tests--test-import
- "UID
- :b60d398e-1dd1-11b2-a159-cf8cb05139f4
-SUMMARY
- :Waitangi Day
-DESCRIPTION
- :abcdef
-CATEGORIES
- :Public Holiday
-STATUS
- :CONFIRMED
-CLASS
- :PRIVATE
-DTSTART
- ;VALUE=DATE
- :20050206
-DTEND
- ;VALUE=DATE
- :20050207
-DTSTAMP
- :20050128T011209Z"
- nil
- "&%%(and (diary-block 6 2 2005 6 2 2005)) Waitangi Day
- Desc: abcdef
- Status: CONFIRMED
- Class: PRIVATE
- UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
-"
- "&%%(and (diary-block 2 6 2005 2 6 2005)) Waitangi Day
- Desc: abcdef
- Status: CONFIRMED
- Class: PRIVATE
- UID: b60d398e-1dd1-11b2-a159-cf8cb05139f4
-")
+ (icalendar-tests--test-import "import-real-world-2005-02-07.ics"
+ nil
+ "import-real-world-2005-02-07.diary-european"
+ "import-real-world-2005-02-07.diary-american")
;; 2005-03-01 lt
- (icalendar-tests--test-import
- "DTSTART;VALUE=DATE:20050217
-SUMMARY:Hhhhhh Aaaaa ii Aaaaaaaa
-UID:6AFA7558-6994-11D9-8A3A-000A95A0E830-RID
-DTSTAMP:20050118T210335Z
-DURATION:P7D"
- nil
- "&%%(and (diary-block 17 2 2005 23 2 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
- UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n"
- "&%%(and (diary-block 2 17 2005 2 23 2005)) Hhhhhh Aaaaa ii Aaaaaaaa
- UID: 6AFA7558-6994-11D9-8A3A-000A95A0E830-RID\n")
+ (icalendar-tests--test-import "import-real-world-2005-03-01.ics"
+ nil
+ "import-real-world-2005-03-01.diary-european"
+ "import-real-world-2005-03-01.diary-american")
;; 2005-03-23 lt
(icalendar-tests--test-export
@@ -2343,132 +1604,24 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30
")
;; bug#11473
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR
-METHOD:REQUEST
-PRODID:Microsoft Exchange Server 2007
-VERSION:2.0
-BEGIN:VTIMEZONE
-TZID:(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
-BEGIN:STANDARD
-DTSTART:16010101T030000
-TZOFFSETFROM:+0200
-TZOFFSETTO:+0100
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10
-END:STANDARD
-BEGIN:DAYLIGHT
-DTSTART:16010101T020000
-TZOFFSETFROM:+0100
-TZOFFSETTO:+0200
-RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3
-END:DAYLIGHT
-END:VTIMEZONE
-BEGIN:VEVENT
-ORGANIZER;CN=\"A. Luser\":MAILTO:a.luser@foo.com
-ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=\"Luser, Oth
- er\":MAILTO:other.luser@foo.com
-DESCRIPTION;LANGUAGE=en-US:\nWhassup?\n\n
-SUMMARY;LANGUAGE=en-US:Query
-DTSTART;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\"
- :20120515T150000
-DTEND;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna\":2
- 0120515T153000
-UID:040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000
- 010000000575268034ECDB649A15349B1BF240F15
-RECURRENCE-ID;TZID=\"(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, V
- ienna\":20120515T170000
-CLASS:PUBLIC
-PRIORITY:5
-DTSTAMP:20120514T153645Z
-TRANSP:OPAQUE
-STATUS:CONFIRMED
-SEQUENCE:15
-LOCATION;LANGUAGE=en-US:phone
-X-MICROSOFT-CDO-APPT-SEQUENCE:15
-X-MICROSOFT-CDO-OWNERAPPTID:1907632092
-X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE
-X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY
-X-MICROSOFT-CDO-ALLDAYEVENT:FALSE
-X-MICROSOFT-CDO-IMPORTANCE:1
-X-MICROSOFT-CDO-INSTTYPE:3
-BEGIN:VALARM
-ACTION:DISPLAY
-DESCRIPTION:REMINDER
-TRIGGER;RELATED=START:-PT15M
-END:VALARM
-END:VEVENT
-END:VCALENDAR"
- nil
- "&15/5/2012 15:00-15:30 Query
- Location: phone
- Organizer: MAILTO:a.luser@foo.com
- Status: CONFIRMED
- Class: PUBLIC
- UID: 040000008200E00074C5B7101A82E0080000000020FFAED0CFEFCC01000000000000000010000000575268034ECDB649A15349B1BF240F15
-" nil)
+ (icalendar-tests--test-import "import-bug-11473.ics"
+ nil
+ "import-bug-11473.diary-european"
+ nil)
;; 2015-12-05, mixed line endings and empty lines, see Bug#22092.
- (icalendar-tests--test-import
- "BEGIN:VCALENDAR\r
-PRODID:-//www.norwegian.no//iCalendar MIMEDIR//EN\r
-VERSION:2.0\r
-METHOD:REQUEST\r
-BEGIN:VEVENT\r
-UID:RFCALITEM1\r
-SEQUENCE:1512040950\r
-DTSTAMP:20141204T095043Z\r
-ORGANIZER:noreply@norwegian.no\r
-DTSTART:20141208T173000Z\r
-
-DTEND:20141208T215500Z\r
-
-LOCATION:Stavanger-Sola\r
-
-DESCRIPTION:Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390\r
-
-X-ALT-DESC;FMTTYPE=text/html:Reisereferanse
-SUMMARY:Norwegian til Tromsoe-Langnes -\r
-
-CATEGORIES:Appointment\r
-
-
-PRIORITY:5\r
-
-CLASS:PUBLIC\r
-
-TRANSP:OPAQUE\r
-END:VEVENT\r
-END:VCALENDAR
-"
-"&2014/12/8 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-"&8/12/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-"&12/8/2014 18:30-22:55 Norwegian til Tromsoe-Langnes -
- Desc: Fly med Norwegian, reservasjon. Fra Stavanger til Tromsø 8. des 2014 18:30, DY545Fly med Norwegian, reservasjon . Fra Stavanger til Tromsø 8. des 2014 21:00, DY390
- Location: Stavanger-Sola
- Organizer: noreply@norwegian.no
- Class: PUBLIC
- UID: RFCALITEM1
-"
-)
- )
+ (icalendar-tests--test-import "import-bug-22092.ics"
+ "import-bug-22092.diary-iso"
+ "import-bug-22092.diary-european"
+ "import-bug-22092.diary-american"))
(defun icalendar-test--format (string &optional day zone)
+ "Decode and format STRING with DAY and ZONE."
(let ((time (icalendar--decode-isodatetime string day zone)))
(format-time-string "%FT%T%z" (encode-time time) 0)))
(defun icalendar-tests--decode-isodatetime (_ical-string)
+ "Test icalendar--decode-isodatetime."
(should (equal (icalendar-test--format "20040917T050910-0200")
"2004-09-17T03:09:10+0000"))
(should (equal (icalendar-test--format "20040917T050910")
commit 997ebf91dd6b1f586af44843c37aaad4708011c3
Author: Stefan Kangas
Date: Thu Oct 22 16:34:11 2020 +0200
Use lexical-binding in time-date.el and expand tests
* lisp/calendar/time-date.el: Use lexical-binding.
* test/lisp/calendar/time-date-tests.el
(test-obsolete-with-decoded-time-value)
(test-obsolete-encode-time-value, test-format-seconds)
(test-days-to-time, test-seconds-to-string): New tests.
(test-days-in-month, test-time-since, test-time-decoded-period):
Expand test with a few more values.
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 638d8c1f88..f60c9c2ffd 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -1,4 +1,4 @@
-;;; time-date.el --- Date and time handling functions
+;;; time-date.el --- Date and time handling functions -*- lexical-binding: t -*-
;; Copyright (C) 1998-2020 Free Software Foundation, Inc.
diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el
index 233d43cd01..3f8954a8ff 100644
--- a/test/lisp/calendar/time-date-tests.el
+++ b/test/lisp/calendar/time-date-tests.el
@@ -22,19 +22,67 @@
(require 'ert)
(require 'time-date)
+(ert-deftest test-obsolete-with-decoded-time-value ()
+ (with-suppressed-warnings ((obsolete with-decoded-time-value))
+ (with-decoded-time-value ((high low micro pico type '(1 2 3 4 5 6 8 8)))
+ (should (equal (list high low micro pico type) '(1 2 3 4 3))))))
+
+(ert-deftest test-obsolete-encode-time-value ()
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 0))
+ '(1 . 2)))
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 1))
+ '(1 2)))
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 2))
+ '(1 2 3)))
+ (should (equal (with-suppressed-warnings ((obsolete encode-time-value))
+ (encode-time-value 1 2 3 4 3))
+ '(1 2 3 4))))
+
(ert-deftest test-leap-year ()
(should-not (date-leap-year-p 1999))
(should-not (date-leap-year-p 1900))
(should (date-leap-year-p 2000))
(should (date-leap-year-p 2004)))
+(ert-deftest test-days-to-time ()
+ (should (equal (days-to-time 0) '(0 0)))
+ (should (equal (days-to-time 1) '(1 20864)))
+ (should (equal (days-to-time 999) '(1317 2688)))
+ (should (equal (days-to-time 0.0) '(0 0 0 0)))
+ (should (equal (days-to-time 0.5) '(0 43200 0 0)))
+ (should (equal (days-to-time 1.0) '(1 20864 0 0)))
+ (should (equal (days-to-time 999.0) '(1317 2688 0 0))))
+
+(ert-deftest test-seconds-to-string ()
+ (should (equal (seconds-to-string 0) "0s"))
+ (should (equal (seconds-to-string 9) "9.00s"))
+ (should (equal (seconds-to-string 99) "99.00s"))
+ (should (equal (seconds-to-string 999) "16.65m"))
+ (should (equal (seconds-to-string 9999) "2.78h"))
+ (should (equal (seconds-to-string 99999) "27.78h"))
+ (should (equal (seconds-to-string 999999) "11.57d"))
+ (should (equal (seconds-to-string 9999999) "115.74d"))
+ (should (equal (seconds-to-string 99999999) "3.17y"))
+ (should (equal (seconds-to-string 999999999) "31.69y")))
+
(ert-deftest test-days-in-month ()
(should (= (date-days-in-month 2004 2) 29))
(should (= (date-days-in-month 2004 3) 31))
+ (should (= (date-days-in-month 2019 2) 28))
+ (should (= (date-days-in-month 2020 12) 31))
(should-not (= (date-days-in-month 1900 3) 28))
+ (should-error (date-days-in-month 2020 0))
(should-error (date-days-in-month 2020 15))
(should-error (date-days-in-month 2020 'foo)))
+(ert-deftest test-format-seconds ()
+ (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %"))
+ (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %"))
+ (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) " 1 %")))
+
(ert-deftest test-ordinal ()
(should (equal (date-ordinal-to-time 2008 271)
'(nil nil nil 27 9 2008 nil nil nil)))
@@ -107,7 +155,8 @@
'(12 15 14 8 7 2019 1 t 7200)))))
(ert-deftest test-time-since ()
- (should (time-equal-p 0 (time-since nil))))
+ (should (time-equal-p 0 (time-since nil)))
+ (should (= (cadr (time-since (time-subtract (current-time) 1))) 1)))
(ert-deftest test-time-decoded-period ()
(should (equal (decoded-time-period '(nil nil 1 nil nil nil nil nil nil))
@@ -119,6 +168,7 @@
(should (equal (decoded-time-period '(0 0 0 1 0 0 nil nil nil)) 86400))
(should (equal (decoded-time-period '(0 0 0 0 1 0 nil nil nil)) 2592000))
(should (equal (decoded-time-period '(0 0 0 0 0 1 nil nil nil)) 31536000))
+ (should (equal (decoded-time-period '(1 2 3 4 5 6 nil nil nil)) 202532521))
(should (equal (decoded-time-period '((135 . 10) 0 0 0 0 0 nil nil nil))
13.5)))
commit 8dffe61a9c461506311027c99374246440bd97fe
Author: Mauro Aranda
Date: Thu Oct 22 16:55:03 2020 +0200
Make State button interaction less confusing
* lisp/cus-edit.el (custom-variable-current-value): New function.
(custom-variable-backup-value): Use it.
(custom-variable-set, custom-variable-mark-to-reset-standard): Check
that old value is different than the new one. If it is, make a
backup. This way, we avoid offering the Set to Backup Value
unnecesarily.
(custom-variable-reset-saved): Reset the variable-comment property for
the variable, to help custom-variable-state be more correct. Also
check if we should backup old value.
(custom-variable-state): If a variable was set to the standard value,
say its state is standard rather than set, which is more correct.
Getting the right variable state is important for menu options to be
enabled/disabled, and for displaying the right message to the user
(bug#12864).
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 510c6e3b4c..85c197b400 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -2789,7 +2789,9 @@ Possible return values are `standard', `saved', `set', `themed',
(and (equal value (eval (car tmp)))
(equal comment temp))
(error nil))
- 'set
+ (if (equal value (eval (car (get symbol 'standard-value))))
+ 'standard
+ 'set)
'changed))
((progn (setq tmp (get symbol 'theme-value))
(setq temp (get symbol 'saved-variable-comment))
@@ -2859,6 +2861,18 @@ otherwise."
(defun custom-variable-standard-value (widget)
(get (widget-value widget) 'standard-value))
+(defun custom-variable-current-value (widget)
+ "Return the current value of the variable edited by WIDGET.
+
+WIDGET should be a custom-variable widget."
+ (let* ((symbol (widget-value widget))
+ (get (or (get symbol 'custom-get) 'default-value))
+ (type (custom-variable-type symbol))
+ (conv (widget-convert type)))
+ (if (default-boundp symbol)
+ (funcall get symbol)
+ (widget-get conv :value))))
+
(defvar custom-variable-menu nil
"If non-nil, an alist of actions for the `custom-variable' widget.
@@ -2989,10 +3003,12 @@ Optional EVENT is the location for the menu."
(setq comment nil)
;; Make the comment invisible by hand if it's empty
(custom-comment-hide comment-widget))
- (custom-variable-backup-value widget)
+ (setq val (widget-value child))
+ (unless (equal (eval val) (custom-variable-current-value widget))
+ (custom-variable-backup-value widget))
(custom-push-theme 'theme-value symbol 'user
- 'set (custom-quote (widget-value child)))
- (funcall set symbol (eval (setq val (widget-value child))))
+ 'set (custom-quote val))
+ (funcall set symbol (eval val))
(put symbol 'customized-value (list val))
(put symbol 'variable-comment comment)
(put symbol 'customized-variable-comment comment))
@@ -3001,10 +3017,12 @@ Optional EVENT is the location for the menu."
(setq comment nil)
;; Make the comment invisible by hand if it's empty
(custom-comment-hide comment-widget))
- (custom-variable-backup-value widget)
+ (setq val (widget-value child))
+ (unless (equal val (custom-variable-current-value widget))
+ (custom-variable-backup-value widget))
(custom-push-theme 'theme-value symbol 'user
- 'set (custom-quote (widget-value child)))
- (funcall set symbol (setq val (widget-value child)))
+ 'set (custom-quote val))
+ (funcall set symbol val)
(put symbol 'customized-value (list (custom-quote val)))
(put symbol 'variable-comment comment)
(put symbol 'customized-variable-comment comment)))
@@ -3073,17 +3091,23 @@ before this operation becomes the backup value."
(let* ((symbol (widget-value widget))
(saved-value (get symbol 'saved-value))
(comment (get symbol 'saved-variable-comment))
+ (old-value (custom-variable-current-value widget))
value)
- (custom-variable-backup-value widget)
(if (not (or saved-value comment))
- ;; If there is no saved value, remove the setting.
- (custom-push-theme 'theme-value symbol 'user 'reset)
+ (progn
+ (setq value (car (get symbol 'standard-value)))
+ ;; If there is no saved value, remove the setting.
+ (custom-push-theme 'theme-value symbol 'user 'reset)
+ ;; And reset this property too.
+ (put symbol 'variable-comment nil))
(setq value (car-safe saved-value))
(custom-push-theme 'theme-value symbol 'user 'set value)
(put symbol 'variable-comment comment))
+ (unless (equal (eval value) old-value)
+ (custom-variable-backup-value widget))
(ignore-errors
(funcall (or (get symbol 'custom-set) #'set-default) symbol
- (eval (or value (car (get symbol 'standard-value))))))
+ (eval value)))
(put symbol 'customized-value nil)
(put symbol 'customized-variable-comment nil)
(widget-put widget :custom-state 'unknown)
@@ -3096,7 +3120,9 @@ If `custom-reset-standard-variables-list' is nil, save, reset and
redraw the widget immediately."
(let* ((symbol (widget-value widget)))
(if (get symbol 'standard-value)
- (custom-variable-backup-value widget)
+ (unless (equal (custom-variable-current-value widget)
+ (eval (car (get symbol 'standard-value))))
+ (custom-variable-backup-value widget))
(user-error "No standard setting known for %S" symbol))
(put symbol 'variable-comment nil)
(put symbol 'customized-value nil)
@@ -3133,13 +3159,8 @@ becomes the backup value, so you can get it again."
(defun custom-variable-backup-value (widget)
"Back up the current value for WIDGET's variable.
The backup value is kept in the car of the `backup-value' property."
- (let* ((symbol (widget-value widget))
- (get (or (get symbol 'custom-get) 'default-value))
- (type (custom-variable-type symbol))
- (conv (widget-convert type))
- (value (if (default-boundp symbol)
- (funcall get symbol)
- (widget-get conv :value))))
+ (let ((symbol (widget-value widget))
+ (value (custom-variable-current-value widget)))
(put symbol 'backup-value (list value))))
(defun custom-variable-reset-backup (widget)
commit d5fdb1b1f6335da2a1dd60430b7521910dacab68
Author: Robert Pluim
Date: Thu Oct 22 16:49:10 2020 +0200
; fix docstring typo in last commit
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 575821bdea..94aba5e5fb 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1051,8 +1051,8 @@ out of NAME."
(defcustom ffap-rfc-path "https://www.rfc-editor.org/in-notes/rfc%s.txt"
"A `format' string making a filename for RFC documents.
-This can be an URL, and ange-ftp or Tramp remote filename to
-download, or a local filename if you have full set of RFCs
+This can be an URL, an ange-ftp or Tramp remote filename to
+download, or a local filename if you have the full set of RFCs
locally. See also `ffap-rfc-directories'."
:type 'string
:version "28.1")
commit 5d152ed73754f3fcd8ce7e08bf1cfcf96e9656bb
Author: Lars Ingebrigtsen
Date: Thu Oct 22 15:36:59 2020 +0200
Use HTTP instead of Tramp for the ffap rfc path (and also fix it)
* lisp/ffap.el (ffap-rfc-path): Use an URL instead of an FTP tramp
file, since that's more widely supported (bug#41663).
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 2c1d3d5bd9..575821bdea 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1049,22 +1049,19 @@ out of NAME."
"/pub/gnu/emacs/elisp-archive/"))
(substring name 2))))
-(defcustom ffap-rfc-path
- (concat (ffap-host-to-filename "ftp.rfc-editor.org") "/in-notes/rfc%s.txt")
+(defcustom ffap-rfc-path "https://www.rfc-editor.org/in-notes/rfc%s.txt"
"A `format' string making a filename for RFC documents.
-This can be an ange-ftp or Tramp remote filename to download, or
-a local filename if you have full set of RFCs locally. See also
-`ffap-rfc-directories'."
+This can be an URL, and ange-ftp or Tramp remote filename to
+download, or a local filename if you have full set of RFCs
+locally. See also `ffap-rfc-directories'."
:type 'string
- :version "23.1"
- :group 'ffap)
+ :version "28.1")
(defcustom ffap-rfc-directories nil
"A list of directories to look for RFC files.
If a given RFC isn't in these then `ffap-rfc-path' is offered."
:type '(repeat directory)
- :version "23.1"
- :group 'ffap)
+ :version "23.1")
(defun ffap-rfc (name)
(let ((num (match-string 1 name)))
commit 45c1be62a1e92f3e688495880664a13d042e718c
Author: Lars Ingebrigtsen
Date: Thu Oct 22 15:20:04 2020 +0200
Comment JSX lines using JSX syntax
* lisp/progmodes/js.el (js-jsx--comment-region): New function
(bug#41696).
(js-jsx-mode): Use it.
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 5c50e2accd..f3cfbbb948 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -4656,8 +4656,19 @@ could set `js-jsx-syntax' to t in your init file, or in a
one of the aforementioned options instead of using this mode."
:group 'js
(js-jsx-enable)
+ (setq-local comment-region-function #'js-jsx--comment-region)
(js-use-syntactic-mode-name))
+(defun js-jsx--comment-region (beg end &optional arg)
+ (if (or (js-jsx--context)
+ (save-excursion
+ (skip-chars-forward " \t")
+ (js-jsx--looking-at-start-tag-p)))
+ (let ((comment-start "{/* ")
+ (comment-end " */}"))
+ (comment-region-default beg end arg))
+ (comment-region-default beg end arg)))
+
;;;###autoload (defalias 'javascript-mode 'js-mode)
(eval-after-load 'folding
commit 0d7d09b0ef1b3a939422d273be2fa348e8a148c8
Author: Stefan Kangas
Date: Wed Oct 21 18:23:38 2020 +0200
Test for error with multibyte strings in bindat.el
* test/lisp/emacs-lisp/bindat-tests.el
(bindat-test-pack/multibyte-string-fails)
(bindat-test-unpack/multibyte-string-fails): New tests.
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
index 14f95a8bf8..0fb1955695 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -1,4 +1,4 @@
-;;; bindat-tests.el --- tests for bindat.el -*- lexical-binding: t; -*-
+;;; bindat-tests.el --- tests for bindat.el -*- lexical-binding: t; coding: utf-8; -*-
;; Copyright (C) 2019-2020 Free Software Foundation, Inc.
@@ -94,7 +94,13 @@
(src-ip .
[192 168 1 101])
(dest-ip .
- [192 168 1 100]))))))
+ [192 168 1 100]))))))
+
+(ert-deftest bindat-test-pack/multibyte-string-fails ()
+ (should-error (bindat-pack nil nil (decode-coding-string "ö" 'utf-8))))
+
+(ert-deftest bindat-test-unpack/multibyte-string-fails ()
+ (should-error (bindat-unpack nil (decode-coding-string "ö" 'utf-8))))
(ert-deftest bindat-test-format-vector ()
(should (equal (bindat-format-vector [1 2 3] "%d" "x" 2) "1x2"))
commit 5215067c4efd186ffc0d8bf2e68bd4be7bf627c5
Author: Mauro Aranda
Date: Thu Oct 22 14:30:13 2020 +0200
Pretty print restricted sexp values too
* lisp/wid-edit.el (restricted-sexp widget): Use
widget-sexp-value-to-internal to pretty print the widget's value, when
it is a valid one (bug#7524).
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index c3366b62cd..009c6b4faf 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -3584,7 +3584,7 @@ To use this type, you must define :match or :match-alternatives."
:match 'widget-restricted-sexp-match
:value-to-internal (lambda (widget value)
(if (widget-apply widget :match value)
- (prin1-to-string value)
+ (widget-sexp-value-to-internal widget value)
value)))
(defun widget-restricted-sexp-match (widget value)
commit a5b4789d994622acc8eb5e92e476839025583edc
Author: Stefan Kangas
Date: Thu Oct 22 13:58:23 2020 +0200
Remove reference HP-UX 8.0 and 9.x bug from FAQ
* doc/misc/efaq.texi (Meta key does not work in xterm): Remove section
about a bug on HP-UX 8.0 and 9.x. Support for these platforms were
removed in 23.1.
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index a5f3311343..e1b099edaa 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -3664,7 +3664,6 @@ See the file @file{nextstep/INSTALL} in the distribution.
* Compose Character::
* Binding combinations of modifiers and function keys::
* Meta key does not work in xterm::
-* ExtendChar key does not work as Meta::
* SPC no longer completes file names::
@end menu
@@ -4139,29 +4138,6 @@ You might have to replace @samp{Meta} with @samp{Alt}.
@end itemize
-@node ExtendChar key does not work as Meta
-@section Why doesn't my @key{ExtendChar} key work as a @key{Meta} key under HP-UX 8.0 and 9.x?
-@cindex @key{ExtendChar} key as @key{Meta}
-@cindex @key{Meta}, using @key{ExtendChar} for
-@cindex HP-UX, the @key{ExtendChar} key
-
-This is a result of an internationalization extension in X11R4 and the
-fact that HP is now using this extension. Emacs assumes that the
-@code{XLookupString} function returns the same result regardless of the
-@key{Meta} key state which is no longer necessarily true. Until Emacs
-is fixed, the temporary kludge is to run this command after each time
-the X server is started but preferably before any xterm clients are:
-
-@example
-xmodmap -e 'remove mod1 = Mode_switch'
-@end example
-
-@c FIXME: Emacs 21 supports I18N in X11; does that mean that this bug is
-@c solved?
-
-This will disable the use of the extra keysyms systemwide, which may be
-undesirable if you actually intend to use them.
-
@node SPC no longer completes file names
@section Why doesn't @key{SPC} complete file names anymore?
@cindex @kbd{SPC} file name completion
commit bb0256d9d129390690b8fb03a1e1b2739f3e0984
Author: Stefan Kangas
Date: Thu Oct 22 13:52:42 2020 +0200
Remove two references to Emacs 21 from the FAQ
* doc/misc/efaq.texi (Turning on syntax highlighting): Remove some
references to Emacs 21 and older.
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index 115dd8a5ae..a5f3311343 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -2718,8 +2718,7 @@ menus}), use:
@cindex FAQ, @code{font-lock-mode}
@code{font-lock-mode} is the standard way to have Emacs perform syntax
-highlighting in the current buffer. It is enabled by default in Emacs
-22.1 and later.
+highlighting in the current buffer. It is enabled by default.
With @code{font-lock-mode} turned on, different types of text will
appear in different colors. For instance, in a programming mode,
@@ -2729,13 +2728,6 @@ a third.
To turn @code{font-lock-mode} off within an existing buffer, use
@kbd{M-x font-lock-mode @key{RET}}.
-In Emacs 21 and earlier versions, you could use the following code in
-your @file{.emacs} file to turn on @code{font-lock-mode} globally:
-
-@lisp
-(global-font-lock-mode 1)
-@end lisp
-
Highlighting a buffer with @code{font-lock-mode} can take quite a while,
and cause an annoying delay in display, so several features exist to
work around this.
commit c009a0a6f73bb61d2bd37f4acb8435b335ed2fa0
Author: Mauro Aranda
Date: Thu Oct 22 13:52:42 2020 +0200
Allow moving members of editable-list widget, via delete+insert
* etc/NEWS (Widget): Announce the feature (bug#6419).
* lisp/wid-edit.el (widget-editable-list-delete-at): Save into a new
widget property, :last-deleted, the WIDGET to be deleted. Add
docstring.
(widget-editable-list-insert-before): If there is a recently deleted
child for the editable list, insert that one, instead of a new default
widget. Add docstring.
(insert-button widget): Make :help-echo a function to avoid the
help-echo string become too long.
(delete-button widget): Tweak the :help-echo string, to document this
behavior.
* test/lisp/wid-edit-tests.el (widget-test-moving-editable-list-item):
Test the feature.
diff --git a/etc/NEWS b/etc/NEWS
index 2aed575159..9e8182a2da 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1166,6 +1166,13 @@ window after starting). This variable defaults to nil.
+++
*** 'widget-choose' now supports menus in extended format.
+---
+*** The 'editable-list' widget now supports moving items up and down.
+You can now move items up and down by deleting and then reinserting
+them, using the DEL and INS buttons respectively. This is useful in
+Custom buffers, for example, to change the order of the elements in a
+list.
+
** Miscellaneous
---
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 6568cd2c8f..c3366b62cd 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -2721,7 +2721,10 @@ Return an alist of (TYPE MATCH)."
(define-widget 'insert-button 'push-button
"An insert button for the `editable-list' widget."
:tag "INS"
- :help-echo "Insert a new item into the list at this position."
+ :help-echo (lambda (widget)
+ (if (widget-get (widget-get widget :parent) :last-deleted)
+ "Insert back the last deleted item from this list, at this position."
+ "Insert a new item into the list at this position."))
:action 'widget-insert-button-action)
(defun widget-insert-button-action (widget &optional _event)
@@ -2734,7 +2737,7 @@ Return an alist of (TYPE MATCH)."
(define-widget 'delete-button 'push-button
"A delete button for the `editable-list' widget."
:tag "DEL"
- :help-echo "Delete this item from the list."
+ :help-echo "Delete this item from the list, saving it for later reinsertion."
:action 'widget-delete-button-action)
(defun widget-delete-button-action (widget &optional _event)
@@ -2824,9 +2827,18 @@ Return an alist of (TYPE MATCH)."
(cons found value)))
(defun widget-editable-list-insert-before (widget before)
- ;; Insert a new child in the list of children.
+ "Insert a new widget as a child of WIDGET.
+
+If there is a recently deleted child, the new widget is that deleted child.
+Otherwise, the new widget is the default child of WIDGET.
+
+The new widget gets inserted at the position of the BEFORE child."
(save-excursion
(let ((children (widget-get widget :children))
+ (last-deleted (when-let ((lst (widget-get widget :last-deleted)))
+ (prog1
+ (pop lst)
+ (widget-put widget :last-deleted lst))))
(inhibit-read-only t)
(inhibit-modification-hooks t))
(cond (before
@@ -2834,7 +2846,11 @@ Return an alist of (TYPE MATCH)."
(t
(goto-char (widget-get widget :value-pos))))
(let ((child (widget-editable-list-entry-create
- widget nil nil)))
+ widget (and last-deleted
+ (widget-apply last-deleted
+ :value-to-external
+ (widget-get last-deleted :value)))
+ last-deleted)))
(when (< (widget-get child :entry-from) (widget-get widget :from))
(set-marker (widget-get widget :from)
(widget-get child :entry-from)))
@@ -2847,6 +2863,15 @@ Return an alist of (TYPE MATCH)."
(widget-apply widget :notify widget))
(defun widget-editable-list-delete-at (widget child)
+ "Delete the widget CHILD from the known children of widget WIDGET.
+
+Save CHILD into the :last-deleted list, so it can be inserted later."
+ ;; Save the current value of CHILD, to use if the user later inserts the
+ ;; widget.
+ (widget-put child :value (widget-apply child :value-get))
+ (let ((lst (widget-get widget :last-deleted)))
+ (push child lst)
+ (widget-put widget :last-deleted lst))
;; Delete child from list of children.
(save-excursion
(let ((buttons (copy-sequence (widget-get widget :buttons)))
diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el
index df49ffc822..4508b68023 100644
--- a/test/lisp/wid-edit-tests.el
+++ b/test/lisp/wid-edit-tests.el
@@ -129,4 +129,23 @@
(widget-insert "And some non-widget text.")
(should (string= (widget-apply wid :value-get) "")))))
+(ert-deftest widget-test-moving-editable-list-item ()
+ "Check that we can move an editable list item up or down, via delete+insert."
+ (with-temp-buffer
+ (widget-insert "Testing editable-list.\n\n")
+ (let ((lst (widget-create 'editable-list
+ :value '("beg" "end" "middle")
+ '(editable-field :value "unknown"))))
+ (use-local-map widget-keymap)
+ (widget-setup)
+ ;; Go to the DEL button for the 2nd element and action it.
+ (goto-char (widget-get (nth 2 (widget-get lst :buttons)) :from))
+ (widget-apply-action (widget-at))
+ ;; Go to the INS button and action it.
+ (goto-char (widget-get lst :to))
+ (widget-backward 1)
+ (widget-apply-action (widget-at))
+ ;; Check that we effectively moved the item to the last position.
+ (should (equal (widget-value lst) '("beg" "middle" "end"))))))
+
;;; wid-edit-tests.el ends here
commit 954a4decfcc8e41084789516773b22d0adc11d91
Author: Pip Cet
Date: Thu Oct 22 13:40:34 2020 +0200
Handle Cairo errors in ftcrfont_open
* src/ftcrfont.c (ftcrfont_open): Handle Cairo errors (bug#41627).
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 4892a34a3a..a10308c62e 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -139,7 +139,8 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
FcPatternDestroy (pat);
font_face = cairo_ft_font_face_create_for_pattern (match);
- if (!font_face)
+ if (!font_face
+ || cairo_font_face_status (font_face) != CAIRO_STATUS_SUCCESS)
{
unblock_input ();
FcPatternDestroy (match);
@@ -154,6 +155,18 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
cairo_font_face_destroy (font_face);
cairo_font_options_destroy (options);
unblock_input ();
+ if (!scaled_font
+ || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)
+ {
+ FcPatternDestroy (match);
+ return Qnil;
+ }
+ ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+ if (!ft_face)
+ {
+ FcPatternDestroy (match);
+ return Qnil;
+ }
font_object = font_build_object (VECSIZE (struct font_info),
AREF (entity, FONT_TYPE_INDEX),
@@ -234,7 +247,6 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
font->descent = font->height - font->ascent;
}
- ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0)
{
int upEM = ft_face->units_per_EM;
commit 701ed2e4edd470f8b45de7671becde30b3786989
Author: Mattias Engdegård
Date: Thu Oct 22 12:18:16 2020 +0200
Use lexical binding in fortran.el
* lisp/progmodes/fortran.el: Use lexical binding.
(fortran-make-syntax-propertize-function): Hoist use of lexical
variable to outside the 'eval' call.
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index abc860b947..206d1f2a05 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -1,4 +1,4 @@
-;;; fortran.el --- Fortran mode for GNU Emacs
+;;; fortran.el --- Fortran mode for GNU Emacs -*- lexical-binding: t -*-
;; Copyright (C) 1986, 1993-1995, 1997-2020 Free Software Foundation,
;; Inc.
@@ -495,13 +495,13 @@ This is used to fontify fixed-format Fortran comments."
;; `byte-compile', but simple benchmarks indicate that it's probably not
;; worth the trouble (about 0.5% of slow down).
(eval ;I hate `eval', but it's hard to avoid it here.
- '(syntax-propertize-rules
+ `(syntax-propertize-rules
("^[CcDd\\*]" (0 "<"))
;; We mark all chars after line-length as "comment-start", rather than
;; just the first one. This is so that a closing ' that's past the
;; line-length will indeed be ignored (and will result in a string that
;; leaks into subsequent lines).
- ((format "^[^CcDd\\*\t\n].\\{%d\\}\\(.+\\)" (1- line-length))
+ (,(format "^[^CcDd\\*\t\n].\\{%d\\}\\(.+\\)" (1- line-length))
(1 "<")))))
(defvar fortran-font-lock-keywords fortran-font-lock-keywords-1
commit 3479390c4c4b053667aab79c83239ababbdac9d0
Author: Mattias Engdegård
Date: Thu Oct 22 11:46:09 2020 +0200
* lisp/progmodes/cpp.el: Use lexical binding.
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index bcbe669c16..65ef83f769 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -1,4 +1,4 @@
-;;; cpp.el --- highlight or hide text according to cpp conditionals
+;;; cpp.el --- highlight or hide text according to cpp conditionals -*- lexical-binding: t -*-
;; Copyright (C) 1994-1995, 2001-2020 Free Software Foundation, Inc.
commit 420023a6f066d6ffb85e23ffe3abcfee3d523ea7 (refs/remotes/origin/scratch/substitute-command-keys)
Author: Stefan Kangas
Date: Sun Oct 18 16:49:55 2020 +0200
Prefer Lisp version of describer in help--describe-vector
* src/keymap.c (Fhelp__describe_vector):
* lisp/help.el (describe-map): Use Lisp versions of describe_command
and describe_translation.
* src/keymap.c (describe_command, describe_translation): Remove.
(describe_vector_basic): New function.
diff --git a/lisp/help.el b/lisp/help.el
index e8dfbdef74..6ae2664cf4 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1274,10 +1274,13 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
(map (keymap-canonicalize map))
(tail map)
(first t)
+ (describer (if transl
+ #'help--describe-translation
+ #'help--describe-command))
done vect)
(while (and (consp tail) (not done))
(cond ((or (vectorp (car tail)) (char-table-p (car tail)))
- (help--describe-vector (car tail) prefix transl partial
+ (help--describe-vector (car tail) prefix describer partial
shadow map mention-shadow))
((consp (car tail))
(let ((event (caar tail))
diff --git a/src/keymap.c b/src/keymap.c
index 46fa586c75..e5b4781076 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -89,8 +89,6 @@ static Lisp_Object where_is_cache_keymaps;
static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object);
static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object);
-static void describe_command (Lisp_Object, Lisp_Object);
-static void describe_translation (Lisp_Object, Lisp_Object);
static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object,
void (*) (Lisp_Object, Lisp_Object), bool,
Lisp_Object, Lisp_Object, bool, bool);
@@ -2943,74 +2941,18 @@ You type Translation\n\
return Qnil;
}
-static int previous_description_column;
-
-static void
-describe_command (Lisp_Object definition, Lisp_Object args)
-{
- register Lisp_Object tem1;
- ptrdiff_t column = current_column ();
- int description_column;
-
- /* If column 16 is no good, go to col 32;
- but don't push beyond that--go to next line instead. */
- if (column > 30)
- {
- insert_char ('\n');
- description_column = 32;
- }
- else if (column > 14 || (column > 10 && previous_description_column == 32))
- description_column = 32;
- else
- description_column = 16;
-
- Findent_to (make_fixnum (description_column), make_fixnum (1));
- previous_description_column = description_column;
-
- if (SYMBOLP (definition))
- {
- tem1 = SYMBOL_NAME (definition);
- insert1 (tem1);
- insert_string ("\n");
- }
- else if (STRINGP (definition) || VECTORP (definition))
- insert_string ("Keyboard Macro\n");
- else if (KEYMAPP (definition))
- insert_string ("Prefix Command\n");
- else
- insert_string ("??\n");
-}
-
static void
-describe_translation (Lisp_Object definition, Lisp_Object args)
+describe_vector_princ (Lisp_Object elt, Lisp_Object fun)
{
- register Lisp_Object tem1;
-
Findent_to (make_fixnum (16), make_fixnum (1));
-
- if (SYMBOLP (definition))
- {
- tem1 = SYMBOL_NAME (definition);
- insert1 (tem1);
- insert_string ("\n");
- }
- else if (STRINGP (definition) || VECTORP (definition))
- {
- insert1 (Fkey_description (definition, Qnil));
- insert_string ("\n");
- }
- else if (KEYMAPP (definition))
- insert_string ("Prefix Command\n");
- else
- insert_string ("??\n");
+ call1 (fun, elt);
+ Fterpri (Qnil, Qnil);
}
static void
-describe_vector_princ (Lisp_Object elt, Lisp_Object fun)
+describe_vector_basic (Lisp_Object elt, Lisp_Object fun)
{
- Findent_to (make_fixnum (16), make_fixnum (1));
call1 (fun, elt);
- Fterpri (Qnil, Qnil);
}
DEFUN ("describe-vector", Fdescribe_vector, Sdescribe_vector, 1, 2, 0,
@@ -3032,6 +2974,7 @@ DESCRIBER is the output function used; nil means use `princ'. */)
DEFUN ("help--describe-vector", Fhelp__describe_vector, Shelp__describe_vector, 7, 7, 0,
doc: /* Insert in the current buffer a description of the contents of VECTOR.
+Call DESCRIBER to insert the description of one value found in VECTOR.
PREFIX is a string describing the key which leads to the keymap that
this vector is in.
@@ -3045,7 +2988,7 @@ if it is defined by any of them.
ENTIRE-MAP is the keymap in which this vector appears.
If the definition in effect in the whole map does not match
the one in this keymap, we ignore this one. */)
- (Lisp_Object vector, Lisp_Object prefix, Lisp_Object transl,
+ (Lisp_Object vector, Lisp_Object prefix, Lisp_Object describer,
Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map,
Lisp_Object mention_shadow)
{
@@ -3053,19 +2996,16 @@ the one in this keymap, we ignore this one. */)
specbind (Qstandard_output, Fcurrent_buffer ());
CHECK_VECTOR_OR_CHAR_TABLE (vector);
- bool b_transl = NILP (transl) ? false : true;
bool b_partial = NILP (partial) ? false : true;
bool b_mention_shadow = NILP (mention_shadow) ? false : true;
- describe_vector (vector, prefix, Qnil,
- b_transl ? describe_translation : describe_command,
- b_partial, shadow, entire_map,
- true, b_mention_shadow);
+ describe_vector (vector, prefix, describer, describe_vector_basic, b_partial,
+ shadow, entire_map, true, b_mention_shadow);
return unbind_to (count, Qnil);
}
/* Insert in the current buffer a description of the contents of VECTOR.
- We call ELT_DESCRIBER to insert the description of one value found
+ Call ELT_DESCRIBER to insert the description of one value found
in VECTOR.
ELT_PREFIX describes what "comes before" the keys or indices defined
commit ef5a604f082f772424400f48b64e9c04edbcc766
Author: Stefan Kangas
Date: Sun Oct 18 15:19:09 2020 +0200
Remove C version of substitute-command-keys
* src/doc.c (Fsubstitute_command_keys_old): Remove.
(syms_of_doc): Remove defsubr for Fsubstitute_command_keys_old.
* src/keymap.c (describe_map, describe_map_tree)
(describe_map_compare, describe_map_elt): Remove.
* src/keymap.h: Remove 'describe_map_tree'.
* test/lisp/help-tests.el (with-substitute-command-keys-test)
(help-tests-substitute-command-keys/compare)
(help-tests-substitute-command-keys/compare-all):
Don't test the C version of 'substitute-command-keys' removed
above.
diff --git a/src/doc.c b/src/doc.c
index 212ebe9633..f1ce266d39 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -715,308 +715,6 @@ See variable `text-quoting-style'. */)
}
}
-DEFUN ("substitute-command-keys-old", Fsubstitute_command_keys_old,
- Ssubstitute_command_keys_old, 1, 1, 0,
- doc: /* Substitute key descriptions for command names in STRING.
-Each substring of the form \\=\\[COMMAND] is replaced by either a
-keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND
-is not on any keys.
-
-Each substring of the form \\=\\{MAPVAR} is replaced by a summary of
-the value of MAPVAR as a keymap. This summary is similar to the one
-produced by `describe-bindings'. The summary ends in two newlines
-\(used by the helper function `help-make-xrefs' to find the end of the
-summary).
-
-Each substring of the form \\=\\ specifies the use of MAPVAR
-as the keymap for future \\=\\[COMMAND] substrings.
-
-Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
-is replaced by right quote. Left and right quote characters are
-specified by `text-quoting-style'.
-
-\\=\\= quotes the following character and is discarded; thus, \\=\\=\\=\\= puts \\=\\=
-into the output, \\=\\=\\=\\[ puts \\=\\[ into the output, and \\=\\=\\=` puts \\=` into the
-output.
-
-Return the original STRING if no substitutions are made.
-Otherwise, return a new string (without any text properties). */)
- (Lisp_Object string)
-{
- char *buf;
- bool changed = false;
- bool nonquotes_changed = false;
- unsigned char *strp;
- char *bufp;
- ptrdiff_t idx;
- ptrdiff_t bsize;
- Lisp_Object tem;
- Lisp_Object keymap;
- unsigned char const *start;
- ptrdiff_t length, length_byte;
- Lisp_Object name;
- ptrdiff_t nchars;
-
- if (NILP (string))
- return Qnil;
-
- /* If STRING contains non-ASCII unibyte data, process its
- properly-encoded multibyte equivalent instead. This simplifies
- the implementation and is OK since substitute-command-keys is
- intended for use only on text strings. Keep STRING around, since
- it will be returned if no changes occur. */
- Lisp_Object str = Fstring_make_multibyte (string);
-
- enum text_quoting_style quoting_style = text_quoting_style ();
-
- nchars = 0;
-
- /* KEYMAP is either nil (which means search all the active keymaps)
- or a specified local map (which means search just that and the
- global map). If non-nil, it might come from Voverriding_local_map,
- or from a \\ construct in STRING itself.. */
- keymap = Voverriding_local_map;
-
- ptrdiff_t strbytes = SBYTES (str);
- bsize = strbytes;
-
- /* Fixed-size stack buffer. */
- char sbuf[MAX_ALLOCA];
-
- /* Heap-allocated buffer, if any. */
- char *abuf;
-
- /* Extra room for expansion due to replacing ‘\[]’ with ‘M-x ’. */
- enum { EXTRA_ROOM = sizeof "M-x " - sizeof "\\[]" };
-
- ptrdiff_t count = SPECPDL_INDEX ();
-
- if (bsize <= sizeof sbuf - EXTRA_ROOM)
- {
- abuf = NULL;
- buf = sbuf;
- bsize = sizeof sbuf;
- }
- else
- {
- buf = abuf = xpalloc (NULL, &bsize, EXTRA_ROOM, STRING_BYTES_BOUND, 1);
- record_unwind_protect_ptr (xfree, abuf);
- }
- bufp = buf;
-
- strp = SDATA (str);
- while (strp < SDATA (str) + strbytes)
- {
- unsigned char *close_bracket;
-
- if (strp[0] == '\\' && strp[1] == '='
- && strp + 2 < SDATA (str) + strbytes)
- {
- /* \= quotes the next character;
- thus, to put in \[ without its special meaning, use \=\[. */
- changed = nonquotes_changed = true;
- strp += 2;
- /* Fall through to copy one char. */
- }
- else if (strp[0] == '\\' && strp[1] == '['
- && (close_bracket
- = memchr (strp + 2, ']',
- SDATA (str) + strbytes - (strp + 2))))
- {
- bool follow_remap = 1;
-
- start = strp + 2;
- length_byte = close_bracket - start;
- idx = close_bracket + 1 - SDATA (str);
-
- name = Fintern (make_string ((char *) start, length_byte), Qnil);
-
- do_remap:
- tem = Fwhere_is_internal (name, keymap, Qt, Qnil, Qnil);
-
- if (VECTORP (tem) && ASIZE (tem) > 1
- && EQ (AREF (tem, 0), Qremap) && SYMBOLP (AREF (tem, 1))
- && follow_remap)
- {
- name = AREF (tem, 1);
- follow_remap = 0;
- goto do_remap;
- }
-
- /* Fwhere_is_internal can GC, so take relocation of string
- contents into account. */
- strp = SDATA (str) + idx;
- start = strp - length_byte - 1;
-
- if (NILP (tem)) /* but not on any keys */
- {
- memcpy (bufp, "M-x ", 4);
- bufp += 4;
- nchars += 4;
- length = multibyte_chars_in_text (start, length_byte);
- goto subst;
- }
- else
- { /* function is on a key */
- tem = Fkey_description (tem, Qnil);
- goto subst_string;
- }
- }
- /* \{foo} is replaced with a summary of the keymap (symbol-value foo).
- \ just sets the keymap used for \[cmd]. */
- else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<')
- && (close_bracket
- = memchr (strp + 2, strp[1] == '{' ? '}' : '>',
- SDATA (str) + strbytes - (strp + 2))))
- {
- {
- bool generate_summary = strp[1] == '{';
- /* This is for computing the SHADOWS arg for describe_map_tree. */
- Lisp_Object active_maps = Fcurrent_active_maps (Qnil, Qnil);
- ptrdiff_t count = SPECPDL_INDEX ();
-
- start = strp + 2;
- length_byte = close_bracket - start;
- idx = close_bracket + 1 - SDATA (str);
-
- /* Get the value of the keymap in TEM, or nil if undefined.
- Do this while still in the user's current buffer
- in case it is a local variable. */
- name = Fintern (make_string ((char *) start, length_byte), Qnil);
- tem = Fboundp (name);
- if (! NILP (tem))
- {
- tem = Fsymbol_value (name);
- if (! NILP (tem))
- tem = get_keymap (tem, 0, 1);
- }
-
- /* Now switch to a temp buffer. */
- struct buffer *oldbuf = current_buffer;
- set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
- /* This is for an unusual case where some after-change
- function uses 'format' or 'prin1' or something else that
- will thrash Vprin1_to_string_buffer we are using. */
- specbind (Qinhibit_modification_hooks, Qt);
-
- if (NILP (tem))
- {
- name = Fsymbol_name (name);
- AUTO_STRING (msg_prefix, "\nUses keymap `");
- insert1 (Fsubstitute_command_keys_old (msg_prefix));
- insert_from_string (name, 0, 0,
- SCHARS (name),
- SBYTES (name), 1);
- AUTO_STRING (msg_suffix, "', which is not currently defined.\n");
- insert1 (Fsubstitute_command_keys_old (msg_suffix));
- if (!generate_summary)
- keymap = Qnil;
- }
- else if (!generate_summary)
- keymap = tem;
- else
- {
- /* Get the list of active keymaps that precede this one.
- If this one's not active, get nil. */
- Lisp_Object earlier_maps
- = Fcdr (Fmemq (tem, Freverse (active_maps)));
- describe_map_tree (tem, 1, Fnreverse (earlier_maps),
- Qnil, 0, 1, 0, 0, 1);
- }
- tem = Fbuffer_string ();
- Ferase_buffer ();
- set_buffer_internal (oldbuf);
- unbind_to (count, Qnil);
- }
-
- subst_string:
- /* Convert non-ASCII unibyte data to properly-encoded multibyte,
- for the same reason STRING was converted to STR. */
- tem = Fstring_make_multibyte (tem);
- start = SDATA (tem);
- length = SCHARS (tem);
- length_byte = SBYTES (tem);
- subst:
- nonquotes_changed = true;
- subst_quote:
- changed = true;
- {
- ptrdiff_t offset = bufp - buf;
- ptrdiff_t avail = bsize - offset;
- ptrdiff_t need = strbytes - idx;
- if (INT_ADD_WRAPV (need, length_byte + EXTRA_ROOM, &need))
- string_overflow ();
- if (avail < need)
- {
- abuf = xpalloc (abuf, &bsize, need - avail,
- STRING_BYTES_BOUND, 1);
- if (buf == sbuf)
- {
- record_unwind_protect_ptr (xfree, abuf);
- memcpy (abuf, sbuf, offset);
- }
- else
- set_unwind_protect_ptr (count, xfree, abuf);
- buf = abuf;
- bufp = buf + offset;
- }
- memcpy (bufp, start, length_byte);
- bufp += length_byte;
- nchars += length;
-
- /* Some of the previous code can GC, so take relocation of
- string contents into account. */
- strp = SDATA (str) + idx;
-
- continue;
- }
- }
- else if ((strp[0] == '`' || strp[0] == '\'')
- && quoting_style == CURVE_QUOTING_STYLE)
- {
- start = (unsigned char const *) (strp[0] == '`' ? uLSQM : uRSQM);
- length = 1;
- length_byte = sizeof uLSQM - 1;
- idx = strp - SDATA (str) + 1;
- goto subst_quote;
- }
- else if (strp[0] == '`' && quoting_style == STRAIGHT_QUOTING_STYLE)
- {
- *bufp++ = '\'';
- strp++;
- nchars++;
- changed = true;
- continue;
- }
-
- /* Copy one char. */
- do
- *bufp++ = *strp++;
- while (! CHAR_HEAD_P (*strp));
- nchars++;
- }
-
- if (changed) /* don't bother if nothing substituted */
- {
- tem = make_string_from_bytes (buf, nchars, bufp - buf);
- if (!nonquotes_changed)
- {
- /* Nothing has changed other than quoting, so copy the string’s
- text properties. FIXME: Text properties should survive other
- changes too; see bug#17052. */
- INTERVAL interval_copy = copy_intervals (string_intervals (string),
- 0, SCHARS (string));
- if (interval_copy)
- {
- set_interval_object (interval_copy, tem);
- set_string_intervals (tem, interval_copy);
- }
- }
- }
- else
- tem = string;
- return unbind_to (count, tem);
-}
void
syms_of_doc (void)
@@ -1058,5 +756,4 @@ otherwise. */);
defsubr (&Sdocumentation_property);
defsubr (&Ssnarf_documentation);
defsubr (&Sget_quoting_style);
- defsubr (&Ssubstitute_command_keys_old);
}
diff --git a/src/keymap.c b/src/keymap.c
index 1eded130b5..46fa586c75 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -91,9 +91,6 @@ static Lisp_Object store_in_keymap (Lisp_Object, Lisp_Object, Lisp_Object);
static Lisp_Object define_as_prefix (Lisp_Object, Lisp_Object);
static void describe_command (Lisp_Object, Lisp_Object);
static void describe_translation (Lisp_Object, Lisp_Object);
-static void describe_map (Lisp_Object, Lisp_Object,
- void (*) (Lisp_Object, Lisp_Object),
- bool, Lisp_Object, Lisp_Object *, bool, bool);
static void describe_vector (Lisp_Object, Lisp_Object, Lisp_Object,
void (*) (Lisp_Object, Lisp_Object), bool,
Lisp_Object, Lisp_Object, bool, bool);
@@ -2946,119 +2943,6 @@ You type Translation\n\
return Qnil;
}
-/* Insert a description of the key bindings in STARTMAP,
- followed by those of all maps reachable through STARTMAP.
- If PARTIAL, omit certain "uninteresting" commands
- (such as `undefined').
- If SHADOW is non-nil, it is a list of maps;
- don't mention keys which would be shadowed by any of them.
- PREFIX, if non-nil, says mention only keys that start with PREFIX.
- TITLE, if not 0, is a string to insert at the beginning.
- TITLE should not end with a colon or a newline; we supply that.
- If NOMENU, then omit menu-bar commands.
-
- If TRANSL, the definitions are actually key translations
- so print strings and vectors differently.
-
- If ALWAYS_TITLE, print the title even if there are no maps
- to look through.
-
- If MENTION_SHADOW, then when something is shadowed by SHADOW,
- don't omit it; instead, mention it but say it is shadowed.
-
- Any inserted text ends in two newlines (used by `help-make-xrefs'). */
-
-void
-describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow,
- Lisp_Object prefix, const char *title, bool nomenu,
- bool transl, bool always_title, bool mention_shadow)
-{
- Lisp_Object maps, orig_maps, seen, sub_shadows;
- bool something = 0;
- const char *key_heading
- = "\
-key binding\n\
---- -------\n";
-
- orig_maps = maps = Faccessible_keymaps (startmap, prefix);
- seen = Qnil;
- sub_shadows = Qnil;
-
- if (nomenu)
- {
- Lisp_Object list;
-
- /* Delete from MAPS each element that is for the menu bar. */
- for (list = maps; CONSP (list); list = XCDR (list))
- {
- Lisp_Object elt, elt_prefix, tem;
-
- elt = XCAR (list);
- elt_prefix = Fcar (elt);
- if (ASIZE (elt_prefix) >= 1)
- {
- tem = Faref (elt_prefix, make_fixnum (0));
- if (EQ (tem, Qmenu_bar))
- maps = Fdelq (elt, maps);
- }
- }
- }
-
- if (!NILP (maps) || always_title)
- {
- if (title)
- {
- insert_string (title);
- if (!NILP (prefix))
- {
- insert_string (" Starting With ");
- insert1 (Fkey_description (prefix, Qnil));
- }
- insert_string (":\n");
- }
- insert_string (key_heading);
- something = 1;
- }
-
- for (; CONSP (maps); maps = XCDR (maps))
- {
- register Lisp_Object elt, elt_prefix, tail;
-
- elt = XCAR (maps);
- elt_prefix = Fcar (elt);
-
- sub_shadows = Flookup_key (shadow, elt_prefix, Qt);
- if (FIXNATP (sub_shadows))
- sub_shadows = Qnil;
- else if (!KEYMAPP (sub_shadows)
- && !NILP (sub_shadows)
- && !(CONSP (sub_shadows)
- && KEYMAPP (XCAR (sub_shadows))))
- /* If elt_prefix is bound to something that's not a keymap,
- it completely shadows this map, so don't
- describe this map at all. */
- goto skip;
-
- /* Maps we have already listed in this loop shadow this map. */
- for (tail = orig_maps; !EQ (tail, maps); tail = XCDR (tail))
- {
- Lisp_Object tem;
- tem = Fequal (Fcar (XCAR (tail)), elt_prefix);
- if (!NILP (tem))
- sub_shadows = Fcons (XCDR (XCAR (tail)), sub_shadows);
- }
-
- describe_map (Fcdr (elt), elt_prefix,
- transl ? describe_translation : describe_command,
- partial, sub_shadows, &seen, nomenu, mention_shadow);
-
- skip: ;
- }
-
- if (something)
- insert_string ("\n");
-}
-
static int previous_description_column;
static void
@@ -3121,224 +3005,6 @@ describe_translation (Lisp_Object definition, Lisp_Object args)
insert_string ("??\n");
}
-/* describe_map puts all the usable elements of a sparse keymap
- into an array of `struct describe_map_elt',
- then sorts them by the events. */
-
-struct describe_map_elt
-{
- Lisp_Object event;
- Lisp_Object definition;
- bool shadowed;
-};
-
-/* qsort comparison function for sorting `struct describe_map_elt' by
- the event field. */
-
-static int
-describe_map_compare (const void *aa, const void *bb)
-{
- const struct describe_map_elt *a = aa, *b = bb;
- if (FIXNUMP (a->event) && FIXNUMP (b->event))
- return ((XFIXNUM (a->event) > XFIXNUM (b->event))
- - (XFIXNUM (a->event) < XFIXNUM (b->event)));
- if (!FIXNUMP (a->event) && FIXNUMP (b->event))
- return 1;
- if (FIXNUMP (a->event) && !FIXNUMP (b->event))
- return -1;
- if (SYMBOLP (a->event) && SYMBOLP (b->event))
- /* Sort the keystroke names in the "natural" way, with (for
- instance) "" coming between "" and "". */
- return string_version_cmp (SYMBOL_NAME (a->event), SYMBOL_NAME (b->event));
- return 0;
-}
-
-/* Describe the contents of map MAP, assuming that this map itself is
- reached by the sequence of prefix keys PREFIX (a string or vector).
- PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */
-
-static void
-describe_map (Lisp_Object map, Lisp_Object prefix,
- void (*elt_describer) (Lisp_Object, Lisp_Object),
- bool partial, Lisp_Object shadow,
- Lisp_Object *seen, bool nomenu, bool mention_shadow)
-{
- Lisp_Object tail, definition, event;
- Lisp_Object tem;
- Lisp_Object suppress;
- Lisp_Object kludge;
- bool first = 1;
-
- /* These accumulate the values from sparse keymap bindings,
- so we can sort them and handle them in order. */
- ptrdiff_t length_needed = 0;
- struct describe_map_elt *vect;
- ptrdiff_t slots_used = 0;
- ptrdiff_t i;
-
- suppress = Qnil;
-
- if (partial)
- suppress = intern ("suppress-keymap");
-
- /* This vector gets used to present single keys to Flookup_key. Since
- that is done once per keymap element, we don't want to cons up a
- fresh vector every time. */
- kludge = make_nil_vector (1);
- definition = Qnil;
-
- map = call1 (Qkeymap_canonicalize, map);
-
- for (tail = map; CONSP (tail); tail = XCDR (tail))
- length_needed++;
-
- USE_SAFE_ALLOCA;
- SAFE_NALLOCA (vect, 1, length_needed);
-
- for (tail = map; CONSP (tail); tail = XCDR (tail))
- {
- maybe_quit ();
-
- if (VECTORP (XCAR (tail))
- || CHAR_TABLE_P (XCAR (tail)))
- describe_vector (XCAR (tail),
- prefix, Qnil, elt_describer, partial, shadow, map,
- 1, mention_shadow);
- else if (CONSP (XCAR (tail)))
- {
- bool this_shadowed = 0;
-
- event = XCAR (XCAR (tail));
-
- /* Ignore bindings whose "prefix" are not really valid events.
- (We get these in the frames and buffers menu.) */
- if (!(SYMBOLP (event) || FIXNUMP (event)))
- continue;
-
- if (nomenu && EQ (event, Qmenu_bar))
- continue;
-
- definition = get_keyelt (XCDR (XCAR (tail)), 0);
-
- /* Don't show undefined commands or suppressed commands. */
- if (NILP (definition)) continue;
- if (SYMBOLP (definition) && partial)
- {
- tem = Fget (definition, suppress);
- if (!NILP (tem))
- continue;
- }
-
- /* Don't show a command that isn't really visible
- because a local definition of the same key shadows it. */
-
- ASET (kludge, 0, event);
- if (!NILP (shadow))
- {
- tem = shadow_lookup (shadow, kludge, Qt, 0);
- if (!NILP (tem))
- {
- /* If both bindings are keymaps, this key is a prefix key,
- so don't say it is shadowed. */
- if (KEYMAPP (definition) && KEYMAPP (tem))
- ;
- /* Avoid generating duplicate entries if the
- shadowed binding has the same definition. */
- else if (mention_shadow && !EQ (tem, definition))
- this_shadowed = 1;
- else
- continue;
- }
- }
-
- tem = Flookup_key (map, kludge, Qt);
- if (!EQ (tem, definition)) continue;
-
- vect[slots_used].event = event;
- vect[slots_used].definition = definition;
- vect[slots_used].shadowed = this_shadowed;
- slots_used++;
- }
- else if (EQ (XCAR (tail), Qkeymap))
- {
- /* The same keymap might be in the structure twice, if we're
- using an inherited keymap. So skip anything we've already
- encountered. */
- tem = Fassq (tail, *seen);
- if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix)))
- break;
- *seen = Fcons (Fcons (tail, prefix), *seen);
- }
- }
-
- /* If we found some sparse map events, sort them. */
-
- qsort (vect, slots_used, sizeof (struct describe_map_elt),
- describe_map_compare);
-
- /* Now output them in sorted order. */
-
- for (i = 0; i < slots_used; i++)
- {
- Lisp_Object start, end;
-
- if (first)
- {
- previous_description_column = 0;
- insert ("\n", 1);
- first = 0;
- }
-
- ASET (kludge, 0, vect[i].event);
- start = vect[i].event;
- end = start;
-
- definition = vect[i].definition;
-
- /* Find consecutive chars that are identically defined. */
- if (FIXNUMP (vect[i].event))
- {
- while (i + 1 < slots_used
- && EQ (vect[i+1].event, make_fixnum (XFIXNUM (vect[i].event) + 1))
- && !NILP (Fequal (vect[i + 1].definition, definition))
- && vect[i].shadowed == vect[i + 1].shadowed)
- i++;
- end = vect[i].event;
- }
-
- /* Now START .. END is the range to describe next. */
-
- /* Insert the string to describe the event START. */
- insert1 (Fkey_description (kludge, prefix));
-
- if (!EQ (start, end))
- {
- insert (" .. ", 4);
-
- ASET (kludge, 0, end);
- /* Insert the string to describe the character END. */
- insert1 (Fkey_description (kludge, prefix));
- }
-
- /* Print a description of the definition of this character.
- elt_describer will take care of spacing out far enough
- for alignment purposes. */
- (*elt_describer) (vect[i].definition, Qnil);
-
- if (vect[i].shadowed)
- {
- ptrdiff_t pt = max (PT - 1, BEG);
-
- SET_PT (pt);
- insert_string ("\n (this binding is currently shadowed)");
- pt = min (PT + 1, Z);
- SET_PT (pt);
- }
- }
-
- SAFE_FREE ();
-}
-
static void
describe_vector_princ (Lisp_Object elt, Lisp_Object fun)
{
diff --git a/src/keymap.h b/src/keymap.h
index 3ef48fb748..2f7df2bd95 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -36,8 +36,6 @@ extern Lisp_Object current_global_map;
extern char *push_key_description (EMACS_INT, char *);
extern Lisp_Object access_keymap (Lisp_Object, Lisp_Object, bool, bool, bool);
extern Lisp_Object get_keymap (Lisp_Object, bool, bool);
-extern void describe_map_tree (Lisp_Object, bool, Lisp_Object, Lisp_Object,
- const char *, bool, bool, bool, bool);
extern ptrdiff_t current_minor_maps (Lisp_Object **, Lisp_Object **);
extern void initial_define_key (Lisp_Object, int, const char *);
extern void initial_define_lispy_key (Lisp_Object, const char *, const char *);
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index aff5d1853a..079b1114a8 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -58,23 +58,15 @@
;;; substitute-command-keys
(defmacro with-substitute-command-keys-test (&rest body)
- `(cl-flet* ((should-be-same-as-c-version
- ;; TODO: Remove this when old C function is removed.
- (lambda (orig)
- (should (equal-including-properties
- (substitute-command-keys orig)
- (substitute-command-keys-old orig)))))
- (test
+ `(cl-flet* ((test
(lambda (orig result)
(should (equal-including-properties
(substitute-command-keys orig)
- result))
- (should-be-same-as-c-version orig)))
+ result))))
(test-re
(lambda (orig regexp)
(should (string-match (concat "^" regexp "$")
- (substitute-command-keys orig)))
- (should-be-same-as-c-version orig))))
+ (substitute-command-keys orig))))))
,@body))
(ert-deftest help-tests-substitute-command-keys/no-change ()
@@ -369,29 +361,6 @@ C-b undefined
")))))
-;; TODO: This is a temporary test that should be removed together with
-;; substitute-command-keys-old.
-(ert-deftest help-tests-substitute-command-keys/compare ()
- (with-substitute-command-keys-test
- (with-temp-buffer
- (Info-mode)
- (outline-minor-mode)
- (test-re "\\{Info-mode-map}" ".*")))
- (with-substitute-command-keys-test
- (with-temp-buffer
- (c-mode)
- (outline-minor-mode)
- (test-re "\\{c-mode-map}" ".*"))))
-
-(ert-deftest help-tests-substitute-command-keys/compare-all ()
- (let (keymaps)
- (mapatoms (lambda (var)
- (when (keymapp var)
- (push var keymaps))))
- (dolist (keymap keymaps)
- (with-substitute-command-keys-test
- (test-re (concat "\\{" (symbol-name keymap) "}") ".*")))))
-
(provide 'help-tests)
;;; help-tests.el ends here
commit 8a1441310aa151e739cfed3bd2eff3358edc8001
Author: Stefan Kangas
Date: Sun Oct 18 15:32:22 2020 +0200
Prefer Lisp version of describe-map-tree
This is a prerequisite to remove the old C functions, and gives a
measured 3 ms slowdown on my machine, from 0.27s to 0.30s per call to
describe-buffer-bindings (average over 50 calls).
* src/keymap.c (Fdescribe_buffer_bindings): Call Lisp function
describe-map-tree instead of C function describe_map_tree.
diff --git a/src/keymap.c b/src/keymap.c
index 5ae8da6a05..1eded130b5 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -2750,7 +2750,7 @@ The optional argument MENUS, if non-nil, says to mention menu bindings.
(Lisp_Object buffer, Lisp_Object prefix, Lisp_Object menus)
{
Lisp_Object outbuf, shadow;
- bool nomenu = NILP (menus);
+ Lisp_Object nomenu = NILP (menus) ? Qt : Qnil;
Lisp_Object start1;
const char *alternate_heading
@@ -2799,9 +2799,13 @@ You type Translation\n\
}
if (!NILP (Vkey_translation_map))
- describe_map_tree (Vkey_translation_map, 0, Qnil, prefix,
- "Key translations", nomenu, 1, 0, 0);
-
+ {
+ Lisp_Object msg = build_unibyte_string ("Key translations");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ Vkey_translation_map, Qnil, Qnil, prefix,
+ msg, nomenu, Qt, Qnil, Qnil);
+ }
/* Print the (major mode) local map. */
start1 = Qnil;
@@ -2810,8 +2814,11 @@ You type Translation\n\
if (!NILP (start1))
{
- describe_map_tree (start1, 1, shadow, prefix,
- "\f\nOverriding Bindings", nomenu, 0, 0, 0);
+ Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ start1, Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qnil, Qnil);
shadow = Fcons (start1, shadow);
start1 = Qnil;
}
@@ -2820,8 +2827,11 @@ You type Translation\n\
if (!NILP (start1))
{
- describe_map_tree (start1, 1, shadow, prefix,
- "\f\nOverriding Bindings", nomenu, 0, 0, 0);
+ Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ start1, Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qnil, Qnil);
shadow = Fcons (start1, shadow);
}
else
@@ -2841,9 +2851,11 @@ You type Translation\n\
XBUFFER (buffer), Qkeymap);
if (!NILP (start1))
{
- describe_map_tree (start1, 1, shadow, prefix,
- "\f\n`keymap' Property Bindings", nomenu,
- 0, 0, 0);
+ Lisp_Object msg = build_unibyte_string ("\f\n`keymap' Property Bindings");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ start1, Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qnil, Qnil);
shadow = Fcons (start1, shadow);
}
@@ -2852,7 +2864,7 @@ You type Translation\n\
{
/* The title for a minor mode keymap
is constructed at run time.
- We let describe_map_tree do the actual insertion
+ We let describe-map-tree do the actual insertion
because it takes care of other features when doing so. */
char *title, *p;
@@ -2872,8 +2884,11 @@ You type Translation\n\
p += strlen (" Minor Mode Bindings");
*p = 0;
- describe_map_tree (maps[i], 1, shadow, prefix,
- title, nomenu, 0, 0, 0);
+ Lisp_Object msg = build_unibyte_string (title);
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ maps[i], Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qnil, Qnil);
shadow = Fcons (maps[i], shadow);
SAFE_FREE ();
}
@@ -2883,30 +2898,51 @@ You type Translation\n\
if (!NILP (start1))
{
if (EQ (start1, BVAR (XBUFFER (buffer), keymap)))
- describe_map_tree (start1, 1, shadow, prefix,
- "\f\nMajor Mode Bindings", nomenu, 0, 0, 0);
+ {
+ Lisp_Object msg = build_unibyte_string ("\f\nMajor Mode Bindings");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ start1, Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qnil, Qnil);
+ }
else
- describe_map_tree (start1, 1, shadow, prefix,
- "\f\n`local-map' Property Bindings",
- nomenu, 0, 0, 0);
+ {
+ Lisp_Object msg = build_unibyte_string ("\f\n`local-map' Property Bindings");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ start1, Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qnil, Qnil);
+ }
shadow = Fcons (start1, shadow);
}
}
- describe_map_tree (current_global_map, 1, shadow, prefix,
- "\f\nGlobal Bindings", nomenu, 0, 1, 0);
+ Lisp_Object msg = build_unibyte_string ("\f\nGlobal Bindings");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ current_global_map, Qt, shadow, prefix,
+ msg, nomenu, Qnil, Qt, Qnil);
/* Print the function-key-map translations under this prefix. */
if (!NILP (KVAR (current_kboard, Vlocal_function_key_map)))
- describe_map_tree (KVAR (current_kboard, Vlocal_function_key_map), 0, Qnil, prefix,
- "\f\nFunction key map translations", nomenu, 1, 0, 0);
+ {
+ Lisp_Object msg = build_unibyte_string ("\f\nFunction key map translations");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ KVAR (current_kboard, Vlocal_function_key_map), Qnil, Qnil, prefix,
+ msg, nomenu, Qt, Qt, Qt);
+ }
/* Print the input-decode-map translations under this prefix. */
if (!NILP (KVAR (current_kboard, Vinput_decode_map)))
- describe_map_tree (KVAR (current_kboard, Vinput_decode_map), 0, Qnil, prefix,
- "\f\nInput decoding map translations", nomenu, 1, 0, 0);
-
+ {
+ Lisp_Object msg = build_unibyte_string ("\f\nInput decoding map translations");
+ CALLN (Ffuncall,
+ Qdescribe_map_tree,
+ KVAR (current_kboard, Vinput_decode_map), Qnil, Qnil, prefix,
+ msg, nomenu, Qt, Qnil, Qnil);
+ }
return Qnil;
}
@@ -3619,6 +3655,7 @@ void
syms_of_keymap (void)
{
DEFSYM (Qkeymap, "keymap");
+ DEFSYM (Qdescribe_map_tree, "describe-map-tree");
staticpro (&apropos_predicate);
staticpro (&apropos_accumulate);
apropos_predicate = Qnil;
commit afde53cd81c7817c5b3187e60e7a49790e0af832
Author: Stefan Kangas
Date: Sun Oct 18 00:02:55 2020 +0200
Improve substitute-command-keys performance
The previous conversion of describe_vector from C to Lisp for the
keymap and char table case lead to an unacceptable performance hit.
Moving back to the C version, as we do here, makes this function
around 50 times faster.
The Lisp version of `substitute-command-keys' was benchmarked using
the form `(documentation 'dired-mode)', which now takes less than 8 ms
on my machine. This is around 16 times slower than the previous C
version.
Thanks to Stefan Monnier for helpful pointers on benchmarking.
* src/keymap.c (Fhelp__describe_vector): New defun to expose
describe_vector to Lisp for keymaps and char tables.
(syms_of_keymap): New defsubr for Fhelp__describe_vector.
* lisp/help.el (describe-map): Use above defun instead of Lisp
version.
(help--describe-vector): Remove defun; keep it commented out for now.
diff --git a/lisp/help.el b/lisp/help.el
index 06d43857c2..e8dfbdef74 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1367,76 +1367,78 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
;; Next item in list.
(setq vect (cdr vect))))))
-(defun help--describe-vector
- (vector prefix transl partial shadow entire-map mention-shadow)
- "Insert in the current buffer a description of the contents of VECTOR.
-
-PREFIX a prefix key which leads to the keymap that this vector is
-in.
-
-If PARTIAL, it means do not mention suppressed commands
-(that assumes the vector is in a keymap).
-
-SHADOW is a list of keymaps that shadow this map. If it is
-non-nil, look up the key in those maps and don't mention it if it
-is defined by any of them.
-
-ENTIRE-MAP is the vector in which this vector appears.
-If the definition in effect in the whole map does not match
-the one in this vector, we ignore this one."
- ;; Converted from describe_vector in keymap.c.
- (let* ((first t)
- (idx 0))
- (while (< idx (length vector))
- (let* ((val (aref vector idx))
- (definition (keymap--get-keyelt val nil))
- (start-idx idx)
- this-shadowed
- found-range)
- (when (and definition
- ;; Don't mention suppressed commands.
- (not (and partial
- (symbolp definition)
- (get definition 'suppress-keymap)))
- ;; If this binding is shadowed by some other map,
- ;; ignore it.
- (not (and shadow
- (help--shadow-lookup shadow (vector start-idx) t nil)
- (if mention-shadow
- (prog1 nil (setq this-shadowed t))
- t)))
- ;; Ignore this definition if it is shadowed by an earlier
- ;; one in the same keymap.
- (not (and entire-map
- (not (eq (lookup-key entire-map (vector start-idx) t)
- definition)))))
- (when first
- (insert "\n")
- (setq first nil))
- (when (and prefix (> (length prefix) 0))
- (insert (format "%s" prefix)))
- (insert (key-description (vector start-idx) prefix))
- ;; Find all consecutive characters or rows that have the
- ;; same definition.
- (while (equal (keymap--get-keyelt (aref vector (1+ idx)) nil)
- definition)
- (setq found-range t)
- (setq idx (1+ idx)))
- ;; If we have a range of more than one character,
- ;; print where the range reaches to.
- (when found-range
- (insert " .. ")
- (when (and prefix (> (length prefix) 0))
- (insert (format "%s" prefix)))
- (insert (key-description (vector idx) prefix)))
- (if transl
- (help--describe-translation definition)
- (help--describe-command definition))
- (when this-shadowed
- (goto-char (1- (point)))
- (insert " (binding currently shadowed)")
- (goto-char (1+ (point))))))
- (setq idx (1+ idx)))))
+;;;; This Lisp version is 100 times slower than its C equivalent:
+;;
+;; (defun help--describe-vector
+;; (vector prefix transl partial shadow entire-map mention-shadow)
+;; "Insert in the current buffer a description of the contents of VECTOR.
+;;
+;; PREFIX a prefix key which leads to the keymap that this vector is
+;; in.
+;;
+;; If PARTIAL, it means do not mention suppressed commands
+;; (that assumes the vector is in a keymap).
+;;
+;; SHADOW is a list of keymaps that shadow this map. If it is
+;; non-nil, look up the key in those maps and don't mention it if it
+;; is defined by any of them.
+;;
+;; ENTIRE-MAP is the vector in which this vector appears.
+;; If the definition in effect in the whole map does not match
+;; the one in this vector, we ignore this one."
+;; ;; Converted from describe_vector in keymap.c.
+;; (let* ((first t)
+;; (idx 0))
+;; (while (< idx (length vector))
+;; (let* ((val (aref vector idx))
+;; (definition (keymap--get-keyelt val nil))
+;; (start-idx idx)
+;; this-shadowed
+;; found-range)
+;; (when (and definition
+;; ;; Don't mention suppressed commands.
+;; (not (and partial
+;; (symbolp definition)
+;; (get definition 'suppress-keymap)))
+;; ;; If this binding is shadowed by some other map,
+;; ;; ignore it.
+;; (not (and shadow
+;; (help--shadow-lookup shadow (vector start-idx) t nil)
+;; (if mention-shadow
+;; (prog1 nil (setq this-shadowed t))
+;; t)))
+;; ;; Ignore this definition if it is shadowed by an earlier
+;; ;; one in the same keymap.
+;; (not (and entire-map
+;; (not (eq (lookup-key entire-map (vector start-idx) t)
+;; definition)))))
+;; (when first
+;; (insert "\n")
+;; (setq first nil))
+;; (when (and prefix (> (length prefix) 0))
+;; (insert (format "%s" prefix)))
+;; (insert (key-description (vector start-idx) prefix))
+;; ;; Find all consecutive characters or rows that have the
+;; ;; same definition.
+;; (while (equal (keymap--get-keyelt (aref vector (1+ idx)) nil)
+;; definition)
+;; (setq found-range t)
+;; (setq idx (1+ idx)))
+;; ;; If we have a range of more than one character,
+;; ;; print where the range reaches to.
+;; (when found-range
+;; (insert " .. ")
+;; (when (and prefix (> (length prefix) 0))
+;; (insert (format "%s" prefix)))
+;; (insert (key-description (vector idx) prefix)))
+;; (if transl
+;; (help--describe-translation definition)
+;; (help--describe-command definition))
+;; (when this-shadowed
+;; (goto-char (1- (point)))
+;; (insert " (binding currently shadowed)")
+;; (goto-char (1+ (point))))))
+;; (setq idx (1+ idx)))))
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
diff --git a/src/keymap.c b/src/keymap.c
index 9d12c3a47d..5ae8da6a05 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -3328,6 +3328,40 @@ DESCRIBER is the output function used; nil means use `princ'. */)
return unbind_to (count, Qnil);
}
+DEFUN ("help--describe-vector", Fhelp__describe_vector, Shelp__describe_vector, 7, 7, 0,
+ doc: /* Insert in the current buffer a description of the contents of VECTOR.
+
+PREFIX is a string describing the key which leads to the keymap that
+this vector is in.
+
+If PARTIAL, it means do not mention suppressed commands.
+
+SHADOW is a list of keymaps that shadow this map.
+If it is non-nil, look up the key in those maps and don't mention it
+if it is defined by any of them.
+
+ENTIRE-MAP is the keymap in which this vector appears.
+If the definition in effect in the whole map does not match
+the one in this keymap, we ignore this one. */)
+ (Lisp_Object vector, Lisp_Object prefix, Lisp_Object transl,
+ Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map,
+ Lisp_Object mention_shadow)
+{
+ ptrdiff_t count = SPECPDL_INDEX ();
+ specbind (Qstandard_output, Fcurrent_buffer ());
+ CHECK_VECTOR_OR_CHAR_TABLE (vector);
+
+ bool b_transl = NILP (transl) ? false : true;
+ bool b_partial = NILP (partial) ? false : true;
+ bool b_mention_shadow = NILP (mention_shadow) ? false : true;
+
+ describe_vector (vector, prefix, Qnil,
+ b_transl ? describe_translation : describe_command,
+ b_partial, shadow, entire_map,
+ true, b_mention_shadow);
+ return unbind_to (count, Qnil);
+}
+
/* Insert in the current buffer a description of the contents of VECTOR.
We call ELT_DESCRIBER to insert the description of one value found
in VECTOR.
@@ -3726,6 +3760,7 @@ be preferred. */);
defsubr (&Saccessible_keymaps);
defsubr (&Skey_description);
defsubr (&Skeymap__get_keyelt);
+ defsubr (&Shelp__describe_vector);
defsubr (&Sdescribe_vector);
defsubr (&Ssingle_key_description);
defsubr (&Stext_char_description);
commit 5ad2bb0fa95d9c9ae2387c963b453f695577450a
Author: Stefan Kangas
Date: Sun Aug 23 17:20:09 2020 +0200
Translate describe_vector to Lisp
* lisp/help.el (help--describe-vector): New Lisp implementation of
describe_vector.
* src/keymap.c (Fdescribe_vector_internal): Remove defun.
(syms_of_keymap): Remove defsubr for Fdescribe_vector_internal.
diff --git a/lisp/help.el b/lisp/help.el
index 4541d66519..06d43857c2 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1277,8 +1277,8 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
done vect)
(while (and (consp tail) (not done))
(cond ((or (vectorp (car tail)) (char-table-p (car tail)))
- (describe-vector-internal (car tail) prefix transl partial
- shadow map t mention-shadow))
+ (help--describe-vector (car tail) prefix transl partial
+ shadow map mention-shadow))
((consp (car tail))
(let ((event (caar tail))
definition this-shadowed)
@@ -1367,6 +1367,77 @@ TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
;; Next item in list.
(setq vect (cdr vect))))))
+(defun help--describe-vector
+ (vector prefix transl partial shadow entire-map mention-shadow)
+ "Insert in the current buffer a description of the contents of VECTOR.
+
+PREFIX a prefix key which leads to the keymap that this vector is
+in.
+
+If PARTIAL, it means do not mention suppressed commands
+(that assumes the vector is in a keymap).
+
+SHADOW is a list of keymaps that shadow this map. If it is
+non-nil, look up the key in those maps and don't mention it if it
+is defined by any of them.
+
+ENTIRE-MAP is the vector in which this vector appears.
+If the definition in effect in the whole map does not match
+the one in this vector, we ignore this one."
+ ;; Converted from describe_vector in keymap.c.
+ (let* ((first t)
+ (idx 0))
+ (while (< idx (length vector))
+ (let* ((val (aref vector idx))
+ (definition (keymap--get-keyelt val nil))
+ (start-idx idx)
+ this-shadowed
+ found-range)
+ (when (and definition
+ ;; Don't mention suppressed commands.
+ (not (and partial
+ (symbolp definition)
+ (get definition 'suppress-keymap)))
+ ;; If this binding is shadowed by some other map,
+ ;; ignore it.
+ (not (and shadow
+ (help--shadow-lookup shadow (vector start-idx) t nil)
+ (if mention-shadow
+ (prog1 nil (setq this-shadowed t))
+ t)))
+ ;; Ignore this definition if it is shadowed by an earlier
+ ;; one in the same keymap.
+ (not (and entire-map
+ (not (eq (lookup-key entire-map (vector start-idx) t)
+ definition)))))
+ (when first
+ (insert "\n")
+ (setq first nil))
+ (when (and prefix (> (length prefix) 0))
+ (insert (format "%s" prefix)))
+ (insert (key-description (vector start-idx) prefix))
+ ;; Find all consecutive characters or rows that have the
+ ;; same definition.
+ (while (equal (keymap--get-keyelt (aref vector (1+ idx)) nil)
+ definition)
+ (setq found-range t)
+ (setq idx (1+ idx)))
+ ;; If we have a range of more than one character,
+ ;; print where the range reaches to.
+ (when found-range
+ (insert " .. ")
+ (when (and prefix (> (length prefix) 0))
+ (insert (format "%s" prefix)))
+ (insert (key-description (vector idx) prefix)))
+ (if transl
+ (help--describe-translation definition)
+ (help--describe-command definition))
+ (when this-shadowed
+ (goto-char (1- (point)))
+ (insert " (binding currently shadowed)")
+ (goto-char (1+ (point))))))
+ (setq idx (1+ idx)))))
+
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
(declare-function x-display-pixel-width "xfns.c" (&optional terminal))
diff --git a/src/keymap.c b/src/keymap.c
index 2076e29b6f..9d12c3a47d 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -3328,28 +3328,6 @@ DESCRIBER is the output function used; nil means use `princ'. */)
return unbind_to (count, Qnil);
}
-DEFUN ("describe-vector-internal", Fdescribe_vector_internal, Sdescribe_vector_internal, 8, 8, 0,
- doc: /* Insert a description of contents of VECTOR. */)
- (Lisp_Object vector, Lisp_Object prefix, Lisp_Object transl,
- Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map,
- Lisp_Object keymap_p, Lisp_Object mention_shadow)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
- specbind (Qstandard_output, Fcurrent_buffer ());
- CHECK_VECTOR_OR_CHAR_TABLE (vector);
-
- bool b_transl = NILP (transl) ? false : true;
- bool b_partial = NILP (partial) ? false : true;
- bool b_keymap_p = NILP (keymap_p) ? false : true;
- bool b_mention_shadow = NILP (mention_shadow) ? false : true;
-
- describe_vector (vector, prefix, Qnil,
- b_transl ? describe_translation : describe_command,
- b_partial, shadow, entire_map,
- b_keymap_p, b_mention_shadow);
- return unbind_to (count, Qnil);
-}
-
/* Insert in the current buffer a description of the contents of VECTOR.
We call ELT_DESCRIBER to insert the description of one value found
in VECTOR.
@@ -3749,7 +3727,6 @@ be preferred. */);
defsubr (&Skey_description);
defsubr (&Skeymap__get_keyelt);
defsubr (&Sdescribe_vector);
- defsubr (&Sdescribe_vector_internal);
defsubr (&Ssingle_key_description);
defsubr (&Stext_char_description);
defsubr (&Swhere_is_internal);
commit 647b1c5142d7a029a3124e0177112f16f84d3794
Author: Stefan Kangas
Date: Wed Aug 19 12:49:39 2020 +0200
Translate describe_map to Lisp
Third step in converting substitute-command-keys to Lisp.
* lisp/help.el (describe-map): New Lisp version of describe_map.
(help--describe-map-compare, help--describe-translation)
(help--describe-command, help--shadow-lookup): New helper
functions for describe-map.
(help--keymaps-seen, help--previous-description-column): New
variables.
* src/keymap.c
(Fkeymap__get_keyelt): New defun to expose get_keyelt to Lisp.
(Fdescribe_map_tree_old, Fdescribe_map): Remove defuns.
(Fdescribe_vector_internal): New defun to expose describe_vector to
Lisp in a way usable by describe-map.
(syms_of_keymap): New defsubrs for Fkeymap__get_keyelt and
Fdescribe_vector_internal. Remove defsubrs for Fdescribe_map_tree_old
and Fdescribe_map. Remove 'help--keymaps-seen'.
* test/lisp/help-tests.el
(help-tests-substitute-command-keys/shadow): Extend test.
(help-tests-substitute-command-keys/test-mode)
(help-tests-substitute-command-keys/compare-all)
(help-tests-describe-map-tree/no-menu-t)
(help-tests-describe-map-tree/no-menu-nil)
(help-tests-describe-map-tree/mention-shadow-t)
(help-tests-describe-map-tree/mention-shadow-nil)
(help-tests-describe-map-tree/partial-t)
(help-tests-describe-map-tree/partial-nil): New tests.
diff --git a/lisp/help.el b/lisp/help.el
index 2996581f94..4541d66519 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1118,6 +1118,7 @@ Otherwise, return a new string (without any text properties)."
(t (forward-char 1)))))
(buffer-string)))))
+(defvar help--keymaps-seen nil)
(defun describe-map-tree (startmap partial shadow prefix title no-menu
transl always-title mention-shadow)
"Insert a description of the key bindings in STARTMAP.
@@ -1203,6 +1204,169 @@ Any inserted text ends in two newlines (used by
(when print-title
(princ "\n"))))
+(defun help--shadow-lookup (keymap key accept-default remap)
+ "Like `lookup-key', but with command remapping.
+Return nil if the key sequence is too long."
+ ;; Converted from shadow_lookup in keymap.c.
+ (let ((value (lookup-key keymap key accept-default)))
+ (cond ((and (fixnump value) (<= 0 value)))
+ ((and value remap (symbolp value))
+ (or (command-remapping value nil keymap)
+ value))
+ (t value))))
+
+(defvar help--previous-description-column 0)
+(defun help--describe-command (definition)
+ ;; Converted from describe_command in keymap.c.
+ ;; If column 16 is no good, go to col 32;
+ ;; but don't push beyond that--go to next line instead.
+ (let* ((column (current-column))
+ (description-column (cond ((> column 30)
+ (insert "\n")
+ 32)
+ ((or (> column 14)
+ (and (> column 10)
+ (= help--previous-description-column 32)))
+ 32)
+ (t 16))))
+ (indent-to description-column 1)
+ (setq help--previous-description-column description-column)
+ (cond ((symbolp definition)
+ (insert (symbol-name definition) "\n"))
+ ((or (stringp definition) (vectorp definition))
+ (insert "Keyboard Macro\n"))
+ ((keymapp definition)
+ (insert "Prefix Command\n"))
+ (t (insert "??\n")))))
+
+(defun help--describe-translation (definition)
+ ;; Converted from describe_translation in keymap.c.
+ (indent-to 16 1)
+ (cond ((symbolp definition)
+ (insert (symbol-name definition) "\n"))
+ ((or (stringp definition) (vectorp definition))
+ (insert (key-description definition nil) "\n"))
+ ((keymapp definition)
+ (insert "Prefix Command\n"))
+ (t (insert "??\n"))))
+
+(defun help--describe-map-compare (a b)
+ (let ((a (car a))
+ (b (car b)))
+ (cond ((and (fixnump a) (fixnump b)) (< a b))
+ ;; ((and (not (fixnump a)) (fixnump b)) nil) ; not needed
+ ((and (fixnump a) (not (fixnump b))) t)
+ ((and (symbolp a) (symbolp b))
+ ;; Sort the keystroke names in the "natural" way, with (for
+ ;; instance) "" coming between "" and "".
+ (string-version-lessp (symbol-name a) (symbol-name b)))
+ (t nil))))
+
+(defun describe-map (map prefix transl partial shadow nomenu mention-shadow)
+ "Describe the contents of keymap MAP.
+Assume that this keymap itself is reached by the sequence of
+prefix keys PREFIX (a string or vector).
+
+TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW are as in
+`describe-map-tree'."
+ ;; Converted from describe_map in keymap.c.
+ (let* ((suppress (and partial 'suppress-keymap))
+ (map (keymap-canonicalize map))
+ (tail map)
+ (first t)
+ done vect)
+ (while (and (consp tail) (not done))
+ (cond ((or (vectorp (car tail)) (char-table-p (car tail)))
+ (describe-vector-internal (car tail) prefix transl partial
+ shadow map t mention-shadow))
+ ((consp (car tail))
+ (let ((event (caar tail))
+ definition this-shadowed)
+ ;; Ignore bindings whose "prefix" are not really
+ ;; valid events. (We get these in the frames and
+ ;; buffers menu.)
+ (and (or (symbolp event) (fixnump event))
+ (not (and nomenu (eq event 'menu-bar)))
+ ;; Don't show undefined commands or suppressed
+ ;; commands.
+ (setq definition (keymap--get-keyelt (cdr (car tail)) nil))
+ (or (not (symbolp definition))
+ (null (get definition suppress)))
+ ;; Don't show a command that isn't really
+ ;; visible because a local definition of the
+ ;; same key shadows it.
+ (or (not shadow)
+ (let ((tem (help--shadow-lookup shadow (vector event) t nil)))
+ (cond ((null tem) t)
+ ;; If both bindings are keymaps,
+ ;; this key is a prefix key, so
+ ;; don't say it is shadowed.
+ ((and (keymapp definition) (keymapp tem)) t)
+ ;; Avoid generating duplicate
+ ;; entries if the shadowed binding
+ ;; has the same definition.
+ ((and mention-shadow (not (eq tem definition)))
+ (setq this-shadowed t))
+ (t nil))))
+ (push (list event definition this-shadowed) vect))))
+ ((eq (car tail) 'keymap)
+ ;; The same keymap might be in the structure twice, if
+ ;; we're using an inherited keymap. So skip anything
+ ;; we've already encountered.
+ (let ((tem (assq tail help--keymaps-seen)))
+ (if (and (consp tem)
+ (equal (car tem) prefix))
+ (setq done t)
+ (push (cons tail prefix) help--keymaps-seen)))))
+ (setq tail (cdr tail)))
+ ;; If we found some sparse map events, sort them.
+ (let ((vect (sort vect 'help--describe-map-compare)))
+ ;; Now output them in sorted order.
+ (while vect
+ (let* ((elem (car vect))
+ (start (car elem))
+ (definition (cadr elem))
+ (shadowed (caddr elem))
+ (end start))
+ (when first
+ (setq help--previous-description-column 0)
+ (insert "\n")
+ (setq first nil))
+ ;; Find consecutive chars that are identically defined.
+ (when (fixnump start)
+ (while (and (cdr vect)
+ (let ((this-event (caar vect))
+ (this-definition (cadar vect))
+ (this-shadowed (caddar vect))
+ (next-event (caar (cdr vect)))
+ (next-definition (cadar (cdr vect)))
+ (next-shadowed (caddar (cdr vect))))
+ (and (eq next-event (1+ this-event))
+ (equal next-definition this-definition)
+ (eq this-shadowed next-shadowed))))
+ (setq vect (cdr vect))
+ (setq end (caar vect))))
+ ;; Now START .. END is the range to describe next.
+ ;; Insert the string to describe the event START.
+ (insert (key-description (vector start) prefix))
+ (when (not (eq start end))
+ (insert " .. " (key-description (vector end) prefix)))
+ ;; Print a description of the definition of this character.
+ ;; Called function will take care of spacing out far enough
+ ;; for alignment purposes.
+ (if transl
+ (help--describe-translation definition)
+ (help--describe-command definition))
+ ;; Print a description of the definition of this character.
+ ;; elt_describer will take care of spacing out far enough for
+ ;; alignment purposes.
+ (when shadowed
+ (goto-char (max (1- (point)) (point-min)))
+ (insert "\n (this binding is currently shadowed)")
+ (goto-char (min (1+ (point)) (point-max)))))
+ ;; Next item in list.
+ (setq vect (cdr vect))))))
+
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
(declare-function x-display-pixel-width "xfns.c" (&optional terminal))
diff --git a/src/keymap.c b/src/keymap.c
index 704b89eeec..2076e29b6f 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -679,6 +679,23 @@ usage: (map-keymap FUNCTION KEYMAP) */)
return Qnil;
}
+DEFUN ("keymap--get-keyelt", Fkeymap__get_keyelt, Skeymap__get_keyelt, 2, 2, 0,
+ doc: /* Given OBJECT which was found in a slot in a keymap,
+trace indirect definitions to get the actual definition of that slot.
+An indirect definition is a list of the form
+(KEYMAP . INDEX), where KEYMAP is a keymap or a symbol defined as one
+and INDEX is the object to look up in KEYMAP to yield the definition.
+
+Also if OBJECT has a menu string as the first element,
+remove that. Also remove a menu help string as second element.
+
+If AUTOLOAD, load autoloadable keymaps
+that are referred to with indirection. */)
+ (Lisp_Object object, Lisp_Object autoload)
+{
+ return get_keyelt (object, NILP (autoload) ? false : true);
+}
+
/* Given OBJECT which was found in a slot in a keymap,
trace indirect definitions to get the actual definition of that slot.
An indirect definition is a list of the form
@@ -2915,37 +2932,6 @@ You type Translation\n\
Any inserted text ends in two newlines (used by `help-make-xrefs'). */
-DEFUN ("describe-map-tree-old", Fdescribe_map_tree_old, Sdescribe_map_tree_old, 1, 8, 0,
- doc: /* This is just temporary. */)
- (Lisp_Object startmap, Lisp_Object partial, Lisp_Object shadow,
- Lisp_Object prefix, Lisp_Object title, Lisp_Object nomenu,
- Lisp_Object transl, Lisp_Object always_title)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
- char *title_string;
-
- if ( !NILP (title) )
- {
- CHECK_STRING (title);
- title_string = SSDATA(title);
- }
- else
- {
- title_string = NULL;
- }
-
- bool b_partial = NILP (partial) ? false : true;
- bool b_nomenu = NILP (nomenu) ? false : true;
- bool b_transl = NILP (transl) ? false : true;
- bool b_always_title = NILP (always_title) ? false : true;
-
- /* specbind (Qstandard_output, Fcurrent_buffer ()); */
- describe_map_tree (startmap, b_partial, shadow, prefix, title_string,
- b_nomenu, b_transl, b_always_title, true);
-
- return unbind_to (count, Qnil);
-}
-
void
describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow,
Lisp_Object prefix, const char *title, bool nomenu,
@@ -3131,27 +3117,6 @@ describe_map_compare (const void *aa, const void *bb)
return 0;
}
-DEFUN ("describe-map", Fdescribe_map, Sdescribe_map, 1, 7, 0,
- doc: /* This is a temporary definition preparing the transition
-of this function to Lisp. */)
- (Lisp_Object map, Lisp_Object prefix,
- Lisp_Object transl, Lisp_Object partial, Lisp_Object shadow,
- Lisp_Object nomenu, Lisp_Object mention_shadow)
-{
- ptrdiff_t count = SPECPDL_INDEX ();
-
- bool b_transl = NILP(transl) ? false : true;
- bool b_partial = NILP (partial) ? false : true;
- bool b_nomenu = NILP (nomenu) ? false : true;
- bool b_mention_shadow = NILP (mention_shadow) ? false : true;
- describe_map (map, prefix,
- b_transl ? describe_translation : describe_command,
- b_partial, shadow, &Vhelp__keymaps_seen,
- b_nomenu, b_mention_shadow);
-
- return unbind_to (count, Qnil);
-}
-
/* Describe the contents of map MAP, assuming that this map itself is
reached by the sequence of prefix keys PREFIX (a string or vector).
PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */
@@ -3363,6 +3328,28 @@ DESCRIBER is the output function used; nil means use `princ'. */)
return unbind_to (count, Qnil);
}
+DEFUN ("describe-vector-internal", Fdescribe_vector_internal, Sdescribe_vector_internal, 8, 8, 0,
+ doc: /* Insert a description of contents of VECTOR. */)
+ (Lisp_Object vector, Lisp_Object prefix, Lisp_Object transl,
+ Lisp_Object partial, Lisp_Object shadow, Lisp_Object entire_map,
+ Lisp_Object keymap_p, Lisp_Object mention_shadow)
+{
+ ptrdiff_t count = SPECPDL_INDEX ();
+ specbind (Qstandard_output, Fcurrent_buffer ());
+ CHECK_VECTOR_OR_CHAR_TABLE (vector);
+
+ bool b_transl = NILP (transl) ? false : true;
+ bool b_partial = NILP (partial) ? false : true;
+ bool b_keymap_p = NILP (keymap_p) ? false : true;
+ bool b_mention_shadow = NILP (mention_shadow) ? false : true;
+
+ describe_vector (vector, prefix, Qnil,
+ b_transl ? describe_translation : describe_command,
+ b_partial, shadow, entire_map,
+ b_keymap_p, b_mention_shadow);
+ return unbind_to (count, Qnil);
+}
+
/* Insert in the current buffer a description of the contents of VECTOR.
We call ELT_DESCRIBER to insert the description of one value found
in VECTOR.
@@ -3706,10 +3693,6 @@ exists, bindings using keys without modifiers (or only with meta) will
be preferred. */);
Vwhere_is_preferred_modifier = Qnil;
where_is_preferred_modifier = 0;
- DEFVAR_LISP ("help--keymaps-seen", Vhelp__keymaps_seen,
- doc: /* List of seen keymaps.
-This is used for internal purposes only. */);
- Vhelp__keymaps_seen = Qnil;
DEFSYM (Qmenu_bar, "menu-bar");
DEFSYM (Qmode_line, "mode-line");
@@ -3764,9 +3747,9 @@ This is used for internal purposes only. */);
defsubr (&Scurrent_active_maps);
defsubr (&Saccessible_keymaps);
defsubr (&Skey_description);
- defsubr (&Sdescribe_map_tree_old);
- defsubr (&Sdescribe_map);
+ defsubr (&Skeymap__get_keyelt);
defsubr (&Sdescribe_vector);
+ defsubr (&Sdescribe_vector_internal);
defsubr (&Ssingle_key_description);
defsubr (&Stext_char_description);
defsubr (&Swhere_is_internal);
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index 048b6c325e..aff5d1853a 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -194,6 +194,17 @@ M-s next-matching-history-element
(defvar help-tests-major-mode-map
(let ((map (make-keymap)))
(define-key map "x" 'foo-original)
+ (define-key map "1" 'foo-range)
+ (define-key map "2" 'foo-range)
+ (define-key map "3" 'foo-range)
+ (define-key map "4" 'foo-range)
+ (define-key map (kbd "C-e") 'foo-something)
+ (define-key map '[F1] 'foo-function-key1)
+ (define-key map "(" 'short-range)
+ (define-key map ")" 'short-range)
+ (define-key map "a" 'foo-other-range)
+ (define-key map "b" 'foo-other-range)
+ (define-key map "c" 'foo-other-range)
map))
(define-derived-mode help-tests-major-mode nil
@@ -202,12 +213,13 @@ M-s next-matching-history-element
(defvar help-tests-minor-mode-map
(let ((map (make-keymap)))
(define-key map "x" 'foo-shadow)
+ (define-key map (kbd "C-e") 'foo-shadow)
map))
(define-minor-mode help-tests-minor-mode
"Minor mode for testing shadowing.")
-(ert-deftest help-tests-substitute-command-keys/shadow ()
+(ert-deftest help-tests-substitute-command-keys/test-mode ()
(with-substitute-command-keys-test
(with-temp-buffer
(help-tests-major-mode)
@@ -216,17 +228,35 @@ M-s next-matching-history-element
key binding
--- -------
+( .. ) short-range
+1 .. 4 foo-range
+a .. c foo-other-range
+
+C-e foo-something
x foo-original
+ foo-function-key1
+
+"))))
-")
+(ert-deftest help-tests-substitute-command-keys/shadow ()
+ (with-substitute-command-keys-test
+ (with-temp-buffer
+ (help-tests-major-mode)
(help-tests-minor-mode)
(test "\\{help-tests-major-mode-map}"
"\
key binding
--- -------
+( .. ) short-range
+1 .. 4 foo-range
+a .. c foo-other-range
+
+C-e foo-something
+ (this binding is currently shadowed)
x foo-original
(this binding is currently shadowed)
+ foo-function-key1
"))))
@@ -247,6 +277,98 @@ key binding
")))))
+(ert-deftest help-tests-describe-map-tree/no-menu-t ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (menu-bar keymap
+ (foo menu-item "Foo" foo
+ :enable mark-active
+ :help "Help text"))))))
+ (describe-map-tree map nil nil nil nil t nil nil nil)
+ (should (equal (buffer-string) "key binding
+--- -------
+
+C-a foo
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/no-menu-nil ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (menu-bar keymap
+ (foo menu-item "Foo" foo
+ :enable mark-active
+ :help "Help text"))))))
+ (describe-map-tree map nil nil nil nil nil nil nil nil)
+ (should (equal (buffer-string) "key binding
+--- -------
+
+C-a foo
+ Prefix Command
+
+ foo
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/mention-shadow-t ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . bar))))
+ (shadow-maps '((keymap . ((1 . baz))))))
+ (describe-map-tree map t shadow-maps nil nil t nil nil t)
+ (should (equal (buffer-string) "key binding
+--- -------
+
+C-a foo
+ (this binding is currently shadowed)
+C-b bar
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/mention-shadow-nil ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . bar))))
+ (shadow-maps '((keymap . ((1 . baz))))))
+ (describe-map-tree map t shadow-maps nil nil t nil nil nil)
+ (should (equal (buffer-string) "key binding
+--- -------
+
+C-b bar
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/partial-t ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . undefined)))))
+ (describe-map-tree map t nil nil nil nil nil nil nil)
+ (should (equal (buffer-string) "key binding
+--- -------
+
+C-a foo
+
+")))))
+
+(ert-deftest help-tests-describe-map-tree/partial-nil ()
+ (with-temp-buffer
+ (let ((standard-output (current-buffer))
+ (map '(keymap . ((1 . foo)
+ (2 . undefined)))))
+ (describe-map-tree map nil nil nil nil nil nil nil nil)
+ (should (equal (buffer-string) "key binding
+--- -------
+
+C-a foo
+C-b undefined
+
+")))))
+
;; TODO: This is a temporary test that should be removed together with
;; substitute-command-keys-old.
(ert-deftest help-tests-substitute-command-keys/compare ()
@@ -261,6 +383,15 @@ key binding
(outline-minor-mode)
(test-re "\\{c-mode-map}" ".*"))))
+(ert-deftest help-tests-substitute-command-keys/compare-all ()
+ (let (keymaps)
+ (mapatoms (lambda (var)
+ (when (keymapp var)
+ (push var keymaps))))
+ (dolist (keymap keymaps)
+ (with-substitute-command-keys-test
+ (test-re (concat "\\{" (symbol-name keymap) "}") ".*")))))
+
(provide 'help-tests)
;;; help-tests.el ends here
commit afd31f9e62e551a3f286d1d581a56ef1de33ee94
Author: Stefan Kangas
Date: Sat Oct 17 20:55:04 2020 +0200
Translate describe_map_tree to Lisp
This is the second step in converting substitute-command-keys to Lisp.
* lisp/help.el (describe-map-tree): New Lisp version of
describe_map_tree.
(substitute-command-keys): Update to use above function.
* src/keymap.c (Fdescribe_map): New defun to expose describe_map to
Lisp.
* src/keymap.c (syms_of_keymap): New variable 'help--keymaps-seen'; a
temporary kludge planned for removal. New defsubr for Fdescribe_map.
diff --git a/lisp/help.el b/lisp/help.el
index 8d0d9c4270..2996581f94 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1013,7 +1013,8 @@ Otherwise, return a new string (without any text properties)."
(insert string)
(goto-char (point-min))
(while (< (point) (point-max))
- (let ((orig-point (point))
+ (let ((standard-output (current-buffer))
+ (orig-point (point))
end-point active-maps
close generate-summary)
(cond
@@ -1101,7 +1102,7 @@ Otherwise, return a new string (without any text properties)."
;; If this one's not active, get nil.
(let ((earlier-maps (cdr (memq this-keymap (reverse active-maps)))))
(describe-map-tree this-keymap t (nreverse earlier-maps)
- nil nil t nil nil))))))))
+ nil nil t nil nil t))))))))
;; 2. Handle quotes.
((and (eq (get-quoting-style) 'curve)
(or (and (= (following-char) ?\`)
@@ -1117,6 +1118,91 @@ Otherwise, return a new string (without any text properties)."
(t (forward-char 1)))))
(buffer-string)))))
+(defun describe-map-tree (startmap partial shadow prefix title no-menu
+ transl always-title mention-shadow)
+ "Insert a description of the key bindings in STARTMAP.
+This is followed by the key bindings of all maps reachable
+through STARTMAP.
+
+If PARTIAL is non-nil, omit certain uninteresting commands
+\(such as `undefined').
+
+If SHADOW is non-nil, it is a list of maps; don't mention keys
+which would be shadowed by any of them.
+
+If PREFIX is non-nil, mention only keys that start with PREFIX.
+
+If TITLE is non-nil, is a string to insert at the beginning.
+TITLE should not end with a colon or a newline; we supply that.
+
+If NOMENU is non-nil, then omit menu-bar commands.
+
+If TRANSL is non-nil, the definitions are actually key
+translations so print strings and vectors differently.
+
+If ALWAYS_TITLE is non-nil, print the title even if there are no
+maps to look through.
+
+If MENTION_SHADOW is non-nil, then when something is shadowed by
+SHADOW, don't omit it; instead, mention it but say it is
+shadowed.
+
+Any inserted text ends in two newlines (used by
+`help-make-xrefs')."
+ (let* ((amaps (accessible-keymaps startmap prefix))
+ (orig-maps (if no-menu
+ (progn
+ ;; Delete from MAPS each element that is for
+ ;; the menu bar.
+ (let* ((tail amaps)
+ result)
+ (while tail
+ (let ((elem (car tail)))
+ (when (not (and (>= (length (car elem)) 1)
+ (eq (elt (car elem) 0) 'menu-bar)))
+ (setq result (append result (list elem)))))
+ (setq tail (cdr tail)))
+ result))
+ amaps))
+ (maps orig-maps)
+ (print-title (or maps always-title)))
+ ;; Print title.
+ (when print-title
+ (princ (concat (if title
+ (concat title
+ (if prefix
+ (concat " Starting With "
+ (key-description prefix)))
+ ":\n"))
+ "key binding\n"
+ "--- -------\n")))
+ ;; Describe key bindings.
+ (setq help--keymaps-seen nil)
+ (while (consp maps)
+ (let* ((elt (car maps))
+ (elt-prefix (car elt))
+ (sub-shadows (lookup-key shadow elt-prefix t)))
+ (when (if (natnump sub-shadows)
+ (prog1 t (setq sub-shadows nil))
+ ;; Describe this map iff elt_prefix is bound to a
+ ;; keymap, since otherwise it completely shadows this
+ ;; map.
+ (or (keymapp sub-shadows)
+ (null sub-shadows)
+ (consp sub-shadows)
+ (not (keymapp (car sub-shadows)))))
+ ;; Maps we have already listed in this loop shadow this map.
+ (let ((tail orig-maps))
+ (while (not (equal tail maps))
+ (when (equal (car (car tail)) elt-prefix)
+ (setq sub-shadows (cons (cdr (car tail)) sub-shadows)))
+ (setq tail (cdr tail))))
+ (describe-map (cdr elt) elt-prefix transl partial
+ sub-shadows no-menu mention-shadow)))
+ (setq maps (cdr maps)))
+ (when print-title
+ (princ "\n"))))
+
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
(declare-function x-display-pixel-width "xfns.c" (&optional terminal))
diff --git a/src/keymap.c b/src/keymap.c
index 05b0814c47..704b89eeec 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -2915,7 +2915,7 @@ You type Translation\n\
Any inserted text ends in two newlines (used by `help-make-xrefs'). */
-DEFUN ("describe-map-tree", Fdescribe_map_tree, Sdescribe_map_tree, 1, 8, 0,
+DEFUN ("describe-map-tree-old", Fdescribe_map_tree_old, Sdescribe_map_tree_old, 1, 8, 0,
doc: /* This is just temporary. */)
(Lisp_Object startmap, Lisp_Object partial, Lisp_Object shadow,
Lisp_Object prefix, Lisp_Object title, Lisp_Object nomenu,
@@ -3131,6 +3131,27 @@ describe_map_compare (const void *aa, const void *bb)
return 0;
}
+DEFUN ("describe-map", Fdescribe_map, Sdescribe_map, 1, 7, 0,
+ doc: /* This is a temporary definition preparing the transition
+of this function to Lisp. */)
+ (Lisp_Object map, Lisp_Object prefix,
+ Lisp_Object transl, Lisp_Object partial, Lisp_Object shadow,
+ Lisp_Object nomenu, Lisp_Object mention_shadow)
+{
+ ptrdiff_t count = SPECPDL_INDEX ();
+
+ bool b_transl = NILP(transl) ? false : true;
+ bool b_partial = NILP (partial) ? false : true;
+ bool b_nomenu = NILP (nomenu) ? false : true;
+ bool b_mention_shadow = NILP (mention_shadow) ? false : true;
+ describe_map (map, prefix,
+ b_transl ? describe_translation : describe_command,
+ b_partial, shadow, &Vhelp__keymaps_seen,
+ b_nomenu, b_mention_shadow);
+
+ return unbind_to (count, Qnil);
+}
+
/* Describe the contents of map MAP, assuming that this map itself is
reached by the sequence of prefix keys PREFIX (a string or vector).
PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above. */
@@ -3685,6 +3706,10 @@ exists, bindings using keys without modifiers (or only with meta) will
be preferred. */);
Vwhere_is_preferred_modifier = Qnil;
where_is_preferred_modifier = 0;
+ DEFVAR_LISP ("help--keymaps-seen", Vhelp__keymaps_seen,
+ doc: /* List of seen keymaps.
+This is used for internal purposes only. */);
+ Vhelp__keymaps_seen = Qnil;
DEFSYM (Qmenu_bar, "menu-bar");
DEFSYM (Qmode_line, "mode-line");
@@ -3739,7 +3764,8 @@ be preferred. */);
defsubr (&Scurrent_active_maps);
defsubr (&Saccessible_keymaps);
defsubr (&Skey_description);
- defsubr (&Sdescribe_map_tree);
+ defsubr (&Sdescribe_map_tree_old);
+ defsubr (&Sdescribe_map);
defsubr (&Sdescribe_vector);
defsubr (&Ssingle_key_description);
defsubr (&Stext_char_description);
commit dcf9cd47ae71e39eb616d77acb531ac11357391f
Author: Stefan Kangas
Date: Mon Jul 8 18:37:50 2019 +0200
Add new Lisp implementation of substitute-command-keys
This is only the first step towards a full Lisp implementation, and
does not remove the old C code. On the contrary, it is partly based
on using the old C code, which is to be replaced in steps. This also
makes it easy to test that it produces the same output as the old.
* src/doc.c (Fsubstitute_command_keys_old): Rename from
Fsubstitute_command_keys.
(Fget_quoting_style): New defun to expose text_quoting_style to Lisp.
(syms_of_doc): Expose above symbols.
* lisp/help.el (substitute-command-keys): New Lisp version of
substitute-command-keys. (Bug#8951)
* src/keymap.c
(Fdescribe_map_tree): New defun to expose describe_map_tree to Lisp.
(syms_of_keymap): New defsubr for Fdescribe_map_tree.
* src/keyboard.c (help_echo_substitute_command_keys):
* src/doc.c (Fdocumentation, Fdocumentation_property):
* src/print.c (print_error_message):
* src/syntax.c (Finternal_describe_syntax_value): Fix calls to use new
Lisp implementation of substitute-command-keys.
* test/src/doc-tests.el: Remove file.
* test/lisp/help-tests.el: Add tests for substitute-command-keys
copied from above file.
diff --git a/lisp/help.el b/lisp/help.el
index 9b7355c6b6..8d0d9c4270 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -973,6 +973,150 @@ is currently activated with completion."
minor-modes nil)
(setq minor-modes (cdr minor-modes)))))
result))
+
+
+(defun substitute-command-keys (string)
+ "Substitute key descriptions for command names in STRING.
+Each substring of the form \\\\=[COMMAND] is replaced by either a
+keystroke sequence that invokes COMMAND, or \"M-x COMMAND\" if COMMAND
+is not on any keys.
+
+Each substring of the form \\\\={MAPVAR} is replaced by a summary of
+the value of MAPVAR as a keymap. This summary is similar to the one
+produced by ‘describe-bindings’. The summary ends in two newlines
+(used by the helper function ‘help-make-xrefs’ to find the end of the
+summary).
+
+Each substring of the form \\\\= specifies the use of MAPVAR
+as the keymap for future \\\\=[COMMAND] substrings.
+
+Each grave accent \\=` is replaced by left quote, and each apostrophe \\='
+is replaced by right quote. Left and right quote characters are
+specified by ‘text-quoting-style’.
+
+\\\\== quotes the following character and is discarded; thus, \\\\==\\\\== puts \\\\==
+into the output, \\\\==\\[ puts \\[ into the output, and \\\\==\\=` puts \\=` into the
+output.
+
+Return the original STRING if no substitutions are made.
+Otherwise, return a new string (without any text properties)."
+ (when (not (null string))
+ ;; KEYMAP is either nil (which means search all the active
+ ;; keymaps) or a specified local map (which means search just that
+ ;; and the global map). If non-nil, it might come from
+ ;; overriding-local-map, or from a \\ construct in STRING
+ ;; itself.
+ (let ((keymap overriding-local-map)
+ (inhibit-modification-hooks t)
+ (orig-buf (current-buffer)))
+ (with-temp-buffer
+ (insert string)
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (let ((orig-point (point))
+ end-point active-maps
+ close generate-summary)
+ (cond
+ ;; 1. Handle all sequences starting with "\"
+ ((= (following-char) ?\\)
+ (ignore-errors
+ (forward-char 1))
+ (cond
+ ;; 1A. Ignore \= at end of string.
+ ((and (= (+ (point) 1) (point-max))
+ (= (following-char) ?=))
+ (forward-char 1))
+ ;; 1B. \= quotes the next character; thus, to put in \[
+ ;; without its special meaning, use \=\[.
+ ((= (following-char) ?=)
+ (goto-char orig-point)
+ (delete-char 2)
+ (ignore-errors
+ (forward-char 1)))
+ ;; 1C. \[foo] is replaced with the keybinding.
+ ((and (= (following-char) ?\[)
+ (save-excursion
+ (prog1 (search-forward "]" nil t)
+ (setq end-point (- (point) 2)))))
+ (goto-char orig-point)
+ (delete-char 2)
+ (let* ((fun (intern (buffer-substring (point) (1- end-point))))
+ (key (with-current-buffer orig-buf
+ (where-is-internal fun keymap t))))
+ ;; If this a command remap, we need to follow it.
+ (when (and (vectorp key)
+ (> (length key) 1)
+ (eq (aref key 0) 'remap)
+ (symbolp (aref key 1)))
+ (setq fun (aref key 1))
+ (setq key (with-current-buffer orig-buf
+ (where-is-internal fun keymap t))))
+ (if (not key)
+ ;; Function is not on any key.
+ (progn (insert "M-x ")
+ (goto-char (+ end-point 3))
+ (delete-char 1))
+ ;; Function is on a key.
+ (delete-char (- end-point (point)))
+ (insert (key-description key)))))
+ ;; 1D. \{foo} is replaced with a summary of the keymap
+ ;; (symbol-value foo).
+ ;; \ just sets the keymap used for \[cmd].
+ ((and (or (and (= (following-char) ?{)
+ (setq close "}")
+ (setq generate-summary t))
+ (and (= (following-char) ?<)
+ (setq close ">")))
+ (or (save-excursion
+ (prog1 (search-forward close nil t)
+ (setq end-point (- (point) 2))))))
+ (goto-char orig-point)
+ (delete-char 2)
+ (let* ((name (intern (buffer-substring (point) (1- end-point))))
+ this-keymap)
+ (delete-char (- end-point (point)))
+ ;; Get the value of the keymap in TEM, or nil if
+ ;; undefined. Do this in the user's current buffer
+ ;; in case it is a local variable.
+ (with-current-buffer orig-buf
+ ;; This is for computing the SHADOWS arg for
+ ;; describe-map-tree.
+ (setq active-maps (current-active-maps))
+ (when (boundp name)
+ (setq this-keymap (and (keymapp (symbol-value name))
+ (symbol-value name)))))
+ (cond
+ ((null this-keymap)
+ (insert "\nUses keymap "
+ (substitute-command-keys "`")
+ (symbol-name name)
+ (substitute-command-keys "'")
+ ", which is not currently defined.\n")
+ (unless generate-summary
+ (setq keymap nil)))
+ ((not generate-summary)
+ (setq keymap this-keymap))
+ (t
+ ;; Get the list of active keymaps that precede this one.
+ ;; If this one's not active, get nil.
+ (let ((earlier-maps (cdr (memq this-keymap (reverse active-maps)))))
+ (describe-map-tree this-keymap t (nreverse earlier-maps)
+ nil nil t nil nil))))))))
+ ;; 2. Handle quotes.
+ ((and (eq (get-quoting-style) 'curve)
+ (or (and (= (following-char) ?\`)
+ (prog1 t (insert "‘")))
+ (and (= (following-char) ?')
+ (prog1 t (insert "’")))))
+ (delete-char 1))
+ ((and (eq (get-quoting-style) 'straight)
+ (= (following-char) ?\`))
+ (insert "'")
+ (delete-char 1))
+ ;; 3. Nothing to do -- next character.
+ (t (forward-char 1)))))
+ (buffer-string)))))
+
(declare-function x-display-pixel-height "xfns.c" (&optional terminal))
(declare-function x-display-pixel-width "xfns.c" (&optional terminal))
diff --git a/src/doc.c b/src/doc.c
index 18ab346cd1..212ebe9633 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -415,7 +415,7 @@ string is passed through `substitute-command-keys'. */)
}
if (NILP (raw))
- doc = Fsubstitute_command_keys (doc);
+ doc = call1 (Qsubstitute_command_keys, doc);
return doc;
}
@@ -472,7 +472,7 @@ aren't strings. */)
tem = Feval (tem, Qnil);
if (NILP (raw) && STRINGP (tem))
- tem = Fsubstitute_command_keys (tem);
+ tem = call1 (Qsubstitute_command_keys, tem);
return tem;
}
@@ -696,8 +696,27 @@ text_quoting_style (void)
return CURVE_QUOTING_STYLE;
}
-DEFUN ("substitute-command-keys", Fsubstitute_command_keys,
- Ssubstitute_command_keys, 1, 1, 0,
+/* This is just a Lisp wrapper for text_quoting_style above. */
+DEFUN ("get-quoting-style", Fget_quoting_style,
+ Sget_quoting_style, 0, 0, 0,
+ doc: /* Return the current effective text quoting style.
+See variable `text-quoting-style'. */)
+ (void)
+{
+ switch (text_quoting_style ())
+ {
+ case STRAIGHT_QUOTING_STYLE:
+ return Qstraight;
+ case CURVE_QUOTING_STYLE:
+ return Qcurve;
+ case GRAVE_QUOTING_STYLE:
+ default:
+ return Qgrave;
+ }
+}
+
+DEFUN ("substitute-command-keys-old", Fsubstitute_command_keys_old,
+ Ssubstitute_command_keys_old, 1, 1, 0,
doc: /* Substitute key descriptions for command names in STRING.
Each substring of the form \\=\\[COMMAND] is replaced by either a
keystroke sequence that invokes COMMAND, or "M-x COMMAND" if COMMAND
@@ -884,12 +903,12 @@ Otherwise, return a new string (without any text properties). */)
{
name = Fsymbol_name (name);
AUTO_STRING (msg_prefix, "\nUses keymap `");
- insert1 (Fsubstitute_command_keys (msg_prefix));
+ insert1 (Fsubstitute_command_keys_old (msg_prefix));
insert_from_string (name, 0, 0,
SCHARS (name),
SBYTES (name), 1);
AUTO_STRING (msg_suffix, "', which is not currently defined.\n");
- insert1 (Fsubstitute_command_keys (msg_suffix));
+ insert1 (Fsubstitute_command_keys_old (msg_suffix));
if (!generate_summary)
keymap = Qnil;
}
@@ -1002,9 +1021,11 @@ Otherwise, return a new string (without any text properties). */)
void
syms_of_doc (void)
{
+ DEFSYM (Qsubstitute_command_keys, "substitute-command-keys");
DEFSYM (Qfunction_documentation, "function-documentation");
DEFSYM (Qgrave, "grave");
DEFSYM (Qstraight, "straight");
+ DEFSYM (Qcurve, "curve");
DEFVAR_LISP ("internal-doc-file-name", Vdoc_file_name,
doc: /* Name of file containing documentation strings of built-in symbols. */);
@@ -1036,5 +1057,6 @@ otherwise. */);
defsubr (&Sdocumentation);
defsubr (&Sdocumentation_property);
defsubr (&Ssnarf_documentation);
- defsubr (&Ssubstitute_command_keys);
+ defsubr (&Sget_quoting_style);
+ defsubr (&Ssubstitute_command_keys_old);
}
diff --git a/src/keyboard.c b/src/keyboard.c
index 10d2f6323e..2e0143379a 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2040,7 +2040,7 @@ help_echo_substitute_command_keys (Lisp_Object help)
help)))
return help;
- return Fsubstitute_command_keys (help);
+ return call1 (Qsubstitute_command_keys, help);
}
/* Display the help-echo property of the character after the mouse pointer.
@@ -7856,7 +7856,7 @@ parse_menu_item (Lisp_Object item, int inmenubar)
/* The previous code preferred :key-sequence to :keys, so we
preserve this behavior. */
if (STRINGP (keyeq) && !CONSP (keyhint))
- keyeq = concat2 (space_space, Fsubstitute_command_keys (keyeq));
+ keyeq = concat2 (space_space, call1 (Qsubstitute_command_keys, keyeq));
else
{
Lisp_Object prefix = keyeq;
diff --git a/src/keymap.c b/src/keymap.c
index 0608bdddee..05b0814c47 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -2915,6 +2915,37 @@ You type Translation\n\
Any inserted text ends in two newlines (used by `help-make-xrefs'). */
+DEFUN ("describe-map-tree", Fdescribe_map_tree, Sdescribe_map_tree, 1, 8, 0,
+ doc: /* This is just temporary. */)
+ (Lisp_Object startmap, Lisp_Object partial, Lisp_Object shadow,
+ Lisp_Object prefix, Lisp_Object title, Lisp_Object nomenu,
+ Lisp_Object transl, Lisp_Object always_title)
+{
+ ptrdiff_t count = SPECPDL_INDEX ();
+ char *title_string;
+
+ if ( !NILP (title) )
+ {
+ CHECK_STRING (title);
+ title_string = SSDATA(title);
+ }
+ else
+ {
+ title_string = NULL;
+ }
+
+ bool b_partial = NILP (partial) ? false : true;
+ bool b_nomenu = NILP (nomenu) ? false : true;
+ bool b_transl = NILP (transl) ? false : true;
+ bool b_always_title = NILP (always_title) ? false : true;
+
+ /* specbind (Qstandard_output, Fcurrent_buffer ()); */
+ describe_map_tree (startmap, b_partial, shadow, prefix, title_string,
+ b_nomenu, b_transl, b_always_title, true);
+
+ return unbind_to (count, Qnil);
+}
+
void
describe_map_tree (Lisp_Object startmap, bool partial, Lisp_Object shadow,
Lisp_Object prefix, const char *title, bool nomenu,
@@ -3708,6 +3739,7 @@ be preferred. */);
defsubr (&Scurrent_active_maps);
defsubr (&Saccessible_keymaps);
defsubr (&Skey_description);
+ defsubr (&Sdescribe_map_tree);
defsubr (&Sdescribe_vector);
defsubr (&Ssingle_key_description);
defsubr (&Stext_char_description);
diff --git a/src/print.c b/src/print.c
index dca095f281..53aa353769 100644
--- a/src/print.c
+++ b/src/print.c
@@ -941,7 +941,7 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context,
else
{
Lisp_Object error_conditions = Fget (errname, Qerror_conditions);
- errmsg = Fsubstitute_command_keys (Fget (errname, Qerror_message));
+ errmsg = call1 (Qsubstitute_command_keys, Fget (errname, Qerror_message));
file_error = Fmemq (Qfile_error, error_conditions);
}
diff --git a/src/syntax.c b/src/syntax.c
index 066972e6d8..df07809aaa 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1421,7 +1421,7 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
{
AUTO_STRING (prefixdoc,
",\n\t is a prefix character for `backward-prefix-chars'");
- insert1 (Fsubstitute_command_keys (prefixdoc));
+ insert1 (call1 (Qsubstitute_command_keys, prefixdoc));
}
return syntax;
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index 0862d1264c..048b6c325e 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -3,6 +3,8 @@
;; Copyright (C) 2019-2020 Free Software Foundation, Inc.
;; Author: Juanma Barranquero
+;; Eli Zaretskii
+;; Stefan Kangas
;; Keywords: help, internal
;; This file is part of GNU Emacs.
@@ -23,6 +25,7 @@
;;; Code:
(require 'ert)
+(eval-when-compile (require 'cl-lib))
(ert-deftest help-split-fundoc-SECTION ()
"Test new optional arg SECTION."
@@ -51,6 +54,213 @@
(should (equal (help-split-fundoc nil t 'usage) nil))
(should (equal (help-split-fundoc nil t 'doc) nil))))
+
+;;; substitute-command-keys
+
+(defmacro with-substitute-command-keys-test (&rest body)
+ `(cl-flet* ((should-be-same-as-c-version
+ ;; TODO: Remove this when old C function is removed.
+ (lambda (orig)
+ (should (equal-including-properties
+ (substitute-command-keys orig)
+ (substitute-command-keys-old orig)))))
+ (test
+ (lambda (orig result)
+ (should (equal-including-properties
+ (substitute-command-keys orig)
+ result))
+ (should-be-same-as-c-version orig)))
+ (test-re
+ (lambda (orig regexp)
+ (should (string-match (concat "^" regexp "$")
+ (substitute-command-keys orig)))
+ (should-be-same-as-c-version orig))))
+ ,@body))
+
+(ert-deftest help-tests-substitute-command-keys/no-change ()
+ (with-substitute-command-keys-test
+ (test "foo" "foo")
+ (test "\\invalid-escape" "\\invalid-escape")))
+
+(ert-deftest help-tests-substitute-command-keys/commands ()
+ (with-substitute-command-keys-test
+ (test "foo \\[goto-char]" "foo M-g c")
+ (test "\\[next-line]" "C-n")
+ (test "\\[next-line]\n\\[next-line]" "C-n\nC-n")
+ (test "\\[next-line]\\[previous-line]" "C-nC-p")
+ (test "\\[next-line]\\=\\[previous-line]" "C-n\\[previous-line]")
+ ;; Allow any style of quotes, since the terminal might not support
+ ;; UTF-8. Same thing is done below.
+ (test-re "\\[next-line]`foo'" "C-n[`'‘]foo['’]")
+ (test "\\[emacs-version]" "M-x emacs-version")
+ (test "\\[emacs-version]\\[next-line]" "M-x emacs-versionC-n")
+ (test-re "\\[emacs-version]`foo'" "M-x emacs-version[`'‘]foo['’]")))
+
+(ert-deftest help-tests-substitute-command-keys/keymaps ()
+ (with-substitute-command-keys-test
+ (test "\\{minibuffer-local-must-match-map}"
+ "\
+key binding
+--- -------
+
+C-g abort-recursive-edit
+TAB minibuffer-complete
+C-j minibuffer-complete-and-exit
+RET minibuffer-complete-and-exit
+ESC Prefix Command
+SPC minibuffer-complete-word
+? minibuffer-completion-help
+ file-cache-minibuffer-complete
+ previous-history-element
+ next-history-element
+ next-line-or-history-element
+ next-history-element
+ switch-to-completions
+ previous-line-or-history-element
+
+M-v switch-to-completions
+
+M-< minibuffer-beginning-of-buffer
+M-n next-history-element
+M-p previous-history-element
+M-r previous-matching-history-element
+M-s next-matching-history-element
+
+")))
+
+(ert-deftest help-tests-substitute-command-keys/keymap-change ()
+ (with-substitute-command-keys-test
+ (test "\\\\[abort-recursive-edit]" "C-g")
+ (test "\\\\[eval-defun]" "C-M-x")))
+
+(ert-deftest help-tests-substitute-command-keys/undefined-map ()
+ (with-substitute-command-keys-test
+ (test-re "\\{foobar-map}"
+ "\nUses keymap [`'‘]foobar-map['’], which is not currently defined.\n")))
+
+(ert-deftest help-tests-substitute-command-keys/quotes ()
+ (with-substitute-command-keys-test
+ (let ((text-quoting-style 'curve))
+ (test "quotes ‘like this’" "quotes ‘like this’")
+ (test "`x'" "‘x’")
+ (test "`" "‘")
+ (test "'" "’")
+ (test "\\`" "\\‘"))
+ (let ((text-quoting-style 'straight))
+ (test "quotes `like this'" "quotes 'like this'")
+ (test "`x'" "'x'")
+ (test "`" "'")
+ (test "'" "'")
+ (test "\\`" "\\'"))
+ (let ((text-quoting-style 'grave))
+ (test "quotes `like this'" "quotes `like this'")
+ (test "`x'" "`x'")
+ (test "`" "`")
+ (test "'" "'")
+ (test "\\`" "\\`"))))
+
+(ert-deftest help-tests-substitute-command-keys/literals ()
+ (with-substitute-command-keys-test
+ (test "foo \\=\\[goto-char]" "foo \\[goto-char]")
+ (test "foo \\=\\=" "foo \\=")
+ (test "\\=\\=" "\\=")
+ (test "\\=\\[" "\\[")
+ (let ((text-quoting-style 'curve))
+ (test "\\=`x\\='" "`x'"))
+ (let ((text-quoting-style 'straight))
+ (test "\\=`x\\='" "`x'"))
+ (let ((text-quoting-style 'grave))
+ (test "\\=`x\\='" "`x'"))))
+
+(ert-deftest help-tests-substitute-command-keys/no-change ()
+ (with-substitute-command-keys-test
+ (test "\\[foobar" "\\[foobar")
+ (test "\\=" "\\=")))
+
+(ert-deftest help-tests-substitute-command-keys/multibyte ()
+ ;; Cannot use string= here, as that compares unibyte and multibyte
+ ;; strings not equal.
+ (should (compare-strings
+ (substitute-command-keys "\200 \\[goto-char]") nil nil
+ "\200 M-g c" nil nil)))
+
+(ert-deftest help-tests-substitute-command-keys/apropos ()
+ (save-window-excursion
+ (apropos "foo")
+ (switch-to-buffer "*Apropos*")
+ (goto-char (point-min))
+ (should (looking-at "Type RET on"))))
+
+(defvar help-tests-major-mode-map
+ (let ((map (make-keymap)))
+ (define-key map "x" 'foo-original)
+ map))
+
+(define-derived-mode help-tests-major-mode nil
+ "Major mode for testing shadowing.")
+
+(defvar help-tests-minor-mode-map
+ (let ((map (make-keymap)))
+ (define-key map "x" 'foo-shadow)
+ map))
+
+(define-minor-mode help-tests-minor-mode
+ "Minor mode for testing shadowing.")
+
+(ert-deftest help-tests-substitute-command-keys/shadow ()
+ (with-substitute-command-keys-test
+ (with-temp-buffer
+ (help-tests-major-mode)
+ (test "\\{help-tests-major-mode-map}"
+ "\
+key binding
+--- -------
+
+x foo-original
+
+")
+ (help-tests-minor-mode)
+ (test "\\{help-tests-major-mode-map}"
+ "\
+key binding
+--- -------
+
+x foo-original
+ (this binding is currently shadowed)
+
+"))))
+
+(ert-deftest help-tests-substitute-command-keys/command-remap ()
+ (with-substitute-command-keys-test
+ (let ((help-tests-major-mode-map (make-keymap))) ; Protect from changes.
+ (with-temp-buffer
+ (help-tests-major-mode)
+ (define-key help-tests-major-mode-map [remap foo] 'bar)
+ (test "\\{help-tests-major-mode-map}"
+ "\
+key binding
+--- -------
+
+ Prefix Command
+
+ bar
+
+")))))
+
+;; TODO: This is a temporary test that should be removed together with
+;; substitute-command-keys-old.
+(ert-deftest help-tests-substitute-command-keys/compare ()
+ (with-substitute-command-keys-test
+ (with-temp-buffer
+ (Info-mode)
+ (outline-minor-mode)
+ (test-re "\\{Info-mode-map}" ".*")))
+ (with-substitute-command-keys-test
+ (with-temp-buffer
+ (c-mode)
+ (outline-minor-mode)
+ (test-re "\\{c-mode-map}" ".*"))))
+
(provide 'help-tests)
;;; help-tests.el ends here
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
deleted file mode 100644
index 797b9ba548..0000000000
--- a/test/src/doc-tests.el
+++ /dev/null
@@ -1,98 +0,0 @@
-;;; doc-tests.el --- Tests for doc.c -*- lexical-binding: t -*-
-
-;; Copyright (C) 2016-2020 Free Software Foundation, Inc.
-
-;; Author: Eli Zaretskii
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see .
-
-;;; Code:
-
-(require 'ert)
-
-(ert-deftest doc-test-substitute-command-keys ()
- ;; Bindings.
- (should (string= (substitute-command-keys "foo \\[goto-char]") "foo M-g c"))
- ;; Cannot use string= here, as that compares unibyte and multibyte
- ;; strings not equal.
- (should (compare-strings
- (substitute-command-keys "\200 \\[goto-char]") nil nil
- "\200 M-g c" nil nil))
- ;; Literals.
- (should (string= (substitute-command-keys "foo \\=\\[goto-char]")
- "foo \\[goto-char]"))
- (should (string= (substitute-command-keys "foo \\=\\=")
- "foo \\="))
- ;; Keymaps.
- ;; I don't see that this is testing anything useful.
- ;; AFAICS all it does it fail whenever someone modifies the
- ;; minibuffer map.
-;;; (should (string= (substitute-command-keys
-;;; "\\{minibuffer-local-must-match-map}")
-;;; "\
-;;; key binding
-;;; --- -------
-;;;
-;;; C-g abort-recursive-edit
-;;; TAB minibuffer-complete
-;;; C-j minibuffer-complete-and-exit
-;;; RET minibuffer-complete-and-exit
-;;; ESC Prefix Command
-;;; SPC minibuffer-complete-word
-;;; ? minibuffer-completion-help
-;;; file-cache-minibuffer-complete
-;;; previous-history-element
-;;; next-history-element
-;;; next-line-or-history-element
-;;; next-history-element
-;;; switch-to-completions
-;;; previous-line-or-history-element
-;;;
-;;; M-v switch-to-completions
-;;;
-;;; M-< minibuffer-beginning-of-buffer
-;;; M-n next-history-element
-;;; M-p previous-history-element
-;;; M-r previous-matching-history-element
-;;; M-s next-matching-history-element
-;;;
-;;; "))
- (should (string=
- (substitute-command-keys
- "\\\\[abort-recursive-edit]")
- "C-g"))
- ;; Allow any style of quotes, since the terminal might not support
- ;; UTF-8.
- (should (string-match
- "\nUses keymap [`‘']foobar-map['’], which is not currently defined.\n"
- (substitute-command-keys "\\{foobar-map}")))
- ;; Quotes.
- (should (let ((text-quoting-style 'grave))
- (string= (substitute-command-keys "quotes `like this'")
- "quotes `like this'")))
- (should (let ((text-quoting-style 'grave))
- (string= (substitute-command-keys "quotes ‘like this’")
- "quotes ‘like this’")))
- (should (let ((text-quoting-style 'straight))
- (string= (substitute-command-keys "quotes `like this'")
- "quotes 'like this'")))
- ;; Bugs.
- (should (string= (substitute-command-keys "\\[foobar") "\\[foobar"))
- (should (string= (substitute-command-keys "\\=") "\\="))
- )
-
-(provide 'doc-tests)
-;;; doc-tests.el ends here