coderay 0.4.3.48
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +340 -0
- data/README +103 -0
- data/demo/demo_count.rb +10 -0
- data/demo/demo_css.rb +4 -0
- data/demo/demo_div.rb +19 -0
- data/demo/demo_dump.rb +15 -0
- data/demo/demo_encoder.rb +39 -0
- data/demo/demo_global_vars.rb +13 -0
- data/demo/demo_global_vars2.rb +28 -0
- data/demo/demo_html.rb +394 -0
- data/demo/demo_html2.rb +11 -0
- data/demo/demo_load_encoder.rb +17 -0
- data/demo/demo_more.rb +204 -0
- data/demo/demo_scanner.rb +36 -0
- data/demo/demo_server.rb +92 -0
- data/demo/demo_simple.rb +10 -0
- data/demo/demo_stream.rb +25 -0
- data/demo/demo_stream2.rb +8 -0
- data/demo/demo_tokens.rb +3 -0
- data/lib/coderay.rb +284 -0
- data/lib/coderay/encoder.rb +151 -0
- data/lib/coderay/encoders/count.rb +21 -0
- data/lib/coderay/encoders/div.rb +16 -0
- data/lib/coderay/encoders/helpers/html_css.rb +155 -0
- data/lib/coderay/encoders/helpers/html_helper.rb +68 -0
- data/lib/coderay/encoders/helpers/html_output.rb +237 -0
- data/lib/coderay/encoders/html.rb +169 -0
- data/lib/coderay/encoders/null.rb +20 -0
- data/lib/coderay/encoders/span.rb +16 -0
- data/lib/coderay/encoders/statistic.rb +74 -0
- data/lib/coderay/encoders/text.rb +33 -0
- data/lib/coderay/encoders/tokens.rb +44 -0
- data/lib/coderay/encoders/yaml.rb +19 -0
- data/lib/coderay/helpers/filetype.rb +145 -0
- data/lib/coderay/helpers/gzip_simple.rb +123 -0
- data/lib/coderay/helpers/plugin.rb +286 -0
- data/lib/coderay/helpers/scanner_helper.rb +63 -0
- data/lib/coderay/scanner.rb +197 -0
- data/lib/coderay/scanners/c.rb +147 -0
- data/lib/coderay/scanners/delphi.rb +123 -0
- data/lib/coderay/scanners/helpers/ruby_helper.rb +212 -0
- data/lib/coderay/scanners/plaintext.rb +13 -0
- data/lib/coderay/scanners/ruby.rb +337 -0
- data/lib/coderay/tokens.rb +324 -0
- metadata +89 -0
data/demo/demo_html2.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'coderay'
|
2
|
+
|
3
|
+
# scan this file
|
4
|
+
tokens = CodeRay.scan(File.read($0) * 1, :ruby)
|
5
|
+
|
6
|
+
# output it with two styles of line numbers
|
7
|
+
out = tokens.div(:line_numbers => :table)
|
8
|
+
out << '<hr />'
|
9
|
+
out << tokens.div(:line_numbers => :inline, :line_number_start => 8)
|
10
|
+
|
11
|
+
puts out.page
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'coderay'
|
2
|
+
|
3
|
+
begin
|
4
|
+
CodeRay::Encoders::YAML
|
5
|
+
rescue
|
6
|
+
puts 'CodeRay::Encoders::YAML is not defined; you must load it first.'
|
7
|
+
end
|
8
|
+
|
9
|
+
yaml_encoder = CodeRay::Encoders[:yaml]
|
10
|
+
print 'Now it is loaded: '
|
11
|
+
p yaml_encoder
|
12
|
+
puts 'See?'
|
13
|
+
|
14
|
+
tokens_encoder = require_plugin 'CodeRay::Encoders/tokens'
|
15
|
+
print 'Require is also possible: '
|
16
|
+
p tokens_encoder
|
17
|
+
puts 'See?'
|
data/demo/demo_more.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'coderay'
|
2
|
+
|
3
|
+
c, ruby = DATA.read.split(/^---$/)
|
4
|
+
DATA.rewind
|
5
|
+
me = DATA.read[/.*^__END__$/m]
|
6
|
+
$input = c + ruby + me
|
7
|
+
|
8
|
+
require 'benchmark'
|
9
|
+
time = Benchmark.realtime do
|
10
|
+
|
11
|
+
# here CodeRay comes to play
|
12
|
+
hl = CodeRay.encoder(:html, :tab_width => 2, :line_numbers => :table, :wrap => :div)
|
13
|
+
c = hl.highlight c, :c
|
14
|
+
ruby = hl.highlight ruby, :ruby
|
15
|
+
me = hl.highlight me, :ruby
|
16
|
+
|
17
|
+
body = %w[C Ruby Genereated\ by].zip([c, ruby, me]).map do |title, code|
|
18
|
+
"<h1>#{title}</h1>\n#{code}"
|
19
|
+
end.join
|
20
|
+
body = hl.class::Output.new(body, :div).page!
|
21
|
+
|
22
|
+
# CodeRay also provides a simple page generator
|
23
|
+
$output = body #hl.class.wrap_in_page body
|
24
|
+
end
|
25
|
+
|
26
|
+
File.open('test.html', 'w') do |f|
|
27
|
+
f.write $output
|
28
|
+
end
|
29
|
+
puts 'Input: %dB, Output: %dB' % [$input.size, $output.size]
|
30
|
+
puts 'Created "test.html" in %0.3f seconds (%d KB/s). Take a look with your browser.' % [time, $input.size / 1024.0 / time]
|
31
|
+
|
32
|
+
__END__
|
33
|
+
/**********************************************************************
|
34
|
+
|
35
|
+
version.c -
|
36
|
+
|
37
|
+
$Author: nobu $
|
38
|
+
$Date: 2004/03/25 12:01:40 $
|
39
|
+
created at: Thu Sep 30 20:08:01 JST 1993
|
40
|
+
|
41
|
+
Copyright (C) 1993-2003 Yukihiro Matsumoto
|
42
|
+
|
43
|
+
**********************************************************************/
|
44
|
+
|
45
|
+
#include "ruby.h"
|
46
|
+
#include "version.h"
|
47
|
+
#include <stdio.h>
|
48
|
+
|
49
|
+
const char ruby_version[] = RUBY_VERSION;
|
50
|
+
const char ruby_release_date[] = RUBY_RELEASE_DATE;
|
51
|
+
const char ruby_platform[] = RUBY_PLATFORM;
|
52
|
+
|
53
|
+
void
|
54
|
+
Init_version()
|
55
|
+
{
|
56
|
+
VALUE v = rb_obj_freeze(rb_str_new2(ruby_version));
|
57
|
+
VALUE d = rb_obj_freeze(rb_str_new2(ruby_release_date));
|
58
|
+
VALUE p = rb_obj_freeze(rb_str_new2(ruby_platform));
|
59
|
+
|
60
|
+
rb_define_global_const("RUBY_VERSION", v);
|
61
|
+
rb_define_global_const("RUBY_RELEASE_DATE", d);
|
62
|
+
rb_define_global_const("RUBY_PLATFORM", p);
|
63
|
+
}
|
64
|
+
|
65
|
+
void
|
66
|
+
ruby_show_version()
|
67
|
+
{
|
68
|
+
printf("ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
|
69
|
+
}
|
70
|
+
|
71
|
+
void
|
72
|
+
ruby_show_copyright()
|
73
|
+
{
|
74
|
+
printf("ruby - Copyright (C) 1993-%d Yukihiro Matsumoto\n", RUBY_RELEASE_YEAR);
|
75
|
+
exit(0);
|
76
|
+
}
|
77
|
+
---
|
78
|
+
#
|
79
|
+
# = ostruct.rb: OpenStruct implementation
|
80
|
+
#
|
81
|
+
# Author:: Yukihiro Matsumoto
|
82
|
+
# Documentation:: Gavin Sinclair
|
83
|
+
#
|
84
|
+
# OpenStruct allows the creation of data objects with arbitrary attributes.
|
85
|
+
# See OpenStruct for an example.
|
86
|
+
#
|
87
|
+
|
88
|
+
#
|
89
|
+
# OpenStruct allows you to create data objects and set arbitrary attributes.
|
90
|
+
# For example:
|
91
|
+
#
|
92
|
+
# require 'ostruct'
|
93
|
+
#
|
94
|
+
# record = OpenStruct.new
|
95
|
+
# record.name = "John Smith"
|
96
|
+
# record.age = 70
|
97
|
+
# record.pension = 300
|
98
|
+
#
|
99
|
+
# puts record.name # -> "John Smith"
|
100
|
+
# puts record.address # -> nil
|
101
|
+
#
|
102
|
+
# It is like a hash with a different way to access the data. In fact, it is
|
103
|
+
# implemented with a hash, and you can initialize it with one.
|
104
|
+
#
|
105
|
+
# hash = { "country" => "Australia", :population => 20_000_000 }
|
106
|
+
# data = OpenStruct.new(hash)
|
107
|
+
#
|
108
|
+
# p data # -> <OpenStruct country="Australia" population=20000000>
|
109
|
+
#
|
110
|
+
class OpenStruct
|
111
|
+
#
|
112
|
+
# Create a new OpenStruct object. The optional +hash+, if given, will
|
113
|
+
# generate attributes and values. For example.
|
114
|
+
#
|
115
|
+
# require 'ostruct'
|
116
|
+
# hash = { "country" => "Australia", :population => 20_000_000 }
|
117
|
+
# data = OpenStruct.new(hash)
|
118
|
+
#
|
119
|
+
# p data # -> <OpenStruct country="Australia" population=20000000>
|
120
|
+
#
|
121
|
+
# By default, the resulting OpenStruct object will have no attributes.
|
122
|
+
#
|
123
|
+
def initialize(hash=nil)
|
124
|
+
@table = {}
|
125
|
+
if hash
|
126
|
+
for k,v in hash
|
127
|
+
@table[k.to_sym] = v
|
128
|
+
new_ostruct_member(k)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Duplicate an OpenStruct object members.
|
134
|
+
def initialize_copy(orig)
|
135
|
+
super
|
136
|
+
@table = @table.dup
|
137
|
+
end
|
138
|
+
|
139
|
+
def marshal_dump
|
140
|
+
@table
|
141
|
+
end
|
142
|
+
def marshal_load(x)
|
143
|
+
@table = x
|
144
|
+
@table.each_key{|key| new_ostruct_member(key)}
|
145
|
+
end
|
146
|
+
|
147
|
+
def new_ostruct_member(name)
|
148
|
+
unless self.respond_to?(name)
|
149
|
+
self.instance_eval %{
|
150
|
+
def #{name}; @table[:#{name}]; end
|
151
|
+
def #{name}=(x); @table[:#{name}] = x; end
|
152
|
+
}
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def method_missing(mid, *args) # :nodoc:
|
157
|
+
mname = mid.id2name
|
158
|
+
len = args.length
|
159
|
+
if mname =~ /=$/
|
160
|
+
if len != 1
|
161
|
+
raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
|
162
|
+
end
|
163
|
+
if self.frozen?
|
164
|
+
raise TypeError, "can't modify frozen #{self.class}", caller(1)
|
165
|
+
end
|
166
|
+
mname.chop!
|
167
|
+
@table[mname.intern] = args[0]
|
168
|
+
self.new_ostruct_member(mname)
|
169
|
+
elsif len == 0
|
170
|
+
@table[mid]
|
171
|
+
else
|
172
|
+
raise NoMethodError, "undefined method `#{mname}' for #{self}", caller(1)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Remove the named field from the object.
|
178
|
+
#
|
179
|
+
def delete_field(name)
|
180
|
+
@table.delete name.to_sym
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# Returns a string containing a detailed summary of the keys and values.
|
185
|
+
#
|
186
|
+
def inspect
|
187
|
+
str = "<#{self.class}"
|
188
|
+
for k,v in @table
|
189
|
+
str << " #{k}=#{v.inspect}"
|
190
|
+
end
|
191
|
+
str << ">"
|
192
|
+
end
|
193
|
+
|
194
|
+
attr_reader :table # :nodoc:
|
195
|
+
protected :table
|
196
|
+
|
197
|
+
#
|
198
|
+
# Compare this object and +other+ for equality.
|
199
|
+
#
|
200
|
+
def ==(other)
|
201
|
+
return false unless(other.kind_of?(OpenStruct))
|
202
|
+
return @table == other.table
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'coderay'
|
2
|
+
|
3
|
+
c_code = "if (*p == '{') nest++;"
|
4
|
+
puts 'C Code: ' + c_code
|
5
|
+
puts
|
6
|
+
|
7
|
+
c_scanner = CodeRay::Scanners[:c].new c_code
|
8
|
+
|
9
|
+
puts '> print only operators:'
|
10
|
+
for text, kind in c_scanner
|
11
|
+
print text if kind == :operator
|
12
|
+
end
|
13
|
+
puts
|
14
|
+
puts '-' * 30
|
15
|
+
puts
|
16
|
+
|
17
|
+
ruby_code = %q!ruby_code(:can, BE, %r[q[ui]te #{ /comple/x },] => $-s, &?\xee)!
|
18
|
+
puts 'Ruby Code: ' + ruby_code
|
19
|
+
puts
|
20
|
+
|
21
|
+
ruby_scanner = CodeRay::Scanners[:ruby].new ruby_code
|
22
|
+
|
23
|
+
puts '> has a string?'
|
24
|
+
puts ruby_scanner.
|
25
|
+
any? { |text, kind| kind == :string }
|
26
|
+
puts
|
27
|
+
|
28
|
+
puts '> number of regexps?'
|
29
|
+
puts ruby_scanner.
|
30
|
+
select { |token| token == [:open, :regexp] }.size
|
31
|
+
puts
|
32
|
+
|
33
|
+
puts '> has a string?'
|
34
|
+
puts ruby_scanner.
|
35
|
+
reject { |text, kind| not text.is_a? String }.
|
36
|
+
map { |text, kind| %("#{text}" (#{kind})) }.join(', ')
|
data/demo/demo_server.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# CodeRay dynamic highlighter
|
2
|
+
#
|
3
|
+
# Usage: start this and your browser.
|
4
|
+
#
|
5
|
+
# Go to http://localhost:49374/?<path to the file>
|
6
|
+
# (mnemonic: 49374 = Four-Nine-Three-Seven-Four = For No Token Shall Fall)
|
7
|
+
# and you should get the highlighted version.
|
8
|
+
|
9
|
+
require 'webrick'
|
10
|
+
require 'pathname'
|
11
|
+
|
12
|
+
class << File
|
13
|
+
alias dir? directory?
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'erb'
|
17
|
+
include ERB::Util
|
18
|
+
def url_decode s
|
19
|
+
s.to_s.gsub(/%([0-9a-f]{2})/i) { [$1.hex].pack 'C' }
|
20
|
+
end
|
21
|
+
|
22
|
+
class String
|
23
|
+
def to_link name = File.basename(self)
|
24
|
+
"<a href=\"?path=#{url_encode self}\">#{name}</a>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'coderay'
|
29
|
+
class CodeRayServlet < WEBrick::HTTPServlet::AbstractServlet
|
30
|
+
|
31
|
+
STYLE = 'style="font-family: sans-serif; color: navy;"'
|
32
|
+
BANNER = '<p><img src="http://rd.cYcnus.de/coderay/coderay-banner" style="border: 0" alt="HIghlighted by CodeRay"/></p>'
|
33
|
+
|
34
|
+
def do_GET req, res
|
35
|
+
q = req.query_string || ''
|
36
|
+
args = Hash[*q.scan(/(.*?)=(.*?)(?:&|$)/).flatten].each_value { |v| v.replace url_decode(v) }
|
37
|
+
path = args.fetch 'path', '.'
|
38
|
+
|
39
|
+
backlinks = '<p>current path: %s<br />' % html_escape(path) +
|
40
|
+
(Pathname.new(path) + '..').cleanpath.to_s.to_link('up') + ' - ' +
|
41
|
+
'.'.to_link('current') + '</p>'
|
42
|
+
|
43
|
+
res.body =
|
44
|
+
if File.dir? path
|
45
|
+
path = Pathname.new(path).cleanpath.to_s
|
46
|
+
dirs, files = Dir[File.join(path, '*')].sort.partition { |p| File.dir? p }
|
47
|
+
|
48
|
+
page = "<html><head></head><body #{STYLE}>"
|
49
|
+
page << backlinks
|
50
|
+
|
51
|
+
page << '<dl>'
|
52
|
+
page << "<dt>Directories</dt>\n" + dirs.map do |p|
|
53
|
+
"<dd>#{p.to_link}</dd>\n"
|
54
|
+
end.join << "\n"
|
55
|
+
page << "<dt>Files</dt>\n" + files.map do |p|
|
56
|
+
"<dd>#{p.to_link}</dd>\n"
|
57
|
+
end.join << "\n"
|
58
|
+
page << "</dl>\n"
|
59
|
+
page << "#{BANNER}</body></html>"
|
60
|
+
|
61
|
+
elsif File.exist? path
|
62
|
+
div = CodeRay.scan_file(path).html :tab_width => 8, :wrap => :div
|
63
|
+
div.replace <<-DIV
|
64
|
+
<div #{STYLE}>
|
65
|
+
#{backlinks}
|
66
|
+
#{div}
|
67
|
+
</div>
|
68
|
+
#{BANNER}
|
69
|
+
DIV
|
70
|
+
div.page
|
71
|
+
end
|
72
|
+
|
73
|
+
res['Content-Type'] = 'text/html'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# this is taken by "qip_msgd" - I don't know that.
|
78
|
+
module CodeRay
|
79
|
+
PORT = 0xC0DE / 20
|
80
|
+
end
|
81
|
+
|
82
|
+
server = WEBrick::HTTPServer.new :Port => CodeRay::PORT
|
83
|
+
|
84
|
+
server.mount '/', CodeRayServlet
|
85
|
+
|
86
|
+
server.mount_proc '/version' do |req, res|
|
87
|
+
res.body = 'CodeRay::Version = ' + CodeRay::Version
|
88
|
+
res['Content-Type'] = "text/plain"
|
89
|
+
end
|
90
|
+
|
91
|
+
trap("INT") { server.shutdown }
|
92
|
+
server.start
|
data/demo/demo_simple.rb
ADDED
data/demo/demo_stream.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'coderay'
|
2
|
+
|
3
|
+
code = File.read($0) * 500
|
4
|
+
puts "Size of code: %d KB" % [code.size / 1024]
|
5
|
+
|
6
|
+
puts "Use your system's memory tracker to see how much RAM this takes."
|
7
|
+
print 'Press some key to continue...'; gets
|
8
|
+
|
9
|
+
require 'benchmark'
|
10
|
+
e = CodeRay.encoder(:div)
|
11
|
+
for do_stream in [true, false]
|
12
|
+
puts "Scanning and encoding in %s mode, please wait..." %
|
13
|
+
[do_stream ? 'streaming' : 'normal']
|
14
|
+
output = ''
|
15
|
+
time = Benchmark.realtime do
|
16
|
+
if do_stream
|
17
|
+
output = e.encode_stream(code, :ruby)
|
18
|
+
else
|
19
|
+
output = e.encode_tokens(t = CodeRay.scan(code, :ruby))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
puts 'Finished after %4.2f seconds.' % time
|
23
|
+
puts "Size of output: %d KB" % [output.size / 1024]
|
24
|
+
print 'Press some key to continue...'; gets
|
25
|
+
end
|
data/demo/demo_tokens.rb
ADDED
data/lib/coderay.rb
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
# = CodeRay Library
|
2
|
+
#
|
3
|
+
# $Id: coderay.rb 44 2005-10-01 00:59:05Z murphy $
|
4
|
+
#
|
5
|
+
# CodeRay is a Ruby library for syntax highlighting.
|
6
|
+
#
|
7
|
+
# I try to make CodeRay easy to use and intuitive, but at the same time fully featured, complete,
|
8
|
+
# fast and efficient.
|
9
|
+
#
|
10
|
+
# See README.
|
11
|
+
#
|
12
|
+
# It consists mainly of
|
13
|
+
# * the main engine: CodeRay (Scanners::Scanner, Tokens/TokenStream, Encoders::Encoder), PluginHost
|
14
|
+
# * the scanners in CodeRay::Scanners
|
15
|
+
# * the encoders in CodeRay::Encoders
|
16
|
+
#
|
17
|
+
# Here's a fancy graphic to light up this gray docu:
|
18
|
+
#
|
19
|
+
# http://rd.cYcnus.de/coderay/scheme.png
|
20
|
+
#
|
21
|
+
# == Documentation
|
22
|
+
#
|
23
|
+
# See CodeRay, Encoders, Scanners, Tokens.
|
24
|
+
#
|
25
|
+
# == Usage
|
26
|
+
#
|
27
|
+
# Remember you need RubyGems to use CodeRay. Run Ruby with -rubygems option
|
28
|
+
# if required.
|
29
|
+
#
|
30
|
+
# === Highlight Ruby code in a string as html
|
31
|
+
#
|
32
|
+
# require 'coderay'
|
33
|
+
# print CodeRay.scan('puts "Hello, world!"', :ruby).html
|
34
|
+
#
|
35
|
+
# # prints something like this:
|
36
|
+
# puts <span class="s">"Hello, world!"</span>
|
37
|
+
#
|
38
|
+
#
|
39
|
+
# === Highlight C code from a file in a html div
|
40
|
+
#
|
41
|
+
# require 'coderay'
|
42
|
+
# print CodeRay.scan(File.read('ruby.h'), :c).div
|
43
|
+
# print CodeRay.scan_file('ruby.h').html.div
|
44
|
+
#
|
45
|
+
# You can include this div in your page. The used CSS styles can be printed with
|
46
|
+
#
|
47
|
+
# % ruby -rcoderay -e "print CodeRay::Encoders[:html]::CSS"
|
48
|
+
#
|
49
|
+
# === Highlight without typing too much
|
50
|
+
#
|
51
|
+
# If you are one of the hasty (or lazy, or extremely curious) people, just run this file:
|
52
|
+
#
|
53
|
+
# % ruby -rubygems coderay.rb
|
54
|
+
#
|
55
|
+
# If the output was to fast for you, try
|
56
|
+
#
|
57
|
+
# % ruby -rubygems coderay.rb > example.html
|
58
|
+
#
|
59
|
+
# and look at the file it created.
|
60
|
+
#
|
61
|
+
# = CodeRay Module
|
62
|
+
#
|
63
|
+
# The CodeRay module provides convenience methods for the engine.
|
64
|
+
#
|
65
|
+
# * The +lang+ and +format+ arguments select Scanner and Encoder to use. These are
|
66
|
+
# simply lower-case symbols, like <tt>:python</tt> or <tt>:html</tt>.
|
67
|
+
# * All methods take an optional hash as last parameter, +options+, that is send to
|
68
|
+
# the Encoder / Scanner.
|
69
|
+
# * Input and language are always sorted in this order: +code+, +lang+.
|
70
|
+
# (This is in alphabetical order, if you need a mnemonic ;)
|
71
|
+
#
|
72
|
+
# You should be able to highlight everything you want just using this methods;
|
73
|
+
# so there is no need to dive into CodeRay's deep class hierarchy.
|
74
|
+
#
|
75
|
+
# The exmaples in the demo/ directory demonstrate common cases using this interface.
|
76
|
+
#
|
77
|
+
# = Basic Access Ways
|
78
|
+
#
|
79
|
+
# Read this to get a general view what CodeRay provides.
|
80
|
+
#
|
81
|
+
# == Scanning
|
82
|
+
#
|
83
|
+
# Scanning means analysing an input string, splitting it up into Tokens.
|
84
|
+
# Each Token knows about what type it is: string, comment, class name, etc.
|
85
|
+
#
|
86
|
+
# Each +lang+ (language) has its own Scanner; for example, <tt>:ruby</tt> code is
|
87
|
+
# handled by CodeRay::Scanners::RubyScanner.
|
88
|
+
#
|
89
|
+
# CodeRay.scan:: Scan a string in a given language into Tokens.
|
90
|
+
# This is the most common method to use.
|
91
|
+
# CodeRay.scan_file:: Scan a file and guess the language using FileType.
|
92
|
+
#
|
93
|
+
# The Tokens object you get from these methods can encode itself; see Tokens.
|
94
|
+
#
|
95
|
+
# == Encoding
|
96
|
+
#
|
97
|
+
# Encoding means compiling Tokens into an output. This can be colored HTML or
|
98
|
+
# LaTeX, a textual statistic or just the number of non-whitespace tokens.
|
99
|
+
#
|
100
|
+
# Each Encoder provides output in a specific +format+, so you select Encoders via
|
101
|
+
# formats like <tt>:html</tt> or <tt>:statistic</tt>.
|
102
|
+
#
|
103
|
+
# CodeRay.encode:: Scan and encode a string in a given language.
|
104
|
+
# CodeRay.encode_tokens:: Encode the given tokens.
|
105
|
+
# CodeRay.encode_file:: Scan a file, guess the language using FileType and encode it.
|
106
|
+
#
|
107
|
+
# == Streaming
|
108
|
+
#
|
109
|
+
# Streaming saves RAM by running Scanner and Encoder in some sort of
|
110
|
+
# pipe mode; see TokenStream.
|
111
|
+
#
|
112
|
+
# CodeRay.scan_stream:: Scan in stream mode.
|
113
|
+
#
|
114
|
+
# == All-in-One Encoding
|
115
|
+
#
|
116
|
+
# CodeRay.encode:: Highlight a string with a given input and output format.
|
117
|
+
#
|
118
|
+
# == Instanciating
|
119
|
+
#
|
120
|
+
# You can use an Encoder instance to highlight multiple inputs. This way, the setup
|
121
|
+
# for this Encoder must only be done once.
|
122
|
+
#
|
123
|
+
# CodeRay.encoder:: Create an Encoder instance with format and options.
|
124
|
+
#
|
125
|
+
# There is no CodeRay.scanner method because Scanners are bound to an input string
|
126
|
+
# on creation; you can't re-use them with another string.
|
127
|
+
#
|
128
|
+
# The scanning methods provide more flexibility; we recommend to use these.
|
129
|
+
module CodeRay
|
130
|
+
|
131
|
+
Version = '0.4.4'
|
132
|
+
|
133
|
+
require 'coderay/tokens'
|
134
|
+
require 'coderay/scanner'
|
135
|
+
require 'coderay/encoder'
|
136
|
+
|
137
|
+
|
138
|
+
class << self
|
139
|
+
|
140
|
+
# Scans the given +code+ (a String) with the Scanner for +lang+.
|
141
|
+
#
|
142
|
+
# This is a simple way to use CodeRay. Example:
|
143
|
+
# require 'coderay'
|
144
|
+
# page = CodeRay.scan("puts 'Hello, world!'", :ruby).html
|
145
|
+
#
|
146
|
+
# See also demo/demo_simple.
|
147
|
+
def scan code, lang, options = {}, &block
|
148
|
+
scanner = Scanners[lang].new code, options, &block
|
149
|
+
scanner.tokenize
|
150
|
+
end
|
151
|
+
|
152
|
+
# Scans +filename+ (a path to a code file) with the Scanner for +lang+.
|
153
|
+
#
|
154
|
+
# If +lang+ is :auto or omitted, the CodeRay::FileType module is used to
|
155
|
+
# determine it. If it cannot find out what type it is, it uses
|
156
|
+
# CodeRay::Scanners::Plaintext.
|
157
|
+
#
|
158
|
+
# Calls CodeRay.scan.
|
159
|
+
#
|
160
|
+
# Example:
|
161
|
+
# require 'coderay'
|
162
|
+
# page = CodeRay.scan_file('some_c_code.c').html
|
163
|
+
def scan_file filename, lang = :auto, options = {}, &block
|
164
|
+
file = IO.read filename
|
165
|
+
if lang == :auto
|
166
|
+
require 'coderay/helpers/filetype'
|
167
|
+
lang = FileType.fetch filename, :plaintext, true
|
168
|
+
end
|
169
|
+
scan file, lang, options = {}, &block
|
170
|
+
end
|
171
|
+
|
172
|
+
# Scan the +code+ (a string) with the scanner for +lang+.
|
173
|
+
#
|
174
|
+
# Calls scan.
|
175
|
+
#
|
176
|
+
# See CodeRay.scan.
|
177
|
+
def scan_stream code, lang, options = {}, &block
|
178
|
+
options[:stream] = true
|
179
|
+
scan code, lang, options, &block
|
180
|
+
end
|
181
|
+
|
182
|
+
# Encode a string in Streaming mode.
|
183
|
+
#
|
184
|
+
# This starts scanning +code+ with the the Scanner for +lang+
|
185
|
+
# while encodes the output with the Encoder for +format+.
|
186
|
+
# +options+ will be passed to the Encoder.
|
187
|
+
#
|
188
|
+
# See CodeRay::Encoder.encode_stream
|
189
|
+
def encode_stream code, lang, format, options = {}
|
190
|
+
encoder(format, options).encode_stream code, lang, options
|
191
|
+
end
|
192
|
+
|
193
|
+
# Encode a string.
|
194
|
+
#
|
195
|
+
# This scans +code+ with the the Scanner for +lang+ and then
|
196
|
+
# encodes it with the Encoder for +format+.
|
197
|
+
# +options+ will be passed to the Encoder.
|
198
|
+
#
|
199
|
+
# See CodeRay::Encoder.encode
|
200
|
+
def encode code, lang, format, options = {}
|
201
|
+
encoder(format, options).encode code, lang, options
|
202
|
+
end
|
203
|
+
|
204
|
+
# Encode pre-scanned Tokens.
|
205
|
+
# Use this together with CodeRay.scan:
|
206
|
+
#
|
207
|
+
# require 'coderay'
|
208
|
+
#
|
209
|
+
# # Highlight a short Ruby code example in a HTML span
|
210
|
+
# tokens = CodeRay.scan '1 + 2', :ruby
|
211
|
+
# puts CodeRay.encode_tokens(tokens, :span)
|
212
|
+
#
|
213
|
+
def encode_tokens tokens, format, options = {}
|
214
|
+
encoder(format, options).encode_tokens tokens, options
|
215
|
+
end
|
216
|
+
|
217
|
+
# Encodes +filename+ (a path to a code file) with the Scanner for +lang+.
|
218
|
+
#
|
219
|
+
# See CodeRay.scan_file.
|
220
|
+
# Notice that the second argument is the output +format+, not the input language.
|
221
|
+
#
|
222
|
+
# Example:
|
223
|
+
# require 'coderay'
|
224
|
+
# page = CodeRay.encode_file 'some_c_code.c', :html
|
225
|
+
def encode_file filename, format, options = {}
|
226
|
+
tokens = scan_file filename, auto, get_scanner_options(options)
|
227
|
+
encode_tokens tokens, format, options
|
228
|
+
end
|
229
|
+
|
230
|
+
# Finds the Encoder class for +format+ and creates an instance, passing
|
231
|
+
# +options+ to it.
|
232
|
+
#
|
233
|
+
# Example:
|
234
|
+
# require 'coderay'
|
235
|
+
#
|
236
|
+
# stats = CodeRay.encoder(:statistic)
|
237
|
+
# stats.encode("puts 17 + 4\n", :ruby)
|
238
|
+
#
|
239
|
+
# puts '%d out of %d tokens have the kind :integer.' % [
|
240
|
+
# stats.type_stats[:integer].count,
|
241
|
+
# stats.real_token_count
|
242
|
+
# ]
|
243
|
+
# #-> 2 out of 4 tokens have the kind :integer.
|
244
|
+
def encoder format, options = {}
|
245
|
+
Encoders[format].new options
|
246
|
+
end
|
247
|
+
|
248
|
+
# Extract the options for the scanner from the +options+ hash.
|
249
|
+
#
|
250
|
+
# Returns an empty Hash if <tt>:scanner_options</tt> is not set.
|
251
|
+
#
|
252
|
+
# This is used if a method like CodeRay.encode has to provide options
|
253
|
+
# for Encoder _and_ scanner.
|
254
|
+
def get_scanner_options options
|
255
|
+
options.fetch :scanner_options, {}
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
# This Exception is raised when you try to stream with something that is not
|
261
|
+
# capable of streaming.
|
262
|
+
class NotStreamableError < Exception
|
263
|
+
def initialize obj
|
264
|
+
@obj = obj
|
265
|
+
end
|
266
|
+
|
267
|
+
def to_s
|
268
|
+
'%s is not Streamable!' % @obj.class
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# A dummy module that is included by subclasses of CodeRay::Scanner an CodeRay::Encoder
|
273
|
+
# to show that they are able to handle streams.
|
274
|
+
module Streamable
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
# Run a test script.
|
280
|
+
if $0 == __FILE__
|
281
|
+
$stderr.print 'Press key to print demo.'; gets
|
282
|
+
code = File.read($0)[/module CodeRay.*/m]
|
283
|
+
print CodeRay.scan(code, :ruby).html
|
284
|
+
end
|