From bc8bdccb7d52377150cc5c11cdb5573be739260e Mon Sep 17 00:00:00 2001 From: Simon Rozet Date: Fri, 19 Mar 2010 15:53:51 -0700 Subject: [PATCH 01/10] allow to use pygments.appspot.com instead of pygmentize(1) --- bin/rocco | 12 +++++++++ lib/rocco.rb | 69 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 24 deletions(-) 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.

From fb4b5404ae72214b5ee92d235bb8ef45eaa6d259 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 13:46:24 -0500
Subject: [PATCH 02/10] just use the pygments.appspot.com if there's no
 pygmentize on the path, rather than as a command line flag

---
 bin/rocco    |  5 -----
 lib/rocco.rb | 10 ++++++----
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/bin/rocco b/bin/rocco
index 100e608..aaa526f 100755
--- a/bin/rocco
+++ b/bin/rocco
@@ -7,10 +7,6 @@
 #/   -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
 
 require 'optparse'
@@ -40,7 +36,6 @@ 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
diff --git a/lib/rocco.rb b/lib/rocco.rb
index 4a544ba..28a5d4d 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -75,7 +75,6 @@ class Rocco
     defaults = {
       :language      => 'ruby',
       :comment_chars => '#',
-      :webservice    => false
     }
     @options = defaults.merge(options)
     @sources = sources
@@ -162,9 +161,10 @@ class Rocco
     code_stream = code_blocks.join("\n\n# DIVIDER\n\n")
 
     code_html =
-      if @options[:webservice]
+      if `which pygmentize` == ""
+        puts "Warning: pygmentize not installed. Using pygmentize.appspot.com"
         highlight_webservice(code_stream)
-      else
+      elsif 
         highlight_pygmentize(code_stream)
       end
 
@@ -199,7 +199,9 @@ class Rocco
 
     code_html
   end
