rocco 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rocco +14 -8
- data/lib/rocco.rb +48 -20
- data/rocco.gemspec +2 -2
- metadata +8 -4
data/bin/rocco
CHANGED
@@ -7,14 +7,14 @@
|
|
7
7
|
#/ -c, --comment-chars=<chars>
|
8
8
|
#/ The string to recognize as a comment marker
|
9
9
|
#/ -o, --output=<dir> Directory where generated HTML files are written
|
10
|
-
#/
|
11
10
|
#/ --help Show this help message
|
12
11
|
|
13
12
|
require 'optparse'
|
13
|
+
require 'fileutils'
|
14
14
|
|
15
15
|
# Write usage message to stdout and exit.
|
16
16
|
def usage(stream=$stderr, status=1)
|
17
|
-
stream.puts File.
|
17
|
+
stream.puts File.readlines(__FILE__).
|
18
18
|
grep(/^#\//).
|
19
19
|
map { |line| line.sub(/^#. ?/, '') }.
|
20
20
|
join
|
@@ -35,12 +35,20 @@ options = {}
|
|
35
35
|
ARGV.options { |o|
|
36
36
|
o.program_name = File.basename($0)
|
37
37
|
o.on("-o", "--output=DIR") { |dir| output_dir = dir }
|
38
|
-
|
39
|
-
|
38
|
+
o.on("-l", "--language=LANG") { |lang| options[:language] = lang }
|
39
|
+
o.on("-c", "--comment-chars=CHARS") { |chars| options[:comment_chars] = Regexp.escape(chars) }
|
40
40
|
o.on_tail("-h", "--help") { usage($stdout, 0) }
|
41
41
|
o.parse!
|
42
42
|
} or abort_with_note
|
43
43
|
|
44
|
+
# Use http://pygments.appspot.com in case `pygmentize(1)` isn't available.
|
45
|
+
if ! ENV['PATH'].split(':').any? { |dir| File.exist?("#{dir}/pygmentize") }
|
46
|
+
unless options[:webservice]
|
47
|
+
$stderr.puts "pygmentize not in PATH; using pygments.appspot.com instead"
|
48
|
+
options[:webservice] = true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
44
52
|
# Eat sources from ARGV.
|
45
53
|
sources << ARGV.shift while ARGV.any?
|
46
54
|
|
@@ -77,13 +85,11 @@ rescue LoadError
|
|
77
85
|
raise
|
78
86
|
end
|
79
87
|
|
80
|
-
# Create the output directory if it doesn't already exist.
|
81
|
-
Dir.mkdir output_dir if !File.directory?(output_dir)
|
82
|
-
|
83
88
|
# Run each file through Rocco and write output.
|
84
89
|
sources.each do |filename|
|
85
90
|
rocco = Rocco.new(filename, sources, options)
|
86
|
-
dest = filename.split('.')[0..-2].join('.') + '.html'
|
91
|
+
dest = File.join(output_dir, (filename.split('.')[0..-2].empty? ? filename : filename.split('.')[0..-2].join('.')) + '.html')
|
87
92
|
puts "rocco: #{filename} -> #{dest}"
|
93
|
+
FileUtils.mkdir_p File.dirname(dest)
|
88
94
|
File.open(dest, 'wb') { |fd| fd.write(rocco.to_html) }
|
89
95
|
end
|
data/lib/rocco.rb
CHANGED
@@ -38,7 +38,7 @@
|
|
38
38
|
begin
|
39
39
|
require 'rdiscount'
|
40
40
|
rescue LoadError => boom
|
41
|
-
warn "
|
41
|
+
warn "WARNING: #{boom}. Trying bluecloth."
|
42
42
|
require 'bluecloth'
|
43
43
|
Markdown = BlueCloth
|
44
44
|
end
|
@@ -47,11 +47,14 @@ end
|
|
47
47
|
# HTML templating.
|
48
48
|
require 'mustache'
|
49
49
|
|
50
|
+
# We use `Net::HTTP` to highlight code via <http://pygments.appspot.com>
|
51
|
+
require 'net/http'
|
52
|
+
|
50
53
|
# Code is run through [Pygments](http://pygments.org/) for syntax
|
51
|
-
# highlighting.
|
52
|
-
|
53
|
-
if !
|
54
|
-
|
54
|
+
# highlighting. If it's not installed, locally, use a webservice.
|
55
|
+
include FileTest
|
56
|
+
if !ENV['PATH'].split(':').any? { |dir| executable?("#{dir}/pygmentize") }
|
57
|
+
warn "WARNING: Pygments not found. Using webservice."
|
55
58
|
end
|
56
59
|
|
57
60
|
#### Public Interface
|
@@ -66,7 +69,7 @@ end
|
|
66
69
|
# means necessary and return it as a string. With no `block`, the file is read
|
67
70
|
# to retrieve data.
|
68
71
|
class Rocco
|
69
|
-
VERSION = '0.
|
72
|
+
VERSION = '0.5'
|
70
73
|
|
71
74
|
def initialize(filename, sources=[], options={}, &block)
|
72
75
|
@file = filename
|
@@ -76,7 +79,10 @@ class Rocco
|
|
76
79
|
else
|
77
80
|
File.read(filename)
|
78
81
|
end
|
79
|
-
defaults = {
|
82
|
+
defaults = {
|
83
|
+
:language => 'ruby',
|
84
|
+
:comment_chars => '#',
|
85
|
+
}
|
80
86
|
@options = defaults.merge(options)
|
81
87
|
@sources = sources
|
82
88
|
@comment_pattern = Regexp.new("^\\s*#{@options[:comment_chars]}")
|
@@ -157,15 +163,36 @@ class Rocco
|
|
157
163
|
to_html.
|
158
164
|
split(/\n*<h5>DIVIDER<\/h5>\n*/m)
|
159
165
|
|
160
|
-
# Combine all code blocks into a single big stream and run through
|
161
|
-
#
|
162
|
-
|
166
|
+
# Combine all code blocks into a single big stream and run through either
|
167
|
+
# `pygmentize(1)` or <http://pygments.appspot.com>
|
168
|
+
code_stream = code_blocks.join("\n\n#{@options[:comment_chars]} DIVIDER\n\n")
|
169
|
+
|
170
|
+
if ENV['PATH'].split(':').any? { |dir| executable?("#{dir}/pygmentize") }
|
171
|
+
code_html = highlight_pygmentize(code_stream)
|
172
|
+
else
|
173
|
+
code_html = highlight_webservice(code_stream)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Do some post-processing on the pygments output to split things back
|
177
|
+
# into sections and remove partial `<pre>` blocks.
|
178
|
+
code_html = code_html.
|
179
|
+
split(/\n*<span class="c.">#{@options[:comment_chars]} DIVIDER<\/span>\n*/m).
|
180
|
+
map { |code| code.sub(/\n?<div class="highlight"><pre>/m, '') }.
|
181
|
+
map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
|
182
|
+
|
183
|
+
# Lastly, combine the docs and code lists back into a list of two-tuples.
|
184
|
+
docs_html.zip(code_html)
|
185
|
+
end
|
186
|
+
|
187
|
+
# We `popen` a read/write pygmentize process in the parent and
|
188
|
+
# then fork off a child process to write the input.
|
189
|
+
def highlight_pygmentize(code)
|
163
190
|
code_html = nil
|
164
191
|
open("|pygmentize -l #{@options[:language]} -f html", 'r+') do |fd|
|
165
192
|
pid =
|
166
193
|
fork {
|
167
194
|
fd.close_read
|
168
|
-
fd.write
|
195
|
+
fd.write code
|
169
196
|
fd.close_write
|
170
197
|
exit!
|
171
198
|
}
|
@@ -175,15 +202,16 @@ class Rocco
|
|
175
202
|
Process.wait(pid)
|
176
203
|
end
|
177
204
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
205
|
+
code_html
|
206
|
+
end
|
207
|
+
|
208
|
+
# Pygments is not one of those things that's trivial for a ruby user to install,
|
209
|
+
# so we'll fall back on a webservice to highlight the code if it isn't available.
|
210
|
+
def highlight_webservice(code)
|
211
|
+
Net::HTTP.post_form(
|
212
|
+
URI.parse('http://pygments.appspot.com/'),
|
213
|
+
{'lang' => @options['language'], 'code' => code}
|
214
|
+
).body
|
187
215
|
end
|
188
216
|
end
|
189
217
|
|
data/rocco.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'rocco'
|
6
|
-
s.version = '0.
|
7
|
-
s.date = '2010-
|
6
|
+
s.version = '0.5'
|
7
|
+
s.date = '2010-09-10'
|
8
8
|
|
9
9
|
s.description = "Docco in Ruby"
|
10
10
|
s.summary = s.description
|
metadata
CHANGED
@@ -4,8 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
version: "0.
|
7
|
+
- 5
|
8
|
+
version: "0.5"
|
9
9
|
platform: ruby
|
10
10
|
authors:
|
11
11
|
- Ryan Tomayko
|
@@ -13,13 +13,14 @@ autorequire:
|
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
15
|
|
16
|
-
date: 2010-
|
16
|
+
date: 2010-09-10 00:00:00 -07:00
|
17
17
|
default_executable:
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: rdiscount
|
21
21
|
prerelease: false
|
22
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
23
24
|
requirements:
|
24
25
|
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
@@ -32,6 +33,7 @@ dependencies:
|
|
32
33
|
name: mustache
|
33
34
|
prerelease: false
|
34
35
|
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
35
37
|
requirements:
|
36
38
|
- - ">="
|
37
39
|
- !ruby/object:Gem::Version
|
@@ -68,6 +70,7 @@ rdoc_options: []
|
|
68
70
|
require_paths:
|
69
71
|
- lib
|
70
72
|
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
71
74
|
requirements:
|
72
75
|
- - ">="
|
73
76
|
- !ruby/object:Gem::Version
|
@@ -75,6 +78,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
78
|
- 0
|
76
79
|
version: "0"
|
77
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
78
82
|
requirements:
|
79
83
|
- - ">="
|
80
84
|
- !ruby/object:Gem::Version
|
@@ -84,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
88
|
requirements: []
|
85
89
|
|
86
90
|
rubyforge_project:
|
87
|
-
rubygems_version: 1.3.
|
91
|
+
rubygems_version: 1.3.7
|
88
92
|
signing_key:
|
89
93
|
specification_version: 2
|
90
94
|
summary: Docco in Ruby
|