From c8890a1d2208328523925f77e3812ed951218809 Mon Sep 17 00:00:00 2001 From: Jaidyn Ann <10477760+JadedCtrl@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:24:28 -0600 Subject: [PATCH] =?UTF-8?q?Fold=20serialized=20vCards=E2=80=99=20lines=20t?= =?UTF-8?q?o=20~70=20characters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec recommends splitting at 75 octets, but that’s hard. We assume that 70 characters is more-or-less 75 octets (even though with UTF-8 chars this might be passed). --- vcarded.scm | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/vcarded.scm b/vcarded.scm index 94e72ab..04434e4 100644 --- a/vcarded.scm +++ b/vcarded.scm @@ -84,9 +84,7 @@ ;; description, but unfortunately I’m coming up empty! =w=, (define (write-vcard vcard-alist #!optional (port (current-output-port))) (for-each (lambda (element) - (write-string (serialize-vcard-element element) #f port) - (write-char #\return port) - (write-char #\newline port)) + (write-folded-line (serialize-vcard-element element))) vcard-alist)) @@ -185,7 +183,7 @@ - ;;; ~ Property-value parsers ~ + ;;; ~ Property-value parsers/serializers ~ ;; List of all properties with semicoloned-structured strings. (define vcard-semicoloned-properties @@ -328,16 +326,37 @@ ;; Reader-thunk. Read a “logical” folded-line, where a line beginning with a ;; space is a continuation of the previous line — like with vcards. - (define (read-folded-line #!optional (limit 100) (port (current-input-port))) - (if (not (eof-object? (peek-char port))) - (let [(line (read-line port limit))] - (if (or (eq? (peek-char port) #\space) - (eq? (peek-char port) #\tab)) - (string-concatenate - (list line - (string-drop (read-folded-line limit port) 1))) - line)) - "")) + ;; LIMIT is the maximum amount of characters it will read before giving up + ;; on finding a newline. + ;; It will default to (current-input-port) as the PORT. + (define (read-folded-line #!optional (limit #f) (port (current-input-port))) + (let [(port (or port (current-input-port)))] + (if (not (eof-object? (peek-char port))) + (let [(line (read-line port limit))] + (if (or (eq? (peek-char port) #\space) + (eq? (peek-char port) #\tab)) + (string-concatenate + (list line + (string-drop (read-folded-line limit port) 1))) + line)) + ""))) + + + ;; Write a line to a port as a “logical” folded-line string, in the style of + ;; vCard and vCalendar. If the line is too long (passed FOLD-LENGTH [70]), it + ;; will be written as several lines of FOLD-LENGTH, with each such line + ;; prepended by the CREASE-CHAR (#\tab). + ;; It will default to (current-output-port), if PORT is #f or unspecified. + (define (write-folded-line string #!optional + (port (current-output-port)) + (fold-length 70) + (crease-char #\tab)) + (write-string + (string-concatenate + (list (string-join (string-split-by-lengths string fold-length) + (list->string (list #\return #\newline crease-char))) + (list->string '(#\return #\newline)))) + #f (or port (current-output-port)))) ;; Split a STRING into strings of a size of (at most) LENGTH signs.