特定パターンのファイル名のみアイコンや色を変える【file-icons >= 2.0.0】

file-iconsパッケージが[2.0.0](https://github.com/file-icons/atom/releases/tag/v2.0.0)でだいぶリファクタされたので、以前の記事、

- [【Atom Editor, file-icons】特定パターンのファイル名のみアイコンと色を変える](http://qiita.com/ymtszw/items/33747cb298db9d0f3d40)

をアップデート。
file-iconsのReadmeにも少し[移行ガイド](https://github.com/file-icons/atom#troubleshooting)が載っているが、ここで補足する。

# ファイル名に基づいてアイコンを変更

前提として、Atomはどこかのバージョンで、[カスタムファイル拡張子に対応した](http://flight-manual.atom.io/using-atom/sections/basic-customization/#customizing-language-recognition)模様。
以前は[file-types](https://atom.io/packages/file-types)というパッケージが必要だった。

file-iconsも、このビルトイン設定に連動してファイルアイコンを変更してくれる。
例えば、

```coffeescript:.atom/config.cson
"*":
  core:
    customFileTypes:
      "source.jade": [
        "dt"
      ]
      "source.ruby": [
        "god"
      ]
```

以上のようにconfig.csonファイルで設定すると、".dt"ファイル[^dt]はJadeファイル[^jade]として、".god"ファイル[^god]はRubyファイルとして扱われ、言語パッケージのシンタックスハイライトなどの恩恵を受けられるようになるとともに、アイコンも連動して変わる。

[^dt]: [vibe.d](http://vibed.org/)で使われている[Diet](http://vibed.org/docs#html-templates)というJadeコンパチのテンプレートファイル。
[^jade]: Jadeテンプレートエンジンは最近v2になって、[Pug](https://github.com/pugjs/pug)という名前に変わったらしい。商標問題に当たった模様。
[^god]: [God](http://godrb.com/)はRuby製のプロセスモニター。設定ファイルをRubyで書ける。

つまり**アイコン変更のためだけに別個の設定をする必要はなくなった**。

# ファイル名に基づいてアイコンの色を変更

今まではこんな感じで書いていた。

```css:.atom/styles.less
@import "packages/file-icons/styles/colors";
@import "packages/file-icons/styles/icons";
@import "packages/file-icons/styles/items";
@{pane-tab-override}, .icon-file-text {
  &[data-name$="_test.exs"]:before { .elixir-icon; .medium-green; }
}
```

2つの変更点がある。

- `@pane-tab-...`系の変数は廃止された。
- Mixinに使っていたclass(`.<lang>-icon`や`.(dark|light|medium)-<color>`)はmixinとしては使えなくなった。
    - アイコン系クラスについては直接アイコン表示等に使われるクラスとなり、mixinできなくなった。
        - `file-icons/styles/icons.less`を見ると`:before`擬似要素つきでしか定義されていない。
        - [Issue](https://github.com/less/less.js/issues/1630)を見る限り、Lessでは疑似要素を`:extend`することはできるがmixinすることはできない模様。
    - 色系クラスはそもそも廃止され、代わりに`@(dark|light|medium)-<color>`系変数として定義された。

上記を踏まえて、v2では以下のように書く。

```css:.atom/styles.less
@import "packages/file-icons/styles/colours";
.elixir-icon {
  &[data-name$="_test.exs"]:before { color: @medium-green; }
}
```

色変数のために`@import`するファイル名が`colours`とBritish spellingになったことも注意。

**ファイルアイコンが表示される要素には`.<lang>-icon`クラスが必ず付くようになった**ので、[CSSのAttribute selectors](https://developer.mozilla.org/ja/docs/Web/CSS/Attribute_selectors)を使って条件を指定しつつ、その`:before`要素に対して変更を書けば良い。
アイコンそのものは実体としてはフォントなので、色の変更は単に`color`プロパティを使う。

# ファイルパスに基づいてアイコンの色を変更

前の記事には書かなかったが、実は前項の応用で、**ファイルパスに基づいた変更**というのもできる。
Atomでは大概のファイルアイコンが表示される要素には`data-path`というattributeもついているので、こちらを見れば良い。

ただ注意点として、`data-path`には絶対パスと相対パス、どちらが入っているケースもありうる。
例えば、`Cmd+p`で現れるFuzzy Finderのmodalなんかは（プロジェクトrootからの）相対パスになっている一方、Tree Viewでは絶対パスが入っている。
達成したい変更内容によっては両方のパターンに対応したスタイルを書く必要がある。

もう一点、プロジェクト内検索(`Shift+Cmd+F`)の結果ビューでは、アイコンが表示される要素と`data-path`が存在する要素が異なる。
具体的には、`data-path`は検索結果全体としてのリストの`<li>`にそれぞれ付与されているが、アイコンクラスは更にその子にあたる`<span>`に付与されている。
これも特別扱いで対処しなければならない。

結論、v2では以下のように書くことになる。

```css:.atom/styles.less
@import "packages/file-icons/styles/colours";
.elixir-icon {
  &[data-path*="/project/hoge/"], &[data-path^="hoge/"] {
    &:before { color: @dark-cyan; }
  }
}

// For search result views
[data-path*="/project/hoge/"] {
  .elixir-icon:before { color: @dark-cyan; }
}
```

やっていることは、Elixirのファイルで、かつプロジェクトroot階層の`hoge`というディレクトリ内にあるものだけ特別扱いで色を変える、というもの。
ディレクトリ構造が比較的自由な言語・フレームワークで、**一つのレポジトリ内に異なるスコープのファイル群を共存させる場合に識別しやすくなる**。

記述内容としては前項でやったファイル名（の末尾）の場合と同様、Attribute selectorsでエディタ内のHTML構造に合わせた個別指定をしているだけ。
絶対パスの場合は中間一致にしつつ、プロジェクトディレクトリ名自体も含めている一方、相対パスの場合は前方一致で対象ディレクトリから指定している。
Windowsではディレクトリのデリミタを変更する必要があるかも（未確認）。

# 備考

今後のバージョンアップ（Atom本体あるいはfile-icons）でも、Less/CSSの構造が変わったり、HTMLの構造自体が変わったりした場合は、カスタム設定も合わせて変更する必要がある。
とはいえ、基本的には**`Alt-Cmd-i`でDevConsoleを開いてHTMLの構造を確認しつつ、file-iconsが提供するアセットを使う**、というワークフローで修正できる。