diff options
author | Kornelius Kalnbach <murphy@rubychan.de> | 2011-09-09 01:00:35 +0200 |
---|---|---|
committer | Kornelius Kalnbach <murphy@rubychan.de> | 2011-09-09 01:00:35 +0200 |
commit | d42887ef56c724d9f7b3b21ed8e1758f9d96e706 (patch) | |
tree | 5ba4b6dbc8774dbb09743121d3d469b7299d840a | |
parent | 03583bbfa756de93a3e75fb3f61d5d9729e250f7 (diff) | |
download | coderay-d42887ef56c724d9f7b3b21ed8e1758f9d96e706.tar.gz |
#353 New scanner: HAML!
-rw-r--r-- | Changes-1.0.textile | 8 | ||||
-rw-r--r-- | lib/coderay/helpers/file_type.rb | 1 | ||||
-rw-r--r-- | lib/coderay/scanners/haml.rb | 168 |
3 files changed, 177 insertions, 0 deletions
diff --git a/Changes-1.0.textile b/Changes-1.0.textile index 76d1060..9f8126c 100644 --- a/Changes-1.0.textile +++ b/Changes-1.0.textile @@ -15,6 +15,7 @@ h3. General changes * *NEW*: The new Diff scanner colorizes code inside of the diff, and highlights inline changes. * *NEW*: Extended support and usage of HTML5 and CSS 3 features. * *NEW*: Direct Streaming +* *NEW* scanners: Clojure and HAML * *CHANGED*: Token classes (used as CSS classes) are readable names; breaks you stylesheet! * *IMPROVED* documentation * *IMPROVED* speed: faster startup (using @autoload@), scanning, and encoding @@ -212,6 +213,13 @@ h3. @Scanners::Diff@ h3. *RENAMED*: @Scanners::ERB@ (was @Scanners::RHTML@) +h3. *NEW*: @Scanners::HAML@ + +It uses the new :state options of the HTML and Ruby scanners. + +Some rare cases are not considered (like @#{...}@ snippets inside of :javascript blocks), +but it highlights pretty well. + h3. @Scanners::HTML@ * *FIXED*: Closes open string groups. diff --git a/lib/coderay/helpers/file_type.rb b/lib/coderay/helpers/file_type.rb index c752a03..7b9939c 100644 --- a/lib/coderay/helpers/file_type.rb +++ b/lib/coderay/helpers/file_type.rb @@ -88,6 +88,7 @@ module CodeRay 'groovy' => :groovy, 'gvy' => :groovy, 'h' => :c, + 'haml' => :haml, 'htm' => :page, 'html' => :page, 'html.erb' => :erb, diff --git a/lib/coderay/scanners/haml.rb b/lib/coderay/scanners/haml.rb new file mode 100644 index 0000000..52988b2 --- /dev/null +++ b/lib/coderay/scanners/haml.rb @@ -0,0 +1,168 @@ +module CodeRay +module Scanners + + load :ruby + load :html + load :java_script + + class HAML < Scanner + + register_for :haml + title 'HAML Template' + + KINDS_NOT_LOC = HTML::KINDS_NOT_LOC + + protected + + def setup + super + @ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true + @embedded_ruby_scanner = CodeRay.scanner :ruby, :tokens => @tokens, :keep_tokens => true, :state => @ruby_scanner.interpreted_string_state + @html_scanner = CodeRay.scanner :html, :tokens => @tokens, :keep_tokens => true + end + + def scan_tokens encoder, options + + match = nil + code = '' + + until eos? + + if bol? + if match = scan(/!!!.*/) + encoder.text_token match, :doctype + next + end + + if match = scan(/(?>( *)(\/(?!\[if)|-\#|:javascript|:ruby|:\w+) *)(?=\n)/) + encoder.text_token match, :comment + + code = self[2] + if match = scan(/(?:\n+#{self[1]} .*)+/) + case code + when '/', '-#' + encoder.text_token match, :comment + when ':javascript' + # TODO: recognize #{...} snippets inside JavaScript + @java_script_scanner ||= CodeRay.scanner :java_script, :tokens => @tokens, :keep_tokens => true + @java_script_scanner.tokenize match, :tokens => encoder + when ':ruby' + @ruby_scanner.tokenize match, :tokens => encoder + when /:\w+/ + encoder.text_token match, :comment + else + raise 'else-case reached: %p' % [code] + end + end + end + + if match = scan(/ +/) + encoder.text_token match, :space + end + + if match = scan(/\/.*/) + encoder.text_token match, :comment + next + end + + if match = scan(/\\/) + encoder.text_token match, :plain + if match = scan(/.+/) + @html_scanner.tokenize match, :tokens => encoder + end + next + end + + tag = false + + if match = scan(/%[\w:]+\/?/) + encoder.text_token match, :tag + # if match = scan(/( +)(.+)/) + # encoder.text_token self[1], :space + # @embedded_ruby_scanner.tokenize self[2], :tokens => encoder + # end + tag = true + end + + while match = scan(/([.#])[-\w]*\w/) + encoder.text_token match, self[1] == '#' ? :constant : :class + tag = true + end + + if tag && match = scan(/(\()([^)]+)?(\))?/) + # TODO: recognize title=@title, class="widget_#{@widget.number}" + encoder.text_token self[1], :plain + @html_scanner.tokenize self[2], :tokens => encoder, :state => :attribute if self[2] + encoder.text_token self[3], :plain if self[3] + end + + if tag && match = scan(/\{/) + encoder.text_token match, :plain + + code = '' + level = 1 + while true + code << scan(/([^\{\},\n]|, *\n?)*/) + case match = getch + when '{' + level += 1 + code << match + when '}' + level -= 1 + if level > 0 + code << match + else + break + end + when "\n", ",", nil + break + end + end + @ruby_scanner.tokenize code, :tokens => encoder unless code.empty? + + encoder.text_token match, :plain if match + end + + if tag && match = scan(/(\[)([^\]\n]+)?(\])?/) + encoder.text_token self[1], :plain + @ruby_scanner.tokenize self[2], :tokens => encoder if self[2] + encoder.text_token self[3], :plain if self[3] + end + + if tag && match = scan(/\//) + encoder.text_token match, :tag + end + + if scan(/(>?<?[-=]|[&!]=|(& |!)|~)( *)([^,\n\|]+(?:(, *|\|(?=.|\n.*\|$))\n?[^,\n\|]*)*)?/) + encoder.text_token self[1] + self[3], :plain + if self[4] + if self[2] + @embedded_ruby_scanner.tokenize self[4], :tokens => encoder + else + @ruby_scanner.tokenize self[4], :tokens => encoder + end + end + elsif match = scan(/((?:<|><?)(?![!?\/\w]))?(.+)?/) + encoder.text_token self[1], :plain if self[1] + # TODO: recognize #{...} snippets + @html_scanner.tokenize self[2], :tokens => encoder if self[2] + end + + elsif match = scan(/.+/) + @html_scanner.tokenize match, :tokens => encoder + + end + + if match = scan(/\n/) + encoder.text_token match, :space + end + end + + encoder + + end + + end + +end +end |