tlist 0.0.1

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.
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in tlist.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tlist (0.0.1)
5
+ colorize
6
+ methodchain
7
+ trollop
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ colorize (0.5.8)
13
+ methodchain (0.4.2)
14
+ trollop (1.16.2)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ tlist!
@@ -0,0 +1,17 @@
1
+ Copyright (c) 2011, Caleb Spare
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5
+ the following conditions are met:
6
+
7
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the
8
+ following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of
9
+ conditions and the following disclaimer in the documentation and/or other materials provided with the
10
+ distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
11
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
12
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
13
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
15
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
16
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
17
+ DAMAGE.
@@ -0,0 +1,226 @@
1
+ tlist
2
+ =====
3
+
4
+ tlist is an extremely lightweight TODO list manager for your commandline. It was written to be the bare
5
+ minimum that would meet my particular needs. It takes its inspiration heavily from
6
+ [t](http://stevelosh.com/projects/t/), a wonderful tool in the same vein written by the amazing Steve Losh
7
+ (incidentally, owner of the prettiest website on the interwebs). tlist also borrows a workflow from
8
+ [Things](http://culturedcode.com/things/) (as described to me; I've never actually used it).
9
+
10
+ The are three primary features that separate tlist from t:
11
+
12
+ 1. tlist is optimized for the single-person use case. The order of the list can be significant (it can
13
+ represent a priority).
14
+ 2. tlist has a built-in notion of labels for each task.
15
+ 3. tlist can be used with a two-step workflow. Each new task is put into the "Unsorted" category, and then
16
+ later the unsorted tasks may all be sorted at once.
17
+
18
+ Point #3 is why tlist is very efficient in my workflow. When a new task occurs to me, I can add it to my queue
19
+ of new tasks with almost no overhead (this avoids interruping my current train of thought). Later, I can sort
20
+ through my new tasks and organize them all at once.
21
+
22
+ Installation
23
+ ------------
24
+
25
+ The easiest way to install tlist is to install the gem
26
+
27
+ gem install tlist
28
+
29
+ This will install all the dependencies for you. It requires Ruby (I've tested with 1.8.7 and 1.9.2).
30
+
31
+ You can also install the latest version from Github by cloning the
32
+ [repository](https://github.com/cespare/tlist) and then adding `tlist` to your path. You'll need to make sure
33
+ the following dependencies (gems) are installed:
34
+
35
+ * trollop
36
+ * colorize
37
+ * methodchain
38
+
39
+ After you've got tlist, you should set up a few things in your `.bashrc`/`.bash_profile`. First, specify your
40
+ chosen todo-list file as follows:
41
+
42
+ export TLIST_FILE=path/to/tlist_file.txt
43
+
44
+ (Pro-tip: put this in your Dropbox folder as a quick way to share your todo list between multiple computers.)
45
+ Next, you can get tab completion by sourcing the included file. Download `tlist_completion.bash` and put it
46
+ somewhere on your machine. Then
47
+
48
+ source path/to/tlist_completion.bash
49
+
50
+ (This is optional.) Finally, if you want to get really crazy, you might alias `tlist` to something shorter. I
51
+ do this as follows:
52
+
53
+ alias t=tlist
54
+ complete -F _tlist t
55
+
56
+ Now you should be ready to go. Make sure it works by checking that you see the following output at your
57
+ command line (be sure to source your `.bashrc` or open a new terminal first):
58
+
59
+ $ tlist
60
+ Unsorted
61
+ (No tasks)
62
+
63
+ Usage
64
+ -----
65
+
66
+ You can see the full list of options by typing
67
+
68
+ $ tlist --help
69
+
70
+ However, there are only a few that you'll typically need. I'll guide you through a typical workflow using
71
+ those commands.
72
+
73
+ Let's start by adding a few tasks.
74
+
75
+ $ tlist -a "Go to the bank"
76
+ Added task 'Go to the bank' to label 'Unsorted'.
77
+ $ tlist -a "Set up dentist appointment"
78
+ Added task 'Set up dentist appointment' to label 'Unsorted'.
79
+ $ tlist -a "Buy milk"
80
+ Added task 'Buy milk' to label 'Unsorted'.
81
+ $ tlist -a "Buy coffee"
82
+ Added task 'Buy coffee' to label 'Unsorted'.
83
+
84
+ (Note: tlist will join all arguments together, so you can type `$ tlist -a Go to the bank` with no quotes.
85
+ However, if you've got any `'` characters in the task it will be interpreted as the start of a single-quoted
86
+ string by bash, so it's good to get in the habit of quoting the whole task.) You can inspect your tasks by
87
+ simply using `tlist`:
88
+
89
+ $ tlist
90
+ Unsorted
91
+ * Go to the bank
92
+ * Set up dentist appointment
93
+ * Buy milk
94
+ * Buy coffee
95
+
96
+ Now, adding new tasks is extremely quick, but they go to this "Unsorted" label. Now let's suppose you have a
97
+ few spare minutes, so you decide to organize all your tasks.
98
+
99
+ $ tlist -s
100
+ Sorting 4 unsorted tasks.
101
+
102
+ Unsorted task:
103
+ > Go to the bank
104
+ No existing labels.
105
+ Other options:
106
+ n Create a new label
107
+ s Skip this task
108
+ q Abort
109
+ Select an option: n
110
+ Enter new label name: Errands
111
+ Added task 'Go to the bank' to new label 'Errands'.
112
+ Removed task 'Go to the bank' from label 'Unsorted'.
113
+
114
+ Unsorted task:
115
+ > Set up dentist appointment
116
+ ...
117
+
118
+ I'm ommitting extra output here, but you can see how this interactive sorting step lets you quickly sort the
119
+ tasks you made earlier. Let's suppose that your current task list looks like this:
120
+
121
+ $ tlist
122
+ Errands
123
+ 1. Go to the bank
124
+ 2. Set up dentist appointment
125
+
126
+ Groceries
127
+ 1. Buy milk
128
+ 2. Buy coffee
129
+
130
+ Unsorted
131
+ (No tasks)
132
+
133
+ We can easily remove tasks:
134
+
135
+ $ tlist -d
136
+ Errands
137
+ 1. Go to the bank
138
+ 2. Set up dentist appointment
139
+
140
+ Groceries
141
+ 3. Buy milk
142
+ 4. Buy coffee
143
+
144
+ Select a task to delete (1-4 or q to abort): 3
145
+ Removed task 'Buy milk' from label 'Groceries'.
146
+
147
+ It's also easy to restrict many of these operations to a specific label:
148
+
149
+ $ tlist -l Groceries -a Buy yogurt
150
+ Added task 'Buy yogurt' to label 'Groceries'.
151
+ $ tlist -l Groceries -a Buy fruit
152
+ Added task 'Buy fruit' to label 'Groceries'.
153
+ $ tlist -l Groceries
154
+ Groceries
155
+ 1. Buy coffee
156
+ 2. Buy yogurt
157
+ 3. Buy fruit
158
+
159
+ $ tlist -l Groceries -d
160
+ Groceries
161
+ 1. Buy coffee
162
+ 2. Buy yogurt
163
+ 3. Buy fruit
164
+
165
+ Select a task to delete (1-3 or q to abort): 2
166
+ Removed task 'Buy yogurt' from label 'Groceries'.
167
+
168
+ Advanced usage
169
+ --------------
170
+
171
+ In addition to these basic operations, there is a concept of a "working" label from which you are actively
172
+ completing items. You can get and set your working label as follows:
173
+
174
+ $ tlist -g
175
+ No working label set. Use $ tlist --current to set a working label.
176
+ $ tlist -c Errands
177
+ Set current working label to 'Errands'.
178
+ $ tlist -g
179
+ Errands
180
+
181
+ Once you've set a working label, you can quickly pop items from the list and delete them as you finish with
182
+ the `--next` and `--finish` commands:
183
+
184
+ $ tlist -n
185
+ Go to the bank
186
+ $ tlist -f
187
+ Removed task 'Go to the bank' from label 'Errands'.
188
+ $ tlist -n
189
+ Set up dentist appointment
190
+ $ tlist -f
191
+ Removed task 'Set up dentist appointment' from label 'Errands'.
192
+ Removed empty label 'Errands'.
193
+
194
+ One last command that is very useful is `--edit`. Just type
195
+
196
+ $ tlist -e
197
+
198
+ and the tlist file will be opened in your `$EDITOR`. Be careful not to change the formatting. The blank lines
199
+ are significant, as are the colons (signify labels) and `>` (signifies current label). It's often quickest to
200
+ do complex reorganization of your tasks in your editor, rather than the one-by-one operations that tlist
201
+ natively supports.
202
+
203
+ Tests
204
+ -----
205
+
206
+ The tests for tlist are in the `tests/` directory, and they're written using
207
+ [cram](https://bitheap.org/cram/). Install cram and then run all the tests with
208
+
209
+ $ cram test/*.t
210
+
211
+ Contributions
212
+ -------------
213
+
214
+ If you'd like to hack on tlist, go ahead and [fork the project on github](https://github.com/cespare/tlist).
215
+ Open a pull request if you'd like me to incorporate your changes, but keep in mind that I'd like to keep tlist
216
+ pretty lightweight so I may not accept large new features.
217
+
218
+ Author
219
+ ------
220
+
221
+ tlist was written by Caleb Spare (cespare on Github).
222
+
223
+ License
224
+ -------
225
+
226
+ [BSD 2-clause license](http://opensource.org/licenses/bsd-license.php); see LICENSE.txt.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/TODO.md ADDED
@@ -0,0 +1,11 @@
1
+ TODO
2
+ ====
3
+
4
+ * Finish tests:
5
+ * sort
6
+ * current
7
+ * get-current
8
+ * next
9
+ * finish
10
+ * labels
11
+ * See if it's possible to fix bug with tab-completing labels with spaces.
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "trollop"
5
+ require "colorize"
6
+ require "methodchain"
7
+
8
+ UNSORTED_NAME = "Unsorted"
9
+
10
+ def print_numbered(item, number, total_items)
11
+ number_width = total_items.to_s.size + 1
12
+ puts "#{"#{number}.".ljust(number_width)} #{item}"
13
+ end
14
+
15
+ class Tlist
16
+ attr_reader :label_array, :label_hash
17
+ attr_accessor :current
18
+ def initialize(filename)
19
+ @filename = filename
20
+ # I'd like to have ordered hashes instead of keeping the list + the hash, but I want 1.8 compatibility.
21
+ @label_array = [] # Array of label names
22
+ @label_hash = {} # Label name => Array of tasks
23
+ @current = nil
24
+ end
25
+
26
+ def add_label(name)
27
+ raise "Invalid name '#{name}'" if name.start_with? "> "
28
+ @label_array << name
29
+ @label_hash[name] = []
30
+ end
31
+
32
+ def delete_label(name)
33
+ raise "No such label '#{name}'" unless @label_hash.include? name
34
+ @label_array.delete name
35
+ @label_hash.delete name
36
+ end
37
+
38
+ def resolve_label(label_part)
39
+ return UNSORTED_NAME unless label_part
40
+ selected_labels = @label_array.select { |l| l.downcase.index label_part.downcase }
41
+ if selected_labels.size > 1
42
+ raise "Error: '#{label}' matches multiple labels: #{selected_labels.join(', ')}."
43
+ end
44
+ selected_labels[0]
45
+ end
46
+
47
+ def set_current(label_part)
48
+ label = resolve_label label_part
49
+ raise "Error: no label matches '#{label_part}'." unless label
50
+ @current = label
51
+ puts "Set current working label to '#{label}'."
52
+ end
53
+
54
+ def add_task(label, task)
55
+ raise "Invalid task name." if task.strip.empty?
56
+ selected_label = resolve_label(label)
57
+ add_label(label) unless selected_label
58
+ label = selected_label || label
59
+ if @label_hash[label].include? task
60
+ raise "Error: '#{label}' already includes a task '#{task}'."
61
+ end
62
+ @label_hash[label] << task
63
+ puts "Added task '#{task}' to #{"new " unless selected_label}label '#{label}'."
64
+ end
65
+
66
+ def delete_task(label, task)
67
+ selected_label = resolve_label(label)
68
+ raise "Error: No such label '#{label}'." unless selected_label
69
+ unless @label_hash[selected_label].include? task
70
+ raise "Error: No such task '#{task}' in label '#{selected_label}'."
71
+ end
72
+ @label_hash[selected_label].delete task
73
+ puts "Removed task '#{task}' from label '#{selected_label}'."
74
+ if @label_hash[selected_label].empty? && selected_label != UNSORTED_NAME
75
+ delete_label selected_label
76
+ puts "Removed empty label '#{selected_label}'."
77
+ end
78
+ end
79
+
80
+ def next_task
81
+ raise "No working label is set." unless @current
82
+ tasks = @label_hash[@current]
83
+ raise "No tasks left in working label '#{@current}'." if tasks.empty?
84
+ tasks[0]
85
+ end
86
+
87
+ def print_all_tasks_numbered(label)
88
+ labels = (label ? [resolve_label(label)] : @label_array).reject { |label| @label_hash[label].empty? }
89
+ return {} if labels.empty?
90
+ result = {}
91
+ task_count = @label_hash.values_at(*labels).map(&:size).reduce(&:+)
92
+ number = 0
93
+ labels.each do |label|
94
+ print_label label
95
+ @label_hash[label].each do |task|
96
+ print_numbered task, number += 1, task_count
97
+ result[number] = [label, task]
98
+ end
99
+ puts
100
+ end
101
+ result
102
+ end
103
+
104
+ def print(label)
105
+ labels = label ? [resolve_label(label)] : @label_array
106
+ labels.each do |label|
107
+ print_label label
108
+ tasks = @label_hash[label]
109
+ if tasks.empty?
110
+ puts "(No tasks)"
111
+ elsif label == UNSORTED_NAME
112
+ tasks.each { |task| puts "* #{task}" }
113
+ else
114
+ tasks.each_with_index { |task, i| print_numbered task, i + 1, tasks.size }
115
+ end
116
+ puts
117
+ end
118
+ end
119
+
120
+ def print_label(name)
121
+ colored = name == UNSORTED_NAME ? name.blue.underline : name.green.underline
122
+ puts @current == name ? "#{colored} (Current)" : colored
123
+ end
124
+
125
+ def write_file!
126
+ File.open(@filename, "w") do |file|
127
+ @label_array.each do |label|
128
+ file.puts "#{"> " if @current == label}#{label}:"
129
+ @label_hash[label].each { |task| file.puts task }
130
+ file.puts
131
+ end
132
+ end
133
+ end
134
+
135
+ def self.from_file(filename)
136
+ raise "Bad file: #{filename}" unless File.file? filename
137
+ tlist = Tlist.new(filename)
138
+ lines = File.open(filename).readlines.map(&:strip)
139
+ expect_label = true
140
+ lines.each_with_index do |line, i|
141
+ if line.empty?
142
+ expect_label = true
143
+ next
144
+ end
145
+
146
+ if expect_label
147
+ current, label = line.match(/^(> )?(.*):$/).to_a[1..2]
148
+ raise "Error parsing #{filename} at line #{i + 1} (expecting label)." unless label
149
+ if tlist.label_hash.include? label
150
+ raise "Error parsing #{filename} at line #{i + 1} (duplicate label)."
151
+ end
152
+ if current
153
+ if tlist.current
154
+ raise "Error parsing #{filename} at line #{i + 1} (more than one label is marked as current)."
155
+ end
156
+ tlist.current = label
157
+ end
158
+ tlist.add_label label
159
+ expect_label = false
160
+ else
161
+ tlist.label_hash[tlist.label_array.last] << line
162
+ end
163
+ end
164
+
165
+ # Keep the unsorted task list at the end.
166
+ if tlist.label_hash.include? UNSORTED_NAME
167
+ tlist.label_array.delete UNSORTED_NAME
168
+ tlist.label_array << UNSORTED_NAME
169
+ else
170
+ tlist.add_label UNSORTED_NAME
171
+ end
172
+ tlist
173
+ end
174
+ end
175
+
176
+ MODES = [:print, :add, :sort, :delete, :edit, :next, :finish, :current, :get_current, :unsorted, :labels]
177
+
178
+ def get_mode(options)
179
+ modes = options.keys.select { |option| MODES.include?(option) && options[option] }
180
+ if modes.size > 1
181
+ puts "Error: only one of the following may be specified:"
182
+ MODES.each { |mode| puts " --#{mode}" }
183
+ exit 1
184
+ end
185
+ modes[0] || :print
186
+ end
187
+
188
+ todo_file = ENV["TLIST_FILE"]
189
+ abort "Need to set TLIST_FILE environment variable" unless todo_file
190
+ editor = ENV["EDITOR"] || "vim"
191
+
192
+ options = Trollop::options do
193
+ opt :print, "Print tasks (can omit this flag)."
194
+ opt :add, "Add a task"
195
+ opt :sort, "Sort unsorted tasks"
196
+ opt :delete, "Delete a task"
197
+ opt :label, "Limit to a particular label (used in combination with another option)",
198
+ :default => nil, :type => String
199
+ opt :edit, "Edit the task list file in your $EDITOR (use carefully)"
200
+ opt :current, "Set the current working label", :default => nil, :type => String
201
+ opt :get_current, "Get the current working label"
202
+ opt :next, "Print the next task in the current label"
203
+ opt :finish, "Delete the next task in the current label"
204
+ opt :unsorted, "Print unsorted tasks (shorthand for --print #{UNSORTED_NAME})"
205
+ opt :labels, "Print all labels"
206
+
207
+ # TODO: Decide whether to implement something like this
208
+ #opt :finish, "Move a task to the finished list", :default => false
209
+ #opt :print_finished, "Print finished tasks.", :default => false
210
+ end
211
+
212
+ begin
213
+ mode = get_mode(options)
214
+ exec "#{editor} #{todo_file}" if mode == :edit
215
+
216
+ tlist = Tlist.from_file(todo_file)
217
+ label = options[:label]
218
+ argument = ARGV.join(" ")
219
+
220
+ case mode
221
+ when :print
222
+ tlist.print label
223
+ when :unsorted
224
+ tlist.print UNSORTED_NAME
225
+ when :add
226
+ label = tlist.add_task(label, argument)
227
+ tlist.write_file!
228
+ when :sort
229
+ unsorted_tasks = tlist.label_hash[UNSORTED_NAME].clone
230
+ puts "Sorting #{unsorted_tasks.size} unsorted tasks."
231
+ unsorted_tasks.each do |task|
232
+ puts
233
+ labels = tlist.label_array - [UNSORTED_NAME]
234
+ puts "Unsorted task:"
235
+ puts "> #{task}".yellow
236
+ if labels.size >= 1
237
+ puts "Existing labels:"
238
+ labels.each_with_index { |label, i| print_numbered label, i + 1, labels.size }
239
+ else
240
+ puts "No existing labels."
241
+ end
242
+ puts "Other options:"
243
+ ["n Create a new label", "s Skip this task", "q Abort"].each { |option| puts option }
244
+ print "Select an option: "
245
+ choice = STDIN.gets.strip
246
+ case choice
247
+ when *(1..labels.size).map(&:to_s)
248
+ tlist.add_task labels[choice.to_i - 1], task
249
+ tlist.delete_task UNSORTED_NAME, task
250
+ tlist.write_file!
251
+ when "n", "new"
252
+ print "Enter new label name: "
253
+ tlist.add_task STDIN.gets.strip, task
254
+ tlist.delete_task UNSORTED_NAME, task
255
+ tlist.write_file!
256
+ when "s", "skip"
257
+ when "q", "quit", "a"
258
+ exit 0
259
+ else
260
+ raise "Error: '#{choice}' unrecognized option. Aborting."
261
+ end
262
+ end
263
+ when :delete
264
+ choices = tlist.print_all_tasks_numbered label
265
+ if choices.empty?
266
+ puts "No tasks."
267
+ else
268
+ range = choices.size == 1 ? "1" : "1-#{choices.size}"
269
+ print "Select a task to delete (#{range} or q to abort): "
270
+ choice = STDIN.gets.strip
271
+ case choice
272
+ when *choices.keys.map(&:to_s)
273
+ tlist.delete_task *choices[choice.to_i]
274
+ tlist.write_file!
275
+ when "q", "quit", "a"
276
+ exit 0
277
+ else
278
+ raise "Error: '#{choice}' unrecognized option. Aborting."
279
+ end
280
+ end
281
+ when :next
282
+ puts tlist.next_task
283
+ when :finish
284
+ task = tlist.next_task
285
+ tlist.delete_task tlist.current, task
286
+ tlist.write_file!
287
+ when :current
288
+ tlist.set_current options[:current]
289
+ tlist.write_file!
290
+ when :get_current
291
+ puts tlist.current.else { "No working label set. Use $ tlist --current to set a working label." }
292
+ when :labels
293
+ puts tlist.label_array.join(" ")
294
+ end
295
+ rescue RuntimeError => e
296
+ abort e.message
297
+ end
@@ -0,0 +1,50 @@
1
+ # Test adding new tasks
2
+
3
+ # Setup
4
+ $ touch tlist_file
5
+ $ export TLIST_FILE=tlist_file
6
+ $ PATH=$TESTDIR/../bin:$PATH
7
+
8
+ # Tests
9
+ $ tlist
10
+ Unsorted
11
+ (No tasks)
12
+
13
+ $ tlist -a task 1
14
+ Added task 'task 1' to label 'Unsorted'.
15
+ $ tlist
16
+ Unsorted
17
+ * task 1
18
+
19
+ $ tlist --label "Label1" --add task 2
20
+ Added task 'task 2' to new label 'Label1'.
21
+ $ tlist
22
+ Label1
23
+ 1. task 2
24
+
25
+ Unsorted
26
+ * task 1
27
+
28
+ $ tlist -l "Label1" -a task 3
29
+ Added task 'task 3' to label 'Label1'.
30
+ $ tlist
31
+ Label1
32
+ 1. task 2
33
+ 2. task 3
34
+
35
+ Unsorted
36
+ * task 1
37
+
38
+ $ tlist -l "Label2" -a task 4
39
+ Added task 'task 4' to new label 'Label2'.
40
+ $ tlist
41
+ Label1
42
+ 1. task 2
43
+ 2. task 3
44
+
45
+ Label2
46
+ 1. task 4
47
+
48
+ Unsorted
49
+ * task 1
50
+
@@ -0,0 +1,73 @@
1
+ # Deleting tasks.
2
+
3
+ # Setup
4
+ $ cp $TESTDIR/files/many_labels.txt tlist_file
5
+ $ export TLIST_FILE=tlist_file
6
+ $ PATH=$TESTDIR/../bin:$PATH
7
+
8
+ # Tests
9
+ # The long line below is confusing. There is no newline after ": " because '4' is echoed in. When the user
10
+ # inputs '4' from the prompt, a newline will separate the prompt from the response.
11
+ $ echo "4" | tlist --delete
12
+ Foo
13
+ 1. foo task 1
14
+ 2. foo task 2
15
+
16
+ Bar
17
+ 3. bar task 1
18
+
19
+ Baz
20
+ 4. baz task 1
21
+ 5. baz task 2
22
+ 6. baz task 3
23
+
24
+ Unsorted
25
+ 7. unsorted 1
26
+ 8. unsorted 2
27
+ 9. unsorted 3
28
+ 10. unsorted 4
29
+
30
+ Select a task to delete (1-10 or q to abort): Removed task 'baz task 1' from label 'Baz'.
31
+ $ tlist
32
+ Foo
33
+ 1. foo task 1
34
+ 2. foo task 2
35
+
36
+ Bar
37
+ 1. bar task 1
38
+
39
+ Baz
40
+ 1. baz task 2
41
+ 2. baz task 3
42
+
43
+ Unsorted
44
+ * unsorted 1
45
+ * unsorted 2
46
+ * unsorted 3
47
+ * unsorted 4
48
+
49
+ $ echo "3" | tlist -d -l unsor
50
+ Unsorted
51
+ 1. unsorted 1
52
+ 2. unsorted 2
53
+ 3. unsorted 3
54
+ 4. unsorted 4
55
+
56
+ Select a task to delete (1-4 or q to abort): Removed task 'unsorted 3' from label 'Unsorted'.
57
+ $ tlist
58
+ Foo
59
+ 1. foo task 1
60
+ 2. foo task 2
61
+
62
+ Bar
63
+ 1. bar task 1
64
+
65
+ Baz
66
+ 1. baz task 2
67
+ 2. baz task 3
68
+
69
+ Unsorted
70
+ * unsorted 1
71
+ * unsorted 2
72
+ * unsorted 4
73
+
File without changes
@@ -0,0 +1,7 @@
1
+ Foo:
2
+
3
+ Bar:
4
+
5
+ Baz:
6
+
7
+ Unsorted:
@@ -0,0 +1,17 @@
1
+ Foo:
2
+ foo task 1
3
+ foo task 2
4
+
5
+ Bar:
6
+ bar task 1
7
+
8
+ Baz:
9
+ baz task 1
10
+ baz task 2
11
+ baz task 3
12
+
13
+ Unsorted:
14
+ unsorted 1
15
+ unsorted 2
16
+ unsorted 3
17
+ unsorted 4
@@ -0,0 +1,7 @@
1
+ Foo:
2
+ foo task 1
3
+ foo task 2
4
+
5
+ Unsorted:
6
+ unsorted 1
7
+ unsorted 2
@@ -0,0 +1,4 @@
1
+ Foo:
2
+ foo task 1
3
+ foo task 2
4
+ foo task 3
@@ -0,0 +1,5 @@
1
+ Unsorted:
2
+ unsorted 1
3
+ unsorted 2
4
+ unsorted 3
5
+ unsorted 4
@@ -0,0 +1,86 @@
1
+ # Test printing various pre-made tlist files.
2
+
3
+ # Setup
4
+ $ PATH=$TESTDIR/../bin:$PATH
5
+
6
+ # Tests
7
+ $ TLIST_FILE=$TESTDIR/files/empty.txt tlist
8
+ Unsorted
9
+ (No tasks)
10
+
11
+ $ TLIST_FILE=$TESTDIR/files/empty.txt tlist --print
12
+ Unsorted
13
+ (No tasks)
14
+
15
+ $ TLIST_FILE=$TESTDIR/files/empty.txt tlist -p
16
+ Unsorted
17
+ (No tasks)
18
+
19
+ $ TLIST_FILE=$TESTDIR/files/empty_labels.txt tlist
20
+ Foo
21
+ (No tasks)
22
+
23
+ Bar
24
+ (No tasks)
25
+
26
+ Baz
27
+ (No tasks)
28
+
29
+ Unsorted
30
+ (No tasks)
31
+
32
+ $ TLIST_FILE=$TESTDIR/files/only_unsorted.txt tlist
33
+ Unsorted
34
+ * unsorted 1
35
+ * unsorted 2
36
+ * unsorted 3
37
+ * unsorted 4
38
+
39
+ $ TLIST_FILE=$TESTDIR/files/only_one_label.txt tlist
40
+ Foo
41
+ 1. foo task 1
42
+ 2. foo task 2
43
+ 3. foo task 3
44
+
45
+ Unsorted
46
+ (No tasks)
47
+
48
+ $ TLIST_FILE=$TESTDIR/files/one_label_and_unsorted.txt tlist
49
+ Foo
50
+ 1. foo task 1
51
+ 2. foo task 2
52
+
53
+ Unsorted
54
+ * unsorted 1
55
+ * unsorted 2
56
+
57
+ $ TLIST_FILE=$TESTDIR/files/many_labels.txt tlist
58
+ Foo
59
+ 1. foo task 1
60
+ 2. foo task 2
61
+
62
+ Bar
63
+ 1. bar task 1
64
+
65
+ Baz
66
+ 1. baz task 1
67
+ 2. baz task 2
68
+ 3. baz task 3
69
+
70
+ Unsorted
71
+ * unsorted 1
72
+ * unsorted 2
73
+ * unsorted 3
74
+ * unsorted 4
75
+
76
+ $ TLIST_FILE=$TESTDIR/files/many_labels.txt tlist --unsorted
77
+ Unsorted
78
+ * unsorted 1
79
+ * unsorted 2
80
+ * unsorted 3
81
+ * unsorted 4
82
+
83
+ $ TLIST_FILE=$TESTDIR/files/only_one_label.txt tlist -u
84
+ Unsorted
85
+ (No tasks)
86
+
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "tlist"
5
+ s.version = "0.0.1"
6
+ s.authors = ["Caleb Spare"]
7
+ s.email = ["cespare@gmail.com"]
8
+ s.homepage = ""
9
+ s.summary = "A simple todo-list"
10
+ s.description = "tlist is a small todo-list manager with labels for tasks and a highly efficient workflow."
11
+
12
+ s.rubyforge_project = "tlist"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
16
+
17
+ s.add_dependency "trollop"
18
+ s.add_dependency "colorize"
19
+ s.add_dependency "methodchain"
20
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+
3
+ _tlist() {
4
+ local current_word
5
+ local options='--print --add --sort --delete --label --edit --current --get-current --next --finish
6
+ --unsorted --labels -p -a -s -d -l -e -c -g -n -f -u -b'
7
+ COMPREPLY=()
8
+ current_word=${COMP_WORDS[COMP_CWORD]}
9
+ if [[ ${#COMP_WORDS[@]} -gt 1 && $COMP_CWORD -gt 0 ]]; then
10
+ local previous_word=${COMP_WORDS[COMP_CWORD - 1]}
11
+ for test_label in "--label" "-l" "--current" "-c"; do
12
+ if [[ "$test_label" = "$previous_word" ]]; then
13
+ local labels=$(tlist --labels)
14
+ COMPREPLY=($(compgen -W "$labels" -- $current_word))
15
+ return 0
16
+ fi
17
+ done
18
+ fi
19
+ COMPREPLY=($(compgen -W "$options" -- $current_word))
20
+ return 0
21
+ }
22
+
23
+ complete -F _tlist tlist
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tlist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Caleb Spare
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-06 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: trollop
16
+ requirement: &70256313193860 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70256313193860
25
+ - !ruby/object:Gem::Dependency
26
+ name: colorize
27
+ requirement: &70256313193420 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70256313193420
36
+ - !ruby/object:Gem::Dependency
37
+ name: methodchain
38
+ requirement: &70256313193000 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70256313193000
47
+ description: tlist is a small todo-list manager with labels for tasks and a highly
48
+ efficient workflow.
49
+ email:
50
+ - cespare@gmail.com
51
+ executables:
52
+ - tlist
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - .gitignore
57
+ - Gemfile
58
+ - Gemfile.lock
59
+ - LICENSE.txt
60
+ - README.md
61
+ - Rakefile
62
+ - TODO.md
63
+ - bin/tlist
64
+ - test/add.t
65
+ - test/delete.t
66
+ - test/files/empty.txt
67
+ - test/files/empty_labels.txt
68
+ - test/files/many_labels.txt
69
+ - test/files/one_label_and_unsorted.txt
70
+ - test/files/only_one_label.txt
71
+ - test/files/only_unsorted.txt
72
+ - test/print.t
73
+ - tlist.gemspec
74
+ - tlist_completion.bash
75
+ homepage: ''
76
+ licenses: []
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project: tlist
95
+ rubygems_version: 1.8.7
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: A simple todo-list
99
+ test_files: []