mvz-dnote 1.8.0 → 1.9.0

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