Class: DNote::Notes

Inherits:
Object
  • Object
show all
Defined in:
lib/dnote/notes.rb

Overview

Developer Notes

This class goes through you source files and compiles a list of any labeled comments. Labels are all-cap single word prefixes to a comment ending in a colon.

Special labels do not require the colon. By default these are TODO, FIXME, OPTIMIZE, THINK and DEPRECATE.

TODO: Add ability to read header notes. They often
      have a outline format, rather then the single line.

++

Constant Summary collapse

DEFAULT_PATHS =

Default paths (all ruby scripts).

["**/*.rb"].freeze
DEFAULT_LABELS =

Default note labels to look for in source code. (NOT CURRENTLY USED!)

%w[TODO FIXME OPTIMIZE THINK DEPRECATE].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(files, marker: nil, url: nil, labels: DEFAULT_LABELS, colon: true, context: 0) ⇒ Notes

New set of notes for give files and optional special labels.



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/dnote/notes.rb', line 47

def initialize(files, marker: nil, url: nil, labels: DEFAULT_LABELS,
               colon: true, context: 0)
  @files = files
  @labels = labels
  @colon = colon
  @marker = marker
  @url = url
  @context = context
  @remark = {}

  parse
end

Instance Attribute Details

#colonObject (readonly)

Require label colon? Default is true.



35
36
37
# File 'lib/dnote/notes.rb', line 35

def colon
  @colon
end

#contextObject (readonly)

Number of lines of context to show.



44
45
46
# File 'lib/dnote/notes.rb', line 44

def context
  @context
end

#filesObject (readonly)

Files to search for notes.



29
30
31
# File 'lib/dnote/notes.rb', line 29

def files
  @files
end

#labelsObject (readonly)

Labels to document. Defaults are: TODO, FIXME, OPTIMIZE and DEPRECATE.



32
33
34
# File 'lib/dnote/notes.rb', line 32

def labels
  @labels
end

#markerObject (readonly)

Specific remark marker (nil for auto).



38
39
40
# File 'lib/dnote/notes.rb', line 38

def marker
  @marker
end

#urlObject (readonly)

Link template.



41
42
43
# File 'lib/dnote/notes.rb', line 41

def url
  @url
end

Instance Method Details

#guess_marker(file) ⇒ Object

Guess marker based on file extension. Fallsback to ‘#’ if the extension is unknown.

TODO: Continue to add comment types.



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/dnote/notes.rb', line 177

def guess_marker(file)
  return @marker if @marker # forced marker

  case File.extname(file)
  when ".js", ".c", "cpp", ".css"
    "//"
  when ".bas"
    "'"
  when ".sql", ".ada"
    "--"
  when ".asm"
    ";"
  else
    "#"
  end
end

#match(line, lineno, file) ⇒ Object

Is this line a note?



113
114
115
116
117
118
119
# File 'lib/dnote/notes.rb', line 113

def match(line, lineno, file)
  if labels.empty?
    match_general(line, lineno, file)
  else
    match_special(line, lineno, file)
  end
end

#match_general(line, lineno, file) ⇒ Object

Match notes that are labeled with a colon.



144
145
146
147
148
149
150
151
152
# File 'lib/dnote/notes.rb', line 144

def match_general(line, lineno, file)
  rec = nil
  if (md = match_general_regex(file).match(line))
    label = md[1]
    text = md[2]
    rec = Note.new(self, file, label, lineno, text, remark(file))
  end
  rec
end

#match_general_regex(file) ⇒ Object

Keep in mind that general non-colon matches have a higher potential of false positives.



156
157
158
159
160
161
162
163
# File 'lib/dnote/notes.rb', line 156

def match_general_regex(file)
  mark = remark(file)
  if colon
    /#{mark}\s*([A-Z]+):\s+(.*?)$/
  else
    /#{mark}\s*([A-Z]+)\s+(.*?)$/
  end
end

#match_special(line, lineno, file) ⇒ Object

Match special notes.



122
123
124
125
126
127
128
129
130
131
# File 'lib/dnote/notes.rb', line 122

def match_special(line, lineno, file)
  rec = nil
  labels.each do |label|
    if (md = match_special_regex(label, file).match(line))
      text = md[1]
      rec = Note.new(self, file, label, lineno, text, remark(file))
    end
  end
  rec
end

#match_special_regex(label, file) ⇒ Object



133
134
135
136
137
138
139
140
141
# File 'lib/dnote/notes.rb', line 133

def match_special_regex(label, file)
  mark = remark(file)
  label = Regexp.escape(label)
  if colon
    /#{mark}\s*#{label}:\s+(.*?)$/
  else
    /#{mark}\s*#{label}:?\s+(.*?)$/
  end
end

#notes_collectionObject



60
61
62
# File 'lib/dnote/notes.rb', line 60

def notes_collection
  @notes_collection ||= NotesCollection.new(@notes)
end

#parseObject

Gather notes. – TODO: Play golf with Notes#parse. ++



68
69
70
71
72
73
74
75
# File 'lib/dnote/notes.rb', line 68

def parse
  records = []
  files.each do |fname|
    records += parse_file(fname)
  end

  @notes = records.sort
end

#parse_file(fname) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/dnote/notes.rb', line 77

def parse_file(fname)
  return [] unless File.file?(fname)

  records = []
  mark = remark(fname)
  lineno = 0
  note = nil
  text = nil
  capt = nil
  File.readlines(fname).each do |line|
    lineno += 1
    note = match(line, lineno, fname)
    if note
      text = note.text
      capt = note.capture
      records << note
    elsif text
      case line
      when /^\s*#{mark}+\s*$/, /^\s*#{mark}--/, /^\s*#{mark}\+\+/
        text.strip!
        text = nil
      when /^\s*#{mark}/
        text << "\n" unless text[-1, 1] == "\n"
        text << line.gsub(/^\s*#{mark}\s*/, "")
      else
        text.strip!
        text = nil
      end
    elsif !/^\s*#{mark}/.match?(line)
      capt << line if capt && capt.size < context
    end
  end
  records
end

#remark(file) ⇒ Object



165
166
167
168
169
170
171
# File 'lib/dnote/notes.rb', line 165

def remark(file)
  @remark[File.extname(file)] ||=
    begin
      mark = guess_marker(file)
      Regexp.escape(mark)
    end
end