todorb 0.2.1 → 1.0.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.
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,12 @@
1
+ = todorb 0.2.2, 2010-06-15
2
+ * Added subtask addition. One may add subtasks under a task.
3
+ * This effects everything! Deleting a task, you may wanna delete all
4
+ children. Changing the status of a task may affect all children.
5
+ Renumberign and redoing etc affects subtasks. The impact of this change
6
+ is quite huge.
7
+
8
+ = todorb 0.2.1
9
+ * Version without subtask. This is a simpler version which i prefer.
10
+
11
+
12
+ ## vim:tw=72:ai:formatoptions=tcqln:nocindent
data/Makefile ADDED
@@ -0,0 +1,29 @@
1
+ DISTFILES := README.markdown get_serial_number colors.sh todoapp.sh
2
+ VERSION := `cat VERSION_FILE`
3
+
4
+ all: install
5
+
6
+ install:
7
+
8
+ rake build && sudo rake install
9
+
10
+ #
11
+ # Testing
12
+ #
13
+ TESTS = $(wildcard tests/t[0-9][0-9][0-9][0-9]-*.sh)
14
+ #TEST_OPTIONS=--verbose
15
+
16
+ test-pre-clean:
17
+ rm -rf tests/test-results "tests/trash directory"*
18
+
19
+ aggregate-results: $(TESTS)
20
+
21
+ $(TESTS): test-pre-clean
22
+ -cd tests && sh $(notdir $@) $(TEST_OPTIONS)
23
+
24
+ test: aggregate-results
25
+ tests/aggregate-results.sh tests/test-results/t*-*
26
+ rm -rf tests/test-results
27
+
28
+ # Force tests to get run every time
29
+ .PHONY: test test-pre-clean aggregate-results $(TESTS)
data/README.markdown CHANGED
@@ -10,11 +10,56 @@ The fun things about this app, is that I am having to write ruby code that will
10
10
 
11
11
  The TODO file output is TODO2.txt and is a plain text file. A TAB separates the task number from the Task. I use task numbers, since I may refer to tasks elsewhere. Gina's app never saved a task Id but kept showing them.
12
12
 
