dnote 1.1.4 → 1.2.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.
Files changed (52) hide show
  1. data/HISTORY +29 -0
  2. data/bin/dnote +2 -2
  3. data/lib/dnote.rb +2 -3
  4. data/lib/dnote/format.rb +26 -69
  5. data/lib/dnote/note.rb +57 -0
  6. data/lib/dnote/notes.rb +158 -97
  7. data/lib/dnote/session.rb +277 -0
  8. data/lib/dnote/templates/html.erb +4 -4
  9. data/lib/dnote/templates/html/file.erb +40 -0
  10. data/lib/dnote/templates/html/label.erb +41 -0
  11. data/lib/dnote/templates/html/list.erb +33 -0
  12. data/lib/dnote/templates/json.erb +8 -0
  13. data/lib/dnote/templates/json/file.erb +8 -0
  14. data/lib/dnote/templates/json/label.erb +8 -0
  15. data/lib/dnote/templates/json/list.erb +8 -0
  16. data/lib/dnote/templates/md.erb +18 -0
  17. data/lib/dnote/templates/md/file.erb +13 -0
  18. data/lib/dnote/templates/md/label.erb +18 -0
  19. data/lib/dnote/templates/md/list.erb +9 -0
  20. data/lib/dnote/templates/rdoc.erb +3 -3
  21. data/lib/dnote/templates/rdoc/file.erb +9 -0
  22. data/lib/dnote/templates/rdoc/label.erb +11 -0
  23. data/lib/dnote/templates/rdoc/list.erb +6 -0
  24. data/lib/dnote/templates/soap.erb +4 -0
  25. data/lib/dnote/templates/soap/file.erb +4 -0
  26. data/lib/dnote/templates/soap/label.erb +4 -0
  27. data/lib/dnote/templates/soap/list.erb +4 -0
  28. data/lib/dnote/templates/text.erb +11 -0
  29. data/lib/dnote/templates/text/file.erb +10 -0
  30. data/lib/dnote/templates/text/label.erb +11 -0
  31. data/lib/dnote/templates/text/list.erb +7 -0
  32. data/lib/dnote/templates/xml.erb +6 -6
  33. data/lib/dnote/templates/xml/file.erb +15 -0
  34. data/lib/dnote/templates/xml/label.erb +15 -0
  35. data/lib/dnote/templates/xml/list.erb +6 -0
  36. data/lib/dnote/templates/xoxo.erb +4 -0
  37. data/lib/dnote/templates/xoxo/file.erb +4 -0
  38. data/lib/dnote/templates/xoxo/label.erb +4 -0
  39. data/lib/dnote/templates/xoxo/list.erb +6 -0
  40. data/lib/dnote/templates/yaml.erb +1 -0
  41. data/lib/dnote/templates/yaml/file.erb +1 -0
  42. data/lib/dnote/templates/yaml/label.erb +1 -0
  43. data/lib/dnote/templates/yaml/list.erb +1 -0
  44. data/lib/plugins/syckle/dnote.rb +35 -8
  45. data/meta/version +1 -1
  46. data/test/cases/notes_case.rb +20 -31
  47. metadata +44 -14
  48. data/MANIFEST +0 -33
  49. data/lib/dnote/command.rb +0 -134
  50. data/lib/dnote/site.rb +0 -140
  51. data/lib/dnote/templates/gnu.erb +0 -8
  52. data/lib/dnote/templates/markdown.erb +0 -17
data/HISTORY CHANGED
@@ -1,5 +1,34 @@
1
1
  = RELEASE HISTORY
2
2
 
3
+ == 1.2 / 2010-02-18
4
+
5
+ By request this release adds additional formats, allowing notes to be
6
+ sorted by filename as well a label. In addition, paths can now be
7
+ excluded from the search. To implement these changes it was necessary
8
+ to makes some significant under-the-hood adjustments, and this required
9
+ making some adjustments to the design of the templates and the
10
+ command-line interface.
11
+
12
+ If are using any of your own custom templates you will have to make
13
+ adjustments accordingly --which basically entails exchanging +notes.each+
14
+ for +notes.by_label_file.each+. Also, notice that the serialization formats
15
+ have changed accordingly to match the improved underlying model.
16
+
17
+ On the command-line, the format type itself is no longer used as the
18
+ option name, e.g. "--yaml", but instead use "-f", e.g. "-f yaml". This
19
+ opens DNote up to many more templates. Use "-T" to get a list of all
20
+ template format available.
21
+
22
+ Changes:
23
+
24
+ * Improve underlying model by adding a Note class.
25
+ * Add --exclude and --ignore options.
26
+ * Add new formats and rename "gnu" formats to "text".
27
+ * Use --format/-f to designate formats.
28
+ * Renamed --template/-t option to --custom/-c.
29
+ * Add --templates/-T to list all format templates.
30
+
31
+
3
32
  == 1.1 / 2010-02-06
