rygments 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/CHANGELOG.markdown +11 -0
- data/README.markdown +10 -3
- data/Rakefile +14 -0
- data/ext/wrapper.c +59 -17
- data/lib/rygments.rb +4 -6
- data/lib/rygments/version.rb +1 -1
- data/rygments.gemspec +3 -0
- data/spec/rygments_spec.rb +125 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +6 -0
- metadata +43 -8
data/.gitignore
CHANGED
data/CHANGELOG.markdown
ADDED
data/README.markdown
CHANGED
@@ -6,10 +6,10 @@ highlighter.
|
|
6
6
|
Rygments differs from other implementations in that it embeds a full
|
7
7
|
Python interpreter for the Pygments Python files as a Ruby C extension.
|
8
8
|
This enables Rygments to reach a level of performance that is equal to
|
9
|
-
invoking Pygments from a native Python application, and without the overhead forking
|
9
|
+
invoking Pygments from a native Python application, and without the overhead of forking
|
10
10
|
a new process. This difference in performance really pays off when
|
11
11
|
you are highlighting lots of smaller code fragments, e.g. for blog
|
12
|
-
posts.
|
12
|
+
posts or documentation generators such as Rocco.
|
13
13
|
|
14
14
|
Compared to Albino (another popular Pygments Ruby wrapper) Rygments is over 30% faster when using it to highlight all files from the Ruby 1.9.2 source code.
|
15
15
|
|
@@ -73,7 +73,14 @@ website.
|
|
73
73
|
|
74
74
|
# Compatibility
|
75
75
|
|
76
|
-
Rygments has been tested
|
76
|
+
Rygments has been tested and is known to work on Ruby Enterprise Edition 1.8.7-2011.01 and Ruby 1.9.2.
|
77
|
+
|
78
|
+
It has been tested on the following platforms:
|
79
|
+
|
80
|
+
* OSX Snow Leopard (10.6.6)
|
81
|
+
* Ubuntu Linux (8.04 and 10.10)
|
82
|
+
|
83
|
+
If you used it with success on a different Ruby implementation or platform then please let me know so I can extend this list.
|
77
84
|
|
78
85
|
# License
|
79
86
|
|
data/Rakefile
CHANGED
@@ -1,2 +1,16 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/extensiontask'
|
5
|
+
Rake::ExtensionTask.new do |ext|
|
6
|
+
ext.name = 'wrapper'
|
7
|
+
ext.ext_dir = 'ext'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rspec/core/rake_task'
|
11
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
12
|
+
t.rspec_opts = ['--options', 'spec/spec.opts']
|
13
|
+
end
|
14
|
+
|
15
|
+
task :spec => :compile
|
16
|
+
task :default => :spec
|
data/ext/wrapper.c
CHANGED
@@ -25,6 +25,34 @@ struct wrapper_struct {
|
|
25
25
|
static VALUE rygments_class = Qnil;
|
26
26
|
static VALUE wrapper_class = Qnil;
|
27
27
|
|
28
|
+
/* This function collects a Python exception and raises it as a Ruby exception */
|
29
|
+
static void reraise() {
|
30
|
+
PyObject *ptype, *pvalue, *ptraceback, *pystr = NULL;
|
31
|
+
VALUE rstr;
|
32
|
+
|
33
|
+
if (PyErr_Occurred()) {
|
34
|
+
/* Fetch and normalize information about the exception */
|
35
|
+
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
|
36
|
+
PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
|
37
|
+
|
38
|
+
/* Convert the Python exception string to a Ruby string */
|
39
|
+
if (pvalue != NULL && (pystr = PyObject_Str(pvalue)) != NULL && PyString_Check(pystr)) {
|
40
|
+
rstr = rb_str_new2(PyString_AsString(pystr));
|
41
|
+
} else {
|
42
|
+
rstr = rb_str_new2("An unknown Python exception was thrown");
|
43
|
+
}
|
44
|
+
Py_XDECREF(pystr);
|
45
|
+
|
46
|
+
/* Release the references given by PyErr_Fetch */
|
47
|
+
Py_DECREF(ptype);
|
48
|
+
Py_XDECREF(pvalue);
|
49
|
+
Py_XDECREF(ptraceback);
|
50
|
+
|
51
|
+
/* Raise a Ruby exception */
|
52
|
+
rb_raise(rb_eRuntimeError, "%s", RSTRING_PTR(rstr));
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
28
56
|
/* This function places a string at a certain index in the given tuple */
|
29
57
|
static int put_in_tuple(PyObject *tuple, int index, const char *string) {
|
30
58
|
/* Don't accept NULL pointers */
|
@@ -57,9 +85,7 @@ static int initialize(struct wrapper_struct *s) {
|
|
57
85
|
|
58
86
|
/* Check if module was loaded successfully */
|
59
87
|
if (s->module == NULL) {
|
60
|
-
|
61
|
-
fprintf(stderr, "Failed to load the rygments python module\n");
|
62
|
-
return 1;
|
88
|
+
reraise();
|
63
89
|
}
|
64
90
|
|
65
91
|
/* Get a reference to the rygmentize function */
|
@@ -71,11 +97,12 @@ static int initialize(struct wrapper_struct *s) {
|
|
71
97
|
Py_DECREF(s->module);
|
72
98
|
|
73
99
|
if (PyErr_Occurred()) {
|
74
|
-
|
100
|
+
reraise();
|
75
101
|
}
|
76
102
|
|
77
|
-
|
78
|
-
|
103
|
+
Py_Finalize();
|
104
|
+
|
105
|
+
rb_raise(rb_eRuntimeError, "Cannot find the rygmentize function in the Python module");
|
79
106
|
}
|
80
107
|
|
81
108
|
return 0;
|
@@ -96,6 +123,11 @@ static VALUE wrapper_highlight_string(VALUE self, VALUE code, VALUE lexer, VALUE
|
|
96
123
|
PyObject *pArgs, *pValue;
|
97
124
|
int res;
|
98
125
|
|
126
|
+
/* Make sure we have three strings as input */
|
127
|
+
Check_Type(code, T_STRING);
|
128
|
+
Check_Type(lexer, T_STRING);
|
129
|
+
Check_Type(formatter, T_STRING);
|
130
|
+
|
99
131
|
/* Get the wrapper structure */
|
100
132
|
Data_Get_Struct(self, struct wrapper_struct, s);
|
101
133
|
|
@@ -109,8 +141,7 @@ static VALUE wrapper_highlight_string(VALUE self, VALUE code, VALUE lexer, VALUE
|
|
109
141
|
/* Check if we have bad arguments */
|
110
142
|
if (res) {
|
111
143
|
Py_DECREF(pArgs);
|
112
|
-
|
113
|
-
return Qnil;
|
144
|
+
rb_raise(rb_eRuntimeError, "bad input given");
|
114
145
|
}
|
115
146
|
|
116
147
|
/* Call the function */
|
@@ -119,8 +150,9 @@ static VALUE wrapper_highlight_string(VALUE self, VALUE code, VALUE lexer, VALUE
|
|
119
150
|
|
120
151
|
/* Check if we have a valid result */
|
121
152
|
if (pValue == NULL) {
|
122
|
-
|
123
|
-
|
153
|
+
reraise();
|
154
|
+
|
155
|
+
rb_raise(rb_eRuntimeError, "Call failed");
|
124
156
|
}
|
125
157
|
|
126
158
|
/* Convert the pygmentized result to a Ruby string */
|
@@ -143,23 +175,33 @@ static VALUE wrapper_highlight_string(VALUE self, VALUE code, VALUE lexer, VALUE
|
|
143
175
|
static VALUE wrapper_highlight_file(VALUE self, VALUE filename, VALUE lexer, VALUE formatter) {
|
144
176
|
FILE *f;
|
145
177
|
|
178
|
+
/* Make sure the filename is a string */
|
179
|
+
Check_Type(filename, T_STRING);
|
180
|
+
|
146
181
|
/* Open the file */
|
147
182
|
if ((f=fopen(RSTRING_PTR(filename),"r"))==NULL) {
|
148
|
-
|
149
|
-
return Qnil;
|
183
|
+
rb_sys_fail("could not open file");
|
150
184
|
}
|
151
185
|
|
152
186
|
/* Determine the file size */
|
153
|
-
fseek(f,0,SEEK_END)
|
187
|
+
if (fseek(f,0,SEEK_END) == -1) {
|
188
|
+
rb_sys_fail("could not seek to end of file");
|
189
|
+
}
|
154
190
|
long fsize=ftell(f);
|
191
|
+
if (fsize == -1) {
|
192
|
+
rb_sys_fail("could not determine file length");
|
193
|
+
}
|
155
194
|
rewind(f);
|
156
195
|
|
157
196
|
/* Read the contents of the file into a buffer */
|
158
197
|
char *buf=ALLOC_N(char, fsize);
|
159
198
|
if ((fread(buf,1,fsize,f))!=(size_t)fsize) {
|
160
|
-
|
199
|
+
/* Close file handle with cached errno value */
|
200
|
+
int err = errno;
|
161
201
|
fclose(f);
|
162
|
-
|
202
|
+
errno = err;
|
203
|
+
|
204
|
+
rb_sys_fail("could not read from file");
|
163
205
|
}
|
164
206
|
fclose(f);
|
165
207
|
|
@@ -174,7 +216,7 @@ static VALUE wrapper_highlight_file(VALUE self, VALUE filename, VALUE lexer, VAL
|
|
174
216
|
/* Free the wrapper structure and deinitialize the Python interpreter */
|
175
217
|
static void wrapper_free(void *p) {
|
176
218
|
struct wrapper_struct *s = (struct wrapper_struct *)p;
|
177
|
-
|
219
|
+
|
178
220
|
/* Decrese refcounts of the Python helper */
|
179
221
|
Py_DECREF(s->rygmentize);
|
180
222
|
Py_DECREF(s->module);
|
@@ -183,7 +225,7 @@ static void wrapper_free(void *p) {
|
|
183
225
|
if (PyErr_Occurred()) {
|
184
226
|
PyErr_Print();
|
185
227
|
}
|
186
|
-
|
228
|
+
|
187
229
|
/* Free the Python interpreter */
|
188
230
|
Py_Finalize();
|
189
231
|
|
data/lib/rygments.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "wrapper"
|
2
2
|
|
3
3
|
# = Introduction
|
4
4
|
#
|
@@ -40,6 +40,9 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "ext", "wrapper
|
|
40
40
|
# Author:: Emil Loer (http://emilloer.com)
|
41
41
|
# License:: Licensed under the terms of the MIT license
|
42
42
|
module Rygments
|
43
|
+
# The full filename of the Python helper script
|
44
|
+
HELPER_PATH = File.expand_path(File.join(File.dirname(__FILE__), "rygments"))
|
45
|
+
|
43
46
|
# Perform syntax highlighting on a string.
|
44
47
|
# Returns the highlighted string.
|
45
48
|
def self.highlight_string(code, lexer = "ruby", formatter = "html")
|
@@ -52,11 +55,6 @@ module Rygments
|
|
52
55
|
wrapper.highlight_file filename, lexer, formatter
|
53
56
|
end
|
54
57
|
|
55
|
-
private
|
56
|
-
|
57
|
-
# The full filename of the Python helper script
|
58
|
-
HELPER_PATH = File.expand_path(File.join(File.dirname(__FILE__), "rygments"))
|
59
|
-
|
60
58
|
# This function maintains a single instance of the Python wrapper
|
61
59
|
# extension.
|
62
60
|
def self.wrapper
|
data/lib/rygments/version.rb
CHANGED
data/rygments.gemspec
CHANGED
@@ -19,6 +19,9 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
+
s.add_development_dependency("rspec", ["~> 2.0"])
|
23
|
+
s.add_development_dependency("rake-compiler", ["~> 0.7"])
|
24
|
+
|
22
25
|
s.has_rdoc = true
|
23
26
|
s.extensions = ["ext/extconf.rb"]
|
24
27
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Rygments::Wrapper do
|
4
|
+
subject do
|
5
|
+
# We don't want to recreate wrappers because reinitializing Python
|
6
|
+
# fails on OSX
|
7
|
+
Rygments.wrapper
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#highlight_string" do
|
11
|
+
it "should return a string" do
|
12
|
+
subject.highlight_string("puts 'Hello World!'", "ruby", "html").should be_a(String)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should raise an exception when given an invalid formatter" do
|
16
|
+
expect {
|
17
|
+
subject.highlight_string("puts 'Hello World!", "ruby", "awesome_nonexistant_formatter")
|
18
|
+
}.to raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an exception when given an invalid lexer" do
|
22
|
+
expect {
|
23
|
+
subject.highlight_string("puts 'Hello World!", "awesome_nonexistant_lexer", "html")
|
24
|
+
}.to raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#highlight_file" do
|
29
|
+
it "should return a string" do
|
30
|
+
subject.highlight_file(__FILE__, "ruby", "html").should be_a(String)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise an exception when given a nonexisting filename" do
|
34
|
+
expect {
|
35
|
+
subject.highlight_file("this_file_does_not_exist", "ruby", "html")
|
36
|
+
}.to raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should raise an exception when given an invalid formatter" do
|
40
|
+
expect {
|
41
|
+
subject.highlight_file(__FILE__, "ruby", "awesome_nonexistant_formatter")
|
42
|
+
}.to raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should raise an exception when given an invalid lexer" do
|
46
|
+
expect {
|
47
|
+
subject.highlight_file(__FILE__, "awesome_nonexistant_lexer", "html")
|
48
|
+
}.to raise_error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe Rygments do
|
54
|
+
describe "#highlight_string" do
|
55
|
+
it "should return a string" do
|
56
|
+
Rygments.highlight_string("puts 'Hello World!'", "ruby", "html").should be_a(String)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should raise an exception when given an invalid formatter" do
|
60
|
+
expect {
|
61
|
+
Rygments.highlight_string("puts 'Hello World!", "ruby", "awesome_nonexistant_formatter")
|
62
|
+
}.to raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should raise an exception when given an invalid lexer" do
|
66
|
+
expect {
|
67
|
+
Rygments.highlight_string("puts 'Hello World!", "awesome_nonexistant_lexer", "html")
|
68
|
+
}.to raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should raise an exception when the first argument is not a string" do
|
72
|
+
expect {
|
73
|
+
Rygments.highlight_string(:no_string, "ruby", "html")
|
74
|
+
}.to raise_error
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should raise an exception when the second argument is not a string" do
|
78
|
+
expect {
|
79
|
+
Rygments.highlight_string("puts 'Hello World!", :no_string, "html")
|
80
|
+
}.to raise_error
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise an exception when the third argument is not a string" do
|
84
|
+
expect {
|
85
|
+
Rygments.highlight_string("puts 'Hello World!", "ruby", :no_string)
|
86
|
+
}.to raise_error
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#highlight_file" do
|
91
|
+
it "should return a string" do
|
92
|
+
Rygments.highlight_file(__FILE__, "ruby", "html").should be_a(String)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should raise an exception when given an invalid formatter" do
|
96
|
+
expect {
|
97
|
+
Rygments.highlight_file(__FILE__, "ruby", "awesome_nonexistant_formatter")
|
98
|
+
}.to raise_error
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should raise an exception when given an invalid lexer" do
|
102
|
+
expect {
|
103
|
+
Rygments.highlight_file(__FILE__, "awesome_nonexistant_lexer", "html")
|
104
|
+
}.to raise_error
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should raise an exception when the first argument is not a string" do
|
108
|
+
expect {
|
109
|
+
Rygments.highlight_file(:no_string, "ruby", "html")
|
110
|
+
}.to raise_error
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should raise an exception when the second argument is not a string" do
|
114
|
+
expect {
|
115
|
+
Rygments.highlight_file(__FILE__, :no_string, "html")
|
116
|
+
}.to raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should raise an exception when the third argument is not a string" do
|
120
|
+
expect {
|
121
|
+
Rygments.highlight_file(__FILE__, "ruby", :no_string)
|
122
|
+
}.to raise_error
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rygments
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Emil Loer
|
@@ -15,10 +15,39 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02
|
18
|
+
date: 2011-03-02 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 0
|
33
|
+
version: "2.0"
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake-compiler
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 5
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 7
|
48
|
+
version: "0.7"
|
49
|
+
type: :development
|
50
|
+
version_requirements: *id002
|
22
51
|
description: Rygments is a Ruby wrapper for the Pygments syntax highlighter. It uses an embedded Python interpreter to get high processing throughput.
|
23
52
|
email:
|
24
53
|
- emil@koffietijd.net
|
@@ -30,6 +59,7 @@ extra_rdoc_files: []
|
|
30
59
|
|
31
60
|
files:
|
32
61
|
- .gitignore
|
62
|
+
- CHANGELOG.markdown
|
33
63
|
- Gemfile
|
34
64
|
- README.markdown
|
35
65
|
- Rakefile
|
@@ -40,6 +70,9 @@ files:
|
|
40
70
|
- lib/rygments/rygments.py
|
41
71
|
- lib/rygments/version.rb
|
42
72
|
- rygments.gemspec
|
73
|
+
- spec/rygments_spec.rb
|
74
|
+
- spec/spec.opts
|
75
|
+
- spec/spec_helper.rb
|
43
76
|
has_rdoc: true
|
44
77
|
homepage: https://github.com/thedjinn/rygments
|
45
78
|
licenses: []
|
@@ -74,5 +107,7 @@ rubygems_version: 1.5.2
|
|
74
107
|
signing_key:
|
75
108
|
specification_version: 3
|
76
109
|
summary: Rygments is a Ruby wrapper for Pygments
|
77
|
-
test_files:
|
78
|
-
|
110
|
+
test_files:
|
111
|
+
- spec/rygments_spec.rb
|
112
|
+
- spec/spec.opts
|
113
|
+
- spec/spec_helper.rb
|