tdo 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/bin/tdo +5 -5
- data/lib/tdo.rb +189 -120
- data/tdo.gemspec +2 -2
- data/test/test_tdo.rb +28 -21
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
data/bin/tdo
CHANGED
@@ -27,12 +27,12 @@ opts = OptionParser.new do |opts|
|
|
27
27
|
end
|
28
28
|
|
29
29
|
opts.on("--summary", "-s", "Summary") do
|
30
|
-
puts Tdo.
|
30
|
+
puts Tdo.summary
|
31
31
|
exit 0
|
32
32
|
end
|
33
33
|
|
34
34
|
opts.on("--clear", "-c", "Clear done items") do
|
35
|
-
Tdo.
|
35
|
+
Tdo.clear
|
36
36
|
exit 0
|
37
37
|
end
|
38
38
|
|
@@ -46,9 +46,9 @@ opts.parse!
|
|
46
46
|
|
47
47
|
|
48
48
|
if ARGV.size == 2
|
49
|
-
Tdo.
|
49
|
+
Tdo.add(ARGV[1], ARGV[0])
|
50
50
|
elsif ARGV.size == 1
|
51
|
-
Tdo.
|
51
|
+
Tdo.add(ARGV[0])
|
52
52
|
else
|
53
|
-
puts Tdo.
|
53
|
+
puts Tdo.summary
|
54
54
|
end
|
data/lib/tdo.rb
CHANGED
@@ -1,154 +1,223 @@
|
|
1
1
|
module Tdo
|
2
2
|
|
3
3
|
class InvalidGroup < ArgumentError; end
|
4
|
-
|
5
|
-
TODO_FILE = File.expand_path "~/.todo.txt"
|
6
4
|
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
# @return [String] the tasks
|
11
|
-
def self.read_tasks( group=nil )
|
12
|
-
unless group
|
13
|
-
File.new(TODO_FILE, "r").read
|
14
|
-
else
|
15
|
-
t = File.new(TODO_FILE, "r").read
|
16
|
-
raise InvalidGroup, "'#{group}' is not a valid group name", caller unless self.group?(group)
|
17
|
-
to_s( to_hash(t)[ group[1..-1] ] )
|
18
|
-
end
|
19
|
-
end
|
5
|
+
# If using ENV, path must be absolute
|
6
|
+
TODO_FILE = ENV['TDO_FILE'] || File.expand_path("~/.todo.txt")
|
7
|
+
|
20
8
|
|
21
9
|
# Gives a summary of remaining tasks
|
22
10
|
#
|
23
11
|
# @return [String] summary of tasks
|
24
|
-
def self.
|
25
|
-
t =
|
26
|
-
groups = t.size
|
12
|
+
def self.summary
|
13
|
+
t = Tasks.new.items
|
14
|
+
groups = t.size-1
|
27
15
|
tasks = t.inject(0) {|sum, t| sum += t[1].size}
|
28
16
|
done = t.inject(0) {|sum, t| sum += t[1].delete_if {|i| !i.include? ' #done' }.size}
|
29
17
|
"#{tasks} tasks in #{groups} groups, #{done} done"
|
30
18
|
end
|
31
19
|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def self.add_task( task, group='@ungrouped' )
|
37
|
-
if File.exists? TODO_FILE
|
38
|
-
t = to_hash( self.read_tasks )
|
39
|
-
else
|
40
|
-
t = {}
|
41
|
-
end
|
42
|
-
if group[0] == "@"
|
43
|
-
group = group[1..-1]
|
20
|
+
# Takes the groups name from a string
|
21
|
+
def self.get_group( str )
|
22
|
+
if str[0] == '@'
|
23
|
+
return str[1..-1]
|
44
24
|
else
|
45
|
-
|
25
|
+
return str
|
46
26
|
end
|
47
|
-
t[group] ||= [] # need to create new group if it doesn't exist
|
48
|
-
t[group] << task.strip
|
49
|
-
|
50
|
-
write_hash t
|
51
27
|
end
|
52
28
|
|
53
|
-
# Marks the selected item as done
|
54
|
-
#
|
55
|
-
# @param [String, Integer] task to mark as done
|
56
|
-
# @param [String] group that the task belongs to
|
57
|
-
def self.mark_done( id, group='@ungrouped' )
|
58
|
-
if group[0] == "@"
|
59
|
-
group = group[1..-1]
|
60
|
-
else
|
61
|
-
raise InvalidGroup, "'#{group}' is not a valid group name", caller
|
62
|
-
end
|
63
29
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
30
|
+
|
31
|
+
class Tasks
|
32
|
+
|
33
|
+
attr_accessor :items
|
34
|
+
|
35
|
+
# Creates a new Tasks object and loads in the TODO_FILE
|
36
|
+
def initialize
|
37
|
+
@items = {'ungrouped' => []}
|
38
|
+
self.read
|
39
|
+
end
|
40
|
+
|
41
|
+
# Reads TODO_FILE and converts it to a hash
|
42
|
+
def read
|
43
|
+
t = File.new(TODO_FILE, "r").read
|
44
|
+
_group = ''
|
45
|
+
t.split("\n").each do |l|
|
46
|
+
if l[0] == '-'
|
47
|
+
@items['ungrouped'] << l[1..-1].strip
|
48
|
+
elsif l[0] == '@'
|
49
|
+
_group = l[1..-1].strip
|
50
|
+
@items[_group] = []
|
51
|
+
elsif l[0..1] == ' -'
|
52
|
+
@items[_group] << l[2..-1].strip
|
69
53
|
end
|
70
54
|
end
|
71
|
-
elsif id.is_a? Integer
|
72
|
-
t[group][id] += ' #done'
|
73
55
|
end
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
56
|
+
|
57
|
+
# Adds the task to the list
|
58
|
+
#
|
59
|
+
# @param [String] task to add
|
60
|
+
# @param [String] group to add the task to
|
61
|
+
# @return [Boolean] whether the task has been added successfully
|
62
|
+
def add(task, group=nil)
|
63
|
+
if group.nil?
|
64
|
+
group = 'ungrouped'
|
65
|
+
else
|
66
|
+
group = Tdo.get_group(group)
|
67
|
+
end
|
68
|
+
|
69
|
+
if self.find(task, group)
|
70
|
+
false
|
71
|
+
else
|
72
|
+
@items[group] ||= []
|
73
|
+
@items[group] << task.strip
|
74
|
+
self.write
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Marks the selected item as done
|
80
|
+
#
|
81
|
+
# @param [String, Integer] task to mark as done
|
82
|
+
# @param [String] group that the task belongs to
|
83
|
+
def mark_done(id, group=nil)
|
84
|
+
unless group.nil?
|
85
|
+
group = Tdo.get_group(group)
|
86
|
+
self.group?(group)
|
87
|
+
end
|
88
|
+
|
89
|
+
if id.is_a? Integer
|
90
|
+
if group
|
91
|
+
@items[group][id] += ' #done'
|
92
|
+
else
|
93
|
+
# should really count across groups, another time!
|
94
|
+
@items['ungrouped'][id] += ' #done'
|
95
|
+
end
|
96
|
+
elsif id.is_a? String
|
97
|
+
if group
|
98
|
+
@items[group].collect! { |t|
|
99
|
+
t.include?(id) ? t += ' #done' : t
|
100
|
+
}
|
101
|
+
else
|
102
|
+
# should test in every group as above
|
103
|
+
@items['ungrouped'].collect! { |t|
|
104
|
+
t.include?(id) ? t += ' #done' : t
|
105
|
+
}
|
106
|
+
end
|
107
|
+
else
|
108
|
+
# error
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
self.write
|
112
|
+
true
|
113
|
+
end
|
114
|
+
|
115
|
+
# Deletes all tasks marked as done
|
116
|
+
#
|
117
|
+
# @return [Integer] number of tasks cleared
|
118
|
+
def clear
|
119
|
+
r = 0
|
120
|
+
@items.each do |g, ts|
|
121
|
+
s = ts.size
|
122
|
+
ts.delete_if {|i| i.include?(' #done') }
|
123
|
+
r += s - ts.size
|
124
|
+
end
|
125
|
+
@items.delete_if {|g, ts| ts == [] }
|
126
|
+
self.write
|
127
|
+
r
|
128
|
+
end
|
129
|
+
|
130
|
+
# Finds tasks which contain the string to look for
|
131
|
+
#
|
132
|
+
# @param [String] arg string to look for
|
133
|
+
# @param [String] group to look within
|
134
|
+
# @return [Array] found tasks
|
135
|
+
# @todo find within group
|
136
|
+
def find(str, group=nil)
|
137
|
+
r = []
|
138
|
+
@items.each do |g, ts|
|
139
|
+
ts.each do |t|
|
140
|
+
r << t if t.include?(str)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
if r == []
|
144
|
+
false
|
145
|
+
else
|
146
|
+
r
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Converts the tasks to a string which can then be written to a file
|
151
|
+
#
|
152
|
+
# @param [String] group
|
153
|
+
# @return [String] string representation of tasks
|
154
|
+
def to_s(group=nil)
|
155
|
+
r = ''
|
156
|
+
if group
|
157
|
+
self.group?(group)
|
158
|
+
group = Tdo.get_group(group)
|
159
|
+
@items[group].each do |t|
|
160
|
+
r += "- #{t}\n"
|
161
|
+
end
|
162
|
+
else
|
163
|
+
@items.each do |g, ts|
|
164
|
+
if g == 'ungrouped'
|
165
|
+
ts.each do |t|
|
166
|
+
r += "- #{t}\n"
|
167
|
+
end
|
168
|
+
else
|
169
|
+
r += "\n@#{g}\n"
|
170
|
+
ts.each do |t|
|
171
|
+
r += " - #{t}\n"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
r
|
177
|
+
end
|
178
|
+
|
179
|
+
# Writes the tasks to a file
|
180
|
+
def write
|
181
|
+
File.open(TODO_FILE, "w") {|f| f.write( self.to_s )}
|
182
|
+
end
|
183
|
+
|
184
|
+
# Tests whether the group exists
|
185
|
+
#
|
186
|
+
# @param [String] group name
|
187
|
+
# @return [Boolean] whether the group exists
|
188
|
+
def group?( name )
|
189
|
+
if self.items.has_key?( Tdo.get_group(name) )
|
190
|
+
true
|
191
|
+
else
|
192
|
+
raise InvalidGroup, "'#{name}' is not a valid group name", caller
|
193
|
+
end
|
87
194
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
195
|
+
|
196
|
+
# Override default insepct
|
197
|
+
def inspect
|
198
|
+
"#<Tdo::Tasks>"
|
199
|
+
end
|
200
|
+
|
91
201
|
end
|
92
202
|
|
93
|
-
|
203
|
+
##
|
204
|
+
# These are a group of methods to make it easy to use the above class
|
94
205
|
#
|
95
|
-
|
96
|
-
|
97
|
-
File.open(TODO_FILE, "w") {|f| f.write( to_s(hash) )}
|
206
|
+
def self.read_tasks(group=nil)
|
207
|
+
Tdo::Tasks.new.to_s(group)
|
98
208
|
end
|
99
209
|
|
100
|
-
|
101
|
-
|
102
|
-
#
|
103
|
-
# @param [String] group name
|
104
|
-
# @return [Boolean] whether the group exists
|
105
|
-
def self.group?( name )
|
106
|
-
t = to_hash( self.read_tasks )
|
107
|
-
t.has_key?(name[1..-1])
|
210
|
+
def self.mark_done(id, group=nil)
|
211
|
+
Tdo::Tasks.new.mark_done(id, group)
|
108
212
|
end
|
109
213
|
|
110
|
-
|
111
|
-
|
112
|
-
# @param [String] read file string
|
113
|
-
# @return [Hash] the string as a hash
|
114
|
-
def self.to_hash( s )
|
115
|
-
r = {'ungrouped' => []}
|
116
|
-
last_group ||= ''
|
117
|
-
s.split("\n").each do |l|
|
118
|
-
if l[0] == '@'
|
119
|
-
last_group = l[1..-1].strip
|
120
|
-
r[last_group] = []
|
121
|
-
elsif l[1] == '-'
|
122
|
-
r[last_group] << l[2..-1].strip
|
123
|
-
elsif l[0] == '-'
|
124
|
-
r['ungrouped'] << l[1..-1].strip
|
125
|
-
end
|
126
|
-
end
|
127
|
-
r
|
214
|
+
def self.clear
|
215
|
+
Tdo::Tasks.new.clear
|
128
216
|
end
|
129
217
|
|
130
|
-
|
131
|
-
|
132
|
-
# @param [Hash] hash of todo tasks
|
133
|
-
# @return [String] string representation of hash
|
134
|
-
def self.to_s( hash )
|
135
|
-
if !hash.is_a? Hash
|
136
|
-
hash = {'ungrouped' => hash}
|
137
|
-
end
|
138
|
-
r = ""
|
139
|
-
hash.each do |group, tasks|
|
140
|
-
if group == 'ungrouped'
|
141
|
-
tasks.each do |task|
|
142
|
-
r += "- #{task}\n"
|
143
|
-
end
|
144
|
-
else
|
145
|
-
r += "\n@#{group}\n"
|
146
|
-
tasks.each do |task|
|
147
|
-
r += " - #{task}\n"
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
r
|
218
|
+
def self.add(task, group=nil)
|
219
|
+
Tdo::Tasks.new.add(task, group)
|
152
220
|
end
|
221
|
+
|
153
222
|
|
154
223
|
end
|
data/tdo.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{tdo}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Joshua Hawxwell"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-07-01}
|
13
13
|
s.default_executable = %q{tdo}
|
14
14
|
s.description = %q{Tdo is a simple ruby app to add, edit and read your todo list. It stores the list at ~/.todo.txt}
|
15
15
|
s.email = %q{m@hawx.me}
|
data/test/test_tdo.rb
CHANGED
@@ -1,63 +1,70 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestTdo < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
should "read tasks" do
|
6
6
|
clear_todo
|
7
|
-
|
7
|
+
t = Tdo::Tasks.new
|
8
|
+
assert_equal t.to_s, file_text
|
8
9
|
end
|
9
10
|
|
10
11
|
should "read tasks from specific group" do
|
11
12
|
clear_todo
|
12
|
-
assert_equal
|
13
|
+
assert_equal "- Another group\n", Tdo::Tasks.new.to_s('@home')
|
13
14
|
end
|
14
15
|
|
15
16
|
should "add new task" do
|
16
17
|
clear_todo
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
t = Tdo::Tasks.new
|
19
|
+
b = t.to_s
|
20
|
+
t.add("Pick up milk")
|
21
|
+
|
22
|
+
assert_equal b.size + " - Pick up milk".size, t.to_s.size
|
21
23
|
end
|
22
24
|
|
23
25
|
should "add new task to group" do
|
24
26
|
clear_todo
|
25
|
-
Tdo.
|
27
|
+
t = Tdo::Tasks.new
|
28
|
+
t.add('Pick up milk', '@test')
|
26
29
|
|
27
|
-
assert_equal
|
30
|
+
assert_equal " - Pick up milk".size, t.to_s('@test').size
|
28
31
|
end
|
29
32
|
|
30
33
|
should "mark task as done" do
|
31
34
|
clear_todo
|
32
|
-
|
33
|
-
|
35
|
+
t = Tdo::Tasks.new
|
36
|
+
b = t.to_s('@ungrouped').strip
|
37
|
+
t.mark_done('A task', '@ungrouped')
|
34
38
|
|
35
|
-
assert_equal
|
39
|
+
assert_equal b + " #done\n", t.to_s('@ungrouped')
|
36
40
|
end
|
37
41
|
|
38
42
|
should "mark task at index as done" do
|
39
43
|
clear_todo
|
40
|
-
|
41
|
-
|
44
|
+
t = Tdo::Tasks.new
|
45
|
+
b = t.to_s('@ungrouped').strip
|
46
|
+
t.mark_done(0, '@ungrouped')
|
42
47
|
|
43
|
-
assert_equal
|
48
|
+
assert_equal b + " #done\n", t.to_s('@ungrouped')
|
44
49
|
end
|
45
50
|
|
46
51
|
should "remove all tasks marked done" do
|
47
52
|
clear_todo
|
48
|
-
Tdo.
|
53
|
+
t = Tdo::Tasks.new
|
54
|
+
t.clear
|
49
55
|
|
50
|
-
assert_equal
|
56
|
+
assert_equal "- Another task\n", t.to_s('@group')
|
51
57
|
end
|
52
58
|
|
53
59
|
should "remove group when all tasks are cleared" do
|
54
60
|
clear_todo
|
55
|
-
Tdo.
|
56
|
-
|
61
|
+
t = Tdo::Tasks.new
|
62
|
+
t.mark_done(0, '@home')
|
63
|
+
t.clear
|
57
64
|
|
58
65
|
assert_raise Tdo::InvalidGroup do
|
59
|
-
|
66
|
+
t.to_s('@home')
|
60
67
|
end
|
61
68
|
end
|
62
|
-
|
69
|
+
|
63
70
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 5
|
9
|
+
version: 0.0.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Joshua Hawxwell
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-07-01 00:00:00 +01:00
|
18
18
|
default_executable: tdo
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|