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.
Files changed (6) hide show
  1. data/VERSION +1 -1
  2. data/bin/tdo +5 -5
  3. data/lib/tdo.rb +189 -120
  4. data/tdo.gemspec +2 -2
  5. data/test/test_tdo.rb +28 -21
  6. metadata +3 -3
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
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.task_summary
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.clear_done
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.add_task(ARGV[1], ARGV[0])
49
+ Tdo.add(ARGV[1], ARGV[0])
50
50
  elsif ARGV.size == 1
51
- Tdo.add_task(ARGV[0])
51
+ Tdo.add(ARGV[0])
52
52
  else
53
- puts Tdo.task_summary
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
- # Reads the TODO file
8
- #
9
- # @param [String] group to read tasks from
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.task_summary
25
- t = to_hash( self.read_tasks )
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
- # Allows you to add a new task to the file
33
- #
34
- # @param [String] task to add
35
- # @param [String] group to add the task to
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
- raise InvalidGroup, "'#{group}' is not a valid group name", caller
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
- t = to_hash( self.read_tasks )
65
- if id.is_a? String
66
- t[group].each_with_index do |task, i|
67
- if task.include? id
68
- t[group][i] += ' #done'
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
- write_hash t
75
- end
76
-
77
-
78
- # Deletes all items which have been marked done
79
- #
80
- # @return [Integer] number of tasks cleared
81
- def self.clear_done
82
- t = to_hash( self.read_tasks )
83
- r = 0
84
- t.each do |group, tasks|
85
- s = tasks.size
86
- r += tasks.delete_if {|i| i.include? ' #done' }.size - s
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
- t.delete_if {|k, v| v == [] }
89
- write_hash t
90
- r
195
+
196
+ # Override default insepct
197
+ def inspect
198
+ "#<Tdo::Tasks>"
199
+ end
200
+
91
201
  end
92
202
 
93
- # Converts the given hash to a string and writes to the TODO_FILE
203
+ ##
204
+ # These are a group of methods to make it easy to use the above class
94
205
  #
95
- # @param [Hash] tasks hash to write
96
- def self.write_hash( hash )
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
- # Tests whether the group exists
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
- # Converts the string read from the file to a hash so it can easily be used
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
- # Converts the given hash to a string which can then be written to a file
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
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tdo}
8
- s.version = "0.0.4"
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-06-26}
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}
@@ -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
- assert_equal Tdo.read_tasks, file_text
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 Tdo.read_tasks('@home'), "- Another group\n"
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
- b = Tdo.read_tasks
18
- Tdo.add_task("Pick up milk")
19
-
20
- assert_equal Tdo.read_tasks.size, b.size + " - Pick up milk".size
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.add_task('Pick up milk', '@test')
27
+ t = Tdo::Tasks.new
28
+ t.add('Pick up milk', '@test')
26
29
 
27
- assert_equal Tdo.read_tasks('@test').size, " - Pick up milk".size
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
- b = Tdo.read_tasks('@ungrouped').strip
33
- Tdo.mark_done('A task', '@ungrouped')
35
+ t = Tdo::Tasks.new
36
+ b = t.to_s('@ungrouped').strip
37
+ t.mark_done('A task', '@ungrouped')
34
38
 
35
- assert_equal Tdo.read_tasks('@ungrouped'), b + " #done\n"
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
- b = Tdo.read_tasks( '@ungrouped').strip
41
- Tdo.mark_done(0, '@ungrouped')
44
+ t = Tdo::Tasks.new
45
+ b = t.to_s('@ungrouped').strip
46
+ t.mark_done(0, '@ungrouped')
42
47
 
43
- assert_equal Tdo.read_tasks('@ungrouped'), b + " #done\n"
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.clear_done
53
+ t = Tdo::Tasks.new
54
+ t.clear
49
55
 
50
- assert_equal Tdo.read_tasks('@group'), "- Another task\n"
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.mark_done(0, '@home')
56
- Tdo.clear_done
61
+ t = Tdo::Tasks.new
62
+ t.mark_done(0, '@home')
63
+ t.clear
57
64
 
58
65
  assert_raise Tdo::InvalidGroup do
59
- Tdo.read_tasks('@home')
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
- - 4
9
- version: 0.0.4
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-06-26 00:00:00 +01:00
17
+ date: 2010-07-01 00:00:00 +01:00
18
18
  default_executable: tdo
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency