trac のレポジトリブラウザで Delphi のコードを syntax highlighting
trac のレポジトリブラウザでソースコードに色付けをするには,下記の2つのコンポーネントのうちいずれかをインストールする必要があります。
ただ,後者は別プロセスを立ち上げるので重そう。前者を使うことにします。
SilverCity は rpmforge 等でも rpm はなさそうなので,自らセットアップします。このへんの手順は lapis25 さんのtracでソースコードの色つけと権限設定 - LAPISLAZULI HILL#diaryが詳しいです。ので省略。
で,Delphi (Pascal) についてですが,SilverCity がバックエンドで利用している Scintilla のコード上ではサポートされているのですが,残念ながら SilverCity のレベルでサポートされていません。SilverCityAddLanguage – The Trac Project の手順に沿って Pascal 用のコードを自分で書く必要があります*1。
上記ドキュメントによると SilverCity を展開したツリーの下に最新版の Scintilla のコードを展開せよ,とのことになっていますが,なぜかうまくコンパイルできませんでした。幸い SilverCity 同梱の Scintilla コードに Pascal のレキシカルアナライザが含まれているので最新版は使いませんでした。
ということで,上記ドキュメントと手順が異なるので要所要所を書いておくと,
- SilverCity を展開
python setup.py build
で一度ビルドしておく- 同梱の Scintilla ライブラリを使うので ScintillaConstants.py の再生成は必要ない
- PySilverCity/SilverCity/Pascal.py というファイルを YAML.py あたりをベースにでっちあげる
SCLEX_YAML
はSCLEX_PASCAL
に置き換えればいいんだけど,Pascal のアナライザはレキシカルステートとして C のものを利用しているのでSCE_YAML
という文字列リテラルはすべてSCE_C
に置き換え- Keywords.py に
pascal_keywords
とpascal_classwords
を追加する(後述) - LanguageInfo.py の
do_registration
にimport Pascal
を追加 - css まわりはなぜかスクリプトがみつからなかったので放置。先ほど上げたように,Pascal の場合 C と同じ css class を利用するので変更する必要はない
- setup.py の
py_modules
に"SilverCity.Pascal"
を追加 - 再度
python setup.py build
を行う sudo python setup.py install
でインストール
と,これで Pascal 対応の SilverCity がインストールされました。Perl, HTML 等デフォルトで対応しているコードについては自動的に色がつきますが,Pascal については trac.ini を書き換える必要があります。
重要な部分だけ抽出すると,こんな感じ。
[mimeviewer] mime_map = text/x-pascal:pas silvercity_modes = text/x-pascal:Pascal:5
mime_map で拡張子と対応する mime-type を関連付けます。silvercity_modes に記述しておくと,指定された mime-type のものについてはたとえ Enscript がインストールされていたとしても SilverCity で色付けしてくれます。「mime-type:SilverCityの対応モジュール:品質優先度」の順になります。品質優先度,のところは私もよくわからないので適当に 5 とかしてます。
はてさて,これでようやく無事 Delphi のコードに色がつく……はずなのです。ですが私の場合,各ファイルの svn:mime-type
を「text/plain; charset=Shift_JIS
」としていたため*2,Pascal ファイルとして認識してくれませんでした。なので,「text/x-pascal; charset=Shift_JIS
」のようにする必要があります。つまり上記の mime_map
で設定した mime-type を指定する必要があります。
以下,私のでっちあげた Pascal.py とか。
import HTMLGenerator import Keywords import Lexer from DispatchHandler import DispatchHandler from _SilverCity import find_lexer_module_by_id, PropertySet, WordList from ScintillaConstants import SCLEX_PASCAL import LanguageInfo class PascalLexer(Lexer.Lexer): def __init__(self, properties = PropertySet()): self._properties = properties self._lexer = find_lexer_module_by_id(SCLEX_PASCAL) self._keyword_lists = [ WordList(Keywords.pascal_keywords), WordList(Keywords.pascal_classwords), ] class PascalHandler(DispatchHandler): def __init__(self): DispatchHandler.__init__(self, 'SCE_C') class PascalHTMLGenerator(HTMLGenerator.SimpleHTMLGenerator, PascalHandler): name = 'pascal' description = 'Pascal' def __init__(self): PascalHandler.__init__(self) HTMLGenerator.SimpleHTMLGenerator.__init__(self, 'SCE_C') def generate_html(self, file, buffer, lexer = PascalLexer()): self._file = file lexer.tokenize_by_style(buffer, self.event_handler) pascal_language_info = LanguageInfo.LanguageInfo( 'Pascal', ['pas', 'dpr'], ['.*?pascal.*?'], [PascalHTMLGenerator] ) LanguageInfo.register_language(pascal_language_info)
んで,Keywords に追加する pascal_keywords と pascal_classwords は以下の通り(といってもウェブで拾ったものですが)。
pascal_keywords = \ "and array asm begin case cdecl class const constructor " \ "default destructor div do downto else end end. except exit " \ "exports external far file finalization finally for function " \ "goto if implementation in index inherited initialization " \ "inline interface label library message mod near nil not " \ "object of on or out overload override packed pascal private " \ "procedure program property protected public published raise " \ "read record register repeat resourcestring safecall set shl " \ "shr stdcall stored string then threadvar to try type unit " \ "until uses var virtual while with write xor" pascal_classwords = \ "array boolean char integer file pointer real set string " \ "text variant write read default public protected private " \ "property published stored"