Index: app/helpers/application_helper.rb =================================================================== --- app/helpers/application_helper.rb (revision 2614) +++ app/helpers/application_helper.rb (working copy) @@ -20,6 +20,32 @@ require 'forwardable' require 'cgi' +# This is needed for Pygments Integration +require 'tempfile' + +# Ruby pre 1.9 does not provide the full functionality needed +# Tempfiles need to have a fixed suffix to be correctly recognized +# by pygments. +# See ApplicationHelper.syntax_hightlight() +ruby_version = RUBY_VERSION.split('.') +if Integer(ruby_version[0]) <= 1 and Integer(ruby_version[1]) <= 8 + class Tempfile + # This is the imlementation comming from Ruby 1.9.0.0 + def make_tmpname(basename, n) + case basename + when Array + prefix, suffix = *basename + else + prefix, suffix = basename, '' + end + + t = Time.now.strftime("%Y%m%d") + path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}" + end + private :make_tmpname + end +end + module ApplicationHelper include Redmine::WikiFormatting::Macros::Definitions include GravatarHelper::PublicMethods @@ -189,8 +215,21 @@ end def syntax_highlight(name, content) - type = CodeRay::FileType[name] - type ? CodeRay.scan(content, type).html : h(content) + tmp_file = Tempfile.new(['redmine_pygments', File.extname(name)]) + tmp_file_path = tmp_file.path() + + tmp_file.write(content) + tmp_file.flush() + code = IO.popen("pygmentize -f html -O encoding=utf8 '#{tmp_file_path}' 2>&1").read() + if code.empty? + code = IO.popen("pygmentize -l text -f html -O encoding=utf8 '#{tmp_file_path}' 2>&1").read() + end + tmp_file.close!() + if code.empty? + h(content) + else + "%s" % code[28...-13] + end end def to_path_param(path) Index: public/stylesheets/scm.css =================================================================== --- public/stylesheets/scm.css (revision 2614) +++ public/stylesheets/scm.css (working copy) @@ -182,3 +182,64 @@ .CodeRay .ty { color:#339; font-weight:bold } .CodeRay .v { color:#036 } .CodeRay .xt { color:#444 } + +# Pygments Rules +.c { color: #808080 } /* Comment */ +.err { color: #F00000; background-color: #F0A0A0 } /* Error */ +.k { color: #008000; font-weight: bold } /* Keyword */ +.o { color: #303030 } /* Operator */ +.cm { color: #808080 } /* Comment.Multiline */ +.cp { color: #507090 } /* Comment.Preproc */ +.c1 { color: #808080 } /* Comment.Single */ +.cs { color: #cc0000; font-weight: bold } /* Comment.Special */ +.gd { color: #A00000 } /* Generic.Deleted */ +.ge { font-style: italic } /* Generic.Emph */ +.gr { color: #FF0000 } /* Generic.Error */ +.gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.gi { color: #00A000 } /* Generic.Inserted */ +.go { color: #808080 } /* Generic.Output */ +.gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.gs { font-weight: bold } /* Generic.Strong */ +.gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.gt { color: #0040D0 } /* Generic.Traceback */ +.kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */ +.kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.kt { color: #303090; font-weight: bold } /* Keyword.Type */ +.m { color: #6000E0; font-weight: bold } /* Literal.Number */ +.s { background-color: #fff0f0 } /* Literal.String */ +.na { color: #0000C0 } /* Name.Attribute */ +.nb { color: #007020 } /* Name.Builtin */ +.nc { color: #B00060; font-weight: bold } /* Name.Class */ +.no { color: #003060; font-weight: bold } /* Name.Constant */ +.nd { color: #505050; font-weight: bold } /* Name.Decorator */ +.ni { color: #800000; font-weight: bold } /* Name.Entity */ +.ne { color: #F00000; font-weight: bold } /* Name.Exception */ +.nf { color: #0060B0; font-weight: bold } /* Name.Function */ +.nl { color: #907000; font-weight: bold } /* Name.Label */ +.nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.nt { color: #007000 } /* Name.Tag */ +.nv { color: #906030 } /* Name.Variable */ +.ow { color: #000000; font-weight: bold } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */ +.mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */ +.mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */ +.mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */ +.sb { background-color: #fff0f0 } /* Literal.String.Backtick */ +.sc { color: #0040D0 } /* Literal.String.Char */ +.sd { color: #D04020 } /* Literal.String.Doc */ +.s2 { background-color: #fff0f0 } /* Literal.String.Double */ +.se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ +.sh { background-color: #fff0f0 } /* Literal.String.Heredoc */ +.si { background-color: #e0e0e0 } /* Literal.String.Interpol */ +.sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */ +.sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ +.s1 { background-color: #fff0f0 } /* Literal.String.Single */ +.ss { color: #A06000 } /* Literal.String.Symbol */ +.bp { color: #007020 } /* Name.Builtin.Pseudo */ +.vc { color: #306090 } /* Name.Variable.Class */ +.vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */ +.vi { color: #3030B0 } /* Name.Variable.Instance */ +.il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */