mvz-dnote 1.8.0 → 1.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b9675201f53edcd5b27e0121bd08844769047c613d3d92b44b7ec9326e2f49d
4
- data.tar.gz: 0b386e81dea084ee1618d6fd13fe48b5a8c15ec6be9a420442880f715956c05a
3
+ metadata.gz: 63a1703569a00e121051d24aa575d670c35a073d2ad3bb297ac21d9962df74c4
4
+ data.tar.gz: bb4a5b8e4af7345fd785a99437894558fde1db23afec33483fba5cc80a48bf2d
5
5
  SHA512:
6
- metadata.gz: dfe4a7bb7d9fb549025519ee59030c863e3a4c9242a55f96bdbb5dc17d93d9eae569f09f16ed39a3fb107382b753fc307cf2c8fad543bc7c819cba85f7a1010b
7
- data.tar.gz: 190179a14bcddc1ae626107c05237afc6adce940e2c72047b3a7e4f3348c0646bb82c59ed4984357feb716113c068d749819005d7247f48536e15549efff6fae
6
+ metadata.gz: 42983874e4878d69f6e6611a5498ca3fa8fe69432970430851375a42d7c8380c2a30c3dcdd7a72b867c570b35dcd9c7dcee47236608cff0869fa85ddc20e6fb2
7
+ data.tar.gz: 4818f542b9c8ff57c1764ab33e54d938777d23c24b78713f45d19cb6b84c55d5705bbe0cdbf907475d81486e9ae917b296b554382ff35fef0dcc72b7aed24719
data/HISTORY.rdoc CHANGED
@@ -1,5 +1,14 @@
1
1
  = RELEASE HISTORY
2
2
 
3
+ == Unreleased
4
+
5
+ == 1.9.0 / 2021-09-17
6
+
7
+ * Drop support for Ruby 2.3 and 2.4
8
+ * Officially support Ruby 2.7 and 3.0
9
+ * Update development dependencies
10
+ * Improve code quality
11
+
3
12
  == 1.8.0 / 2018-12-29
4
13
 
5
14
  * Officially support CRuby 2.5 and 2.6
