rtasklib 0.1.5 → 0.2.0
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 -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
|