Module: Lazydoc::Utils
- Included in:
- Comment
- Defined in:
- lib/lazydoc/utils.rb
Overview
A number of utility methods used by Comment, factored out for testing and re-use.
Class Method Summary collapse
-
.categorize(fragment, indent) ⇒ Object
utility method used by scan to categorize and yield the appropriate objects to add the fragment to a comment.
-
.convert_to_scanner(str) ⇒ Object
Converts str to a StringScanner (or returns str if it already is a StringScanner).
-
.determine_line_number(scanner) ⇒ Object
Returns the line at which scanner currently resides.
-
.match_index(lines, regexp) ⇒ Object
Returns the index of the line in lines matching regexp, or nil if no line matches regexp.
-
.scan(line) ⇒ Object
Scan determines if and how to add a line fragment to a comment and yields the appropriate fragments to the block.
-
.scan_args(str) ⇒ Object
Parses an argument string (anything following the method name in a standard method definition, including parenthesis, comments, default values, etc) into an array of strings.
-
.scan_index(scanner, regexp) ⇒ Object
Returns the index of the line where scanner ends up after the first match to regexp (starting at position 0).
-
.scan_trailer(str) ⇒ Object
Scans a stripped trailing comment off the input.
-
.skip_quote(scanner, regexp) ⇒ Object
helper method to skip to the next non-escaped instance matching the quote regexp (/‘/ or /“/).
- .split_lines(str) ⇒ Object
-
.wrap(line, cols = 80, tabsize = 2) ⇒ Object
Splits a line of text along whitespace breaks into fragments of cols width.
Class Method Details
.categorize(fragment, indent) ⇒ Object
utility method used by scan to categorize and yield the appropriate objects to add the fragment to a comment
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/lazydoc/utils.rb', line 219 def categorize(fragment, indent) # :nodoc: case when fragment == indent # empty comment line yield [""] yield [] when indent.empty? # continuation line yield fragment.rstrip else # indented line yield [fragment.rstrip] yield [] end end |
.convert_to_scanner(str) ⇒ Object
Converts str to a StringScanner (or returns str if it already is a StringScanner). Raises a TypeError if str is not a String or a StringScanner.
17 18 19 20 21 22 23 |
# File 'lib/lazydoc/utils.rb', line 17 def convert_to_scanner(str) case str when String then StringScanner.new(str) when StringScanner then str else raise TypeError, "can't convert #{str.class} into StringScanner" end end |
.determine_line_number(scanner) ⇒ Object
Returns the line at which scanner currently resides. The position of scanner is not modified.
177 178 179 |
# File 'lib/lazydoc/utils.rb', line 177 def determine_line_number(scanner) scanner.string[0, scanner.pos].count("\n") end |
.match_index(lines, regexp) ⇒ Object
Returns the index of the line in lines matching regexp, or nil if no line matches regexp.
200 201 202 203 204 205 206 207 |
# File 'lib/lazydoc/utils.rb', line 200 def match_index(lines, regexp) index = 0 lines.each do |line| return index if line =~ regexp index += 1 end nil end |
.scan(line) ⇒ Object
Scan determines if and how to add a line fragment to a comment and yields the appropriate fragments to the block. Returns true if fragments are yielded and false otherwise.
Content may be built from an array of lines using scan like so:
lines = [
"# comments spanning multiple",
"# lines are collected",
"#",
"# while indented lines",
"# are preserved individually",
"# ",
"not a comment line",
"# skipped since the loop breaks",
"# at the first non-comment line"]
c = Comment.new
lines.each do |line|
break unless Utils.scan(line) do |fragment|
c.push(fragment)
end
end
c.content
# => [
# ['comments spanning multiple', 'lines are collected'],
# [''],
# [' while indented lines'],
# [' are preserved individually'],
# [''],
# []]
58 59 60 61 62 63 64 |
# File 'lib/lazydoc/utils.rb', line 58 def scan(line) # :yields: fragment return false unless line =~ /^[ \t]*#[ \t]?(([ \t]*).*?)\r?$/ categorize($1, $2) do |fragment| yield(fragment) end true end |
.scan_args(str) ⇒ Object
Parses an argument string (anything following the method name in a standard method definition, including parenthesis, comments, default values, etc) into an array of strings.
Utils.parse_args("(a, b='default', *c, &block)")
# => ["a", "b='default'", "*c", "&block"]
Note the %-syntax for strings and arrays is not fully supported, ie %w, %Q, %q, etc. may not parse correctly. The same is true for multiline argument strings.
Accepts a String or a StringScanner.
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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/lazydoc/utils.rb', line 78 def scan_args(str) scanner = convert_to_scanner(str) str = scanner.string # skip whitespace and leading LPAREN scanner.skip(/\s*\(?\s*/) args = [] brakets = braces = parens = 0 start = scanner.pos broke = false while scanner.skip(/.*?['"#,\(\)\{\}\[\]]/) pos = scanner.pos - 1 case str[pos] when ?,,nil # skip if in brakets, braces, or parenthesis next if parens > 0 || brakets > 0 || braces > 0 # ok, found an arg args << str[start, pos-start].strip start = pos + 1 when ?# then broke = true; break # break on a comment when ?' then skip_quote(scanner, /'/) # parse over quoted strings when ?" then skip_quote(scanner, /"/) # parse over double-quoted string when ?( then parens += 1 # for brakets, braces, and parenthesis when ?) # simply track the nesting EXCEPT for if parens == 0 # RPAREN. If the closing parenthesis broke = true; break end parens -= 1 # is found, break. when ?[ then braces += 1 when ?] then braces -= 1 when ?{ then brakets += 1 when ?} then brakets -= 1 end end # parse out the final arg. if the loop broke (ie # a comment or the closing parenthesis was found) # then the end position is determined by the # scanner, otherwise take all that remains pos = broke ? scanner.pos-1 : str.length args << str[start, pos-start].strip unless pos == start args end |
.scan_index(scanner, regexp) ⇒ Object
Returns the index of the line where scanner ends up after the first match to regexp (starting at position 0). The existing position of scanner is not modified by this method. Returns nil if the scanner cannot match regexp.
scanner = StringScanner.new %Q{zero\none\ntwo\nthree}
Utils.scan_index(scanner, /two/) # => 2
Utils.scan_index(scanner, /no match/) # => nil
190 191 192 193 194 195 196 |
# File 'lib/lazydoc/utils.rb', line 190 def scan_index(scanner, regexp) pos = scanner.pos scanner.pos = 0 n = scanner.skip_until(regexp) ? determine_line_number(scanner) : nil scanner.pos = pos n end |
.scan_trailer(str) ⇒ Object
Scans a stripped trailing comment off the input. Returns nil for strings without a trailing comment.
Utils.scan_trailer "str with # trailer" # => "trailer"
Utils.scan_trailer "'# in str' # trailer" # => "trailer"
Utils.scan_trailer "str with without trailer" # => nil
Note the %Q and %q syntax for defining strings is not supported within the leader and may not parse correctly:
Utils.scan_trailer "%Q{# in str} # trailer" # => "in str} # trailer"
Accepts a String or a StringScanner.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/lazydoc/utils.rb', line 141 def scan_trailer(str) scanner = convert_to_scanner(str) args = [] brakets = braces = parens = 0 start = scanner.pos while scanner.skip(/.*?['"#]/) pos = scanner.pos - 1 case str[pos] when ?# then return scanner.rest.strip # return the trailer when ?' then skip_quote(scanner, /'/) # parse over quoted strings when ?" then skip_quote(scanner, /"/) # parse over double-quoted string end end return nil end |
.skip_quote(scanner, regexp) ⇒ Object
helper method to skip to the next non-escaped instance matching the quote regexp (/‘/ or /“/).
211 212 213 214 |
# File 'lib/lazydoc/utils.rb', line 211 def skip_quote(scanner, regexp) # :nodoc: scanner.skip_until(regexp) scanner.skip_until(regexp) while scanner.string[scanner.pos-2] == ?\\ end |
.split_lines(str) ⇒ Object
10 11 12 |
# File 'lib/lazydoc/utils.rb', line 10 def split_lines(str) (str.empty? ? [""] : str.split(/\r?\n/)) end |
.wrap(line, cols = 80, tabsize = 2) ⇒ Object
Splits a line of text along whitespace breaks into fragments of cols width. Tabs in the line will be expanded into tabsize spaces; fragments are rstripped of whitespace.
Utils.wrap("some line that will wrap", 10) # => ["some line", "that will", "wrap"]
Utils.wrap(" line that will wrap ", 10) # => [" line", "that will", "wrap"]
Utils.wrap(" ", 10) # => []
The wrapping algorithm is slightly modified from: blog.macromates.com/2006/wrapping-text-with-regular-expressions/
170 171 172 173 |
# File 'lib/lazydoc/utils.rb', line 170 def wrap(line, cols=80, tabsize=2) line = line.gsub(/\t/, " " * tabsize) unless tabsize == nil line.gsub(/(.{1,#{cols}})( +|$\r?\n?)|(.{1,#{cols}})/, "\\1\\3\n").split(/\s*?\n/) end |