data/README.md CHANGED
@@ -5,9 +5,6 @@
5
5
  * [Source Code](http://github.com/rubyworks/dnote)
6
6
 
7
7
  [![Gem Version](https://badge.fury.io/rb/mvz-dnote.svg)](https://badge.fury.io/rb/mvz-dnote)
8
- [![Build Status](https://travis-ci.org/mvz/mvz-dnote.svg?branch=master)](https://travis-ci.org/mvz/mvz-dnote)
9
- [![Coverage Status](https://coveralls.io/repos/github/mvz/mvz-dnote/badge.svg?branch=master)](https://coveralls.io/github/mvz/mvz-dnote?branch=master)
10
- [![Dependency Status](https://gemnasium.com/badges/github.com/mvz/mvz-dnote.svg)](https://gemnasium.com/github.com/mvz/mvz-dnote)
11
8
  [![Maintainability](https://api.codeclimate.com/v1/badges/608621bbad5de3a98e3b/maintainability)](https://codeclimate.com/github/mvz/dnote/maintainability)
12
9
 
13
10
  ## DESCRIPTION
data/bin/dnote CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'dnote'
4
+ require "dnote"
5
5
 
6
6
  begin
7
7
  DNote::Session.main(*ARGV)
8
- rescue StandardError => err
9
- raise err if $DEBUG
8
+ rescue StandardError => e
9
+ raise e if $DEBUG
10
10
 
11
- puts err
11
+ puts e
12
12
  exit 1
13
13
  end
@@ -13,9 +13,9 @@ module DNote
13
13
 
14
14
  def indent(num)
15
15
  if num >= 0
16
- gsub(/^/, ' ' * num)
16
+ gsub(/^/, " " * num)
17
17
  else
18
- gsub(/^ {0,#{-num}}/, '')
18
+ gsub(/^ {0,#{-num}}/, "")
19
19
  end
20
20
  end
21
21
 
data/lib/dnote/format.rb CHANGED
@@ -9,35 +9,27 @@ module DNote
9
9
  # TODO: Need XSL?
10
10
  #++
11
11
  class Format
12
- require 'fileutils'
13
- require 'erb'
14
- require 'rexml/text'
15
- require 'dnote/core_ext'
16
-
17
- EXTENSIONS = { 'text' => 'txt', 'soap' => 'xml', 'xoxo' => 'xml' }.freeze
18
-
19
- attr_reader :notes
20
-
21
- attr_accessor :format
22
-
23
- attr_accessor :subtype
24
-
25
- attr_accessor :output
26
-
27
- attr_accessor :template
28
-
29
- attr_accessor :title
30
-
31
- attr_accessor :dryrun
32
-
33
- def initialize(notes, options = {})
34
- @notes = notes
35
- @format = 'text'
36
- @subtype = 'label'
37
- @title = "Developer's Notes"
38
- @dryrun = false
39
- options.each { |k, v| __send__("#{k}=", v) if v }
40
- yield(self) if block_given?
12
+ require "fileutils"
13
+ require "erb"
14
+ require "rexml/text"
15
+ require "dnote/core_ext"
16
+
17
+ EXTENSIONS = { "text" => "txt", "soap" => "xml", "xoxo" => "xml" }.freeze
18
+
19
+ attr_reader :notes, :format, :output, :template, :title, :dryrun
20
+
21
+ def initialize(notes,
22
+ format: "text",
23
+ title: "Developer's Notes",
24
+ template: nil,
25
+ output: nil,
26
+ dryrun: false)
27
+ @notes = notes
28
+ @format = format
29
+ @title = title
30
+ @dryrun = dryrun
31
+ @template = template
32
+ @output = output
41
33
  end
42
34
 
43
35
  def render
@@ -45,7 +37,7 @@ module DNote
45
37
  $stderr << "No #{notes.labels.join(', ')} notes.\n"
46
38
  else
47
39
  case format
48
- when 'custom'
40
+ when "custom"
49
41
  render_custom
50
42
  else
51
43
  render_template
@@ -53,6 +45,8 @@ module DNote
53
45
  end
54
46
  end
55
47
 
48
+ private
49
+
56
50
  # C U S T O M
57
51
 
58
52
  def render_custom
@@ -63,15 +57,13 @@ module DNote
63
57
  # T E M P L A T E
64
58
 
65
59
  def render_template
66
- template = File.join(File.dirname(__FILE__), 'templates', "#{format}.erb")
60
+ template = File.join(File.dirname(__FILE__), "templates", "#{format}.erb")
67
61
  raise "No such format - #{format}" unless File.exist?(template)
68
62
 
69
63
  result = erb(template)
70
64
  publish(result)
71
65
  end
72
66
 
73
- private
74
-
75
67
  def erb(file)
76
68
  scope = ErbScope.new(notes: notes, title: title)
77
69
  scope.render(file)
@@ -83,12 +75,12 @@ module DNote
83
75
  else
84
76
  puts(result)
85
77
  end
86
- $stderr << '(' + notes.counts.map { |l, n| "#{n} #{l}s" }.join(', ') + ")\n"
78
+ $stderr << "(#{notes.counts.map { |l, n| "#{n} #{l}s" }.join(', ')})\n"
87
79
  end
88
80
 
89
81
  def write(result, fname = nil)
90
- if output.to_s[-1, 1] == '/' || File.directory?(output)
91
- fmt = format.split('/').first
82
+ if output.to_s[-1, 1] == "/" || File.directory?(output)
83
+ fmt = format.split("/").first
92
84
  ext = EXTENSIONS[fmt] || fmt
93
85
  file = File.join(output, fname || "notes.#{ext}")
94
86
  else
@@ -100,7 +92,7 @@ module DNote
100
92
  else
101
93
  dir = File.dirname(file)
102
94
  fu.mkdir(dir) unless File.exist?(dir)
103
- File.open(file, 'w') { |f| f << result }
95
+ File.open(file, "w") { |f| f << result }
104
96
  end
105
97
  file
106
98
  end
@@ -114,7 +106,7 @@ module DNote
114
106
  end
115
107
 
116
108
  def fu
117
- @fu ||= begin
109
+ @fu ||=
118
110
  if dryrun? && debug?
119
111
  FileUtils::DryRun
120
112
  elsif dryrun?
@@ -124,7 +116,6 @@ module DNote
124
116
  else
125
117
  FileUtils
126
118
  end
127
- end
128
119
  end
129
120
 
130
121
  # Evaluation scope for ERB templates
@@ -134,7 +125,12 @@ module DNote
134
125
  end
135
126
 
136
127
  def render(file)
137
- erb = ERB.new(File.read(file), nil, '<>')
128
+ contents = File.read(file)
129
+ erb = if RUBY_VERSION >= "2.6"
130
+ ERB.new(contents, trim_mode: "<>")
131
+ else
132
+ ERB.new(contents, nil, "<>")
133
+ end
138
134
  erb.result(binding)
139
135
  end
140
136
 
@@ -150,7 +146,7 @@ module DNote
150
146
  end
151
147
 
152
148
  def respond_to_missing?(method)
153
- @data.key? method.to_sym
149
+ @data.key?(method.to_sym) || super
154
150
  end
155
151
  end
156
152
  end
data/lib/dnote/note.rb CHANGED
@@ -31,7 +31,6 @@ module DNote
31
31
  # Initialize new Note instance.
32
32
  def initialize(notes, file, label, line, text, mark)
33
33
  @notes = notes
34
-
35
34
  @file = file
36
35
  @label = label
37
36
  @line = line
@@ -52,13 +51,13 @@ module DNote
52
51
 
53
52
  # Remove newlines from note text.
54
53
  def textline
55
- text.tr("\n", ' ')
54
+ text.tr("\n", " ")
56
55
  end
57
56
 
58
57
  # Sort by file name and line number.
59
58
  def <=>(other)
60
59
  s = file <=> other.file
61
- return s unless s.zero?
60
+ return s unless s == 0
62
61
 
63
62
  line <=> other.line
64
63
  end
@@ -69,12 +68,12 @@ module DNote
69
68
  # TODO: Add +code+? Problem is that xml needs code in CDATA.
70
69
  #++
71
70
  def to_h
72
- { 'label' => label, 'text' => textline, 'file' => file, 'line' => line }
71
+ { "label" => label, "text" => textline, "file" => file, "line" => line }
73
72
  end
74
73
 
75
74
  # Convert to Hash, leaving the note text verbatim.
76
75
  def to_h_raw
77
- { 'label' => label, 'text' => text, 'file' => file, 'line' => line, 'code' => code }
76
+ { "label" => label, "text" => text, "file" => file, "line" => line, "code" => code }
78
77
  end
79
78
 
80
79
  # Convert to JSON.
@@ -89,6 +88,8 @@ module DNote
89
88
 
90
89
  # Return line URL based on URL template. If no template was set, then
91
90
  # returns the file.
91
+ #
92
+ # FIXME: Move out of Note so we can drop the reference to notes
92
93
  def url
93
94
  if notes.url
94
95
  format(notes.url, file, line)
@@ -112,13 +113,13 @@ module DNote
112
113
  def unindent(lines)
113
114
  dents = []
114
115
  lines.each do |line|
115
- if (md = /^([\ ]*)/.match(line))
116
+ if (md = /^(\ *)/.match(line))
116
117
  dents << md[1]
117
118
  end
118
119
  end
119
120
  dent = dents.min_by(&:size)
120
121
  lines.map do |line|
121
- line.sub(dent, '')
122
+ line.sub(dent, "")
122
123
  end
123
124
  end
124
125
  end
data/lib/dnote/notes.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pathname'
4
- require 'dnote/note'
3
+ require "pathname"
4
+ require "dnote/note"
5
+ require "dnote/notes_collection"
5
6
 
6
7
  module DNote
7
8
  # = Developer Notes
@@ -18,31 +19,29 @@ module DNote
18
19
  # have a outline format, rather then the single line.
19
20
  #++
20
21
  class Notes
21
- include Enumerable
22
-
23
22
  # Default paths (all ruby scripts).
24
- DEFAULT_PATHS = ['**/*.rb'].freeze
23
+ DEFAULT_PATHS = ["**/*.rb"].freeze
25
24
 
26
25
  # Default note labels to look for in source code. (NOT CURRENTLY USED!)
27
26
  DEFAULT_LABELS = %w(TODO FIXME OPTIMIZE THINK DEPRECATE).freeze
28
27
 
29
28
  # Files to search for notes.
30
- attr_accessor :files
29
+ attr_reader :files
31
30
 
32
31
  # Labels to document. Defaults are: +TODO+, +FIXME+, +OPTIMIZE+ and +DEPRECATE+.
33
- attr_accessor :labels
32
+ attr_reader :labels
34
33
 
35
34
  # Require label colon? Default is +true+.
36
- attr_accessor :colon
35
+ attr_reader :colon
37
36
 
38
37
  # Specific remark marker (+nil+ for auto).
39
- attr_accessor :marker
38
+ attr_reader :marker
40
39
 
41
40
  # Link template.
42
- attr_accessor :url
41
+ attr_reader :url
43
42
 
44
43
  # Number of lines of context to show.
45
- attr_accessor :context
44
+ attr_reader :context
46
45
 
47
46
  # New set of notes for give +files+ and optional special labels.
48
47
  def initialize(files, options = {})
@@ -52,34 +51,13 @@ module DNote
52
51
  @marker = options[:marker]
53
52
  @url = options[:url]
54
53
  @context = options[:context] || 0
55
-
56
54
  @remark = {}
57
55
 
58
56
  parse
59
57
  end
60
58
 
61
- # Array of notes.
62
- attr_reader :notes
63
-
64
- # Notes counts by label.
65
- def counts
66
- @counts ||= begin
67
- h = {}
68
- by_label.each do |label, notes|
69
- h[label] = notes.size
70
- end
71
- h
72
- end
73
- end
74
-
75
- # Iterate through notes.
76
- def each(&block)
77
- notes.each(&block)
78
- end
79
-
80
- # No notes?
81
- def empty?
82
- notes.empty?
59
+ def notes_collection
60
+ @notes_collection ||= NotesCollection.new(@notes)
83
61
  end
84
62
 
85
63
  # Gather notes.
@@ -89,42 +67,45 @@ module DNote
89
67
  def parse
90
68
  records = []
91
69
  files.each do |fname|
92
- next unless File.file?(fname)
70
+ records += parse_file(fname)
71
+ end
93
72
 
94
- mark = remark(fname)
95
- lineno = 0
96
- note = nil
97
- text = nil
98
- capt = nil
99
- File.readlines(fname).each do |line|
100
- lineno += 1
101
- note = match(line, lineno, fname)
102
- if note
103
- text = note.text
104
- capt = note.capture
105
- records << note
106
- elsif text
107
- case line
108
- when /^\s*#{mark}+\s*$/, /^\s*#{mark}\-\-/, /^\s*#{mark}\+\+/
109
- text.strip!
110
- text = nil
111
- when /^\s*#{mark}/
112
- if text[-1, 1] == "\n"
113
- text << line.gsub(/^\s*#{mark}\s*/, '')
114
- else
115
- text << "\n" << line.gsub(/^\s*#{mark}\s*/, '')
116
- end
117
- else
118
- text.strip!
119
- text = nil
120
- end
121
- elsif line !~ /^\s*#{mark}/
122
- capt << line if capt && capt.size < context
73
+ @notes = records.sort
74
+ end
75
+
76
+ def parse_file(fname)
77
+ return [] unless File.file?(fname)
78
+
79
+ records = []
80
+ mark = remark(fname)
81
+ lineno = 0
82
+ note = nil
83
+ text = nil
84
+ capt = nil
85
+ File.readlines(fname).each do |line|
86
+ lineno += 1
87
+ note = match(line, lineno, fname)
88
+ if note
89
+ text = note.text
90
+ capt = note.capture
91
+ records << note
92
+ elsif text
93
+ case line
94
+ when /^\s*#{mark}+\s*$/, /^\s*#{mark}--/, /^\s*#{mark}\+\+/
95
+ text.strip!
96
+ text = nil
97
+ when /^\s*#{mark}/
98
+ text << "\n" unless text[-1, 1] == "\n"
99
+ text << line.gsub(/^\s*#{mark}\s*/, "")
100
+ else
101
+ text.strip!
102
+ text = nil
123
103
  end
104
+ elsif !/^\s*#{mark}/.match?(line)
105
+ capt << line if capt && capt.size < context
124
106
  end
125
107
  end
126
-
127
- @notes = records.sort
108
+ records
128
109
  end
129
110
 
130
111
  # Is this line a note?
@@ -148,15 +129,13 @@ module DNote
148
129
  rec
149
130
  end
150
131
 
151
- #--
152
- # TODO: ruby-1.9.1-p378 reports: `match': invalid byte sequence in UTF-8
153
- #++
154
132
  def match_special_regex(label, file)
155
133
  mark = remark(file)
134
+ label = Regexp.escape(label)
156
135
  if colon
157
- /#{mark}\s*#{Regexp.escape(label)}[:]\s+(.*?)$/
136
+ /#{mark}\s*#{label}:\s+(.*?)$/
158
137
  else
159
- /#{mark}\s*#{Regexp.escape(label)}[:]?\s+(.*?)$/
138
+ /#{mark}\s*#{label}:?\s+(.*?)$/
160
139
  end
161
140
  end
162
141
 
@@ -176,83 +155,18 @@ module DNote
176
155
  def match_general_regex(file)
177
156
  mark = remark(file)
178
157
  if colon
179
- /#{mark}\s*([A-Z]+)[:]\s+(.*?)$/
158
+ /#{mark}\s*([A-Z]+):\s+(.*?)$/
180
159
  else
181
160
  /#{mark}\s*([A-Z]+)\s+(.*?)$/
182
161
  end
183
162
  end
184
163
 
185
- # Organize notes into a hash with labels for keys.
186
- def by_label
187
- @by_label ||= begin
188
- list = {}
189
- notes.each do |note|
190
- list[note.label] ||= []
191
- list[note.label] << note
192
- list[note.label].sort
193
- end
194
- list
195
- end
196
- end
197
-
198
- # Organize notes into a hash with filename for keys.
199
- def by_file
200
- @by_file ||= begin
201
- list = {}
202
- notes.each do |note|
203
- list[note.file] ||= []
204
- list[note.file] << note
205
- list[note.file].sort!
206
- end
207
- list
208
- end
209
- end
210
-
211
- # Organize notes into a hash with labels for keys, followed
212
- # by a hash with filename for keys.
213
- def by_label_file
214
- @by_label_file ||= begin
215
- list = {}
216
- notes.each do |note|
217
- list[note.label] ||= {}
218
- list[note.label][note.file] ||= []
219
- list[note.label][note.file] << note
220
- list[note.label][note.file].sort!
221
- end
222
- list
223
- end
224
- end
225
-
226
- # Organize notes into a hash with filenames for keys, followed
227
- # by a hash with labels for keys.
228
- def by_file_label
229
- @by_file_label ||= begin
230
- list = {}
231
- notes.each do |note|
232
- list[note.file] ||= {}
233
- list[note.file][note.label] ||= []
234
- list[note.file][note.label] << note
235
- list[note.file][note.label].sort!
236
- end
237
- list
238
- end
239
- end
240
-
241
- # Convert to an array of hashes.
242
- def to_a
243
- notes.map(&:to_h)
244
- end
245
-
246
- # Same as #by_label.
247
- def to_h
248
- by_label
249
- end
250
-
251
164
  def remark(file)
252
- @remark[File.extname(file)] ||= begin
253
- mark = guess_marker(file)
254
- Regexp.escape(mark)
255
- end
165
+ @remark[File.extname(file)] ||=
166
+ begin
167
+ mark = guess_marker(file)
168
+ Regexp.escape(mark)
169
+ end
256
170
  end
257
171
 
258
172
  # Guess marker based on file extension. Fallsback to '#'
@@ -263,16 +177,16 @@ module DNote
263
177
  return @marker if @marker # forced marker
264
178
 
265
179
  case File.extname(file)
266
- when '.js', '.c', 'cpp', '.css'
267
- '//'
268
- when '.bas'
180
+ when ".js", ".c", "cpp", ".css"
181
+ "//"
182
+ when ".bas"
269
183
  "'"
270
- when '.sql', '.ada'
271
- '--'
272
- when '.asm'
273
- ';'
184
+ when ".sql", ".ada"
185
+ "--"
186
+ when ".asm"
187
+ ";"
274
188
  else
275
- '#'
189
+ "#"
276
190
  end
277
191
  end
278
192
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DNote
4
+ # = Notes Collection
5
+ #
6
+ # This class contains a collection of Note objects and can group them in
7
+ # several ways.
8
+ #
9
+ class NotesCollection
10
+ include Enumerable
11
+
12
+ def initialize(notes)
13
+ @notes = notes
14
+ end
15
+
16
+ # Array of notes.
17
+ attr_reader :notes
18
+
19
+ # Notes counts by label.
20
+ def counts
21
+ @counts ||=
22
+ begin
23
+ h = {}
24
+ by_label.each do |label, notes|
25
+ h[label] = notes.size
26
+ end
27
+ h
28
+ end
29
+ end
30
+
31
+ # Iterate through notes.
32
+ def each(&block)
33
+ notes.each(&block)
34
+ end
35
+
36
+ # No notes?
37
+ def empty?
38
+ notes.empty?
39
+ end
40
+
41
+ # Organize notes into a hash with labels for keys.
42
+ def by_label
43
+ @by_label ||= notes.group_by(&:label)
44
+ end
45
+
46
+ # Organize notes into a hash with filename for keys.
47
+ def by_file
48
+ @by_file ||= notes.group_by(&:file)
49
+ end
50
+
51
+ # Organize notes into a hash with labels for keys, followed
52
+ # by a hash with filename for keys.
53
+ def by_label_file
54
+ @by_label_file ||= by_label.transform_values { |notes| notes.group_by(&:file) }
55
+ end
56
+
57
+ # Organize notes into a hash with filenames for keys, followed
58
+ # by a hash with labels for keys.
59
+ def by_file_label
60
+ @by_file_label ||= by_file.transform_values { |notes| notes.group_by(&:label) }
61
+ end
62
+
63
+ # Convert to an array of hashes.
64
+ def to_a
65
+ notes.map(&:to_h)
66
+ end
67
+
68
+ # Same as #by_label.
69
+ def to_h
70
+ by_label
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dnote/core_ext"
4
+ require "dnote/notes"
5
+ require "dnote/format"
6
+ require "optparse"
7
+
8
+ module DNote
9
+ # Option parser
10
+ class Options
11
+ def self.parse(*argv)
12
+ new(argv).parse
13
+ end
14
+
15
+ def initialize(argv)
16
+ @argv = argv
17
+ end
18
+
19
+ def parse
20
+ session = Session.new
21
+
22
+ opts = OptionParser.new do |opt|
23
+ opt.banner = "DNote v#{DNote::VERSION}"
24
+
25
+ opt.separator(" ")
26
+ opt.separator("USAGE:\n dnote [OPTIONS] path1 [path2 ...]")
27
+
28
+ add_output_format_options(session, opt)
29
+ add_other_options(session, opt)
30
+ add_command_options(session, opt)
31
+ end
32
+
33
+ opts.parse!(@argv)
34
+ session.paths.replace(@argv)
35
+ session
36
+ end
37
+
38
+ def add_command_options(session, opt)
39
+ opt.separator(" ")
40
+ opt.separator("COMMAND OPTIONS:")
41
+
42
+ opt.on_tail("--templates", "-T", "list available format templates") do
43
+ session.list_templates
44
+ exit
45
+ end
46
+
47
+ opt.on_tail("--help", "-h", "show this help information") do
48
+ puts opt
49
+ exit
50
+ end
51
+ end
52
+
53
+ def add_output_format_options(session, opt)
54
+ opt.separator(" ")
55
+ opt.separator("OUTPUT FORMAT: (choose one)")
56
+
57
+ opt.on("--format", "-f NAME", "select a format [text]") do |format|
58
+ session.format = format
59
+ end
60
+
61
+ opt.on("--custom", "-C FILE", "use a custom ERB template") do |file|
62
+ session.format = "custom"
63
+ session.template = file
64
+ end
65
+
66
+ opt.on("--file", "shortcut for text/file format") do
67
+ session.format = "text/file"
68
+ end
69
+
70
+ opt.on("--list", "shortcut for text/list format") do
71
+ session.format = "text/list"
72
+ end
73
+ end
74
+
75
+ def add_other_options(session, opt)
76
+ opt.separator(" ")
77
+ opt.separator("OTHER OPTIONS:")
78
+
79
+ opt.on("--label", "-l LABEL", "labels to collect") do |lbl|
80
+ session.labels.concat(lbl.split(":"))
81
+ end
82
+
83
+ opt.on(:colon, "--[no-]colon", "match labels with/without colon suffix") do |val|
84
+ session.colon = val
85
+ end
86
+
87
+ opt.on("--marker", "-m MARK", "alternative remark marker") do |mark|
88
+ session.marker = mark
89
+ end
90
+
91
+ opt.on("--url", "-u TEMPLATE", "url template for line entries (for HTML)") do |url|
92
+ session.url = url
93
+ end
94
+
95
+ opt.on("--context", "-c INTEGER", "number of lines of context to display") do |int|
96
+ session.context = int.to_i
97
+ end
98
+
99
+ opt.on("--exclude", "-x PATH", "exclude file or directory") do |path|
100
+ session.exclude << path
101
+ end
102
+
103
+ opt.on("--ignore", "-i NAME", "ignore file based on any part of pathname") do |name|
104
+ session.ignore << name
105
+ end
106
+
107
+ opt.on("--title", "-t TITLE", "title to use in header") do |title|
108
+ session.title = title
109
+ end
110
+
111
+ opt.on("--output", "-o PATH", "save to file or directory") do |path|
112
+ session.output = path
113
+ end
114
+
115
+ opt.on("--dryrun", "-n", "do not actually write to disk") do
116
+ session.dryrun = true
117
+ end
118
+
119
+ opt.on("--debug", "debug mode") do
120
+ $DEBUG = true
121
+ $VERBOSE = true
122
+ end
123
+ end
124
+ end
125
+ end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rspec/core/rake_task'
3
+ require "rspec/core/rake_task"
4
4
 
5
5
  module DNote
6
6
  # = Developmer's Notes Rake Task
7
7
  #
8
8
  class RakeTask < Rake::TaskLib
9
- require 'rake/clean'
9
+ require "rake/clean"
10
10
 
11
11
  # Default note labels to looked for in source code.
12
12
  DEFAULT_LABELS = %w(TODO FIXME OPTIMIZE DEPRECATE).freeze
@@ -38,30 +38,47 @@ module DNote
38
38
  end
39
39
 
40
40
  def init
41
- require 'dnote'
42
- require 'dnote/format'
43
- @files = '**/*.rb'
44
- @output = 'log/dnote'
45
- @formats = ['index']
41
+ require "dnote"
42
+ require "dnote/format"
43
+ @files = "**/*.rb"
44
+ @output = "log/dnote"
45
+ @formats = ["index"]
46
46
  @labels = nil
47
47
  end
48
48
 
49
49
  def define
50
50
  desc "Collect Developer's Notes"
51
- task 'dnote' do
51
+ task "dnote" do
52
52
  document
53
53
  end
54
- task 'dnote:clobber' do
54
+ task "dnote:clobber" do
55
55
  clean
56
56
  end
57
- task clobber: ['dnote:clobber']
57
+ task clobber: ["dnote:clobber"]
58
58
  end
59
59
 
60
60
  # Generate notes document(s).
61
61
  def document
62
62
  abort "dnote: #{output} is not a directory" unless output.directory?
63
63
 
64
- session = ::DNote::Session.new do |s|
64
+ session = new_session
65
+
66
+ formats.each do |format|
67
+ generate_document_for_format(session, format)
68
+ end
69
+ end
70
+
71
+ # Remove output files.
72
+ def clean
73
+ formats.each do |format|
74
+ clean_format format
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def new_session
81
+ ::DNote::Session.new do |s|
65
82
  s.paths = files
66
83
  s.exclude = exclude
67
84
  s.ignore = ignore
@@ -70,31 +87,28 @@ module DNote
70
87
  s.output = output
71
88
  s.dryrun = application.options.dryrun # trial?
72
89
  end
90
+ end
73
91
 
74
- formats.each do |format|
75
- if format == 'index'
76
- session.format = 'html'
77
- session.output = File.join(output, 'index.html')
78
- else
79
- session.format = format
80
- end
81
- session.run
82
- report "Updated #{output.to_s.sub(Dir.pwd + '/', '')}" unless trial?
92
+ def generate_document_for_format(session, format)
93
+ if format == "index"
94
+ session.format = "html"
95
+ session.output = File.join(output, "index.html")
96
+ else
97
+ session.format = format
83
98
  end
99
+ session.run
100
+ report "Updated #{output.to_s.sub("#{Dir.pwd}/", '')}" unless trial?
84
101
  end
85
102
 
86
- # Remove output files.
87
- def clean
88
- formats.each do |format|
89
- if format == 'index'
90
- file = (output + 'index.html').to_s
91
- else
92
- ext = ::DNote::Format::EXTENSIONS[format] || format
93
- file = (output + "notes.#{ext}").to_s
94
- end
95
- rm(file)
96
- report "Removed #{output}"
103
+ def clean_format(format)
104
+ if format == "index"
105
+ file = "#{output}index.html".to_s
106
+ else
107
+ ext = ::DNote::Format::EXTENSIONS[format] || format
108
+ file = (output + "notes.#{ext}").to_s
97
109
  end
110
+ rm(file)
111
+ report "Removed #{output}"
98
112
  end
99
113
  end
100
114
  end
data/lib/dnote/session.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dnote/core_ext'
4
- require 'dnote/notes'
5
- require 'dnote/format'
3
+ require "dnote/core_ext"
4
+ require "dnote/notes"
5
+ require "dnote/format"
6
+ require "dnote/options"
6
7
 
7
8
  module DNote
8
9
  # User session which is used by commandline interface.
@@ -17,7 +18,7 @@ module DNote
17
18
  DIR = File.dirname(__FILE__)
18
19
 
19
20
  # Default format.
20
- DEFAULT_FORMAT = 'text'
21
+ DEFAULT_FORMAT = "text"
21
22
 
22
23
  # Default title.
23
24
  DEFAULT_TITLE = "Developer's Notes"
@@ -105,13 +106,18 @@ module DNote
105
106
 
106
107
  # Run session.
107
108
  def run
108
- notes = Notes.new(files, labels: labels, colon: colon, marker: marker, url: url, context: context)
109
- formatter = Format.new(notes) do |f|
110
- f.format = format
111
- f.template = template
112
- f.title = title
113
- f.output = output
114
- end
109
+ notes = Notes.new(files,
110
+ labels: labels,
111
+ colon: colon,
112
+ marker: marker,
113
+ url: url,
114
+ context: context)
115
+ collection = notes.notes_collection
116
+ formatter = Format.new(collection,
117
+ format: format,
118
+ template: template,
119
+ title: title,
120
+ output: output)
115
121
  formatter.render
116
122
  end
117
123
 
@@ -120,11 +126,11 @@ module DNote
120
126
  # compile the list of files.
121
127
  def files
122
128
  list = [paths].flatten.compact
123
- list = ['**/*.rb'] if list.empty?
129
+ list = ["**/*.rb"] if list.empty?
124
130
  list = glob(list)
125
131
  list -= glob(exclude)
126
132
  list.reject do |path|
127
- path.split('/').any? { |part| ignore.any? { |ig| File.fnmatch?(ig, part) } }
133
+ path.split("/").any? { |part| ignore.any? { |ig| File.fnmatch?(ig, part) } }
128
134
  end
129
135
  end
130
136
 
@@ -133,115 +139,27 @@ module DNote
133
139
  def glob(paths)
134
140
  paths.map do |path|
135
141
  if File.directory?(path)
136
- Dir.glob(File.join(path, '**/*'))
142
+ Dir.glob(File.join(path, "**/*"))
137
143
  else
138
144
  Dir.glob(path)
139
145
  end
140
146
  end.flatten.uniq
141
147
  end
142
148
 
143
- # Commandline interface.
144
- def self.main(*argv)
145
- require 'optparse'
146
-
147
- session = Session.new
148
-
149
- opts = OptionParser.new do |opt|
150
- opt.banner = "DNote v#{DNote::VERSION}"
151
-
152
- opt.separator(' ')
153
- opt.separator("USAGE:\n dnote [OPTIONS] path1 [path2 ...]")
154
-
155
- opt.separator(' ')
156
- opt.separator('OUTPUT FORMAT: (choose one)')
157
-
158
- opt.on('--format', '-f NAME', 'select a format [text]') do |format|
159
- session.format = format
160
- end
161
-
162
- opt.on('--custom', '-C FILE', 'use a custom ERB template') do |file|
163
- session.format = 'custom'
164
- session.template = file
165
- end
166
-
167
- opt.on('--file', 'shortcut for text/file format') do
168
- session.format = 'text/file'
169
- end
170
-
171
- opt.on('--list', 'shortcut for text/list format') do
172
- session.format = 'text/list'
173
- end
174
-
175
- opt.separator(' ')
176
- opt.separator('OTHER OPTIONS:')
177
-
178
- opt.on('--label', '-l LABEL', 'labels to collect') do |lbl|
179
- session.labels.concat(lbl.split(':'))
180
- end
181
-
182
- opt.on('--[no-]colon', 'match labels with/without colon suffix') do |val|
183
- session.colon = val
184
- end
185
-
186
- opt.on('--marker', '-m MARK', 'alternative remark marker') do |mark|
187
- session.marker = mark
188
- end
189
-
190
- opt.on('--url', '-u TEMPLATE', 'url template for line entries (for HTML)') do |url|
191
- session.url = url
192
- end
193
-
194
- opt.on('--context', '-c INTEGER', 'number of lines of context to display') do |int|
195
- session.context = int.to_i
196
- end
197
-
198
- opt.on('--exclude', '-x PATH', 'exclude file or directory') do |path|
199
- session.exclude << path
200
- end
201
-
202
- opt.on('--ignore', '-i NAME', 'ignore file based on any part of pathname') do |name|
203
- session.ignore << name
204
- end
205
-
206
- opt.on('--title', '-t TITLE', 'title to use in header') do |title|
207
- session.title = title
208
- end
209
-
210
- opt.on('--output', '-o PATH', 'save to file or directory') do |path|
211
- session.output = path
212
- end
213
-
214
- opt.on('--dryrun', '-n', 'do not actually write to disk') do
215
- session.dryrun = true
216
- end
217
-
218
- opt.on('--debug', 'debug mode') do
219
- $DEBUG = true
220
- $VERBOSE = true
221
- end
222
-
223
- opt.separator(' ')
224
- opt.separator('COMMAND OPTIONS:')
225
-
226
- opt.on_tail('--templates', '-T', 'list available format templates') do
227
- tdir = File.join(DIR, 'templates')
228
- tfiles = Dir[File.join(tdir, '**/*.erb')]
229
- tnames = tfiles.map { |tname| tname.sub(tdir + '/', '').chomp('.erb') }
230
- groups = tnames.group_by { |tname| tname.split('/').first }
231
- groups.sort.each do |(_type, names)|
232
- puts('%-18s ' * names.size % names.sort)
233
- end
234
- exit
235
- end
236
-
237
- opt.on_tail('--help', '-h', 'show this help information') do
238
- puts opt
239
- exit
240
- end
149
+ # List availble format templates
150
+ def list_templates
151
+ tdir = File.join(DIR, "templates")
152
+ tfiles = Dir[File.join(tdir, "**/*.erb")]
153
+ tnames = tfiles.map { |tname| tname.sub("#{tdir}/", "").chomp(".erb") }
154
+ groups = tnames.group_by { |tname| tname.split("/").first }
155
+ groups.sort.each do |(_type, names)|
156
+ puts("%-18s " * names.size % names.sort)
241
157
  end
158
+ end
242
159
 
243
- opts.parse!(argv)
244
- session.paths.replace(argv)
160
+ # Commandline interface.
161
+ def self.main(*argv)
162
+ session = Options.parse(*argv)
245
163
  session.run
246
164
  end
247
165
  end
data/lib/dnote/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DNote
4
- VERSION = '1.8.0'
4
+ VERSION = "1.9.0"
5
5
  end
data/lib/dnote.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dnote/version'
4
- require 'dnote/session'
3
+ require "dnote/version"
4
+ require "dnote/session"
5
5
 
6
6
  # TEST: This is a test of an arbitrary label.
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mvz-dnote
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Sawyer
8
8
  - Matijs van Zuijlen
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-12-29 00:00:00.000000000 Z
12
+ date: 2021-09-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aruba
@@ -17,42 +17,70 @@ dependencies:
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: 0.14.1
20
+ version: '2.0'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: 0.14.1
27
+ version: '2.0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: cucumber
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '3.0'
34
+ version: '7.0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '3.0'
41
+ version: '7.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: pry
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.14.0
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.14.0
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: rake
44
58
  requirement: !ruby/object:Gem::Requirement
45
59
  requirements:
46
60
  - - "~>"
47
61
  - !ruby/object:Gem::Version
48
- version: '12.0'
62
+ version: '13.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '13.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rake-manifest
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 0.2.0
49
77
  type: :development
50
78
  prerelease: false
51
79
  version_requirements: !ruby/object:Gem::Requirement
52
80
  requirements:
53
81
  - - "~>"
54
82
  - !ruby/object:Gem::Version
55
- version: '12.0'
83
+ version: 0.2.0
56
84
  - !ruby/object:Gem::Dependency
57
85
  name: rspec
58
86
  requirement: !ruby/object:Gem::Requirement
@@ -67,23 +95,79 @@ dependencies:
67
95
  - - "~>"
68
96
  - !ruby/object:Gem::Version
69
97
  version: '3.5'
98
+ - !ruby/object:Gem::Dependency
99
+ name: rubocop
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: 1.21.0
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: 1.21.0
112
+ - !ruby/object:Gem::Dependency
113
+ name: rubocop-packaging
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: 0.5.0
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: 0.5.0
126
+ - !ruby/object:Gem::Dependency
127
+ name: rubocop-performance
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: 1.11.0
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: 1.11.0
140
+ - !ruby/object:Gem::Dependency
141
+ name: rubocop-rspec
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - "~>"
145
+ - !ruby/object:Gem::Version
146
+ version: 2.4.0
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: 2.4.0
70
154
  - !ruby/object:Gem::Dependency
71
155
  name: simplecov
72
156
  requirement: !ruby/object:Gem::Requirement
73
157
  requirements:
74
158
  - - "~>"
75
159
  - !ruby/object:Gem::Version
76
- version: 0.16.1
160
+ version: 0.21.0
77
161
  type: :development
78
162
  prerelease: false
79
163
  version_requirements: !ruby/object:Gem::Requirement
80
164
  requirements:
81
165
  - - "~>"
82
166
  - !ruby/object:Gem::Version
83
- version: 0.16.1
84
- description: |2
85
- DNote makes it easy to extract developer's notes from source code,
86
- and supports almost any language.
167
+ version: 0.21.0
168
+ description: |
169
+ DNote makes it easy to extract developer's notes from source code,
170
+ and supports almost any language.
87
171
  email:
88
172
  - matijs@matijs.net
89
173
  executables:
@@ -103,6 +187,8 @@ files:
103
187
  - lib/dnote/format.rb
104
188
  - lib/dnote/note.rb
105
189
  - lib/dnote/notes.rb
190
+ - lib/dnote/notes_collection.rb
191
+ - lib/dnote/options.rb
106
192
  - lib/dnote/rake/dnotetask.rb
107
193
  - lib/dnote/session.rb
108
194
  - lib/dnote/templates/html.erb
@@ -143,25 +229,31 @@ files:
143
229
  - lib/dnote/templates/yaml/list.erb
144
230
  - lib/dnote/version.rb
145
231
  homepage: https://github.com/mvz/dnote
146
- licenses: []
147
- metadata: {}
148
- post_install_message:
149
- rdoc_options: []
232
+ licenses:
233
+ - BSD-2-Clause
234
+ metadata:
235
+ homepage_uri: https://github.com/mvz/dnote
236
+ source_code_uri: https://github.com/mvz/dnote
237
+ changelog_uri: https://github.com/mvz/dnote/blob/master/HISTORY.rdoc
238
+ post_install_message:
239
+ rdoc_options:
240
+ - "--main"
241
+ - README.md
150
242
  require_paths:
151
243
  - lib
152
244
  required_ruby_version: !ruby/object:Gem::Requirement
153
245
  requirements:
154
246
  - - ">="
155
247
  - !ruby/object:Gem::Version
156
- version: 2.3.0
248
+ version: 2.5.0
157
249
  required_rubygems_version: !ruby/object:Gem::Requirement
158
250
  requirements:
159
251
  - - ">="
160
252
  - !ruby/object:Gem::Version
161
253
  version: '0'
162
254
  requirements: []
163
- rubygems_version: 3.0.1
164
- signing_key:
255
+ rubygems_version: 3.2.22
256
+ signing_key:
165
257
  specification_version: 4
166
258
  summary: Extract developer's notes from source code.
167
259
  test_files: []