rtasklib 0.1.4 → 0.1.5
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.travis.yml +2 -0
- data/README.md +12 -1
- data/Rakefile +9 -4
- data/lib/rtasklib.rb +12 -10
- data/lib/rtasklib/controller.rb +116 -49
- data/lib/rtasklib/execute.rb +47 -37
- data/lib/rtasklib/helpers.rb +205 -0
- data/lib/rtasklib/models.rb +24 -11
- data/lib/rtasklib/taskrc.rb +4 -28
- data/lib/rtasklib/version.rb +1 -1
- data/spec/controller_spec.rb +49 -3
- data/spec/data/.task/backlog.data +3 -0
- data/spec/data/.task/pending.data +2 -0
- data/spec/data/.task/undo.data +10 -0
- data/spec/helpers_spec.rb +76 -0
- data/spec/rtasklib_spec.rb +4 -4
- metadata +5 -5
- data/lib/rtasklib/serializer.rb +0 -10
- data/spec/serializer_spec.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dd45dd292c87269556e732b902f18cf38a098eb
|
4
|
+
data.tar.gz: a8adeee47b89eb6cadc2a5cf79e4825711f4e181
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2ad056508be0fabd7365c5431abe144220283ea6ba7beb77718d807f1549307876f1cde5708342339a50b3c4e6fa9b0ce4d9781b52c670020d55397850d5678
|
7
|
+
data.tar.gz: 8afd466375b305d8ed56fe5e98b66328391063c864db40637a02ecb9f65b58bfc4b6f49542977a739a7f44ccd394744deb9e0d5a7fe7bd2e3ff7b028eb2459c1
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -25,6 +25,8 @@ before_install:
|
|
25
25
|
- export TASKRC=/home/travis/build/dropofwill/rtasklib/spec/data/.taskrc
|
26
26
|
- export TASKDATA=/home/travis/build/dropofwill/rtasklib/spec/data/.task
|
27
27
|
- task _version
|
28
|
+
- task export
|
29
|
+
- task add "Test task persistence"
|
28
30
|
|
29
31
|
script: 'bundle exec rake'
|
30
32
|
|
data/README.md
CHANGED
@@ -36,7 +36,18 @@ Or install it yourself as:
|
|
36
36
|
|
37
37
|
## Usage
|
38
38
|
|
39
|
-
|
39
|
+
```
|
40
|
+
require 'rtasklib'
|
41
|
+
|
42
|
+
tw = Rtasklib::TW.new('../path/to/.task')
|
43
|
+
|
44
|
+
# do some stuff with the task database
|
45
|
+
# available commands are documented in the Controller class
|
46
|
+
|
47
|
+
tw.all
|
48
|
+
```
|
49
|
+
|
50
|
+
[Controller docs](http://will-paul.com/rtasklib/Rtasklib/Controller.html)
|
40
51
|
|
41
52
|
|
42
53
|
## Development
|
data/Rakefile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
|
+
require "open3"
|
4
|
+
require "pp"
|
3
5
|
|
4
6
|
# run tests with `rake spec`
|
5
7
|
RSpec::Core::RakeTask.new :spec do |task|
|
@@ -10,9 +12,12 @@ task default: :spec
|
|
10
12
|
|
11
13
|
desc "Update and publish docs to gh-pages"
|
12
14
|
task :docs do |task|
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
o, s = Open3.capture2("yard doc")
|
16
|
+
o.split("\n").each { |line| p line }
|
17
|
+
p ""
|
16
18
|
|
17
|
-
|
19
|
+
Open3.capture2("ghp-import -p doc")
|
18
20
|
end
|
21
|
+
|
22
|
+
# task :build_rpm do
|
23
|
+
# end
|
data/lib/rtasklib.rb
CHANGED
@@ -2,15 +2,15 @@ require_relative "rtasklib/version"
|
|
2
2
|
require_relative "rtasklib/models"
|
3
3
|
require_relative "rtasklib/execute"
|
4
4
|
require_relative "rtasklib/controller"
|
5
|
+
require_relative "rtasklib/helpers"
|
5
6
|
require_relative "rtasklib/taskrc"
|
6
7
|
|
7
|
-
require "open3"
|
8
8
|
require "pathname"
|
9
9
|
|
10
10
|
module Rtasklib
|
11
11
|
|
12
12
|
class TaskWarrior
|
13
|
-
attr_reader :version, :data_location, :taskrc,
|
13
|
+
attr_reader :version, :data_location, :taskrc, :udas,
|
14
14
|
:override, :override_a, :override_str
|
15
15
|
|
16
16
|
include Controller
|
@@ -25,22 +25,24 @@ module Rtasklib
|
|
25
25
|
LOWEST_VERSION = Gem::Version.new('2.4.0')
|
26
26
|
|
27
27
|
def initialize data="#{Dir.home}/.task", opts = {}
|
28
|
+
# Check TaskWarrior version, and throw warning if unavailable
|
29
|
+
begin
|
30
|
+
@version = check_version
|
31
|
+
rescue
|
32
|
+
warn "Couldn't verify TaskWarrior's version"
|
33
|
+
end
|
28
34
|
|
29
35
|
@data_location = data
|
30
36
|
override_h = DEFAULTS.merge({data_location: data}).merge(opts)
|
31
37
|
@override = Taskrc.new(override_h, :hash)
|
32
38
|
@override_a = override.model_to_rc
|
33
39
|
@taskrc = get_rc
|
34
|
-
|
35
|
-
|
36
|
-
begin
|
37
|
-
@version = check_version(get_version())
|
38
|
-
rescue
|
39
|
-
warn "Couldn't verify TaskWarrior's version"
|
40
|
-
end
|
40
|
+
@udas = get_udas
|
41
|
+
add_udas_to_model!(udas) unless udas.nil?
|
41
42
|
end
|
42
43
|
|
43
|
-
def check_version version
|
44
|
+
def check_version version=nil
|
45
|
+
version = get_version if version.nil?
|
44
46
|
if version < LOWEST_VERSION
|
45
47
|
warn "The current TaskWarrior version, #{version}, is untested"
|
46
48
|
end
|
data/lib/rtasklib/controller.rb
CHANGED
@@ -3,6 +3,15 @@ require "oj"
|
|
3
3
|
|
4
4
|
module Rtasklib
|
5
5
|
|
6
|
+
# Accessed through the main TW, which includes this module, e.g. `tw.all`
|
7
|
+
#
|
8
|
+
# Ideally should only be the well documented public, user-facing methods.
|
9
|
+
# We're getting there.
|
10
|
+
#
|
11
|
+
# By convention bang methods modify the task database, and non-bang read
|
12
|
+
# from the database, e.g. `Controller#all` vs `Controller#modify!`
|
13
|
+
#
|
14
|
+
# XXX: depends on @override_a currently, which isn't great.
|
6
15
|
module Controller
|
7
16
|
extend self
|
8
17
|
|
@@ -12,65 +21,115 @@ module Rtasklib
|
|
12
21
|
# @api public
|
13
22
|
def all
|
14
23
|
all = []
|
15
|
-
Execute.task_popen3(
|
24
|
+
Execute.task_popen3(*override_a, "export") do |i, o, e, t|
|
16
25
|
all = MultiJson.load(o.read).map do |x|
|
17
26
|
Rtasklib::Models::TaskModel.new(x)
|
18
27
|
end
|
19
28
|
end
|
20
|
-
all
|
29
|
+
return all
|
21
30
|
end
|
22
31
|
|
23
|
-
|
32
|
+
# Retrieves the current task list filtered by id, tag, or a dom query
|
33
|
+
#
|
34
|
+
# @example filter by an array of ids
|
35
|
+
# tw.some(ids: [1..2, 5])
|
36
|
+
# @example filter by tags
|
37
|
+
# tw.some(tags: ["+school", "or", "-work"]
|
38
|
+
#
|
39
|
+
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
40
|
+
# @param tags [Array<String>, String]
|
41
|
+
# @param dom [Array<String>, String]
|
42
|
+
# @return [Array<Models::TaskModel>]
|
43
|
+
# @api public
|
44
|
+
def some ids: nil, tags: nil, dom: nil
|
45
|
+
some = []
|
46
|
+
filter_s = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
47
|
+
Execute.task_popen3(*@override_a, filter_s, "export") do |i, o, e, t|
|
48
|
+
some = MultiJson.load(o.read).map do |x|
|
49
|
+
Rtasklib::Models::TaskModel.new(x)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
return some
|
24
53
|
end
|
25
54
|
|
26
|
-
|
55
|
+
#
|
56
|
+
#
|
57
|
+
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
58
|
+
# @param tags [Array<String>, String]
|
59
|
+
# @param dom [Array<String>, String]
|
60
|
+
# @api public
|
61
|
+
def add! description
|
27
62
|
end
|
28
63
|
|
29
|
-
#
|
30
|
-
#
|
64
|
+
#
|
65
|
+
#
|
66
|
+
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
67
|
+
# @param tags [Array<String>, String]
|
68
|
+
# @param dom [Array<String>, String]
|
69
|
+
# @api public
|
70
|
+
def modify! attr:, val:, ids: nil, tags: nil, dom: nil
|
71
|
+
f = filter(ids, tags, dom)
|
72
|
+
query = "#{f} modify #{attr} #{val}"
|
73
|
+
Execute.task_popen3(*override_a, query) do |i, o, e, t|
|
74
|
+
return t.value
|
75
|
+
end
|
76
|
+
end
|
31
77
|
|
78
|
+
# Directly call `task undo`, which only applies to edits to the task db
|
79
|
+
# not configuration changes
|
80
|
+
#
|
81
|
+
# @api public
|
32
82
|
def undo!
|
83
|
+
Execute.task_popen3(*override_a, "undo") do |i, o, e, t|
|
84
|
+
return t.value
|
85
|
+
end
|
33
86
|
end
|
34
87
|
|
88
|
+
# Update a configuration variable in the .taskrc
|
89
|
+
#
|
90
|
+
# @param attr [String]
|
91
|
+
# @param val [String]
|
92
|
+
# @api public
|
35
93
|
def update_config! attr, val
|
36
94
|
Execute.task_popen3(*override_a, "config #{attr} #{val}") do |i, o, e, t|
|
37
95
|
return t.value
|
38
96
|
end
|
39
97
|
end
|
40
98
|
|
41
|
-
# Retrieves
|
99
|
+
# Retrieves a hash of hashes with info about the UDAs currently available
|
100
|
+
#
|
101
|
+
# @return [Hash{Symbol=>Hash}]
|
102
|
+
# @api public
|
42
103
|
def get_udas
|
104
|
+
udas = {}
|
43
105
|
taskrc.config.attributes
|
44
|
-
.select { |attr, val| uda_attr? attr }
|
106
|
+
.select { |attr, val| Helpers.uda_attr? attr }
|
45
107
|
.sort
|
46
|
-
.chunk { |attr, val| arbitrary_attr attr }
|
47
|
-
.
|
108
|
+
.chunk { |attr, val| Helpers.arbitrary_attr attr }
|
109
|
+
.each do |attr, arr|
|
48
110
|
uda = arr.map do |pair|
|
49
|
-
|
50
|
-
val = pair[1]
|
51
|
-
[key, val]
|
111
|
+
[Helpers.deep_attr(pair[0]), pair[1]]
|
52
112
|
end
|
53
|
-
|
113
|
+
udas[attr.to_sym] = Hash[uda]
|
54
114
|
end
|
115
|
+
return udas
|
55
116
|
end
|
56
117
|
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
attr.to_s.split("_")[depth..-1].join("_")
|
118
|
+
# Add new found udas to our internal TaskModel
|
119
|
+
#
|
120
|
+
# @param uda_hash [Hash{Symbol=>Hash}]
|
121
|
+
# @param type [Class, nil]
|
122
|
+
# @param model [Models::TaskModel, Class]
|
123
|
+
# @api protected
|
124
|
+
def add_udas_to_model! uda_hash, type=nil, model=Models::TaskModel
|
125
|
+
uda_hash.each do |attr, val|
|
126
|
+
val.each do |k, v|
|
127
|
+
type = Helpers.determine_type(v) if type.nil?
|
128
|
+
model.attribute attr, type
|
129
|
+
end
|
130
|
+
end
|
71
131
|
end
|
72
|
-
|
73
|
-
|
132
|
+
protected :add_udas_to_model!
|
74
133
|
|
75
134
|
# Retrieve an array of the uda names
|
76
135
|
#
|
@@ -95,18 +154,32 @@ module Rtasklib
|
|
95
154
|
end
|
96
155
|
end
|
97
156
|
|
98
|
-
|
157
|
+
# Add a UDA to the users config/database
|
158
|
+
#
|
159
|
+
# @param name [String]
|
160
|
+
# @param type [String]
|
161
|
+
# @param label [String]
|
162
|
+
# @param values [String]
|
163
|
+
# @param default [String]
|
164
|
+
# @param urgency [String]
|
165
|
+
# @return [Boolean] success
|
166
|
+
# @api public
|
167
|
+
def create_uda! name, type: "string", label: nil, values: nil,
|
99
168
|
default: nil, urgency: nil
|
100
169
|
label = name if label.nil?
|
101
|
-
p name, label, values, default, urgency
|
102
170
|
|
103
|
-
update_config
|
104
|
-
update_config
|
105
|
-
update_config
|
106
|
-
update_config
|
107
|
-
update_config
|
171
|
+
update_config("uda.#{name}.type", type)
|
172
|
+
update_config("uda.#{name}.label", label)
|
173
|
+
update_config("uda.#{name}.values", values) unless values.nil?
|
174
|
+
update_config("uda.#{name}.default", default) unless default.nil?
|
175
|
+
update_config("uda.#{name}.urgency", urgency) unless urgency.nil?
|
108
176
|
end
|
109
177
|
|
178
|
+
# Calls `task _show` with initial overrides returns a Taskrc object of the
|
179
|
+
# result
|
180
|
+
#
|
181
|
+
# @return [Taskrc]
|
182
|
+
# @api public
|
110
183
|
def get_rc
|
111
184
|
res = []
|
112
185
|
Execute.task_popen3(*@override_a, "_show") do |i, o, e, t|
|
@@ -115,22 +188,16 @@ module Rtasklib
|
|
115
188
|
Taskrc.new(res, :array)
|
116
189
|
end
|
117
190
|
|
191
|
+
# Calls `task _version` and returns the result
|
192
|
+
#
|
193
|
+
# @return [String]
|
194
|
+
# @api public
|
118
195
|
def get_version
|
119
196
|
version = nil
|
120
|
-
Execute.task_popen3(
|
121
|
-
version = to_gem_version(o.read.chomp)
|
197
|
+
Execute.task_popen3("_version") do |i, o, e, t|
|
198
|
+
version = Helpers.to_gem_version(o.read.chomp)
|
122
199
|
end
|
123
200
|
version
|
124
201
|
end
|
125
|
-
|
126
|
-
# Converts a string of format "1.6.2 (adf342jsd)" to Gem::Version object
|
127
|
-
#
|
128
|
-
#
|
129
|
-
def to_gem_version raw
|
130
|
-
std_ver = raw.chomp.gsub(' ','.').delete('(').delete(')')
|
131
|
-
Gem::Version.new std_ver
|
132
|
-
end
|
133
|
-
private :to_gem_version
|
134
|
-
|
135
202
|
end
|
136
203
|
end
|
data/lib/rtasklib/execute.rb
CHANGED
@@ -12,12 +12,23 @@ module Rtasklib
|
|
12
12
|
so \s taskwarrior \s can \s proceed\? \s
|
13
13
|
\(yes/no\)}x }
|
14
14
|
|
15
|
-
#
|
15
|
+
# Use Open3#popen3 to execute a unix program with an array of options
|
16
|
+
# and an optional block to handle the response.
|
16
17
|
#
|
18
|
+
# @example
|
19
|
+
# Execute.popen3("task", "export") do |i, o, e, t|
|
20
|
+
# # Arbitrary code to handle the response...
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# @param program [String]
|
24
|
+
# @param opts [Array<String>] args to pass directly to the program
|
25
|
+
# @param block [Block] to execute after thread is successful
|
26
|
+
# @yield [i,o,e,t] STDIN, STDOUT, STDERR, and the thread to that block.
|
27
|
+
# @api public
|
17
28
|
def popen3 program='task', *opts, &block
|
18
29
|
execute = opts.unshift(program)
|
19
30
|
execute = execute.join(" ")
|
20
|
-
|
31
|
+
warn execute
|
21
32
|
|
22
33
|
Open3.popen3(execute) do |i, o, e, t|
|
23
34
|
handle_response(e, t)
|
@@ -25,10 +36,30 @@ module Rtasklib
|
|
25
36
|
end
|
26
37
|
end
|
27
38
|
|
39
|
+
# Same as Execute#popen3, only defaults to using the 'task' program for
|
40
|
+
# convenience.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Execute.task_popen3("export") do |i, o, e, t|
|
44
|
+
# # Arbitrary code to handle the response...
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# @param opts [Array<String>] args to pass directly to the program
|
48
|
+
# @param block [Block] to execute after thread is successful
|
49
|
+
# @yield [i,o,e,t] STDIN, STDOUT, STDERR, and the thread to that block.
|
50
|
+
# @api public
|
28
51
|
def task_popen3 *opts, &block
|
29
52
|
popen3('task', opts, &block)
|
30
53
|
end
|
31
54
|
|
55
|
+
# Same as Execute#popen3, but yields each line of input
|
56
|
+
#
|
57
|
+
# @param program [String]
|
58
|
+
# @param opts [Array<String>] args to pass directly to the program
|
59
|
+
# @param block [Block] to execute after thread is successful
|
60
|
+
# @yield [l,i,o,e,t] a line of STDIN, STDIN, STDOUT, STDERR,
|
61
|
+
# and the thread to that block.
|
62
|
+
# @api public
|
32
63
|
def each_popen3 program='task', *opts, &block
|
33
64
|
popen3(program, *opts) do |i, o, e, t|
|
34
65
|
o.each_line do |l|
|
@@ -37,49 +68,28 @@ module Rtasklib
|
|
37
68
|
end
|
38
69
|
end
|
39
70
|
|
71
|
+
# Same as Execute#each_popen3, but calls it with the 'task' program
|
72
|
+
#
|
73
|
+
# @param opts [Array<String>] args to pass directly to the program
|
74
|
+
# @param block [Block] to execute after thread is successful
|
75
|
+
# @yield [l,i,o,e,t] a line of STDIN, STDIN, STDOUT, STDERR,
|
76
|
+
# and the thread to that block.
|
77
|
+
# @api public
|
40
78
|
def task_each_popen3 *opts, &block
|
41
|
-
|
42
|
-
yield(i, o, e, t)
|
79
|
+
each_popen3("task", *opts) do |l, i, o, e, t|
|
80
|
+
yield(l, i, o, e, t)
|
43
81
|
end
|
44
82
|
end
|
45
83
|
|
84
|
+
# Default error handling called in every popen3 call. Only executes if
|
85
|
+
# thread had a failing exit code
|
86
|
+
#
|
87
|
+
# @raise [RuntimeError] if failing exit code
|
46
88
|
def handle_response stderr, thread
|
47
89
|
unless thread.value.success?
|
48
90
|
puts stderr.read
|
49
|
-
|
91
|
+
raise thread.inspect
|
50
92
|
end
|
51
93
|
end
|
52
|
-
|
53
|
-
# Non-greedy json object detection
|
54
|
-
# if /\{.*\}/ =~ l
|
55
|
-
# p l.chomp
|
56
|
-
# res.push(l.chomp)
|
57
|
-
# end
|
58
|
-
# def task create_new, *opts, &block
|
59
|
-
# exp_regex = @@exp_regex
|
60
|
-
# retval = 0
|
61
|
-
# res = nil
|
62
|
-
# buff = ""
|
63
|
-
#
|
64
|
-
# run("task", *opts) do |exp, procedure|
|
65
|
-
# res = procedure.any do
|
66
|
-
# puts exp
|
67
|
-
# expect exp_regex[:create_rc] do
|
68
|
-
# if create_new
|
69
|
-
# send "yes"
|
70
|
-
# else
|
71
|
-
# send "no"
|
72
|
-
# end
|
73
|
-
# end
|
74
|
-
# block.call if block_given?
|
75
|
-
# end
|
76
|
-
|
77
|
-
# Filters should be a list of values
|
78
|
-
# Ranges interpreted as ids
|
79
|
-
# 1...5 : "1-5"
|
80
|
-
# 1..5 : "1-4"
|
81
|
-
# 1 : "1"
|
82
|
-
# and joined with ","
|
83
|
-
# [1...5, 8, 9] : "1-5,8,9"
|
84
94
|
end
|
85
95
|
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require "multi_json"
|
2
|
+
require "oj"
|
3
|
+
|
4
|
+
module Rtasklib
|
5
|
+
|
6
|
+
# A collection of stateless, non-end-user facing functions available
|
7
|
+
# throughout the library
|
8
|
+
module Helpers
|
9
|
+
# make this module a stateless, singleton
|
10
|
+
extend self
|
11
|
+
|
12
|
+
# Converts ids, tags, and dom queries to a single string ready to pass
|
13
|
+
# directly to task.
|
14
|
+
#
|
15
|
+
# @param ids[Range, Array<String, Range, Fixnum>, String, Fixnum]
|
16
|
+
# @param tags[String, Array<String>]
|
17
|
+
# @param dom[String, Array<String>]
|
18
|
+
# @return [String] a string with ids tags and dom joined by a space
|
19
|
+
# @api public
|
20
|
+
def filter ids: nil, tags: nil, dom: nil
|
21
|
+
id_s = tag_s = dom_s = ""
|
22
|
+
id_s = process_ids(ids) unless ids.nil?
|
23
|
+
tag_s = process_tags(tags) unless tags.nil?
|
24
|
+
dom_s = process_dom(dom) unless dom.nil?
|
25
|
+
return "#{id_s} #{tag_s} #{dom_s}".strip
|
26
|
+
end
|
27
|
+
|
28
|
+
# Filters should be a list of values
|
29
|
+
# Ranges interpreted as ids
|
30
|
+
# 1...5 : "1,2,3,4,5"
|
31
|
+
# 1..5 : "1,2,3,4"
|
32
|
+
# 1 : "1"
|
33
|
+
# and joined with ","
|
34
|
+
# [1...5, 8, 9] : "1,2,3,4,5,8,9"
|
35
|
+
#
|
36
|
+
# @param id_a [Array<String, Range, Fixnum>]
|
37
|
+
# @return [String]
|
38
|
+
# @api public
|
39
|
+
def id_a_to_s id_a
|
40
|
+
id_a.map do |el|
|
41
|
+
proc_ids = process_ids(el)
|
42
|
+
proc_ids
|
43
|
+
end.compact.join(",")
|
44
|
+
end
|
45
|
+
|
46
|
+
# Converts arbitrary id input to a task safe string
|
47
|
+
#
|
48
|
+
# @param ids[Range, Array<String, Range, Fixnum>, String, Fixnum]
|
49
|
+
# @api public
|
50
|
+
def process_ids ids
|
51
|
+
case ids
|
52
|
+
when Range
|
53
|
+
return id_range_to_s(ids)
|
54
|
+
when Array
|
55
|
+
return id_a_to_s(ids)
|
56
|
+
when String
|
57
|
+
return ids.delete(" ")
|
58
|
+
when Fixnum
|
59
|
+
return ids
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Convert a range to a comma separated strings, e.g. 1..4 -> "1,2,3,4"
|
64
|
+
#
|
65
|
+
# @param id_range [Range]
|
66
|
+
# @return [Array<String>]
|
67
|
+
# @api public
|
68
|
+
def id_range_to_s id_range
|
69
|
+
id_range.to_a.join(",")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Convert a tag string or an array of strings to a space separated string
|
73
|
+
#
|
74
|
+
# @param tags [String, Array<String>]
|
75
|
+
# @api private
|
76
|
+
def process_tags tags
|
77
|
+
case tags
|
78
|
+
when String
|
79
|
+
tags.split(" ").map { |t| process_tag t }.join(" ")
|
80
|
+
when Array
|
81
|
+
tags.map { |t| process_tags t }.join(" ")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Ensures that a tag begins with a + or -
|
86
|
+
#
|
87
|
+
# @return [String]
|
88
|
+
# @api public
|
89
|
+
def process_tag tag
|
90
|
+
reserved_symbols = %w{+ - and or xor < <= = != >= > ( )}
|
91
|
+
|
92
|
+
# convert plain tags to plus tags
|
93
|
+
unless tag.start_with?(*reserved_symbols)
|
94
|
+
tag = "+#{tag}"
|
95
|
+
end
|
96
|
+
return tag
|
97
|
+
end
|
98
|
+
|
99
|
+
# @api private
|
100
|
+
def process_dom dom
|
101
|
+
end
|
102
|
+
|
103
|
+
# Is a given taskrc attribute dealing with udas?
|
104
|
+
#
|
105
|
+
# @api public
|
106
|
+
def uda_attr? attr
|
107
|
+
attr.to_s.start_with? "uda"
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns part of attribute at a given depth
|
111
|
+
#
|
112
|
+
# @api public
|
113
|
+
def arbitrary_attr attr, depth: 1
|
114
|
+
attr.to_s.split("_")[depth]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Returns all attribute string after given depth
|
118
|
+
#
|
119
|
+
# @api public
|
120
|
+
def deep_attr attr, depth: 2
|
121
|
+
attr.to_s.split("_")[depth..-1].join("_")
|
122
|
+
end
|
123
|
+
|
124
|
+
# Converts a string of format "1.6.2 (adf342jsd)" to Gem::Version object
|
125
|
+
#
|
126
|
+
# @param raw [String]
|
127
|
+
# @return [Gem::Version]
|
128
|
+
# @api public
|
129
|
+
def to_gem_version raw
|
130
|
+
std_ver = raw.chomp.gsub(' ','.').delete('(').delete(')')
|
131
|
+
Gem::Version.new std_ver
|
132
|
+
end
|
133
|
+
|
134
|
+
# Determine the type that a value should be coerced to
|
135
|
+
# Int needs to precede float because ints are also floats
|
136
|
+
# Doesn't detect arrays, b/c task stores these as comma separated strings
|
137
|
+
# which could just as easily be Strings....
|
138
|
+
# If nothing works it defaults to String.
|
139
|
+
# TODO: JSON parse
|
140
|
+
#
|
141
|
+
# @param value [Object] anything that needs to be coerced, probably string
|
142
|
+
# @return [Axiom::Types::Boolean, Integer, Float, String]
|
143
|
+
# @api public
|
144
|
+
def determine_type value
|
145
|
+
if boolean? value
|
146
|
+
return Axiom::Types::Boolean
|
147
|
+
elsif integer? value
|
148
|
+
return Integer
|
149
|
+
elsif float? value
|
150
|
+
return Float
|
151
|
+
elsif json? value
|
152
|
+
return MultiJson
|
153
|
+
else
|
154
|
+
return String
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Can the input be coerced to an integer without losing information?
|
159
|
+
#
|
160
|
+
# @return [Boolean] true if coercible, false if not
|
161
|
+
# @api private
|
162
|
+
def integer? value
|
163
|
+
value.to_i.to_s == value rescue false
|
164
|
+
end
|
165
|
+
private :integer?
|
166
|
+
|
167
|
+
# Can the input be coerced to a JSON object without losing information?
|
168
|
+
#
|
169
|
+
# @return [Boolean] true if coercible, false if not
|
170
|
+
# @api private
|
171
|
+
def json? value
|
172
|
+
begin
|
173
|
+
return false unless value.is_a? String
|
174
|
+
MultiJson.load(value)
|
175
|
+
true
|
176
|
+
rescue MultiJson::ParseError
|
177
|
+
false
|
178
|
+
end
|
179
|
+
end
|
180
|
+
private :json?
|
181
|
+
|
182
|
+
# Can the input be coerced to a float without losing information?
|
183
|
+
#
|
184
|
+
# @return [Boolean] true if coercible, false if not
|
185
|
+
# @api private
|
186
|
+
def float? value
|
187
|
+
begin
|
188
|
+
true if Float(value)
|
189
|
+
rescue
|
190
|
+
false
|
191
|
+
end
|
192
|
+
end
|
193
|
+
private :float?
|
194
|
+
|
195
|
+
# Can the input be coerced to a boolean without losing information?
|
196
|
+
#
|
197
|
+
# @return [Boolean] true if coercible, false if not
|
198
|
+
# @api private
|
199
|
+
def boolean? value
|
200
|
+
["on", "off", "yes", "no", "false", "true"]
|
201
|
+
.include? value.to_s.downcase rescue false
|
202
|
+
end
|
203
|
+
private :boolean?
|
204
|
+
end
|
205
|
+
end
|
data/lib/rtasklib/models.rb
CHANGED
@@ -1,22 +1,37 @@
|
|
1
1
|
require "virtus"
|
2
2
|
require "active_model"
|
3
|
+
require 'iso8601'
|
4
|
+
require 'date'
|
3
5
|
|
4
6
|
module Rtasklib::Models
|
5
|
-
ValidationError = Class.new RuntimeError
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
# A subclass of the ISO8601::Duration object that use `task calc` to parse
|
9
|
+
# string names like 'weekly', 'biannual', and '3 quarters'
|
10
|
+
#
|
11
|
+
# Modifies the #initialize method, preserving the original string duration
|
12
|
+
class TWDuration < ISO8601::Duration
|
13
|
+
attr_reader :frozen_value
|
14
|
+
|
15
|
+
def initialize input, base=nil
|
16
|
+
@frozen_value = input.dup.freeze
|
17
|
+
parsed = `task calc #{input}`.chomp
|
18
|
+
|
19
|
+
super parsed, base
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Custom coercer to change a string input into an TWDuration object
|
24
|
+
class VirtusDuration < Virtus::Attribute
|
25
|
+
def coerce(v)
|
26
|
+
if v.nil? || v.blank? then nil else TWDuration.new(v) end
|
10
27
|
end
|
11
28
|
end
|
12
29
|
|
13
30
|
RcBooleans = Virtus.model do |mod|
|
14
31
|
mod.coerce = true
|
15
32
|
mod.coercer.config.string.boolean_map = {
|
16
|
-
'
|
17
|
-
'
|
18
|
-
'on' => true,
|
19
|
-
'off' => false }
|
33
|
+
'yes' => true, 'on' => true,
|
34
|
+
'no' => false, 'off' => false }
|
20
35
|
end
|
21
36
|
|
22
37
|
class TaskrcModel
|
@@ -61,7 +76,7 @@ module Rtasklib::Models
|
|
61
76
|
attribute :wait, DateTime
|
62
77
|
|
63
78
|
# Required only for tasks that are Recurring or have Recurring Parent
|
64
|
-
attribute :recur,
|
79
|
+
attribute :recur, VirtusDuration
|
65
80
|
|
66
81
|
# Optional except for tasks with Recurring Parents
|
67
82
|
attribute :due, DateTime
|
@@ -74,8 +89,6 @@ module Rtasklib::Models
|
|
74
89
|
attribute :imask, String
|
75
90
|
attribute :modified, DateTime
|
76
91
|
|
77
|
-
# TODO: handle arbitrary UDA's
|
78
|
-
|
79
92
|
# Refactoring idea, need to understand Virtus internals a bit better
|
80
93
|
# [:mask, :imask, :modified, :status, :uuid, :entry].each do |ro_attr|
|
81
94
|
# define_method("set_#{ro_attr.to_s}") do |value|
|
data/lib/rtasklib/taskrc.rb
CHANGED
@@ -25,7 +25,7 @@ module Rtasklib
|
|
25
25
|
hash_to_model(rc)
|
26
26
|
when :path
|
27
27
|
if path_exist?(rc)
|
28
|
-
mappable_to_model(File.open(rc))
|
28
|
+
mappable_to_model(File.open(rc).readlines)
|
29
29
|
else
|
30
30
|
raise RuntimeError.new("rc path does not exist on the file system")
|
31
31
|
end
|
@@ -53,7 +53,7 @@ module Rtasklib
|
|
53
53
|
# Converts a .taskrc file path into a Hash that can be converted into a
|
54
54
|
# TaskrcModel object
|
55
55
|
#
|
56
|
-
# @param
|
56
|
+
# @param rc_file [String,Pathname] a valid pathname to a .taskrc file
|
57
57
|
# @return [Models::TaskrcModel] the instance variable config
|
58
58
|
# @api private
|
59
59
|
def mappable_to_model rc_file
|
@@ -123,7 +123,6 @@ module Rtasklib
|
|
123
123
|
|
124
124
|
# Dynamically add a Virtus attr, detect Boolean, Integer, and Float types
|
125
125
|
# based on the value, otherwise just treat it like a string.
|
126
|
-
# Int needs to precede float because ints are also floats
|
127
126
|
# Modifies the config instance variable
|
128
127
|
# TODO: May also be able to detect arrays
|
129
128
|
#
|
@@ -132,22 +131,14 @@ module Rtasklib
|
|
132
131
|
# @return [undefined]
|
133
132
|
# @api private
|
134
133
|
def add_model_attr attr, value
|
135
|
-
|
136
|
-
config.attribute attr.to_sym, Axiom::Types::Boolean
|
137
|
-
elsif integer? value
|
138
|
-
config.attribute attr.to_sym, Integer
|
139
|
-
elsif float? value
|
140
|
-
config.attribute attr.to_sym, Float
|
141
|
-
else
|
142
|
-
config.attribute attr.to_sym, String
|
143
|
-
end
|
134
|
+
config.attribute(attr.to_sym, Helpers.determine_type(value))
|
144
135
|
end
|
145
136
|
private :add_model_attr
|
146
137
|
|
147
138
|
# Modifies the value of a given attr in the config object
|
148
139
|
#
|
149
140
|
# @param attr [#to_s] the name for the attr, e.g. "json_array"
|
150
|
-
# @param
|
141
|
+
# @param value [String] the value of the attr, e.g. "yes"
|
151
142
|
# @return [undefined]
|
152
143
|
# @api public
|
153
144
|
def set_model_attr_value attr, value
|
@@ -194,20 +185,5 @@ module Rtasklib
|
|
194
185
|
end
|
195
186
|
end
|
196
187
|
private :path_exist?
|
197
|
-
|
198
|
-
def integer? value
|
199
|
-
value.to_i.to_s == value
|
200
|
-
end
|
201
|
-
private :integer?
|
202
|
-
|
203
|
-
def float? value
|
204
|
-
Float(value) rescue false
|
205
|
-
end
|
206
|
-
private :float?
|
207
|
-
|
208
|
-
def boolean? value
|
209
|
-
["on", "off", "yes", "no", "false", "true"].include? value.to_s.downcase
|
210
|
-
end
|
211
|
-
private :boolean?
|
212
188
|
end
|
213
189
|
end
|
data/lib/rtasklib/version.rb
CHANGED
data/spec/controller_spec.rb
CHANGED
@@ -3,16 +3,62 @@ require 'spec_helper'
|
|
3
3
|
describe Rtasklib::Controller do
|
4
4
|
include Rtasklib::Controller
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
.to eq
|
6
|
+
shared_examples_for 'export' do
|
7
|
+
it 'should return an Array' do
|
8
|
+
expect(subject.class).to eq Array
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should return an Array<TaskModel>' do
|
12
|
+
expect(subject.each do |t|
|
13
|
+
expect(t.class).to eq(Rtasklib::Models::TaskModel)
|
14
|
+
end)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
shared_examples_for 'export all' do
|
19
|
+
it_behaves_like 'export'
|
20
|
+
|
21
|
+
it 'should load in the correct number of task models' do
|
22
|
+
expect(subject.size).to eq(4)
|
23
|
+
end
|
9
24
|
end
|
10
25
|
|
11
26
|
describe 'Rtasklib::Controller#all' do
|
27
|
+
subject { Rtasklib::TaskWarrior.new("spec/data/.task").all }
|
28
|
+
it_behaves_like 'export all'
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'Rtasklib::Controller#some' do
|
32
|
+
|
33
|
+
describe '#some without arguments should behave like #all' do
|
34
|
+
subject { Rtasklib::TaskWarrior.new("spec/data/.task").some }
|
35
|
+
it_behaves_like 'export all'
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#some should accept filter parameters' do
|
39
|
+
subject { Rtasklib::TaskWarrior.new("spec/data/.task").some ids:[1,2] }
|
40
|
+
it_behaves_like 'export'
|
41
|
+
|
42
|
+
it 'should load in the correct number of task models' do
|
43
|
+
expect(subject.size).to eq(2)
|
44
|
+
end
|
45
|
+
end
|
12
46
|
end
|
13
47
|
|
14
48
|
describe 'Rtasklib::Controller#check_uda' do
|
15
49
|
it 'should return true if a uda is found that matches the input' do
|
16
50
|
end
|
17
51
|
end
|
52
|
+
|
53
|
+
describe 'Rtasklib::Controller#all' do
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'Rtasklib::Controller#add!' do
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'Rtasklib::Controller#modify!' do
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'Rtasklib::Controller#undo!' do
|
63
|
+
end
|
18
64
|
end
|
@@ -1,2 +1,5 @@
|
|
1
1
|
{"description":"Wash dishes","entry":"20150316T174823Z","modified":"20150316T174823Z","status":"pending","uuid":"1ecac94d-b4d6-4c02-98f7-75e4de03006b"}
|
2
2
|
{"description":"Clean room","entry":"20150316T174852Z","modified":"20150316T174852Z","status":"pending","uuid":"12d3176a-b6b1-42ab-90ad-6cd6acf8d6a1"}
|
3
|
+
{"description":"Test recur","entry":"20150512T200658Z","modified":"20150512T200658Z","status":"pending","uuid":"d203a656-f7ab-4707-8e38-abdced29acc4"}
|
4
|
+
{"description":"Test recur","due":"20160101T045959Z","entry":"20150512T200658Z","modified":"20150512T200658Z","recur":"weekly","status":"recurring","uuid":"d203a656-f7ab-4707-8e38-abdced29acc4"}
|
5
|
+
{"description":"biannual test","due":"20160101T045959Z","entry":"20150512T204148Z","modified":"20150512T204148Z","recur":"biannual","status":"recurring","uuid":"45fc918e-f106-45d8-96b6-37eaf61f2f4e"}
|
@@ -1,2 +1,4 @@
|
|
1
1
|
[description:"Wash dishes" entry:"1426528103" modified:"1426528103" status:"pending" uuid:"1ecac94d-b4d6-4c02-98f7-75e4de03006b"]
|
2
2
|
[description:"Clean room" entry:"1426528132" modified:"1426528132" status:"pending" uuid:"12d3176a-b6b1-42ab-90ad-6cd6acf8d6a1"]
|
3
|
+
[description:"Test recur" due:"1451624399" entry:"1431461218" modified:"1431461218" recur:"weekly" status:"recurring" uuid:"d203a656-f7ab-4707-8e38-abdced29acc4"]
|
4
|
+
[description:"biannual test" due:"1451624399" entry:"1431463308" modified:"1431463308" recur:"biannual" status:"recurring" uuid:"45fc918e-f106-45d8-96b6-37eaf61f2f4e"]
|
data/spec/data/.task/undo.data
CHANGED
@@ -4,3 +4,13 @@ new [description:"Wash dishes" entry:"1426528103" modified:"1426528103" status:"
|
|
4
4
|
time 1426528132
|
5
5
|
new [description:"Clean room" entry:"1426528132" modified:"1426528132" status:"pending" uuid:"12d3176a-b6b1-42ab-90ad-6cd6acf8d6a1"]
|
6
6
|
---
|
7
|
+
time 1431461218
|
8
|
+
new [description:"Test recur" entry:"1431461218" modified:"1431461218" status:"pending" uuid:"d203a656-f7ab-4707-8e38-abdced29acc4"]
|
9
|
+
---
|
10
|
+
time 1431461251
|
11
|
+
old [description:"Test recur" entry:"1431461218" modified:"1431461218" status:"pending" uuid:"d203a656-f7ab-4707-8e38-abdced29acc4"]
|
12
|
+
new [description:"Test recur" due:"1451624399" entry:"1431461218" modified:"1431461218" recur:"weekly" status:"recurring" uuid:"d203a656-f7ab-4707-8e38-abdced29acc4"]
|
13
|
+
---
|
14
|
+
time 1431463308
|
15
|
+
new [description:"biannual test" due:"1451624399" entry:"1431463308" modified:"1431463308" recur:"biannual" status:"recurring" uuid:"45fc918e-f106-45d8-96b6-37eaf61f2f4e"]
|
16
|
+
---
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rtasklib::Helpers do
|
4
|
+
|
5
|
+
describe 'Rtasklib::Helpers#to_gem_version' do
|
6
|
+
|
7
|
+
it 'can handle sub version numbers' do
|
8
|
+
expect(Rtasklib::Helpers.to_gem_version("2.5.3 (afdj5)"))
|
9
|
+
.to eq(Gem::Version.new("2.5.3.afdj5"))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'Rtasklib::Helpers#determine_type' do
|
14
|
+
|
15
|
+
it 'considers "10" an integer' do
|
16
|
+
expect(Rtasklib::Helpers.determine_type("10")).to eq(Integer)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'considers "10.1" a float' do
|
20
|
+
expect(Rtasklib::Helpers.determine_type("10.1")).to eq(Float)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'considers "on" a boolean' do
|
24
|
+
expect(Rtasklib::Helpers.determine_type("on")).to eq(Axiom::Types::Boolean)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'considers "{"yolo":[1,2,3]}" a JSON object' do
|
28
|
+
test_json = '{"id":1,"description":"Anonymous Book",
|
29
|
+
"entry":"20150115T190114Z","modified":"20150115T190114Z",
|
30
|
+
"project":"Read","status":"pending","tags":["stuff"],
|
31
|
+
"uuid":"c483b58d-a3f2-4a2a-b944-8b41414309cb",
|
32
|
+
"urgency":"2.45753"}'
|
33
|
+
expect(Rtasklib::Helpers.determine_type(test_json)).to eq(MultiJson)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'considers "on off" a String' do
|
37
|
+
expect(Rtasklib::Helpers.determine_type("on ")).to eq(String)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'Rtasklib::Helpers#filter' do
|
42
|
+
|
43
|
+
it 'treats arrays of ranges properly' do
|
44
|
+
expect(Rtasklib::Helpers.filter(ids: [1..3,5...6])).to eq("1,2,3,5")
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'treats arrays of strings properly' do
|
48
|
+
expect(Rtasklib::Helpers.filter(ids: ["1,2", "5"])).to eq("1,2,5")
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'treats arrays of ints properly' do
|
52
|
+
expect(Rtasklib::Helpers.filter(ids: [1,2,3,4,5])).to eq("1,2,3,4,5")
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'treats arrays mixed objects properly' do
|
56
|
+
expect(Rtasklib::Helpers.filter(ids: [1,2,3,4,5, 10..20, "7,8"]))
|
57
|
+
.to eq("1,2,3,4,5,10,11,12,13,14,15,16,17,18,19,20,7,8")
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'treats tag arrays properly' do
|
61
|
+
expect(Rtasklib::Helpers.filter(tags: ["(", "+stuff", "or", "-school", ")", "work"]))
|
62
|
+
.to eq("( +stuff or -school ) +work")
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'treats tag strings properly' do
|
66
|
+
expect(Rtasklib::Helpers.filter(tags: "+stuff -school work"))
|
67
|
+
.to eq("+stuff -school +work")
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'treats tag/id combos properly' do
|
71
|
+
expect(Rtasklib::Helpers.filter(ids: [1,2,4..5], tags: "+stuff -school work"))
|
72
|
+
.to eq("1,2,4,5 +stuff -school +work")
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
data/spec/rtasklib_spec.rb
CHANGED
@@ -6,8 +6,8 @@ describe Rtasklib do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
describe Rtasklib::TaskWarrior do
|
9
|
-
describe "Rtasklib::TaskWarrior.new('spec/data/.
|
10
|
-
subject{ Rtasklib::TaskWarrior.new('spec/data/.
|
9
|
+
describe "Rtasklib::TaskWarrior.new('spec/data/.task')" do
|
10
|
+
subject{ Rtasklib::TaskWarrior.new('spec/data/.task') }
|
11
11
|
it 'has a version number' do
|
12
12
|
expect(subject.version.class).to eq Gem::Version
|
13
13
|
end
|
@@ -16,8 +16,8 @@ describe Rtasklib do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
describe "Rtasklib::TaskWarrior.new('spec/data/.
|
20
|
-
subject{ Rtasklib::TaskWarrior.new('spec/data/.
|
19
|
+
describe "Rtasklib::TaskWarrior.new('spec/data/.task', {color: off})" do
|
20
|
+
subject{ Rtasklib::TaskWarrior.new('spec/data/.task', {verbose: 'on'}) }
|
21
21
|
it 'updates the default configuration override' do
|
22
22
|
end
|
23
23
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtasklib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Paul
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -245,8 +245,8 @@ files:
|
|
245
245
|
- lib/rtasklib.rb
|
246
246
|
- lib/rtasklib/controller.rb
|
247
247
|
- lib/rtasklib/execute.rb
|
248
|
+
- lib/rtasklib/helpers.rb
|
248
249
|
- lib/rtasklib/models.rb
|
249
|
-
- lib/rtasklib/serializer.rb
|
250
250
|
- lib/rtasklib/taskrc.rb
|
251
251
|
- lib/rtasklib/version.rb
|
252
252
|
- rtasklib.gemspec
|
@@ -257,9 +257,9 @@ files:
|
|
257
257
|
- spec/data/.task/undo.data
|
258
258
|
- spec/data/.taskrc
|
259
259
|
- spec/execute_spec.rb
|
260
|
+
- spec/helpers_spec.rb
|
260
261
|
- spec/models_spec.rb
|
261
262
|
- spec/rtasklib_spec.rb
|
262
|
-
- spec/serializer_spec.rb
|
263
263
|
- spec/spec_helper.rb
|
264
264
|
- spec/taskrc_spec.rb
|
265
265
|
homepage: http://github.com/dropofwill/rtasklib
|
@@ -283,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
283
283
|
requirements:
|
284
284
|
- taskwarrior, >=2.4.0
|
285
285
|
rubyforge_project:
|
286
|
-
rubygems_version: 2.
|
286
|
+
rubygems_version: 2.2.2
|
287
287
|
signing_key:
|
288
288
|
specification_version: 4
|
289
289
|
summary: A Ruby wrapper around the TaskWarrior CLI
|
data/lib/rtasklib/serializer.rb
DELETED
data/spec/serializer_spec.rb
DELETED
File without changes
|