ソースコードを見やすく表示する(CodeRay)
すでにいくつかのプログラムサンプルを掲載していますが、これらは全て CodeRay ライブラリを用いて整形されています。
CodeRay ライブラリは、プログラムの構文を解析し、キーワードや文字列、コメント等をわかりやすく表示できる HTMLに変換してくれます。例えば、
require 'rubygems' require 'coderay' # CodeRay を利用したサンプルプログラム text = '@blogs = Blog.find(:all, :conditions => [ "category_id = ?" ], :order => "created_at desc")' print CodeRay.highlight(text, :ruby, :css => :class, :wrap => :div)
というプログラムソースを整形すると、
<div class="CodeRay"> <div class="code"> <pre> require <span class="s"><span class="dl">'</span><span class="k">rubygems</span><span class="dl">'</span></span> require <span class="s"><span class="dl">'</span><span class="k">coderay</span><span class="dl">'</span></span> <span class="c"># CodeRay を利用したサンプルプログラム</span> text = <span class="s"><span class="dl">'</span><span class="k">@blogs = Blog.find(:all, :conditions => [ "category_id = ?" ], :order => "created_at desc")</span><span class="dl">'</span></span> print <span class="co">CodeRay</span>.highlight(text, <span class="sy">:ruby</span>, <span class="sy">:css</span> => <span class="sy">:class</span>, <span class="sy">:wrap</span> => <span class="sy">:div</span>) </pre></div> </div> </div>
のような HTMLに変換されます(見やすくする為に改行をしています)。
Ruby on Rails で利用する為の準備
まずは、CodeRay をインストールします。コマンドラインで以下のコマンドを実行します。
# gem install coderay
あと、 config/environment.rb に以下の記述もしておきます。
config.gem "coderay"
Ruby on Rails で使う
例えば、以下のようなヘルパーを app/helpers/application_helper.rb に定義します。
引数は、プログラムコード( code )とパラメータです。パラメータは、 :lang 以外は CodeRay の highlight() のものと同じです(そのまま渡しています)。
def syntax_highlight(code, params = { }) lang = params.delete(:lang) || :ruby params[:css] ||= :style params[:wrap] ||= :div CodeRay.highlight(code, lang, params) end
で、テンプレートからは以下のように呼び出します。 @entry には、プログラムコード( source_code )、そのコードの開始行番号( line_number_start )が入っているものとします。また、スタイルシートは別途準備する必要があります。
<h2><%= @entry.title %></h2> <div class="source-code"> <%= syntax_highlight @entry.source_code, :lang => :ruby, :css => :class, :line_numbers => :inline, :line_number_start => @entry.line_number_start %> </div>
まあ、あまり実用的なサンプルではありませんね。一つのエントリに一個ソースコードの破片を書いて、それを議論するようなサイトなら使えるのかな。
ブログエントリ中のソースコードを整形
僕がやりたいと思うのは、ブログのエントリの中にあるソースコードを整形してもらうようなものなので、実際に当サイトでやっているのは以下のようなコードです。例のフォーマットを指定して、HTML文書に変換するヘルパーに組み込んでいます。エントリ中の <coderay> タグの中身を CodeRay で整形させます。
def text_to_html(text, params = { }) params[:format] = :textile unless params[:format] text.gsub!(/<coderay\s+lang="([^"\s]+)">((?:(?!<\/coderay>).)*)<\/coderay>/m) do lang = $1.to_sym highlight = syntax_highlight($2.gsub(/>/, '>').gsub(/</, '<'), :lang => lang) if params[:format] == :textile "<notextile>" + highlight + "</notextile>" else highlight end end if params[:format] != :text if params[:format] == :html text elsif params[:format] == :text # 改行を HTMLタグに。URL等はリンクに auto_link(simple_format(text), :all) elsif params[:format] == :markdown markdown(text) else textilize(text) end end
params[:format] が :text の時の処理が出来ていないので、その場合は処理しないようになっています。あと、正規表現の部分があやしいです。本来なら textile の処理は CodeRay::ForRedCloth でなんとかするのではないかと思っているのですが、使い方がよく分からなかったので下手な小細工をやっています。
いつか、もうちょっとまともな処理にしたいと思っていますが。
さて、使い方ですが、テンプレートはそのままです。たとえば、show.html.erb ファイルなんかに以下のコードを書きます。 Entry モデルの body フィールドにブログ記事の本文が格納されているものとします。
<div class="entry"> <h1><%=h @entry.title %></h1> <div class="body"> <%= text_to_html @entry.body, @entry.format_sym %> </div> </div>
あとは ブログ記事の中で、ソースコードを <coderay lang="ruby"> とか、 <coderay lang="rhtml"> で囲めばうまく表示されるはずです。
