diff --git a/bin/rocco b/bin/rocco index 5f03958..100e608 100755 --- a/bin/rocco +++ b/bin/rocco @@ -7,6 +7,9 @@ #/ -c, --comment-chars= #/ The string to recognize as a comment marker #/ -o, --output= Directory where generated HTML files are written +#/ -w Highlight code using http://pygments.appspot.com +#/ instead of pygmentize(1) +#/ #/ #/ --help Show this help message @@ -37,10 +40,19 @@ ARGV.options { |o| o.on("-o", "--output=DIR") { |dir| output_dir = dir } o.on("-l", "--language=LANG") { |lang| options[:language] = lang } o.on("-c", "--comment-chars=CHARS") { |chars| options[:comment_chars] = Regexp.escape(chars) } + o.on("-w") { |v| options[:webservice] = v } o.on_tail("-h", "--help") { usage($stdout, 0) } o.parse! } or abort_with_note +# Use http://pygments.appspot.com in case `pygmentize(1)` isn't available. +if ! ENV['PATH'].split(':').any? { |dir| File.exist?("#{dir}/pygmentize") } + unless options[:webservice] + $stderr.puts "pygmentize not in PATH; using pygments.appspot.com instead" + options[:webservice] = true + end +end + # Eat sources from ARGV. sources << ARGV.shift while ARGV.any? diff --git a/lib/rocco.rb b/lib/rocco.rb index c0f0474..4a544ba 100644 --- a/lib/rocco.rb +++ b/lib/rocco.rb @@ -47,12 +47,8 @@ end # HTML templating. require 'mustache' -# Code is run through [Pygments](http://pygments.org/) for syntax -# highlighting. Fail fast right here if we can't find the `pygmentize` -# program on PATH. -if ! ENV['PATH'].split(':').any? { |dir| File.exist?("#{dir}/pygmentize") } - fail "Pygments is required for syntax highlighting" -end +# We use `Net::HTTP` to highlight code via +require 'net/http' #### Public Interface @@ -76,7 +72,11 @@ class Rocco else File.read(filename) end - defaults = { :language => 'ruby', :comment_chars => '#' } + defaults = { + :language => 'ruby', + :comment_chars => '#', + :webservice => false + } @options = defaults.merge(options) @sources = sources @comment_pattern = Regexp.new("^\\s*#{@options[:comment_chars]}") @@ -157,23 +157,16 @@ class Rocco to_html. split(/\n*
DIVIDER<\/h5>\n*/m) - # Combine all code blocks into a single big stream and run through - # Pygments. We `popen` a read/write pygmentize process in the parent and - # then fork off a child process to write the input. - code_html = nil - open("|pygmentize -l #{@options[:language]} -f html", 'r+') do |fd| - pid = - fork { - fd.close_read - fd.write code_blocks.join("\n\n# DIVIDER\n\n") - fd.close_write - exit! - } - fd.close_write - code_html = fd.read - fd.close_read - Process.wait(pid) - end + # Combine all code blocks into a single big stream and run through either + # `pygmentize(1)` or + code_stream = code_blocks.join("\n\n# DIVIDER\n\n") + + code_html = + if @options[:webservice] + highlight_webservice(code_stream) + else + highlight_pygmentize(code_stream) + end # Do some post-processing on the pygments output to split things back # into sections and remove partial `
` blocks.
@@ -185,6 +178,34 @@ class Rocco
     # Lastly, combine the docs and code lists back into a list of two-tuples.
     docs_html.zip(code_html)
   end
+
+  # We `popen` a read/write pygmentize process in the parent and
+  # then fork off a child process to write the input.
+  def highlight_pygmentize(code)
+    code_html = nil
+    open("|pygmentize -l #{@options[:language]} -f html", 'r+') do |fd|
+      pid =
+        fork {
+          fd.close_read
+          fd.write code
+          fd.close_write
+          exit!
+        }
+      fd.close_write
+      code_html = fd.read
+      fd.close_read
+      Process.wait(pid)
+    end
+
+    code_html
+  end
+
+  def highlight_webservice(code)
+    Net::HTTP.post_form(
+      URI.parse('http://pygments.appspot.com/'),
+      {'lang' => 'ruby', 'code' => code}
+    ).body
+  end
 end
 
 # And that's it.