4
33
 
5
34
  This relase primarily adjusts the way output it rendered
data/bin/dnote CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- require "dnote/command"
3
- DNote.run
2
+ require "dnote"
3
+ DNote::Session.main(*ARGV)
4
4
 
@@ -1,8 +1,7 @@
1
1
  module DNote
2
- VERSION = "1.1.3" #:till: VERSION = "<%= version %>"
2
+ VERSION = "1.2.0" #:till: VERSION = "<%= version %>"
3
3
 
4
- require 'dnote/notes'
5
- require 'dnote/format'
4
+ require 'dnote/session'
6
5
 
7
6
  # NOTE: Toying with the idea of making DNote a class.
8
7
 
@@ -24,6 +24,9 @@ module DNote
24
24
  #
25
25
  attr_accessor :format
26
26
 
27
+ #
28
+ attr_accessor :subtype
29
+
27
30
  #
28
31
  attr_accessor :output
29
32
 
@@ -38,12 +41,12 @@ module DNote
38
41
 
39
42
  #
40
43
  def initialize(notes, options={})
41
- @notes = notes
42
- @format = :gnu
43
- @title = "Developer's Notes"
44
- options.each do |k,v|
45
- __send__("#{k}=", v) if v
46
- end
44
+ @notes = notes
45
+ @format = 'text'
46
+ @subtype = 'label'
47
+ @title = "Developer's Notes"
48
+ options.each{ |k,v| __send__("#{k}=", v) if v }
49
+ yield(self) if block_given?
47
50
  end
48
51
 
49
52
  #
@@ -51,78 +54,32 @@ module DNote
51
54
  if notes.empty?
52
55
  $stderr << "No #{notes.labels.join(', ')} notes.\n"
53
56
  else
54
- raise ArgumentError unless respond_to?("render_#{format}")
55
- __send__("render_#{format}")
57
+ case format
58
+ when 'custom'
59
+ render_custom
60
+ else
61
+ render_template
62
+ end
56
63
  end
57
64
  end
58
65
 
59
- # S E R I A L I Z A T I O N
60
-
61
- def render_yaml
62
- result = notes.to_yaml
63
- publish(result)
64
- end
65
-
66
- def render_json
67
- result = notes.to_json
68
- publish(result)
69
- end
70
-
71
- # M L M A R K U P
72
-
73
- def render_soap
74
- result = notes.to_soap
75
- publish(result)
76
- end
77
-
78
- def render_xoxo
79
- result = notes.to_xoxo
80
- publish(result)
81
- end
82
-
83
- def render_xml
84
- template = File.join(File.dirname(__FILE__), 'templates/xml.erb')
85
- result = erb(template)
86
- publish(result)
87
- end
88
-
89
- def render_html
90
- template = File.join(File.dirname(__FILE__), 'templates/html.erb')
91
- result = erb(template)
92
- publish(result)
93
- end
94
-
95
- def render_index
96
- template = File.join(File.dirname(__FILE__), 'templates/html.erb')
97
- result = erb(template)
98
- publish(result, 'index.html')
99
- end
100
-
101
- # W I K I M A R K U P
102
-
103
- def render_gnu
104
- template = File.join(File.dirname(__FILE__), 'templates/gnu.erb')
105
- result = erb(template)
106
- publish(result)
107
- end
66
+ # C U S T O M
108
67
 
109
- def render_rdoc
110
- template = File.join(File.dirname(__FILE__), 'templates/rdoc.erb')
111
- result = erb(template)
112
- publish(result)
113
- end
114
-
115
- def render_markdown
116
- template = File.join(File.dirname(__FILE__), 'templates/markdown.erb')
68
+ #
69
+ def render_custom
70
+ #raise ArgumentError unless File.exist?(template)
117
71
  result = erb(template)
118
- publish(result)
72
+ publish(result)
119
73
  end
120
74
 
121
- # C U S T O M T E M P L A T E
75
+ # T E M P L A T E
122
76
 
123
- def render_custom
77
+ #
78
+ def render_template
79
+ template = File.join(File.dirname(__FILE__), 'templates', "#{format}.erb")
80
+ raise "No such format - #{format}" unless File.exist?(template)
124
81
  result = erb(template)
