[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/ebdb 96b113d 251/350: New functions for folding/unfoldi
From: |
Eric Abrahamsen |
Subject: |
[elpa] externals/ebdb 96b113d 251/350: New functions for folding/unfolding long vCard lines |
Date: |
Mon, 14 Aug 2017 11:46:48 -0400 (EDT) |
branch: externals/ebdb
commit 96b113d6d69e8462505b28ac6ce3b1429250db94
Author: Eric Abrahamsen <address@hidden>
Commit: Eric Abrahamsen <address@hidden>
New functions for folding/unfolding long vCard lines
* ebdb-vcard.el (ebdb-vcard-fold-lines, ebdb-vcard-unfold-lines): RFC
says lines longer than 75 octets must be folded. Folding consists
of CRLF followed immediate by space or tab.
* ebdb-test.el (ebdb-vcard-fold/unfold): Test new functions.
---
ebdb-test.el | 34 ++++++++++++++++++++++++++++++++++
ebdb-vcard.el | 46 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/ebdb-test.el b/ebdb-test.el
index 93e3819..9ff328d 100644
--- a/ebdb-test.el
+++ b/ebdb-test.el
@@ -384,6 +384,40 @@ uncle"))
"Look, a bog; dogs."))
"Look, a bog; dogs.")))
+(ert-deftest ebdb-vcard-fold/unfold ()
+ "Test line-length folding/unfolding."
+ (let ((short-lines "For sale:\r\nBaby shoes,\r\nNever used.")
+ (long-lines
+ "Turns out seventy five bytes is a lot of bytes when you just have to
keep typing and typing\r\nand typing.")
+ (multibyte-lines
+ "然后还要用中文写一行没完没了的话。\r\n其实先要来一个短的,然后一行特别长的,那就是现在这行,\r\n然后可以再有一个短的"))
+ (should (equal (ebdb-vcard-fold-lines short-lines)
+ "For sale:
+Baby shoes,
+Never used."))
+ (should (equal (ebdb-vcard-unfold-lines
+ (ebdb-vcard-fold-lines short-lines))
+ short-lines))
+ (should
+ (equal (ebdb-vcard-fold-lines long-lines)
+ "Turns out seventy five bytes is a lot of bytes when you just have
to keep t
+ yping and typing
+and typing."))
+ (should
+ (equal (ebdb-vcard-unfold-lines
+ (ebdb-vcard-fold-lines long-lines))
+ long-lines))
+ (should
+ (equal (ebdb-vcard-fold-lines multibyte-lines)
+ "然后还要用中文写一行没完没了的话。
+其实先要来一个短的,然后一行特别长的,那就是现在这
+ 行,
+然后可以再有一个短的"))
+ (should
+ (equal (ebdb-vcard-unfold-lines
+ (ebdb-vcard-fold-lines multibyte-lines))
+ multibyte-lines))))
+
(ert-deftest ebdb-vcard-export-dont-explode ()
"Can we export a record to Vcard without immediate disaster?"
(ebdb-test-with-records
diff --git a/ebdb-vcard.el b/ebdb-vcard.el
index d1fad84..08b01dc 100644
--- a/ebdb-vcard.el
+++ b/ebdb-vcard.el
@@ -126,13 +126,54 @@ not always respect these headings."
"\\([^\\]\\)\\([\n\r]+\\)" "\\1\\\\\\2"
(replace-regexp-in-string "\\([^\\]\\)\\([,;]\\)" "\\1\\\\\\2" str)))
-(defun ebdb-vcard-unescape (str)
+(defsubst ebdb-vcard-unescape (str)
"Unescape escaped commas, semicolons and newlines in STR."
(replace-regexp-in-string
"\\\\n" "\n"
(replace-regexp-in-string
"\\\\\\([,;]\\)" "\\1" str)))
+;; The RFC says fold any lines longer than 75 octets, excluding the
+;; line break. Folded lines are delineated by a CRLF plus a space or
+;; tab. Multibyte characters must not be broken.
+
+;; TODO: This implementation assumes that Emacs' internal coding
+;; system is similar enough to the utf-8 that the file will eventually
+;; be written in that `string-bytes' (which returns a length according
+;; to Emacs' own coding) will map accurately to what eventually goes
+;; in the file. Eli notes this is not really true, and could result
+;; in unexpected behavior, and he recommends using
+;; `filepos-to-bufferpos' instead. Presumably that would involve
+;; /first/ writing the vcf file, then backtracking and checking for
+;; correctness.
+(defun ebdb-vcard-fold-lines (text)
+ "Fold lines in TEXT, which represents a vCard contact."
+ (let ((lines (split-string text "\r\n"))
+ outlines)
+ (dolist (l lines)
+ (while (> (string-bytes l) 75) ; Line is too long.
+ (if (> (string-bytes l) (length l))
+ ;; Multibyte characters.
+ (let ((acc (string-to-vector l)))
+ (setq l nil)
+ (while (> (string-bytes (concat acc)) 75)
+ ;; Pop characters off the end of acc and stick them
+ ;; back in l, until acc is short enough to go in
+ ;; outlines. Probably hideously inefficient.
+ (push (aref acc (1- (length acc))) l)
+ (setq acc (substring acc 0 -1)))
+ (push acc outlines)
+ (setq l (concat " " l)))
+ ;; No multibyte characters.
+ (push (substring l 0 75) outlines)
+ (setq l (concat " " (substring l 75)))))
+ (push l outlines))
+ (mapconcat #'identity (nreverse outlines) "\r\n")))
+
+(defun ebdb-vcard-unfold-lines (text)
+ "Unfold lines in TEXT, which represents a vCard contact."
+ (replace-regexp-in-string "\r\n[\s\t]" "" text))
+
(cl-defmethod ebdb-fmt-process-fields ((_f ebdb-formatter-vcard)
(_record ebdb-record)
field-list)
@@ -176,7 +217,8 @@ All this does is split role instances into multiple fields."
(r ebdb-record))
"Format a single record R in VCARD format."
;; Because of the simplicity of the VCARD format, we only collect
- ;; the fields, there's no need to sort or "process" them.
+ ;; the fields, there's no need to sort them, and the only processing
+ ;; that happens is for role fields.
(let ((fields (ebdb-fmt-process-fields
f r
(ebdb-fmt-collect-fields f r)))
- [elpa] externals/ebdb cacb97b 271/350: Fix bug in MUA record creation, (continued)
- [elpa] externals/ebdb cacb97b 271/350: Fix bug in MUA record creation, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb e5bdee2 278/350: Rework ebdb-mail-yank, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 8dd1600 273/350: Change type of anniversary field dates, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 57b2514 276/350: Use ebdb-with-record-edits in more places, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb f44a797 286/350: New function ebdb-mua-in-ebdb-buffer, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 4ce353e 237/350: Migrate more search routines to the ebdb-search-display thing, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 7040cad 247/350: Expand ebdb-helm to complete on mails as well, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb a6bc423 249/350: Remove unused customization groups, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 4ded53d 250/350: All vCard lines should be delimited with CRLF, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb a776d37 248/350: Don't use copy-sequence plus add-text-properties on strings, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 96b113d 251/350: New functions for folding/unfolding long vCard lines,
Eric Abrahamsen <=
- [elpa] externals/ebdb b52cdc0 265/350: Record-insert|delete-field methods can find their own slots, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb fcee6ab 267/350: Protect against no current record when redisplaying, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb f3b9525 269/350: Temporarily abandon having record-change-name accept strings, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 1a31515 274/350: Fixes to record loading, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 01262e3 277/350: Mark EBDB buffers as modified after edits, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb cc83f62 197/350: Add protection around ebdb-record-uuid, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 4f3db7f 195/350: Save match data around ebdb-parse-i18n, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb fcf0702 275/350: Mark EBDB buffers as unmodified after save, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb 88f5e12 261/350: Fill out functionality of gnorb messages field, Eric Abrahamsen, 2017/08/14
- [elpa] externals/ebdb a81769c 272/350: Allow custom hash predicates, Eric Abrahamsen, 2017/08/14