rtasklib 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +0 -1
- data/README.md +2 -2
- data/lib/rtasklib.rb +2 -1
- data/lib/rtasklib/controller.rb +140 -39
- data/lib/rtasklib/execute.rb +15 -9
- data/lib/rtasklib/helpers.rb +51 -1
- data/lib/rtasklib/models.rb +1 -0
- data/lib/rtasklib/version.rb +1 -1
- data/spec/controller_spec.rb +78 -6
- data/spec/data/.taskrc +231 -0
- data/spec/helpers_spec.rb +15 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/taskrc_spec.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c5a99ddcc9e77d7834e92188d32d30b3ee4cd9a
|
4
|
+
data.tar.gz: 45ca4b324093c94949cebfe0d73dbe50ff11e1ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b535c4f6d7d4a6af2cfab8d2b0daace0db2d447cb50ada8d5e4746f7a36bf26e8e284b916b100e4829ae1da0ee68ad3cb29803409cb8f8d0d22e1f0b06f617fb
|
7
|
+
data.tar.gz: 6bcf89204ae9ea660e969ea5972d8690b71c0d8937df9c224297f908fbc9777dfbf7eb008f7f5d21249e002914b5621f2e2d91e57ef6b48a674b24e00978c5a0
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
## Description
|
7
7
|
|
8
|
-
A Ruby wrapper around the TaskWarrior
|
8
|
+
A Ruby wrapper around the TaskWarrior command line tool.
|
9
9
|
|
10
10
|
|
11
11
|
## Installation
|
@@ -29,7 +29,7 @@ Or install it yourself as:
|
|
29
29
|
|
30
30
|
* Taskwarrior > 2.4 (require custom UDAs, recurrences, and duration data types)
|
31
31
|
|
32
|
-
* Ruby > 2 (
|
32
|
+
* Ruby > 2.1 (Because default keyword arguments are too hard to live without :) )
|
33
33
|
|
34
34
|
* See `./rtasklib.gemspec` for the latest Ruby dependencies
|
35
35
|
|
data/lib/rtasklib.rb
CHANGED
@@ -18,6 +18,7 @@ module Rtasklib
|
|
18
18
|
DEFAULTS = {
|
19
19
|
json_array: 'true',
|
20
20
|
verbose: 'nothing',
|
21
|
+
gc: 'off',
|
21
22
|
confirmation: 'no',
|
22
23
|
dependency_confirmation: 'no',
|
23
24
|
exit_on_missing_db: 'yes', }
|
@@ -49,7 +50,7 @@ module Rtasklib
|
|
49
50
|
version
|
50
51
|
end
|
51
52
|
end
|
52
|
-
|
53
|
+
|
53
54
|
# Add a convenience alias
|
54
55
|
TW = TaskWarrior
|
55
56
|
end
|
data/lib/rtasklib/controller.rb
CHANGED
@@ -17,11 +17,13 @@ module Rtasklib
|
|
17
17
|
|
18
18
|
# Retrieves the current task list from the TW database
|
19
19
|
#
|
20
|
+
# @param active [Boolean] return only pending & waiting tasks
|
20
21
|
# @return [Array<Models::TaskModel>]
|
21
22
|
# @api public
|
22
|
-
def all
|
23
|
+
def all active: true
|
23
24
|
all = []
|
24
|
-
|
25
|
+
f = Helpers.pending_or_waiting(active)
|
26
|
+
Execute.task_popen3(*override_a, f, "export") do |i, o, e, t|
|
25
27
|
all = MultiJson.load(o.read).map do |x|
|
26
28
|
Rtasklib::Models::TaskModel.new(x)
|
27
29
|
end
|
@@ -43,8 +45,8 @@ module Rtasklib
|
|
43
45
|
# @api public
|
44
46
|
def some ids: nil, tags: nil, dom: nil
|
45
47
|
some = []
|
46
|
-
|
47
|
-
Execute.task_popen3(*@override_a,
|
48
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
49
|
+
Execute.task_popen3(*@override_a, f, "export") do |i, o, e, t|
|
48
50
|
some = MultiJson.load(o.read).map do |x|
|
49
51
|
Rtasklib::Models::TaskModel.new(x)
|
50
52
|
end
|
@@ -52,46 +54,144 @@ module Rtasklib
|
|
52
54
|
return some
|
53
55
|
end
|
54
56
|
|
55
|
-
#
|
57
|
+
# Add a single task to the database
|
56
58
|
#
|
57
59
|
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
58
60
|
# @param tags [Array<String>, String]
|
59
61
|
# @param dom [Array<String>, String]
|
60
62
|
# @api public
|
61
|
-
def
|
63
|
+
def count ids: nil, tags: nil, dom: nil
|
64
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
65
|
+
Execute.task_popen3(*@override_a, f, "count") do |i, o, e, t|
|
66
|
+
return Integer(o.read)
|
67
|
+
end
|
62
68
|
end
|
69
|
+
alias_method :size, :count
|
70
|
+
alias_method :length, :count
|
63
71
|
|
72
|
+
# Calls `task _show` with initial overrides returns a Taskrc object of the
|
73
|
+
# result
|
64
74
|
#
|
75
|
+
# @return [Taskrc]
|
76
|
+
# @api public
|
77
|
+
def get_rc
|
78
|
+
res = []
|
79
|
+
Execute.task_popen3(*@override_a, "_show") do |i, o, e, t|
|
80
|
+
res = o.read.each_line.map { |l| l.chomp }
|
81
|
+
end
|
82
|
+
Taskrc.new(res, :array)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Calls `task _version` and returns the result
|
65
86
|
#
|
87
|
+
# @return [String]
|
88
|
+
# @api public
|
89
|
+
def get_version
|
90
|
+
version = nil
|
91
|
+
Execute.task_popen3("_version") do |i, o, e, t|
|
92
|
+
version = Helpers.to_gem_version(o.read.chomp)
|
93
|
+
end
|
94
|
+
version
|
95
|
+
end
|
96
|
+
|
97
|
+
# Mark the filter of tasks as started
|
98
|
+
# Returns false if filter (ids:, tags:, dom:) is blank.
|
99
|
+
#
|
100
|
+
# @api public
|
101
|
+
def start! ids: nil, tags: nil, dom: nil
|
102
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
103
|
+
return false if f.blank?
|
104
|
+
|
105
|
+
Execute.task_popen3(*@override_a, f, "start") do |i, o, e, t|
|
106
|
+
return t.value
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Mark the filter of tasks as stopped
|
111
|
+
# Returns false if filter (ids:, tags:, dom:) is blank.
|
112
|
+
#
|
113
|
+
# @api public
|
114
|
+
def stop! ids: nil, tags: nil, dom: nil
|
115
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
116
|
+
return false if f.blank?
|
117
|
+
|
118
|
+
Execute.task_popen3(*@override_a, f, "stop") do |i, o, e, t|
|
119
|
+
return t.value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Add a single task to the database w/required description and optional
|
124
|
+
# tags and dom queries (e.g. project:Work)
|
125
|
+
#
|
126
|
+
# @param description [String] the required desc of the task
|
127
|
+
# @param tags [Array<String>, String]
|
128
|
+
# @param dom [Array<String>, String]
|
129
|
+
# @api public
|
130
|
+
def add! description, tags: nil, dom: nil
|
131
|
+
f = Helpers.filter(tags: tags, dom: dom)
|
132
|
+
d = Helpers.wrap_string(description)
|
133
|
+
Execute.task_popen3(*override_a, "add", d, f) do |i, o, e, t|
|
134
|
+
return t.value
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Modify a set of task the match the input filter with a single attr/value
|
139
|
+
# pair.
|
140
|
+
# Returns false if filter (ids:, tags:, dom:) is blank.
|
141
|
+
#
|
142
|
+
# @param attr [String]
|
143
|
+
# @param val [String]
|
66
144
|
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
67
145
|
# @param tags [Array<String>, String]
|
68
146
|
# @param dom [Array<String>, String]
|
69
147
|
# @api public
|
70
148
|
def modify! attr:, val:, ids: nil, tags: nil, dom: nil
|
71
|
-
f = filter(ids, tags, dom)
|
149
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
150
|
+
return false if f.blank?
|
151
|
+
|
72
152
|
query = "#{f} modify #{attr} #{val}"
|
73
153
|
Execute.task_popen3(*override_a, query) do |i, o, e, t|
|
74
154
|
return t.value
|
75
155
|
end
|
76
156
|
end
|
77
157
|
|
78
|
-
#
|
79
|
-
#
|
158
|
+
# Finishes the filtered tasks
|
159
|
+
# Returns false if filter (ids:, tags:, dom:) is blank.
|
80
160
|
#
|
161
|
+
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
162
|
+
# @param tags [Array<String>, String]
|
163
|
+
# @param dom [Array<String>, String]
|
81
164
|
# @api public
|
82
|
-
def
|
83
|
-
|
165
|
+
def done! ids: nil, tags: nil, dom: nil
|
166
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
167
|
+
return false if f.blank?
|
168
|
+
|
169
|
+
Execute.task_popen3(*override_a, f, "done") do |i, o, e, t|
|
84
170
|
return t.value
|
85
171
|
end
|
86
172
|
end
|
87
173
|
|
88
|
-
#
|
174
|
+
# Returns false if filter is blank.
|
89
175
|
#
|
90
|
-
# @param
|
91
|
-
# @param
|
176
|
+
# @param ids [Array<Range, Fixnum, String>, String, Range, Fixnum]
|
177
|
+
# @param tags [Array<String>, String]
|
178
|
+
# @param dom [Array<String>, String]
|
92
179
|
# @api public
|
93
|
-
def
|
94
|
-
|
180
|
+
def delete! ids: nil, tags: nil, dom: nil
|
181
|
+
f = Helpers.filter(ids: ids, tags: tags, dom: dom)
|
182
|
+
return false if f.blank?
|
183
|
+
|
184
|
+
Execute.task_popen3(*override_a, f, "delete") do |i, o, e, t|
|
185
|
+
return t.value
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Directly call `task undo`, which only applies to edits to the task db
|
190
|
+
# not configuration changes
|
191
|
+
#
|
192
|
+
# @api public
|
193
|
+
def undo!
|
194
|
+
Execute.task_popen3(*override_a, "undo") do |i, o, e, t|
|
95
195
|
return t.value
|
96
196
|
end
|
97
197
|
end
|
@@ -115,6 +215,17 @@ module Rtasklib
|
|
115
215
|
return udas
|
116
216
|
end
|
117
217
|
|
218
|
+
# Update a configuration variable in the .taskrc
|
219
|
+
#
|
220
|
+
# @param attr [String]
|
221
|
+
# @param val [String]
|
222
|
+
# @api public
|
223
|
+
def update_config! attr, val
|
224
|
+
Execute.task_popen3(*override_a, "config #{attr} #{val}") do |i, o, e, t|
|
225
|
+
return t.value
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
118
229
|
# Add new found udas to our internal TaskModel
|
119
230
|
#
|
120
231
|
# @param uda_hash [Hash{Symbol=>Hash}]
|
@@ -146,7 +257,7 @@ module Rtasklib
|
|
146
257
|
# @param uda_name [String] the uda name to check for
|
147
258
|
# @return [Boolean] whether it matches or not
|
148
259
|
# @api public
|
149
|
-
def
|
260
|
+
def uda_exists? uda_name
|
150
261
|
if get_udas.any? { |uda| uda == uda_name }
|
151
262
|
true
|
152
263
|
else
|
@@ -175,29 +286,19 @@ module Rtasklib
|
|
175
286
|
update_config("uda.#{name}.urgency", urgency) unless urgency.nil?
|
176
287
|
end
|
177
288
|
|
178
|
-
# Calls `task _show` with initial overrides returns a Taskrc object of the
|
179
|
-
# result
|
180
|
-
#
|
181
|
-
# @return [Taskrc]
|
182
|
-
# @api public
|
183
|
-
def get_rc
|
184
|
-
res = []
|
185
|
-
Execute.task_popen3(*@override_a, "_show") do |i, o, e, t|
|
186
|
-
res = o.read.each_line.map { |l| l.chomp }
|
187
|
-
end
|
188
|
-
Taskrc.new(res, :array)
|
189
|
-
end
|
190
289
|
|
191
|
-
#
|
290
|
+
# TODO: implement and test convenience methods for modifying tasks
|
192
291
|
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
292
|
+
# def annotate
|
293
|
+
# end
|
294
|
+
#
|
295
|
+
# def denotate
|
296
|
+
# end
|
297
|
+
#
|
298
|
+
# def append
|
299
|
+
# end
|
300
|
+
#
|
301
|
+
# def prepend
|
302
|
+
# end
|
202
303
|
end
|
203
304
|
end
|
data/lib/rtasklib/execute.rb
CHANGED
@@ -7,10 +7,16 @@ module Rtasklib
|
|
7
7
|
# so that the methods are available within the modules lookup path
|
8
8
|
extend self
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
DEBUG = false
|
11
|
+
|
12
|
+
# Turned off confirmations, so this regex is deprecated
|
13
|
+
# This also means we have to handle that all ourselves
|
14
|
+
# For example warn user with bang methods.
|
15
|
+
#
|
16
|
+
# @@exp_regex = {
|
17
|
+
# create_rc: %r{Would \s you \s like \s a \s sample \s *.+ \s created, \s
|
18
|
+
# so \s taskwarrior \s can \s proceed\? \s
|
19
|
+
# \(yes/no\)}x }
|
14
20
|
|
15
21
|
# Use Open3#popen3 to execute a unix program with an array of options
|
16
22
|
# and an optional block to handle the response.
|
@@ -28,10 +34,10 @@ module Rtasklib
|
|
28
34
|
def popen3 program='task', *opts, &block
|
29
35
|
execute = opts.unshift(program)
|
30
36
|
execute = execute.join(" ")
|
31
|
-
warn execute
|
37
|
+
warn execute if DEBUG
|
32
38
|
|
33
39
|
Open3.popen3(execute) do |i, o, e, t|
|
34
|
-
handle_response(e, t)
|
40
|
+
handle_response(o, e, t)
|
35
41
|
yield(i, o, e, t) if block_given?
|
36
42
|
end
|
37
43
|
end
|
@@ -85,10 +91,10 @@ module Rtasklib
|
|
85
91
|
# thread had a failing exit code
|
86
92
|
#
|
87
93
|
# @raise [RuntimeError] if failing exit code
|
88
|
-
def handle_response stderr, thread
|
94
|
+
def handle_response stdout, stderr, thread
|
89
95
|
unless thread.value.success?
|
90
|
-
|
91
|
-
raise
|
96
|
+
dump = "#{thread.value} \n Stderr: #{stderr.read} \n Stdout: #{stdout.read} \n"
|
97
|
+
raise dump
|
92
98
|
end
|
93
99
|
end
|
94
100
|
end
|
data/lib/rtasklib/helpers.rb
CHANGED
@@ -9,6 +9,14 @@ module Rtasklib
|
|
9
9
|
# make this module a stateless, singleton
|
10
10
|
extend self
|
11
11
|
|
12
|
+
# Wrap a string with quotes to make it safe to pass to `task`
|
13
|
+
#
|
14
|
+
# @param string [String]
|
15
|
+
# @api public
|
16
|
+
def wrap_string string
|
17
|
+
"\"#{string.to_s}\""
|
18
|
+
end
|
19
|
+
|
12
20
|
# Converts ids, tags, and dom queries to a single string ready to pass
|
13
21
|
# directly to task.
|
14
22
|
#
|
@@ -96,12 +104,35 @@ module Rtasklib
|
|
96
104
|
return tag
|
97
105
|
end
|
98
106
|
|
99
|
-
#
|
107
|
+
# Process string and array input of the likes of project:Work or
|
108
|
+
# description.contains:yolo
|
109
|
+
#
|
110
|
+
# @param dom [String, Array<String>, Hash]
|
111
|
+
# @api public
|
100
112
|
def process_dom dom
|
113
|
+
case dom
|
114
|
+
when String
|
115
|
+
dom
|
116
|
+
when Array
|
117
|
+
dom.join(" ")
|
118
|
+
when Hash
|
119
|
+
process_hash_dom(dom)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Parse the hash input to a string
|
124
|
+
#
|
125
|
+
# @param dom_hash [Hash]
|
126
|
+
# @return [String]
|
127
|
+
# @api public
|
128
|
+
def process_hash_dom dom_hash
|
129
|
+
dom_hash.reduce("") { |dom, (k,v)| dom += "#{k.to_s}:#{v} " }.strip
|
101
130
|
end
|
102
131
|
|
103
132
|
# Is a given taskrc attribute dealing with udas?
|
104
133
|
#
|
134
|
+
# @param attr [String]
|
135
|
+
# @return [Boolean]
|
105
136
|
# @api public
|
106
137
|
def uda_attr? attr
|
107
138
|
attr.to_s.start_with? "uda"
|
@@ -109,6 +140,9 @@ module Rtasklib
|
|
109
140
|
|
110
141
|
# Returns part of attribute at a given depth
|
111
142
|
#
|
143
|
+
# @param attr [String]
|
144
|
+
# @param depth [Integer]
|
145
|
+
# @return [Boolean]
|
112
146
|
# @api public
|
113
147
|
def arbitrary_attr attr, depth: 1
|
114
148
|
attr.to_s.split("_")[depth]
|
@@ -116,6 +150,9 @@ module Rtasklib
|
|
116
150
|
|
117
151
|
# Returns all attribute string after given depth
|
118
152
|
#
|
153
|
+
# @param attr [String]
|
154
|
+
# @param depth [Integer]
|
155
|
+
# @return [Boolean]
|
119
156
|
# @api public
|
120
157
|
def deep_attr attr, depth: 2
|
121
158
|
attr.to_s.split("_")[depth..-1].join("_")
|
@@ -131,6 +168,19 @@ module Rtasklib
|
|
131
168
|
Gem::Version.new std_ver
|
132
169
|
end
|
133
170
|
|
171
|
+
# Returns a "+PENDING or +WAITING" tag string if true, else ""
|
172
|
+
#
|
173
|
+
# @param use [Boolean]
|
174
|
+
# @return [String]
|
175
|
+
# @api public
|
176
|
+
def pending_or_waiting use=true
|
177
|
+
if use
|
178
|
+
"+PENDING or +WAITING"
|
179
|
+
else
|
180
|
+
""
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
134
184
|
# Determine the type that a value should be coerced to
|
135
185
|
# Int needs to precede float because ints are also floats
|
136
186
|
# Doesn't detect arrays, b/c task stores these as comma separated strings
|
data/lib/rtasklib/models.rb
CHANGED
data/lib/rtasklib/version.rb
CHANGED
data/spec/controller_spec.rb
CHANGED
@@ -18,9 +18,10 @@ describe Rtasklib::Controller do
|
|
18
18
|
shared_examples_for 'export all' do
|
19
19
|
it_behaves_like 'export'
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
# Number changes to often
|
22
|
+
# it 'should load in the correct number of task models' do
|
23
|
+
# expect(subject.size).to eq(4)
|
24
|
+
# end
|
24
25
|
end
|
25
26
|
|
26
27
|
describe 'Rtasklib::Controller#all' do
|
@@ -45,20 +46,91 @@ describe Rtasklib::Controller do
|
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
describe 'Rtasklib::Controller#
|
49
|
-
|
49
|
+
describe 'Rtasklib::Controller#uda_exists?' do
|
50
|
+
subject { Rtasklib::TaskWarrior.new("spec/data/.task").uda_exists?("client")}
|
51
|
+
|
52
|
+
it 'should return false if a uda is not found that matches the input' do
|
53
|
+
expect(subject).to eq(false)
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
53
|
-
describe 'Rtasklib::Controller#
|
57
|
+
describe 'Rtasklib::Controller#count' do
|
58
|
+
|
59
|
+
describe '#count should count existing tasks' do
|
60
|
+
|
61
|
+
subject { Rtasklib::TaskWarrior.new("spec/data/.task").count ids:[1,2] }
|
62
|
+
|
63
|
+
it 'should return an integer' do
|
64
|
+
expect(subject.is_a? Integer).to eq(true)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should return 2 for ids 1,2' do
|
68
|
+
expect(subject).to eq(2)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#count should return 0 for non existing tasks' do
|
73
|
+
|
74
|
+
subject { Rtasklib::TaskWarrior.new("spec/data/.task").count ids:1000 }
|
75
|
+
|
76
|
+
it 'should return 0 for ids 1000' do
|
77
|
+
expect(subject).to eq(0)
|
78
|
+
end
|
79
|
+
end
|
54
80
|
end
|
55
81
|
|
56
82
|
describe 'Rtasklib::Controller#add!' do
|
83
|
+
before(:context) do
|
84
|
+
@tw = Rtasklib::TaskWarrior.new("spec/data/.task")
|
85
|
+
@pre_count = @tw.all.count
|
86
|
+
@count_of_undos = 0
|
87
|
+
@tw.add!("Test adding methods")
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should add another task' do
|
91
|
+
expect(@tw.all.count).to eq(@pre_count + 1)
|
92
|
+
end
|
93
|
+
|
94
|
+
after(:context) do
|
95
|
+
@tw.undo!
|
96
|
+
end
|
57
97
|
end
|
58
98
|
|
59
99
|
describe 'Rtasklib::Controller#modify!' do
|
100
|
+
before(:context) do
|
101
|
+
@tw = Rtasklib::TaskWarrior.new("spec/data/.task")
|
102
|
+
@pre_task = @tw.some(ids: 1).first
|
103
|
+
@tw.modify!(attr: "description", val: "Modified description", ids: 1)
|
104
|
+
@after_task = @tw.some(ids: 1).first
|
105
|
+
@tw.undo!
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should have a different description after modification' do
|
109
|
+
expect(@pre_task.description).not_to eq(@after_task.description)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should have the same description after undo' do
|
113
|
+
expect(@pre_task.description).to eq(@tw.some(ids: 1).first.description)
|
114
|
+
end
|
60
115
|
end
|
61
116
|
|
62
117
|
describe 'Rtasklib::Controller#undo!' do
|
118
|
+
describe '#undo! should fix changes from add!' do
|
119
|
+
before(:context) do
|
120
|
+
@tw = Rtasklib::TaskWarrior.new("spec/data/.task")
|
121
|
+
@pre_count = @tw.all.count
|
122
|
+
@tw.add!("#undo! test")
|
123
|
+
@after_count = @tw.all.count
|
124
|
+
@tw.undo!
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should have the same count as before the "undo! test" task was created' do
|
128
|
+
expect(@tw.all.count).to eq(@pre_count)
|
129
|
+
expect(@tw.all.count).not_to eq(@after_count)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#undo! should fix changes from modify!' do
|
134
|
+
end
|
63
135
|
end
|
64
136
|
end
|
data/spec/data/.taskrc
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
data.location=.task
|
2
|
+
|
3
|
+
forcecolor=no
|
4
|
+
abbreviation.minimum=2
|
5
|
+
active.indicator=*
|
6
|
+
alias.burndown=burndown.weekly
|
7
|
+
alias.ghistory=ghistory.monthly
|
8
|
+
alias.history=history.monthly
|
9
|
+
alias.rm=delete
|
10
|
+
alias.shell=exec tasksh
|
11
|
+
allow.empty.filter=yes
|
12
|
+
avoidlastcolumn=no
|
13
|
+
bulk=3
|
14
|
+
burndown.bias=0.666
|
15
|
+
calendar.details=sparse
|
16
|
+
calendar.details.report=list
|
17
|
+
calendar.holidays=none
|
18
|
+
calendar.legend=yes
|
19
|
+
calendar.offset=no
|
20
|
+
calendar.offset.value=-1
|
21
|
+
color=on
|
22
|
+
color.active=color15 on rgb035
|
23
|
+
color.alternate=on gray0
|
24
|
+
color.blocked=bold gray10 on gray4
|
25
|
+
color.blocking=bold gray18 on gray6
|
26
|
+
color.burndown.done=on rgb013
|
27
|
+
color.burndown.pending=on gray9
|
28
|
+
color.burndown.started=on gray16
|
29
|
+
color.calendar.due=color0 on gray10
|
30
|
+
color.calendar.due.today=color0 on gray15
|
31
|
+
color.calendar.holiday=color15 on rgb005
|
32
|
+
color.calendar.overdue=color0 on gray20
|
33
|
+
color.calendar.today=underline black on color15
|
34
|
+
color.calendar.weekend=on gray4
|
35
|
+
color.calendar.weeknumber=gray10
|
36
|
+
color.completed=
|
37
|
+
color.debug=rgb500
|
38
|
+
color.deleted=
|
39
|
+
color.due=color0 on rgb013
|
40
|
+
color.due.today=color0 on rgb024
|
41
|
+
color.error=rgb500
|
42
|
+
color.footnote=gray10
|
43
|
+
color.header=gray10
|
44
|
+
color.history.add=on gray9
|
45
|
+
color.history.delete=black on gray23
|
46
|
+
color.history.done=black on rgb013
|
47
|
+
color.label=
|
48
|
+
color.label.sort=
|
49
|
+
color.overdue=color0 on rgb035
|
50
|
+
color.pri.H=
|
51
|
+
color.pri.L=
|
52
|
+
color.pri.M=
|
53
|
+
color.pri.none=
|
54
|
+
color.project.none=
|
55
|
+
color.recurring=
|
56
|
+
color.scheduled=
|
57
|
+
color.summary.background=on color0
|
58
|
+
color.summary.bar=on rgb012
|
59
|
+
color.sync.added=gray10
|
60
|
+
color.sync.changed=gray15
|
61
|
+
color.sync.rejected=gray23
|
62
|
+
color.tag.next=
|
63
|
+
color.tag.none=
|
64
|
+
color.tagged=
|
65
|
+
color.undo.after=red
|
66
|
+
color.undo.before=green
|
67
|
+
color.until=
|
68
|
+
color.warning=
|
69
|
+
column.padding=1
|
70
|
+
complete.all.tags=no
|
71
|
+
confirmation=yes
|
72
|
+
dateformat=Y-M-D
|
73
|
+
dateformat.annotation=
|
74
|
+
dateformat.edit=Y-M-D H:N:S
|
75
|
+
dateformat.holiday=YMD
|
76
|
+
dateformat.info=Y-M-D H:N:S
|
77
|
+
dateformat.report=
|
78
|
+
debug=no
|
79
|
+
default.command=next
|
80
|
+
default.due=
|
81
|
+
default.priority=
|
82
|
+
default.project=
|
83
|
+
defaultheight=24
|
84
|
+
defaultwidth=80
|
85
|
+
dependency.confirmation=on
|
86
|
+
dependency.indicator=D
|
87
|
+
dependency.reminder=on
|
88
|
+
detection=on
|
89
|
+
displayweeknumber=yes
|
90
|
+
dom=on
|
91
|
+
due=7
|
92
|
+
exit.on.missing.db=no
|
93
|
+
expressions=infix
|
94
|
+
fontunderline=yes
|
95
|
+
gc=on
|
96
|
+
hooks=on
|
97
|
+
hyphenate=on
|
98
|
+
indent.annotation=2
|
99
|
+
indent.report=0
|
100
|
+
journal.info=on
|
101
|
+
journal.time=no
|
102
|
+
journal.time.start.annotation=Started task
|
103
|
+
journal.time.stop.annotation=Stopped task
|
104
|
+
json.array=off
|
105
|
+
list.all.projects=no
|
106
|
+
list.all.tags=no
|
107
|
+
locking=on
|
108
|
+
nag=You have more urgent tasks.
|
109
|
+
print.empty.columns=no
|
110
|
+
recurrence.confirmation=prompt
|
111
|
+
recurrence.indicator=R
|
112
|
+
recurrence.limit=1
|
113
|
+
regex=yes
|
114
|
+
report.active.columns=id,start,start.age,entry.age,depends.indicator,priority,project,tags,recur,wait.indicator,scheduled.age,due,until,description
|
115
|
+
report.active.description=Active tasks
|
116
|
+
report.active.filter=status:pending and +ACTIVE
|
117
|
+
report.active.labels=ID,Started,Active,Age,D,P,Project,Tags,Recur,W,Sch,Due,Until,Description
|
118
|
+
report.active.sort=project+,start+
|
119
|
+
report.all.columns=id,status.short,uuid.short,start.active,entry.age,end.age,depends.indicator,priority,project.parent,tags.count,recur.indicator,wait.age,scheduled.age,due,until.age,description
|
120
|
+
report.all.description=All tasks
|
121
|
+
report.all.labels=ID,St,UUID,A,Age,Done,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description
|
122
|
+
report.all.sort=entry-
|
123
|
+
report.blocked.columns=id,depends,project,priority,due,start.active,entry.age,description
|
124
|
+
report.blocked.description=Blocked tasks
|
125
|
+
report.blocked.filter=status:pending +BLOCKED
|
126
|
+
report.blocked.labels=ID,Deps,Proj,Pri,Due,Active,Age,Description
|
127
|
+
report.blocked.sort=due+,priority-,start-,project+
|
128
|
+
report.blocking.columns=id,uuid.short,start.active,depends,project,tags,recur,wait.indicator,scheduled.age,due.age,until.age,description.count,urgency
|
129
|
+
report.blocking.description=Blocking tasks
|
130
|
+
report.blocking.filter=status:pending +BLOCKING
|
131
|
+
report.blocking.labels=ID,UUID,A,Deps,Project,Tags,R,W,Sch,Due,Until,Description,Urg
|
132
|
+
report.blocking.sort=urgency-,due+,entry+
|
133
|
+
report.completed.columns=id,uuid.short,entry,end,entry.age,depends,priority,project,tags,recur.indicator,due,description
|
134
|
+
report.completed.description=Completed tasks
|
135
|
+
report.completed.filter=status:completed
|
136
|
+
report.completed.labels=ID,UUID,Created,Completed,took,Deps,P,Project,Tags,R,Due,Description
|
137
|
+
report.completed.sort=end+
|
138
|
+
report.list.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due,until.age,description.count,urgency
|
139
|
+
report.list.description=Most details of tasks
|
140
|
+
report.list.filter=status:pending
|
141
|
+
report.list.labels=ID,Active,Age,D,P,Project,Tags,R,Sch,Due,Until,Description,Urg
|
142
|
+
report.list.sort=start-,due+,project+/,urgency-
|
143
|
+
report.long.columns=id,start.active,entry,modified.age,depends,priority,project,tags,recur,wait.age,scheduled,due,until,description
|
144
|
+
report.long.description=All details of tasks
|
145
|
+
report.long.filter=status:pending
|
146
|
+
report.long.labels=ID,A,Created,Mod,Deps,P,Project,Tags,Recur,Wait,Sched,Due,Until,Description
|
147
|
+
report.long.sort=modified-
|
148
|
+
report.ls.columns=id,start.active,depends.indicator,project,tags,recur.indicator,wait.age,scheduled.countdown,due.countdown,until.countdown,description.count
|
149
|
+
report.ls.description=Few details of tasks
|
150
|
+
report.ls.filter=status:pending
|
151
|
+
report.ls.labels=ID,A,D,Project,Tags,R,Wait,S,Due,Until,Description
|
152
|
+
report.ls.sort=start-,description+
|
153
|
+
report.minimal.columns=id,project,tags.count,description.count
|
154
|
+
report.minimal.description=Minimal details of tasks
|
155
|
+
report.minimal.filter=(status:pending or status:waiting)
|
156
|
+
report.minimal.labels=ID,Project,Tags,Description
|
157
|
+
report.minimal.sort=project+/,description+
|
158
|
+
report.newest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.age,scheduled.countdown,due,until.age,description
|
159
|
+
report.newest.description=Newest tasks
|
160
|
+
report.newest.filter=(status:pending or status:waiting) and recur.none:
|
161
|
+
report.newest.labels=ID,Active,Created,Age,Mod,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description
|
162
|
+
report.newest.sort=entry-
|
163
|
+
report.next.columns=id,start.age,entry.age,depends,priority,project,tags,recur,scheduled.countdown,due.age,until.age,description,urgency
|
164
|
+
report.next.description=Most urgent tasks
|
165
|
+
report.next.filter=status:pending limit:page
|
166
|
+
report.next.labels=ID,Active,Age,Deps,P,Project,Tag,Recur,S,Due,Until,Description,Urg
|
167
|
+
report.next.sort=start-,urgency-
|
168
|
+
report.oldest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.age,scheduled.countdown,due,until.age,description
|
169
|
+
report.oldest.description=Oldest tasks
|
170
|
+
report.oldest.filter=(status:pending or status:waiting)
|
171
|
+
report.oldest.labels=ID,Active,Created,Age,Mod,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description
|
172
|
+
report.oldest.sort=entry+
|
173
|
+
report.overdue.columns=id,start.age,entry.age,depends,priority,project,tags,recur.indicator,scheduled.countdown,due,until,description,urgency
|
174
|
+
report.overdue.description=Overdue tasks
|
175
|
+
report.overdue.filter=(status:pending or status:waiting) and +OVERDUE
|
176
|
+
report.overdue.labels=ID,Active,Age,Deps,P,Project,Tag,R,S,Due,Until,Description,Urg
|
177
|
+
report.overdue.sort=urgency-,due+
|
178
|
+
report.ready.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due.countdown,until.age,description,urgency
|
179
|
+
report.ready.description=Most urgent actionable tasks
|
180
|
+
report.ready.filter=+READY
|
181
|
+
report.ready.labels=ID,Active,Age,D,P,Project,Tags,R,S,Due,Until,Description,Urg
|
182
|
+
report.ready.sort=start-,urgency-
|
183
|
+
report.recurring.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur,scheduled.countdown,due,until.age,description,urgency
|
184
|
+
report.recurring.description=Recurring Tasks
|
185
|
+
report.recurring.filter=(status:pending or status:waiting) and (+PARENT or +CHILD)
|
186
|
+
report.recurring.labels=ID,Active,Age,D,P,Project,Tags,Recur,Sch,Due,Until,Description,Urg
|
187
|
+
report.recurring.sort=due+,urgency-,entry+
|
188
|
+
report.unblocked.columns=id,depends,project,priority,due,start.active,entry.age,description
|
189
|
+
report.unblocked.description=Unblocked tasks
|
190
|
+
report.unblocked.filter=status:pending -BLOCKED
|
191
|
+
report.unblocked.labels=ID,Deps,Proj,Pri,Due,Active,Age,Description
|
192
|
+
report.unblocked.sort=due+,priority-,start-,project+
|
193
|
+
report.waiting.columns=id,start.active,entry.age,depends.indicator,priority,project,tags,recur.indicator,wait,wait.age,scheduled,due,until,description
|
194
|
+
report.waiting.description=Waiting (hidden) tasks
|
195
|
+
report.waiting.filter=+WAITING
|
196
|
+
report.waiting.labels=ID,A,Age,D,P,Project,Tags,R,Wait,for,Sched,Due,Until,Description
|
197
|
+
report.waiting.sort=due+,wait+,entry+
|
198
|
+
reserved.lines=1
|
199
|
+
row.padding=0
|
200
|
+
rule.precedence.color=deleted,completed,active,keyword.,tag.,uda.,project.,overdue,scheduled,due.today,due,blocked,blocking,recurring,tagged,pri.
|
201
|
+
search.case.sensitive=yes
|
202
|
+
shell.prompt=task>
|
203
|
+
tag.indicator=+
|
204
|
+
taskd.ca=~/.task/ca.cert.pem
|
205
|
+
taskd.certificate=~/.task/private.certificate.pem
|
206
|
+
taskd.ciphers=NORMAL
|
207
|
+
taskd.credentials=inthe_am/whp3652/76399cb0-70e4-42c0-9a2e-4095a11d52b2
|
208
|
+
taskd.key=~/.task/private.key.pem
|
209
|
+
taskd.server=taskwarrior.inthe.am:53589
|
210
|
+
taskd.trust=ignore hostname
|
211
|
+
uda.author.label=Auth
|
212
|
+
uda.author.type=string
|
213
|
+
uda.author.values=
|
214
|
+
undo.style=side
|
215
|
+
urgency.active.coefficient=4.0
|
216
|
+
urgency.age.coefficient=2.0
|
217
|
+
urgency.age.max=365
|
218
|
+
urgency.annotations.coefficient=1.0
|
219
|
+
urgency.blocked.coefficient=-5.0
|
220
|
+
urgency.blocking.coefficient=8.0
|
221
|
+
urgency.due.coefficient=12.0
|
222
|
+
urgency.inherit.coefficient=0.0
|
223
|
+
urgency.next.coefficient=15.0
|
224
|
+
urgency.priority.coefficient=6.0
|
225
|
+
urgency.project.coefficient=1.0
|
226
|
+
urgency.scheduled.coefficient=5.0
|
227
|
+
urgency.tags.coefficient=1.0
|
228
|
+
urgency.waiting.coefficient=-3.0
|
229
|
+
verbose=yes
|
230
|
+
weekstart=sunday
|
231
|
+
xterm.title=no
|
data/spec/helpers_spec.rb
CHANGED
@@ -72,5 +72,20 @@ describe Rtasklib::Helpers do
|
|
72
72
|
.to eq("1,2,4,5 +stuff -school +work")
|
73
73
|
end
|
74
74
|
|
75
|
+
it 'treats dom strings properly' do
|
76
|
+
expect(Rtasklib::Helpers.filter(dom: "project:Work due:today"))
|
77
|
+
.to eq("project:Work due:today")
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'treats dom arrays properly' do
|
81
|
+
expect(Rtasklib::Helpers.filter(dom: ["project:Work", "due:today priority:L"]))
|
82
|
+
.to eq("project:Work due:today priority:L")
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'treats dom hashes properly' do
|
86
|
+
expect(Rtasklib::Helpers.filter(dom: {project:"Work", due:"today", priority:"L"}))
|
87
|
+
.to eq("project:Work due:today priority:L")
|
88
|
+
end
|
89
|
+
|
75
90
|
end
|
76
91
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/taskrc_spec.rb
CHANGED
@@ -3,6 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Rtasklib::Taskrc do
|
4
4
|
|
5
5
|
describe "initialize with a test .taskrc" do
|
6
|
+
|
6
7
|
subject { Rtasklib::Taskrc.new("spec/data/.taskrc", :path).config }
|
7
8
|
|
8
9
|
it "creates a Virtus model representation" do
|
@@ -10,7 +11,7 @@ describe Rtasklib::Taskrc do
|
|
10
11
|
end
|
11
12
|
|
12
13
|
it "attribute name dot paths are converted to underscores" do
|
13
|
-
expect(subject.data_location).to eq "
|
14
|
+
expect(subject.data_location).to eq ".task"
|
14
15
|
end
|
15
16
|
|
16
17
|
it "top level configs are possible" do
|
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.
|
4
|
+
version: 0.2.0
|
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-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|