Permalink
Browse files

Initial import

  • Loading branch information...
0 parents commit 8612d7aa6e3a2835ed7fb231e97ef0d2958d9824 @lsegal committed Jun 22, 2008
@@ -0,0 +1,40 @@
+Things Export 1.0
+=================
+
+Written by **Loren Segal** in 2008. Licensed under MIT license.
+
+
+SYNOPSIS
+--------
+
+Exports your **Things.app** todo items to a simple webpage using `scp`. It
+is recommended that you add your public key to your remote SSH server for
+this to work smoothly.
+
+
+INSTALL
+-------
+
+`things-export` requires the environment variable `THINGS_REMOTE_PATH` to be
+set to the public www directory that the page will be copied to. You can set
+this manually per session or in your `~/.profile` file with:
+
+ export THINGS_REMOTE_PATH=user@example.com:/var/www/htdocs/todo/
+
+*Note the username and host that need to be changed.*
+
+You can optionally specify the `THINGS_AUTHOR` environment variable which will
+put your name in the title, ex. "Loren Segal's ToDo List". Defaults to "My ToDo List".
+
+Finally, type `ruby things-export.rb --install` after configuring your environment
+variables to copy over the necessary support files to the remote server. This will
+also export your database for the first time. After the support files are copied,
+you no longer need to run the script with `--install`.
+
+
+RUNNING
+-------
+
+After things-exporter is installed on the remote server, simply use `ruby things-exporter.rb`
+to update the remote index file. Ideally, you can run this from a cron-job to update your
+Things todo list every now and then.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,3 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><title>Loren Segal's ToDo List</title><link rel="stylesheet" type="text/css" href="style.css" charset="utf-8"/></head><body><h1>Loren Segal's Things List</h1><ul id="notdone"><li class="odd"><span class="leftcap"></span><span class="title">Chainable tag</span><span class="rightcap"></span><span class="duedate">2 days left</span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">tags</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="even"><span class="leftcap"></span><span class="title">Options tag</span><span class="rightcap"></span><span class="duedate">2 days left</span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">tags</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="odd"><span class="leftcap"></span><span class="title">Add "defined in" listing for class/module header</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">template</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="even"><span class="leftcap"></span><span class="title">Show @example tags in docs</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">template</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="odd"><span class="leftcap"></span><span class="title">New template stylesheet following sproutit / obj-c style</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">template</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="even"><span class="leftcap"></span><span class="title">Add support for multiple @return tags in documentation</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">template</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="odd"><span class="leftcap"></span><span class="title">Serialization to multiple files</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">registry</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">future</span><span class="rightcap"></span></span></span></li><li class="even"><span class="leftcap"></span><span class="title">Classmethod paths (File.relative_path)</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">registry</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">future</span><span class="rightcap"></span></span></span></li><li class="odd"><span class="leftcap"></span><span class="title">Should yard automatically link first occurence of each ++?</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">future</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">template</span><span class="rightcap"></span></span></span></li></ul><ul id="done"><li class="odd"><span class="leftcap"></span><span class="completed">Jun 19, 1977</span><span class="title">Method parameters</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">code objects</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="even"><span class="leftcap"></span><span class="completed">Jun 19, 1977</span><span class="title">Type list parser should parse until last ] is found. (Ditch regex)</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">tags</span><span class="rightcap"></span></span><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="odd"><span class="leftcap"></span><span class="completed">Jun 17, 1977</span><span class="title">Improve RDoc formatting for ++ (+yard-graph+ and +lib/+ should work)</span><span class="rightcap"></span><span class="tags"></span></li><li class="even"><span class="leftcap"></span><span class="completed">Jun 17, 1977</span><span class="title">Markdown/Textile/etc. support for README (and globally)</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="odd"><span class="leftcap"></span><span class="completed">Jun 17, 1977</span><span class="title">Improve RDoc formatting for links</span><span class="rightcap"></span><span class="tags"><span class="tag"><span class="leftcap"></span><span class="tagtitle">0.2.3</span><span class="rightcap"></span></span></span></li><li class="even"><span class="leftcap"></span><span class="completed">Jun 17, 1977</span><span class="title">Minor formatting fixes for README</span><span class="rightcap"></span><span class="tags"></span></li></ul></body></html>
@@ -0,0 +1,25 @@
+body { background: #b3b8c1; font-family: "Lucida Grande", sans-serif; font-size: 11px; }
+h1 { color: #fff; text-shadow: 3px 3px 3px black; margin-bottom: 1.1em; }
+ul { padding-left: 0; }
+#done li { color: #4b4b4c; background: #cfd2d7; list-style: url(images/done-check.gif) inside; margin-bottom: 1px; height: 27px; }
+#done li * { vertical-align: 60%; }
+#done li .leftcap { display: block; float: left; background: url(images/done-cap.gif); width: 4px; height: 27px; margin-right: 4px; }
+#done li .rightcap { display: block; float: right; background: url(images/done-cap.gif) right; width: 4px; height: 27px; }
+#done li .title { position: relative; top: 6px; }
+#done { margin-top: 2px; }
+#notdone li { color: #161616; background: #f7f7f7; list-style: url(images/notdone-check.gif) inside; margin-bottom: 1px; height: 27px; }
+#notdone li * { vertical-align: 60%; }
+#notdone li .title { padding-left: 15px; margin-top: 9px; position: relative; top: 6px; }
+#notdone li .leftcap { display: block; float: left; background: url(images/notdone-cap.gif); width: 4px; height: 27px; margin-right: 4px; }
+#notdone li .rightcap { display: block; float: right; background: url(images/notdone-cap.gif) right; width: 4px; height: 27px; }
+#notdone { margin-bottom: 1px; padding-bottom: 0; }
+.tags .tag { background: url(images/tag-bg.gif); height: 13px; font-family: "Myriad Pro"; float: left; margin-right: 6px; }
+.tags .tag .tagtitle { position: relative; left: -2px; top: 1px; }
+.tags { color: #3c4350; font-size: 10px; padding-top: 7px; float: right; }
+#notdone .tags .tag .leftcap { width: 6px; background: url(images/tag-cap.gif); height: 13px; }
+#notdone .tags .tag .rightcap { width: 6px; background: url(images/tag-cap.gif) right; height: 13px; }
+#done .tags .tag { color: #797b7d; background: url(images/done-tags-bg.gif); }
+#done .tags .tag .leftcap { width: 6px; background: url(images/done-tags-cap.gif); height: 13px; }
+#done .tags .tag .rightcap { width: 6px; background: url(images/done-tags-cap.gif) right; height: 13px; }
+#notdone li .duedate { display: block; float: right; color: #636363; border-left: 1px solid #cdcdcd; margin-left: 7px; padding-left: 20px; height: 18px; padding-right: 20px; padding-top: 9px; font-size: 9px; }
+#done li .completed { color: #7b7b7c; font-size: 9px; margin-right: 20px; padding-left: 5px; position: relative; top: 6px; }
@@ -0,0 +1,129 @@
+require 'rubygems'
+require 'hpricot'
+require 'markaby'
+require 'ostruct'
+
+if ARGV.index('-v') || ARGV.index('--version')
+ puts "things-export 1.0"
+ exit
+end
+
+if !ENV['THINGS_REMOTE_PATH']
+ STDERR.puts "You need to set THINGS_REMOTE_PATH as the URL to copy the index file with scp."
+ STDERR.puts "Example: username@example.com:/var/www/htdocs/todo/"
+ exit
+end
+
+author = ENV['THINGS_AUTHOR'] ? "#{ENV['THINGS_AUTHOR']}'s" : "My"
+things_remote = ENV['THINGS_REMOTE_PATH']
+
+if ARGV.index('--configure') || ARGV.index('-c') || ARGV.index('--install') || ARGV.index('-i')
+ pub = File.join(File.dirname(__FILE__), 'public')
+ puts "Installing things-export to #{things_remote}"
+ system("scp -r #{pub} #{things_remote}")
+end
+
+todos = {:done => [], :notdone => []}
+$tags = {}
+
+filename = File.expand_path('~/Library/Application Support/Cultured Code/Things/Database.xml')
+doc = Hpricot(File.read(filename))
+
+# Get all tags
+doc.search('object[@type="TAG"]').each do |tag|
+ $tags[tag.attributes["id"]] = tag.search('attribute[@name="title"]').text
+end
+
+# Loop through todo items
+doc.search('object[@type="TODO"]').each do |todo|
+ next if todo.search('relationship[@name="parent"][@idrefs]').empty?
+ which = todo.search('attribute[@name="status"]').text.to_i == 3 ? :done : :notdone
+
+ obj = OpenStruct.new
+ obj.tags = []
+ if which == :done
+ obj.completed = todo.search('attribute[@name="datecompleted"]').text.to_f
+ elsif t=todo.search('attribute[@name="datedue"]').first
+ obj.duedate = t.inner_html.to_f
+ end
+
+ if t=todo.search('relationship[@name="tags"][@idrefs]').first
+ obj.tags += t.attributes["idrefs"].split(/\s+/)
+ end
+
+ obj.title = todo.search('attribute[@name="title"]').text
+ obj.index = todo.search('attribute[@name="index"]').text
+
+ todos[which] << obj
+end
+todos[:done] = todos[:done].sort_by {|x| x.index }
+todos[:notdone] = todos[:notdone].sort_by {|x| x.index }
+
+def taglist(mab, taglist)
+ taglist.each do |tag|
+ mab.span(:class => 'tag') do
+ span(:class => 'leftcap')
+ span(:class => 'tagtitle') { $tags[tag] }
+ span(:class => 'rightcap')
+ end
+ end
+end
+
+mab = Markaby::Builder.new
+mab.html do
+ head do
+ title "#{author} ToDo List"
+ link :rel => 'stylesheet', :href => 'style.css', :type => 'text/css', :charset => 'utf-8'
+ end
+ body do
+ h1 "#{author} Things List"
+
+ ul(:id => 'notdone') do
+ row = 0
+ todos[:notdone].each do |todo|
+ row = !row
+ li(:class => (row ? 'even' : 'odd')) do
+ span(:class => 'leftcap')
+ span(:class => 'title') { todo.title }
+ span(:class => 'rightcap')
+ span(:class => 'duedate') do
+ (todo.duedate / 86400000).to_i.to_s + " days left"
+ end if todo.duedate
+ span(:class => 'tags') { taglist(mab, todo.tags) }
+ end
+ end
+ end
+
+ ul(:id => 'done') do
+ row = 0
+ todos[:done].each do |todo|
+ row = !row
+ li(:class => (row ? 'even' : 'odd')) do
+ span(:class => 'leftcap')
+ span(:class => 'completed') { Time.at(todo.completed).strftime("%b %d, %Y") }
+ span(:class => 'title') { todo.title }
+ span(:class => 'rightcap')
+ span(:class => 'tags') { taglist(mab, todo.tags) }
+ end
+ end
+ end
+
+ end
+end
+
+index = File.join(File.dirname(__FILE__), 'public', 'index.html')
+contents = <<-eof
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+#{mab}
+eof
+
+if !ARGV.index('-f') && File.file?(index) && File.read(index) == contents
+ puts "Todo list is identical to current local copy, no remote update necessary. Use -f to force."
+ exit
+end
+
+File.open(index, "w") {|f| f.write(contents) }
+
+puts "Pushing new list to #{things_remote}"
+system("scp #{index} #{things_remote}")

0 comments on commit 8612d7a

Please sign in to comment.