From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.emacs.gnus.general/83881 Path: news.gmane.org!not-for-mail From: Jan Tatarik Newsgroups: gmane.emacs.gnus.general Subject: FEATURE: gnus-icalendar appt participants synced to org Date: Fri, 15 Nov 2013 00:19:56 +0100 Message-ID: <87txfe371f.fsf@nb-jtatarik2.xing.hh> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1384471285 27654 80.91.229.3 (14 Nov 2013 23:21:25 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 14 Nov 2013 23:21:25 +0000 (UTC) To: ding@gnus.org Original-X-From: ding-owner+M32137@lists.math.uh.edu Fri Nov 15 00:21:29 2013 Return-path: Envelope-to: ding-account@gmane.org Original-Received: from util0.math.uh.edu ([129.7.128.18]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Vh6E0-0003P7-Fv for ding-account@gmane.org; Fri, 15 Nov 2013 00:21:24 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.math.uh.edu) by util0.math.uh.edu with smtp (Exim 4.63) (envelope-from ) id 1Vh6Cs-0007Ho-N2; Thu, 14 Nov 2013 17:20:14 -0600 Original-Received: from mx2.math.uh.edu ([129.7.128.33]) by util0.math.uh.edu with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1Vh6Cq-0007Hd-M8 for ding@lists.math.uh.edu; Thu, 14 Nov 2013 17:20:12 -0600 Original-Received: from quimby.gnus.org ([80.91.231.51]) by mx2.math.uh.edu with esmtps (TLSv1:AES128-SHA:128) (Exim 4.76) (envelope-from ) id 1Vh6Co-00068n-Rq for ding@lists.math.uh.edu; Thu, 14 Nov 2013 17:20:12 -0600 Original-Received: from mail-bk0-f49.google.com ([209.85.214.49]) by quimby.gnus.org with esmtp (Exim 4.80) (envelope-from ) id 1Vh6Cn-0000V8-Ea for ding@gnus.org; Fri, 15 Nov 2013 00:20:09 +0100 Original-Received: by mail-bk0-f49.google.com with SMTP id w14so1584477bkz.22 for ; Thu, 14 Nov 2013 15:20:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:subject:date:message-id:user-agent:mime-version :content-type; bh=q431wiVGNYLQpimGrpEenU9ZKBBLQvR1oHU0LVE5bKs=; b=VNdniLddh13ZWneQpqjIfVCV378rN/V3EkqW0DIUEgqK3M6nIDkHfu+FismNvifAZw q2wnrodgkYAn0pUlBZsYpXFGRt0OJgAj6hFB+y4r6KG3oTj92DW6G3LRfzjjj6+/7Pk5 pEo+c6UNBMvgRIwWi+Y5FJ7mSCU/C/doYh7p/p0OnIXSup7wPcTrcBpMq1VDN+I0JZki 2ftotRLVyZt1Ar5w9bYs2oiiuEbApCnxXnHwyDgnWkAVIrDyipKrH7nxgBXANqf02IB4 l7CXAi7lhbjjVjnW/VEGtfnn3nOpajGapgyoViJmBYeQgYugBvo+Q0Poo8kdpVf5lwmS pdzg== X-Received: by 10.205.34.197 with SMTP id st5mr899151bkb.61.1384471204016; Thu, 14 Nov 2013 15:20:04 -0800 (PST) Original-Received: from nb-jtatarik2.xing.hh (f054088203.adsl.alicedsl.de. [78.54.88.203]) by mx.google.com with ESMTPSA id b6sm5158285bko.16.2013.11.14.15.20.02 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 14 Nov 2013 15:20:03 -0800 (PST) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) X-Spam-Score: -3.0 (---) List-ID: Precedence: bulk Xref: news.gmane.org gmane.emacs.gnus.general:83881 Archived-At: --=-=-= Content-Type: text/plain Hi, the enclosed patch adds two features to gnus-icalendar: - the article buffer now shows a new field 'Attendance' with values of either 'Required' or 'Optional' - good to know which meetings are safe to ignore - appointments exported to org outline now contain additional properties PARTICIPATION_REQUIRED (t when required), REQ_PARTICIPANTS (list of required attendees) and OPT_PARTICIPANTS (list of optional attendees) --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=participants_to_org.patch diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 45af3d8c6b35de1e5479de1518dcfe7be288dad4..5dc27dddb6fc1d4e64c3ff5e17e59caaad5b18da 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,11 @@ +2013-11-15 Jan Tatarik + + * gnus-icalendar.el (gnus-icalendar-event->gnus-calendar) + (gnus-icalendar-event-from-ical) + (gnus-icalendar-event->org-entry) + (gnus-icalendar--update-org-event): Required/optional participation, + list of attendees synced to org. + 2013-11-13 Jan Tatarik * gnus-icalendar.el (gnus-icalendar-event:sync-to-org) diff --git a/lisp/gnus-icalendar.el b/lisp/gnus-icalendar.el index 064ba84cadc907ebe31cc83f7610927d50c9315a..a8277635f3e1571722a01cb4b0fe4452ca7d2434 100644 --- a/lisp/gnus-icalendar.el +++ b/lisp/gnus-icalendar.el @@ -91,7 +91,19 @@ (rsvp :initarg :rsvp :accessor gnus-icalendar-event:rsvp :initform nil - :type (or null boolean))) + :type (or null boolean)) + (participation-required :initarg :participation-required + :accessor gnus-icalendar-event:participation-required + :initform t + :type (or null boolean)) + (req-participants :initarg :req-participants + :accessor gnus-icalendar-event:req-participants + :initform nil + :type (or null t)) + (opt-participants :initarg :opt-participants + :accessor gnus-icalendar-event:opt-participants + :initform nil + :type (or null t))) "generic iCalendar Event class") (defclass gnus-icalendar-event-request (gnus-icalendar-event) @@ -151,6 +163,24 @@ (gnus-icalendar-find-if #'attendee-prop-matches-p event-props)))) +(defun gnus-icalendar-event--get-attendee-names (ical) + (let* ((event (car (icalendar--all-events ical))) + (attendee-props (gnus-remove-if-not + (lambda (p) (eq (car p) 'ATTENDEE)) + (caddr event)))) + + (gmm-labels ((attendee-role (prop) (plist-get (cadr prop) 'ROLE)) + (attendee-name (prop) (plist-get (cadr prop) 'CN)) + (attendees-by-type (type) + (gnus-remove-if-not + (lambda (p) (string= (attendee-role p) type)) + attendee-props)) + (attendee-names-by-type (type) + (mapcar #'attendee-name (attendees-by-type type)))) + + (list + (attendee-names-by-type "REQ-PARTICIPANT") + (attendee-names-by-type "OPT-PARTICIPANT"))))) (defun gnus-icalendar-event-from-ical (ical &optional attendee-name-or-email) (let* ((event (car (icalendar--all-events ical))) @@ -165,12 +195,17 @@ (method (caddr (assoc 'METHOD (caddr (car (nreverse ical)))))) (attendee (when attendee-name-or-email (gnus-icalendar-event--find-attendee ical attendee-name-or-email))) + (attendee-names (gnus-icalendar-event--get-attendee-names ical)) (args (list :method method :organizer organizer :start-time (gnus-icalendar-event--decode-datefield event 'DTSTART) :end-time (gnus-icalendar-event--decode-datefield event 'DTEND) :rsvp (string= (plist-get (cadr attendee) 'RSVP) - "TRUE"))) + "TRUE") + :participation-required (string= (plist-get (cadr attendee) 'ROLE) + "REQ-PARTICIPANT") + :req-participants (cdar attendee-names) + :opt-participants (cadr attendee-names))) (event-class (cond ((string= method "REQUEST") 'gnus-icalendar-event-request) ((string= method "CANCEL") 'gnus-icalendar-event-cancel) @@ -366,6 +401,10 @@ Return nil for non-recurring EVENT." (format "%s (%s)" summary location) (format "%s" summary))) + +(defun gnus-icalendar--format-participant-list (participants) + (mapconcat #'identity participants ", ")) + ;; TODO: make the template customizable (defmethod gnus-icalendar-event->org-entry ((event gnus-icalendar-event) reply-status) "Return string with new `org-mode' entry describing EVENT." @@ -380,6 +419,9 @@ Return nil for non-recurring EVENT." ("DT" . ,(gnus-icalendar-event:org-timestamp event)) ("ORGANIZER" . ,(gnus-icalendar-event:organizer event)) ("LOCATION" . ,(gnus-icalendar-event:location event)) + ("PARTICIPATION_REQUIRED" . ,(when (gnus-icalendar-event:participation-required event) "t")) + ("REQ_PARTICIPANTS" . ,(gnus-icalendar--format-participant-list (gnus-icalendar-event:req-participants event))) + ("OPT_PARTICIPANTS" . ,(gnus-icalendar--format-participant-list (gnus-icalendar-event:opt-participants event))) ("RRULE" . ,(gnus-icalendar-event:recur event)) ("REPLY" . ,reply)))) @@ -438,7 +480,8 @@ is searched." (let ((file (gnus-icalendar-find-org-event-file event org-file))) (when file (with-current-buffer (find-file-noselect file) - (with-slots (uid summary description organizer location recur) event + (with-slots (uid summary description organizer location recur + participation-required req-participants opt-participants) event (let ((event-pos (org-find-entry-with-id uid))) (when event-pos (goto-char event-pos) @@ -480,6 +523,9 @@ is searched." (org-entry-put event-pos "DT" (gnus-icalendar-event:org-timestamp event)) (org-entry-put event-pos "ORGANIZER" organizer) (org-entry-put event-pos "LOCATION" location) + (org-entry-put event-pos "PARTICIPATION_REQUIRED" (when participation-required "t")) + (org-entry-put event-pos "REQ_PARTICIPANTS" (gnus-icalendar--format-participant-list req-participants)) + (org-entry-put event-pos "OPT_PARTICIPANTS" (gnus-icalendar--format-participant-list opt-participants)) (org-entry-put event-pos "RRULE" recur) (when reply-status (org-entry-put event-pos "REPLY" (capitalize (symbol-name reply-status)))) @@ -595,11 +641,13 @@ is searched." (propertize (concat (car x) ":") 'face 'bold) (cadr x)))) - (with-slots (organizer summary description location recur uid method rsvp) event + (with-slots (organizer summary description location recur uid + method rsvp participation-required) event (let ((headers `(("Summary" ,summary) ("Location" ,(or location "")) ("Time" ,(gnus-icalendar-event:org-timestamp event)) ("Organizer" ,organizer) + ("Attendance" ,(if participation-required "Required" "Optional")) ("Method" ,method)))) (when (and (not (gnus-icalendar-event-reply-p event)) rsvp) --=-=-=--