Class: Lazydoc::Comment

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/lazydoc/comment.rb

Overview

Comment represents a code comment parsed by Lazydoc.

Direct Known Subclasses

Method, Subject, Trailer

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils

categorize, convert_to_scanner, determine_line_number, match_index, scan, scan_args, scan_index, scan_trailer, skip_quote, split_lines, wrap

Constructor Details

#initialize(line_number = nil, document = nil) ⇒ Comment

Returns a new instance of Comment.



24
25
26
27
28
29
# File 'lib/lazydoc/comment.rb', line 24

def initialize(line_number=nil, document=nil)
  @line_number = line_number
  @document = document
  @content = []
  @subject = nil
end

Instance Attribute Details

#contentObject (readonly)

An array of comment fragments organized into lines



19
20
21
# File 'lib/lazydoc/comment.rb', line 19

def content
  @content
end

#documentObject

A back-reference to the Document that registered self



16
17
18
# File 'lib/lazydoc/comment.rb', line 16

def document
  @document
end

#line_numberObject

Returns the line number for the subject line, if known. Although normally an integer, line_number may be set to a Regexp or Proc to dynamically determine the subject line during resolve



13
14
15
# File 'lib/lazydoc/comment.rb', line 13

def line_number
  @line_number
end

#subjectObject

The subject of the comment



22
23
24
# File 'lib/lazydoc/comment.rb', line 22

def subject
  @subject
end

Instance Method Details

#<<(fragment) ⇒ Object

Alias for push.



76
77
78
# File 'lib/lazydoc/comment.rb', line 76

def <<(fragment)
  push(fragment)
end

#append(line) ⇒ Object

Scans the comment line using Comment.scan and pushes the appropriate fragments onto self. Used to build a content by scanning down a set of lines.

lines = [
  "# comment spanning multiple",
  "# lines",
  "#",
  "#   indented line one",
  "#   indented line two",
  "#    ",
  "not a comment line"]

c = Comment.new
lines.each {|line| c.append(line) }

c.content 
# => [
# ['comment spanning multiple', 'lines'],
# [''],
# ['  indented line one'],
# ['  indented line two'],
# [''],
# []]


105
106
107
# File 'lib/lazydoc/comment.rb', line 105

def append(line)
  scan(line) {|f| push(f) }
end

#comment(fragment_sep = " ", line_sep = "\n", strip = true) ⇒ Object

Returns content as a string where line fragments are joined by fragment_sep and lines are joined by line_sep.



292
293
294
295
296
297
298
299
300
301
302
# File 'lib/lazydoc/comment.rb', line 292

def comment(fragment_sep=" ", line_sep="\n", strip=true)
  lines = content.collect {|line| line.join(fragment_sep)}

  # strip leading an trailing whitespace lines
  if strip
    lines.shift while !lines.empty? && lines[0].empty?
    lines.pop while !lines.empty? && lines[-1].empty?
  end

  line_sep ? lines.join(line_sep) : lines
end

#empty?Boolean

True if to_s is empty.

Returns:

  • (Boolean)


312
313
314
# File 'lib/lazydoc/comment.rb', line 312

def empty?
  to_s.empty?
end

#parse_down(str, lines = nil, skip_subject = true) ⇒ Object

Like parse_up but builds the content of self by parsing comments down from line_number. Parsing begins immediately after line_number (no whitespace lines are skipped). Previous content is overridden. Returns self.

document = %Q{
# == Section One
# documentation for section one
#   'with' + 'indentation'
#
# == Section Two
# documentation for section two
}

c = Comment.new 1
c.parse_down(document) {|line| line =~ /Section Two/}
c.comment      # => "documentation for section one\n  'with' + 'indentation'"

c = Comment.new /Section Two/
c.parse_down(document)
c.line_number  # => 5
c.comment      # => "documentation for section two"


262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/lazydoc/comment.rb', line 262

def parse_down(str, lines=nil, skip_subject=true)
  parse(str, lines) do |n, comment_lines|
    # skip the subject line
    n += 1 if skip_subject
    
    # put together the comment
    while line = comment_lines[n]
      break if block_given? && yield(line)
      break unless append(line)
      n += 1
    end
  end
end

#parse_up(str, lines = nil, skip_subject = true) ⇒ Object

Builds the content of self by parsing comments up from line_number. Whitespace lines between line_number and the preceding comment are skipped. Previous content is overridden. Returns self.

document = %Q{
module Sample

  # this is the content of the comment
  # for method_one
  def method_one
  end

  # this is the content of the comment
  # for method_two

  def method_two
  end
end}

c = Comment.new 4
c.parse_up(document)
c.comment      # => "this is the content of the comment for method_one"

The input may be a String or StringScanner and, for optimal parsing of multiple comments from the same document, may also take an array of lines representing the input split along newline boundaries.

Stop Block

A block may be provided to determine when to stop parsing comment content. When the block returns true, parsing stops.

