todotxt 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +2 -0
- data/README.md +1 -0
- data/bin/todotxt +3 -3
- data/conf/todotxt.cfg +13 -1
- data/cucumber.yml +3 -0
- data/features/add.feature +24 -0
- data/features/append.feature +28 -0
- data/features/backwards.feature +28 -0
- data/features/colors.feature +51 -0
- data/features/del.feature +52 -0
- data/features/depri.feature +38 -0
- data/features/do.feature +47 -0
- data/features/due.feature +49 -0
- data/features/edit.feature +31 -0
- data/features/generate_config.feature +19 -0
- data/features/generate_txt.feature +20 -0
- data/features/initialize.feature +73 -0
- data/features/list.feature +132 -0
- data/features/move.feature +33 -0
- data/features/prepend.feature +28 -0
- data/features/pri.feature +40 -0
- data/features/replace.feature +28 -0
- data/features/step_definitions/environment_steps.rb +47 -0
- data/features/step_definitions/list_steps.rb +34 -0
- data/features/support/ansi.rb +5 -0
- data/features/support/aruba.rb +9 -0
- data/features/support/debugger.rb +1 -0
- data/features/undo.feature +54 -0
- data/lib/todotxt/cli.rb +131 -45
- data/lib/todotxt/clihelpers.rb +4 -1
- data/lib/todotxt/config.rb +58 -0
- data/lib/todotxt/regex.rb +1 -0
- data/lib/todotxt/todo.rb +5 -0
- data/lib/todotxt/todofile.rb +40 -0
- data/lib/todotxt/todolist.rb +20 -2
- data/lib/todotxt/version.rb +1 -1
- data/lib/todotxt.rb +2 -0
- data/spec/cli_spec.rb +6 -0
- data/spec/config_spec.rb +52 -0
- data/spec/fixtures/config_both.cfg +4 -0
- data/spec/fixtures/config_new.cfg +2 -0
- data/spec/fixtures/config_old.cfg +1 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/todo_spec.rb +12 -0
- data/spec/todofile_spec.rb +31 -0
- data/spec/todolist_spec.rb +20 -2
- data/todotxt.gemspec +4 -0
- 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,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
|
-
|
20
|
-
|
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
|
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",
|
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", @
|
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
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
end
|
334
|
+
if confirm_generate
|
335
|
+
file.generate!
|
336
|
+
else
|
337
|
+
puts ""
|
338
|
+
exit
|
261
339
|
end
|
340
|
+
end
|
262
341
|
|
263
|
-
|
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
|
-
|
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
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
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
|
-
|
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
|
data/lib/todotxt/clihelpers.rb
CHANGED
@@ -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
data/lib/todotxt/todo.rb
CHANGED
@@ -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
|