todotxt 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +2 -0
  3. data/README.md +1 -0
  4. data/bin/todotxt +3 -3
  5. data/conf/todotxt.cfg +13 -1
  6. data/cucumber.yml +3 -0
  7. data/features/add.feature +24 -0
  8. data/features/append.feature +28 -0
  9. data/features/backwards.feature +28 -0
  10. data/features/colors.feature +51 -0
  11. data/features/del.feature +52 -0
  12. data/features/depri.feature +38 -0
  13. data/features/do.feature +47 -0
  14. data/features/due.feature +49 -0
  15. data/features/edit.feature +31 -0
  16. data/features/generate_config.feature +19 -0
  17. data/features/generate_txt.feature +20 -0
  18. data/features/initialize.feature +73 -0
  19. data/features/list.feature +132 -0
  20. data/features/move.feature +33 -0
  21. data/features/prepend.feature +28 -0
  22. data/features/pri.feature +40 -0
  23. data/features/replace.feature +28 -0
  24. data/features/step_definitions/environment_steps.rb +47 -0
  25. data/features/step_definitions/list_steps.rb +34 -0
  26. data/features/support/ansi.rb +5 -0
  27. data/features/support/aruba.rb +9 -0
  28. data/features/support/debugger.rb +1 -0
  29. data/features/undo.feature +54 -0
  30. data/lib/todotxt/cli.rb +131 -45
  31. data/lib/todotxt/clihelpers.rb +4 -1
  32. data/lib/todotxt/config.rb +58 -0
  33. data/lib/todotxt/regex.rb +1 -0
  34. data/lib/todotxt/todo.rb +5 -0
  35. data/lib/todotxt/todofile.rb +40 -0
  36. data/lib/todotxt/todolist.rb +20 -2
  37. data/lib/todotxt/version.rb +1 -1
  38. data/lib/todotxt.rb +2 -0
  39. data/spec/cli_spec.rb +6 -0
  40. data/spec/config_spec.rb +52 -0
  41. data/spec/fixtures/config_both.cfg +4 -0
  42. data/spec/fixtures/config_new.cfg +2 -0
  43. data/spec/fixtures/config_old.cfg +1 -0
  44. data/spec/spec_helper.rb +3 -0
  45. data/spec/todo_spec.rb +12 -0
  46. data/spec/todofile_spec.rb +31 -0
  47. data/spec/todolist_spec.rb +20 -2
  48. data/todotxt.gemspec +4 -0
  49. metadata +154 -28
@@ -0,0 +1,33 @@
1
+ Feature: move
2
+
3
+ So that I can keep items organised
4
+ As a user
5
+ I want to move items between files
6
+
7
+ Background:
8
+ Given a config exists with the following files:
9
+ | alias | path |
10
+ | todo | todo.txt |
11
+ | wishlist | wishlist.txt |
12
+ And a todofile with the following items exists:
13
+ | todo |
14
+ | Getting Things Done @bookstore |
15
+ | Label Maker @officesupply |
16
+ And an empty todofile named "wishlist.txt" exists
17
+
18
+ Scenario: Move item from todo.txt to wishlist.txt
19
+ When I run `todotxt move 1 wishlist`
20
+ Then it should pass with:
21
+ """
22
+ 1. Getting Things Done @bookstore
23
+ => Moved to wishlist.txt
24
+ """
25
+ And the file "todo.txt" should not contain "Getting Things Done @bookstore"
26
+ And the file "wishlist.txt" should contain "Getting Things Done @bookstore"
27
+
28
+ Scenario: Move an illegal item
29
+ When I run `todotxt move 1337 wishlist`
30
+ Then it should pass with:
31
+ """
32
+ ERROR: No todo found at line 1337
33
+ """
@@ -0,0 +1,28 @@
1
+ Feature: Prepend
2
+
3
+ So that I can change items
4
+ As a user
5
+ I want to prepend text to an item
6
+
7
+ Background:
8
+ Given a default config exists
9
+ And a todofile with the following items exists:
10
+ | todo |
11
+ | (B) Install todotxt @cli +todotxt |
12
+ | Drink coffee |
13
+
14
+ Scenario: Add text to an item
15
+ When I run `todotxt prepend 2 Brew and`
16
+ Then it should pass with:
17
+ """
18
+ 2. Brew and Drink coffee
19
+ """
20
+ And the file "todo.txt" should contain "Brew and Drink coffee"
21
+
22
+
23
+ Scenario: Add text to an illegal item:
24
+ When I run `todotxt prepend 1337 @sofa`
25
+ Then it should pass with:
26
+ """
27
+ ERROR: No todo found at line 1337
28
+ """
@@ -0,0 +1,40 @@
1
+ Feature: Prioritise
2
+
3
+ So that I can make items more important
4
+ As a user
5
+ I want to prioritise items
6
+
7
+ Background:
8
+ Given a default config exists
9
+ And a todofile with the following items exists:
10
+ | todo |
11
+ | (B) Install todotxt @cli +todotxt |
12
+ | Drink coffee |
13
+
14
+ Scenario: Set priority of an item should report it and change it in the file
15
+ When I run `todotxt pri 2 A`
16
+ Then it should pass with:
17
+ """
18
+ 2. (A) Drink coffee
19
+ """
20
+ And the file "todo.txt" should contain "(A) Drink coffee"
21
+
22
+ Scenario: Set the priority of an already prioritised item
23
+ When I run `todotxt pri 1 A`
24
+ Then the file "todo.txt" should contain "(A) Install todotxt @cli +todotxt"
25
+
26
+ #todo: make it throw an error instead.
27
+ Scenario: Attempt to set priority to an illegal priority
28
+ When I run `todotxt pri 2 Foo`
29
+ Then it should pass with:
30
+ """
31
+ 2. Drink coffee
32
+ """
33
+ And the file "todo.txt" should not contain "(Foo) Drink coffee"
34
+
35
+ Scenario: Attempt to set the priority of an illegal line
36
+ When I run `todotxt pri 1337 A`
37
+ Then it should pass with:
38
+ """
39
+ ERROR: No todo found at line 1337
40
+ """
@@ -0,0 +1,28 @@
1
+ Feature: Replace
2
+
3
+ So that I can change items
4
+ As a user
5
+ I want to completely replace an item with new text
6
+
7
+ Background:
8
+ Given a default config exists
9
+ And a todofile with the following items exists:
10
+ | todo |
11
+ | (B) Install todotxt @cli +todotxt |
12
+ | Drink coffee |
13
+
14
+ Scenario: Add text to an item
15
+ When I run `todotxt replace 2 sip frappucino @buckstar`
16
+ Then it should pass with:
17
+ """
18
+ 2. sip frappucino @buckstar
19
+ """
20
+ And the file "todo.txt" should contain "sip frappucino @buckstar"
21
+ And the file "todo.txt" should not contain "Drink coffee"
22
+
23
+ Scenario: Add text to an illegal item:
24
+ When I run `todotxt prepend 1337 @sofa`
25
+ Then it should pass with:
26
+ """
27
+ ERROR: No todo found at line 1337
28
+ """
@@ -0,0 +1,47 @@
1
+ Given /^a default config exists$/ do
2
+ write_file(".todotxt.cfg", "[files]\ntodo = todo.txt")
3
+ end
4
+
5
+ Given /^an old config exists$/ do
6
+ write_file(".todotxt.cfg", "todo_txt_path = todo.txt")
7
+ end
8
+
9
+ Given /^an empty environment$/ do
10
+ step %{a file named ".todotxt.cfg" should not exist}
11
+ step %{a file named "todo.txt" should not exist}
12
+ end
13
+
14
+ Given /^a config exists with the following files:$/ do |files|
15
+ files_directive = "[files]\n"
16
+ files_directive += files.hashes.map {|file| "#{file["alias"]}=#{file["path"]}" }.join("\n")
17
+ write_file(".todotxt.cfg", files_directive)
18
+ end
19
+
20
+ Given /^a default config exists with the editor set to "(.*?)"$/ do |editor|
21
+ write_file(".todotxt.cfg", "editor=#{editor}\n[files]\ntodo = todo.txt")
22
+ end
23
+
24
+ Given /^a todofile exists$/ do
25
+ write_file("todo.txt", "Read documentation for todotxt\nWrite cucumber steps for todotxt")
26
+ end
27
+
28
+ Given /^a todofile with done items exists$/ do
29
+ write_file("todo.txt", "Read documentation for todotxt\nx Install todotxt\nWrite cucumber steps for todotxt")
30
+ end
31
+
32
+ Given /^a todofile with the following items exists:$/ do |todolist|
33
+ contents = todolist.hashes.map {|row| row["todo"] }.join("\n")
34
+ write_file("todo.txt", contents)
35
+ end
36
+
37
+ Given /^an empty todofile named "(.*?)" exists$/ do |filename|
38
+ write_file(filename, "")
39
+ end
40
+
41
+ Given /^the enviromnent variable "(.*?)" is set to "(.*?)"$/ do |name, value|
42
+ ENV[name] = value
43
+ end
44
+
45
+ Given /^the date is "(.*?)"$/ do |date|
46
+ step %{the enviromnent variable "date" is set to "#{date}"}
47
+ end
@@ -0,0 +1,34 @@
1
+ Then /^I should see all entries from the todofile with numbers$/ do
2
+ contents = ""
3
+ File.open(File.join(ENV["HOME"], "todo.txt")).each_line do |line|
4
+ # matching "1. Do Something"
5
+ contents += "([\\d]\.\\s+)#{Regexp.escape(line.strip)}.*"
6
+ end
7
+ step "it should pass with regex:", contents
8
+ end
9
+
10
+ Then /^I should see all entries from the todofile without formatting$/ do
11
+ contents = ""
12
+ File.open(File.join(ENV["HOME"], "todo.txt")).each_line do |line|
13
+ # matching "1 Do something", note the missing dot .
14
+ contents += "([\\d]\\s+)#{Regexp.escape(line.strip)}.*"
15
+ end
16
+ step "it should pass with regex:", contents
17
+ step "the output should not match /TODO: [\d]+ items/"
18
+ end
19
+
20
+ Then /^it should count (\d+) TODO\-items$/ do |count|
21
+ step %{the output should match /^TODO: #{count} items$/}
22
+ end
23
+
24
+ Then /^it should output "([^"]*)" brightly in "([^"]*)"$/ do |string, color|
25
+ assert_partial_output(string.color(color.to_sym).bright, all_output)
26
+ end
27
+ Then /^it should output "([^"]*)" in "([^"]*)"$/ do |string, color|
28
+ assert_partial_output(string.color(color.to_sym), all_output)
29
+ end
30
+
31
+ Then /^it should pass with todays date$/ do
32
+ today = DateTime.now.strftime("%Y-%m-%d")
33
+ step "it should pass with regex:", ".*#{today}.*"
34
+ end
@@ -0,0 +1,5 @@
1
+ require "rainbow"
2
+
3
+ Before('@ansi') do
4
+ ENV["FORCE_COLORS"] = "TRUE"
5
+ end
@@ -0,0 +1,9 @@
1
+ require 'aruba/cucumber'
2
+
3
+ # Temporarily enforce an isolated, fake, homedir.
4
+ Around do |scenario, block|
5
+ @__aruba_original_home = ENV["HOME"]
6
+ ENV["HOME"] = File.expand_path(File.join("tmp", "aruba"))
7
+ block.call
8
+ ENV["HOME"] = @__aruba_original_home
9
+ end
@@ -0,0 +1 @@
1
+ require "debugger"
@@ -0,0 +1,54 @@
1
+ Feature: Undo
2
+
3
+ So that I can fix mistakes
4
+ As a user
5
+ I want to mark items as not done
6
+
7
+ Background:
8
+ Given a default config exists
9
+ Given a todofile with the following items exists:
10
+ | todo |
11
+ | x 2013-01-01 Install todotxt @cli +todotxt |
12
+ | x Read documentation +todotxt |
13
+ | 2012-12-12 Buy GTD book @amazon +wishlist |
14
+
15
+ Scenario: Undo a single item reports it back and marks it as not done in the file
16
+ When I run `todotxt undo 2`
17
+ Then it should pass with:
18
+ """
19
+ 2. Read documentation +todotxt
20
+ """
21
+ And the file "todo.txt" should contain exactly:
22
+ """
23
+ x 2013-01-01 Install todotxt @cli +todotxt
24
+ Read documentation +todotxt
25
+ 2012-12-12 Buy GTD book @amazon +wishlist
26
+ """
27
+
28
+ Scenario: Undo multiple items
29
+ When I run `todotxt undo 1 2`
30
+ Then it should pass with:
31
+ """
32
+ 1. 2013-01-01 Install todotxt @cli +todotxt
33
+ 2. Read documentation +todotxt
34
+ """
35
+ And the file "todo.txt" should contain exactly:
36
+ """
37
+ 2013-01-01 Install todotxt @cli +todotxt
38
+ Read documentation +todotxt
39
+ 2012-12-12 Buy GTD book @amazon +wishlist
40
+ """
41
+
42
+ Scenario: Undo an item that was not marked as done
43
+ When I run `todotxt undo 3`
44
+ Then it should pass with:
45
+ """
46
+ 3. 2012-12-12 Buy GTD book @amazon +wishlist
47
+ """
48
+
49
+ Scenario: Undo invalid items
50
+ When I run `todotxt undo 1337`
51
+ Then it should pass with:
52
+ """
53
+ ERROR: No todo found at line 1337
54
+ """
data/lib/todotxt/cli.rb CHANGED
@@ -1,10 +1,9 @@
1
1
  require "thor"
2
2
  require "rainbow"
3
+ require "chronic"
3
4
  require "parseconfig"
4
5
 
5
6
  module Todotxt
6
- CFG_PATH = File.expand_path("~/.todotxt.cfg")
7
-
8
7
  class CLI < Thor
9
8
  include Thor::Actions
10
9
  include Todotxt::CLIHelpers
@@ -15,14 +14,31 @@ module Todotxt
15
14
 
16
15
  def initialize(*args)
17
16
  super
17
+ # Allow testing colors, rainbow usually detects whether
18
+ # the output goes to a TTY, but Aruba/Cucumber is not a
19
+ # TTY, so we enforce it here, based on an environment var
20
+ Sickill::Rainbow.enabled = true if ENV["FORCE_COLORS"] == "TRUE"
21
+ @config = Config.new
22
+ @list = nil
23
+ unless ["help", "generate_config", "generate_txt"].include? ARGV[0]
24
+ ask_and_create @config unless @config.file_exists?
25
+ if @config.deprecated? and options[:file]
26
+ error_and_exit "You are using an old config, which has no support for mulitple files. Please update your configuration."
27
+ end
18
28
 
19
- unless ["help", "generate_config"].include? ARGV[0]
20
- parse_config
21
-
22
- @list = TodoList.new @txt_path
29
+ parse_conf
30
+ ask_and_create @file unless @file.exists?
31
+ @list = TodoList.new @file
23
32
  end
33
+
24
34
  end
25
35
 
36
+ class_option :file, :type => :string, :desc => "Use a different file than todo.txt
37
+ E.g. use 'done' to have the action performed on the file you set for 'done' in the todotxt
38
+ configuration under [files]."
39
+
40
+ default_task :list
41
+
26
42
  #
27
43
  # Listing
28
44
  #
@@ -31,12 +47,7 @@ module Todotxt
31
47
  method_option :done, :type => :boolean, :aliases => "-d", :desc => "Include todo items that have been marked as done"
32
48
  method_option :simple, :type => :boolean, :desc => "Simple output (for scripts, etc)"
33
49
  def list search=""
34
- with_done = false
35
-
36
- with_done = true if options[:done]
37
-
38
- @list.filter(search, :with_done => with_done)
39
-
50
+ @list.filter(search, :with_done => (options[:done] ? true : false))
40
51
  render_list :simple => !!options[:simple]
41
52
  end
42
53
  map "ls" => :list
@@ -61,6 +72,24 @@ module Todotxt
61
72
  end
62
73
  map "lsc" => :lscon
63
74
 
75
+ desc "due", "List due items"
76
+ def due
77
+ if ENV["date"] # Allow testing to "freeze" the date
78
+ today = DateTime.parse(ENV["date"]).to_date
79
+ else
80
+ today = DateTime.now.to_date
81
+ end
82
+
83
+ puts "Due today (#{today.strftime("%Y-%m-%d")})".bright
84
+ @list.on_date(today).each { |todo| puts format_todo(todo) }
85
+ puts "\nPast-due items".bright
86
+ @list.before_date(today).each { |todo| puts format_todo(todo) }
87
+ puts "\nDue 7 days in advance".bright
88
+ ((today+1)..(today+7)).each do |day|
89
+ @list.on_date(day).each { |todo| puts format_todo(todo) }
90
+ end
91
+ end
92
+
64
93
  #
65
94
  # Todo management
66
95
  #
@@ -201,21 +230,72 @@ module Todotxt
201
230
  end
202
231
  map "rm" => :del
203
232
 
233
+ desc "edit", "Open todo.txt file in your default editor"
234
+ def edit
235
+ system "#{@editor} #{@file.path}"
236
+ end
237
+
238
+ desc "move | mv ITEM#[, ITEM#, ITEM#, ...] file", "Move ITEM# to another file"
239
+ def move line1, *lines, other_list_alias
240
+ if @files[other_list_alias.to_sym].nil?
241
+ error_and_exit "File alias #{other_list_alias} not found"
242
+ else
243
+ other_list = TodoList.new @files[other_list_alias.to_sym]
244
+ end
245
+
246
+ lines.unshift(line1).each do |line|
247
+ todo = @list.find_by_line line
248
+ if todo
249
+ say format_todo(todo)
250
+ @list.move line, other_list
251
+ notice "Moved to #{other_list}"
252
+
253
+ other_list.save
254
+ @list.save
255
+ else
256
+ error "No todo found at line #{line}"
257
+ end
258
+ end
259
+ end
260
+ map "mv" => :move
261
+
262
+ desc "move | mv ITEM#[, ITEM#, ITEM#, ...] file", "Move ITEM# to another file"
263
+ def move line1, *lines, other_list_alias
264
+ if @files[other_list_alias.to_sym].nil?
265
+ error_and_exit "File alias #{other_list_alias} not found"
266
+ else
267
+ other_list = TodoList.new @files[other_list_alias.to_sym]
268
+ end
269
+
270
+ lines.unshift(line1).each do |line|
271
+ todo = @list.find_by_line line
272
+ if todo
273
+ say format_todo(todo)
274
+ @list.move line, other_list
275
+ notice "Moved to #{other_list}"
276
+
277
+ other_list.save
278
+ @list.save
279
+ else
280
+ error "No todo found at line #{line}"
281
+ end
282
+ end
283
+ end
284
+ map "mv" => :move
285
+
204
286
  #
205
287
  # File generation
206
288
  #
207
289
 
208
290
  desc "generate_config", "Create a .todotxt.cfg file in your home folder, containing the path to todo.txt"
209
291
  def generate_config
210
- copy_file "todotxt.cfg", CFG_PATH
292
+ copy_file "todotxt.cfg", Config.config_path
211
293
  puts ""
212
-
213
- parse_config
214
294
  end
215
295
 
216
296
  desc "generate_txt", "Create a sample todo.txt"
217
297
  def generate_txt
218
- copy_file "todo.txt", @txt_path
298
+ copy_file "todo.txt", @file
219
299
  puts ""
220
300
  end
221
301
 
@@ -229,7 +309,6 @@ module Todotxt
229
309
  end
230
310
 
231
311
  private
232
-
233
312
  def render_list opts={}
234
313
  numsize = @list.count + 1
235
314
  numsize = numsize.to_s.length + 0
@@ -247,43 +326,50 @@ module Todotxt
247
326
  end
248
327
  end
249
328
 
250
- def parse_config
251
- unless File.exist? CFG_PATH
252
- puts "You need a .todotxt.cfg file in your home folder to continue (used to determine the path of your todo.txt.) Answer yes to have it generated for you (pointing to ~/todo.txt), or no to create it yourself.\n\n"
253
- confirm_generate = yes? "Create ~/.todotxt.cfg? [y/N]"
329
+ # File should respond_to "basename", "path" and "generate!"
330
+ def ask_and_create file
331
+ puts "#{file.basename} doesn't exist yet. Would you like to generate a sample file?"
332
+ confirm_generate = yes? "Create #{file.path}? [y/N]"
254
333
 
255
- if confirm_generate
256
- generate_config
257
- else
258
- puts ""
259
- exit
260
- end
334
+ if confirm_generate
335
+ file.generate!
336
+ else
337
+ puts ""
338
+ exit
261
339
  end
340
+ end
262
341
 
263
- cfg = ParseConfig.new(CFG_PATH)
264
-
265
- txt = cfg["todo_txt_path"]
266
-
267
- if txt
268
- @txt_path = File.expand_path(txt)
342
+ def parse_conf
343
+ @files = {}
269
344
 
270
- unless File.exist? @txt_path
271
- puts "#{txt} doesn't exist yet. Would you like to generate a sample file?"
272
- confirm_generate = yes? "Create #{txt}? [y/N]"
345
+ return if @config.nil?
273
346
 
274
- if confirm_generate
275
- generate_txt
276
- else
277
- puts ""
278
- exit
347
+ # Backwards compatibility with todo_txt_path
348
+ # when old variable is still set, and no files=>todo
349
+ # given, fallback to this old version.
350
+ if @config["todo_txt_path"]
351
+ @files[:todo] ||= TodoFile.new(@config["todo_txt_path"])
352
+ else
353
+ # Fill the @files from settings.
354
+ @config["files"].each do |name, file_path|
355
+ unless file_path.empty?
356
+ @files[name.to_sym] = TodoFile.new(file_path)
279
357
  end
280
358
  end
359
+ end
360
+
361
+ # Determine what file should be activated, set that in @file
362
+ if options[:file]
363
+ file_sym = options[:file].to_sym
364
+ if @files.has_key? file_sym
365
+ @file = @files[file_sym]
366
+ end
281
367
  else
282
- error "Couldn't find todo_txt_path setting in ~/.todotxt.cfg."
283
- puts "Please run the following to create a new configuration file:"
284
- puts " todotxt generate_config"
285
- exit
368
+ @file = @files[:todo]
286
369
  end
370
+
371
+ # Determine the editor
372
+ @editor = @config["editor"] || ENV["EDITOR"]
287
373
  end
288
374
  end
289
375
  end
@@ -3,7 +3,6 @@ module Todotxt
3
3
 
4
4
  def format_todo(todo, number_padding=nil)
5
5
  line = todo.line.to_s
6
-
7
6
  if number_padding
8
7
  line = line.rjust number_padding
9
8
  end
@@ -50,5 +49,9 @@ module Todotxt
50
49
  puts "ERROR: #{message}".color(:red)
51
50
  end
52
51
 
52
+ def error_and_exit message =""
53
+ error message
54
+ exit
55
+ end
53
56
  end
54
57
  end
@@ -0,0 +1,58 @@
1
+ require "parseconfig"
2
+ require "fileutils"
3
+
4
+ module Todotxt
5
+ class Config < ParseConfig
6
+ def initialize config_file = ""
7
+ if config_file.empty?
8
+ @config_file = Config.config_path
9
+ else
10
+ @config_file = config_file
11
+ end
12
+
13
+ if file_exists?
14
+ super @config_file
15
+ validate
16
+ else
17
+ @params = {}
18
+ @groups = []
19
+ end
20
+ end
21
+
22
+ def file_exists?
23
+ File.exists? @config_file
24
+ end
25
+
26
+ def files
27
+ params["files"] || {"todo" => params["todo_txt_path"] }
28
+ end
29
+
30
+ def generate!
31
+ FileUtils.copy File.join(File.dirname(File.expand_path(__FILE__)), "..", "..", "conf", "todotxt.cfg"), @config_file
32
+ import_config
33
+ end
34
+
35
+ def path
36
+ @config_file
37
+ end
38
+
39
+ def basename
40
+ File.basename @config_file
41
+ end
42
+
43
+ def self.config_path
44
+ File.join ENV["HOME"], ".todotxt.cfg"
45
+ end
46
+
47
+ def deprecated?
48
+ params["files"].nil?
49
+ end
50
+
51
+ private
52
+ def validate
53
+ if params["files"] && params["todo_txt_path"]
54
+ raise "Bad configuration file: use either files or todo_txt_path"
55
+ end
56
+ end
57
+ end
58
+ end
data/lib/todotxt/regex.rb CHANGED
@@ -2,5 +2,6 @@ module Todotxt
2
2
  PRIORITY_REGEX = /^\(([A-Z])\) /
3
3
  PROJECT_REGEX = /(\+\w+)/
4
4
  CONTEXT_REGEX = /(@\w+)/
5
+ DATE_REGEX = /^(\([A-Z]\) )?(x )?((\d{4}-)(\d{1,2}-)(\d{1,2}))\s?/
5
6
  DONE_REGEX = /^(\([A-Z]\) )?x /
6
7
  end
data/lib/todotxt/todo.rb CHANGED
@@ -24,6 +24,11 @@ module Todotxt
24
24
  @done = !text.scan(DONE_REGEX).empty?
25
25
  end
26
26
 
27
+ def due
28
+ date = Chronic.parse(text.scan(DATE_REGEX).flatten[2])
29
+ date.nil? ? nil : date.to_date
30
+ end
31
+
27
32
  def do
28
33
  unless done
29
34
  @text = "x #{text}".strip
@@ -0,0 +1,40 @@
1
+ module Todotxt
2
+ class TodoFile
3
+
4
+ def initialize path
5
+ @path = File.expand_path(path)
6
+ end
7
+
8
+ # Generate a file from template
9
+ def generate!
10
+ FileUtils.copy File.join(File.dirname(File.expand_path(__FILE__)), "..", "..", "conf", "todo.txt"), @path
11
+ end
12
+
13
+ def path
14
+ @path
15
+ end
16
+
17
+ def basename
18
+ File.basename @path
19
+ end
20
+
21
+ def exists?
22
+ File.exists? File.expand_path(@path)
23
+ end
24
+
25
+ def self.from_key(key)
26
+ config = Todotxt::Config.new
27
+ if config.files.has_key? key
28
+ path = config.files[key]
29
+ self.new path
30
+ else
31
+ raise "Key not found in config"
32
+ end
33
+ end
34
+
35
+
36
+ def to_s
37
+ @path
38
+ end
39
+ end
40
+ end