##// END OF EJS Templates
Added javascript highlightment support (http://pastie.textmate.org/50774/)...
Jean-Philippe Lang -
r705:27d6da945743
parent child
Show More
@@ -0,0 +1,176
1 # http://pastie.textmate.org/50774/
2 module CodeRay module Scanners
3
4 class JavaScript < Scanner
5
6 register_for :javascript
7
8 RESERVED_WORDS = [
9 'asm', 'break', 'case', 'continue', 'default', 'do', 'else',
10 'for', 'goto', 'if', 'return', 'switch', 'while',
11 # 'struct', 'union', 'enum', 'typedef',
12 # 'static', 'register', 'auto', 'extern',
13 # 'sizeof',
14 'typeof',
15 # 'volatile', 'const', # C89
16 # 'inline', 'restrict', # C99
17 'var', 'function','try','new','in',
18 'instanceof','throw','catch'
19 ]
20
21 PREDEFINED_CONSTANTS = [
22 'void', 'null', 'this',
23 'true', 'false','undefined',
24 ]
25
26 IDENT_KIND = WordList.new(:ident).
27 add(RESERVED_WORDS, :reserved).
28 add(PREDEFINED_CONSTANTS, :pre_constant)
29
30 ESCAPE = / [rbfnrtv\n\\\/'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x
31 UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x
32
33 def scan_tokens tokens, options
34
35 state = :initial
36 string_type = nil
37 regexp_allowed = true
38
39 until eos?
40
41 kind = :error
42 match = nil
43
44 if state == :initial
45
46 if scan(/ \s+ | \\\n /x)
47 kind = :space
48
49 elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)
50 kind = :comment
51 regexp_allowed = false
52
53 elsif match = scan(/ \# \s* if \s* 0 /x)
54 match << scan_until(/ ^\# (?:elif|else|endif) .*? $ | \z /xm) unless eos?
55 kind = :comment
56 regexp_allowed = false
57
58 elsif regexp_allowed and scan(/\//)
59 tokens << [:open, :regexp]
60 state = :regex
61 kind = :delimiter
62
63 elsif scan(/ [-+*\/=<>?:;,!&^|()\[\]{}~%] | \.(?!\d) /x)
64 kind = :operator
65 regexp_allowed=true
66
67 elsif match = scan(/ [$A-Za-z_][A-Za-z_0-9]* /x)
68 kind = IDENT_KIND[match]
69 # if kind == :ident and check(/:(?!:)/)
70 # match << scan(/:/)
71 # kind = :label
72 # end
73 regexp_allowed=false
74
75 elsif match = scan(/["']/)
76 tokens << [:open, :string]
77 string_type = matched
78 state = :string
79 kind = :delimiter
80
81 # elsif scan(/#\s*(\w*)/)
82 # kind = :preprocessor # FIXME multiline preprocs
83 # state = :include_expected if self[1] == 'include'
84 #
85 # elsif scan(/ L?' (?: [^\'\n\\] | \\ #{ESCAPE} )? '? /ox)
86 # kind = :char
87
88 elsif scan(/0[xX][0-9A-Fa-f]+/)
89 kind = :hex
90 regexp_allowed=false
91
92 elsif scan(/(?:0[0-7]+)(?![89.eEfF])/)
93 kind = :oct
94 regexp_allowed=false
95
96 elsif scan(/(?:\d+)(?![.eEfF])/)
97 kind = :integer
98 regexp_allowed=false
99
100 elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/)
101 kind = :float
102 regexp_allowed=false
103
104 else
105 getch
106 end
107
108 elsif state == :regex
109 if scan(/[^\\\/]+/)
110 kind = :content
111 elsif scan(/\\\/|\\\\/)
112 kind = :content
113 elsif scan(/\//)
114 tokens << [matched, :delimiter]
115 tokens << [:close, :regexp]
116 state = :initial
117 next
118 else
119 getch
120 kind = :content
121 end
122
123 elsif state == :string
124 if scan(/[^\\"']+/)
125 kind = :content
126 elsif scan(/["']/)
127 if string_type==matched
128 tokens << [matched, :delimiter]
129 tokens << [:close, :string]
130 state = :initial
131 string_type=nil
132 next
133 else
134 kind = :content
135 end
136 elsif scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)
137 kind = :char
138 elsif scan(/ \\ | $ /x)
139 kind = :error
140 state = :initial
141 else
142 raise "else case \" reached; %p not handled." % peek(1), tokens
143 end
144
145 # elsif state == :include_expected
146 # if scan(/<[^>\n]+>?|"[^"\n\\]*(?:\\.[^"\n\\]*)*"?/)
147 # kind = :include
148 # state = :initial
149 #
150 # elsif match = scan(/\s+/)
151 # kind = :space
152 # state = :initial if match.index ?\n
153 #
154 # else
155 # getch
156 #
157 # end
158 #
159 else
160 raise 'else-case reached', tokens
161
162 end
163
164 match ||= matched
165 # raise [match, kind], tokens if kind == :error
166
167 tokens << [match, kind]
168
169 end
170 tokens
171
172 end
173
174 end
175
176 end end No newline at end of file
@@ -1,189 +1,190
1 module CodeRay
1 module CodeRay
2
2
3 # = FileType
3 # = FileType
4 #
4 #
5 # A simple filetype recognizer.
5 # A simple filetype recognizer.
6 #
6 #
7 # Copyright (c) 2006 by murphy (Kornelius Kalnbach) <murphy rubychan de>
7 # Copyright (c) 2006 by murphy (Kornelius Kalnbach) <murphy rubychan de>
8 #
8 #
9 # License:: LGPL / ask the author
9 # License:: LGPL / ask the author
10 # Version:: 0.1 (2005-09-01)
10 # Version:: 0.1 (2005-09-01)
11 #
11 #
12 # == Documentation
12 # == Documentation
13 #
13 #
14 # # determine the type of the given
14 # # determine the type of the given
15 # lang = FileType[ARGV.first]
15 # lang = FileType[ARGV.first]
16 #
16 #
17 # # return :plaintext if the file type is unknown
17 # # return :plaintext if the file type is unknown
18 # lang = FileType.fetch ARGV.first, :plaintext
18 # lang = FileType.fetch ARGV.first, :plaintext
19 #
19 #
20 # # try the shebang line, too
20 # # try the shebang line, too
21 # lang = FileType.fetch ARGV.first, :plaintext, true
21 # lang = FileType.fetch ARGV.first, :plaintext, true
22 module FileType
22 module FileType
23
23
24 UnknownFileType = Class.new Exception
24 UnknownFileType = Class.new Exception
25
25
26 class << self
26 class << self
27
27
28 # Try to determine the file type of the file.
28 # Try to determine the file type of the file.
29 #
29 #
30 # +filename+ is a relative or absolute path to a file.
30 # +filename+ is a relative or absolute path to a file.
31 #
31 #
32 # The file itself is only accessed when +read_shebang+ is set to true.
32 # The file itself is only accessed when +read_shebang+ is set to true.
33 # That means you can get filetypes from files that don't exist.
33 # That means you can get filetypes from files that don't exist.
34 def [] filename, read_shebang = false
34 def [] filename, read_shebang = false
35 name = File.basename filename
35 name = File.basename filename
36 ext = File.extname name
36 ext = File.extname name
37 ext.sub!(/^\./, '') # delete the leading dot
37 ext.sub!(/^\./, '') # delete the leading dot
38
38
39 type =
39 type =
40 TypeFromExt[ext] ||
40 TypeFromExt[ext] ||
41 TypeFromExt[ext.downcase] ||
41 TypeFromExt[ext.downcase] ||
42 TypeFromName[name] ||
42 TypeFromName[name] ||
43 TypeFromName[name.downcase]
43 TypeFromName[name.downcase]
44 type ||= shebang(filename) if read_shebang
44 type ||= shebang(filename) if read_shebang
45
45
46 type
46 type
47 end
47 end
48
48
49 def shebang filename
49 def shebang filename
50 begin
50 begin
51 File.open filename, 'r' do |f|
51 File.open filename, 'r' do |f|
52 first_line = f.gets
52 first_line = f.gets
53 first_line[TypeFromShebang]
53 first_line[TypeFromShebang]
54 end
54 end
55 rescue IOError
55 rescue IOError
56 nil
56 nil
57 end
57 end
58 end
58 end
59
59
60 # This works like Hash#fetch.
60 # This works like Hash#fetch.
61 #
61 #
62 # If the filetype cannot be found, the +default+ value
62 # If the filetype cannot be found, the +default+ value
63 # is returned.
63 # is returned.
64 def fetch filename, default = nil, read_shebang = false
64 def fetch filename, default = nil, read_shebang = false
65 if default and block_given?
65 if default and block_given?
66 warn 'block supersedes default value argument'
66 warn 'block supersedes default value argument'
67 end
67 end
68
68
69 unless type = self[filename, read_shebang]
69 unless type = self[filename, read_shebang]
70 return yield if block_given?
70 return yield if block_given?
71 return default if default
71 return default if default
72 raise UnknownFileType, 'Could not determine type of %p.' % filename
72 raise UnknownFileType, 'Could not determine type of %p.' % filename
73 end
73 end
74 type
74 type
75 end
75 end
76
76
77 end
77 end
78
78
79 TypeFromExt = {
79 TypeFromExt = {
80 'rb' => :ruby,
80 'rb' => :ruby,
81 'rbw' => :ruby,
81 'rbw' => :ruby,
82 'rake' => :ruby,
82 'rake' => :ruby,
83 'mab' => :ruby,
83 'mab' => :ruby,
84 'cpp' => :c,
84 'cpp' => :c,
85 'c' => :c,
85 'c' => :c,
86 'h' => :c,
86 'h' => :c,
87 'js' => :javascript,
87 'xml' => :xml,
88 'xml' => :xml,
88 'htm' => :html,
89 'htm' => :html,
89 'html' => :html,
90 'html' => :html,
90 'xhtml' => :xhtml,
91 'xhtml' => :xhtml,
91 'raydebug' => :debug,
92 'raydebug' => :debug,
92 'rhtml' => :rhtml,
93 'rhtml' => :rhtml,
93 'ss' => :scheme,
94 'ss' => :scheme,
94 'sch' => :scheme,
95 'sch' => :scheme,
95 'yaml' => :yaml,
96 'yaml' => :yaml,
96 'yml' => :yaml,
97 'yml' => :yaml,
97 }
98 }
98
99
99 TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/
100 TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/
100
101
101 TypeFromName = {
102 TypeFromName = {
102 'Rakefile' => :ruby,
103 'Rakefile' => :ruby,
103 'Rantfile' => :ruby,
104 'Rantfile' => :ruby,
104 }
105 }
105
106
106 end
107 end
107
108
108 end
109 end
109
110
110 if $0 == __FILE__
111 if $0 == __FILE__
111 $VERBOSE = true
112 $VERBOSE = true
112 eval DATA.read, nil, $0, __LINE__+4
113 eval DATA.read, nil, $0, __LINE__+4
113 end
114 end
114
115
115 __END__
116 __END__
116
117
117 require 'test/unit'
118 require 'test/unit'
118
119
119 class TC_FileType < Test::Unit::TestCase
120 class TC_FileType < Test::Unit::TestCase
120
121
121 def test_fetch
122 def test_fetch
122 assert_raise FileType::UnknownFileType do
123 assert_raise FileType::UnknownFileType do
123 FileType.fetch ''
124 FileType.fetch ''
124 end
125 end
125
126
126 assert_throws :not_found do
127 assert_throws :not_found do
127 FileType.fetch '.' do
128 FileType.fetch '.' do
128 throw :not_found
129 throw :not_found
129 end
130 end
130 end
131 end
131
132
132 assert_equal :default, FileType.fetch('c', :default)
133 assert_equal :default, FileType.fetch('c', :default)
133
134
134 stderr, fake_stderr = $stderr, Object.new
135 stderr, fake_stderr = $stderr, Object.new
135 $err = ''
136 $err = ''
136 def fake_stderr.write x
137 def fake_stderr.write x
137 $err << x
138 $err << x
138 end
139 end
139 $stderr = fake_stderr
140 $stderr = fake_stderr
140 FileType.fetch('c', :default) { }
141 FileType.fetch('c', :default) { }
141 assert_equal "block supersedes default value argument\n", $err
142 assert_equal "block supersedes default value argument\n", $err
142 $stderr = stderr
143 $stderr = stderr
143 end
144 end
144
145
145 def test_ruby
146 def test_ruby
146 assert_equal :ruby, FileType['test.rb']
147 assert_equal :ruby, FileType['test.rb']
147 assert_equal :ruby, FileType['C:\\Program Files\\x\\y\\c\\test.rbw']
148 assert_equal :ruby, FileType['C:\\Program Files\\x\\y\\c\\test.rbw']
148 assert_equal :ruby, FileType['/usr/bin/something/Rakefile']
149 assert_equal :ruby, FileType['/usr/bin/something/Rakefile']
149 assert_equal :ruby, FileType['~/myapp/gem/Rantfile']
150 assert_equal :ruby, FileType['~/myapp/gem/Rantfile']
150 assert_equal :ruby, FileType['./lib/tasks\repository.rake']
151 assert_equal :ruby, FileType['./lib/tasks\repository.rake']
151 assert_not_equal :ruby, FileType['test_rb']
152 assert_not_equal :ruby, FileType['test_rb']
152 assert_not_equal :ruby, FileType['Makefile']
153 assert_not_equal :ruby, FileType['Makefile']
153 assert_not_equal :ruby, FileType['set.rb/set']
154 assert_not_equal :ruby, FileType['set.rb/set']
154 assert_not_equal :ruby, FileType['~/projects/blabla/rb']
155 assert_not_equal :ruby, FileType['~/projects/blabla/rb']
155 end
156 end
156
157
157 def test_c
158 def test_c
158 assert_equal :c, FileType['test.c']
159 assert_equal :c, FileType['test.c']
159 assert_equal :c, FileType['C:\\Program Files\\x\\y\\c\\test.h']
160 assert_equal :c, FileType['C:\\Program Files\\x\\y\\c\\test.h']
160 assert_not_equal :c, FileType['test_c']
161 assert_not_equal :c, FileType['test_c']
161 assert_not_equal :c, FileType['Makefile']
162 assert_not_equal :c, FileType['Makefile']
162 assert_not_equal :c, FileType['set.h/set']
163 assert_not_equal :c, FileType['set.h/set']
163 assert_not_equal :c, FileType['~/projects/blabla/c']
164 assert_not_equal :c, FileType['~/projects/blabla/c']
164 end
165 end
165
166
166 def test_html
167 def test_html
167 assert_equal :html, FileType['test.htm']
168 assert_equal :html, FileType['test.htm']
168 assert_equal :xhtml, FileType['test.xhtml']
169 assert_equal :xhtml, FileType['test.xhtml']
169 assert_equal :xhtml, FileType['test.html.xhtml']
170 assert_equal :xhtml, FileType['test.html.xhtml']
170 assert_equal :rhtml, FileType['_form.rhtml']
171 assert_equal :rhtml, FileType['_form.rhtml']
171 end
172 end
172
173
173 def test_yaml
174 def test_yaml
174 assert_equal :yaml, FileType['test.yml']
175 assert_equal :yaml, FileType['test.yml']
175 assert_equal :yaml, FileType['test.yaml']
176 assert_equal :yaml, FileType['test.yaml']
176 assert_equal :yaml, FileType['my.html.yaml']
177 assert_equal :yaml, FileType['my.html.yaml']
177 assert_not_equal :yaml, FileType['YAML']
178 assert_not_equal :yaml, FileType['YAML']
178 end
179 end
179
180
180 def test_shebang
181 def test_shebang
181 dir = './test'
182 dir = './test'
182 if File.directory? dir
183 if File.directory? dir
183 Dir.chdir dir do
184 Dir.chdir dir do
184 assert_equal :c, FileType['test.c']
185 assert_equal :c, FileType['test.c']
185 end
186 end
186 end
187 end
187 end
188 end
188
189
189 end
190 end
General Comments 0
You need to be logged in to leave comments. Login now