From f00272ea527f73bcc868b6de92d00d0e43fb86ef Mon Sep 17 00:00:00 2001 From: Tom Preston-Werner Date: Fri, 12 Dec 2008 19:58:40 -0800 Subject: [PATCH] use pygments for code highlighting if --pygments is specified --- History.txt | 2 + bin/jekyll | 4 ++ lib/jekyll.rb | 7 +++ lib/jekyll/albino.rb | 116 +++++++++++++++++++++++++++++++++++++++++++ lib/jekyll/blocks.rb | 21 ++++++-- 5 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 lib/jekyll/albino.rb diff --git a/History.txt b/History.txt index 7c4617ee..4fabb794 100644 --- a/History.txt +++ b/History.txt @@ -1,4 +1,6 @@ == + * Major Features + * Code highlighting with Pygments if --pygments is specified * Minor Enhancements * Output informative message if RDiscount is not available [github.com/JackDanger] * Bug Fixes diff --git a/bin/jekyll b/bin/jekyll index 1cfc4749..3bd7c6ee 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -24,6 +24,10 @@ opts = OptionParser.new do |opts| opts.on("--auto", "Auto-regenerate") do options[:auto] = true end + + opts.on("--pygments", "Use pygments to highlight code") do + Jekyll.pygments = true + end end opts.parse! diff --git a/lib/jekyll.rb b/lib/jekyll.rb index e1b62bdb..4712862d 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -28,10 +28,17 @@ require 'jekyll/page' require 'jekyll/post' require 'jekyll/filters' require 'jekyll/blocks' +require 'jekyll/albino' module Jekyll VERSION = '0.1.4' + class << self + attr_accessor :pygments + end + + Jekyll.pygments = false + def self.process(source, dest) Jekyll::Site.new(source, dest).process end diff --git a/lib/jekyll/albino.rb b/lib/jekyll/albino.rb new file mode 100644 index 00000000..5e1e6ef8 --- /dev/null +++ b/lib/jekyll/albino.rb @@ -0,0 +1,116 @@ +## +# Wrapper for the Pygments command line tool, pygmentize. +# +# Pygments: http://pygments.org/ +# +# Assumes pygmentize is in the path. If not, set its location +# with Albino.bin = '/path/to/pygmentize' +# +# Use like so: +# +# @syntaxer = Albino.new('/some/file.rb', :ruby) +# puts @syntaxer.colorize +# +# This'll print out an HTMLized, Ruby-highlighted version +# of '/some/file.rb'. +# +# To use another formatter, pass it as the third argument: +# +# @syntaxer = Albino.new('/some/file.rb', :ruby, :bbcode) +# puts @syntaxer.colorize +# +# You can also use the #colorize class method: +# +# puts Albino.colorize('/some/file.rb', :ruby) +# +# Another also: you get a #to_s, for somewhat nicer use in Rails views. +# +# ... helper file ... +# def highlight(text) +# Albino.new(text, :ruby) +# end +# +# ... view file ... +# <%= highlight text %> +# +# The default lexer is 'text'. You need to specify a lexer yourself; +# because we are using STDIN there is no auto-detect. +# +# To see all lexers and formatters available, run `pygmentize -L`. +# +# Chris Wanstrath // chris@ozmm.org +# GitHub // http://github.com +# +require 'open4' + +class Albino + @@bin = Rails.development? ? 'pygmentize' : '/usr/bin/pygmentize' rescue 'pygmentize' + + def self.bin=(path) + @@bin = path + end + + def self.colorize(*args) + new(*args).colorize + end + + def initialize(target, lexer = :text, format = :html) + @target = File.exists?(target) ? File.read(target) : target rescue target + @options = { :l => lexer, :f => format } + end + + def execute(command) + pid, stdin, stdout, stderr = Open4.popen4(command) + stdin.puts @target + stdin.close + stdout.read.strip + end + + def colorize(options = {}) + execute @@bin + convert_options(options) + end + alias_method :to_s, :colorize + + def convert_options(options = {}) + @options.merge(options).inject('') do |string, (flag, value)| + string + " -#{flag} #{value}" + end + end +end + +if $0 == __FILE__ + require 'rubygems' + require 'test/spec' + require 'mocha' + begin require 'redgreen'; rescue LoadError; end + + context "Albino" do + setup do + @syntaxer = Albino.new(__FILE__, :ruby) + end + + specify "defaults to text" do + syntaxer = Albino.new(__FILE__) + syntaxer.expects(:execute).with('pygmentize -f html -l text').returns(true) + syntaxer.colorize + end + + specify "accepts options" do + @syntaxer.expects(:execute).with('pygmentize -f html -l ruby').returns(true) + @syntaxer.colorize + end + + specify "works with strings" do + syntaxer = Albino.new('class New; end', :ruby) + assert_match %r(highlight), syntaxer.colorize + end + + specify "aliases to_s" do + assert_equal @syntaxer.colorize, @syntaxer.to_s + end + + specify "class method colorize" do + assert_equal @syntaxer.colorize, Albino.colorize(__FILE__, :ruby) + end + end +end \ No newline at end of file diff --git a/lib/jekyll/blocks.rb b/lib/jekyll/blocks.rb index 6e1549a2..9cbc9e17 100644 --- a/lib/jekyll/blocks.rb +++ b/lib/jekyll/blocks.rb @@ -1,4 +1,5 @@ module Jekyll + class Highlight < Liquid::Block include Liquid::StandardFilters @@ -8,15 +9,29 @@ module Jekyll end def render(context) - #The div is required because RDiscount blows ass + if Jekyll.pygments + render_pygments(context, super.to_s) + else + render_codehighlighter(context, super.to_s) + end + end + + def render_pygments(context, code) + "" + Albino.new(code, @lang).to_s + "" + end + + def render_codehighlighter(context, code) + #The div is required because RDiscount blows ass <<-HTML
-    #{h(super.to_s).strip}
+    #{h(code).strip}
   
HTML - end + end end + end + Liquid::Template.register_tag('highlight', Jekyll::Highlight) \ No newline at end of file