125
- publish(result)
82
+ publish(result)
126
83
  end
127
84
 
128
85
  private
@@ -0,0 +1,57 @@
1
+ module DNote
2
+
3
+ #
4
+ class Note
5
+ attr :file
6
+ attr :label
7
+ attr :line
8
+ attr :text
9
+
10
+ def initialize(file, label, line, text)
11
+ @file = file
12
+ @label = label
13
+ @line = line
14
+ @text = text.rstrip
15
+ end
16
+
17
+ #
18
+ def to_s
19
+ "#{label}: #{text}"
20
+ end
21
+
22
+ #
23
+ def to_str
24
+ "#{label}: #{text}"
25
+ end
26
+
27
+ #
28
+ def textline
29
+ text.gsub("\n", " ")
30
+ end
31
+
32
+ # Sort by file name and line number.
33
+ def <=>(other)
34
+ s = file <=> other.file
35
+ return s unless s == 0
36
+ line <=> other.line
37
+ end
38
+
39
+ def to_h
40
+ { 'label'=>label, 'text'=>textline, 'file'=>file, 'line'=>line }
41
+ end
42
+
43
+ def to_h_raw
44
+ { 'label'=>label, 'text'=>text, 'file'=>file, 'line'=>line }
45
+ end
46
+
47
+ def to_json(*args)
48
+ to_h_raw.to_json(*args)
49
+ end
50
+
51
+ def to_yaml(*args)
52
+ to_h_raw.to_yaml(*args)
53
+ end
54
+ end
55
+
56
+ end
57
+
@@ -1,15 +1,16 @@
1
1
  require 'pathname'
2
+ require 'dnote/note'
2
3
 
3
4
  module DNote
4
5
 
5
6
  # = Developer Notes
6
7
  #
7
8
  # This class goes through you source files and compiles a list
8
- # of any labeled comments. Labels are single word prefixes to
9
- # a comment ending in a colon.
9
+ # of any labeled comments. Labels are all-cap single word prefixes
10
+ # to a comment ending in a colon.
10
11
  #
11
- # By default the labels supported are TODO, FIXME, OPTIMIZE
12
- # and DEPRECATE.
12
+ # Special labels do require the colon. By default these are +TODO+,
13
+ # +FIXME+, +OPTIMIZE+ and +DEPRECATE+.
13
14
  #
14
15
  #--
15
16
  # TODO: Add ability to read header notes. They often
@@ -21,59 +22,58 @@ module DNote
21
22
  # Default paths (all ruby scripts).
22
23
  DEFAULT_PATHS = ["**/*.rb"]
23
24
 
24
- # Default note labels to look for in source code.
25
+ # Default note labels to look for in source code. (NOT CURRENTLY USED!)
25
26
  DEFAULT_LABELS = ['TODO', 'FIXME', 'OPTIMIZE', 'DEPRECATE']
26
27
 
27
- # Paths to search.
28
- attr_accessor :paths
28
+ # Files to search for notes.
29
+ attr_accessor :files
29
30
 
30
- # Labels to document. Defaults are: TODO, FIXME, OPTIMIZE and DEPRECATE.
31
+ # Labels to document. Defaults are: +TODO+, +FIXME+, +OPTIMIZE+ and +DEPRECATE+.
31
32
  attr_accessor :labels
32
33
 
33
- #
34
- def initialize(paths, labels=nil)
35
- @paths = [paths || DEFAULT_PATHS ].flatten
36
- @labels = [labels || DEFAULT_LABELS].flatten
34
+ # Require label colon? Default is +true+.
35
+ attr_accessor :colon
36
+
37
+ # New set of notes for give +files+ and optional special labels.
38
+ def initialize(files, options={})
39
+ @files = [files].flatten
40
+ @labels = [options[:labels]].flatten.compact
41
+ @colon = options[:colon].nil? ? true : options[:colon]
37
42
  parse
38
43
  end
39
44
 
40
- #
45
+ # Array of notes.
41
46
  def notes
42
47
  @notes
43
48
  end
44
49
 
45
- #
50
+ # Notes counts by label.
46
51
  def counts
47
- @counts
52
+ @counts ||= (
53
+ h = {}
54
+ by_label.each do |label, notes|
55
+ h[label] = notes.size
56
+ end
57
+ h
58
+ )
48
59
  end
49
60
 
50
- #
61
+ # Iterate through notes.
51
62
  def each(&block)
