remember-the-ruby 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +1 -0
- data/bin/rtr +20 -0
- data/lib/core_ext/datetime.rb +9 -0
- data/lib/core_ext/enumerable.rb +7 -0
- data/lib/core_ext/fixnum.rb +7 -0
- data/lib/core_ext/nil.rb +7 -0
- data/lib/core_ext/string.rb +22 -0
- data/lib/remember-the-ruby/api.rb +74 -0
- data/lib/remember-the-ruby/contact.rb +0 -0
- data/lib/remember-the-ruby/entity.rb +57 -0
- data/lib/remember-the-ruby/entity_list.rb +58 -0
- data/lib/remember-the-ruby/group.rb +0 -0
- data/lib/remember-the-ruby/list.rb +11 -0
- data/lib/remember-the-ruby/location.rb +0 -0
- data/lib/remember-the-ruby/note.rb +0 -0
- data/lib/remember-the-ruby/rpc.rb +187 -0
- data/lib/remember-the-ruby/storage.rb +43 -0
- data/lib/remember-the-ruby/tag.rb +21 -0
- data/lib/remember-the-ruby/task.rb +20 -0
- data/lib/remember-the-ruby/task_occurrence.rb +5 -0
- data/lib/remember-the-ruby.rb +49 -0
- data/lib/rtr/api.rb +22 -0
- data/lib/rtr/command_helper.rb +11 -0
- data/lib/rtr/commands.rb +67 -0
- data/lib/rtr.rb +21 -0
- metadata +98 -0
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
This will be a command line interface to Remember the Milk
|
data/bin/rtr
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'remember-the-ruby'))
|
4
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'rtr'))
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
$storage = RememberTheRuby::Storage.new
|
9
|
+
$storage[:cache_timeout] ||= 15.minutes
|
10
|
+
|
11
|
+
usage_and_exit if ARGV.length < 1
|
12
|
+
|
13
|
+
command = ARGV.shift
|
14
|
+
options = ARGV.dup
|
15
|
+
|
16
|
+
proc = $methods[command.to_sym]
|
17
|
+
|
18
|
+
usage_and_exit unless proc
|
19
|
+
|
20
|
+
proc.call(options)
|
data/lib/core_ext/nil.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'term/ansicolor'
|
4
|
+
|
5
|
+
class String
|
6
|
+
|
7
|
+
include Term::ANSIColor
|
8
|
+
|
9
|
+
def to_date
|
10
|
+
begin
|
11
|
+
date = DateTime.parse(self)
|
12
|
+
rescue
|
13
|
+
date = nil
|
14
|
+
end
|
15
|
+
date
|
16
|
+
end
|
17
|
+
|
18
|
+
def blank?
|
19
|
+
self == ""
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module RememberTheRuby
|
2
|
+
class API
|
3
|
+
|
4
|
+
def initialize(options={})
|
5
|
+
@transport = RPC::Transport.new(
|
6
|
+
:key => 'cb877b5c450d216ce9e563394dff6c07',
|
7
|
+
:secret => '97cbbc48a9b1b54c',
|
8
|
+
:frob => options[:frob],
|
9
|
+
:token => options[:token]
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def authorization_url
|
14
|
+
self.frob = @transport.auth.get_frob
|
15
|
+
@transport.auth.get_authorization_url
|
16
|
+
end
|
17
|
+
|
18
|
+
def authenticate
|
19
|
+
self.token = @transport.auth.get_token
|
20
|
+
end
|
21
|
+
|
22
|
+
# first-order objects #####################################################
|
23
|
+
|
24
|
+
def lists
|
25
|
+
@transport.lists.get_list
|
26
|
+
end
|
27
|
+
|
28
|
+
def settings
|
29
|
+
@transport.settings.get_list
|
30
|
+
end
|
31
|
+
|
32
|
+
def tasks
|
33
|
+
@transport.tasks.get_list
|
34
|
+
end
|
35
|
+
|
36
|
+
# derivative objects ######################################################
|
37
|
+
|
38
|
+
def default_list
|
39
|
+
lists.find(settings["defaultlist"])
|
40
|
+
end
|
41
|
+
|
42
|
+
def tags
|
43
|
+
found_tags = EntityList.new(@transport, Tag)
|
44
|
+
tasks.each do |task|
|
45
|
+
task.tags.each do |tag|
|
46
|
+
found = false
|
47
|
+
found_tags.each do |found_tag|
|
48
|
+
if tag.to_s == found_tag.to_s
|
49
|
+
found = true
|
50
|
+
break
|
51
|
+
end
|
52
|
+
end
|
53
|
+
found_tags << tag unless found
|
54
|
+
end
|
55
|
+
end
|
56
|
+
found_tags
|
57
|
+
end
|
58
|
+
|
59
|
+
## accessors ##############################################################
|
60
|
+
|
61
|
+
def frob
|
62
|
+
@transport.frob
|
63
|
+
end
|
64
|
+
|
65
|
+
def frob=(frob)
|
66
|
+
@transport.frob = frob
|
67
|
+
end
|
68
|
+
|
69
|
+
def token=(token)
|
70
|
+
@transport.token = token
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
File without changes
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module RememberTheRuby
|
2
|
+
class Entity < Hash
|
3
|
+
|
4
|
+
def initialize(transport, data={})
|
5
|
+
@transport = transport
|
6
|
+
self.merge!(data)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.from_element(transport, element)
|
10
|
+
data = element.attributes.keys.inject({}) do |memo, key|
|
11
|
+
memo[key] = element.attributes[key]
|
12
|
+
memo
|
13
|
+
end
|
14
|
+
self.new(transport, data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.list_from_elements(transport, rsp, element)
|
18
|
+
EntityList.from_element(transport, self, rsp, element)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(method_name)
|
22
|
+
self[method_name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def hydrate_from(&blk)
|
26
|
+
entity = yield blk
|
27
|
+
entity.each do |key, value|
|
28
|
+
self[key] = value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :regular_reader, :[]
|
33
|
+
alias_method :regular_writer, :[]=
|
34
|
+
|
35
|
+
undef id
|
36
|
+
|
37
|
+
def [](key)
|
38
|
+
regular_reader(key.to_s)
|
39
|
+
end
|
40
|
+
|
41
|
+
def []=(key, value)
|
42
|
+
regular_writer(key.to_s, value)
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :original_lookup, :[]
|
46
|
+
|
47
|
+
def [](key)
|
48
|
+
value = self
|
49
|
+
parts = key.to_s.split('/')
|
50
|
+
parts.each do |part|
|
51
|
+
value = value.original_lookup(part)
|
52
|
+
end
|
53
|
+
value
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RememberTheRuby
|
2
|
+
class EntityList < Array
|
3
|
+
|
4
|
+
attr_accessor :defaults
|
5
|
+
|
6
|
+
def initialize(transport, type)
|
7
|
+
@transport = transport
|
8
|
+
@type = type
|
9
|
+
@defaults = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def new
|
13
|
+
entity = @type.new(@transport)
|
14
|
+
@defaults.each do |key, value|
|
15
|
+
entity[key] = value
|
16
|
+
end
|
17
|
+
entity
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(options)
|
21
|
+
|
22
|
+
case options
|
23
|
+
when String, Integer then
|
24
|
+
params = { 'id' => options.to_s }
|
25
|
+
amount = :one
|
26
|
+
when Hash then
|
27
|
+
params = options
|
28
|
+
amount = :many
|
29
|
+
else
|
30
|
+
params = {}
|
31
|
+
amount = :many
|
32
|
+
end
|
33
|
+
|
34
|
+
matches = EntityList.new(@transport, @type)
|
35
|
+
self.each do |entity|
|
36
|
+
matched = true
|
37
|
+
params.each do |key, value|
|
38
|
+
unless entity[key] == value
|
39
|
+
matched = false
|
40
|
+
break
|
41
|
+
end
|
42
|
+
end
|
43
|
+
matches << entity if matched
|
44
|
+
end
|
45
|
+
|
46
|
+
amount == :many ? matches : matches.first
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.from_element(transport, type, rsp, xpath)
|
50
|
+
entity_list = EntityList.new(transport, type)
|
51
|
+
rsp.get_elements(xpath).map do |element|
|
52
|
+
entity_list << type.from_element(transport, element)
|
53
|
+
end
|
54
|
+
entity_list
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,187 @@
|
|
1
|
+
module RememberTheRuby
|
2
|
+
module RPC
|
3
|
+
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'net/http'
|
6
|
+
require 'rexml/document'
|
7
|
+
|
8
|
+
class Transport
|
9
|
+
|
10
|
+
TRANSPORT_URI = 'http://www.rememberthemilk.com'
|
11
|
+
|
12
|
+
attr_accessor :key, :secret, :frob, :token
|
13
|
+
|
14
|
+
def initialize(params)
|
15
|
+
@key = params[:key]
|
16
|
+
@secret = params[:secret]
|
17
|
+
@frob = params[:frob]
|
18
|
+
@token = params[:token]
|
19
|
+
|
20
|
+
@transport_http = build_transport_http
|
21
|
+
end
|
22
|
+
|
23
|
+
public ####################################################################
|
24
|
+
|
25
|
+
def request(method, params={})
|
26
|
+
params[:method] = method
|
27
|
+
|
28
|
+
uri = URI.encode(rest_path(params))
|
29
|
+
data = @transport_http.get(uri)
|
30
|
+
doc = REXML::Document.new(data.body)
|
31
|
+
|
32
|
+
doc.elements['rsp']
|
33
|
+
end
|
34
|
+
|
35
|
+
# rpc types ###############################################################
|
36
|
+
|
37
|
+
def auth
|
38
|
+
@auth ||= Auth.new(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def lists
|
42
|
+
@lists ||= Lists.new(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
def settings
|
46
|
+
@settings ||= Settings.new(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
def tasks
|
50
|
+
@tasks ||= Tasks.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def timeline
|
54
|
+
Timelines.new(self).create
|
55
|
+
end
|
56
|
+
|
57
|
+
# private #################################################################
|
58
|
+
|
59
|
+
def build_transport_http
|
60
|
+
uri = URI::parse(TRANSPORT_URI)
|
61
|
+
@transport_http = Net::HTTP.start(uri.host, uri.port)
|
62
|
+
end
|
63
|
+
|
64
|
+
def clear_empty_parameters(params)
|
65
|
+
params.dup.each do |k, v|
|
66
|
+
params.delete(k) if v.nil? || v == ''
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def auth_path(params)
|
71
|
+
self.service_path('auth', params)
|
72
|
+
end
|
73
|
+
|
74
|
+
def rest_path(params)
|
75
|
+
self.service_path('rest', params)
|
76
|
+
end
|
77
|
+
|
78
|
+
def service_path(service, params)
|
79
|
+
params[:frob] ||= @frob
|
80
|
+
params[:api_key] ||= @key
|
81
|
+
params[:auth_token] ||= @token
|
82
|
+
|
83
|
+
clear_empty_parameters(params)
|
84
|
+
|
85
|
+
params[:api_sig] = sign_parameters(params)
|
86
|
+
"/services/#{service}/?#{flatten_parameters(params)}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def sign_parameters(params)
|
90
|
+
signature = @secret
|
91
|
+
signature += params.map { |k, v| [k, v].join('') }.sort.join('')
|
92
|
+
Digest::MD5.hexdigest(signature)
|
93
|
+
end
|
94
|
+
|
95
|
+
def flatten_parameters(params)
|
96
|
+
params.map { |k, v| [k, v].join('=') }.join('&')
|
97
|
+
end
|
98
|
+
|
99
|
+
def hash_from_element(element)
|
100
|
+
element.attributes
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
class Transported
|
106
|
+
|
107
|
+
def initialize(transport)
|
108
|
+
@transport = transport
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
class Auth < Transported
|
114
|
+
|
115
|
+
def get_authorization_url(params={})
|
116
|
+
params[:perms] ||= 'delete'
|
117
|
+
data = Transport::TRANSPORT_URI + @transport.auth_path(params)
|
118
|
+
end
|
119
|
+
|
120
|
+
def get_frob
|
121
|
+
rsp = @transport.request('rtm.auth.getFrob')
|
122
|
+
rsp.elements['frob'].text
|
123
|
+
end
|
124
|
+
|
125
|
+
def get_token
|
126
|
+
rsp = @transport.request('rtm.auth.getToken')
|
127
|
+
rsp.elements['auth/token'].text
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
class Lists < Transported
|
133
|
+
|
134
|
+
def get_list
|
135
|
+
rsp = @transport.request('rtm.lists.getList')
|
136
|
+
List.list_from_elements(@transport, rsp, 'lists/list')
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
class Settings < Transported
|
142
|
+
|
143
|
+
def get_list
|
144
|
+
rsp = @transport.request('rtm.settings.getList')
|
145
|
+
rsp.get_elements('settings').first.inject({}) do |memo, element|
|
146
|
+
memo[element.name] = element.text
|
147
|
+
memo
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
class Tasks < Transported
|
154
|
+
|
155
|
+
def add(params={})
|
156
|
+
params[:list_id] ||= nil
|
157
|
+
params[:name] ||= nil
|
158
|
+
params[:parse] ||= nil
|
159
|
+
|
160
|
+
params[:timeline] = @transport.timeline
|
161
|
+
params[:parse] = params[:parse] ? 1 : 0
|
162
|
+
|
163
|
+
rsp = @transport.request('rtm.tasks.add', params)
|
164
|
+
Task.from_element(@transport, rsp.get_elements('list/taskseries').first)
|
165
|
+
end
|
166
|
+
|
167
|
+
def get_list(params={})
|
168
|
+
params[:list_id] ||= nil
|
169
|
+
params[:filter] ||= nil
|
170
|
+
params[:last_sync] ||= nil
|
171
|
+
rsp = @transport.request('rtm.tasks.getList', params)
|
172
|
+
Task.list_from_elements(@transport, rsp, 'tasks/list/taskseries')
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
class Timelines < Transported
|
178
|
+
|
179
|
+
def create(params={})
|
180
|
+
rsp = @transport.request('rtm.timelines.create', params)
|
181
|
+
rsp.get_elements('timeline').first.text
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'preferences'
|
3
|
+
|
4
|
+
module RememberTheRuby
|
5
|
+
class Storage < Preferences::Manager
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super(:remember_the_ruby, :autosave => true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_cache_timeout(key, timeout)
|
12
|
+
self[:cache] ||= {}
|
13
|
+
self[:cache][key] ||= Time.now + timeout
|
14
|
+
self.save
|
15
|
+
end
|
16
|
+
|
17
|
+
def cache_timeout_for(key)
|
18
|
+
original_reader(:cache) ? original_reader(:cache)[key] : nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def purge_cache!
|
22
|
+
return unless self[:cache].is_a?(Enumerable)
|
23
|
+
self[:cache].each do |key, timeout|
|
24
|
+
self.delete(key)
|
25
|
+
end
|
26
|
+
self.delete(:cache)
|
27
|
+
self.save
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_method :original_reader, :[]
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
now = Time.now
|
34
|
+
timeout = cache_timeout_for(key) || now
|
35
|
+
if timeout < now
|
36
|
+
self.delete(key)
|
37
|
+
self[:cache].delete(key)
|
38
|
+
end
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RememberTheRuby
|
2
|
+
class Tag < Entity
|
3
|
+
|
4
|
+
def self.from_element(transport, element)
|
5
|
+
tag = super
|
6
|
+
tag['name'] = element.text
|
7
|
+
tag
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
self['name']
|
12
|
+
end
|
13
|
+
|
14
|
+
def tasks
|
15
|
+
tasks = @transport.tasks.get_list(:filter => "tag:#{self["name"]}")
|
16
|
+
# TODO: add default tag to the tasks list
|
17
|
+
tasks
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RememberTheRuby
|
2
|
+
class Task < Entity
|
3
|
+
|
4
|
+
def self.from_element(transport, element)
|
5
|
+
task = super
|
6
|
+
task["occurrences"] = TaskOccurrence.list_from_elements(transport, element, 'task')
|
7
|
+
task["next"] = task["occurrences"].sorted_by(:due).first
|
8
|
+
task["tags"] = Tag.list_from_elements(transport, element, 'tags/tag')
|
9
|
+
task
|
10
|
+
end
|
11
|
+
|
12
|
+
def save!(params={})
|
13
|
+
hydrate_from do
|
14
|
+
@transport.tasks.add(:name => self[:name], :parse => params[:parse])
|
15
|
+
end
|
16
|
+
# TODO: apply tags
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Equivalent to a header guard in C/C++
|
2
|
+
# Used to prevent the class/module from being loaded more than once
|
3
|
+
unless defined? RememberTheRuby
|
4
|
+
|
5
|
+
module RememberTheRuby
|
6
|
+
|
7
|
+
# :stopdoc:
|
8
|
+
VERSION = '0.4.1'
|
9
|
+
LIBPATH = File.expand_path(File.dirname(__FILE__)) + File::SEPARATOR
|
10
|
+
PATH = File.dirname(LIBPATH) + File::SEPARATOR
|
11
|
+
# :startdoc:
|
12
|
+
|
13
|
+
# Returns the version string for the library.
|
14
|
+
#
|
15
|
+
def self.version
|
16
|
+
VERSION
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns the library path for the module. If any arguments are given,
|
20
|
+
# they will be joined to the end of the libray path using
|
21
|
+
# <tt>File.join</tt>.
|
22
|
+
#
|
23
|
+
def self.libpath( *args )
|
24
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the lpath for the module. If any arguments are given,
|
28
|
+
# they will be joined to the end of the path using
|
29
|
+
# <tt>File.join</tt>.
|
30
|
+
#
|
31
|
+
def self.path( *args )
|
32
|
+
args.empty? ? PATH : ::File.join(PATH, *args)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
36
|
+
# directory below this file that has the same name as the filename passed
|
37
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
38
|
+
# the _filename_ does not have to be equivalent to the directory.
|
39
|
+
#
|
40
|
+
def self.require_all_libs_relative_to(fname)
|
41
|
+
search_me = File.expand_path(File.join(File.dirname(fname), '**', '*.rb'))
|
42
|
+
Dir.glob(search_me).sort.each { |rb| require rb }
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
RememberTheRuby.require_all_libs_relative_to __FILE__
|
48
|
+
|
49
|
+
end # unless defined?
|
data/lib/rtr/api.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
def api
|
2
|
+
|
3
|
+
@api ||= begin
|
4
|
+
|
5
|
+
api = RememberTheRuby::API.new(:frob => $storage[:frob],
|
6
|
+
:token => $storage[:token])
|
7
|
+
|
8
|
+
unless $storage[:frob]
|
9
|
+
system %{open "#{api.authorization_url}"}
|
10
|
+
$storage[:frob] = api.frob
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
unless $storage[:token]
|
15
|
+
$storage[:token] = api.authenticate
|
16
|
+
end
|
17
|
+
|
18
|
+
api
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/rtr/commands.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'term/ansicolor'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module RTR
|
5
|
+
class Commands
|
6
|
+
|
7
|
+
register_method :add do |options|
|
8
|
+
tags, task_name = options.partition { |o| o[0..0] == '@' }
|
9
|
+
task_name = task_name.join(' ')
|
10
|
+
|
11
|
+
task = api.tasks.new
|
12
|
+
|
13
|
+
task["name"] = task_name
|
14
|
+
task["tags"] = tags.map { |tag| tag[1..-1] }
|
15
|
+
|
16
|
+
task.save!(:parse => true)
|
17
|
+
|
18
|
+
$storage.purge_cache!
|
19
|
+
end
|
20
|
+
|
21
|
+
register_method :tasks do |options|
|
22
|
+
|
23
|
+
puts "Oustanding Tasks".white.bold
|
24
|
+
puts
|
25
|
+
|
26
|
+
tasks = $storage[:tasks] || api.default_list.tasks
|
27
|
+
|
28
|
+
tasks.sorted_by('next/due').reverse.each do |task|
|
29
|
+
|
30
|
+
now = DateTime.now
|
31
|
+
|
32
|
+
due = task['next/due']
|
33
|
+
due = due.to_date unless due.blank?
|
34
|
+
|
35
|
+
diff = due.blank? ? nil : due - now
|
36
|
+
|
37
|
+
color = case
|
38
|
+
when diff.nil? then :white
|
39
|
+
when diff.abs < 1 && due.day == now.day then :yellow
|
40
|
+
when diff < 0 then :red
|
41
|
+
else :white
|
42
|
+
end
|
43
|
+
|
44
|
+
title = task.name
|
45
|
+
title = title.send(color).bold if color
|
46
|
+
|
47
|
+
prefix = " *"
|
48
|
+
prefix = prefix.send(color).bold if color
|
49
|
+
|
50
|
+
suffix = task.tags.map { |t| "@#{t.name}" }.join(' ').cyan
|
51
|
+
|
52
|
+
puts "#{prefix} #{title} #{suffix}"
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
$storage[:tasks] = tasks
|
57
|
+
$storage.set_cache_timeout(:tasks, 30.minutes)
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
register_method :purge do |options|
|
62
|
+
$storage.purge_cache!
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
data/lib/rtr.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Equivalent to a header guard in C/C++
|
2
|
+
# Used to prevent the class/module from being loaded more than once
|
3
|
+
unless defined? RTR
|
4
|
+
|
5
|
+
module RTR
|
6
|
+
|
7
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
8
|
+
# directory below this file that has the same name as the filename passed
|
9
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
10
|
+
# the _filename_ does not have to be equivalent to the directory.
|
11
|
+
#
|
12
|
+
def self.require_all_libs_relative_to(fname)
|
13
|
+
search_me = File.expand_path(File.join(File.dirname(fname), '**', '*.rb'))
|
14
|
+
Dir.glob(search_me).sort.each { |rb| require rb }
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
RTR.require_all_libs_relative_to __FILE__
|
20
|
+
|
21
|
+
end # unless defined?
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remember-the-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Dollar
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-30 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ddollar-preferences
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.1.3
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: term-ansicolor
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.3
|
34
|
+
version:
|
35
|
+
description:
|
36
|
+
email: ddollar@gmail.com
|
37
|
+
executables:
|
38
|
+
- rtr
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README
|
43
|
+
files:
|
44
|
+
- bin/rtr
|
45
|
+
- lib/core_ext/datetime.rb
|
46
|
+
- lib/core_ext/enumerable.rb
|
47
|
+
- lib/core_ext/fixnum.rb
|
48
|
+
- lib/core_ext/nil.rb
|
49
|
+
- lib/core_ext/string.rb
|
50
|
+
- lib/remember-the-ruby/api.rb
|
51
|
+
- lib/remember-the-ruby/contact.rb
|
52
|
+
- lib/remember-the-ruby/entity.rb
|
53
|
+
- lib/remember-the-ruby/entity_list.rb
|
54
|
+
- lib/remember-the-ruby/group.rb
|
55
|
+
- lib/remember-the-ruby/list.rb
|
56
|
+
- lib/remember-the-ruby/location.rb
|
57
|
+
- lib/remember-the-ruby/note.rb
|
58
|
+
- lib/remember-the-ruby/rpc.rb
|
59
|
+
- lib/remember-the-ruby/storage.rb
|
60
|
+
- lib/remember-the-ruby/tag.rb
|
61
|
+
- lib/remember-the-ruby/task.rb
|
62
|
+
- lib/remember-the-ruby/task_occurrence.rb
|
63
|
+
- lib/remember-the-ruby.rb
|
64
|
+
- lib/rtr/api.rb
|
65
|
+
- lib/rtr/command_helper.rb
|
66
|
+
- lib/rtr/commands.rb
|
67
|
+
- lib/rtr.rb
|
68
|
+
- README
|
69
|
+
has_rdoc: true
|
70
|
+
homepage: http://peervoice.com/software/remember-the-ruby
|
71
|
+
licenses: []
|
72
|
+
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
version:
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project: remember-the-ruby
|
93
|
+
rubygems_version: 1.3.5
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: A Ruby interface to Remember the Milk
|
97
|
+
test_files: []
|
98
|
+
|