todonotes 0.1.0

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