rouge 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/lib/rouge.rb +3 -0
- data/lib/rouge/cli.rb +18 -2
- data/lib/rouge/formatter.rb +7 -0
- data/lib/rouge/formatters/html.rb +4 -0
- data/lib/rouge/formatters/terminal256.rb +8 -2
- data/lib/rouge/lexer.rb +34 -4
- data/lib/rouge/lexers/c.rb +3 -0
- data/lib/rouge/lexers/common_lisp.rb +1 -0
- data/lib/rouge/lexers/cpp.rb +2 -0
- data/lib/rouge/lexers/css.rb +2 -0
- data/lib/rouge/lexers/diff.rb +2 -0
- data/lib/rouge/lexers/erb.rb +2 -0
- data/lib/rouge/lexers/factor.rb +1 -0
- data/lib/rouge/lexers/haml.rb +9 -4
- data/lib/rouge/lexers/haskell.rb +2 -0
- data/lib/rouge/lexers/html.rb +1 -0
- data/lib/rouge/lexers/java.rb +2 -0
- data/lib/rouge/lexers/javascript.rb +4 -1
- data/lib/rouge/lexers/make.rb +1 -0
- data/lib/rouge/lexers/markdown.rb +2 -0
- data/lib/rouge/lexers/perl.rb +2 -0
- data/lib/rouge/lexers/php.rb +6 -2
- data/lib/rouge/lexers/python.rb +1 -0
- data/lib/rouge/lexers/ruby.rb +2 -1
- data/lib/rouge/lexers/scheme.rb +2 -0
- data/lib/rouge/lexers/shell.rb +2 -0
- data/lib/rouge/lexers/sql.rb +137 -0
- data/lib/rouge/lexers/tcl.rb +1 -0
- data/lib/rouge/lexers/tex.rb +1 -0
- data/lib/rouge/lexers/text.rb +2 -0
- data/lib/rouge/lexers/viml.rb +98 -0
- data/lib/rouge/lexers/viml/keywords.rb +11 -0
- data/lib/rouge/lexers/xml.rb +1 -0
- data/lib/rouge/lexers/yaml.rb +4 -3
- data/lib/rouge/regex_lexer.rb +142 -43
- data/lib/rouge/template_lexer.rb +6 -0
- data/lib/rouge/text_analyzer.rb +9 -0
- data/lib/rouge/util.rb +10 -0
- data/lib/rouge/version.rb +1 -1
- metadata +5 -2
data/Gemfile
CHANGED
data/lib/rouge.rb
CHANGED
@@ -30,8 +30,11 @@ load load_dir.join('rouge/lexers/tex.rb')
|
|
30
30
|
load load_dir.join('rouge/lexers/markdown.rb')
|
31
31
|
load load_dir.join('rouge/lexers/yaml.rb')
|
32
32
|
|
33
|
+
load load_dir.join('rouge/lexers/sql.rb')
|
34
|
+
|
33
35
|
load load_dir.join('rouge/lexers/make.rb')
|
34
36
|
load load_dir.join('rouge/lexers/shell.rb')
|
37
|
+
load load_dir.join('rouge/lexers/viml.rb')
|
35
38
|
|
36
39
|
load load_dir.join('rouge/lexers/javascript.rb')
|
37
40
|
load load_dir.join('rouge/lexers/css.rb')
|
data/lib/rouge/cli.rb
CHANGED
@@ -17,7 +17,7 @@ module Rouge
|
|
17
17
|
exit 0
|
18
18
|
end
|
19
19
|
|
20
|
-
unless %w(highlight style).include?(argv.first)
|
20
|
+
unless %w(highlight style list --help -h help).include?(argv.first)
|
21
21
|
argv.unshift 'highlight'
|
22
22
|
end
|
23
23
|
|
@@ -30,7 +30,7 @@ module Rouge
|
|
30
30
|
:desc => ('Which lexer to use. If not provided, rougify will try to ' +
|
31
31
|
'guess based on --mimetype, the filename, and the file ' +
|
32
32
|
'contents.')
|
33
|
-
option :formatter, :aliases => '-f', :default => '
|
33
|
+
option :formatter, :aliases => '-f', :default => 'terminal256',
|
34
34
|
:desc => ('Which formatter to use.')
|
35
35
|
option :mimetype, :aliases => '-m',
|
36
36
|
:desc => ('a mimetype that Rouge will use to guess the correct lexer. ' +
|
@@ -71,6 +71,22 @@ module Rouge
|
|
71
71
|
puts theme.new(options).render
|
72
72
|
end
|
73
73
|
|
74
|
+
desc 'list', 'list the available lexers, formatters, and styles'
|
75
|
+
def list
|
76
|
+
puts "== Available Lexers =="
|
77
|
+
all_lexers = Lexer.all
|
78
|
+
max_len = all_lexers.map { |l| l.tag.size }.max
|
79
|
+
|
80
|
+
Lexer.all.each do |lexer|
|
81
|
+
desc = "#{lexer.desc}"
|
82
|
+
if lexer.aliases.any?
|
83
|
+
desc << " [aliases: #{lexer.aliases.join(',')}]"
|
84
|
+
end
|
85
|
+
puts "%s: %s" % [lexer.tag, desc]
|
86
|
+
puts
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
74
90
|
private
|
75
91
|
# TODO: does Thor do this for me?
|
76
92
|
def normalize_hash_keys(hash)
|
data/lib/rouge/formatter.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Rouge
|
2
|
+
# A Formatter takes a token stream and formats it for human viewing.
|
2
3
|
class Formatter
|
3
4
|
REGISTRY = {}
|
4
5
|
|
6
|
+
# Specify or get the unique tag for this formatter. This is used
|
7
|
+
# for specifying a formatter in `rougify`.
|
5
8
|
def self.tag(tag=nil)
|
6
9
|
return @tag unless tag
|
7
10
|
REGISTRY[tag] = self
|
@@ -9,14 +12,18 @@ module Rouge
|
|
9
12
|
@tag = tag
|
10
13
|
end
|
11
14
|
|
15
|
+
# Find a formatter class given a unique tag.
|
12
16
|
def self.find(tag)
|
13
17
|
REGISTRY[tag]
|
14
18
|
end
|
15
19
|
|
20
|
+
# Format a token stream.
|
16
21
|
def render(tokens)
|
17
22
|
enum_for(:stream, tokens).to_a.join
|
18
23
|
end
|
19
24
|
|
25
|
+
# @abstract
|
26
|
+
# yield strings that, when concatenated, form the formatted output
|
20
27
|
def stream(tokens, &b)
|
21
28
|
raise 'abstract'
|
22
29
|
end
|
@@ -3,13 +3,17 @@ require 'cgi'
|
|
3
3
|
|
4
4
|
module Rouge
|
5
5
|
module Formatters
|
6
|
+
# Transforms a token stream into HTML output.
|
6
7
|
class HTML < Formatter
|
7
8
|
tag 'html'
|
8
9
|
|
10
|
+
# @option opts :css_class
|
11
|
+
# A css class to be used for the generated <pre> tag.
|
9
12
|
def initialize(opts={})
|
10
13
|
@css_class = opts[:css_class] || 'highlight'
|
11
14
|
end
|
12
15
|
|
16
|
+
# @yield the html output.
|
13
17
|
def stream(tokens, &b)
|
14
18
|
yield "<pre class=#{@css_class.inspect}>"
|
15
19
|
tokens.each do |tok, val|
|
@@ -1,11 +1,17 @@
|
|
1
1
|
module Rouge
|
2
2
|
module Formatters
|
3
|
+
# A formatter for 256-color terminals
|
3
4
|
class Terminal256 < Formatter
|
4
5
|
tag 'terminal256'
|
5
6
|
|
7
|
+
# @private
|
6
8
|
attr_reader :theme
|
9
|
+
|
10
|
+
|
11
|
+
# @option opts :theme
|
12
|
+
# (default is thankful_eyes) the theme to render with.
|
7
13
|
def initialize(opts={})
|
8
|
-
@theme = opts[:theme] ||
|
14
|
+
@theme = opts[:theme] || 'thankful_eyes'
|
9
15
|
@theme = Theme.find(@theme) if @theme.is_a? String
|
10
16
|
end
|
11
17
|
|
@@ -95,7 +101,7 @@ module Rouge
|
|
95
101
|
end
|
96
102
|
end
|
97
103
|
|
98
|
-
|
104
|
+
private
|
99
105
|
def escape(attrs)
|
100
106
|
return '' if attrs.empty?
|
101
107
|
"\e[#{attrs.join(';')}m"
|
data/lib/rouge/lexer.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
require 'strscan'
|
3
3
|
|
4
4
|
module Rouge
|
5
|
+
# @abstract
|
6
|
+
# A lexer transforms text into a stream of `[token, chunk]` pairs.
|
5
7
|
class Lexer
|
6
8
|
class << self
|
7
9
|
# Lexes `stream` with the given options. The lex is delegated to a
|
@@ -23,6 +25,20 @@ module Rouge
|
|
23
25
|
registry[name.to_s]
|
24
26
|
end
|
25
27
|
|
28
|
+
# Specify or get this lexer's description.
|
29
|
+
def desc(arg=:absent)
|
30
|
+
if arg == :absent
|
31
|
+
@desc
|
32
|
+
else
|
33
|
+
@desc = arg
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @return a list of all lexers.
|
38
|
+
def all
|
39
|
+
registry.values.uniq
|
40
|
+
end
|
41
|
+
|
26
42
|
# Guess which lexer to use based on a hash of info.
|
27
43
|
#
|
28
44
|
# @option info :mimetype
|
@@ -82,6 +98,7 @@ module Rouge
|
|
82
98
|
best_match
|
83
99
|
end
|
84
100
|
|
101
|
+
# @private
|
85
102
|
def register(name, lexer)
|
86
103
|
registry[name.to_s] = lexer
|
87
104
|
end
|
@@ -100,7 +117,7 @@ module Rouge
|
|
100
117
|
return @tag if t.nil?
|
101
118
|
|
102
119
|
@tag = t.to_s
|
103
|
-
|
120
|
+
Lexer.register(@tag, self)
|
104
121
|
end
|
105
122
|
|
106
123
|
# Used to specify alternate names this lexer class may be found by.
|
@@ -113,10 +130,12 @@ module Rouge
|
|
113
130
|
#
|
114
131
|
# Lexer.find('eruby') # => Erb
|
115
132
|
def aliases(*args)
|
133
|
+
args.map!(&:to_s)
|
116
134
|
args.each { |arg| Lexer.register(arg, self) }
|
135
|
+
(@aliases ||= []).concat(args)
|
117
136
|
end
|
118
137
|
|
119
|
-
# Specify a list of filename globs associated with this lexer
|
138
|
+
# Specify a list of filename globs associated with this lexer.
|
120
139
|
#
|
121
140
|
# @example
|
122
141
|
# class Ruby < Lexer
|
@@ -144,16 +163,27 @@ module Rouge
|
|
144
163
|
|
145
164
|
# -*- instance methods -*- #
|
146
165
|
|
166
|
+
# Create a new lexer with the given options. Individual lexers may
|
167
|
+
# specify extra options. The only current globally accepted option
|
168
|
+
# is `:debug`.
|
169
|
+
#
|
170
|
+
# @option opts :debug
|
171
|
+
# Prints debug information to stdout. The particular info depends
|
172
|
+
# on the lexer in question. In regex lexers, this will log the
|
173
|
+
# state stack at the beginning of each step, along with each regex
|
174
|
+
# tried and each stream consumed. Try it, it's pretty useful.
|
147
175
|
def initialize(opts={})
|
148
176
|
options(opts)
|
149
177
|
end
|
150
178
|
|
179
|
+
# get and/or specify the options for this lexer.
|
151
180
|
def options(o={})
|
152
181
|
(@options ||= {}).merge!(o)
|
153
182
|
|
154
183
|
self.class.default_options.merge(@options)
|
155
184
|
end
|
156
185
|
|
186
|
+
# get or specify one option for this lexer
|
157
187
|
def option(k, v=:absent)
|
158
188
|
if v == :absent
|
159
189
|
options[k]
|
@@ -209,7 +239,7 @@ module Rouge
|
|
209
239
|
|
210
240
|
# @abstract
|
211
241
|
#
|
212
|
-
# Yield [token, chunk] pairs, given a prepared input stream. This
|
242
|
+
# Yield `[token, chunk]` pairs, given a prepared input stream. This
|
213
243
|
# must be implemented.
|
214
244
|
#
|
215
245
|
# @param [StringScanner] stream
|
@@ -220,7 +250,7 @@ module Rouge
|
|
220
250
|
|
221
251
|
# @abstract
|
222
252
|
#
|
223
|
-
#
|
253
|
+
# Return a number between 0 and 1 indicating the likelihood that
|
224
254
|
# the text given should be lexed with this lexer. The default
|
225
255
|
# implementation returns 0.
|
226
256
|
#
|
data/lib/rouge/lexers/c.rb
CHANGED
@@ -5,6 +5,8 @@ module Rouge
|
|
5
5
|
filenames '*.c', '*.h', '*.idc'
|
6
6
|
mimetypes 'text/x-chdr', 'text/x-csrc'
|
7
7
|
|
8
|
+
desc "The C programming language"
|
9
|
+
|
8
10
|
# optional comment or whitespace
|
9
11
|
ws = %r((?:\s|//.*?\n|/[*].*?[*]/)+)
|
10
12
|
id = /[a-zA-Z_][a-zA-Z0-9_]*/
|
@@ -55,6 +57,7 @@ module Rouge
|
|
55
57
|
rule /__(?:#{__reserved.join('|')})\b/, 'Keyword.Reserved'
|
56
58
|
rule /(?:true|false|NULL)\b/, 'Name.Builtin'
|
57
59
|
rule id, 'Name'
|
60
|
+
rule /\s+/m, 'Text'
|
58
61
|
end
|
59
62
|
|
60
63
|
state :case do
|
data/lib/rouge/lexers/cpp.rb
CHANGED
data/lib/rouge/lexers/css.rb
CHANGED
data/lib/rouge/lexers/diff.rb
CHANGED
data/lib/rouge/lexers/erb.rb
CHANGED
data/lib/rouge/lexers/factor.rb
CHANGED
data/lib/rouge/lexers/haml.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Rouge
|
2
2
|
module Lexers
|
3
|
+
# A lexer for the Haml templating system for Ruby.
|
4
|
+
# @see http://haml.info
|
3
5
|
class Haml < RegexLexer
|
6
|
+
desc "The Haml templating system for Ruby (haml.info)"
|
7
|
+
|
4
8
|
tag 'haml'
|
5
9
|
aliases 'HAML'
|
6
10
|
|
@@ -11,9 +15,10 @@ module Rouge
|
|
11
15
|
return 0.1 if text.start_with? '!!!'
|
12
16
|
end
|
13
17
|
|
14
|
-
# option :filters
|
15
|
-
# various filters should be
|
16
|
-
#
|
18
|
+
# @option opts :filters
|
19
|
+
# A hash of filter name to lexer of how various filters should be
|
20
|
+
# highlighted. By default, :javascript, :css, :ruby, and :erb
|
21
|
+
# are supported.
|
17
22
|
def initialize(opts={})
|
18
23
|
(opts.delete(:filters) || {}).each do |name, lexer|
|
19
24
|
unless lexer.respond_to? :lex
|
@@ -41,10 +46,10 @@ module Rouge
|
|
41
46
|
'css' => CSS.new(options),
|
42
47
|
'ruby' => ruby,
|
43
48
|
'erb' => ERB.new(options),
|
49
|
+
'markdown' => Markdown.new(options),
|
44
50
|
# TODO
|
45
51
|
# 'sass' => Sass.new(options),
|
46
52
|
# 'textile' => Textile.new(options),
|
47
|
-
# 'markdown' => Markdown.new(options),
|
48
53
|
# 'maruku' => Maruku.new(options),
|
49
54
|
}
|
50
55
|
end
|
data/lib/rouge/lexers/haskell.rb
CHANGED
data/lib/rouge/lexers/html.rb
CHANGED
data/lib/rouge/lexers/java.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Rouge
|
2
2
|
module Lexers
|
3
3
|
class Javascript < RegexLexer
|
4
|
+
desc "JavaScript, the browser scripting language"
|
5
|
+
|
4
6
|
tag 'javascript'
|
5
7
|
aliases 'js'
|
6
8
|
filenames '*.js'
|
@@ -94,6 +96,7 @@ module Rouge
|
|
94
96
|
end
|
95
97
|
|
96
98
|
class JSON < RegexLexer
|
99
|
+
desc "JavaScript Object Notation (json.org)"
|
97
100
|
tag 'json'
|
98
101
|
filenames '*.json'
|
99
102
|
mimetypes 'application/json'
|
@@ -102,7 +105,7 @@ module Rouge
|
|
102
105
|
# so I'd think this wouldn't be too bad, but for large documents this
|
103
106
|
# could mean doing two full lexes.
|
104
107
|
def self.analyze_text(text)
|
105
|
-
text.lexes_cleanly?(self)
|
108
|
+
return 0.8 if text =~ /\A\s*{/m && text.lexes_cleanly?(self)
|
106
109
|
end
|
107
110
|
|
108
111
|
state :root do
|
data/lib/rouge/lexers/make.rb
CHANGED
data/lib/rouge/lexers/perl.rb
CHANGED
data/lib/rouge/lexers/php.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Rouge
|
2
2
|
module Lexers
|
3
3
|
class PHP < TemplateLexer
|
4
|
+
desc "The PHP scripting language (php.net)"
|
4
5
|
tag 'php'
|
5
6
|
aliases 'php', 'php3', 'php4', 'php5'
|
6
7
|
filenames '*.php', '*.php[345]'
|
@@ -18,12 +19,15 @@ module Rouge
|
|
18
19
|
super(opts)
|
19
20
|
end
|
20
21
|
|
22
|
+
def self.builtins
|
23
|
+
load Pathname.new(__FILE__).dirname.join('php/builtins.rb')
|
24
|
+
self.builtins
|
25
|
+
end
|
26
|
+
|
21
27
|
def builtins
|
22
28
|
return [] unless @funcnamehighlighting
|
23
29
|
|
24
30
|
@builtins ||= Set.new.tap do |builtins|
|
25
|
-
require Pathname.new(__FILE__).dirname.join('php/builtins.rb')
|
26
|
-
|
27
31
|
self.class.builtins.each do |mod, fns|
|
28
32
|
next if @disabledmodules.include? mod
|
29
33
|
builtins.merge(fns)
|