141 lines
5.3 KiB
EmacsLisp
141 lines
5.3 KiB
EmacsLisp
;;; org-rtm.el --- Simple import/export from rememberthemilk to org-mode
|
|
;; Copyright (c) 2016 Philipp Middendorf
|
|
;; Author: Philipp Middendorf <pmidden@secure.mailbox.org>
|
|
;; Created: 15 Jan 2016
|
|
;; Version: 0.1
|
|
;; Package-Version: 20160214.436
|
|
;; Package-Requires: ((rtm "0.1"))
|
|
;; Keywords: outlines, data
|
|
;; Homepage: https://github.com/pmiddend/org-rtm
|
|
|
|
;; This product uses the Remember The Milk API but is not endorsed or
|
|
;; certified by Remember The Milk
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
;; This file is free software; you can redistribute it and/or modify
|
|
;; it under the terms of the MIT license (see COPYING).
|
|
|
|
;;; Commentary:
|
|
;; Simple import/export from rememberthemilk to org-mode
|
|
;;
|
|
;; The project is hosted at https://github.com/pmiddend/org-rtm
|
|
;; The latest version, and all the relevant information can be found there.
|
|
;;; Code:
|
|
(require 'rtm)
|
|
(require 'org)
|
|
|
|
|
|
(defgroup org-rtm ()
|
|
"Retrieve and complete tasks from rememberthemilk.com and convert them to org-mode"
|
|
:group 'external
|
|
:link '(url-link "https://github.com/pmiddend/org-rtm")
|
|
:prefix "org-rtm-")
|
|
|
|
(defcustom org-rtm-import-file "~/rtm.org"
|
|
"Where to export the contents of RTM to when using org-rtm-import."
|
|
:group 'org-rtm
|
|
:type 'file)
|
|
|
|
(defcustom org-rtm-complete-after-import nil
|
|
"Complete the imported tasks in RTM.
|
|
It might be a good idea to set this after you verified that
|
|
the import process is working well."
|
|
:group 'org-rtm
|
|
:type 'boolean)
|
|
|
|
(defun org-rtm-assoc-value (symbol list)
|
|
"Get the value behind SYMBOL in an association LIST (not the pair of key/value)."
|
|
(cdr (assoc symbol list)))
|
|
|
|
(defun org-rtm-print-list (rtml)
|
|
"Convert an RTM list RTML to an org mode segment (top level, starting with *)."
|
|
(progn
|
|
(concat
|
|
"* "
|
|
(org-rtm-assoc-value 'name (car (cdr rtml))))))
|
|
|
|
(defun org-rtm-format-note (note)
|
|
"Format a single RTM task NOTE."
|
|
(nth 2 note))
|
|
|
|
(defun org-rtm-format-notes (notes-list)
|
|
"Format a list NOTES-LIST of RTM task notes and concatenate to string."
|
|
(cond ((equal (length notes-list) 0) "")
|
|
(t (concat "\n" (mapconcat 'org-rtm-format-note notes-list "\n")))))
|
|
|
|
(defun org-rtm-format-time-to-org (time-value)
|
|
"Convert an ISO date time TIME-VALUE to the org-mode time format.
|
|
I didn't find built-in function to accomplish this."
|
|
(print (length time-value))
|
|
(format-time-string (cdr org-time-stamp-formats) (date-to-time time-value)))
|
|
|
|
(defun org-rtm-print-entry (e)
|
|
"Format a single RTM task E and output as second level org segment (starting with **)."
|
|
(let*
|
|
((topAssocList (cdr e))
|
|
(taskAssocList (car topAssocList))
|
|
(due (org-rtm-assoc-value 'due (car (org-rtm-assoc-value 'task topAssocList))))
|
|
(notes-list (nthcdr 2 (assoc 'notes topAssocList))))
|
|
(progn
|
|
(concat
|
|
"** TODO "
|
|
(org-rtm-assoc-value 'name taskAssocList)
|
|
(if (not (or (eq due nil) (string= due ""))) (concat "\nSCHEDULED: " (org-rtm-format-time-to-org due)))
|
|
(if (org-rtm-assoc-value 'url taskAssocList) (concat "\n" (org-rtm-assoc-value 'url taskAssocList)) "")
|
|
(org-rtm-format-notes notes-list)))))
|
|
|
|
(defun org-rtm-format-list-entries (list-id)
|
|
"Convert a single RTM task list LIST-ID to org mode items."
|
|
(mapconcat 'org-rtm-print-entry (nthcdr 2 (car (rtm-tasks-get-list list-id "status:incomplete"))) "\n"))
|
|
|
|
(defun org-rtm-format-list (list-id list-name)
|
|
"Format a single list with LIST-ID and LIST-NAME as a top-level org-mode segment starting with *."
|
|
(progn
|
|
(concat "* " list-name "\n" (org-rtm-format-list-entries list-id))))
|
|
|
|
(defun org-rtm-format-lists ()
|
|
"Format RTM lists to org mode segments."
|
|
(mapconcat (lambda (list) (org-rtm-format-list (org-rtm-assoc-value 'id (nth 1 list)) (org-rtm-assoc-value 'name (nth 1 list)))) (rtm-lists-get-list) "\n"))
|
|
|
|
(defun org-rtm-complete-items (list-id)
|
|
"Complete all items in a given RTM list with LIST-ID (doesn't do any org-mode conversion)."
|
|
(mapcar
|
|
(lambda (taskseries-w-task)
|
|
(rtm-tasks-complete list-id (car taskseries-w-task) (cdr taskseries-w-task)))
|
|
(org-rtm-retrieve-taskseries-id-with-task-list list-id)))
|
|
|
|
(defun org-rtm-retrieve-taskseries-id-with-task-list (list-id)
|
|
"Retrieves the taskseries entry for list with LIST-ID."
|
|
(mapcar
|
|
(lambda (list)
|
|
`(,(org-rtm-assoc-value 'id (nth 1 list)) . ,(org-rtm-assoc-value 'id (car (org-rtm-assoc-value 'task (nthcdr 2 list))))))
|
|
(nthcdr 2 (car (rtm-tasks-get-list list-id "status:incomplete")))))
|
|
|
|
(defun org-rtm-retrieve-list-ids ()
|
|
"Retrieve a list of RTM list ids."
|
|
(mapcar (lambda (list) (org-rtm-assoc-value 'id (nth 1 list))) (rtm-lists-get-list)))
|
|
|
|
(defun org-rtm-complete-all-lists ()
|
|
"Complete all items of RTM all lists."
|
|
(mapcar (lambda (list-id) (org-rtm-complete-items list-id)) (org-rtm-retrieve-list-ids)))
|
|
|
|
(defun org-rtm-import ()
|
|
"Import RTM tasks to the given import file (overwriting it), then optionally completing the tasks, then opening the file in Emacs."
|
|
(interactive)
|
|
(message "Starting RTM import...")
|
|
(let
|
|
((import-data (org-rtm-format-lists)))
|
|
(find-file org-rtm-import-file)
|
|
(erase-buffer)
|
|
(if
|
|
org-rtm-complete-after-import
|
|
(progn
|
|
(org-rtm-complete-all-lists)
|
|
(message "Imported and completed all RTM tasks"))
|
|
(message "Imported tasks, not completing RTM tasks because of configuration option"))
|
|
(insert import-data)))
|
|
|
|
(provide 'org-rtm)
|
|
;;; org-rtm.el ends here
|