todotxt 0.1.0 → 0.2.0
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.
- 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
|