todonotes 0.1.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.
@@ -0,0 +1,38 @@
1
+ $:.unshift('../lib')
2
+ require 'todonotes'
3
+
4
+ to do
5
+ "mein Ergebnis"
6
+ end
7
+
8
+ todo "mein Text"
9
+
10
+ todo { "mein Ergebnis" }
11
+
12
+ todo ('mein Text' ) { "mein Ergebnis" }
13
+
14
+ todo do
15
+ "mein Ergebnis"
16
+ end
17
+
18
+ todo 'Text' do
19
+ "mein Ergebnis"
20
+ end
21
+
22
+ ####################
23
+ 2.times { fixme "mein Text" }
24
+
25
+ fixme { "mein Ergebnis" }
26
+
27
+ fixme ('mein Text' ) { "mein Ergebnis" }
28
+
29
+ fixme do
30
+ "mein Ergebnis"
31
+ end
32
+
33
+ fixme 'Text' do
34
+ "mein Ergebnis"
35
+ end
36
+ ####################
37
+
38
+ Todonotes.print_stats
@@ -0,0 +1,25 @@
1
+ $:.unshift('../lib')
2
+ require 'todonotes'
3
+
4
+ #
5
+ #
6
+ Todonotes.instance.logger.level = Log4r::WARN #only first time of callinf a fixme/todo
7
+ Todonotes.instance.logger.level = Log4r::INFO #report all calls of fixme/todo
8
+
9
+ primecount = 0
10
+ for i in 1..10
11
+ if fixme "Calculate if prime" do
12
+ i.odd? #tempory: odd = prim
13
+ end
14
+ primecount += 1
15
+ puts "#{i} is a prime number"
16
+ else
17
+ puts "#{i} is no prime number"
18
+ end
19
+ end
20
+
21
+ todo "Return total number of primes"
22
+
23
+ #Details
24
+ Todonotes.print_stats()
25
+
@@ -0,0 +1,32 @@
1
+ $:.unshift('../lib')
2
+ require 'todonotes'
3
+
4
+ #
5
+ #
6
+ Todonotes.instance.logger.level = Log4r::WARN #only first time of callinf a fixme/todo
7
+ Todonotes.instance.logger.level = Log4r::INFO #report all calls of fixme/todo
8
+
9
+ class Fixnum
10
+ def prime?
11
+ fixme "Calculate if prime" do
12
+ self.odd? #tempory: odd = prim
13
+ end
14
+ end
15
+ end
16
+
17
+ primecount = 0
18
+ for i in 1..10
19
+ if i.prime?
20
+ primecount += 1
21
+ puts "#{i} is a prime number"
22
+ else
23
+ puts "#{i} is no prime number"
24
+ end
25
+ end
26
+
27
+ todo "Return total number of primes"
28
+
29
+ #Details
30
+ Todonotes.print_stats()
31
+
32
+
data/lib/todonotes.rb ADDED
@@ -0,0 +1,211 @@
1
+ =begin rdoc
2
+ Define todo- and fixme-command.
3
+
4
+ Usage:
5
+ Add todo and fixme to your code and get track of your todos during
6
+ runtime of your code.
7
+
8
+ When you pass a todo/fixme during execution, you get a logging information.
9
+
10
+
11
+ todo ('message' ) { "temporary result" }
12
+ fixme ('message' ) { "temporary result" }
13
+
14
+ todo and fixme have the same syntax, the sematic meaning is:
15
+ * ToDo: Mark missing code.
16
+ * FixMe: Mark code to repair.
17
+
18
+ Disadvantage:
19
+ * Does not replace a good IDE.
20
+ to see the ToDo/FixMe
21
+
22
+ Gem based on a proposal in http://forum.ruby-portal.de/viewtopic.php?f=11&t=11957
23
+
24
+ =end
25
+
26
+ require 'singleton'
27
+ require 'log4r'
28
+
29
+ =begin rdoc
30
+ Define a formatter.
31
+ =end
32
+ class Log4r::FixmeFormatter < Log4r::BasicFormatter
33
+ =begin rdoc
34
+ If event is an Array, the output is adapted.
35
+
36
+ This outputter is only for internal use via Todonotes.
37
+ =end
38
+ def format(event)
39
+ #@@basicformat "%*s %s"
40
+ #~ buff = sprintf("%-*s %-5s", Log4r::MaxLevelLength, Log4r::LNAMES[event.level],
41
+ #~ event.data.is_a?(Array) ? event.data.first : event.name)
42
+ buff = "%-5s" % (event.data.is_a?(Array) ? event.data.first : event.name)
43
+ #~ buff += (event.tracer.nil? ? "" : "(#{event.tracer[2]})") + ": "
44
+ buff << ": "
45
+ buff << format_object(event.data.is_a?(Array) ? event.data.last : event.data)
46
+ buff << (event.tracer.nil? ? "" : " (#{event.tracer.join('/')})")
47
+ buff << "\n"
48
+ buff
49
+ end
50
+ end
51
+
52
+ =begin rdoc
53
+ Singleton definition for a fixme.
54
+
55
+ You can use Fixme#instance to set some global settings:
56
+ * FiXme#log2file Define log file
57
+ * FiXme#logger adapt level, outputter ...
58
+ * FiXme#codeline get Hash with counter per ToDo-locations.
59
+ * FiXme#overview get overview text with ToDo-locations.
60
+ =end
61
+ class Todonotes
62
+ VERSION = '0.1.0'
63
+ include Singleton
64
+ =begin rdoc
65
+ Define the singleton-instance.
66
+ =end
67
+ def initialize()
68
+ # @codeline is a Hash with Filename and codeline (key). Value is the number of calls.
69
+ @codeline = Hash.new(0)
70
+ @logger = Log4r::Logger.new('ToDo')
71
+ @logger.outputters = Log4r::StdoutOutputter.new('ToDo',
72
+ :level => Log4r::ALL,
73
+ :formatter => Log4r::FixmeFormatter
74
+ )
75
+ #~ @logger.trace = true
76
+ end
77
+ #Get logger to define alternative outputters...
78
+ attr_reader :logger
79
+ =begin rdoc
80
+ Write the todo's in a logging file.
81
+
82
+ Default filename is $0.todo
83
+ =end
84
+ def log2file(filename = File.basename($0) + '.todo', level = Log4r::ALL)
85
+ @logger.add( Log4r::FileOutputter.new('ToDo',
86
+ :filename => filename,
87
+ :level => level,
88
+ :formatter => Log4r::FixmeFormatter
89
+ ))
90
+
91
+ end
92
+ #Direct access to the codeline list. See also #todo_overview
93
+ attr_reader :codeline
94
+ =begin rdoc
95
+ Report a FixMe or a ToDo.
96
+
97
+ The comment is logged,
98
+ the block is evaluated to get a temporary result.
99
+ =end
100
+ def todo( comment, type = :ToDo, &block)
101
+ res = nil
102
+ key = caller[1].split(':in').first
103
+ if block_given?
104
+ res = yield self
105
+ res
106
+ end
107
+ log_todo(key, type, comment, res)
108
+ #~ @logger.debug("Return #{res.inspect} instead") if @logger.debug?
109
+ res
110
+ end
111
+ =begin rdoc
112
+ Report the ToDo/FixMe and count occurence.
113
+
114
+ The first occurence is reported as a warning,
115
+ next occurences are informations.
116
+ =end
117
+ def log_todo( key, type, text, res )
118
+
119
+ @codeline[key] += 1
120
+ if @codeline[key] == 1 #First occurence?
121
+ @logger.warn([type, "#{key} #{text} (temporary: #{res.inspect})"])
122
+ else #Erste auftauchen
123
+ @logger.info([type, "#{key}(#{@codeline[key]}) #{text} (temporary: #{res.inspect})"])
124
+ end
125
+
126
+ end
127
+
128
+ =begin rdoc
129
+ Return a text to be printed
130
+ puts Todonotes.instance.todo_overview()
131
+ Used from Todonotes.print_stats
132
+
133
+ Example:
134
+ List of ToDos/FixMes:
135
+ fixme.rb:195: 1 call
136
+ fixme.rb:198: 2 calls
137
+ fixme.rb:199: 1 call
138
+ fixme.rb:200: 1 call
139
+ =end
140
+ def overview( )
141
+ txt = []
142
+ txt << "List of ToDos/FixMes:"
143
+ @codeline.each do |key, messages|
144
+ txt << "%s: %4i call%s" % [ key, messages, messages > 1 ? 's': '' ]
145
+ end
146
+ txt.join("\n")
147
+ end
148
+
149
+ =begin rdoc
150
+ Class methods
151
+ =end
152
+ class << self
153
+ =begin rdoc
154
+ See Todonotes#overview
155
+ =end
156
+ def print_stats()
157
+ puts Todonotes.instance.overview()
158
+ end
159
+ end #<< self
160
+ end
161
+
162
+ =begin rdoc
163
+ Define todo-commands to global usage.
164
+ =end
165
+ module Kernel
166
+ =begin rdoc
167
+ Usage 1 (only message):
168
+ todo "my todo-message""
169
+
170
+ Usage 2 (only temporary result):
171
+ todo { "temporary result" }
172
+ todo do
173
+ "temporary result"
174
+ end
175
+
176
+ Usage 3(message and temporary result):
177
+ todo ('message') { "temporary result" }
178
+ todo ('message') do
179
+ "temporary result"
180
+ end
181
+
182
+ =end
183
+ def todo( comment = 'ToDo', &block)
184
+ Todonotes.instance.todo(comment, &block)
185
+ end
186
+ =begin rdoc
187
+ Usage:
188
+ to do
189
+ :result
190
+ end
191
+ =end
192
+ alias :to :todo
193
+ =begin rdoc
194
+ Add a fixme-command.
195
+
196
+ Can be used to mark available code.
197
+ =end
198
+ def fixme( comment = 'FixMe', &block)
199
+ Todonotes.instance.todo(comment, :FixMe, &block)
200
+ end
201
+ end
202
+
203
+ if $0 == __FILE__
204
+ todo( 'a' ){
205
+ "result"
206
+ }
207
+ 2.times{todo { "result" }}
208
+ fixme { "result" }
209
+ to('a')
210
+ Todonotes.print_stats( )
211
+ end
data/readme.rd ADDED
@@ -0,0 +1,110 @@
1
+ =fixme
2
+ Define todo- and fixme-command.
3
+
4
+ ==Usage:
5
+ Add todo and fixme to your code and get track of your todos during
6
+ runtime of your code.
7
+
8
+ When you pass a todo/fixme during execution, you get a logging information.
9
+
10
+ todo ('message' ) { "temporary result" }
11
+ fixme ('message' ) { "temporary result" }
12
+
13
+ todo and fixme have the same syntax, the sematic meaning is:
14
+ * ToDo: Mark missing code.
15
+ * Todonotes: Mark code to repair.
16
+
17
+ Disadvantage:
18
+ * Does not replace a good IDE.
19
+ to see the ToDo/Todonotes
20
+
21
+ Gem based on a proposal in http://forum.ruby-portal.de/viewtopic.php?f=11&t=11957
22
+
23
+ =Example
24
+
25
+ Think, you have to write a script to count all prime between 1 to 10.
26
+
27
+ You don't know how to check for primes, but at least you know, primes must be odd.
28
+
29
+ So you can start your program:
30
+ require 'todonotes'
31
+
32
+ primecount = 0
33
+ for i in 1..10
34
+ if fixme "Calculate if prime, prim = true, ja, sonst nein" do
35
+ i.odd? #tempory: odd = prim
36
+ end
37
+ primecount += 1
38
+ puts "#{i} is a prime number"
39
+ else
40
+ puts "#{i} is no prime number"
41
+ end
42
+ end
43
+
44
+ todo "Return total number of primes"
45
+
46
+ Or
47
+ require 'todonotes'
48
+ class Fixnum
49
+ def prime?
50
+ fixme "Calculate if prime" do
51
+ self.odd? #tempory: odd = prim
52
+ end
53
+ end
54
+ end
55
+
56
+ primecount = 0
57
+ for i in 1..10
58
+ if i.prime?
59
+ primecount += 1
60
+ puts "#{i} is a prime number"
61
+ else
62
+ puts "#{i} is no prime number"
63
+ end
64
+ end
65
+
66
+ todo "Return total number of primes"
67
+
68
+ Now you get a output like this:
69
+
70
+ Todonotes: todonotes_prim2.rb:12 Calculate if prime misssing (temporary: true)
71
+ 1 is a prime number
72
+ Todonotes: todonotes_prim2.rb:12(2) Calculate if prime misssing (temporary: false)
73
+ 2 is no prime number
74
+ Todonotes: todonotes_prim2.rb:12(3) Calculate if prime misssing (temporary: true)
75
+ ...
76
+ ToDo : todonotes_prim2.rb:27 Return total number of primes (temporary: nil)
77
+
78
+
79
+ The Todonotes is warning about a wrong or uncompleted code piece.
80
+
81
+ The ToDo is warning for a missing code piece.
82
+
83
+ You are informed about source code file and line number. In braces you get the number of calls.
84
+
85
+ The todo/fixme command evaluates the optional block.
86
+ The result is returned as a temporary result (in this example: odd numbers are primes.).
87
+
88
+ ==Logging
89
+
90
+ The Fixme and ToDo are reported via a logger.
91
+ The first call of a fixme/todo is a warning, the next call is an information.
92
+
93
+
94
+ You may change the level with:
95
+ Todonotes.instance.logger.level = Log4r::WARN #only first time of callinf a fixme/todo
96
+ Todonotes.instance.logger.level = Log4r::INFO #report all calls of fixme/todo
97
+
98
+ You can log the fixme/todos to a file:
99
+ Todonotes.instance.log2file()
100
+
101
+ ==Get Overview
102
+ You may print an overview on all fixme/todos:
103
+ Todonotes.print_stats()
104
+
105
+ Example:
106
+ List of ToDos/Todonotess:
107
+ todonotes_prim.rb:11: 10 calls
108
+ todonotes_prim.rb:21: 1 call
109
+
110
+ There is a fixme/todo in line 11 and 21 in todonotes_prim.rb.
@@ -0,0 +1,177 @@
1
+ gem 'test-unit'
2
+ require 'test/unit'
3
+
4
+ $:.unshift('../lib')
5
+ require 'todonotes'
6
+
7
+ =begin rdoc
8
+ Define a new outputter to catch data into an array
9
+ =end
10
+ class ArrayOutputter < Log4r::StdoutOutputter
11
+ =begin rdoc
12
+ Collect messages in array.
13
+ =end
14
+ def write(message)
15
+ @messages ||= [] #create with first call
16
+ @messages << message
17
+ end
18
+ =begin rdoc
19
+ Clear message array and return messages
20
+ =end
21
+ def flush
22
+ @messages ||= [] #create with first call
23
+ messages = @messages.dup
24
+ @messages.clear
25
+ messages
26
+ end
27
+ end #ArrayOutputter
28
+
29
+ #~ Todonotes.instance.logger.level = Log4r::OFF #No logging
30
+ Todonotes.instance.logger.outputters.first.level = Log4r::OFF
31
+ Todonotes.instance.logger.outputters << $testlog = ArrayOutputter.new('testlog')
32
+ $testlog.formatter = Log4r::FixmeFormatter.new
33
+
34
+ class Test_syntax < Test::Unit::TestCase
35
+ def test_todo()
36
+ assert_nothing_raised{
37
+ to do
38
+ "mein Ergebnis"
39
+ end
40
+ }
41
+ assert_nothing_raised{
42
+ todo "mein Text"
43
+ }
44
+ assert_nothing_raised{
45
+ todo { "mein Ergebnis" }
46
+ }
47
+ assert_nothing_raised{
48
+ todo ('mein Text' ) { "mein Ergebnis" }
49
+ }
50
+ assert_nothing_raised{
51
+ todo do
52
+ "mein Ergebnis"
53
+ end
54
+ }
55
+ assert_nothing_raised{
56
+ todo 'Text' do
57
+ "mein Ergebnis"
58
+ end
59
+ }
60
+ end
61
+ def test_fixme
62
+ assert_nothing_raised{
63
+ fixme "mein Text"
64
+ }
65
+ assert_nothing_raised{
66
+ fixme { "mein Ergebnis" }
67
+ }
68
+ assert_nothing_raised{
69
+ fixme ('mein Text' ) { "mein Ergebnis" }
70
+ }
71
+ assert_nothing_raised{
72
+ fixme do
73
+ "mein Ergebnis"
74
+ end
75
+ }
76
+ assert_nothing_raised{
77
+ fixme 'Text' do
78
+ "mein Ergebnis"
79
+ end
80
+ }
81
+ end
82
+ #~ def test_print_stats
83
+ #~ assert_nothing_raised{ print_stats }
84
+ #~ end
85
+ end
86
+
87
+ class Test_value_and_log < Test::Unit::TestCase
88
+ def setup()
89
+ $testlog.flush
90
+ end
91
+
92
+ def test_todo()
93
+ assert_equal("mein Ergebnis", todo() { "mein Ergebnis" } )
94
+ assert_equal(["ToDo : #{__FILE__}:#{__LINE__ - 1} ToDo (temporary: \"mein Ergebnis\")\n"], $testlog.flush )
95
+
96
+ assert_equal("mein Ergebnis", todo( 'text' ){"mein Ergebnis"} )
97
+ assert_equal(["ToDo : #{__FILE__}:#{__LINE__ - 1} text (temporary: \"mein Ergebnis\")\n"], $testlog.flush )
98
+
99
+ assert_equal(nil, todo( "my text"))
100
+ assert_equal(["ToDo : #{__FILE__}:#{__LINE__ - 1} my text (temporary: nil)\n"], $testlog.flush )
101
+
102
+ end
103
+ def test_fixme
104
+ assert_equal("mein Ergebnis", fixme() {"mein Ergebnis"} )
105
+ assert_equal(["FixMe: #{__FILE__}:#{__LINE__ - 1} FixMe (temporary: \"mein Ergebnis\")\n"], $testlog.flush )
106
+
107
+ assert_equal("mein Ergebnis", fixme( 'text' ){"mein Ergebnis"} )
108
+ assert_equal(["FixMe: #{__FILE__}:#{__LINE__ - 1} text (temporary: \"mein Ergebnis\")\n"], $testlog.flush )
109
+
110
+ assert_equal(nil, fixme( "my text"))
111
+ assert_equal(["FixMe: #{__FILE__}:#{__LINE__ - 1} my text (temporary: nil)\n"], $testlog.flush )
112
+ end
113
+ end
114
+
115
+ class Test_overview < Test::Unit::TestCase
116
+ def test_overview()
117
+ Todonotes.instance.codeline.clear
118
+
119
+ #check empty fixme/todo
120
+ text = "List of ToDos/FixMes:"
121
+ codeline = {}
122
+ assert_equal(text, Todonotes.instance.overview())
123
+ assert_equal(codeline, Todonotes.instance.codeline)
124
+
125
+ line = __LINE__; fixme('a')
126
+ text << "\n#{__FILE__}:#{line}: 1 call"
127
+ codeline["#{__FILE__}:#{line}"] = 1
128
+ assert_equal(text, Todonotes.instance.overview())
129
+ assert_equal(codeline, Todonotes.instance.codeline)
130
+
131
+ #Add 2nd todo
132
+ line = __LINE__; fixme('b')
133
+ text << "\n#{__FILE__}:#{line}: 1 call"
134
+ codeline["#{__FILE__}:#{line}"] = 1
135
+ assert_equal(text, Todonotes.instance.overview())
136
+ assert_equal(codeline, Todonotes.instance.codeline)
137
+
138
+ #check plural-s in calls
139
+ line = __LINE__; 2.times{ fixme('c') }
140
+ text << "\n#{__FILE__}:#{line}: 2 calls"
141
+ codeline["#{__FILE__}:#{line}"] = 2
142
+ assert_equal(text, Todonotes.instance.overview())
143
+ assert_equal(codeline, Todonotes.instance.codeline)
144
+ end
145
+ end
146
+
147
+ class Test_log_with_file < Test::Unit::TestCase
148
+ @@logfilename = 'test.log'
149
+ @@logfilename_default = File.basename($0) + '.todo'
150
+ def setup()
151
+ File.delete(@@logfilename) if File.exist?(@@logfilename)
152
+ File.delete(@@logfilename_default) if File.exist?(@@logfilename_default)
153
+ end
154
+ def teardown()
155
+ File.delete(@@logfilename) if File.exist?(@@logfilename)
156
+ File.delete(@@logfilename_default) if File.exist?(@@logfilename_default)
157
+ end
158
+ def test_logfile()
159
+ assert_false(File.exist?(@@logfilename))
160
+ Todonotes.instance.log2file(@@logfilename)
161
+ assert_equal(@@logfilename, Todonotes.instance.logger.outputters.last.filename)
162
+ assert_true(File.exist?(@@logfilename))
163
+ Todonotes.instance.logger.outputters.last.close #
164
+ Todonotes.instance.logger.outputters.pop #
165
+ end
166
+ def test_logfile_default()
167
+ assert_false(File.exist?(@@logfilename_default))
168
+ Todonotes.instance.log2file() #no filename
169
+ assert_equal(@@logfilename_default, Todonotes.instance.logger.outputters.last.filename)
170
+ assert_true(File.exist?(@@logfilename_default))
171
+ Todonotes.instance.logger.outputters.last.close #
172
+ Todonotes.instance.logger.outputters.pop #
173
+ end
174
+ end
175
+
176
+
177
+ __END__
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: todonotes
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Knut Lickert
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-24 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: log4r
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: |
36
+ todonotes.
37
+ Support programming by fixme/todo commands
38
+
39
+ Gem based on a proposal in http://forum.ruby-portal.de/viewtopic.php?f=11&t=11957
40
+
41
+ email: knut@lickert.net
42
+ executables: []
43
+
44
+ extensions: []
45
+
46
+ extra_rdoc_files:
47
+ - readme.rd
48
+ files:
49
+ - readme.rd
50
+ - lib/todonotes.rb
51
+ - examples/todonotes_how_to.rb
52
+ - examples/todonotes_prim.rb
53
+ - examples/todonotes_prim2.rb
54
+ - unittest/unittest_todonotes.rb
55
+ has_rdoc: true
56
+ homepage:
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - readme.rd
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.7
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Support programming by todonotes/todo commands.
90
+ test_files:
91
+ - unittest/unittest_todonotes.rb