todorb 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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