(module ical mzscheme (require "ical-parser.ss" (all-except (lib "13.ss" "srfi") string-upcase string-titlecase string-downcase)) (provide (all-defined)) (define (ical->x-exprs/port port) (parse icalvcal-parser icalvcal-lexer port)) (define (ical->x-exprs/file filename) (with-input-from-file filename (lambda () (ical->x-exprs/port (current-input-port))))) (define (ical->x-exprs/string input-string) (ical->x-exprs/port (open-input-string input-string))) (define (x-exprs->ical x-expr) (define MAX-WIDTH 72) (define (vobject:attributes->ical attributes) (apply string-append (map (lambda (pair) (let ([left (car pair)] [right (cadr pair)]) (if right (format ";~a=~a" left right) (format ";~a" left)))) attributes))) (define (vobject:value->ical value length-so-far) (let loop ([to-print (format ":~a" value)] [length-so-far length-so-far] [result ""]) (if (equal? "" to-print) (string-drop-right result 1) (let ([n-chars (min (string-length to-print) (- MAX-WIDTH length-so-far))]) (loop (string-drop to-print n-chars) 0 (string-append result (string-take to-print n-chars) (string #\return #\linefeed #\space))))))) (define (vobject->ical x-expr) (let* ([_type (car x-expr)] [type (if (eq? _type 'VCAL) 'VCALENDAR _type)] [content (cdr x-expr)]) (if (member type `(VCAL VCALENDAR VEVENT VTODO VCARD)) (string-append (format "BEGIN:~a" type) (string #\return #\linefeed) (apply string-append (map vobject->ical content)) (format "END:~a" type) (string #\return #\linefeed)) (let* ([has-attributes (and (list? content) (not (null? content)) (list? (car content)))] [attributes (if has-attributes (car content) (list))] [value (if has-attributes (cadr content) (car content))] [beginning (string-append (format "~a" type) (vobject:attributes->ical attributes))]) (string-append beginning (vobject:value->ical value (string-length beginning))))))) (apply string-append (map vobject->ical x-expr))))