-
+  
+  # Pygments is not one of those things that's trivial for a ruby user to install,
+  # so we'll fall back on a webservice to highlight the code if it isn't available.
   def highlight_webservice(code)
     Net::HTTP.post_form(
       URI.parse('http://pygments.appspot.com/'),

From 68b1529714f308b7c6b96992344c25726483adcc Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 13:57:45 -0500
Subject: [PATCH 03/10] Removed warning about pygmentize not being installed.

---
 lib/rocco.rb | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/rocco.rb b/lib/rocco.rb
index 28a5d4d..8407f48 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -50,6 +50,13 @@ require 'mustache'
 # We use `Net::HTTP` to highlight code via 
 require 'net/http'
 
+# Code is run through [Pygments](http://pygments.org/) for syntax
+# highlighting. If it's not installed, locally, use a webservice.
+# It may be a good idea to warn the user.
+#     if `which pygmentize` == ""
+#       puts "Warning: Pygments not found. Using pygments.appspot.com for highlighting"
+#     end
+
 #### Public Interface
 
 # `Rocco.new` takes a source `filename`, an optional list of source filenames
@@ -162,7 +169,6 @@ class Rocco
 
     code_html =
       if `which pygmentize` == ""
-        puts "Warning: pygmentize not installed. Using pygmentize.appspot.com"
         highlight_webservice(code_stream)
       elsif 
         highlight_pygmentize(code_stream)

From 17eeb9e75fdf86e01bb886ada169369eb556f3f5 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 14:07:30 -0500
Subject: [PATCH 04/10] fixed syntax error, re-added warning for webservice

---
 lib/rocco.rb | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/lib/rocco.rb b/lib/rocco.rb
index 8407f48..3a76a2d 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -38,7 +38,7 @@
 begin
   require 'rdiscount'
 rescue LoadError => boom
-  warn "warn: #{boom}. trying bluecloth"
+  warn "WARNING: #{boom}. Trying bluecloth."
   require 'bluecloth'
   Markdown = BlueCloth
 end
@@ -52,10 +52,9 @@ require 'net/http'
 
 # Code is run through [Pygments](http://pygments.org/) for syntax
 # highlighting. If it's not installed, locally, use a webservice.
-# It may be a good idea to warn the user.
-#     if `which pygmentize` == ""
-#       puts "Warning: Pygments not found. Using pygments.appspot.com for highlighting"
-#     end
+if `which pygmentize` == ""
+  warn "WARNING: Pygments not found. Using webservice."
+end
 
 #### Public Interface
 
@@ -167,12 +166,11 @@ class Rocco
     # `pygmentize(1)` or 
     code_stream = code_blocks.join("\n\n# DIVIDER\n\n")
 
-    code_html =
-      if `which pygmentize` == ""
-        highlight_webservice(code_stream)
-      elsif 
-        highlight_pygmentize(code_stream)
-      end
+    if (`which pygmentize` == "")
+      code_html = highlight_webservice(code_stream)
+    else 
+      code_html = highlight_pygmentize(code_stream)
+    end
 
     # Do some post-processing on the pygments output to split things back
     # into sections and remove partial `
` blocks.

From 2f54f4c4244166e9b6513da8e5a7807c434cbf51 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 14:08:12 -0500
Subject: [PATCH 05/10] send @options['language'] to pygments.appspot.com, not
 just 'ruby'.

---
 lib/rocco.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/rocco.rb b/lib/rocco.rb
index 3a76a2d..72a204e 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -209,7 +209,7 @@ class Rocco
   def highlight_webservice(code)
     Net::HTTP.post_form(
       URI.parse('http://pygments.appspot.com/'),
-      {'lang' => 'ruby', 'code' => code}
+      {'lang' => @options['language'], 'code' => code}
     ).body
   end
 end

From 55700ff584a1b123a3140b758f9e7afa2da37407 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 14:38:01 -0500
Subject: [PATCH 06/10] change a class in a regex to deal with the way pygments
 outputs C code.

---
 lib/rocco.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/rocco.rb b/lib/rocco.rb
index 72a204e..963bc41 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -175,7 +175,7 @@ class Rocco
     # Do some post-processing on the pygments output to split things back
     # into sections and remove partial `
` blocks.
     code_html = code_html.
-      split(/\n*# DIVIDER<\/span>\n*/m).
+      split(/\n*# DIVIDER<\/span>\n*/m).
       map { |code| code.sub(/\n?
/m, '') }.
       map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
 

From 8c948bbb95c2712ab56e84588c49ab7c3909c491 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 14:55:26 -0500
Subject: [PATCH 07/10] fixed -o option

---
 bin/rocco | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bin/rocco b/bin/rocco
index aaa526f..3f52f48 100755
--- a/bin/rocco
+++ b/bin/rocco
@@ -90,7 +90,7 @@ Dir.mkdir output_dir if !File.directory?(output_dir)
 # Run each file through Rocco and write output.
 sources.each do |filename|
   rocco = Rocco.new(filename, sources, options)
-  dest = filename.split('.')[0..-2].join('.') + '.html'
+  dest = "#{output_dir}/#{filename.scan(/(.*\/)?(.*)\.[^\.]+/)[0][1]}.html"
   puts "rocco: #{filename} -> #{dest}"
   File.open(dest, 'wb') { |fd| fd.write(rocco.to_html) }
 end

From 6595d5f885391c348c67e1f005c1bc253a4ea119 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 15:01:01 -0500
Subject: [PATCH 08/10] bin/rocco works for extensionless files now (again?)
 too. README -> README.html.

---
 bin/rocco | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bin/rocco b/bin/rocco
index 3f52f48..d2df0a6 100755
--- a/bin/rocco
+++ b/bin/rocco
@@ -90,7 +90,7 @@ Dir.mkdir output_dir if !File.directory?(output_dir)
 # Run each file through Rocco and write output.
 sources.each do |filename|
   rocco = Rocco.new(filename, sources, options)
-  dest = "#{output_dir}/#{filename.scan(/(.*\/)?(.*)\.[^\.]+/)[0][1]}.html"
+  dest = "#{output_dir}/#{filename.scan(/(.*\/)?(.*?)(\.[^\.]+)?$/)[0][1]}.html"
   puts "rocco: #{filename} -> #{dest}"
   File.open(dest, 'wb') { |fd| fd.write(rocco.to_html) }
 end

From 3dc4f87c1201c5068cbdb868a3646c928772d198 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 15:18:17 -0500
Subject: [PATCH 09/10] code DIVIDER is now language-agnostic.

---
 lib/rocco.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/rocco.rb b/lib/rocco.rb
index 963bc41..1b49f23 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -164,7 +164,7 @@ class Rocco
 
     # 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_stream = code_blocks.join("\n\n#{@options[:comment_chars]} DIVIDER\n\n")
 
     if (`which pygmentize` == "")
       code_html = highlight_webservice(code_stream)
@@ -175,7 +175,7 @@ class Rocco
     # Do some post-processing on the pygments output to split things back
     # into sections and remove partial `
` blocks.
     code_html = code_html.
-      split(/\n*# DIVIDER<\/span>\n*/m).
+      split(/\n*#{@options[:comment_chars]} DIVIDER<\/span>\n*/m).
       map { |code| code.sub(/\n?
/m, '') }.
       map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
 

From c1a4dd756a6c3edcd069efeef1228cba32680ad2 Mon Sep 17 00:00:00 2001
From: Burke Libbey 
Date: Tue, 30 Mar 2010 15:26:31 -0500
Subject: [PATCH 10/10] prefer .blank? to == ''

---
 lib/rocco.rb | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/rocco.rb b/lib/rocco.rb
index 1b49f23..f3d96d0 100644
--- a/lib/rocco.rb
+++ b/lib/rocco.rb
@@ -52,7 +52,7 @@ require 'net/http'
 
 # Code is run through [Pygments](http://pygments.org/) for syntax
 # highlighting. If it's not installed, locally, use a webservice.
-if `which pygmentize` == ""
+if `which pygmentize`.blank?
   warn "WARNING: Pygments not found. Using webservice."
 end
 
@@ -166,7 +166,7 @@ class Rocco
     # `pygmentize(1)` or 
     code_stream = code_blocks.join("\n\n#{@options[:comment_chars]} DIVIDER\n\n")
 
-    if (`which pygmentize` == "")
+    if `which pygmentize`.blank?
       code_html = highlight_webservice(code_stream)
     else 
       code_html = highlight_pygmentize(code_stream)