rouge 0.5.3 → 0.5.4
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.
- data/bin/rougify +8 -5
- data/lib/rouge/cli.rb +302 -69
- data/lib/rouge/lexer.rb +12 -2
- data/lib/rouge/lexers/c.rb +2 -0
- data/lib/rouge/lexers/cpp.rb +1 -1
- data/lib/rouge/lexers/gherkin.rb +6 -1
- data/lib/rouge/lexers/http.rb +10 -2
- data/lib/rouge/lexers/objective_c.rb +3 -1
- data/lib/rouge/theme.rb +1 -1
- data/lib/rouge/version.rb +1 -1
- data/rouge.gemspec +0 -2
- metadata +3 -19
data/bin/rougify
CHANGED
@@ -2,13 +2,16 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
ROOT_DIR = Pathname.new(__FILE__).dirname.parent
|
5
|
-
$:.push(ROOT_DIR.join('lib'))
|
5
|
+
$:.push(ROOT_DIR.join('lib').to_s)
|
6
6
|
load ROOT_DIR.join('lib/rouge.rb')
|
7
7
|
load ROOT_DIR.join('lib/rouge/cli.rb')
|
8
8
|
|
9
9
|
begin
|
10
|
-
Rouge::CLI.
|
11
|
-
rescue => e
|
12
|
-
|
13
|
-
exit
|
10
|
+
Rouge::CLI.parse(ARGV).run
|
11
|
+
rescue Rouge::CLI::Error => e
|
12
|
+
puts e.message
|
13
|
+
exit e.status
|
14
|
+
rescue Interrupt
|
15
|
+
$stderr.puts "\nrouge: interrupted"
|
16
|
+
exit 2
|
14
17
|
end
|
data/lib/rouge/cli.rb
CHANGED
@@ -1,100 +1,333 @@
|
|
1
1
|
# not required by the main lib.
|
2
2
|
# to use this module, require 'rouge/cli'.
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Rouge
|
5
|
+
class FileReader
|
6
|
+
attr_reader :input
|
7
|
+
def initialize(input)
|
8
|
+
@input = input
|
9
|
+
end
|
6
10
|
|
7
|
-
|
8
|
-
|
11
|
+
def file
|
12
|
+
case input
|
13
|
+
when '-'
|
14
|
+
$stdin
|
15
|
+
when String
|
16
|
+
File.new(input)
|
17
|
+
when ->(i){ i.respond_to? :read }
|
18
|
+
input
|
19
|
+
end
|
20
|
+
end
|
9
21
|
|
10
|
-
|
11
|
-
|
12
|
-
|
22
|
+
def read
|
23
|
+
@read ||= begin
|
24
|
+
file.read
|
25
|
+
rescue => e
|
26
|
+
$stderr.puts "unable to open #{input}: #{e.message}"
|
27
|
+
exit 1
|
28
|
+
ensure
|
29
|
+
file.close
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class CLI
|
35
|
+
def self.doc
|
36
|
+
return enum_for(:doc) unless block_given?
|
37
|
+
|
38
|
+
yield %|usage: rougify [command] [args...]|
|
39
|
+
yield %||
|
40
|
+
yield %|where <command> is one of:|
|
41
|
+
yield %| highlight #{Highlight.desc}|
|
42
|
+
yield %| help #{Help.desc}|
|
43
|
+
yield %| style #{Style.desc}|
|
44
|
+
yield %| list #{List.desc}|
|
45
|
+
yield %||
|
46
|
+
yield %|See `rougify help <command>` for more info.|
|
47
|
+
end
|
48
|
+
|
49
|
+
class Error < StandardError
|
50
|
+
attr_reader :message, :status
|
51
|
+
def initialize(message, status=1)
|
52
|
+
@message = message
|
53
|
+
@status = status
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.parse(argv=ARGV)
|
58
|
+
argv = normalize_syntax(argv)
|
59
|
+
|
60
|
+
mode = argv.shift
|
61
|
+
|
62
|
+
klass = class_from_arg(mode)
|
63
|
+
return klass.parse(argv) if klass
|
64
|
+
|
65
|
+
case mode
|
66
|
+
when '-h', '--help', 'help', '-help'
|
67
|
+
Help.parse(argv)
|
68
|
+
else
|
69
|
+
argv.unshift(mode) if mode
|
70
|
+
Highlight.parse(argv)
|
71
|
+
end
|
72
|
+
end
|
13
73
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
74
|
+
def initialize(options={})
|
75
|
+
end
|
76
|
+
|
77
|
+
def error!(msg, status=1)
|
78
|
+
raise Error.new(msg, status)
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.class_from_arg(arg)
|
82
|
+
case arg
|
83
|
+
when 'help'
|
84
|
+
Help
|
85
|
+
when 'highlight', 'hi'
|
86
|
+
Highlight
|
87
|
+
when 'style'
|
88
|
+
Style
|
89
|
+
when 'list'
|
90
|
+
List
|
18
91
|
end
|
92
|
+
end
|
19
93
|
|
20
|
-
|
21
|
-
|
94
|
+
class Help < CLI
|
95
|
+
def self.desc
|
96
|
+
"print help info"
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.doc
|
100
|
+
return enum_for(:doc) unless block_given?
|
101
|
+
|
102
|
+
yield %|usage: rougify help <command>|
|
103
|
+
yield %||
|
104
|
+
yield %|print help info for <command>.|
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.parse(argv)
|
108
|
+
opts = { :mode => CLI }
|
109
|
+
until argv.empty?
|
110
|
+
arg = argv.shift
|
111
|
+
klass = class_from_arg(arg)
|
112
|
+
if klass
|
113
|
+
opts[:mode] = klass
|
114
|
+
next
|
115
|
+
end
|
116
|
+
end
|
117
|
+
new(opts)
|
22
118
|
end
|
23
119
|
|
24
|
-
|
120
|
+
def initialize(opts={})
|
121
|
+
@mode = opts[:mode]
|
122
|
+
end
|
123
|
+
|
124
|
+
def run
|
125
|
+
@mode.doc.each(&method(:puts))
|
126
|
+
end
|
25
127
|
end
|
26
128
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
129
|
+
class Highlight < CLI
|
130
|
+
def self.desc
|
131
|
+
"highlight code"
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.doc
|
135
|
+
return enum_for(:doc) unless block_given?
|
136
|
+
|
137
|
+
yield %[usage: rougify highlight <filename> [options...]]
|
138
|
+
yield %[ rougify highlight [options...]]
|
139
|
+
yield %[]
|
140
|
+
yield %[--input-file|-i <filename> specify a file to read, or - to use stdin]
|
141
|
+
yield %[]
|
142
|
+
yield %[--lexer|-l <lexer> specify the lexer to use.]
|
143
|
+
yield %[ If not provided, rougify will try to guess]
|
144
|
+
yield %[ based on --mimetype, the filename, and the]
|
145
|
+
yield %[ file contents.]
|
146
|
+
yield %[]
|
147
|
+
yield %[--mimetype|-m <mimetype> specify a mimetype for lexer guessing]
|
148
|
+
yield %[]
|
149
|
+
yield %[--lexer-opts|-L <opts> specify lexer options in CGI format]
|
150
|
+
yield %[ (opt1=val1&opt2=val2)]
|
151
|
+
yield %[]
|
152
|
+
yield %[--formatter-opts|-F <opts> specify formatter options in CGI format]
|
153
|
+
yield %[ (opt1=val1&opt2=val2)]
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.parse(argv)
|
157
|
+
opts = {
|
158
|
+
:formatter => 'terminal256',
|
159
|
+
:input_file => '-',
|
160
|
+
:lexer_opts => {},
|
161
|
+
:formatter_opts => {},
|
162
|
+
}
|
163
|
+
|
164
|
+
until argv.empty?
|
165
|
+
arg = argv.shift
|
166
|
+
case arg
|
167
|
+
when '--input-file', '-i'
|
168
|
+
opts[:input_file] = argv.shift
|
169
|
+
when '--mimetype', '-m'
|
170
|
+
opts[:mimetype] = argv.shift
|
171
|
+
when '--lexer', '-l'
|
172
|
+
opts[:lexer] = argv.shift
|
173
|
+
when '--formatter', '-f'
|
174
|
+
opts[:formatter] = argv.shift
|
175
|
+
when '--lexer-opts', '-L'
|
176
|
+
opts[:lexer_opts] = parse_cgi(argv.shift)
|
177
|
+
when '--formatter-opts', '-F'
|
178
|
+
opts[:formatter_opts] = parse_cgi(argv.shift)
|
179
|
+
when /^--/
|
180
|
+
error! "unknown option #{arg.inspect}"
|
181
|
+
else
|
182
|
+
opts[:input_file] = arg
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
new(opts)
|
187
|
+
end
|
188
|
+
|
189
|
+
def input_stream
|
190
|
+
@input_stream ||= FileReader.new(@input_file)
|
191
|
+
end
|
192
|
+
|
193
|
+
def input
|
194
|
+
@input ||= input_stream.read
|
195
|
+
end
|
196
|
+
|
197
|
+
def lexer_class
|
198
|
+
@lexer_class ||= Lexer.guess(
|
199
|
+
:filename => @input_file,
|
200
|
+
:mimetype => @mimetype,
|
201
|
+
:source => input_stream,
|
51
202
|
)
|
52
|
-
else
|
53
|
-
lexer_class = Lexer.find(options[:lexer])
|
54
|
-
raise "unknown lexer: #{options[:lexer]}" unless lexer_class
|
55
203
|
end
|
56
204
|
|
57
|
-
|
205
|
+
def lexer
|
206
|
+
@lexer ||= lexer_class.new(@lexer_opts)
|
207
|
+
end
|
58
208
|
|
59
|
-
|
60
|
-
formatter = formatter_class.new(normalize_hash_keys(options[:formatter_opts]))
|
61
|
-
lexer = lexer_class.new(normalize_hash_keys(options[:lexer_opts]))
|
209
|
+
attr_reader :input_file, :lexer_name, :mimetype, :formatter
|
62
210
|
|
63
|
-
|
211
|
+
def initialize(opts={})
|
212
|
+
@input_file = opts[:input_file]
|
213
|
+
|
214
|
+
if opts[:lexer]
|
215
|
+
@lexer_class = Lexer.find(opts[:lexer]) \
|
216
|
+
or error! "unkown lexer #{opts[:lexer].inspect}"
|
217
|
+
else
|
218
|
+
@lexer_name = opts[:lexer]
|
219
|
+
@mimetype = opts[:mimetype]
|
220
|
+
end
|
221
|
+
|
222
|
+
@lexer_opts = opts[:lexer_opts]
|
223
|
+
|
224
|
+
formatter_class = Formatter.find(opts[:formatter]) \
|
225
|
+
or error! "unknown formatter #{opts[:formatter]}"
|
226
|
+
|
227
|
+
@formatter = formatter_class.new(opts[:formatter_opts])
|
228
|
+
end
|
229
|
+
|
230
|
+
def run
|
231
|
+
formatter.format(lexer.lex(input)) do |chunk|
|
232
|
+
print chunk
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
private
|
237
|
+
def self.parse_cgi(str)
|
238
|
+
pairs = CGI.parse(str).map { |k, v| v.first }
|
239
|
+
Hash[pairs]
|
240
|
+
end
|
64
241
|
end
|
65
242
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
raise "unknown theme: #{theme_name}" unless theme
|
243
|
+
class Style < CLI
|
244
|
+
def self.desc
|
245
|
+
"print CSS styles"
|
246
|
+
end
|
71
247
|
|
72
|
-
|
248
|
+
def self.doc
|
249
|
+
return enum_for(:doc) unless block_given?
|
250
|
+
|
251
|
+
yield %|usage: rougify style [<theme-name>] [<options>]|
|
252
|
+
yield %||
|
253
|
+
yield %|Print CSS styles for the given theme. Extra options are|
|
254
|
+
yield %|passed to the theme. Theme defaults to thankful_eyes.|
|
255
|
+
yield %||
|
256
|
+
yield %|options:|
|
257
|
+
yield %| --scope (default: .highlight) a css selector to scope by|
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.parse(argv)
|
261
|
+
opts = { :theme_name => 'thankful_eyes' }
|
262
|
+
|
263
|
+
until argv.empty?
|
264
|
+
arg = argv.shift
|
265
|
+
case arg
|
266
|
+
when /--(\w+)/
|
267
|
+
opts[$1.tr('-', '_').to_sym] = argv.shift
|
268
|
+
else
|
269
|
+
opts[:theme_name] = arg
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
new(opts)
|
274
|
+
end
|
275
|
+
|
276
|
+
def initialize(opts)
|
277
|
+
theme_class = Theme.find(opts.delete(:theme_name)) \
|
278
|
+
or error! "unknown theme: #{theme_name}"
|
279
|
+
|
280
|
+
@theme = theme_class.new(opts)
|
281
|
+
end
|
282
|
+
|
283
|
+
def run
|
284
|
+
@theme.render(&method(:puts))
|
285
|
+
end
|
73
286
|
end
|
74
287
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
288
|
+
class List < CLI
|
289
|
+
def self.desc
|
290
|
+
"list available lexers"
|
291
|
+
end
|
292
|
+
|
293
|
+
def self.doc
|
294
|
+
return enum_for(:doc) unless block_given?
|
295
|
+
|
296
|
+
yield %|usage: rouge list|
|
297
|
+
yield %||
|
298
|
+
yield %|print a list of all available lexers with their descriptions.|
|
299
|
+
end
|
300
|
+
|
301
|
+
def self.parse(argv)
|
302
|
+
new
|
303
|
+
end
|
80
304
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
305
|
+
def run
|
306
|
+
puts "== Available Lexers =="
|
307
|
+
|
308
|
+
Lexer.all.each do |lexer|
|
309
|
+
desc = "#{lexer.desc}"
|
310
|
+
if lexer.aliases.any?
|
311
|
+
desc << " [aliases: #{lexer.aliases.join(',')}]"
|
312
|
+
end
|
313
|
+
puts "%s: %s" % [lexer.tag, desc]
|
314
|
+
puts
|
85
315
|
end
|
86
|
-
puts "%s: %s" % [lexer.tag, desc]
|
87
|
-
puts
|
88
316
|
end
|
89
317
|
end
|
90
318
|
|
91
319
|
private
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
320
|
+
def self.normalize_syntax(argv)
|
321
|
+
out = []
|
322
|
+
argv.each do |arg|
|
323
|
+
case arg
|
324
|
+
when /^(--\w+)=(.*)$/
|
325
|
+
out << $1 << $2
|
326
|
+
when /^(-\w)(.+)$/
|
327
|
+
out << $1 << $2
|
328
|
+
else
|
329
|
+
out << arg
|
330
|
+
end
|
98
331
|
end
|
99
332
|
|
100
333
|
out
|
data/lib/rouge/lexer.rb
CHANGED
@@ -163,7 +163,8 @@ module Rouge
|
|
163
163
|
|
164
164
|
private
|
165
165
|
def filter_by_mimetype(lexers, mt)
|
166
|
-
lexers.select { |lexer| lexer.mimetypes.include? mt }
|
166
|
+
filtered = lexers.select { |lexer| lexer.mimetypes.include? mt }
|
167
|
+
filtered.any? ? filtered : lexers
|
167
168
|
end
|
168
169
|
|
169
170
|
# returns a list of lexers that match the given filename with
|
@@ -195,10 +196,19 @@ module Rouge
|
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
198
|
-
out
|
199
|
+
out.any? ? out : lexers
|
199
200
|
end
|
200
201
|
|
201
202
|
def best_by_source(lexers, source, threshold=0)
|
203
|
+
source = case source
|
204
|
+
when String
|
205
|
+
source
|
206
|
+
when ->(s){ s.respond_to? :read }
|
207
|
+
source.read
|
208
|
+
else
|
209
|
+
raise 'invalid source'
|
210
|
+
end
|
211
|
+
|
202
212
|
assert_utf8!(source)
|
203
213
|
|
204
214
|
source = TextAnalyzer.new(source)
|
data/lib/rouge/lexers/c.rb
CHANGED
data/lib/rouge/lexers/cpp.rb
CHANGED
data/lib/rouge/lexers/gherkin.rb
CHANGED
@@ -90,12 +90,17 @@ module Rouge
|
|
90
90
|
end
|
91
91
|
|
92
92
|
state :table do
|
93
|
-
rule(/^(?=\s*[^\s|])/) { reset_stack }
|
94
93
|
mixin :basic
|
94
|
+
rule /\n/, Text, :table_bol
|
95
95
|
rule /[|]/, Punctuation
|
96
96
|
rule /[^|\s]+/, Name
|
97
97
|
end
|
98
98
|
|
99
|
+
state :table_bol do
|
100
|
+
rule(/(?=\s*[^\s|])/) { reset_stack }
|
101
|
+
rule(//) { pop! }
|
102
|
+
end
|
103
|
+
|
99
104
|
state :description do
|
100
105
|
mixin :basic
|
101
106
|
mixin :has_examples
|
data/lib/rouge/lexers/http.rb
CHANGED
@@ -8,6 +8,14 @@ module Rouge
|
|
8
8
|
@methods ||= %w(GET POST PUT DELETE HEAD OPTIONS TRACE)
|
9
9
|
end
|
10
10
|
|
11
|
+
def content_lexer
|
12
|
+
return Lexers::PlainText unless @content_type
|
13
|
+
|
14
|
+
@content_lexer ||= Lexer.guess_by_mimetype(@content_type)
|
15
|
+
rescue Lexer::AmbiguousGuess
|
16
|
+
@content_lexer = Lexers::PlainText
|
17
|
+
end
|
18
|
+
|
11
19
|
start { @content_type = 'text/plain' }
|
12
20
|
|
13
21
|
state :root do
|
@@ -59,8 +67,8 @@ module Rouge
|
|
59
67
|
end
|
60
68
|
|
61
69
|
state :content do
|
62
|
-
rule /.+/ do |m|
|
63
|
-
delegate
|
70
|
+
rule /.+/m do |m|
|
71
|
+
delegate(content_lexer)
|
64
72
|
end
|
65
73
|
end
|
66
74
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'rouge/lexers/c'
|
2
2
|
|
3
3
|
module Rouge
|
4
4
|
module Lexers
|
@@ -133,6 +133,8 @@ module Rouge
|
|
133
133
|
end
|
134
134
|
|
135
135
|
state :forward_classname do
|
136
|
+
mixin :whitespace
|
137
|
+
|
136
138
|
rule /(#{id})(\s*)(,)(\s*)/ do
|
137
139
|
groups(Name::Class, Text, Punctuation, Text)
|
138
140
|
push
|
data/lib/rouge/theme.rb
CHANGED
data/lib/rouge/version.rb
CHANGED
data/rouge.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rouge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,8 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
13
|
-
dependencies:
|
14
|
-
- !ruby/object:Gem::Dependency
|
15
|
-
type: :runtime
|
16
|
-
name: thor
|
17
|
-
prerelease: false
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
requirements:
|
20
|
-
- - ! '>='
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '0'
|
23
|
-
none: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
requirements:
|
26
|
-
- - ! '>='
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
version: '0'
|
29
|
-
none: false
|
12
|
+
date: 2013-09-22 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
30
14
|
description: Rouge aims to a be a simple, easy-to-extend drop-in replacement for pygments.
|
31
15
|
email:
|
32
16
|
- jjmadkisson@gmail.com
|