52
63
  notes.each(&block)
53
64
  end
54
65
 
55
- #
66
+ # No notes?
56
67
  def empty?
57
68
  notes.empty?
58
69
  end
59
70
 
60
- #
61
- def labels=(labels)
62
- @labels = (
63
- case labels
64
- when String
65
- labels.split(/[:;,]/)
66
- else
67
- labels = [labels].flatten.compact.uniq.map{ |s| s.to_s }
68
- end
69
- )
70
- end
71
-
72
- # Gather and count notes. This returns two elements,
73
- # a hash in the form of label=>notes and a counts hash.
74
-
71
+ # Gather notes.
72
+ #--
73
+ # TODO: Play gold with Notes#parse.
74
+ #++
75
75
  def parse
76
- records, counts = [], Hash.new(0)
76
+ records = []
77
77
  files.each do |fname|
78
78
  next unless File.file?(fname)
79
79
  #next unless fname =~ /\.rb$/ # TODO: should this be done?
@@ -81,13 +81,12 @@ module DNote
81
81
  lineno, save, text = 0, nil, nil
82
82
  while line = f.gets
83
83
  lineno += 1
84
- save = match_common(line, lineno, fname) || match_arbitrary(line, lineno, fname)
84
+ save = match(line, lineno, fname)
85
85
  if save
86
86
  #file = fname
87
- text = save['note']
87
+ text = save.text
88
88
  #save = {'label'=>label,'file'=>file,'line'=>line_no,'note'=>text}
89
89
  records << save
90
- counts[save['label']] += 1
91
90
  else
92
91
  if text
