GNU Source-highlightのカラースキーマをCSSで記述する

少し前のエントリだけど、lessの色付けする方法がちょっと話題になった。

デフォルトの色がひどいということで @nippondanji 氏が作ったカラースキーマファイルなんかも公開されているが、個人的にもう少し色々弄りたいなと思いドキュメントを読んでいたところ、CSSで書くこともできるとのこと。
というわけで、CSSでカラースキーマを書いてみた。

書き方

HTMLでいうところのタグとしては body だけがあり、これは source-highlight 全体を表している。
他のやつ(例えばkeywordとかfunctionとか)はクラスとして指定する。

例えばこんな感じ(僕の作りかけ)。複数行にまたがるコメントは /* */ のくせにできないので注意。

body {
  background-color: white;
}

/* the color for context lines (when specified with line ranges) */
.context {
  color: gray;
}

.keyword {
  color: darkgreen;
}
.type {
  color: darkgreen;
}
.usertype, .classname {
  color: teal;
}
.string {
  color: cyan;
}
.regexp {
  color: orange;
}
.specialchar {
  color: pink;
}
.comment {
  color: cyan;
}
.number {
  color: cyan;
}
.preproc {
  color: red;
}
.symbol {
  color: red;
}
.function {
  color: blue;
}
.cbracket {
  color: blue;
}
.todo {
  color: pink;
}

/* line numbers */
.linenum {
  color: black; font-family: monospace;
}

/* Internet related */
.url {
  color: blue;
  text-decoration: underline;
}

/* other elements for ChangeLog and Log files */
.date {
  color: blue;
}
.time, .file {
  color: darkblue;
}
.ip, .name {
  color: darkgreen;
}

/* for Prolog, Perl */
.variable {
  color: darkgreen;
}
.italics {
  color: darkgreen;
  font-style: italic;
}
.bold {
  color: darkgreen;
  font-weight: bold;
}

/* for LaTeX */
.underline {
  color: darkgreen;
  text-decoration: underline;
}
.fixed {
  color: green;
  font-family: monospace;
}
.argument, .optionalargument {
  color: darkgreen;
}
.math {
  color: orange;
}
.bibtex {
  color: blue;
}

/* for diffs */
.oldfile { color: orange; }
.newfile { color: darkgreen; }
.difflines { color: blue; }

/* for css */
.selector { color: blue; }
.property { color: yellow; }
.value { }

/* for Oz */
.atom { color: orange; }
.meta { font-style: italic; }

body タグに設定できるのは background-color のみ。
セレクタ(つまり.で始まるやつ)は上に列挙されているので全種類。
個々のフィールドとしては以下が使えるらしいが、僕の環境(Lion+iterm2)ではcolor以外動いていない気配がする。

.selector {
   color: <color specification>;
   background-color: <color specification>;
   font-weight: bold; /* this is a comment */
   font-family: monospace;
   font-style: italic;
   text-decoration: underline;
}

colorに指定できるのは以下

black red darkred brown yellow cyan blue pink purple orange brightorange green brightgreen darkgreen teal gray darkblue white

実際に対応する色は

f:id:yuku_t:20120208182751p:image

ただし、bodyのbackground-colorと同じcolorを使う場合は、単純に省略しなければならないようなので、注意が必要。
また、ドキュメントにはcolorを16進数で入力することで、任意の色を使えると書いてあるけど、僕の環境では正常に動作していない。

テキストのどの部分がどのセレクタに対応するか調べる

source-highlightのインストールされているディレクトリの中の share/source-highlight ディレクトリの中に .lang というファイルがあるからそれを見てみるとだいたい分かる。

例えば python.lang はこんな感じ

preproc = "import|from"

include "script_comment.lang"

include "number.lang"

keyword = "and|assert|break|class|continue|def|del|elif|else|except|exec",
           "finally|for|global|if|in|is|lambda|not|or|pass",
           "print|raise|return|try|while"

comment delim '^([[:space:]]*\'{3})' '(\'{3})' multiline 
comment delim '^([[:space:]]*\"{3})' '(\"{3})' multiline 

comment = '^([[:space:]]*\'(?:[^\\\']|\\.)*\'[[:space:]]*|[[:space:]]*\"(?:[^\\\"]|\\.)*\"[[:space:]]*)$'

string delim '([[:space:]]*\'{3})' '(\'{3})' multiline 
string delim '([[:space:]]*\"{3})' '(\"{3})' multiline 

string delim "\"" "\"" escape "\\" 
string delim "'" "'"  escape "\\" 

include "symbols.lang"
symbol = "{|}"

include "function.lang"

つまり、import の色をcyanに変えたければ

.preproc {
  color: cyan;
}

と記述すればいい。

環境構築

source-highlight自体のインストール方法は一番最初にあるリンク先を調べて欲しい。

インストール後ホームディレクトリに.source-highlightというディレクトリを作り、そこに必要なものを置くことにした。CSSファイルはmy.css

$ mkdir ~/.source-hightlight
$ cp `which src-hilight-lesspipe.sh` .source-hightlight.sh
$ touch .source-hightlight/my.css

.zshrcに以下を追記

if [ -f `which source-highlight` ]
then
    export LESS='-R'
    export LESSOPEN="| $HOME/.source-highlight/src-hilite-lesspipe.sh %s"
fi

そして、コピーしたsrc-hilite-lesspipe.shを以下のように変更

6c6
<         source-highlight --failsafe -f esc --lang-def=changelog.lang --style-file=esc.style -i "$source" ;;
---
>         source-highlight --failsafe -f esc --lang-def=changelog.lang --style-css-file=$HOME/.source-highlight/my.css -i "$source" ;;
8,9c8,9
<         source-highlight --failsafe -f esc --lang-def=makefile.lang --style-file=esc.style -i "$source" ;;
<         *) source-highlight --failsafe --infer-lang -f esc --style-file=esc.style -i "$source" ;;
---
>         source-highlight --failsafe -f esc --lang-def=makefile.lang --style-css-file=$HOME/.source-highlight/my.css -i "$source" ;;
>         *) source-highlight --failsafe --infer-lang -f esc --style-css-file=$HOME/.source-highlight/my.css -i "$source" ;;

簡単な話が、--style-fileオプションを--style-css-fileに変更して、my.cssを指定するようにしただけ。

これで、my.cssを読み込んでlessを色付けすることができるようになった。