Gnus development mailing list
 help / color / mirror / Atom feed
* Gnus window configuration with transient buffers
@ 2013-03-15 10:28 Jan Tatarik
  2013-03-15 13:53 ` Eric S Fraga
  2013-03-15 16:00 ` David Engster
  0 siblings, 2 replies; 6+ messages in thread
From: Jan Tatarik @ 2013-03-15 10:28 UTC (permalink / raw)
  To: ding

Hi,

I wrote a module to sync calendar events received by mail with my
org-mode agenda, and I'm not sure whether mine is the correct way of
plugging the functionality into gnus.

Most invitations I receive these days contain no scheduling information
in the message body itself. What I want to achieve on the gnus side is:

1) When reading an article with calendar part, I want to show an
   additional window containing the calendar event details.

2) The calendar event window should disappear again when jumping to an
   article without invitation part.

The first step is easy, but once an article with invitation is shown,
the additional window stays in place, even for messages without calendar
parts.


So I figured the best way would be to

- delete the event buffer (if any) when loading new article

- create new event buffer when the current article contains calendar part

- force gnus window refresh


I hooked this up as follows:

- in gnus-mark-article-hook (this is the part I'm not so sure about)
  delete the transient event buffer, if any.

- in gnus-article-mime-part-function (again, not sure if this is the
  best place, there's also gnus-article-prepare-hook), detect
  text/calendar parts, parse them and create new buffer containing the
  event details.

- set gnus-always-force-window-configuration to t for the forced window
  configuration refresh. This will make the transient window/buffer
  appear/disappear correctly.


So, my question is, is the above the best way to implement the behavior,
or did I miss some easier approach?



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Gnus window configuration with transient buffers
  2013-03-15 10:28 Gnus window configuration with transient buffers Jan Tatarik
@ 2013-03-15 13:53 ` Eric S Fraga
  2013-03-15 16:00 ` David Engster
  1 sibling, 0 replies; 6+ messages in thread
From: Eric S Fraga @ 2013-03-15 13:53 UTC (permalink / raw)
  To: ding

Jan Tatarik <jan.tatarik@gmail.com> writes:

> Hi,
>
> I wrote a module to sync calendar events received by mail with my
> org-mode agenda, and I'm not sure whether mine is the correct way of
> plugging the functionality into gnus.

[...]

> So, my question is, is the above the best way to implement the behavior,
> or did I miss some easier approach?

I cannot comment on whether this is the best way or not
unfortunately.  However, I would be very interested in seeing what you
have done!  Can you share your code?

Thanks,
eric

-- 
: Eric S Fraga, GnuPG: 0xC89193D8FFFCF67D
: in Emacs 24.3.50.1 + Ma Gnus v0.6 + evil 1.0-dev
: BBDB version 3.02 ($Date: 2013/02/16 14:37:17 $)




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Gnus window configuration with transient buffers
  2013-03-15 10:28 Gnus window configuration with transient buffers Jan Tatarik
  2013-03-15 13:53 ` Eric S Fraga
@ 2013-03-15 16:00 ` David Engster
  2013-03-15 22:53   ` Jan Tatarik
  1 sibling, 1 reply; 6+ messages in thread
From: David Engster @ 2013-03-15 16:00 UTC (permalink / raw)
  To: Jan Tatarik; +Cc: ding

Jan Tatarik writes:
> So I figured the best way would be to
>
> - delete the event buffer (if any) when loading new article
>
> - create new event buffer when the current article contains calendar part
>
> - force gnus window refresh
>
>
> I hooked this up as follows:

[...]

Since I was already kneep-deep in the calendaring business (through
org-caldav), I'm afraid I also started adding icalendar support to
Gnus. I didn't publish it yet because I wanted to add the ability to
accept/decline invitations first, but I pushed it now:

https://github.com/dengste/gnus-icalendar

Simply evaluate this file and look at a message with an icalendar event.

Contrary to what you are doing, I directly write into the article
buffer. The reason is that the iCalendar event should contain all
information that is needed. Most clients also provide an alternative
MIME type (mostly HTML), but that should be generated from the calendar
event should not contain further information.

While accepting/declining events is not yet implemented, export to Org
should work fine. By default, the entry will be copied into the kill
ring and you can yank it into your Org file. You can automate this by
adding a template like this

	("c" "Calendar item" entry
	 (file "~/org/icalendar.org")
	 "* %c \n %a %?")

to org-capture-templates, and then set

(setq gnus-icalendar-org-capture-key "c")

If you now hit the "Org export" button, it should directly put the entry
into ~/org/icalendar.org.

I'd like to see your code; maybe we can work together on this, which I
consider to be the last step to let Gnus finally reign the enterprise.

-David



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Gnus window configuration with transient buffers
  2013-03-15 16:00 ` David Engster
@ 2013-03-15 22:53   ` Jan Tatarik
  2013-03-16  3:27     ` Dave Goldberg
  2013-03-22 14:50     ` Jan Tatarik
  0 siblings, 2 replies; 6+ messages in thread
From: Jan Tatarik @ 2013-03-15 22:53 UTC (permalink / raw)
  To: ding

On Fri, Mar 15 2013, David Engster wrote:

> Since I was already kneep-deep in the calendaring business (through
> org-caldav), I'm afraid I also started adding icalendar support to
> Gnus. I didn't publish it yet because I wanted to add the ability to
> accept/decline invitations first, but I pushed it now:

> https://github.com/dengste/gnus-icalendar

I'll have a look.

> I'd like to see your code; maybe we can work together on this, which I
> consider to be the last step to let Gnus finally reign the enterprise.

https://github.com/jtatarik/ical-event

I have no problem with merging or abandoning my code, as long as there's
code that does the job for me.

With what I have right now, you can create/update/cancel a calendar
entry in org file of your choice, just by clicking a button in the gnus
calendar buffer. The org capture template used for creating new entries
is created automatically. As long as you're OK with storing events in
one place, single click does it.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Gnus window configuration with transient buffers
  2013-03-15 22:53   ` Jan Tatarik
@ 2013-03-16  3:27     ` Dave Goldberg
  2013-03-22 14:50     ` Jan Tatarik
  1 sibling, 0 replies; 6+ messages in thread
From: Dave Goldberg @ 2013-03-16  3:27 UTC (permalink / raw)
  To: ding

I wrote a function based on functions in icalendar.el to parse a text/calendar handle and put it into my diary (one of two, actually, depending on whether it's a repeating event) file.  My code was set up to trigger upon opening a message, which was annoying but not so much that I bothered to do anything else.

Recently Adam Sjøgren posted some code to nicely format a text/calendar type.  I now use this, and have set up an action to save the calendar event in the context menu of the text/calendar mime button.  I have posted my function before in the past.  Someone, though I unfortunately don't recall who, suggested some changes to handle timezones which I've incorporated.

Here is the code in hopes it proves useful to someone else:

(add-to-list 'mm-inlined-types "text/calendar")
(add-to-list 'mm-automatic-display "text/calendar")
(add-to-list 'mm-inline-media-tests '("text/calendar" mm-inline-text-calendar identity))

(require 'icalendar)
(require 'boxquote)

(defun mm-inline-text-calendar (handle)
  (let ((text ""))
    (with-temp-buffer
      (mm-insert-part handle)
      (save-window-excursion
        (setq info (mapcar (lambda (s) (mm-decode-string s "utf-8"))
                           (format-text-calendar-for-display (icalendar--read-element nil nil))))))
    (let ((start (point)))
      (mm-insert-inline handle "\n")
      (mm-insert-inline handle (car info))
      (mm-insert-inline handle "\n")
      (goto-char start)
      (when (search-forward "DESCRIPTION " nil t)
        (replace-match "" nil t)
        (beginning-of-line)
        (fill-region (point) (point-max)))
      (boxquote-region start (point-max)))
    (boxquote-title (car (cdr info)))
    (mm-insert-inline handle "\n")))

(defun format-text-calendar-for-display (element)
  "Format a text/calendar element parsed by icalendar--read-element into text"
  (let ((fields '(LOCATION ORGANIZER DESCRIPTION))
        (fieldformat "%-11s %s\n")
        (content "")
        (first-date "")
        (last-date "")
        (title ""))
    (dolist (event (icalendar--all-events element))
      (let* ((zone-map (icalendar--convert-all-timezones element))
             (dtstart-zone (icalendar--find-time-zone (icalendar--get-event-property-attributes event 'DTSTART) zone-map))
             (dtstart (icalendar--decode-isodatetime (icalendar--get-event-property event 'DTSTART) nil dtstart-zone))
             (dtend-zone (icalendar--find-time-zone (icalendar--get-event-property-attributes event 'DTEND) zone-map))
             (dtend   (icalendar--decode-isodatetime (icalendar--get-event-property event 'DTEND) nil dtend-zone))
             (datestring (concat (icalendar--datetime-to-iso-date dtstart "-") " "
                                 (icalendar--datetime-to-colontime dtstart) "-"
                                 (icalendar--datetime-to-colontime dtend))))
        (when (string-equal first-date "")
          (setq first-date datestring))
        (setq last-date datestring)
        (dolist (field fields)
          (let ((propertyvalue (mapconcat (lambda (property)
                                            (icalendar--convert-string-for-import property)
                                            (replace-regexp-in-string "\\\\n" "\n"
                                                                      (replace-regexp-in-string "^MAILTO:" "" property)))
                                          (icalendar--get-event-properties event field) " ")))
            (when (not (string-equal propertyvalue ""))
              (setq content (concat content (format fieldformat field (replace-regexp-in-string "\\\\ " "" propertyvalue)))))))))
    (setq content (replace-regexp-in-string "\n\n$" "" content))
    (setq title (if (string-equal first-date last-date) first-date (concat first-date " ... " last-date)))
    (list content title)))


(defun dsg-icalendar-handle-part (handle)
  (when (equal (car (mm-handle-type handle)) "text/calendar")
    (with-temp-buffer
      (insert (mm-get-part handle))
      (if (equal (mm-handle-encoding handle) 'uuencode)
	  (uudecode-decode-region-internal (point-min) (point-max)))
      (goto-char (point-min))
      (decode-coding-region (point-min) (point-max) 'utf-8 nil)
      (let* ((e
	      (icalendar--all-events (icalendar--read-element nil nil)))
	     (ce (car e))
	     (subject (icalendar--convert-string-for-import
		       (or (icalendar--get-event-property ce 'SUMMARY)
			   "No Subject")))
	     (zone-map (icalendar--convert-all-timezones e))
             (dtstart-zone (icalendar--find-time-zone (icalendar--get-event-property-attributes ce 'DTSTART) zone-map))
             (dtstart (icalendar--decode-isodatetime (icalendar--get-event-property ce 'DTSTART) nil dtstart-zone))
	     (start-d (icalendar--datetime-to-diary-date dtstart))
	     (start-t (icalendar--datetime-to-colontime dtstart))
	     (repq (icalendar--get-event-property ce 'RRULE)))
	(if (y-or-n-p
	     (format
	      "Add %s for \"%s\" on %s at %s to diary? "
	      (if repq "repeating event" "appointment")
	      subject start-d start-t))
	    (icalendar-import-buffer
	     (expand-file-name (if repq "~/repeating-diary"
				 "~/ical-diary")) t nil))))))

(defun dsg-gnus-mime-save-calendar-event ()
  "Save the Calendar event in the text/calendar part under point."
  (interactive)
  (gnus-article-check-buffer)
  (let ((data (get-text-property (point) 'gnus-data)))
    (when data
      (dsg-icalendar-handle-part data))))

(add-to-list 'gnus-mime-action-alist (cons "save calendar event" 'dsg-gnus-mime-save-calendar-event) t)


-- 
Dave Goldberg
david.goldberg6@verizon.net



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Gnus window configuration with transient buffers
  2013-03-15 22:53   ` Jan Tatarik
  2013-03-16  3:27     ` Dave Goldberg
@ 2013-03-22 14:50     ` Jan Tatarik
  1 sibling, 0 replies; 6+ messages in thread
From: Jan Tatarik @ 2013-03-22 14:50 UTC (permalink / raw)
  To: ding

[-- Attachment #1: Type: text/plain, Size: 1362 bytes --]

OK, showing the event details in the message buffer is definitely better
and simpler.

I'm not online these days, and won't be for the next week or so. But I
should have time to do a little bit of coding. Will look into sending the
event confirmation.

Jan


On Fri, Mar 15, 2013 at 11:53 PM, Jan Tatarik <jan.tatarik@gmail.com> wrote:

> On Fri, Mar 15 2013, David Engster wrote:
>
> > Since I was already kneep-deep in the calendaring business (through
> > org-caldav), I'm afraid I also started adding icalendar support to
> > Gnus. I didn't publish it yet because I wanted to add the ability to
> > accept/decline invitations first, but I pushed it now:
>
> > https://github.com/dengste/gnus-icalendar
>
> I'll have a look.
>
> > I'd like to see your code; maybe we can work together on this, which I
> > consider to be the last step to let Gnus finally reign the enterprise.
>
> https://github.com/jtatarik/ical-event
>
> I have no problem with merging or abandoning my code, as long as there's
> code that does the job for me.
>
> With what I have right now, you can create/update/cancel a calendar
> entry in org file of your choice, just by clicking a button in the gnus
> calendar buffer. The org capture template used for creating new entries
> is created automatically. As long as you're OK with storing events in
> one place, single click does it.
>

[-- Attachment #2: Type: text/html, Size: 1948 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-03-22 14:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-15 10:28 Gnus window configuration with transient buffers Jan Tatarik
2013-03-15 13:53 ` Eric S Fraga
2013-03-15 16:00 ` David Engster
2013-03-15 22:53   ` Jan Tatarik
2013-03-16  3:27     ` Dave Goldberg
2013-03-22 14:50     ` Jan Tatarik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).