93
92
  if line =~ /^\s*[#]{0,1}\s*$/ or line !~ /^\s*#/ or line =~ /^\s*#[+][+]/
@@ -105,98 +104,160 @@ module DNote
105
104
  end
106
105
  end
107
106
  end
108
- # organize the notes
109
- notes = organize(records)
110
- #
111
- @notes, @counts = notes, counts
107
+
108
+ @notes = records.sort
112
109
  end
113
110
 
114
111
  #
115
- def files
116
- @files ||= (
117
- [self.paths].flatten.map do |path|
118
- if File.directory?(path)
119
- Dir.glob(File.join(path, '**/*'))
120
- else
121
- Dir.glob(path)
122
- end
123
- end.flatten.uniq
124
- )
112
+ def match(line, lineno, file)
113
+ if labels.empty?
114
+ match_general(line, lineno, file)
115
+ else
116
+ match_special(line, lineno, file)
117
+ end
125
118
  end
126
119
 
127
- # TODO: ruby-1.9.1-p378 reports: notes.rb:131:in `match': invalid byte sequence in UTF-8
128
- def match_common(line, lineno, file)
120
+ # Match special notes.
121
+ def match_special(line, lineno, file)
129
122
  rec = nil
130
123
  labels.each do |label|
131
- if md = /\#\s*#{Regexp.escape(label)}[:]?\s*(.*?)$/.match(line)
124
+ if md = match_special_regex(label).match(line)
132
125
  text = md[1]
133
- rec = {'label'=>label,'file'=>file,'line'=>lineno,'note'=>text}
126
+ #rec = {'label'=>label,'file'=>file,'line'=>lineno,'note'=>text}
127
+ rec = Note.new(file, label, lineno, text)
134
128
  end
135
129
  end
136
- return rec
130
+ rec
137
131
  end
138
132
 
139
- #
140
- def match_arbitrary(line, lineno, file)
133
+ #--
134
+ # TODO: ruby-1.9.1-p378 reports: `match': invalid byte sequence in UTF-8
135
+ #++
136
+ def match_special_regex(label)
137
+ if colon
138
+ /\#\s*#{Regexp.escape(label)}[:]\s*(.*?)$/
139
+ else
140
+ /\#\s*#{Regexp.escape(label)}[:]?\s*(.*?)$/
141
+ end
142
+ end
143
+
144
+ # Match notes that are labeled with a colon.
145
+ def match_general(line, lineno, file)
141
146
  rec = nil
142
- labels.each do |label|
143
- if md = /\#\s*([A-Z]+)[:]\s*(.*?)$/.match(line)
144
- label, text = md[1], md[2]
145
- rec = {'label'=>label,'file'=>file,'line'=>lineno,'note'=>text}
146
- end
147
+ if md = match_general_regex.match(line)
148
+ label, text = md[1], md[2]
149
+ #rec = {'label'=>label,'file'=>file,'line'=>lineno,'note'=>text}
150
+ rec = Note.new(file, label, lineno, text)
147
151
  end
148
152
  return rec
149
153
  end
150
154
 
151
- # Organize records in heirarchical form.
152
155
  #
153
- def organize(records)
154
- orecs = {}
155
- records.each do |record|
156
- label = record['label']
157
- file = record['file']
158
- line = record['line']
159
- note = record['note'].rstrip
160
- orecs[label] ||= {}
161
- orecs[label][file] ||= []
162
- orecs[label][file] << [line, note]
156
+ def match_general_regex
157
+ if colon
158
+ /\#\s*([A-Z]+)[:]\s+(.*?)$/
159
+ else
160
+ /\#\s*([A-Z]+)[:]?\s+(.*?)$/
163
161
  end
164
- orecs
165
162
  end
166
163
 
167
- #
168
- def to(format)
169
- __send__("to_#{format}")
164
+ # Organize notes into a hash with labels for keys.
165
+ def by_label
166
+ @by_label ||= (
167
+ list = {}
168
+ notes.each do |note|
169
+ list[note.label] ||= []
170
+ list[note.label] << note
171
+ list[note.label].sort #!{ |a,b| a.line <=> b.line }
172
+ end
173
+ list
174
+ )
170
175
  end
171
176
 
172
- #
173
- def to_yaml
174
- require 'yaml'
175
- notes.to_yaml
177
+ # Organize notes into a hash with filename for keys.
178
+ def by_file
179
+ @by_file ||= (
180
+ list = {}
181
+ notes.each do |note|
182
+ list[note.file] ||= []
183
+ list[note.file] << note
184
+ list[note.file].sort! #!{ |a,b| a.line <=> b.line }
185
+ end
186
+ list
187
+ )
176
188
  end
177
189
 
178
- #
179
- def to_json
180
- begin
181
- require 'json'
182
- rescue LoadError
183
- require 'json_pure'
184
- end
185
- notes.to_json
190
+ # Organize notes into a hash with labels for keys, followed
191
+ # by a hash with filename for keys.
192
+ def by_label_file
193
+ @by_label ||= (
194
+ list = {}
195
+ notes.each do |note|
196
+ list[note.label] ||= {}
197
+ list[note.label][note.file] ||= []
198
+ list[note.label][note.file] << note
199
+ list[note.label][note.file].sort! #{ |a,b| a.line <=> b.line }
200
+ end
201
+ list
202
+ )
203
+ end
204
+
205
+ # Organize notes into a hash with filenames for keys, followed
206
+ # by a hash with labels for keys.
207
+ def by_file_label
208
+ @by_file ||= (
209
+ list = {}
210
+ notes.each do |note|
211
+ list[note.file] ||= {}
212
+ list[note.file][note.label] ||= []
213
+ list[note.file][note.label] << note
214
+ list[note.file][note.label].sort! #{ |a,b| a.line <=> b.line }
215
+ end
216
+ list
217
+ )
186
218
  end
187
219
 
188
- # Soap envelope XML.
189
- def to_soap
190
- require 'soap/marshal'
191
- SOAP::Marshal.marshal(notes)
220
+ # Convert to an array of hashes.
221
+ def to_a
222
+ notes.map{ |n| n.to_h }
192
223
  end
193
224
 
194
- # XOXO microformat.
195
- def to_xoxo
196
- require 'xoxo'
197
- notes.to_xoxo
225
+ # Same as #by_label.
226
+ def to_h
227
+ by_label
198
228
  end
199
229
 
230
+ # Convert to array of hashes then to YAML.
231
+ #def to_yaml
232
+ # require 'yaml'
233
+ # to_a.to_yaml
234
+ #end
235
+
236
+ # Convert to array of hashes then to JSON.
237
+ #def to_json
238
+ # begin
239
+ # require 'json'
240
+ # rescue LoadError
241
+ # require 'json_pure'
242
+ # end
243
+ # to_a.to_json
244
+ #end
245
+
246
+ # Convert to array of hashes then to a SOAP XML envelope.
247
+ #def to_soap
248
+ # require 'soap/marshal'
249
+ # SOAP::Marshal.marshal(to_a)
250
+ #end
251
+
252
+ # XOXO microformat.
253
+ #--
254
+ # TODO: Would to_xoxo be better organized by label and or file?
255
+ #++
256
+ #def to_xoxo
257
+ # require 'xoxo'
258
+ # to_a.to_xoxo
259
+ #end
260
+
200
261
  end
201
262
 
202
263
  end