<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/assets/rss.xsl" type="text/xsl"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"

>
<channel>
	<title>Sacha Chua - tag - emacslisp</title>
	<atom:link href="https://sachachua.com/blog/tag/emacslisp/feed/index.xml" rel="self" type="application/rss+xml" />
	<atom:link href="https://sachachua.com/blog/tag/emacslisp" rel="alternate" type="text/html" />
	<link>https://sachachua.com/blog/tag/emacslisp/feed/index.xml</link>
	<description>Emacs, sketches, and life</description>
  
	<lastBuildDate>Mon, 06 Jul 2026 16:20:27 GMT</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>daily</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>11ty</generator>
  <item>
		<title>Org-toodledo</title>
		<link>https://sachachua.com/blog/2010/05/org-toodledo/</link>
		<dc:creator><![CDATA[Sacha Chua]]></dc:creator>
		<pubDate>Sun, 16 May 2010 12:00:00 GMT</pubDate>
    <category>emacs</category>
<category>geek</category>
<category>org</category>
<category>productivity</category>
		<guid isPermaLink="false">https://sachachua.com/blog/?p=7192</guid>
		<description><![CDATA[<p>I finally got around to asking my manager for permission to contribute org-toodledo as open source. Here it is. Enjoy!</p>
<pre class="code"><span class="comment-delimiter">;;; </span><span class="comment">org-toodledo.el - Toodledo integration for Emacs Org mode
</span><span class="comment-delimiter">;; </span><span class="comment">(c) 2010 Sacha Chua (sacha@sachachua.com)
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">This file is not part of GNU Emacs.
</span>
<span class="comment-delimiter">;; </span><span class="comment">This is free software; you can redistribute it and/or modify it under
</span><span class="comment-delimiter">;; </span><span class="comment">the terms of the GNU General Public License as published by the Free
</span><span class="comment-delimiter">;; </span><span class="comment">Software Foundation; either version 2, or (at your option) any later
</span><span class="comment-delimiter">;; </span><span class="comment">version.
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">This is distributed in the hope that it will be useful, but WITHOUT
</span><span class="comment-delimiter">;; </span><span class="comment">ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
</span><span class="comment-delimiter">;; </span><span class="comment">FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
</span><span class="comment-delimiter">;; </span><span class="comment">for more details.
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">You should have received a copy of the GNU General Public License
</span><span class="comment-delimiter">;; </span><span class="comment">along with GNU Emacs; see the file COPYING.  If not, write to the
</span><span class="comment-delimiter">;; </span><span class="comment">Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
</span><span class="comment-delimiter">;; </span><span class="comment">MA 02111-1307, USA.
</span>
<span class="comment-delimiter">;; </span><span class="comment">How to use:
</span><span class="comment-delimiter">;; </span><span class="comment">1. Customize org-toodledo-userid and org-toodledo-password
</span><span class="comment-delimiter">;; </span><span class="comment">2. Open a blank org file.
</span><span class="comment-delimiter">;; </span><span class="comment">3. Call org-toodledo-initialize-org
</span><span class="comment-delimiter">;; </span><span class="comment">Call org-toodledo-update to bring in new/updated tasks (skips locally modified tasks newer than updated)
</span><span class="comment-delimiter">;; </span><span class="comment">Call org-toodledo-sync-task to create or update the current task
</span><span class="comment-delimiter">;; </span><span class="comment">Call org-toodledo-delete-current-task to delete the current task
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">Doesn't do lots of error trapping. Might be a good idea to version-control your Org file.
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">TOODLEDO ATTRIBUTES and how they are bi-directionally handled
</span><span class="comment-delimiter">;; </span><span class="comment">Context: Handled by tags (ex:   :@work:  :@errands:)
</span><span class="comment-delimiter">;;   </span><span class="comment">- will create new contexts if necessary
</span><span class="comment-delimiter">;; </span><span class="comment">Task status: Mapped to TODO state.
</span><span class="comment-delimiter">;;   </span><span class="comment">See org-toodledo-status-to-string and org-toodledo-parse-current-task for the mapping
</span><span class="comment-delimiter">;;   </span><span class="comment">You will probably want something like this in your ~/.emacs:
</span><span class="comment-delimiter">;; </span><span class="comment">(setq org-todo-keywords
</span><span class="comment-delimiter">;;      </span><span class="comment">'((sequence
</span><span class="comment-delimiter">;;         </span><span class="comment">"TODO(t)"  ; next action
</span><span class="comment-delimiter">;;         </span><span class="comment">"PLAN(-)"
</span><span class="comment-delimiter">;;         </span><span class="comment">"STARTED(s)"
</span><span class="comment-delimiter">;;         </span><span class="comment">"WAITING(w@/!)"
</span><span class="comment-delimiter">;;         </span><span class="comment">"POSTPONED(p)" "SOMEDAY(s@/!)" "|" "DONE(x!)" "CANCELLED(c@)")
</span><span class="comment-delimiter">;;</span><span class="comment">      (type "DELEGATED(d@!)" "DONE(x)")))
</span><span class="comment-delimiter">;; </span><span class="comment">Length: Mapped to effort
</span><span class="comment-delimiter">;; </span><span class="comment">Priority: Mapped to [#A], [#B], or [#C]. (TODO: Change this to five levels of priority to match Toodledo)
</span><span class="comment-delimiter">;; </span><span class="comment">Start date: Mapped to "SCHEDULED"
</span><span class="comment-delimiter">;; </span><span class="comment">Due date: Mapped to "DEADLINE"
</span><span class="comment-delimiter">;; </span><span class="comment">Tags: Mapped to tags
</span><span class="comment-delimiter">;; </span><span class="comment">Note: Mapped to todo text. May get confused by asterisks, so don't use any starting asterisks in your body text.
</span><span class="comment-delimiter">;;   </span><span class="comment">(or anything that looks like an Org headline).
</span><span class="comment-delimiter">;; </span><span class="comment">Completed: Mapped to DONE todo state.
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">TODO:
</span><span class="comment-delimiter">;; </span><span class="comment">- [ ] Double-check new/changed/deleted task updating, still seems buggy
</span><span class="comment-delimiter">;; </span><span class="comment">- [ ] Test, test, test - maybe make test harness?
</span><span class="comment-delimiter">;; </span><span class="comment">- [ ] Move status&lt;-&gt;string mapping to a variable - lookups are better than logic
</span><span class="comment-delimiter">;; </span><span class="comment">- [ ] Make sure sync timestamps aren't getting updated more often than needed
</span><span class="comment-delimiter">;; </span><span class="comment">- [ ] Suggest some kind of hook to make it easier to mark a task as locally modified
</span>
(<span class="keyword">require</span> '<span class="constant">org</span>)
(<span class="keyword">require</span> '<span class="constant">w3m</span>)
(<span class="keyword">require</span> '<span class="constant">xml</span>)
(<span class="keyword">defcustom</span> <span class="variable-name">org-toodledo-userid</span> <span class="string">""</span>
  <span class="doc">"UserID from Toodledo: http://www.toodledo.com/info/api_doc.php"</span>
  <span class="builtin">:group</span> 'org-toodledo
  <span class="builtin">:type</span> 'string)

(<span class="keyword">defcustom</span> <span class="variable-name">org-toodledo-password</span> <span class="string">""</span>
  <span class="doc">"Password for Toodledo."</span>
  <span class="builtin">:group</span> 'org-toodledo
  <span class="builtin">:type</span> 'string)

(<span class="keyword">defvar</span> <span class="variable-name">org-toodledo-token-expiry</span> nil <span class="doc">"Expiry time for authentication token."</span>)
(<span class="keyword">defvar</span> <span class="variable-name">org-toodledo-token</span> nil <span class="doc">"Authentication token."</span>)
(<span class="keyword">defvar</span> <span class="variable-name">org-toodledo-key</span> nil <span class="doc">"Authentication key."</span>)

(<span class="keyword">require</span> '<span class="constant">url</span>)
(<span class="keyword">require</span> '<span class="constant">url-http</span>)

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-initialize-org</span> ()
  <span class="doc">"Replace buffer contents with Toodledo tasks."</span>
  (interactive)
  (delete-region (point-min) (point-max))
  (<span class="keyword">let</span> ((account-info (org-toodledo-get-account-info))
        (server-info (org-toodledo-get-server-info))
        (tasks (org-toodledo-get-tasks '((<span class="string">"notcomp"</span> . <span class="string">"1"</span>)))))
    (insert <span class="string">"* Toodledo\n"</span>
            <span class="string">":PROPERTIES:\n"</span>
            <span class="string">":Last-modified: "</span> (cdr (assoc <span class="string">"lastaddedit"</span> account-info)) <span class="string">"\n"</span>
            <span class="string">":Last-deleted: "</span> (cdr (assoc <span class="string">"lastdelete"</span> account-info)) <span class="string">"\n"</span>
            <span class="string">":Last-sync: "</span> (cdr (assoc <span class="string">"unixtime"</span> server-info)) <span class="string">"\n"</span>
            <span class="string">":END:\n"</span>)
    (insert (mapconcat 'org-toodledo-task-to-string tasks <span class="string">"\n"</span>))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-token</span> ()
  <span class="doc">"Retrieve authentication token valid for four hours."</span>
  (<span class="keyword">if</span> (and org-toodledo-token
           org-toodledo-token-expiry
           (time-less-p (current-time) org-toodledo-token-expiry))
      org-toodledo-token
    <span class="comment-delimiter">;; </span><span class="comment">Else retrieve a new token
</span>    (<span class="keyword">let</span> ((response
            (<span class="keyword">with-current-buffer</span>
                (url-retrieve-synchronously
                 (concat <span class="string">"http://api.toodledo.com/api.php?method=getToken;userid="</span>
                         org-toodledo-userid))
              (xml-parse-region (point-min) (point-max)))))
      (<span class="keyword">if</span> (equal (car (car response)) 'error)
          (<span class="keyword">progn</span>
            (setq org-toodledo-token nil
                  org-toodledo-key nil
                  org-toodledo-token-expiry nil)
            (<span class="warning">error</span> <span class="string">"Could not log in to Toodledo: %s"</span> (elt (car response) 2)))
        (setq org-toodledo-token
              (elt (car response) 2))
        (setq org-toodledo-key (org-toodledo-key)
              <span class="comment-delimiter">;; </span><span class="comment">Set the expiry time
</span>              org-toodledo-token-expiry
              (seconds-to-time
               (+ (time-to-seconds (current-time))
                  (* 60 60 4)))))   <span class="comment-delimiter">;; </span><span class="comment">four hours
</span>      org-toodledo-token)))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-key</span> ()
  <span class="doc">"Return authentication key used for each request."</span>
  (<span class="keyword">if</span> (and org-toodledo-token
           org-toodledo-token-expiry
           (time-less-p (current-time) org-toodledo-token-expiry)
           org-toodledo-key)
      org-toodledo-key
    (setq org-toodledo-key
          (md5 (concat (md5 org-toodledo-password)
                       org-toodledo-token
                       org-toodledo-userid)))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-url</span> (method-name <span class="type">&amp;optional</span> params)
  <span class="doc">"Return URL for METHOD-NAME and PARAMS."</span>
  (org-toodledo-get-token)
  (concat <span class="string">"http://api.toodledo.com/api.php?method="</span>
          (w3m-url-encode-string method-name)
          <span class="string">";key="</span> (org-toodledo-key)
          (<span class="keyword">if</span> params
              (concat
               <span class="string">";"</span>
               (mapconcat (<span class="keyword">lambda</span> (x)
                            (concat
                             (w3m-url-encode-string (car x)) <span class="string">"="</span>
                             (w3m-url-encode-string (cdr x))))
                          params
                          <span class="string">";"</span>))
            <span class="string">""</span>)))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-call-method</span> (method-name <span class="type">&amp;optional</span> params)
  <span class="doc">"Call METHOD-NAME with PARAMS and return the parsed XML."</span>
  (setq params (cons (cons <span class="string">"unix"</span> <span class="string">"1"</span>) params))
  (<span class="keyword">with-current-buffer</span>
      (url-retrieve-synchronously
       (org-toodledo-get-url method-name params))
    (xml-parse-region (point-min) (point-max))))

(<span class="keyword">defmacro</span> <span class="function-name">org-toodledo-defun</span> (function-name api-name description)
  `(<span class="keyword">defun</span> ,function-name (params)
     ,description
     (org-toodledo-call-method ,api-name params)))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-server-info</span> ()
  <span class="doc">"Return server information."</span>
  (org-toodledo-convert-xml-result-to-alist
    (car (org-toodledo-call-method <span class="string">"getServerInfo"</span>))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-account-info</span> ()
  <span class="doc">"Return server information."</span>
  (org-toodledo-convert-xml-result-to-alist
   (car (org-toodledo-call-method <span class="string">"getAccountInfo"</span>))))

(org-toodledo-defun org-toodledo-add-task <span class="string">"addTask"</span> <span class="string">"Add task with PARAMS."</span>)
(org-toodledo-defun org-toodledo-edit-task <span class="string">"editTask"</span> <span class="string">"Edit task with PARAMS."</span>)
(org-toodledo-defun org-toodledo-delete-task <span class="string">"deleteTask"</span> <span class="string">"Delete task with PARAMS."</span>)

<span class="comment-delimiter">;; </span><span class="comment">(setq temp (org-toodledo-get-tasks '(("notcomp" . "1"))))
</span><span class="comment-delimiter">;; </span><span class="comment">(setq server-info (org-toodledo-get-server-info))
</span><span class="comment-delimiter">;; </span><span class="comment">(setq account-info (org-toodledo-get-account-info))
</span>(<span class="keyword">defun</span> <span class="function-name">org-toodledo-convert-xml-result-to-alist</span> (info)
  <span class="doc">"Convert INFO to an alist."</span>
  (delq nil
        (mapcar
         (<span class="keyword">lambda</span> (item)
           (<span class="keyword">if</span> (listp item)
               (cons (symbol-name (car item)) (elt item 2))))
         (xml-node-children (delete <span class="string">"\n\t"</span> info)))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-tasks</span> (<span class="type">&amp;optional</span> params)
  <span class="doc">"Retrieve tasks using PARAMS.
Return a list of task alists."</span>
  (mapcar
   'org-toodledo-convert-xml-result-to-alist
   (xml-get-children
    (car (org-toodledo-call-method <span class="string">"getTasks"</span> params))
    'task)))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-deleted</span> (<span class="type">&amp;optional</span> params)
  <span class="doc">"Retrieve deleted tasks using PARAMS.
Return a list of task alists."</span>
  (mapcar
   'org-toodledo-convert-xml-result-to-alist
   (xml-get-children
    (car (org-toodledo-call-method <span class="string">"getDeleted"</span> params))
    'task)))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-entry-note</span> ()
  <span class="doc">"Extract the note for this entry."</span>
  (<span class="keyword">save-excursion</span>
    (org-back-to-heading)
    (<span class="keyword">when</span> (looking-at org-complex-heading-regexp)
      (goto-char (match-end 0))
      (<span class="keyword">let</span> ((text (buffer-substring-no-properties
                   (point)
                   (<span class="keyword">if</span> (re-search-forward org-complex-heading-regexp nil t)
                       (match-beginning 0)
                     (org-end-of-subtree)))))
        (<span class="keyword">with-temp-buffer</span>
          (insert text)
          (goto-char (point-min))
          (<span class="keyword">when</span> (re-search-forward
                 (concat <span class="string">"\\&lt;"</span>
                         (regexp-quote org-deadline-string) <span class="string">" +&lt;[</span><span class="string"><span class="negation-char">^</span></span><span class="string">&gt;\n]+&gt;[ \t]*"</span>) nil t)
            (replace-match <span class="string">""</span>))
          (goto-char (point-min))
          (<span class="keyword">when</span> (re-search-forward
                 (concat <span class="string">"\\&lt;"</span>
                         (regexp-quote org-scheduled-string) <span class="string">" +&lt;[</span><span class="string"><span class="negation-char">^</span></span><span class="string">&gt;\n]+&gt;[ \t]*"</span>) nil t)
            (replace-match <span class="string">""</span>))
          (goto-char (point-min))
          (<span class="keyword">while</span> (re-search-forward <span class="string">"\n\n+"</span> nil t)
            (replace-match <span class="string">"\n"</span>))
          (org-export-remove-or-extract-drawers org-drawers nil nil)
          (buffer-substring-no-properties (point-min)
                                          (point-max)))))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-parse-current-task</span> ()
  <span class="doc">"Extract the status and Toodledo ID of the current task."</span>
  (<span class="keyword">save-excursion</span>
    (org-back-to-heading t)
    (<span class="keyword">when</span> (and (looking-at org-complex-heading-regexp)
               (match-string 2)) <span class="comment-delimiter">;; </span><span class="comment">TODO
</span>      (<span class="keyword">let*</span> (info
             (status (match-string-no-properties 2))
             (priority (match-string-no-properties 3))
             (title (match-string-no-properties 4))
             (tags (match-string-no-properties 5))
             (id (org-entry-get (point) <span class="string">"Toodledo-ID"</span>))
             (contexts (org-toodledo-get-contexts))
             context)
        <span class="comment-delimiter">;; </span><span class="comment">(add-to-list 'info (cons "title" (match-string-no-properties 1)))
</span>        (<span class="keyword">if</span> id (add-to-list 'info (cons <span class="string">"id"</span> id)))
        (<span class="keyword">when</span> tags
          (setq tags
              (delq nil
                    (mapcar
                     (<span class="keyword">lambda</span> (tag)
                       (<span class="keyword">if</span> (&gt; (length tag) 0)
                           (<span class="keyword">if</span> (string-match (org-re <span class="string">"@</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">[[:alnum:]_]+</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string">"</span>) tag)
                               (<span class="keyword">progn</span>
                                 <span class="comment-delimiter">;; </span><span class="comment">Not recognized context
</span>                                 (<span class="keyword">if</span> (null (assoc (match-string 1 tag) contexts))
                                     <span class="comment-delimiter">;; </span><span class="comment">Create it if it does not yet exist
</span>                                     (<span class="keyword">let</span> ((result
                                            (org-toodledo-call-method
                                             <span class="string">"addContext"</span>
                                             (list (cons <span class="string">"title"</span> (match-string 1 tag))))))
                                       (<span class="keyword">if</span> (eq (caar result) 'added)
                                           (setq org-toodledo-contexts
                                                 (cons (cons (match-string 1 tag)
                                                             (elt (car result) 2))
                                                       org-toodledo-contexts)
                                                 contexts org-toodledo-contexts))))
                                   <span class="comment-delimiter">;; </span><span class="comment">Get the ID of the context
</span>                                 (setq context
                                       (cdr (assoc (match-string 1 tag) contexts)))
                                 nil)
                             tag)))
                     (split-string tags <span class="string">":"</span>)))))
        (setq info
              (list
               (cons <span class="string">"id"</span> id)
               (cons <span class="string">"title"</span> title)
               (cons <span class="string">"length"</span> (org-entry-get (point) <span class="string">"Effort"</span>))
               (cons <span class="string">"context"</span> context) 
               (cons <span class="string">"tag"</span> (mapconcat 'identity tags <span class="string">" "</span>))
               (cons <span class="string">"completed"</span> (<span class="keyword">if</span> (equal status <span class="string">"DONE"</span>) <span class="string">"1"</span> <span class="string">"0"</span>))
               (cons <span class="string">"status"</span>
                     (<span class="keyword">cond</span> 
                      ((equal status <span class="string">"STARTED"</span>) <span class="string">"2"</span>)
                      ((equal status <span class="string">"DELEGATED"</span>) <span class="string">"4"</span>)
                      ((equal status <span class="string">"SOMEDAY"</span>) <span class="string">"8"</span>)
                      ((equal status <span class="string">"CANCELLED"</span>) <span class="string">"9"</span>)
                      ((equal status <span class="string">"PLAN"</span>) <span class="string">"3"</span>)
                      ((equal status <span class="string">"WAITING"</span>) <span class="string">"5"</span>)                      
                      ((equal status <span class="string">"TODO"</span>) <span class="string">"1"</span>)))
               (cons <span class="string">"priority"</span>
                     (<span class="keyword">cond</span>
                      ((equal priority <span class="string">"[#A]"</span>) <span class="string">"2"</span>)
                      ((equal priority <span class="string">"[#B]"</span>) <span class="string">"1"</span>)
                      ((equal priority <span class="string">"[#C]"</span>) <span class="string">"0"</span>)))
               (cons <span class="string">"note"</span>
                     (org-toodledo-entry-note))))
        (<span class="keyword">when</span> (org-entry-get nil <span class="string">"DEADLINE"</span>)
          (setq info (cons (cons <span class="string">"duedate"</span>
                                 (substring (org-entry-get nil <span class="string">"DEADLINE"</span>)
                                            0 10)) info)))
        (<span class="keyword">when</span> (org-entry-get nil <span class="string">"SCHEDULED"</span>)
          (setq info (cons (cons <span class="string">"startdate"</span>
                                 (substring (org-entry-get nil <span class="string">"SCHEDULED"</span>)
                                            0 10)) info)))
        info))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-sync</span> ()
  <span class="doc">"Synchronize all tasks."</span>
  <span class="comment-delimiter">;; </span><span class="comment">Retrieve all tasks
</span>  <span class="comment-delimiter">;; </span><span class="comment">For each task in the current buffer
</span>  <span class="comment-delimiter">;;   </span><span class="comment">Synchronize an existing task that has changed
</span>   (<span class="keyword">let</span> ((regexp (concat <span class="string">"^\\*+[ \t]+</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">"</span> org-todo-regexp <span class="string">"</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string">"</span>)))
    (goto-char (point-min))
    (<span class="keyword">while</span> (re-search-forward regexp nil t)
      (org-toodledo-sync-task))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-update</span> ()
  <span class="doc">"Insert new tasks and update previous tasks."</span>
  (interactive)
  (<span class="keyword">let*</span> ((server-info (org-toodledo-get-server-info))
         (account-info (org-toodledo-get-account-info))
         (changed (org-toodledo-account-changed account-info))
         (last-deleted (string-to-number (or (org-entry-get-with-inheritance <span class="string">"Last-deleted"</span>) <span class="string">"0"</span>)))
         (last-modified (string-to-number (or (org-entry-get-with-inheritance <span class="string">"Last-modified"</span>) <span class="string">"0"</span>)))
         (last-update (string-to-number (or (org-entry-get-with-inheritance <span class="string">"Last-sync"</span>) <span class="string">"0"</span>)))
         processed)
    <span class="comment-delimiter">;; </span><span class="comment">If tasks have been deleted or modified, then the Toodledo API
</span>    <span class="comment-delimiter">;; </span><span class="comment">will give us the timestamps. We need to find out which tasks
</span>    <span class="comment-delimiter">;; </span><span class="comment">have been deleted or modified since the last time we retrieved
</span>    <span class="comment-delimiter">;; </span><span class="comment">the list of tasks that have been deleted or modified. We store
</span>    <span class="comment-delimiter">;; </span><span class="comment">the last times in the properties of the root element.
</span>    
    (<span class="keyword">if</span> (and (assoc <span class="string">"deleted"</span> changed) <span class="comment-delimiter">;; </span><span class="comment">Tasks have been deleted
</span>             (&gt;= (string-to-number (cdr (assoc <span class="string">"deleted"</span> changed))) last-deleted))
        (setq processed
              (append (org-toodledo-process-deleted-tasks
                       last-deleted)
                       processed)))
    (<span class="keyword">if</span> (and (assoc <span class="string">"modified"</span> changed) <span class="comment-delimiter">;; </span><span class="comment">Tasks have been added or edited
</span>             (&gt;= (string-to-number (cdr (assoc <span class="string">"modified"</span> changed)))
                last-modified))
        <span class="comment-delimiter">;; </span><span class="comment">Retrieve added/modified tasks
</span>        (setq processed (append
                         (org-toodledo-process-modified-tasks last-modified) processed)))
    <span class="comment-delimiter">;; </span><span class="comment">TODO Look for tasks that were modified locally since the last synchronization
</span>    (org-toodledo-process-locally-modified-tasks last-update processed)
    <span class="comment-delimiter">;; </span><span class="comment">TODO Update timestamps here
</span>    (goto-char (point-min))
    (<span class="keyword">when</span> (re-search-forward (concat <span class="string">"^</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">"</span> outline-regexp <span class="string">"</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string">"</span>) nil t)
      (org-entry-put (point)
                     <span class="string">"Last-sync"</span>
                     (cdr (assoc <span class="string">"unixtime"</span> server-info)))
      (<span class="keyword">when</span> (assoc <span class="string">"lastaddedit"</span> account-info)
        (org-entry-put (point)
                       <span class="string">"Last-modified"</span>
                       (cdr 
                        (assoc <span class="string">"lastaddedit"</span> account-info))))
      (<span class="keyword">when</span> (assoc <span class="string">"lastdelete"</span> account-info)
        (org-entry-put (point)
                         <span class="string">"Last-deleted"</span>
                         (cdr
                          (assoc <span class="string">"lastdelete"</span> account-info)))))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-process-locally-modified-tasks</span> (last-update processed)
  <span class="doc">"Synchronize tasks that were locally modified after LAST-UPDATE.
Skip tasks with IDs in PROCESSED."</span>
  (goto-char (point-min))
  (<span class="keyword">let</span> ((start (float-time (current-time))))
    (<span class="keyword">while</span> (re-search-forward org-complex-heading-regexp nil t)
      <span class="comment-delimiter">;; </span><span class="comment">Look for all tasks in this buffer
</span>      (<span class="keyword">if</span> (match-string 2)
          <span class="comment-delimiter">;; </span><span class="comment">Is it a new task, or has it been modified since the last update?
</span>          (<span class="keyword">let</span> ((id (org-entry-get (point) <span class="string">"Toodledo-ID"</span>))
                (modified (string-to-number (or (org-entry-get (point) <span class="string">"Modified"</span>) <span class="string">""</span>)))
                (last-sync (<span class="keyword">if</span> (org-entry-get (point) <span class="string">"Sync"</span>)
                               (string-to-number (org-entry-get (point) <span class="string">"Sync"</span>))
                             0)))
            (<span class="keyword">if</span> (or (null id)
                    (and (&gt; modified last-sync)
                         (&lt; modified start)
                         (not (member id processed))))
                (<span class="keyword">save-excursion</span> (org-toodledo-sync-task))))))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-touch</span> ()
  <span class="doc">"Update the current task."</span>
  (interactive)
  (org-entry-put (point) <span class="string">"Modified"</span> (format <span class="string">"%d"</span> (float-time (current-time)))))

(<span class="keyword">defvar</span> <span class="variable-name">org-toodledo-actually-delete</span> t)
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-process-deleted-tasks</span> (timestamp)
  <span class="doc">"Remove tasks deleted after TIMESTAMP."</span>
  (delq nil
        (mapcar
         (<span class="keyword">lambda</span> (task)
           (<span class="keyword">when</span> (org-toodledo-find-task task)
             (<span class="keyword">if</span> org-toodledo-actually-delete
                 (delete-region (org-back-to-heading)
                                (<span class="keyword">if</span> (re-search-forward org-complex-heading-regexp nil t)
                                    (match-beginning 0)
                                  (org-end-of-subtree)))
               (org-entry-delete (point) <span class="string">"Toodledo-ID"</span>)
               (org-entry-put (point) <span class="string">"Toodledo-Deleted"</span> (timestamp)))
             (org-toodledo-task-id task)))
         (org-toodledo-get-deleted
          (list (cons <span class="string">"after"</span> (number-to-string timestamp)))))))
  
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-process-modified-tasks</span> (modified)
  <span class="doc">"Handle all the tasks that have been modified since MODIFIED."</span>
  (delq nil
        (mapcar
         (<span class="keyword">lambda</span> (task)
           (<span class="keyword">if</span> (org-toodledo-find-task task)
               (<span class="keyword">if</span> (null (org-toodledo-update-task task modified))
                   (org-toodledo-task-id task))
             (org-toodledo-create-task task)))
         (org-toodledo-get-tasks (list (cons <span class="string">"modafter"</span> (number-to-string modified)))))))



(<span class="keyword">defun</span> <span class="function-name">org-toodledo-create-task</span> (task)
  <span class="doc">"Create a task for TASK."</span>
  (goto-char (point-max))
  (<span class="keyword">if</span> (point-at-eol) (insert <span class="string">"\n"</span>))
  (insert (org-toodledo-task-to-string task))
  (org-toodledo-task-id task))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-find-task</span> (task)
  <span class="doc">"Find the task specified by TASK."</span>
  (goto-char (point-min))
  (re-search-forward
   (concat <span class="string">"^[ \t]*:Toodledo-ID:[ \t]+"</span> (org-toodledo-task-id task) <span class="string">"$"</span>)
   nil t))
  
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-account-changed</span> (account-info)
  <span class="doc">"Return non-nil if the account has changed since the last check.
The result will be an alist of (\"modified\" . \"timestamp\") if tasks have
been added/edited and (\"deleted\" . \"timestamp\") if tasks have been deleted."</span>
  (<span class="keyword">let</span> ((last-modified (org-entry-get-with-inheritance <span class="string">"Last-modified"</span>))
        (last-deleted (org-entry-get-with-inheritance <span class="string">"Last-deleted"</span>))
        result)
    (<span class="keyword">if</span> (&gt; (string-to-number (or (cdr (assoc <span class="string">"lastaddedit"</span> account-info)) <span class="string">"0"</span>))
           (string-to-number (or last-modified <span class="string">"0"</span>)))
        (add-to-list 'result (cons <span class="string">"modified"</span> last-modified)))
    (<span class="keyword">if</span> (&gt; (string-to-number (or (cdr (assoc <span class="string">"lastdelete"</span> account-info)) <span class="string">""</span>))
           (string-to-number (or last-deleted <span class="string">"0"</span>)))
        (add-to-list 'result (cons <span class="string">"deleted"</span> last-deleted)))
    result))
  
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-sync-task</span> (<span class="type">&amp;optional</span> force)
  <span class="doc">"Update my Toodledo for the current task."</span>
  (interactive <span class="string">"P"</span>)
  (<span class="keyword">save-excursion</span>
    (<span class="keyword">let</span> ((task (org-toodledo-parse-current-task)))
      (<span class="keyword">if</span> (null (org-toodledo-task-id task))
          <span class="comment-delimiter">;; </span><span class="comment">New task, create it
</span>          (<span class="keyword">let</span> ((result (org-toodledo-add-task task)))
            (<span class="keyword">when</span> (eq (elt (car result) 0) 'added)
              (org-entry-put (point) <span class="string">"Toodledo-ID"</span> (elt (car result) 2))
              (org-entry-put (point) <span class="string">"Sync"</span>
                             (format <span class="string">"%d"</span> (float-time (current-time)) 1000))))
        <span class="comment-delimiter">;; </span><span class="comment">Old task, update
</span>        (<span class="keyword">when</span> (org-toodledo-success-p (org-toodledo-edit-task task))
          (<span class="keyword">if</span> (equal (org-toodledo-task-completed task) <span class="string">"1"</span>)
              (org-entry-put (point) <span class="string">"Completed"</span> <span class="string">"1"</span>)
            (org-entry-put (point) <span class="string">"Status"</span> (org-toodledo-task-status task)))
          (org-entry-put (point) <span class="string">"Sync"</span>
                         (format <span class="string">"%d"</span> (float-time (current-time)) 1000)))))))

<span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-format-date "2003-08-12") "&lt;2003-08-12 Tue&gt;"))
</span>(<span class="keyword">defun</span> <span class="function-name">org-toodledo-format-date</span> (date <span class="type">&amp;optional</span> repeat)
  <span class="doc">"Return yyyy-mm-dd day for DATE."</span>
  (concat
   <span class="string">"&lt;"</span>
   (format-time-string
    <span class="string">"%Y-%m-%d %a"</span>
    (<span class="keyword">cond</span>
     ((listp date) date)
     ((numberp date) (seconds-to-time date))
     ((and (stringp date)
           (string-match <span class="string">"^[0-9]+$"</span> date))
      (seconds-to-time (string-to-number date)))
     (t (apply 'encode-time (org-parse-time-string date)))))
   (<span class="keyword">if</span> repeat (concat <span class="string">" "</span> repeat) <span class="string">""</span>)
   <span class="string">"&gt;"</span>))

<span class="comment-delimiter">;; </span><span class="comment">(mapconcat 'org-toodledo-task-to-string temp "\n")
</span><span class="comment-delimiter">;; </span><span class="comment">(setq task (elt temp 2))
</span><span class="comment-delimiter">;; </span><span class="comment">(org-toodledo-task-to-string task)
</span>(<span class="keyword">defun</span> <span class="function-name">org-toodledo-task-to-string</span> (task <span class="type">&amp;optional</span> level)
  <span class="doc">"Return an Org-formatted version of TASK."</span>
  (<span class="keyword">let*</span> ((repeat (string-to-number (org-toodledo-task-repeat task)))
         (rep-advanced (org-toodledo-task-repeat-advanced task))
         (repeat-string (org-toodledo-repeat-to-string repeat rep-advanced))
         (priority (org-toodledo-task-priority task)))
    (concat
     (make-string (or level 2) ?*) <span class="string">" "</span>
     (org-toodledo-status-to-string task) <span class="string">" "</span>
     (<span class="keyword">cond</span>
      ((equal priority <span class="string">"-1"</span>) <span class="string">""</span>)
      ((equal priority <span class="string">"0"</span>) <span class="string">"[#C] "</span>)
      ((equal priority <span class="string">"1"</span>) <span class="string">"[#B] "</span>)
      ((equal priority <span class="string">"2"</span>) <span class="string">"[#A] "</span>)
      ((equal priority <span class="string">"3"</span>) <span class="string">"[#A] "</span>))
     (org-toodledo-task-title task)
     (<span class="keyword">if</span> (org-toodledo-task-context task)
         (concat <span class="string">" :@"</span> (org-toodledo-task-context task) <span class="string">":"</span>) 
       <span class="string">""</span>)
     <span class="string">"\n"</span>
     (<span class="keyword">if</span> (and (org-toodledo-task-duedate task)
              (not (equal (org-toodledo-task-duedate task) <span class="string">""</span>))
              (not (&lt; (string-to-number (org-toodledo-task-duedate task)) 0)))
         (concat org-deadline-string <span class="string">" "</span>
                 (org-toodledo-format-date
                  (org-toodledo-task-duedate task)
                  repeat-string)
                 <span class="string">"\n"</span>)
       <span class="string">""</span>)
     (or (org-toodledo-task-note task) <span class="string">""</span>) <span class="string">"\n"</span>
     <span class="string">":PROPERTIES:\n"</span>
     <span class="string">":Toodledo-ID: "</span> (org-toodledo-task-id task) <span class="string">"\n"</span>
     <span class="string">":Modified: "</span> (org-toodledo-task-modified task) <span class="string">"\n"</span>
     <span class="string">":Sync: "</span> (format <span class="string">"%d"</span> (float-time (current-time))) <span class="string">"\n"</span>
     <span class="string">":Effort: "</span> (org-toodledo-task-length task) <span class="string">"\n"</span>
     <span class="string">":END:\n"</span>
     )))

<span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 0) ""))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 1) "+1w"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 2) "+1m"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 3) "+1y"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 4) "+1d"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 5) "+2w"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 6) "+2m"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 7) "+6m"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 8) "+3m"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 108) ".+3m"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 101) ".+1w"))
</span><span class="comment-delimiter">;; </span><span class="comment">(assert (equal (org-toodledo-repeat-to-string 0) ""))
</span>
(<span class="keyword">defconst</span> <span class="variable-name">org-toodledo-repeat-intervals</span> '(<span class="string">""</span> <span class="string">"+1w"</span> <span class="string">"+1m"</span> <span class="string">"+1y"</span> <span class="string">"+1d"</span> <span class="string">"+2w"</span> <span class="string">"+2m"</span> <span class="string">"+6m"</span> <span class="string">"+3m"</span>))
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-status-to-string</span> (task)
  (<span class="keyword">let</span> ((comp (org-toodledo-task-completed task))
        (status (string-to-number (org-toodledo-task-status task))))
    (<span class="keyword">cond</span>
     ((not (or (null comp) (equal comp <span class="string">""</span>) (equal comp <span class="string">"0"</span>))) <span class="string">"DONE"</span>)
     ((= status 0) <span class="string">"TODO"</span>)
     ((= status 1) <span class="string">"TODO"</span>)
     ((= status 2) <span class="string">"STARTED"</span>)
     ((= status 3) <span class="string">"PLAN"</span>)
     ((= status 4) <span class="string">"DELEGATED"</span>)
     ((= status 5) <span class="string">"WAITING"</span>)
     ((= status 6) <span class="string">"PLAN"</span>)  <span class="comment-delimiter">; </span><span class="comment">hold
</span>     ((= status 7) <span class="string">"SOMEDAY"</span>)  <span class="comment-delimiter">; </span><span class="comment">postponed
</span>     ((= status 8) <span class="string">"SOMEDAY"</span>)
     ((= status 9) <span class="string">"CANCELLED"</span>)
     )))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-repeat-to-string</span> (repeat <span class="type">&amp;optional</span> rep-advanced)
  <span class="doc">"Turn TASK into a repeat sequence."</span>
  (<span class="keyword">cond</span>
   ((= repeat 0) nil)
   ((&gt; repeat 100) (concat <span class="string">"+"</span> (org-toodledo-repeat-to-string (mod repeat 100) rep-advanced)))
   ((and (= repeat 50) rep-advanced)
    (<span class="keyword">cond</span>
     ((string-match <span class="string">"Every </span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">[0-9]+</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string"> week"</span> rep-advanced)
      (concat <span class="string">"+"</span> (match-string 1 rep-advanced) <span class="string">"w"</span>))
     ((string-match <span class="string">"Every </span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">[0-9]+</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string"> month"</span> rep-advanced)
      (concat <span class="string">"+"</span> (match-string 1 rep-advanced) <span class="string">"m"</span>))
     ((string-match <span class="string">"Every </span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">[0-9]+</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string"> year"</span> rep-advanced)
      (concat <span class="string">"+"</span> (match-string 1 rep-advanced) <span class="string">"y"</span>))
     ((string-match <span class="string">"Every </span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">(</span></span><span class="string">[0-9]+</span><span class="string"><span class="regexp-grouping-backslash">\\</span></span><span class="string"><span class="regexp-grouping-construct">)</span></span><span class="string"> day"</span> rep-advanced)
      (concat <span class="string">"+"</span> (match-string 1 rep-advanced) <span class="string">"d"</span>))
     (t rep-advanced)))
   (t (elt org-toodledo-repeat-intervals repeat))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-delete-current-task</span> ()
  <span class="doc">"Delete the current task."</span>
  (interactive)
  (org-back-to-heading t)
  (<span class="keyword">let</span> ((task (org-toodledo-parse-current-task)))
    (and (&gt; (length (org-toodledo-task-id task)) 0)
         (org-toodledo-success-p (org-toodledo-delete-task task)))
    (delete-region
     (point)
     (<span class="keyword">if</span> (and (end-of-line)
              (re-search-forward org-complex-heading-regexp nil t))
         (match-beginning 0)
       (org-end-of-subtree t t)
       (point)))))

  
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-task-get-prop</span> (task prop) (cdr (assoc prop task)))
(<span class="keyword">defmacro</span> <span class="function-name">org-toodledo-task-prop-defun</span> (field)
  `(<span class="keyword">defun</span> ,(intern (concat <span class="string">"org-toodledo-task-"</span> field)) (task)
     (cdr (assoc ,field task))))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-success-p</span> (result)
  <span class="doc">"Return non-nil if RESULT indicates success."</span>
  (eq (car (car result)) 'success))
        
(org-toodledo-task-prop-defun <span class="string">"id"</span>)
(org-toodledo-task-prop-defun <span class="string">"title"</span>)
(org-toodledo-task-prop-defun <span class="string">"status"</span>)
(org-toodledo-task-prop-defun <span class="string">"completed"</span>)
(org-toodledo-task-prop-defun <span class="string">"repeat"</span>)
(org-toodledo-task-prop-defun <span class="string">"context"</span>)
(org-toodledo-task-prop-defun <span class="string">"duedate"</span>)
(org-toodledo-task-prop-defun <span class="string">"modified"</span>)
(org-toodledo-task-prop-defun <span class="string">"priority"</span>)
(org-toodledo-task-prop-defun <span class="string">"note"</span>)
(org-toodledo-task-prop-defun <span class="string">"length"</span>)
<span class="comment-delimiter">;; </span><span class="comment">defun'd separately because of the change in name
</span>(<span class="keyword">defun</span> <span class="function-name">org-toodledo-task-repeat-advanced</span> (task)
  (cdr (assoc <span class="string">"rep_advanced"</span> task)))

(<span class="keyword">defvar</span> <span class="variable-name">org-toodledo-contexts</span> nil <span class="doc">"An alist of (context . id)."</span>)
(<span class="keyword">defun</span> <span class="function-name">org-toodledo-get-contexts</span> (<span class="type">&amp;optional</span> force)
  <span class="doc">"Store an alist of (context . id) in `</span><span class="doc"><span class="constant">org-toodledo-contexts</span></span><span class="doc">'.
Reload if FORCE is non-nil."</span>
  (<span class="keyword">if</span> (or force (null org-toodledo-contexts))
      (setq org-toodledo-contexts
            (mapcar
             (<span class="keyword">lambda</span> (node)
               (cons
              (car (xml-node-children node))
              (xml-get-attribute node 'id)))
             (xml-get-children (car
                                (org-toodledo-call-method <span class="string">"getContexts"</span>)) 'context)))
    org-toodledo-contexts))

(<span class="keyword">defun</span> <span class="function-name">org-toodledo-agenda-touch</span> ()
  <span class="doc">"Update the Modified timestamp for the current entry in the agenda."</span>
  (org-agenda-check-type t 'agenda 'timeline)
  (org-agenda-check-no-diary)
  (<span class="keyword">let*</span> ((marker (or (org-get-at-bol 'org-marker)
                     (org-agenda-error)))
         (buffer (marker-buffer marker))
         (pos (marker-position marker)))
    (org-with-remote-undo buffer
     (<span class="keyword">with-current-buffer</span> buffer
       (widen)
       (goto-char pos)
       (<span class="keyword">if</span> (org-entry-get (point) <span class="string">"Modified"</span>)
           (org-entry-put (point) <span class="string">"Modified"</span> (format <span class="string">"%d"</span> (float-time (current-time)))))))))


(<span class="keyword">defun</span> <span class="function-name">org-toodledo-update-task</span> (task <span class="type">&amp;optional</span> last-update)
  (<span class="keyword">let*</span> ((modified (string-to-number (or (org-entry-get (point) <span class="string">"Modified"</span>) <span class="string">""</span>)))
         (last-sync (<span class="keyword">if</span> (org-entry-get (point) <span class="string">"Sync"</span>)
                        (string-to-number (org-entry-get (point) <span class="string">"Sync"</span>))
                      0))
         (level (car (org-heading-components)))
         (locally-modified (&gt; modified last-sync)))
    <span class="comment-delimiter">;; </span><span class="comment">Locally modified? keep
</span>    (<span class="keyword">if</span> locally-modified
        nil
      <span class="comment-delimiter">;; </span><span class="comment">Not locally modified? replace
</span>      <span class="comment-delimiter">;; </span><span class="comment">Figure out what our level is
</span>      (delete-region (org-back-to-heading)
                     (<span class="keyword">progn</span> (goto-char (match-end 0))
                            (<span class="keyword">if</span> (re-search-forward org-complex-heading-regexp nil t)
                                (goto-char (match-beginning 0))
                              (org-end-of-subtree))))
      (insert (org-toodledo-task-to-string task level))
      t)))

(<span class="keyword">provide</span> '<span class="constant">org-toodledo</span>)
</pre>

<p>You can <a href="https://sachachua.com/blog/2010/05/org-toodledo/#comment">view 13 comments</a> or <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2010%2F05%2Forg-toodledo%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></description>
		</item><item>
		<title>Emacs Gnus hack: Prioritize based on the number of recipients</title>
		<link>https://sachachua.com/blog/2006/10/emacs-gnus-hack-prioritize-based-on-the-number-of-recipients/</link>
		<dc:creator><![CDATA[Sacha Chua]]></dc:creator>
		<pubDate>Wed, 04 Oct 2006 19:15:00 GMT</pubDate>
    <category>emacs</category>
		<guid isPermaLink="false">https://sachachua.com/blog/?p=3920</guid>
		<description><![CDATA[<p>Ever found yourself confronted with an inbox overflowing with general<br>
messages that you can ignore and messages that you and only you can<br>
act on? Here's something to help you sort the wheat from the chaff.</p>
<p>This indicates how personal messages are so you can immediately see which messages are just for you and which are part of a long Cc. Stephen Perelgut showed me the feature in Lotus Notes and I wanted to steal it sometime, so I did it while waiting for the Instant Rails archive.</p>
<p>To use it, add %ur to your gnus-summary-line-format.</p>
<pre class="example">
(add-to-list 'nnmail-extra-headers 'To)
(add-to-list 'nnmail-extra-headers 'Cc)
(defvar sacha/gnus-count-recipients-threshold 5
  "*Number of recipients to consider as large.")

(defun sacha/gnus-count-recipients (header)
  "Given a Gnus message header, returns priority mark.
If I am the only recipient, return \"!\".
If I am one of a few recipients, but I'm listed in To:, return \"*\".
If I am one of a few recipients, return \"/\".
If I am one of many recipients, return \".\".
Else, return \" \"."
  (let* ((to (or (cdr (assoc 'To (mail-header-extra header))) ""))
         (cc (or (cdr (assoc 'Cc (mail-header-extra header))) "")))
    (cond
     ((string-match gnus-ignored-from-addresses to)
      (let ((len (length (bbdb-split to ","))))
        (cond
         ((= len 1) "!")
         ((< len sacha/gnus-count-recipients-threshold) "*")
         (t "/"))))
     ((string-match gnus-ignored-from-addresses
                    (concat to ", " cc))
      (if (< (length (bbdb-split (concat to ", " cc) ","))
             sacha/gnus-count-recipients-threshold)
          "/"
        "."))
     (t " "))))

(defalias 'gnus-user-format-function-r 'sacha/gnus-count-recipients)
</pre>
<p>Random Emacs symbol: dired-listing-switches - Variable: *Switches passed to `ls' for Dired.  MUST contain the `l' option.</p>


<p>You can <a href="mailto:sacha@sachachua.com?subject=Comment%20on%20https%3A%2F%2Fsachachua.com%2Fblog%2F2006%2F10%2Femacs-gnus-hack-prioritize-based-on-the-number-of-recipients%2F&body=Name%20you%20want%20to%20be%20credited%20by%20(if%20any)%3A%20%0AMessage%3A%20%0ACan%20I%20share%20your%20comment%20so%20other%20people%20can%20learn%20from%20it%3F%20Yes%2FNo%0A">e-mail me at sacha@sachachua.com</a>.</p>]]></description>
		</item>
	</channel>
</rss>