todotxt 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/.gitignore +2 -0
- data/README.md +40 -18
- data/Rakefile +1 -4
- data/bin/todotxt +5 -5
- data/features/edit.feature +1 -1
- data/features/files.feature +53 -0
- data/features/initialize.feature +0 -11
- data/features/move.feature +13 -0
- data/features/step_definitions/environment_steps.rb +8 -4
- data/features/step_definitions/list_steps.rb +5 -1
- data/lib/todotxt.rb +9 -8
- data/lib/todotxt/cli.rb +96 -142
- data/lib/todotxt/clihelpers.rb +21 -24
- data/lib/todotxt/config.rb +45 -16
- data/lib/todotxt/regex.rb +5 -5
- data/lib/todotxt/todo.rb +44 -30
- data/lib/todotxt/todofile.rb +11 -11
- data/lib/todotxt/todolist.rb +31 -19
- data/lib/todotxt/version.rb +1 -1
- data/spec/config_spec.rb +41 -21
- data/spec/fixtures/config_no_todo.cfg +2 -0
- data/spec/todo_spec.rb +77 -90
- data/spec/todofile_spec.rb +17 -12
- data/spec/todolist_spec.rb +65 -66
- data/todotxt.gemspec +19 -21
- metadata +50 -61
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
ZGU5YTU3YjIwNmU3YTNmNzg4ZTlhNDczMmJjZGI5YTE2OTFkY2JmYTM3MDNm
|
10
|
-
MTBhNjliYThhOTk4YjdmODM1ZGM4MTEyYmQwNzRkMDU0Y2IzNjVjMTg3YjBh
|
11
|
-
ZTdiZDIyMjZiODg3YjAzMzRhZmM0YjdjNGFkYzZmNjA4Y2JlOTI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjFiMTU5YzIxNjMxMTZlZTlhZmIxYTRmZmFkMTAzMzY3NmM2OGQ2NDJjYWY3
|
14
|
-
N2ExMDgwZThjMGJhODk0NmJmNTM5Nzc0N2IxNTJiMWM1ODcwYzY5ZjFlMDAy
|
15
|
-
NWI0MmEwNjcxMzNmMDJlNjZlMWY4ZTM1NGEwNGQwOWEyZDU2YjA=
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 21a772c6a03508479892cd47bd8b75e9d6161a369340d9d42991ffac17c18267
|
4
|
+
data.tar.gz: 9f8ee70e7841c6684360964dbcd3dfc23be934fdcfc314160073d5dda66244cf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f6fc1646f58339be5635fb1021301374dbb4a524de107b0689c3910cadffcf757e392de8c7aa61e4745ecb82425f00acd70f5f128a7b393597cfd9a6a1f92249
|
7
|
+
data.tar.gz: 1f180c48442d392b95b6875fe27d4cd8fd8f6941c4825a4c38be05d3343cdf5c77ff4e809900846ee7c7f5cbb7550225cc94dfdcff7c1b813fd8a253d90e5d21
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -38,27 +38,49 @@ The gem will install a command, `todotxt` which is used to interact with your
|
|
38
38
|
todo.txt.
|
39
39
|
|
40
40
|
Tasks:
|
41
|
-
todotxt add | a TEXT
|
42
|
-
todotxt append | app ITEM# STRING
|
43
|
-
todotxt del | rm ITEM#[, ITEM#, ITEM#, ...]
|
44
|
-
todotxt do ITEM#[, ITEM#, ITEM#, ...]
|
45
|
-
todotxt dp | depri ITEM#[, ITEM#, ITEM#, ...]
|
46
|
-
todotxt
|
47
|
-
todotxt
|
48
|
-
todotxt generate_config
|
49
|
-
todotxt
|
50
|
-
todotxt
|
51
|
-
todotxt
|
52
|
-
todotxt
|
53
|
-
todotxt
|
54
|
-
todotxt
|
55
|
-
todotxt
|
56
|
-
todotxt
|
57
|
-
todotxt
|
58
|
-
todotxt
|
41
|
+
todotxt add | a TEXT # Add a new Todo item
|
42
|
+
todotxt append | app ITEM# STRING # Append STRING to ITEM#
|
43
|
+
todotxt del | rm ITEM#[, ITEM#, ITEM#, ...] # Remove ITEM#
|
44
|
+
todotxt do ITEM#[, ITEM#, ITEM#, ...] # Mark ITEM# as done
|
45
|
+
todotxt dp | depri ITEM#[, ITEM#, ITEM#, ...] # Remove priority for ITEM#
|
46
|
+
todotxt due # List due items
|
47
|
+
todotxt edit # Open todo.txt file in your default editor
|
48
|
+
todotxt generate_config # Create a .todotxt.cfg file in your home folder, containing the path to todo.txt
|
49
|
+
todotxt generate_txt # Create a sample todo.txt
|
50
|
+
todotxt help [TASK] # Describe available tasks or one specific task
|
51
|
+
todotxt list | ls [SEARCH] # List all todos, or todos matching SEARCH
|
52
|
+
todotxt listproj | lsproj # List all projects
|
53
|
+
todotxt lscon | lsc # List all contexts
|
54
|
+
todotxt lsdone | lsd # List all done items
|
55
|
+
todotxt move | mv ITEM#[, ITEM#, ITEM#, ...] file # Move ITEM# to another file
|
56
|
+
todotxt prepend | prep ITEM# STRING # Prepend STRING to ITEM#
|
57
|
+
todotxt pri | p ITEM# PRIORITY # Set priority of ITEM# to PRIORITY
|
58
|
+
todotxt replace ITEM# TEXT # Completely replace ITEM# text with TEXT
|
59
|
+
todotxt undo | u ITEM#[, ITEM#, ITEM#, ...] # Mark ITEM# item as not done
|
60
|
+
todotxt version # Show todotxt version
|
59
61
|
|
60
62
|
Calling simply `todotxt` will automatically run the `ls` command.
|
61
63
|
|
64
|
+
You can pass the option `--file=` to point todotxt to another file. You
|
65
|
+
can pass an alias, defined in the configuration, or the path to an
|
66
|
+
arbitrary file.
|
67
|
+
|
68
|
+
With a file wishlist, in the configuration defined as "wishlist", you
|
69
|
+
can run:
|
70
|
+
|
71
|
+
todotxt ls --file=wishlist
|
72
|
+
|
73
|
+
To list all items form this wishlist file. Alternatively you can run:
|
74
|
+
|
75
|
+
todotxt ls --file="~/Dropbox/todo/deferred.txt"
|
76
|
+
|
77
|
+
To list all items from the file deferred.txt, provided that file
|
78
|
+
exists.
|
79
|
+
|
80
|
+
In order to list all items from all files defined in the config, use the
|
81
|
+
`--all` flag with ls:
|
82
|
+
|
83
|
+
todotxt ls --all
|
62
84
|
|
63
85
|
## Screenshot
|
64
86
|
|
data/Rakefile
CHANGED
data/bin/todotxt
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
libdir = File.join(File.dirname(File.dirname(__FILE__)),
|
3
|
+
libdir = File.join(File.dirname(File.dirname(__FILE__)), 'lib')
|
4
4
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
5
5
|
|
6
6
|
args = ARGV.clone
|
7
7
|
|
8
|
-
#if args.empty?
|
9
|
-
|
10
|
-
#end
|
8
|
+
# if args.empty?
|
9
|
+
# args.push "ls"
|
10
|
+
# end
|
11
11
|
|
12
|
-
require
|
12
|
+
require 'todotxt'
|
13
13
|
Todotxt::CLI.start(args)
|
data/features/edit.feature
CHANGED
@@ -13,7 +13,7 @@ Feature: Edit
|
|
13
13
|
| 2012-12-12 Buy GTD book @amazon +wishlist |
|
14
14
|
|
15
15
|
Scenario: Open the file in the systems editor
|
16
|
-
Given the
|
16
|
+
Given the environment variable "EDITOR" is set to "echo"
|
17
17
|
And a default config exists
|
18
18
|
When I run `todotxt edit`
|
19
19
|
Then it should pass with:
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Feature: Files
|
2
|
+
|
3
|
+
So that I can organise my Todo-items better
|
4
|
+
As a user
|
5
|
+
I want to use different 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
|
+
| Read book on GTD |
|
15
|
+
| Publish wishlist on site |
|
16
|
+
And a todofile named "wishlist.txt" with the following items exists:
|
17
|
+
| todo |
|
18
|
+
| Getting Things Done @bookstore |
|
19
|
+
| Label Maker @officesupply |
|
20
|
+
|
21
|
+
Scenario: Run list with --files option
|
22
|
+
When I run `todotxt list --file=wishlist`
|
23
|
+
Then it should pass with:
|
24
|
+
"""
|
25
|
+
Getting Things Done @bookstore
|
26
|
+
"""
|
27
|
+
|
28
|
+
Scenario: Provide a file that is not in the config
|
29
|
+
When I run `todotxt list --file=doesnotexist` interactively
|
30
|
+
Then it should fail with:
|
31
|
+
"""
|
32
|
+
\"doesnotexist\" is not defined in the config
|
33
|
+
"""
|
34
|
+
|
35
|
+
Scenario: Run list with --files option and a filename for a file not in the config
|
36
|
+
Given a todofile named "deferred.txt" with the following items exists:
|
37
|
+
| todo |
|
38
|
+
| Getting Things Done @bookstore |
|
39
|
+
When I run `todotxt list --file=./deferred.txt`
|
40
|
+
Then it should pass with:
|
41
|
+
"""
|
42
|
+
Getting Things Done @bookstore
|
43
|
+
"""
|
44
|
+
|
45
|
+
Scenario: List entries from all files
|
46
|
+
When I run `todotxt list --all`
|
47
|
+
Then it should pass with:
|
48
|
+
"""
|
49
|
+
1. Read book on GTD
|
50
|
+
2. Publish wishlist on site
|
51
|
+
3. Getting Things Done @bookstore
|
52
|
+
4. Label Maker @officesupply
|
53
|
+
"""
|
data/features/initialize.feature
CHANGED
@@ -60,14 +60,3 @@ Feature: Initialize
|
|
60
60
|
When I run `todotxt` interactively
|
61
61
|
And I type "no"
|
62
62
|
Then a file named "todo.txt" should not exist
|
63
|
-
|
64
|
-
Scenario: Running with an old config-file still works
|
65
|
-
Given an old config exists
|
66
|
-
And a todofile with the following items exists:
|
67
|
-
| todo |
|
68
|
-
| Update my config file |
|
69
|
-
When I run `todotxt`
|
70
|
-
Then it should pass with:
|
71
|
-
"""
|
72
|
-
1. Update my config file
|
73
|
-
"""
|
data/features/move.feature
CHANGED
@@ -25,6 +25,19 @@ Feature: move
|
|
25
25
|
And the file "todo.txt" should not contain "Getting Things Done @bookstore"
|
26
26
|
And the file "wishlist.txt" should contain "Getting Things Done @bookstore"
|
27
27
|
|
28
|
+
Scenario: Move an item from wishlist.txt to todo.txt
|
29
|
+
Given a todofile named "wishlist.txt" with the following items exists:
|
30
|
+
| todo |
|
31
|
+
| x Archive todotxt @gtd |
|
32
|
+
When I run `todotxt move 1 todo --file=wishlist`
|
33
|
+
Then it should pass with:
|
34
|
+
"""
|
35
|
+
1. x Archive todotxt @gtd
|
36
|
+
=> Moved to todo.txt
|
37
|
+
"""
|
38
|
+
And the file "wishlist.txt" should not contain "x Archive todotxt @gtd"
|
39
|
+
And the file "todo.txt" should contain "x Archive todotxt @gtd"
|
40
|
+
|
28
41
|
Scenario: Move an illegal item
|
29
42
|
When I run `todotxt move 1337 wishlist`
|
30
43
|
Then it should pass with:
|
@@ -29,19 +29,23 @@ Given /^a todofile with done items exists$/ do
|
|
29
29
|
write_file("todo.txt", "Read documentation for todotxt\nx Install todotxt\nWrite cucumber steps for todotxt")
|
30
30
|
end
|
31
31
|
|
32
|
-
Given /^a todofile with the following items exists:$/ do |todolist|
|
32
|
+
Given /^a todofile named "(.*?)" with the following items exists:$/ do |filename, todolist|
|
33
33
|
contents = todolist.hashes.map {|row| row["todo"] }.join("\n")
|
34
|
-
write_file(
|
34
|
+
write_file(filename, contents)
|
35
|
+
end
|
36
|
+
|
37
|
+
Given /^a todofile with the following items exists:$/ do |todolist|
|
38
|
+
step %{a todofile named "todo.txt" with the following items exists:}, todolist
|
35
39
|
end
|
36
40
|
|
37
41
|
Given /^an empty todofile named "(.*?)" exists$/ do |filename|
|
38
42
|
write_file(filename, "")
|
39
43
|
end
|
40
44
|
|
41
|
-
Given /^the
|
45
|
+
Given /^the environment variable "(.*?)" is set to "(.*?)"$/ do |name, value|
|
42
46
|
ENV[name] = value
|
43
47
|
end
|
44
48
|
|
45
49
|
Given /^the date is "(.*?)"$/ do |date|
|
46
|
-
step %{the
|
50
|
+
step %{the environment variable "date" is set to "#{date}"}
|
47
51
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
Then /^I should see all entries from the todofile with numbers$/ do
|
2
|
+
step %{I should see all entries from the todofile named "todo.txt" with numbers}
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^I should see all entries from the todofile named "([^"]*)" with numbers$/ do |filename|
|
2
6
|
contents = ""
|
3
|
-
File.open(File.join(ENV["HOME"],
|
7
|
+
File.open(File.join(ENV["HOME"], filename)).each_line do |line|
|
4
8
|
# matching "1. Do Something"
|
5
9
|
contents += "([\\d]\.\\s+)#{Regexp.escape(line.strip)}.*"
|
6
10
|
end
|
data/lib/todotxt.rb
CHANGED
@@ -2,14 +2,15 @@
|
|
2
2
|
libdir = File.dirname(__FILE__)
|
3
3
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
4
4
|
|
5
|
+
# Todotxt is a Ruby librairy / CLI interface to work with [todo.txt](http://www.todotxt.com) format files.
|
5
6
|
module Todotxt
|
6
|
-
autoload :Todo,
|
7
|
-
autoload :TodoList,
|
8
|
-
autoload :TodoFile,
|
9
|
-
autoload :CLI,
|
10
|
-
autoload :CLIHelpers,
|
11
|
-
autoload :Config,
|
7
|
+
autoload :Todo, 'todotxt/todo'
|
8
|
+
autoload :TodoList, 'todotxt/todolist'
|
9
|
+
autoload :TodoFile, 'todotxt/todofile'
|
10
|
+
autoload :CLI, 'todotxt/cli'
|
11
|
+
autoload :CLIHelpers, 'todotxt/clihelpers'
|
12
|
+
autoload :Config, 'todotxt/config'
|
12
13
|
end
|
13
14
|
|
14
|
-
require
|
15
|
-
require
|
15
|
+
require 'todotxt/regex'
|
16
|
+
require 'todotxt/version'
|
data/lib/todotxt/cli.rb
CHANGED
@@ -1,39 +1,41 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'thor'
|
2
|
+
require 'rainbow'
|
3
|
+
require 'chronic'
|
4
|
+
require 'parseconfig'
|
5
5
|
|
6
6
|
module Todotxt
|
7
|
+
CFG_PATH = File.expand_path('~/.todotxt.cfg')
|
8
|
+
|
7
9
|
class CLI < Thor
|
8
10
|
include Thor::Actions
|
9
11
|
include Todotxt::CLIHelpers
|
10
12
|
|
11
13
|
def self.source_root
|
12
|
-
File.join File.dirname(__FILE__),
|
14
|
+
File.join File.dirname(__FILE__), '..', '..', 'conf'
|
13
15
|
end
|
14
16
|
|
15
17
|
def initialize(*args)
|
16
18
|
super
|
17
19
|
# Allow testing colors, rainbow usually detects whether
|
18
|
-
# the output goes to a TTY, but Aruba/Cucumber is not a
|
20
|
+
# the output goes to a TTY, but Aruba/Cucumber is not a
|
19
21
|
# TTY, so we enforce it here, based on an environment var
|
20
|
-
Sickill::Rainbow.enabled = true if ENV[
|
21
|
-
|
22
|
+
Sickill::Rainbow.enabled = true if ENV['FORCE_COLORS'] == 'TRUE'
|
23
|
+
|
24
|
+
# Open config file and render config.
|
25
|
+
@config = Config.new options
|
22
26
|
@list = nil
|
23
|
-
unless [
|
27
|
+
unless %w[help generate_config generate_txt].include? ARGV[0]
|
24
28
|
ask_and_create @config unless @config.file_exists?
|
25
|
-
if @config.deprecated?
|
26
|
-
error_and_exit
|
29
|
+
if @config.deprecated? && options[:file]
|
30
|
+
error_and_exit 'You are using an old config, which has no support for multiple files. Please update your configuration.'
|
27
31
|
end
|
28
32
|
|
29
|
-
|
30
|
-
|
31
|
-
@list = TodoList.new @file
|
33
|
+
ask_and_create @config.file unless @config.file.exists?
|
34
|
+
@list = TodoList.new @config.file
|
32
35
|
end
|
33
|
-
|
34
36
|
end
|
35
37
|
|
36
|
-
class_option :file, :
|
38
|
+
class_option :file, type: :string, desc: "Use a different file than todo.txt
|
37
39
|
E.g. use 'done' to have the action performed on the file you set for 'done' in the todotxt
|
38
40
|
configuration under [files]."
|
39
41
|
|
@@ -43,49 +45,57 @@ module Todotxt
|
|
43
45
|
# Listing
|
44
46
|
#
|
45
47
|
|
46
|
-
desc
|
47
|
-
method_option :done, :
|
48
|
-
method_option :simple, :
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
desc 'list | ls [SEARCH]', 'List all todos, or todos matching SEARCH'
|
49
|
+
method_option :done, type: :boolean, aliases: '-d', desc: 'Include todo items that have been marked as done'
|
50
|
+
method_option :simple, type: :boolean, desc: 'Simple output (for scripts, etc)'
|
51
|
+
method_option :all, type: :boolean, aliases: '-a', desc: 'List items from all files'
|
52
|
+
def list(search = '')
|
53
|
+
if options[:all]
|
54
|
+
@config.files.each do |file|
|
55
|
+
count = @list.todos.count || 0
|
56
|
+
@list.todos += TodoList.new(file[1], count).todos unless file[0] == 'todo'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
@list.filter(search, with_done: (options[:done] ? true : false))
|
61
|
+
render_list simple: !!options[:simple]
|
52
62
|
end
|
53
|
-
map
|
63
|
+
map 'ls' => :list
|
54
64
|
|
55
|
-
desc
|
56
|
-
def lsdone
|
57
|
-
@list.filter(search, :
|
65
|
+
desc 'lsdone | lsd', 'List all done items'
|
66
|
+
def lsdone(search = '')
|
67
|
+
@list.filter(search, only_done: true)
|
58
68
|
|
59
69
|
render_list
|
60
70
|
end
|
61
|
-
map
|
71
|
+
map 'lsd' => :lsdone
|
62
72
|
|
63
|
-
desc
|
73
|
+
desc 'listproj | lsproj', 'List all projects'
|
64
74
|
def listproj
|
65
75
|
@list.projects.each { |p| say p }
|
66
76
|
end
|
67
|
-
map
|
77
|
+
map 'lsproj' => :listproj
|
68
78
|
|
69
|
-
desc
|
79
|
+
desc 'lscon | lsc', 'List all contexts'
|
70
80
|
def lscon
|
71
81
|
@list.contexts.each { |c| say c }
|
72
82
|
end
|
73
|
-
map
|
83
|
+
map 'lsc' => :lscon
|
74
84
|
|
75
|
-
desc
|
85
|
+
desc 'due', 'List due items'
|
76
86
|
def due
|
77
|
-
if ENV[
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
87
|
+
today = if ENV['date'] # Allow testing to "freeze" the date
|
88
|
+
DateTime.parse(ENV['date']).to_date
|
89
|
+
else
|
90
|
+
DateTime.now.to_date
|
91
|
+
end
|
82
92
|
|
83
|
-
puts "Due today (#{today.strftime(
|
93
|
+
puts "Due today (#{today.strftime('%Y-%m-%d')})".bright
|
84
94
|
@list.on_date(today).each { |todo| puts format_todo(todo) }
|
85
95
|
puts "\nPast-due items".bright
|
86
96
|
@list.before_date(today).each { |todo| puts format_todo(todo) }
|
87
97
|
puts "\nDue 7 days in advance".bright
|
88
|
-
((today+1)..(today+7)).each do |day|
|
98
|
+
((today + 1)..(today + 7)).each do |day|
|
89
99
|
@list.on_date(day).each { |todo| puts format_todo(todo) }
|
90
100
|
end
|
91
101
|
end
|
@@ -94,7 +104,7 @@ module Todotxt
|
|
94
104
|
# Todo management
|
95
105
|
#
|
96
106
|
|
97
|
-
desc
|
107
|
+
desc 'add | a TEXT', 'Add a new Todo item'
|
98
108
|
def add(str, *str2)
|
99
109
|
string = "#{str} #{str2.join(' ')}"
|
100
110
|
todo = @list.add string
|
@@ -103,10 +113,10 @@ module Todotxt
|
|
103
113
|
|
104
114
|
@list.save
|
105
115
|
end
|
106
|
-
map
|
116
|
+
map 'a' => :add
|
107
117
|
|
108
|
-
desc
|
109
|
-
def do
|
118
|
+
desc 'do ITEM#[, ITEM#, ITEM#, ...]', 'Mark ITEM# as done'
|
119
|
+
def do(line1, *lines)
|
110
120
|
lines.unshift(line1).each do |line|
|
111
121
|
todo = @list.find_by_line line
|
112
122
|
if todo
|
@@ -120,8 +130,8 @@ module Todotxt
|
|
120
130
|
end
|
121
131
|
end
|
122
132
|
|
123
|
-
desc
|
124
|
-
def undo
|
133
|
+
desc 'undo | u ITEM#[, ITEM#, ITEM#, ...]', 'Mark ITEM# item as not done'
|
134
|
+
def undo(line1, *lines)
|
125
135
|
lines.unshift(line1).each do |line|
|
126
136
|
todo = @list.find_by_line line
|
127
137
|
if todo
|
@@ -134,10 +144,10 @@ module Todotxt
|
|
134
144
|
end
|
135
145
|
end
|
136
146
|
end
|
137
|
-
map
|
147
|
+
map 'u' => :undo
|
138
148
|
|
139
|
-
desc
|
140
|
-
def pri
|
149
|
+
desc 'pri | p ITEM# PRIORITY', 'Set priority of ITEM# to PRIORITY'
|
150
|
+
def pri(line, priority)
|
141
151
|
todo = @list.find_by_line line
|
142
152
|
if todo
|
143
153
|
todo.prioritize priority
|
@@ -148,10 +158,10 @@ module Todotxt
|
|
148
158
|
error "No todo found at line #{line}"
|
149
159
|
end
|
150
160
|
end
|
151
|
-
map
|
161
|
+
map 'p' => :pri
|
152
162
|
|
153
|
-
desc
|
154
|
-
def dp
|
163
|
+
desc 'dp | depri ITEM#[, ITEM#, ITEM#, ...]', 'Remove priority for ITEM#'
|
164
|
+
def dp(line1, *lines)
|
155
165
|
lines.unshift(line1).each do |line|
|
156
166
|
todo = @list.find_by_line line
|
157
167
|
if todo
|
@@ -164,10 +174,10 @@ module Todotxt
|
|
164
174
|
end
|
165
175
|
end
|
166
176
|
end
|
167
|
-
map
|
177
|
+
map 'depri' => :dp
|
168
178
|
|
169
|
-
desc
|
170
|
-
def append
|
179
|
+
desc 'append | app ITEM# STRING', 'Append STRING to ITEM#'
|
180
|
+
def append(line, str, *str2)
|
171
181
|
string = "#{str} #{str2.join(' ')}"
|
172
182
|
todo = @list.find_by_line line
|
173
183
|
if todo
|
@@ -179,10 +189,10 @@ module Todotxt
|
|
179
189
|
error "No todo found at line #{line}"
|
180
190
|
end
|
181
191
|
end
|
182
|
-
map
|
192
|
+
map 'app' => :append
|
183
193
|
|
184
|
-
desc
|
185
|
-
def prepend
|
194
|
+
desc 'prepend | prep ITEM# STRING', 'Prepend STRING to ITEM#'
|
195
|
+
def prepend(line, str, *str2)
|
186
196
|
string = "#{str} #{str2.join(' ')}"
|
187
197
|
todo = @list.find_by_line line
|
188
198
|
if todo
|
@@ -194,10 +204,10 @@ module Todotxt
|
|
194
204
|
error "No todo found at line #{line}"
|
195
205
|
end
|
196
206
|
end
|
197
|
-
map
|
207
|
+
map 'prep' => :prepend
|
198
208
|
|
199
|
-
desc
|
200
|
-
def replace
|
209
|
+
desc 'replace ITEM# TEXT', 'Completely replace ITEM# text with TEXT'
|
210
|
+
def replace(line, str, *str2)
|
201
211
|
string = "#{str} #{str2.join(' ')}"
|
202
212
|
todo = @list.find_by_line line
|
203
213
|
if todo
|
@@ -210,16 +220,16 @@ module Todotxt
|
|
210
220
|
end
|
211
221
|
end
|
212
222
|
|
213
|
-
desc
|
214
|
-
method_option :force, :
|
215
|
-
def del
|
223
|
+
desc 'del | rm ITEM#[, ITEM#, ITEM#, ...]', 'Remove ITEM#'
|
224
|
+
method_option :force, type: :boolean, aliases: '-f', desc: "Don't confirm removal"
|
225
|
+
def del(line1, *lines)
|
216
226
|
lines.unshift(line1).each do |line|
|
217
227
|
todo = @list.find_by_line line
|
218
228
|
if todo
|
219
229
|
say format_todo(todo)
|
220
|
-
if options[:force] || yes?(
|
230
|
+
if options[:force] || yes?('Remove this item? [y/N]')
|
221
231
|
@list.remove line
|
222
|
-
notice
|
232
|
+
notice 'Removed from list'
|
223
233
|
|
224
234
|
@list.save
|
225
235
|
end
|
@@ -228,19 +238,19 @@ module Todotxt
|
|
228
238
|
end
|
229
239
|
end
|
230
240
|
end
|
231
|
-
map
|
241
|
+
map 'rm' => :del
|
232
242
|
|
233
|
-
desc
|
243
|
+
desc 'edit', 'Open todo.txt file in your default editor'
|
234
244
|
def edit
|
235
|
-
system "#{@editor} #{@file.path}"
|
245
|
+
Kernel.system "#{@config.editor} #{@config.file.path}"
|
236
246
|
end
|
237
247
|
|
238
|
-
desc
|
239
|
-
def move
|
240
|
-
if @files[other_list_alias
|
248
|
+
desc 'move | mv ITEM#[, ITEM#, ITEM#, ...] file', 'Move ITEM# to another file'
|
249
|
+
def move(line1, *lines, other_list_alias)
|
250
|
+
if @config.files[other_list_alias].nil?
|
241
251
|
error_and_exit "File alias #{other_list_alias} not found"
|
242
252
|
else
|
243
|
-
other_list = TodoList.new @files[other_list_alias
|
253
|
+
other_list = TodoList.new @config.files[other_list_alias]
|
244
254
|
end
|
245
255
|
|
246
256
|
lines.unshift(line1).each do |line|
|
@@ -257,65 +267,42 @@ module Todotxt
|
|
257
267
|
end
|
258
268
|
end
|
259
269
|
end
|
260
|
-
map
|
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
|
270
|
+
map 'mv' => :move
|
285
271
|
|
286
272
|
#
|
287
273
|
# File generation
|
288
274
|
#
|
289
275
|
|
290
|
-
desc
|
276
|
+
desc 'generate_config', 'Create a .todotxt.cfg file in your home folder, containing the path to todo.txt'
|
291
277
|
def generate_config
|
292
|
-
copy_file
|
293
|
-
puts
|
278
|
+
copy_file 'todotxt.cfg', Config.config_path
|
279
|
+
puts ''
|
294
280
|
end
|
295
281
|
|
296
|
-
desc
|
282
|
+
desc 'generate_txt', 'Create a sample todo.txt'
|
297
283
|
def generate_txt
|
298
|
-
copy_file
|
299
|
-
puts
|
284
|
+
copy_file 'todo.txt', @file
|
285
|
+
puts ''
|
300
286
|
end
|
301
287
|
|
302
288
|
#
|
303
289
|
# Extras
|
304
290
|
#
|
305
291
|
|
306
|
-
desc
|
292
|
+
desc 'version', 'Show todotxt version'
|
307
293
|
def version
|
308
294
|
say "todotxt #{VERSION}"
|
309
295
|
end
|
310
296
|
|
311
|
-
|
312
|
-
|
297
|
+
private
|
298
|
+
|
299
|
+
def render_list(opts = {})
|
313
300
|
numsize = @list.count + 1
|
314
301
|
numsize = numsize.to_s.length + 0
|
315
302
|
|
316
303
|
@list.each do |t|
|
317
304
|
if opts[:simple]
|
318
|
-
say "#{t.line} #{t
|
305
|
+
say "#{t.line} #{t}"
|
319
306
|
else
|
320
307
|
say format_todo(t, numsize)
|
321
308
|
end
|
@@ -327,49 +314,16 @@ module Todotxt
|
|
327
314
|
end
|
328
315
|
|
329
316
|
# File should respond_to "basename", "path" and "generate!"
|
330
|
-
def ask_and_create
|
317
|
+
def ask_and_create(file)
|
331
318
|
puts "#{file.basename} doesn't exist yet. Would you like to generate a sample file?"
|
332
319
|
confirm_generate = yes? "Create #{file.path}? [y/N]"
|
333
320
|
|
334
321
|
if confirm_generate
|
335
322
|
file.generate!
|
336
323
|
else
|
337
|
-
puts
|
324
|
+
puts ''
|
338
325
|
exit
|
339
326
|
end
|
340
327
|
end
|
341
|
-
|
342
|
-
def parse_conf
|
343
|
-
@files = {}
|
344
|
-
|
345
|
-
return if @config.nil?
|
346
|
-
|
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)
|
357
|
-
end
|
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
|
367
|
-
else
|
368
|
-
@file = @files[:todo]
|
369
|
-
end
|
370
|
-
|
371
|
-
# Determine the editor
|
372
|
-
@editor = @config["editor"] || ENV["EDITOR"]
|
373
|
-
end
|
374
328
|
end
|
375
329
|
end
|