rtasklib 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|