The syntax highlighting engine in Redmine is CodeRay which is vastly underpowered to be used in software as useful as Redmine. The obvious choice (at least for me) for proper syntax highlighting is Pygments, a python library. To change the syntax highlighting engine a few modifications need to be made to both Redmine and to Pygments.
The method that is called for syntax highlighting is in the app/helpers/repositories_helper.rb file.
def syntax_highlight(name, content) type = CodeRay::FileType[name] type ? CodeRay.scan(content, type).html : h(content) end
(Note: This is for version 0.7-stable as the location of this method has moved in the trunk of the repository to app/helpers/application_helper.rb)
I initially piped the contents to Pygments with the -g argument which tries to guess the language but the success rate was too low. While it can choose a lexer based on a filename it also attempts to read the code from the file which doesn’t physically exist on our filesystem. The only solution was to add the desired functionality to Pygments via a new command-line argument. The ticket along with patch can be viewed here. Hopefully the patch will be accepted and patching will no longer be necessary (see update at end of post). The new argument, -N, allows you to pass a filename to Pygments which will return the lexer which best represents the contents based solely on the filename.
After patching Pygments we need to call it in the syntax highlighting method instead of CodeRay.
def syntax_highlight(name, content) f = IO.popen("pygmentize -N " + name, 'r') lexer = f.read[0...-1] # removes trailing newline f = IO.popen("pygmentize -f html -l " + lexer, 'w+') f.write(content) f.close_write return f.read[28...-13]# removes surrounding div and pre as well as trailing newline end
As this was my first endeavor with Ruby I doubt it’s as elegant as it could be but it gets the job done. For this to work as-is it is assumed that pygmentize is in your PATH variable. Since Pygments uses its own CSS styles we must generate them, embed them in the stylesheet, and change an HTML tag so the new CSS rules are being applied. To generate the CSS use the following command:
[redmine-0.7]$ pygmentize -f html -S colorful -a .Pygments >> public/stylesheets/scm.css
This will append the new rules onto the already existing ones in the scm.css file. We still need to add an additional custom rule though so open scm.css in your favorite text editor and append the following:
.Pygments pre { margin: 0px; }
Now all that needs to be done is editing the templates to change the table class from “CodeRay” to “Pygments” so our new CSS rules are used. Open app/views/repositories/entry.rhtml and change line 4 and app/views/repositories/diff.rhtml and change line 18 and 48 to read:
<table class="filecontent Pygments">
Also open app/views/repositories/annotate.rhtml and change line 6 to read:
<table class="filecontent annotate Pygments">
You should now be able to enjoy the Pygments highlighting engine in your Redmine repositories!
Update:
My patch to Pygments has been accepted and checked into the repository. The changeset can be viewed here. The 1.0 version, the first to include this feature, is slated to be released on December 1st, 2008.