rygments 0.1.0 → 0.2.0
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/.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
|