13
- The shell version, todoapp, allowed for any levels of sub-tasks. I have not yet added that, I may.
14
-
15
- I also may fork this and make a YAML file, so that the format is standard, especially when having sub-tasks.
16
13
  After this, I will port over my bug tracker, [bugzy.txt](http://github.com/rkumar/bugzy.txt), which uses a TAB delimited file. It's a cool app to use for bug tracking - you should try it out. I will possibly use sqlite instead of screwing around with a delimited file.
17
14
 
15
+ ## Features
16
+
17
+ 1. multiple todo lists (per directory)
18
+ 2. subtasks (recursive delete or status update)
19
+ 3. priorities - (A) (B)
20
+ 4. status - [ ], [x], [@] etc
21
+ 5. tag - @WORK
22
+ 6. project - +myproj
23
+ 7. component - @comp1
24
+ 8. notes attached to task
25
+ 9. delete tasks
26
+ 10. archive completed tasks
27
+ 11. colored or plain output
28
+ 12. show or hide completed tasks (default: hide)
29
+ 13. Search, filter, sort tasks by priority (default) or task id.
30
+ 14. Renumber the file
31
+
32
+ ## Sample Output
33
+
34
+ 3 [ ] Add a close for status close (2010-06-14)
35
+ 3.1 [ ] hello there new a u 3 (2010-06-15)
36
+ 3.1.1 [ ] hello there new a u 3 (2010-06-15)
37
+ 3.1.2 [ ] hello there new a u 3 (2010-06-15)
38
+ 3.1.3 [ ] hello there new a u 3 (2010-06-15)
39
+ 3.2 [ ] hello there new a u 3.2 (2010-06-15)
40
+ 3.2.1 [ ] hello there new a u 3.2.1 (2010-06-15)
41
+ 3.2.1.1 [ ] hello there new a u 3.2.1.1
42
+ * a note for frank (2010-06-15)
43
+ 5 [ ] list: if dir given then show full path of TODO2.txt at end (2010-06-14)
44
+ 5.2 [ ] start rubyforge project for todorb (2010-06-14)
45
+ 6 [@] allow for ENV VARS such as verbose, plain, force (2010-06-15)
46
+ 6.1 [@] what if no serial_number file? (2010-06-14)
47
+ 7 [ ] list: search terms with - + and = @RUBY (2010-06-15)
48
+ 8 [ ] testing out add 1 @MYTAG @RUBY (2010-06-19)
49
+ 9 [ ] testing out another one @RUBY
50
+ * a note for chris
51
+ * a note for steve (2010-06-19)
52
+ 11 [x] (A) move common app code to common/cmdapp
53
+ * refactor it also, so not so reliant on variables (2010-06-20)
54
+ 16 [ ] (A) add aliases to subcommand (2010-06-21)
55
+
56
+ 17 of 17 rows displayed from TODO2.txt
57
+
58
+ ## File format
59
+
60
+ 1. The file format is almost identical to the output except that there is a TAB after the task number.
61
+ 2. Notes are saved on same line as task, but displayed on another line with asterisk prefix.
62
+
18
63
  ## Copyright
19
64
 
20
65
  Copyright (c) 2010 Rahul Kumar. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "todorb"
8
+ gem.summary = %Q{command-line todo list manager }
9
+ gem.description = %Q{command-line program that manages a todo list text file }
10
+ gem.email = "sentinel1879@gmail.com"
11
+ gem.homepage = "http://github.com/rkumar/todorb"
12
+ gem.authors = ["Rahul Kumar"]
13
+ gem.rubyforge_project = "todorb"
14
+ #gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "todorb #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 1.0.0
data/bin/todorb CHANGED
@@ -2,4 +2,4 @@
2
2
  require 'rubygems'
3
3
  #require 'todorb/todo.rb'
4
4
  require 'todorb'
5
- Todo.main(ARGV)
5
+ exit Todo.main(ARGV)
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby -w
2
+ =begin
3
+ * Name : cmdapp.rb
4
+ * Description : some basic command line things
5
+ * : Moving some methods from todorb.rb here
6
+ * Author : rkumar
7
+ * Date : 2010-06-20 11:18
8
+ * License :
9
+ Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
10
+
11
+ =end
12
+ require 'common/sed'
13
+
14
+ ERRCODE = 1
15
+
16
+ module Cmdapp
17
+
18
+ ##
19
+ # external dependencies:
20
+ # @app_default_action - action to run if none specified
21
+ # @app_file_path - data file we are backing up, or reading into array
22
+ # @app_serial_path - serial_number file
23
+ ##
24
+ # check whether this action is mapped to some alias and *changes*
25
+ # @action and @argv if true.
26
+ # @param [String] action asked by user
27
+ # @param [Array] rest of args on command line
28
+ # @return [Boolean] whether it is mapped or not.
29
+ #
30
+ def check_aliases action, args
31
+ ret = @aliases[action]
32
+ if ret
33
+ a = ret.shift
34
+ b = [*ret, *args]
35
+ @action = a
36
+ @argv = b
37
+ #puts " #{@action} ; argv: #{@argv} "
38
+ return true
39
+ end
40
+ return false
41
+ end
42
+ ##
43
+ # runs method after checking if valid or alias.
44
+ # If not found prints help.
45
+ # @return [0, ERRCODE] success 0.
46
+ def run
47
+ @action = @argv[0] || @app_default_action
48
+ @action = @action.downcase
49
+ @action.sub!('priority', 'pri')
50
+ @action.sub!(/^del$/, 'delete')
51
+
52
+
53
+ ret = 0
54
+ @argv.shift
55
+ if @actions.include? @action
56
+ ret = send(@action, @argv)
57
+ else
58
+ # check aliases
59
+ if check_aliases @action, @argv
60
+ ret = send(@action, @argv)
61
+ else
62
+ help @argv
63
+ ret = ERRCODE
64
+ end
65
+ end
66
+ ret ||= 0
67
+ ret = 0 if ret != ERRCODE
68
+ return ret
69
+ end
70
+ def help args
71
+ puts "Actions are "
72
+ @actions.each_pair { |name, val| puts "#{name}\t#{val}" }
73
+ puts " "
74
+ puts "Aliases are "
75
+ @aliases.each_pair { |name, val| puts "#{name}:\t#{val.join(' ')}" }
76
+ 0
77
+ end
78
+
79
+ ##
80
+ # reads serial_number file, returns serialno for this app
81
+ # and increments the serial number and writes back.
82
+ def _get_serial_number
83
+ require 'fileutils'
84
+ appname = @appname
85
+ filename = @app_serial_path || "serial_numbers"
86
+ h = {}
87
+ # check if serial file existing in curr dir. Else create
88
+ if File.exists?(filename)
89
+ File.open(filename).each { |line|
90
+ #sn = $1 if line.match regex
91
+ x = line.split ":"
92
+ h[x[0]] = x[1].chomp
93
+ }
94
+ end
95
+ sn = h[appname] || 1
96
+ # update the sn in file
97
+ nsn = sn.to_i + 1
98
+ # this will create if not exists in addition to storing if it does
99
+ h[appname] = nsn
100
+ # write back to file
101
+ File.open(filename, "w") do |f|
102
+ h.each_pair {|k,v| f.print "#{k}:#{v}\n"}
103
+ end
104
+ return sn
105
+ end
106
+ ##
107
+ # After doing a redo of the numbering, we need to reset the numbers for that app
108
+ def _set_serial_number number
109
+ appname = @appname
110
+ pattern = Regexp.new "^#{appname}:.*$"
111
+ filename = @app_serial_path || "serial_numbers"
112
+ _backup filename
113
+ change_row filename, pattern, "#{appname}:#{number}"
114
+ end
115
+
116
+ def _backup filename=@app_file_path
117
+ require 'fileutils'
118
+ FileUtils.cp filename, "#{filename}.org"
119
+ end
120
+ def die text
121
+ $stderr.puts text
122
+ exit ERRCODE
123
+ end
124
+ # prints messages to stderr
125
+ # All messages should go to stderr.
126
+ # Keep stdout only for output which can be used by other programs
127
+ def message text
128
+ $stderr.puts text
129
+ end
130
+ # print to stderr only if verbose set
131
+ def verbose text
132
+ message(text) if @options[:verbose]
133
+ end
134
+ # print to stderr only if verbose set
135
+ def warning text
136
+ print_red("WARNING: #{text}")
137
+ end
138
+ def print_red text
139
+ message "#{RED}#{text}#{CLEAR}"
140
+ end
141
+ def print_green text
142
+ message "#{GREEN}#{text}#{CLEAR}"
143
+ end
144
+
145
+ ##
146
+ # load data into array as item and task
147
+ # @see save_array to write
148
+ def load_array
149
+ #return if $valid_array
150
+ $valid_array = false
151
+ @data = []
152
+ File.open(@app_file_path).each do |line|
153
+ row = line.chomp.split "\t"
154
+ @data << row
155
+ end
156
+ $valid_array = true
157
+ end
158
+ ##
159
+ # saves the task array to disk
160
+ # Please use load_array to load, and not populate
161
+ def save_array
162
+ raise "Cannot save array! Please use load_array to load" if $valid_array == false
163
+
164
+ File.open(@app_file_path, "w") do |file|
165
+ @data.each { |row| file.puts "#{row[0]}\t#{row[1]}" }
166
+ end
167
+ end
168
+
169
+
170
+ end
data/lib/common/sed.rb CHANGED
@@ -11,54 +11,94 @@
11
11
  # matching lines to it
12
12
 
13
13
  module Sed
14
- def change_row filename, pattern, replacement = nil
15
- d = _read filename
16
- d.each { |row|
17
- if row =~ pattern
18
- if replacement
19
- row.gsub!( pattern, replacement)
20
- else
21
- yield row
14
+ def change_row filename, pattern, replacement = nil
15
+ d = _read filename
16
+ d.each { |row|
17
+ if row =~ pattern
18
+ if replacement
19
+ row.gsub!( pattern, replacement)
20
+ else
21
+ yield row
22
+ end
22
23
  end
24
+ }
25
+ _write filename, d
26
+ end
27
+ def change_file filename
28
+ d = _read filename
29
+ d.each { |row|
30
+ yield row
31
+ }
32
+ _write filename, d
33
+ end
34
+ ##
35
+ # deletes on more rows based on a pattern
36
+ # Also takes a block and yields each row to it
37
+ def delete_row filename, pattern = nil
38
+ d = _read filename
39
+ if pattern
40
+ d.delete_if { |row| row =~ pattern }
41
+ else
42
+ d.delete_if { |row| yield row }
23
43
  end
24
- }
25
- _write filename, d
26
- end
27
- def change_file filename
28
- d = _read filename
29
- d.each { |row|
30
- yield row
31
- }
32
- _write filename, d
33
- end
34
- ##
35
- # deletes on more rows based on a pattern
36
- # Also takes a block and yields each row to it
37
- def delete_row filename, pattern = nil
38
- d = _read filename
39
- if pattern
40
- d.delete_if { |row| row =~ pattern }
41
- else
42
- d.delete_if { |row| yield row }
44
+ _write filename, d
43
45
  end
44
- _write filename, d
45
- end
46
- ##
47
- # read the given filename into an array
48
- def _read filename
49
- d = []
50
- File.open(filename).each { |line|
51
- d << line
52
- }
53
- return d
54
- end
55
- ##
56
- # write the given array to the filename
57
- def _write filename, array
58
- File.open(filename, "w") do |file|
59
- array.each { |row| file.puts row }
46
+ ##
47
+ # inserts text in filename at lineno.
48
+ #
49
+ def insert_row filename, lineno, text
50
+ d = _read filename
51
+ d.insert(lineno, text)
52
+ _write filename, d
53
+ 0
54
+ end
55
+ ##
56
+ # read the given filename into an array
57
+ def _read filename
58
+ d = []
59
+ File.open(filename).each { |line|
60
+ d << line
61
+ }
62
+ return d
63
+ end
64
+ ##
65
+ # write the given array to the filename
66
+ def _write filename, array
67
+ File.open(filename, "w") do |file|
68
+ array.each { |row| file.puts row }
69
+ end
70
+ end
71
+ ##
72
+ # searches filelist array for pattern yielding filename, linenumber and line
73
+ # @return [Array, nil] array of lines containing filename,lineno,line tab delimited
74
+ # or nil if nothing found
75
+ # Taken from http://facets.rubyforge.org/apidoc/index.html more filelist.
76
+ # egrepoptions - count only, linenumber, filename, invert etc
77
+ def egrep(filelist, pattern, egrepoptions={})
78
+ lines = []
79
+ filelist.each do |fn|
80
+ open(fn) do |inf|
81
+ count = 0
82
+
83
+ inf.each do |line|
84
+ count += 1
85
+ if pattern.match(line)
86
+ if block_given?
87
+ yield fn, count, line
88
+ else
89
+ #puts "#{fn}:#{count}:#{line}"
90
+ lines << "#{fn}#{@todo_delim}#{count}#{@todo_delim}#{line}"
91
+ end
92
+ end
93
+ end
94
+
95
+ end
96
+ end
97
+ unless block_given?
98
+ ret = lines.empty? nil:lines
99
+ return ret
100
+ end
60
101
  end
61
- end
62
102
  end # module
63
103
 
64
104
  if __FILE__ == $0