Class: Kss::CommentParser

Inherits:
Object
  • Object
show all
Defined in:
lib/kss/comment_parser.rb

Overview

Public: Takes a file path of a text file and extracts comments from it. Currently accepts two formats:

// Single line style. /* Multi-line style. */

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_path, options = {}) ⇒ CommentParser

Public: Initializes a new comment parser object. Does not parse on initialization.

file_path - The location of the file to parse as a String. options - Optional options hash.

:preserve_whitespace - Preserve the whitespace before/after comment
                       markers (default:false).


66
67
68
69
70
71
72
# File 'lib/kss/comment_parser.rb', line 66

def initialize(file_path, options={})
  @options = options
  @options[:preserve_whitespace] = false if @options[:preserve_whitespace].nil?
  @file_path = file_path
  @blocks = []
  @parsed = false
end

Class Method Details

.end_multi_line_comment?(line) ⇒ Boolean

Public: Is this the end of a multi-line comment? /* This style */

line - A String of one line of text.

Returns a boolean.

Returns:

  • (Boolean)


32
33
34
35
# File 'lib/kss/comment_parser.rb', line 32

def self.end_multi_line_comment?(line)
  return false if self.single_line_comment?(line)
  !!(line =~ /.*\*\//)
end

.parse_multi_line(line) ⇒ Object

Public: Remove comment identifiers for multi-line comments.

line - A String of one line of text.

Returns a String.



52
53
54
55
56
# File 'lib/kss/comment_parser.rb', line 52

def self.parse_multi_line(line)
  cleaned = line.to_s.sub(/\s*\/\*/, '')
  cleaned = cleaned.sub(/\*\//, '')
  cleaned.rstrip
end

.parse_single_line(line) ⇒ Object

Public: Removes comment identifiers for single-line comments.

line - A String of one line of text.

Returns a String.



42
43
44
45
# File 'lib/kss/comment_parser.rb', line 42

def self.parse_single_line(line)
  cleaned = line.to_s.sub(/\s*\/\//, '')
  cleaned.rstrip
end

.single_line_comment?(line) ⇒ Boolean

Public: Is this a single-line comment? // This style

line - A String of one line of text.

Returns a boolean.

Returns:

  • (Boolean)


14
15
16
# File 'lib/kss/comment_parser.rb', line 14

def self.single_line_comment?(line)
  !!(line =~ /^\s*\/\//)
end

.start_multi_line_comment?(line) ⇒ Boolean

Public: Is this the start of a multi-line comment? /* This style */

line - A String of one line of text.

Returns a boolean.

Returns:

  • (Boolean)


23
24
25
# File 'lib/kss/comment_parser.rb', line 23

def self.start_multi_line_comment?(line)
  !!(line =~ /^\s*\/\*/)
end

Instance Method Details

#blocksObject

Public: The different sections of parsed comment text. A section is either a multi-line comment block’s content, or consecutive lines of single-line comments.

Returns an Array of parsed comment Strings.



79
80
81
# File 'lib/kss/comment_parser.rb', line 79

def blocks
  @parsed ? @blocks : parse_blocks
end

#normalize(text_block) ⇒ Object

Normalizes the comment block to ignore any consistent preceding whitespace. Consistent means the same amount of whitespace on every line of the comment block. Also strips any whitespace at the start and end of the whole block.

Returns a String of normalized text.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/kss/comment_parser.rb', line 139

def normalize(text_block)
  return text_block if @options[:preserve_whitespace]

  # Strip out any preceding [whitespace]* that occur on every line. Not
  # the smartest, but I wonder if I care.
  text_block = text_block.gsub(/^(\s*\*+)/, '')

  # Strip consistent indenting by measuring first line's whitespace
  indent_size = nil
  unindented = text_block.split("\n").collect do |line|
    preceding_whitespace = line.scan(/^\s*/)[0].to_s.size
    indent_size = preceding_whitespace if indent_size.nil?
    if line == ""
      ""
    elsif indent_size <= preceding_whitespace && indent_size > 0
      line.slice(indent_size, line.length - 1)
    else
      line
    end
  end.join("\n")

  unindented.strip
end

#parse_blocksObject

Parse the file for comment blocks and populate them into @blocks.

Returns an Array of parsed comment Strings.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/kss/comment_parser.rb', line 87

def parse_blocks
  File.open @file_path do |file|
    current_block = nil
    inside_single_line_block = false
    inside_multi_line_block  = false

    file.each_line do |line|
      # Parse single-line style
      if self.class.single_line_comment?(line)
        parsed = self.class.parse_single_line line
        if inside_single_line_block
          current_block += "\n#{parsed}"
        else
          current_block = parsed.to_s
          inside_single_line_block = true
        end
      end

      # Parse multi-lines tyle
      if self.class.start_multi_line_comment?(line) || inside_multi_line_block
        parsed = self.class.parse_multi_line line
        if inside_multi_line_block
          current_block += "\n#{parsed}"
        else
          current_block = parsed
          inside_multi_line_block = true
        end
      end

      # End a multi-line block if detected
      inside_multi_line_block = false if self.class.end_multi_line_comment?(line)

      # Store the current block if we're done
      unless self.class.single_line_comment?(line) || inside_multi_line_block
        @blocks << normalize(current_block) unless current_block.nil?

        inside_single_line_block = false
        current_block = nil
      end
    end
  end

  @parsed = true
  @blocks
end