visionmedia-lightr 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,53 +1,29 @@
1
1
 
2
2
  module Lightr
3
-
4
- ##
5
- # = Grammar
6
- #
7
- # Primary Lightr syntax highlighting mixin, providing
8
- # the #match method to create your own Lightr DSL.
9
- #
10
- # === Examples
11
- #
12
- # module Lightr
13
- # class Ruby
14
- # include Grammar
15
- # id = /[\w\d]*/
16
- # int = /\d[\d_]*/
17
- # match :comment, /#.*?(\n|\z)/
18
- # match :constant, /[A-Z]#{id}/
19
- # match :symbol, /:#{id}/
20
- # match :number, /-?#{int}(?:\.#{int})?/
21
- # match nil, /\n|\s|.+?/
22
- # ...
23
- #
24
-
25
3
  module Grammar
26
4
  def self.included base
27
5
  base.extend ClassMethods
28
6
  base.send :include, InstanceMethods
29
7
  end
30
-
8
+
31
9
  module ClassMethods
32
- def match name, regexp
33
- (@matchers ||= []) << [name, regexp]
34
- end
35
-
36
10
  def parse input
37
11
  new(input).parse!
38
12
  end
39
13
  end
40
-
14
+
41
15
  module InstanceMethods
42
16
  attr_reader :input, :output
43
17
  alias :to_s :output
44
-
18
+
45
19
  def initialize input
46
20
  @input, @output = input, ''
47
- @matchers = self.class.instance_variable_get :"@matchers"
48
- @regexp = Regexp.union *@matchers.transpose[1]
49
21
  end
50
-
22
+
23
+ def parse!
24
+ parse @input
25
+ end
26
+
51
27
  def escape string
52
28
  string.
53
29
  gsub(/&/, '&amp;').
@@ -55,21 +31,6 @@ module Lightr
55
31
  gsub(/>/, '&gt;').
