LightTableのプラグイン形式によるスキン作成

[これ](http://qiita.com/kurogelee/items/43297e27dc3262001662)の話です。テーマの作成については[以前のもの](http://qiita.com/kurogelee/items/bc686c39c410755f7702)を参照。

LightTableのスタイル定義には主にエディタ部分のスタイルを定義する「テーマ」と、全体のスタイルを定義する「スキン」があります。

プラグイン形式でスキンを作成するには、まずプラグインの雛形を`lein new lt-plugin プラグイン名`で作成した後、*.behaviorsファイルで`(:lt.objs.style/provide-skin スキン名 CSSファイル名)`でスキンがあることを宣言します。

```theme_rabbit_house.behaviors
{:+ {:app [(:lt.objs.style/provide-theme "rabbit-house-light" "theme.css")
           (:lt.objs.style/provide-skin "rabbit-house-light-1" "skins/light-1.css")
           (:lt.objs.style/provide-skin "rabbit-house-light-2" "skins/light-2.css")
           (:lt.objs.style/provide-skin "rabbit-house-light-3" "skins/light-3.css")
           (:lt.objs.style/provide-skin "rabbit-house-light-4" "skins/light-4.css")
           (:lt.objs.style/provide-skin "rabbit-house-light-5" "skins/light-5.css")
           (:lt.objs.plugins/load-js "theme_rabbit_house_compiled.js")
           (:lt.objs.plugins/load-keymap "plugin.keymap")]}}
```

※最後の2行はとりあえず無視してください

スキンのCSSファイルはLightTableのcore/css/skins/にあるものを参考にするとよいでしょう。その際、CSSのクラス名をスキン名に修正することと画像ファイルのパスを修正することに注意が必要です。

```css:core/css/skins/new-dark.css
:root .skin-dark, :root .skin-light {
  var-bg: #3b3f41;
  var-fg: #ccc;
...
```

```css:skins/light-base.css
:root .skin-rabbit-house-light-1,
:root .skin-rabbit-house-light-2,
:root .skin-rabbit-house-light-3,
:root .skin-rabbit-house-light-4,
:root .skin-rabbit-house-light-5 {
  var-bg: rgba(59,63,65,0.8);
  var-fg: #eee;
...
```

この例では*.behaviorsから参照するCSSファイルは以下で、そこからベースとなるCSSファイルを@importで読み込んでいます。

```css:skins/light-1.css
@import url("light-base.css");

body:before {
    z-index: -1;
    position: absolute;
    top: 0;
    left: 0;
    content: url("../img/cocoa_1920.jpg");
    -webkit-transform: scale(1.0) translate(0px, 0px);
}
```

以上でスキン作成ができます。そんなに難しくなかったですね。

# その他の話
### プラグイン内でショートカットキーを設定する
あまり行儀はよくないですが、プラグイン内でショートカットキーの設定ができます。

User keymapとかと同じ形式のファイルを作成して

```clj:plugin.keymap
{:+ {:app {"ctrl-alt-shift-1" [:set-skin-rabbit-house-light-1]
           "ctrl-alt-shift-2" [:set-skin-rabbit-house-light-2]
           "ctrl-alt-shift-3" [:set-skin-rabbit-house-light-3]
           "ctrl-alt-shift-4" [:set-skin-rabbit-house-light-4]
           "ctrl-alt-shift-5" [:set-skin-rabbit-house-light-5]
           }}}
```

*.behaviorsファイルで`(:lt.objs.plugins/load-keymap "plugin.keymap")`のようにして読み込みます。


### プラグイン内でコマンドの定義をする
上の例で`:set-skin-rabbit-house-light-1`のようなコマンドを定義するにはClojureScriptを記述する必要があります。

lt.objs.commandのcommand関数を使って以下のような記述をします。

```clj
(cmd/command {:command :コマンド名
              :hidden true ; trueだとCommandsに現れない
              :desc "ポップアップで現れる説明"
              :exec #(do ...)})
```

```clj:lt/plugins/theme_rabbit_house.cljs
(ns lt.plugins.theme-rabbit-house
  (:require [lt.object :as object]
            [lt.objs.tabs :as tabs]
            [lt.objs.command :as cmd]
            [lt.objs.style :as style]
            [lt.objs.settings :as settings])
  (:require-macros [lt.macros :refer [defui behavior]]))

(def plugin-name "theme-rabbit-house")
(def theme "rabbit-house-light")
(def base-name "rabbit-house-light")

(defn skin-command [name]
  (let [skin (str base-name "-" name)]
    (cmd/command {:command (keyword (str "set-skin-" skin))
                  :hidden true
                  :desc (str plugin-name ": set skin " skin)
                  :exec #(do
                           (let [cur-skin (:skin @style/styles)]
                             (when-not (= skin cur-skin)
                               (object/remove-tag-behaviors :app [(list :lt.objs.style/set-skin cur-skin)])
                               (object/tag-behaviors :app [(list :lt.objs.style/set-skin skin)])))
                           (let [cur-theme (:theme @style/styles)]
                             (when-not (= theme cur-theme)
                               (object/remove-tag-behaviors :editor [(list :lt.objs.style/set-theme cur-theme)])
                               (object/tag-behaviors :editor [(list :lt.objs.style/set-theme theme)]))))})))

(doseq [n (range 1 6)] (skin-command n))
```

コマンド定義内で、以下のようにしてスキンの変更とテーマの変更をしていましたが、Workspaceの表示がおかしくなったりしてこれだけだとダメなようです。

```clj
(object/tag-behaviors :app [(list :lt.objs.style/set-skin skin)])
(object/tag-behaviors :editor [(list :lt.objs.style/set-theme theme)])
```

※追記
object/remove-tag-behaviorsで現在のスキン、テーマを削除する必要があったようです。そうしたらWorkspaceの表示は正常になりました。
lt.objs.style/stylesに現在のスキン、テーマの情報がAtomとして存在しているので、それを使って削除するようにしました。
※追記ここまで

あとは、ClojureScriptを保存すると*_compiled.jsファイルが自動生成されるので、それを*.behaviorsファイルで`(:lt.objs.plugins/load-js "theme_rabbit_house_compiled.js")`のようにして読みこめばOKです。

※plugin.ednの:nameを変えたら自動生成される*_compiled.jsの名前も変わってしまうので注意が必要です
※ClojureScript保存時にできる*_compiled.js.mapファイルは動作には不要なようです

※余談ですが、CSSで変数定義（var）できるようになったんですね～はじめて知りました。