c = Comment.new 4
c.parse_up(document) {|line| line =~ /# this is/ }
c.comment      # => "for method_one"

Dynamic Line Numbers

The line_number used by parse_up may be determined dynamically from the input by setting line_number to a Regexp and Proc. In the case of a Regexp, the first line matching the regexp is used:

c = Comment.new(/def method/)
c.parse_up(document)
c.line_number  # => 4
c.comment      # => "this is the content of the comment for method_one"

Procs are called with lines and are expected to return the actual line number.

c = Comment.new lambda {|scanner, lines| 9 }
c.parse_up(document)
c.line_number  # => 9
c.comment      # => "this is the content of the comment for method_two"

As shown in the examples, the dynamically determined line_number overwrites the Regexp or Proc.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/lazydoc/comment.rb', line 223

def parse_up(str, lines=nil, skip_subject=true)
  parse(str, lines) do |n, comment_lines|
    # remove whitespace lines
    n -= 1 if skip_subject
    n -= 1 while n >=0 && comment_lines[n].strip.empty?

    # put together the comment
    while n >= 0
      line = comment_lines[n]
      break if block_given? && yield(line)
      break unless prepend(line)
      n -= 1
    end
  end
end

#prepend(line) ⇒ Object

Scans the comment line using Comment.scan and unshifts the appropriate fragments onto self. Used to build a content by scanning up a set of lines.

lines = [
  "# comment spanning multiple",
  "# lines",
  "#",
  "#   indented line one",
  "#   indented line two",
  "#    ",
  "not a comment line"]

c = Comment.new
lines.reverse_each {|line| c.prepend(line) }

c.content 
# => [
# ['comment spanning multiple', 'lines'],
# [''],
# ['  indented line one'],
# ['  indented line two'],
# ['']]


162
163
164
# File 'lib/lazydoc/comment.rb', line 162

def prepend(line)
  scan(line) {|f| unshift(f) }
end

#push(fragment) ⇒ Object

Pushes the fragment onto the last line of content. If the fragment is an array itself then it will be pushed onto content as a new line.

c = Comment.new
c.push "some line"
c.push "fragments"
c.push ["a", "whole", "new line"]

c.content         
# => [
# ["some line", "fragments"], 
# ["a", "whole", "new line"]]


60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/lazydoc/comment.rb', line 60

def push(fragment)
  content << [] if content.empty?

  case fragment
  when Array
    if content[-1].empty? 
      content[-1] = fragment
    else
      content.push fragment
    end
  else
     content[-1].push fragment
  end
end

#resolve(str = nil, force = false) ⇒ Object

Resolves the document for self, if set.



277
278
279
280
# File 'lib/lazydoc/comment.rb', line 277

def resolve(str=nil, force=false)
  document.resolve(str, force) if document
  self
end

#to_sObject

Self-resolves and returns comment.



317
318
319
320
# File 'lib/lazydoc/comment.rb', line 317

def to_s
  resolve
  comment
end

#trailerObject

Returns the comment trailing the subject.



42
43
44
# File 'lib/lazydoc/comment.rb', line 42

def trailer
  subject ? scan_trailer(subject) : nil
end

#trimObject

Removes leading and trailing lines from content that are empty or whitespace. Returns self.



284
285
286
287
288
# File 'lib/lazydoc/comment.rb', line 284

def trim
  content.shift while !content.empty? && (content[0].empty? || content[0].join.strip.empty?)
  content.pop   while !content.empty? && (content[-1].empty? || content[-1].join.strip.empty?)
  self
end

#unshift(fragment) ⇒ Object

Unshifts the fragment to the first line of content. If the fragment is an array itself then it will be unshifted onto content as a new line.

c = Comment.new
c.unshift "some line"
c.unshift "fragments"
c.unshift ["a", "whole", "new line"]

c.content         
# => [
# ["a", "whole", "new line"], 
# ["fragments", "some line"]]


123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/lazydoc/comment.rb', line 123

def unshift(fragment)
  content << [] if content.empty?

  case fragment
  when Array
    if content[0].empty? 
      content[0] = fragment
    else
      content.unshift fragment
    end
  else
     content[0].unshift fragment
  end
end

#valueObject

Alias for subject



32
33
34
# File 'lib/lazydoc/comment.rb', line 32

def value
  subject
end

#value=(value) ⇒ Object

Alias for subject=



37
38
39
# File 'lib/lazydoc/comment.rb', line 37

def value=(value)
  self.subject = value
end

#wrap(cols = 80, tabsize = 2, line_sep = "\n", fragment_sep = " ", strip = true) ⇒ Object

Like comment, but wraps the content to the specified number of cols and expands tabs to tabsize spaces.



306
307
308
309
# File 'lib/lazydoc/comment.rb', line 306

def wrap(cols=80, tabsize=2, line_sep="\n", fragment_sep=" ", strip=true)
  lines = super(comment(fragment_sep, "\n", strip), cols, tabsize)
  line_sep ? lines.join(line_sep) : lines
end