56
32
  gsub(/"/, '&quot;')
57
33
  end
58
-
59
- def wrap string
60
- @matchers.each do |name, regexp|
61
- return escape(string) if name.nil? and string =~ regexp
62
- return %(<span class="#{name}">#{escape(string)}</span>) if string =~ regexp
63
- end
64
- end
65
-
66
- def parse!
67
- @input.dup.gsub @regexp do |match|
68
- @output << wrap(match)
69
- end
70
- self
71
- end
72
34
  end
73
-
74
35
  end
75
- end
36
+ end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Lightr
3
- VERSION = '0.0.4'
3
+ VERSION = '0.0.5'
4
4
  end
@@ -2,22 +2,22 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{lightr}
5
- s.version = "0.0.4"
5
+ s.version = "0.0.5"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["TJ Holowaychuk"]
9
- s.date = %q{2009-03-07}
10
- s.description = %q{Extremely light-weight syntax highlighting DSL.}
9
+ s.date = %q{2009-04-06}
10
+ s.description = %q{High performance syntax highlighting.}
11
11
  s.email = %q{tj@vision-media.ca}
12
- s.extra_rdoc_files = ["lib/lightr/grammars/c.rb", "lib/lightr/grammars/javascript.rb", "lib/lightr/grammars/ruby.rb", "lib/lightr/grammars.rb", "lib/lightr/mixins/grammar.rb", "lib/lightr/mixins.rb", "lib/lightr/version.rb", "lib/lightr.rb", "README.rdoc", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
13
- s.files = ["examples/c.rb", "examples/javascript.rb", "examples/ruby.rb", "History.rdoc", "lib/lightr/grammars/c.rb", "lib/lightr/grammars/javascript.rb", "lib/lightr/grammars/ruby.rb", "lib/lightr/grammars.rb", "lib/lightr/mixins/grammar.rb", "lib/lightr/mixins.rb", "lib/lightr/version.rb", "lib/lightr.rb", "lightr.gemspec", "Manifest", "Rakefile", "README.rdoc", "spec/grammars/c_spec.rb", "spec/grammars/javascript_spec.rb", "spec/grammars/ruby_spec.rb", "spec/spec_helper.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake", "Todo.rdoc"]
12
+ s.extra_rdoc_files = ["ext/javascript.rl", "ext/ruby.rl", "lib/lightr/grammars/javascript.rb", "lib/lightr/grammars/ruby.rb", "lib/lightr/grammars.rb", "lib/lightr/mixins/grammar.rb", "lib/lightr/mixins.rb", "lib/lightr/version.rb", "lib/lightr.rb", "README.rdoc", "tasks/benchmark.rake", "tasks/docs.rake", "tasks/ext.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
13
+ s.files = ["benchmarks/_huge.rb", "benchmarks/_large.rb", "benchmarks/helper.rb", "benchmarks/huge.rb", "benchmarks/large.rb", "examples/javascript.rb", "examples/ruby.rb", "ext/javascript.rl", "ext/ruby.rl", "History.rdoc", "lib/lightr/grammars/javascript.rb", "lib/lightr/grammars/ruby.rb", "lib/lightr/grammars.rb", "lib/lightr/mixins/grammar.rb", "lib/lightr/mixins.rb", "lib/lightr/version.rb", "lib/lightr.rb", "lightr.gemspec", "Manifest", "Rakefile", "README.rdoc", "spec/grammars/javascript_spec.rb", "spec/grammars/ruby_spec.rb", "spec/spec_helper.rb", "tasks/benchmark.rake", "tasks/docs.rake", "tasks/ext.rake", "tasks/gemspec.rake", "tasks/spec.rake", "Todo.rdoc"]
14
14
  s.has_rdoc = true
15
15
  s.homepage = %q{http://github.com/visionmedia/lightr}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Lightr", "--main", "README.rdoc"]
17
- s.require_paths = ["lib"]
17
+ s.require_paths = ["lib", "ext"]
18
18
  s.rubyforge_project = %q{lightr}
19
19
  s.rubygems_version = %q{1.3.1}
20
- s.summary = %q{Extremely light-weight syntax highlighting DSL.}
20
+ s.summary = %q{High performance syntax highlighting.}
21
21
 
22
22
  if s.respond_to? :specification_version then
23
23
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -8,30 +8,57 @@ describe Lightr::JavaScript do
8
8
  describe "should highlight" do
9
9
 
10
10
  it 'strings' do
11
- parse('"test"').should include('class="string">&quot;test&quot;')
12
- parse("'test'").should include(%(class="string">'test'))
11
+ parse('"test"').should highlight(:string, '&quot;test&quot;')
12
+ parse("'test'").should highlight(:string, "'test'")
13
+ end
14
+
15
+ it "strings with escaped quotes" do
16
+ parse("'\''").should highlight(:string, "'\\''")
17
+ parse('"\""').should highlight(:string, '&quot;\&quot;&quot;')
18
+ end
19
+
20
+ it 'this' do
21
+ parse('this.test').should highlight(:self, 'this')
13
22
  end
14
23
 
15
24
  it 'comments' do
16
- parse('test // comment').should include('class="comment">// comment')
17
- # TODO: fixme
18
- # parse('test // comment "Test"').should include('class="comment">// comment')
25
+ parse("//foo bar\n").should highlight(:comment, "//foo bar\n")
26
+ parse("test /// foo 'bar' \n").should highlight(:comment, "/// foo 'bar' \n")
27
+ end
28
+
29
+ it "regular expressions" do
30
+ parse('/test/').should highlight(:regexp, '/test/')
31
+ end
32
+
33
+ it "regular expressions with mode flags" do
34
+ parse('/test/sex').should highlight(:regexp, '/test/sex')
35
+ parse('/test/sex test').should highlight(:regexp, '/test/sex')
36
+ end
37
+
38
+ it "integers" do
39
+ parse('100').should highlight(:number, '100')
40
+ parse('100').should highlight(:int, '100')
41
+ end
42
+
43
+ it "floats" do
44
+ parse('1.3').should highlight(:number, '1.3')
45
+ parse('1.3').should highlight(:float, '1.3')
19
46
  end
20
47
 
21
- %w( if else throw break case catch continue default delete do double true
22
- false final finally float for function int instanceof in long new null return short
23
- switch throw try typeof var void while with ).
48
+ it "constructors as constants" do
49
+ parse('FooBar').should highlight(:constant, 'FooBar')
50
+ parse('FOOBAR').should highlight(:constant, 'FOOBAR')
51
+ end
52
+
53
+ %w( if else break default case continue do delete true false class enum const final
54
+ for function instanceof new null return throw try typeof var void with while finally in ).
24
55
  each do |keyword|
25
56
  it "#{keyword.strip} as a keyword" do
26
- parse("#{keyword.strip} foo").should include(%(class="keyword">#{keyword.strip} <))
57
+ parse("\n#{keyword.strip} foo").should highlight(:keyword, keyword.strip)
58
+ parse("(#{keyword.strip})").should highlight(:keyword, keyword.strip)
27
59
  end
28
60
  end
29
-
30
- end
31
-
32
- it 'should not highlight // within strings as comment' do
33
- parse('"//test"').should include(%(class="string">&quot;//test&quot;))
34
- parse("'//test'").should include(%(class="string">'//test'))
61
+
35
62
  end
36
-
37
- end
63
+
64
+ end
@@ -8,65 +8,169 @@ describe Lightr::Ruby do
8
8
  describe "should highlight" do
9
9
 
10
10
  it 'symbols' do
11
- parse('a :symbol').should include('class="symbol">:symbol')
12
- parse(':"foo bar" test').should include('class="symbol">:&quot;foo bar&quot;<')
11
+ parse('a :symbol is cool').should highlight(:symbol, ':symbol')
12
+ parse(':"foo bar" test').should highlight(:symbol, ':&quot;foo bar&quot;')
13
13
  end
14
14
 
15
15
  it 'strings' do
16
- parse('"test"').should include('class="string">&quot;test&quot;')
17
- parse("'test'").should include(%(class="string">'test'))
16
+ parse('"test"').should highlight(:string, '&quot;test&quot;')
17
+ parse("'test'").should highlight(:string, "'test'")
18
+ end
19
+
20
+ it "strings with escaped quotes" do
21
+ parse("'\''").should highlight(:string, "'\\''")
22
+ parse('"\""').should highlight(:string, '&quot;\&quot;&quot;')
23
+ end
24
+
25
+ it "string %( alternate syntax" do
26
+ parse('%(something)').should highlight(:string, '%(something)')
27
+ end
28
+
29
+ it "strings with interpolation" do
30
+ output = parse("begin#\{ (foo ? 'foo' : 'bar' ) \}end")
31
+ output.should include('class="string">begin<')
32
+ output.should include('class="string">foo<')
33
+ output.should include('class="string">bar<')
34
+ output.should include('class="string">end<')
35
+ end
36
+
37
+ it "array %w( alternative syntax" do
38
+ parse('%w( foo bar )').should highlight(:string, '%w( foo bar )')
39
+ parse('%w( foo bar )').should highlight(:array, '%w( foo bar )')
18
40
  end
19
41
 
20
42
  it 'self' do
21
- parse('self.test').should include('class="self">self<')
43
+ parse('self.test').should highlight(:self, 'self')
44
+ end
45
+
46
+ it "block params" do
47
+ parse('|foo, bar|').should highlight(:params, '|foo, bar|')
22
48
  end
23
49
 
24
50
  it 'comments' do
25
- parse('test # comment').should include('class="comment"># comment')
51
+ parse("# foo bar\n").should highlight(:comment, "# foo bar\n")
52
+ parse("test # foo 'bar' \n").should highlight(:comment, "# foo 'bar' \n")
53
+ end
54
+
55
+ it "shell" do
56
+ parse("`foo bar`").should highlight(:shell, '`foo bar`')
57
+ parse("`foo bar`").should highlight(:string, '`foo bar`')
58
+ end
59
+
60
+ it "shell %x{ alternative syntax" do
61
+ parse("%x{foo}").should highlight(:shell, '%x{foo}')
62
+ parse("%x{foo}").should highlight(:string, '%x{foo}')
26
63
  end
27
64
 
28
65
  it "regular expressions" do
29
- parse('/test/').should include('class="regexp">/test/')
66
+ parse('/test/').should highlight(:regexp, '/test/')
67
+ end
68
+
69
+ it "regular expressions when using %r{ alternative syntax" do
70
+ parse('%r{/foo/}').should highlight(:regexp, '%r{/foo/}')
71
+ parse('%r{/foo/}').should highlight(:string, '%r{/foo/}')
30
72
  end
31
73
 
32
74
  it "regular expressions with mode flags" do
33
- parse('/test/sex').should include('class="regexp">/test/sex')
34
- parse('/test/sex test').should include('class="regexp">/test/sex<')
75
+ parse('/test/sex').should highlight(:regexp, '/test/sex')
76
+ parse('/test/sex test').should highlight(:regexp, '/test/sex')
77
+ parse('%r{test}sex test').should highlight(:regexp, '%r{test}sex')
35
78
  end
36
79
 
37
80
  it "instance variables" do
38
- parse('@foo_1').should include('class="variable">@foo_1<')
81
+ parse('@foo_1').should highlight(:instance, '@foo_1')
82
+ parse('@foo_1').should highlight(:variable, '@foo_1')
39
83
  end
40
84
 
41
85
  it "class variables" do
42
- parse('@@__bar').should include('class="variable">@@__bar<')
86
+ parse('@@__bar').should highlight(:class, '@@__bar')
87
+ parse('@@__bar').should highlight(:variable, '@@__bar')
88
+ end
89
+
90
+ it "global variables" do
91
+ parse('$foo').should highlight(:variable, '$foo')
92
+ parse('$foo').should highlight(:global, '$foo')
93
+ parse('$:').should highlight(:variable, '$:')
94
+ parse('$:').should highlight(:global, '$:')
95
+ parse('($~)').should highlight(:variable, '$~')
96
+ parse('($~)').should highlight(:global, '$~')
43
97
  end
44
98
 
45
- %w( 11 1_000 1.1 1.100_00 ).each do |number|
46
- it "#{number} as number" do
47
- parse(number).should include('class="number"')
48
- end
99
+ it "integers" do
100
+ parse('100_000').should highlight(:number, '100_000')
101
+ parse('100_000').should highlight(:int, '100_000')
102
+ end
103
+
104
+ it "floats" do
105
+ parse('1.3').should highlight(:number, '1.3')
106
+ parse('1.3').should highlight(:float, '1.3')
49
107
  end
50
108
 
109
+ it "ranges" do
110
+ parse('1..10').should highlight(:number, '1..10')
111
+ parse('1..10').should highlight(:range, '1..10')
112
+ parse('1...10').should highlight(:number, '1...10')
113
+ parse('1...10').should highlight(:range, '1...10')
114
+ end
115
+
51
116
  it "constants" do
52
- parse('FooBar').should include('class="constant"')
53
- parse('FOOBAR').should include('class="constant"')
117
+ parse('FooBar').should highlight(:constant, 'FooBar')
118
+ parse('FOOBAR').should highlight(:constant, 'FOOBAR')
119
+ parse('__FILE__').should highlight(:constant, '__FILE__')
120
+ end
121
+
122
+ it "constants with namespace resolution" do
123
+ parse('Foo::Bar').should highlight(:constant, 'Foo::Bar')
124
+ parse('Foo::Bar.test()').should highlight(:constant, 'Foo::Bar')
125
+ end
126
+
127
+ it "heredoc syntax" do
128
+ parse('
129
+ <<-EOF
130
+ stuff
131
+ EOF
132
+ ').should highlight(:string, "<<-EOF\n stuff\n EOF")
133
+ parse('
134
+ <<EOF
135
+ stuff
136
+ EOF
137
+ ').should highlight(:string, "<<EOF\n stuff\n EOF")
138
+ parse("
139
+ <<-'...'
140
+ stuff
141
+ ...
142
+ ").should highlight(:string, "<<-'...'\n stuff\n ...")
143
+ end
144
+
145
+ it "contents after __END__ as a comment" do
146
+ ruby = parse(%(
147
+ :foo
148
+ __END__
149
+ :bar
150
+ should not be literal ruby
151
+ "test"
152
+ ))
153
+ ruby.should include('class="string symbol">:foo')
154
+ ruby.should include('class="keyword">__END__</span><span class="comment"')
54
155
  end
55
156
 
56
157
  %w( if else elsif unless retry super then true while until class module def end in alias
57
158
  BEGIN END begin break defined do nil not or and redo rescue return yield ).
58
159
  each do |keyword|
59
160
  it "#{keyword.strip} as a keyword" do
60
- parse("#{keyword.strip} foo").should include(%(class="keyword">#{keyword.strip} <))
161
+ parse("\n#{keyword.strip} foo").should highlight(:keyword, keyword.strip)
162
+ parse("(#{keyword.strip})").should highlight(:keyword, keyword.strip)
61
163
  end
62
164
  end
63
-
64
- end
65
165
 
66
- it 'should not highlight # within regexp or strings as comment' do
67
- parse('/#test/').should include('class="regexp">/#test/')
68
- parse('"#test"').should include(%(class="string">&quot;#test&quot;))
69
- parse("'#test'").should include(%(class="string">'#test'))
70
166
  end
71
167
 
168
+ describe "should not highlight" do
169
+
170
+ it "keywords when part of other words" do
171
+ parse('define').should_not highlight(:keyword, 'def')
172
+ end
173
+
174
+ end
175
+
72
176
  end
@@ -1,2 +1,31 @@
1
1
 
2
2
  require 'lightr'
3
+
4
+ class HighlightMatcher
5
+ def initialize klass, contents
6
+ @klass, @contents = klass, contents
7
+ end
8
+
9
+ def matches? got
10
+ @input = got
11
+ @classes = $1.split if got.match /class="(.*?)"/
12
+ @got = $1 if got.match /">(.*?)<\//
13
+ @classes.include? @klass.to_s and @got == @contents rescue false
14
+ end
15
+
16
+ def failure_message
17
+ "expected #{@input} to have class '#{@klass}' and contents of '#{@contents}'"
18
+ end
19
+
20
+ def negative_failure_message
21
+ "expected #{@input} to not have class '#{@klass}' and contents of '#{@contents}'"
22
+ end
23
+
24
+ def description
25
+ "highlight #{@klass}s"
26
+ end
27
+ end
28
+
29
+ def highlight klass, contents
30
+ HighlightMatcher.new klass, contents
31
+ end
@@ -0,0 +1,6 @@
1
+
2
+ desc 'Run all benchmark suites for SIZE or large'
3
+ task :benchmark do
4
+ size = ENV['SIZE'] || 'large'
5
+ ruby "benchmarks/#{size}.rb"
6
+ end
@@ -0,0 +1,20 @@
1
+
2
+ FSMS = Dir['ext/*.rl']
3
+
4
+ namespace :ext do
5
+
6
+ desc 'Build ragel scanners'
7
+ task :build do
8
+ FSMS.each do |fsm|
9
+ `ragel #{fsm} -R -F1 -o lib/lightr/grammars/#{ File.basename(fsm).sub('.rl', '.rb') }`
10
+ puts "Built #{fsm}"
11
+ end
12
+ end
13
+
14
+ desc 'Build scanners and run specs'
15
+ task :spec do
16
+ task(:'ext:build').invoke
17
+ task(:'spec').invoke
18
+ end
19
+
20
+ end