ardekantur-taskomaly 0.0.8
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/LICENSE +8 -0
- data/README.rdoc +54 -0
- data/Rakefile +73 -0
- data/lib/api.rb +125 -0
- data/lib/paper.rb +52 -0
- data/lib/project.rb +19 -0
- data/lib/task.rb +80 -0
- data/lib/taskomaly.rb +1 -0
- metadata +61 -0
data/LICENSE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
taskomaly: access tasko and taskpaper files in ruby
|
2
|
+
Copyright (C) 2008 Ardekantur
|
3
|
+
|
4
|
+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
5
|
+
|
6
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
7
|
+
|
8
|
+
Please see <http://www.gnu.org/licenses/> for the full version of this license.
|
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= taskomaly
|
2
|
+
|
3
|
+
access your Tasko or TaskPaper papers. in ruby.
|
4
|
+
|
5
|
+
== you need to clean your room
|
6
|
+
|
7
|
+
=== make it a project
|
8
|
+
|
9
|
+
proj = Taskomaly::Project.new 'Room Cleaning'
|
10
|
+
|
11
|
+
=== add some tasks to it
|
12
|
+
|
13
|
+
proj.add 'put away clean laundry'
|
14
|
+
proj.add 'wash dirty dishes'
|
15
|
+
|
16
|
+
=== tag those suckas up
|
17
|
+
|
18
|
+
proj.add 'file taxes @april @15'
|
19
|
+
proj.tasks.last.tags # [:april, :"15"]
|
20
|
+
|
21
|
+
proj.add 'organize shelf'
|
22
|
+
proj.tasks.last.tag :knickknacks, 1000, 'september'
|
23
|
+
proj.tasks.last.tags # [:knickknacks, :"1000", :september]
|
24
|
+
|
25
|
+
== working with tasko
|
26
|
+
|
27
|
+
t = Taskomaly::With :user => 9999, :key => 'd9cca721a735dac4efe709e0f3518373'
|
28
|
+
|
29
|
+
or, create this file:
|
30
|
+
|
31
|
+
# ~/.tasks.yml
|
32
|
+
user: 9999
|
33
|
+
key: d9cca721a735dac4efe709e0f3518373
|
34
|
+
|
35
|
+
and do this:
|
36
|
+
|
37
|
+
t = Taskomaly::From '~/.tasks.yml'
|
38
|
+
|
39
|
+
=== getting your papers
|
40
|
+
|
41
|
+
t.get :papers # ['Paper One', 'Paper Two']
|
42
|
+
p = t.papers.first
|
43
|
+
|
44
|
+
puts p.name # 'Paper One'
|
45
|
+
puts p.body # duh
|
46
|
+
|
47
|
+
=== change + upload
|
48
|
+
|
49
|
+
p.body["@today"] = "@tomorrow"
|
50
|
+
p.save # true if groovy, false if failed
|
51
|
+
|
52
|
+
=== made a mistake? refresh from the server
|
53
|
+
|
54
|
+
p.refresh # true if groovy, false if failed
|
data/Rakefile
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'hanna/rdoctask'
|
3
|
+
require 'spec/rake/spectask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rubygems/specification'
|
6
|
+
require 'date'
|
7
|
+
|
8
|
+
GEM = "taskomaly"
|
9
|
+
GEM_VERSION = "0.0.8"
|
10
|
+
AUTHOR = "Ardekantur"
|
11
|
+
EMAIL = "greystone@ardekantur.com"
|
12
|
+
HOMEPAGE = "http://github.com/ardekantur/taskomaly"
|
13
|
+
SUMMARY = "use taskpaper papers and tasko in ruby"
|
14
|
+
|
15
|
+
spec = Gem::Specification.new do |s|
|
16
|
+
s.name = GEM
|
17
|
+
s.version = GEM_VERSION
|
18
|
+
s.platform = Gem::Platform::RUBY
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.extra_rdoc_files = ["README.rdoc", "LICENSE"]
|
21
|
+
s.summary = SUMMARY
|
22
|
+
s.description = s.summary
|
23
|
+
s.author = AUTHOR
|
24
|
+
s.email = EMAIL
|
25
|
+
s.homepage = HOMEPAGE
|
26
|
+
|
27
|
+
# Uncomment this to add a dependency
|
28
|
+
# s.add_dependency "foo"
|
29
|
+
|
30
|
+
s.require_path = 'lib'
|
31
|
+
s.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("{lib,specs}/**/*")
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
35
|
+
pkg.gem_spec = spec
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "install the gem locally"
|
39
|
+
task :install => [:package] do
|
40
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "create a gemspec file"
|
44
|
+
task :make_spec do
|
45
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
46
|
+
file.puts spec.to_ruby
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Run all specs"
|
51
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
52
|
+
t.spec_files = FileList['spec/*.rb']
|
53
|
+
t.spec_opts = ['--color']
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "generate rdoc documentation"
|
57
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
58
|
+
rdoc.rdoc_files.include('README.rdoc', 'LICENSE' ).
|
59
|
+
include('lib/**/*.rb')
|
60
|
+
|
61
|
+
rdoc.main = "README.rdoc"
|
62
|
+
rdoc.rdoc_dir = 'doc' # rdoc output folder
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "run rspec + rcov"
|
66
|
+
Spec::Rake::SpecTask.new("spec:rcov") do |t|
|
67
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
68
|
+
t.rcov_opts = ['--exclude', "spec/,rcov.rb,rspec.rb,spec*,gems*"]
|
69
|
+
t.rcov = true
|
70
|
+
t.rcov_dir = 'doc/coverage'
|
71
|
+
end
|
72
|
+
|
73
|
+
task :default => :spec
|
data/lib/api.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
module Taskomaly
|
6
|
+
|
7
|
+
def self.From file
|
8
|
+
return API.new(:config => file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.With hash
|
12
|
+
return API.new(hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
class API
|
16
|
+
|
17
|
+
SERVICE = 'http://taskodone.com/api'
|
18
|
+
SUPPORTED_ACTIONS = [ :papers, :paper, :rename, :edit, :new, :delete ]
|
19
|
+
|
20
|
+
attr_reader :response
|
21
|
+
attr_reader :papers
|
22
|
+
|
23
|
+
# Creates an instance of the API processor with +hash+ passed a set of configuration
|
24
|
+
# options in a hash. +hash+ should either be a Tasko user ID and API key (in this case
|
25
|
+
# +:user+ and +:key+), or a file where those keys are located in YAML format (in this case
|
26
|
+
# +:config+).
|
27
|
+
def initialize hash
|
28
|
+
@config = {}
|
29
|
+
|
30
|
+
raise ArgumentError,
|
31
|
+
'please specify either :user and :key or :config' unless (hash.has_key? :user and hash.has_key? :key) or (hash.has_key? :config)
|
32
|
+
|
33
|
+
@config['user'] = hash[:user] if hash.has_key? :user
|
34
|
+
@config['key'] = hash[:key] if hash.has_key? :key
|
35
|
+
|
36
|
+
if hash.has_key? :config
|
37
|
+
begin
|
38
|
+
@config = parse_config(File.expand_path(hash[:config]))
|
39
|
+
rescue
|
40
|
+
raise ArgumentError, "unable to load from file #{hash[:config]}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
# The user ID specified in the API configuration.
|
47
|
+
def user; @config['user']; end
|
48
|
+
|
49
|
+
# The API key specified in the API configuration.
|
50
|
+
def key; @config['key']; end
|
51
|
+
|
52
|
+
# Request something from the server. See SUPPORTED_ACTIONS for what is possible to retrieve
|
53
|
+
# and send. A brief summary follows:
|
54
|
+
#
|
55
|
+
# <tt>api.request :papers</tt>:: retrieve a list of all papers the user has saved to Tasko.
|
56
|
+
# <tt>api.request :paper, 'Paper Name'</tt>:: return the single paper with the name passed to +request+.
|
57
|
+
# <tt>api.request :rename, 'Old Paper Name', 'New Paper Name'</tt>:: rename one of the papers in the account.
|
58
|
+
# <tt>api.request :edit, 'Paper Name', 'Paper Body'</tt>:: save a new version of the document to Tasko.
|
59
|
+
def request type, *args
|
60
|
+
raise ArgumentError, "invalid send request type #{type}" unless SUPPORTED_ACTIONS.include? type
|
61
|
+
|
62
|
+
begin
|
63
|
+
@req = request_generator
|
64
|
+
@response = @req.send :post, (base_payload type, *args)
|
65
|
+
rescue SocketError
|
66
|
+
raise 'the site appears to be unavailable'
|
67
|
+
rescue
|
68
|
+
raise 'there was an error processing your request'
|
69
|
+
end
|
70
|
+
|
71
|
+
return handle_response(type, *args)
|
72
|
+
end
|
73
|
+
|
74
|
+
alias :get :request
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def handle_response type, *args
|
79
|
+
doc = REXML::Document.new @response
|
80
|
+
case type
|
81
|
+
when :papers
|
82
|
+
@papers = doc.elements.to_a('//string').map { |m| m.text }
|
83
|
+
return @papers
|
84
|
+
when :paper
|
85
|
+
@data = doc.elements.to_a('//string').map { |m| m.text }
|
86
|
+
return Taskomaly::Paper.new( args.first, @data.last, self )
|
87
|
+
when :edit
|
88
|
+
@data = doc.elements.to_a('//string').map { |m| m.text }
|
89
|
+
return true if @data.size > 0
|
90
|
+
end
|
91
|
+
|
92
|
+
return false
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def request_generator
|
97
|
+
RestClient::Resource.new SERVICE
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse_config config_filepath
|
101
|
+
YAML::load_file config_filepath
|
102
|
+
end
|
103
|
+
|
104
|
+
def base_payload method_name, *args
|
105
|
+
params = ''
|
106
|
+
extra_data = ([] << args).flatten.compact
|
107
|
+
if extra_data
|
108
|
+
extra_data.each do |data|
|
109
|
+
type = (data.class == Fixnum) ? 'integer' : 'string'
|
110
|
+
params += "<param><value><#{type}>#{data}</#{type}></value></param>\n"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
<<-XML
|
114
|
+
<methodCall><methodName>#{method_name}</methodName>
|
115
|
+
<params>
|
116
|
+
<param><value><int>#{user}</int></value></param>
|
117
|
+
<param><value><string>#{key}</string></value></param>
|
118
|
+
#{params}
|
119
|
+
</params></methodCall>
|
120
|
+
XML
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
data/lib/paper.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Taskomaly
|
2
|
+
|
3
|
+
class Paper
|
4
|
+
|
5
|
+
attr_accessor :name, :body
|
6
|
+
|
7
|
+
def self.From file
|
8
|
+
raise ArgumentError, "file #{file} does not exist" unless File.exist? file
|
9
|
+
return Paper.new(
|
10
|
+
file.gsub(/\.\w+$/, '').gsub(/^.*\//, '').gsub(/[-_]/, ' ').split(' ').each{|word| word.capitalize! }.join(' '),
|
11
|
+
File.open(file, "r").readlines.join
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize name, body = "", api = nil
|
16
|
+
@name = name
|
17
|
+
@body = body
|
18
|
+
@api = api
|
19
|
+
parse_body
|
20
|
+
end
|
21
|
+
|
22
|
+
def api
|
23
|
+
return @api
|
24
|
+
end
|
25
|
+
|
26
|
+
def save
|
27
|
+
return false unless @api
|
28
|
+
return @api.request(:edit, @name, @body)
|
29
|
+
end
|
30
|
+
|
31
|
+
def refresh
|
32
|
+
return false unless @api
|
33
|
+
@body = (@api.request :paper, @name).body
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
|
37
|
+
def projects
|
38
|
+
@projects
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_body
|
44
|
+
@projects = []
|
45
|
+
@body.split("\n").each do |line|
|
46
|
+
@projects << line.gsub(/:\s*$/, '').gsub(/ /, '_').downcase.to_sym if line =~ /^.*:\s*$/
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/project.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Taskomaly
|
2
|
+
|
3
|
+
class Project
|
4
|
+
|
5
|
+
attr_accessor :name, :tasks
|
6
|
+
|
7
|
+
def initialize name
|
8
|
+
@name = name
|
9
|
+
@tasks = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add task
|
13
|
+
@tasks << Task.new(task) if task.class == String
|
14
|
+
@tasks << task if task.class == Taskomaly::Task
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/lib/task.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Taskomaly
|
2
|
+
|
3
|
+
TAG_REGEX = /\@\w+/
|
4
|
+
|
5
|
+
def self.Do task
|
6
|
+
return Task.new(task)
|
7
|
+
end
|
8
|
+
|
9
|
+
class Task
|
10
|
+
|
11
|
+
attr_accessor :desc, :tags
|
12
|
+
|
13
|
+
def initialize description
|
14
|
+
@desc, @tags = parse(description)
|
15
|
+
@delimiter = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# Tag a task. Duplicate tags are ignored.
|
19
|
+
#
|
20
|
+
# t = Taskomaly::Do 'wash the dishes'
|
21
|
+
# t.tag :kitchen
|
22
|
+
# puts t.tags # [:kitchen]
|
23
|
+
# t.tag :sink, :july, 4
|
24
|
+
# puts t.tags # [:kitchen, :sink, :july, :"4"]
|
25
|
+
#
|
26
|
+
def tag *args
|
27
|
+
@tags = [] unless @tags
|
28
|
+
@tags = (@tags + args.map { |tag| tag.to_s.to_sym } ).uniq
|
29
|
+
end
|
30
|
+
|
31
|
+
# Remove tags from a task.
|
32
|
+
#
|
33
|
+
# t = Taskomaly::Do 'wash the dishes @kitchen'
|
34
|
+
# t.untag :kitchen
|
35
|
+
# puts t.display # "wash the dishes"
|
36
|
+
def untag *args
|
37
|
+
return unless @tags
|
38
|
+
@tags = (@tags - args)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Display the task, with tags appended to the end.
|
42
|
+
#
|
43
|
+
# t = Taskomaly::Do 'wash the dishes'
|
44
|
+
# t.tag :kitchen
|
45
|
+
# puts t.display # "wash the dishes @kitchen"
|
46
|
+
def display
|
47
|
+
"#{@desc} #{@tags.collect { |tag| '@' + tag.to_s }.join(@delimiter || ' ')}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Change how listing tags are delimited. +delimiter+ is a string, like <tt>','</tt>,
|
51
|
+
# that will be used to join tags. +symmetric_spacing+ is a boolean value
|
52
|
+
# that determines whether or not the delimiter should be separated by tags
|
53
|
+
# on both sides, or just the right side.
|
54
|
+
# Some examples:
|
55
|
+
#
|
56
|
+
# t = Taskomaly::Do 'wash the dishes @dishes @sink @other'
|
57
|
+
# t.display # 'wash the dishes @dishes @sink @other'
|
58
|
+
#
|
59
|
+
# t.delimit_with ','
|
60
|
+
# t.display # 'wash the dishes @dishes, @sink, @other'
|
61
|
+
#
|
62
|
+
# t.delimit_with '/'
|
63
|
+
# t.display # 'wash the dishes @dishes/ @sink/ @other'
|
64
|
+
# t.delimit_with '/', true
|
65
|
+
# t.display # 'wash the dishes @dishes / @sink / @other'
|
66
|
+
#
|
67
|
+
def delimit_with delimiter, symmetric_spacing = false
|
68
|
+
@delimiter = (symmetric_spacing ? ' ' : '') + delimiter + ' '
|
69
|
+
return true
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def parse description
|
75
|
+
return description.gsub(TAG_REGEX, '').strip.squeeze(' '), description.scan(TAG_REGEX).map { |tag| tag.to_s.gsub(/^\@/, '').to_sym }.uniq
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/lib/taskomaly.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
%w/ api paper project task /.each { |x| require x }
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ardekantur-taskomaly
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ardekantur
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-16 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: use taskpaper papers and tasko in ruby
|
17
|
+
email: greystone@ardekantur.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
- LICENSE
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- lib/api.rb
|
30
|
+
- lib/paper.rb
|
31
|
+
- lib/project.rb
|
32
|
+
- lib/task.rb
|
33
|
+
- lib/taskomaly.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: http://github.com/ardekantur/taskomaly
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
version:
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
requirements: []
|
54
|
+
|
55
|
+
rubyforge_project:
|
56
|
+
rubygems_version: 1.2.0
|
57
|
+
signing_key:
|
58
|
+
specification_version: 2
|
59
|
+
summary: use taskpaper papers and tasko in ruby
|
60
|
+
test_files: []
|
61
|
+
|