diff options
author | Kornelius Kalnbach <murphy@rubychan.de> | 2013-06-10 01:44:16 +0200 |
---|---|---|
committer | Kornelius Kalnbach <murphy@rubychan.de> | 2013-06-10 01:44:16 +0200 |
commit | 4ffc0afac656bef8a897023711cad7f3ca92a5fc (patch) | |
tree | 6637d5a2f48078d9db6459e73306402c4ee4dddb /lib/coderay | |
parent | 02e1bf3c236778197627fe9f9a7b3cf126825a8b (diff) | |
parent | 2de5dab7d59021622dabf4728e0b8123dc29da8a (diff) | |
download | coderay-4ffc0afac656bef8a897023711cad7f3ca92a5fc.tar.gz |
Merge branch 'master' into bash-scanner
Diffstat (limited to 'lib/coderay')
-rw-r--r-- | lib/coderay/encoders/debug.rb | 3 | ||||
-rw-r--r-- | lib/coderay/encoders/html.rb | 6 | ||||
-rw-r--r-- | lib/coderay/helpers/file_type.rb | 5 | ||||
-rw-r--r-- | lib/coderay/helpers/plugin.rb | 1 | ||||
-rw-r--r-- | lib/coderay/scanners/c.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/cpp.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/css.rb | 31 | ||||
-rw-r--r-- | lib/coderay/scanners/diff.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/java.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/java_script.rb | 4 | ||||
-rw-r--r-- | lib/coderay/scanners/json.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/python.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/sass.rb | 207 | ||||
-rw-r--r-- | lib/coderay/scanners/sql.rb | 2 | ||||
-rw-r--r-- | lib/coderay/styles/alpha.rb | 2 | ||||
-rwxr-xr-x | lib/coderay/token_kinds.rb | 2 | ||||
-rw-r--r-- | lib/coderay/tokens.rb | 1 | ||||
-rw-r--r-- | lib/coderay/version.rb | 2 |
18 files changed, 241 insertions, 37 deletions
diff --git a/lib/coderay/encoders/debug.rb b/lib/coderay/encoders/debug.rb index 95d6138..c03d3fb 100644 --- a/lib/coderay/encoders/debug.rb +++ b/lib/coderay/encoders/debug.rb @@ -24,11 +24,12 @@ module Encoders end def text_token text, kind + raise 'empty token' if $CODERAY_DEBUG && text.empty? if kind == :space @out << text else # TODO: Escape ( - text = text.gsub(/[)\\]/, '\\\\\0') # escape ) and \ + text = text.gsub(/[)\\]/, '\\\\\0') if text.index(/[)\\]/) @out << kind.to_s << '(' << text << ')' end end diff --git a/lib/coderay/encoders/html.rb b/lib/coderay/encoders/html.rb index 635a4d8..0fd1317 100644 --- a/lib/coderay/encoders/html.rb +++ b/lib/coderay/encoders/html.rb @@ -286,8 +286,7 @@ module Encoders def end_group kind if $CODERAY_DEBUG && (@opened.empty? || @opened.last != kind) - warn 'Malformed token stream: Trying to close a token (%p) ' \ - 'that is not open. Open are: %p.' % [kind, @opened[1..-1]] + warn 'Malformed token stream: Trying to close a token group (%p) that is not open. Open are: %p.' % [kind, @opened[1..-1]] end if @opened.pop @out << '</span>' @@ -312,8 +311,7 @@ module Encoders def end_line kind if $CODERAY_DEBUG && (@opened.empty? || @opened.last != kind) - warn 'Malformed token stream: Trying to close a line (%p) ' \ - 'that is not open. Open are: %p.' % [kind, @opened[1..-1]] + warn 'Malformed token stream: Trying to close a line (%p) that is not open. Open are: %p.' % [kind, @opened[1..-1]] end if @opened.pop @out << '</span>' diff --git a/lib/coderay/helpers/file_type.rb b/lib/coderay/helpers/file_type.rb index 637001b..a5d83ff 100644 --- a/lib/coderay/helpers/file_type.rb +++ b/lib/coderay/helpers/file_type.rb @@ -99,6 +99,7 @@ module CodeRay 'mab' => :ruby, 'pas' => :delphi, 'patch' => :diff, + 'phtml' => :php, 'php' => :php, 'php3' => :php, 'php4' => :php, @@ -116,10 +117,10 @@ module CodeRay 'rpdf' => :ruby, 'ru' => :ruby, 'rxml' => :ruby, - # 'sch' => :scheme, + 'sass' => :sass, 'sql' => :sql, - # 'ss' => :scheme, 'tmproj' => :xml, + 'xaml' => :xml, 'xhtml' => :html, 'xml' => :xml, 'yaml' => :yaml, diff --git a/lib/coderay/helpers/plugin.rb b/lib/coderay/helpers/plugin.rb index 137c1ab..dd4e830 100644 --- a/lib/coderay/helpers/plugin.rb +++ b/lib/coderay/helpers/plugin.rb @@ -180,7 +180,6 @@ module CodeRay rescue LoadError => boom if @plugin_map_loaded if h.has_key?(:default) - warn '%p could not load plugin %p; falling back to %p' % [self, id, h[:default]] h[:default] else raise PluginNotFound, '%p could not load plugin %p: %s' % [self, id, boom] diff --git a/lib/coderay/scanners/c.rb b/lib/coderay/scanners/c.rb index 8d24b99..84b6e8e 100644 --- a/lib/coderay/scanners/c.rb +++ b/lib/coderay/scanners/c.rb @@ -148,7 +148,7 @@ module Scanners encoder.text_token match, :char elsif match = scan(/ \\ | $ /x) encoder.end_group :string - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? state = :initial label_expected = false else diff --git a/lib/coderay/scanners/cpp.rb b/lib/coderay/scanners/cpp.rb index 9da62f4..e61f56f 100644 --- a/lib/coderay/scanners/cpp.rb +++ b/lib/coderay/scanners/cpp.rb @@ -160,7 +160,7 @@ module Scanners encoder.text_token match, :char elsif match = scan(/ \\ | $ /x) encoder.end_group :string - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? state = :initial label_expected = false else diff --git a/lib/coderay/scanners/css.rb b/lib/coderay/scanners/css.rb index 7b731ef..003eed6 100644 --- a/lib/coderay/scanners/css.rb +++ b/lib/coderay/scanners/css.rb @@ -15,19 +15,17 @@ module Scanners module RE # :nodoc: Hex = /[0-9a-fA-F]/ - Unicode = /\\#{Hex}{1,6}(?:\r\n|\s)?/ # differs from standard because it allows uppercase hex too - Escape = /#{Unicode}|\\[^\r\n\f0-9a-fA-F]/ - NMChar = /[-_a-zA-Z0-9]|#{Escape}/ - NMStart = /[_a-zA-Z]|#{Escape}/ - NL = /\r\n|\r|\n|\f/ - String1 = /"(?:[^\n\r\f\\"]|\\#{NL}|#{Escape})*"?/ # TODO: buggy regexp - String2 = /'(?:[^\n\r\f\\']|\\#{NL}|#{Escape})*'?/ # TODO: buggy regexp + Unicode = /\\#{Hex}{1,6}\b/ # differs from standard because it allows uppercase hex too + Escape = /#{Unicode}|\\[^\n0-9a-fA-F]/ + NMChar = /[-_a-zA-Z0-9]/ + NMStart = /[_a-zA-Z]/ + String1 = /"(?:[^\n\\"]+|\\\n|#{Escape})*"?/ # TODO: buggy regexp + String2 = /'(?:[^\n\\']+|\\\n|#{Escape})*'?/ # TODO: buggy regexp String = /#{String1}|#{String2}/ HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/ - Color = /#{HexColor}/ - Num = /-?(?:[0-9]+|[0-9]*\.[0-9]+)/ + Num = /-?(?:[0-9]*\.[0-9]+|[0-9]+)/ Name = /#{NMChar}+/ Ident = /-?#{NMStart}#{NMChar}*/ AtKeyword = /@#{Ident}/ @@ -35,16 +33,15 @@ module Scanners reldimensions = %w[em ex px] absdimensions = %w[in cm mm pt pc] - Unit = Regexp.union(*(reldimensions + absdimensions + %w[s])) + Unit = Regexp.union(*(reldimensions + absdimensions + %w[s dpi dppx deg])) Dimension = /#{Num}#{Unit}/ - Comment = %r! /\* (?: .*? \*/ | .* ) !mx - Function = /(?:url|alpha|attr|counters?)\((?:[^)\n\r\f]|\\\))*\)?/ + Function = /(?:url|alpha|attr|counters?)\((?:[^)\n]|\\\))*\)?/ - Id = /##{Name}/ + Id = /(?!#{HexColor}\b(?!-))##{Name}/ Class = /\.#{Name}/ - PseudoClass = /:#{Name}/ + PseudoClass = /::?#{Ident}/ AttributeSelector = /\[[^\]]*\]?/ end @@ -52,7 +49,7 @@ module Scanners def setup @state = :initial - @value_expected = nil + @value_expected = false end def scan_tokens encoder, options @@ -158,7 +155,7 @@ module Scanners elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox) encoder.text_token match, :float - elsif match = scan(/#{RE::Color}/o) + elsif match = scan(/#{RE::HexColor}/o) encoder.text_token match, :color elsif match = scan(/! *important/) @@ -170,7 +167,7 @@ module Scanners elsif match = scan(RE::AtKeyword) encoder.text_token match, :directive - elsif match = scan(/ [+>:;,.=()\/] /x) + elsif match = scan(/ [+>~:;,.=()\/] /x) if match == ':' value_expected = true elsif match == ';' diff --git a/lib/coderay/scanners/diff.rb b/lib/coderay/scanners/diff.rb index 38efaf4..af0f755 100644 --- a/lib/coderay/scanners/diff.rb +++ b/lib/coderay/scanners/diff.rb @@ -45,7 +45,7 @@ module Scanners if match = scan(/--- |\+\+\+ |=+|_+/) encoder.begin_line line_kind = :head encoder.text_token match, :head - if match = scan(/.*?(?=$|[\t\n\x00]| \(revision)/) + if match = scan(/[^\x00\n]+?(?=$|[\t\n]| \(revision)/) encoder.text_token match, :filename if options[:highlight_code] && match != '/dev/null' file_type = CodeRay::FileType.fetch(match, :text) diff --git a/lib/coderay/scanners/java.rb b/lib/coderay/scanners/java.rb index c1490ac..b282864 100644 --- a/lib/coderay/scanners/java.rb +++ b/lib/coderay/scanners/java.rb @@ -147,7 +147,7 @@ module Scanners elsif match = scan(/ \\ | $ /x) encoder.end_group state state = :initial - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? else raise_inspect "else case \" reached; %p not handled." % peek(1), encoder end diff --git a/lib/coderay/scanners/java_script.rb b/lib/coderay/scanners/java_script.rb index 43ecb18..92e3dfa 100644 --- a/lib/coderay/scanners/java_script.rb +++ b/lib/coderay/scanners/java_script.rb @@ -175,11 +175,11 @@ module Scanners encoder.text_token match, :content elsif match = scan(/ \\ | $ /x) encoder.end_group state - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? key_expected = value_expected = false state = :initial else - raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + raise_inspect "else case #{string_delimiter} reached; %p not handled." % peek(1), encoder end else diff --git a/lib/coderay/scanners/json.rb b/lib/coderay/scanners/json.rb index 0c90c34..4e0f462 100644 --- a/lib/coderay/scanners/json.rb +++ b/lib/coderay/scanners/json.rb @@ -70,7 +70,7 @@ module Scanners encoder.text_token match, :content elsif match = scan(/ \\ | $ /x) encoder.end_group state - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? state = :initial else raise_inspect "else case \" reached; %p not handled." % peek(1), encoder diff --git a/lib/coderay/scanners/python.rb b/lib/coderay/scanners/python.rb index cbdbbdb..a9492ab 100644 --- a/lib/coderay/scanners/python.rb +++ b/lib/coderay/scanners/python.rb @@ -133,7 +133,7 @@ module Scanners elsif match = scan(/ \\ | $ /x) encoder.end_group string_type string_type = nil - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? state = :initial else raise_inspect "else case \" reached; %p not handled." % peek(1), encoder, state diff --git a/lib/coderay/scanners/sass.rb b/lib/coderay/scanners/sass.rb new file mode 100644 index 0000000..0eb2caa --- /dev/null +++ b/lib/coderay/scanners/sass.rb @@ -0,0 +1,207 @@ +module CodeRay +module Scanners + + # A scanner for Sass. + class Sass < CSS + + register_for :sass + file_extension 'sass' + + SASS_FUNCTION = /(?:inline-image|linear-gradient|color-stops|mix|lighten|darken|rotate|image-url|image-width|image-height|sprite-url|sprite-path|sprite-file|sprite-map|sprite-position|sprite|unquote|join|round|ceil|floor|nth)/ + + STRING_CONTENT_PATTERN = { + "'" => /(?:[^\n\'\#]+|\\\n|#{RE::Escape}|#(?!\{))+/, + '"' => /(?:[^\n\"\#]+|\\\n|#{RE::Escape}|#(?!\{))+/, + } + + protected + + def setup + @state = :initial + end + + def scan_tokens encoder, options + states = Array(options[:state] || @state) + string_delimiter = nil + + until eos? + + if match = scan(/\s+/) + encoder.text_token match, :space + value_expected = false if match.index(/\n/) + + elsif states.last == :sass_inline && (match = scan(/\}/)) + encoder.text_token match, :inline_delimiter + encoder.end_group :inline + states.pop + + elsif case states.last + when :initial, :media, :sass_inline + if match = scan(/(?>#{RE::Ident})(?!\()/ox) + encoder.text_token match, value_expected ? :value : (check(/.*:/) ? :key : :type) + next + elsif !value_expected && (match = scan(/\*/)) + encoder.text_token match, :type + next + elsif match = scan(RE::Class) + encoder.text_token match, :class + next + elsif match = scan(RE::Id) + encoder.text_token match, :constant + next + elsif match = scan(RE::PseudoClass) + encoder.text_token match, :pseudo_class + next + elsif match = scan(RE::AttributeSelector) + # TODO: Improve highlighting inside of attribute selectors. + encoder.text_token match[0,1], :operator + encoder.text_token match[1..-2], :attribute_name if match.size > 2 + encoder.text_token match[-1,1], :operator if match[-1] == ?] + next + elsif match = scan(/(\=|@mixin +)#{RE::Ident}/o) + encoder.text_token match, :function + next + elsif match = scan(/@media/) + encoder.text_token match, :directive + # states.push :media_before_name + next + end + + when :block + if match = scan(/(?>#{RE::Ident})(?!\()/ox) + if value_expected + encoder.text_token match, :value + else + encoder.text_token match, :key + end + next + end + + when :string + if match = scan(STRING_CONTENT_PATTERN[string_delimiter]) + encoder.text_token match, :content + elsif match = scan(/['"]/) + encoder.text_token match, :delimiter + encoder.end_group :string + string_delimiter = nil + states.pop + elsif match = scan(/#\{/) + encoder.begin_group :inline + encoder.text_token match, :inline_delimiter + states.push :sass_inline + elsif match = scan(/ \\ | $ /x) + encoder.end_group state + encoder.text_token match, :error unless match.empty? + states.pop + else + raise_inspect "else case #{string_delimiter} reached; %p not handled." % peek(1), encoder + end + + else + #:nocov: + raise_inspect 'Unknown state', encoder + #:nocov: + + end + + elsif match = scan(/\$#{RE::Ident}/o) + encoder.text_token match, :variable + next + + elsif match = scan(/&/) + encoder.text_token match, :local_variable + + elsif match = scan(/\+#{RE::Ident}/o) + encoder.text_token match, :include + value_expected = true + + elsif match = scan(/\/\*(?:.*?\*\/|.*)|\/\/.*/) + encoder.text_token match, :comment + + elsif match = scan(/#\{/) + encoder.begin_group :inline + encoder.text_token match, :inline_delimiter + states.push :sass_inline + + elsif match = scan(/\{/) + value_expected = false + encoder.text_token match, :operator + states.push :block + + elsif match = scan(/\}/) + value_expected = false + encoder.text_token match, :operator + if states.last == :block || states.last == :media + states.pop + end + + elsif match = scan(/['"]/) + encoder.begin_group :string + string_delimiter = match + encoder.text_token match, :delimiter + if states.include? :sass_inline + content = scan_until(/(?=#{string_delimiter}|\}|\z)/) + encoder.text_token content, :content unless content.empty? + encoder.text_token string_delimiter, :delimiter if scan(/#{string_delimiter}/) + encoder.end_group :string + else + states.push :string + end + + elsif match = scan(/#{SASS_FUNCTION}/o) + encoder.text_token match, :predefined + + elsif match = scan(/#{RE::Function}/o) + encoder.begin_group :function + start = match[/^[-\w]+\(/] + encoder.text_token start, :delimiter + if match[-1] == ?) + encoder.text_token match[start.size..-2], :content + encoder.text_token ')', :delimiter + else + encoder.text_token match[start.size..-1], :content + end + encoder.end_group :function + + elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox) + encoder.text_token match, :float + + elsif match = scan(/#{RE::HexColor}/o) + encoder.text_token match, :color + + elsif match = scan(/! *(?:important|optional)/) + encoder.text_token match, :important + + elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/) + encoder.text_token match, :color + + elsif match = scan(/@else if\b|#{RE::AtKeyword}/) + encoder.text_token match, :directive + value_expected = true + + elsif match = scan(/ == | != | [-+*\/>~:;,.=()] /x) + if match == ':' + value_expected = true + elsif match == ';' + value_expected = false + end + encoder.text_token match, :operator + + else + encoder.text_token getch, :error + + end + + end + + if options[:keep_state] + @state = states + end + + encoder + end + + end + +end +end diff --git a/lib/coderay/scanners/sql.rb b/lib/coderay/scanners/sql.rb index bcbffd5..b757278 100644 --- a/lib/coderay/scanners/sql.rb +++ b/lib/coderay/scanners/sql.rb @@ -148,7 +148,7 @@ module CodeRay module Scanners encoder.text_token string_content, :content string_content = '' end - encoder.text_token match, :error + encoder.text_token match, :error unless match.empty? state = :initial else raise "else case \" reached; %p not handled." % peek(1), encoder diff --git a/lib/coderay/styles/alpha.rb b/lib/coderay/styles/alpha.rb index 8506d10..1f073b6 100644 --- a/lib/coderay/styles/alpha.rb +++ b/lib/coderay/styles/alpha.rb @@ -78,6 +78,7 @@ table.CodeRay td { padding: 2px 4px; vertical-align: top; } .exception { color:#C00; font-weight:bold } .float { color:#60E } .function { color:#06B; font-weight:bold } +.function .delimiter { color:#024; font-weight:bold } .global-variable { color:#d70 } .hex { color:#02b } .imaginary { color:#f00 } @@ -86,6 +87,7 @@ table.CodeRay td { padding: 2px 4px; vertical-align: top; } .inline-delimiter { font-weight: bold; color: #666 } .instance-variable { color:#33B } .integer { color:#00D } +.important { color:#D00 } .key .char { color: #60f } .key .delimiter { color: #404 } .key { color: #606 } diff --git a/lib/coderay/token_kinds.rb b/lib/coderay/token_kinds.rb index 3b8d07e..8db8530 100755 --- a/lib/coderay/token_kinds.rb +++ b/lib/coderay/token_kinds.rb @@ -85,6 +85,4 @@ module CodeRay TokenKinds[:method] = TokenKinds[:function] TokenKinds[:escape] = TokenKinds[:delimiter] TokenKinds[:docstring] = TokenKinds[:comment] - - TokenKinds.freeze end diff --git a/lib/coderay/tokens.rb b/lib/coderay/tokens.rb index c747017..6957d69 100644 --- a/lib/coderay/tokens.rb +++ b/lib/coderay/tokens.rb @@ -93,6 +93,7 @@ module CodeRay # This method is used by @Scanner#tokenize@ when called with an Array # of source strings. The Diff encoder uses it for inline highlighting. def split_into_parts *sizes + return Array.new(sizes.size) { Tokens.new } if size == 2 && first == '' parts = [] opened = [] content = nil diff --git a/lib/coderay/version.rb b/lib/coderay/version.rb index bfb5f24..4b4f085 100644 --- a/lib/coderay/version.rb +++ b/lib/coderay/version.rb @@ -1,3 +1,3 @@ module CodeRay - VERSION = '1.0.9' + VERSION = '1.1.0' end |