Enable code highlighting with Pygments/Jekyll

If you have been using Jekyll, you must be aware of code highlighting feature using highlight blocks. This highlighting is accomplished by a neat python script called Pygments

Pygments is a very powerful code syntax highlighter. It allows you to pass various options such as weather to display line no.s or which lines to be highlighted. When Jekyll was released, there was no way to use these options since Jekyll encapsulated the execution of Python internally through Albino gem

There has been some progress over this, a pull request was submitted in Jekyll which allowed various options to be passed to Pygments.

However, when I tried to use hl_lines option to highlight the lines of code, I faced several issues. Following is the syntax I used

 highlight html hl_lines=2 4

Running the above piece of code reults in only line 2 being highlighted and not both. So I decided to enclose it with quotation marks

 highlight html hl_lines="2 4"  

The above piece of code gives the error.

Invalid flag value -O

Certainly, there are some things which needs to be fixed. First of all in albino, the validation function has a bug. The value regular express should be allowed quotation marks character so that hl_lines list can be provided enclosed in quotation marks. This is the first problem in albino.rb file.

  def validate_shell_args(flag, value)
    if flag !~ /^[a-z]+$/i
      raise ShellArgumentError, "Flag is invalid: #{flag.inspect}"
    if value !~ /^[a-z0-9\-\_\+\=\#\,\s]+$/i
      raise ShellArgumentError, "Flag value is invalid: -#{flag} #{value.inspect}"

The second problem is that we can seperate the hl_lines list with spaces since Jekyll uses the space as a delimeter to parse these options. To solve this problem, I pass in the list seperated by commas and then modified the highlight.rb file in Jekyll to recombine them into the list. See the updated function below:

 def initialize(tag_name, markup, tokens)
      if markup =~ SYNTAX	
        @lang = $1
        if defined? $2
		# puts $2
          tmp_options = {}
          $2.split.each do |opt|		    
            key, value = opt.split('=')						
			if key == 'hl_lines'
				puts value
				value = value.gsub(","," ")
            if value.nil?
              if key == 'linenos'			
                value = 'inline'
                value = true
            tmp_options[key] = value
          tmp_options = tmp_options.to_a.collect { |opt| opt.join('=') }
          # additional options to pass to Albino
          @options = { 'O' => tmp_options.join(',') }		  		  		  
          @options = {}
        raise SyntaxError.new("Syntax Error in 'highlight' - Valid syntax: highlight <lang> [linenos]")

I cannot submit it as patch in Jekyll since this fix involves fixing two components: Jekyll and Albino. May be someone can come with better approach to fix this. This works for me as of now.