Light TableにUndo selectionとGo back to bracketコマンドを作る

Light Table 0.7？からUser scriptの設定をすることができるようになったので、プラグインを自作しなくても自作コマンドを作って設定することができます。

# Undo selectionコマンド
`:editor.sublime.selectNextOccurrence`コマンド等で選択しすぎた箇所のUndoをするUndo selectionコマンドを作るのは簡単です。

```user.cljs
(ns lt.plugins.user
  (:require [lt.objs.command :as cmd]
            [lt.objs.editor :as ed]))

(defn ->clj [x] (lt.util.cljs/js->clj x :keywordize-keys true))
(defn ->js [x] (lt.util.cljs/clj->js x))
(defn get-cm [] (ed/->cm-ed (lt.objs.editor.pool/last-active)))

(cmd/command {:command :user.undo-selection
              :desc "User: Undo selection"
              :exec #(.undoSelection (get-cm))})
```

CodeMirrorオブジェクトにそのまま`.undoSelection`があります。

# Go back to bracketコマンド

`:editor.sublime.goToBracket`コマンドでは右のほうにあるかっこに移動できます。その逆の、左のほうに移動するコマンドもほしいので作ってみます。
※`:editor.sublime.goToBracket`コマンドの実装のほぼコピーです。

```user.cljs
(defn go-back-to-bracket [cm]
  (.extendSelectionsBy cm #(if-let [prev (->clj (.scanForBracket cm (.-head %) -1))]
                             (->js (update-in (:pos prev) [:ch] inc))
                             (.-head %))))

(cmd/command {:command :user.go-back-to-bracket
              :desc "User: Go back to bracket"
              :exec #(go-back-to-bracket (get-cm))})
```

`.scanForBracket`で前にあるかっこの位置を検索して、その位置+1の値を返す関数を`.extendSelectionsBy`に渡しています。
複数カーソルにも対応しているのがすばらしいです。

# Delete to bracket, Delete back to bracketコマンド

作成したコマンドを組み合わせて、かっこの位置まで削除するコマンドを作ってみます。

```user.cljs
(defn delete-to-bracket [cm command]
  (.setExtending cm true)
  (cmd/exec! command)
  (.replaceSelection cm "")
  (.setExtending cm false))

(cmd/command {:command :user.delete-to-bracket
              :desc "User: Delete to bracket"
              :exec #(delete-to-bracket (get-cm) :editor.sublime.goToBracket)})

(cmd/command {:command :user.delete-back-to-bracket
              :desc "User: Delete back to bracket"
              :exec #(delete-to-bracket (get-cm) :user.go-back-to-bracket)})
```

`.setExtending`はShiftキーを押しているのと同じような効果を持ちます。
`cmd/exec!`を使うと指定したコマンドが実行できます。
`.replaceSelection`はそのまんま選択箇所の置換です。

# keymapに設定する

keymapでショートカットキーを設定して使うと便利です。

```clj:user.keymap抜粋
 [:editor "ctrl-f12" :user.undo-selection]
 [:editor "ctrl-left" :user.go-back-to-bracket]
 [:editor "ctrl-shift-left" :user.go-back-to-bracket]
 [:editor "ctrl-del" :user.delete-to-bracket]
 [:editor "ctrl-backspace" :user.delete-back-to-bracket]
```

# 参考：User keymap全体

```clj:user.keymap
[
 [:editor.keys.hinting.active "-enter" :passthrough]

 ;; watch
 [:tabs "-pmeta-w" :passthrough]
 [:editor "ctrl-w" :editor.watch.watch-selection]
 [:editor "ctrl-shift-w" :editor.watch.remove-all]
 [:editor.clojure "ctrl-e" (:eval.custom "(macroexpand-1 '__SELECTION__)")]

 ;; edit
 [:editor "ctrl-/" :toggle-comment-selection]
 [:editor "ctrl-i" :smart-indent-selection]
 [:editor "ins right" :paredit.grow.right]
 [:editor "ins left" :paredit.grow.left]
 [:editor "ctrl-del" :user.delete-to-bracket]
 [:editor "ctrl-backspace" :user.delete-back-to-bracket]

 ;; move
 [:editor "f3" :find.next]
 [:editor "shift-f3" :find.prev]
 [:editor "ctrl-right" :editor.sublime.goToBracket]
 [:editor "ctrl-left" :user.go-back-to-bracket]

 ;; select
 [:editor "f4" :paredit.select.parent]
 [:editor "f5" :paredit.select.clear :editor.sublime.selectBetweenBrackets]
 [:editor "f12" :editor.sublime.selectNextOccurrence]
 [:editor "ctrl-f12" :user.undo-selection]
 [:editor "ctrl-shift-right" :editor.sublime.goToBracket]
 [:editor "ctrl-shift-left" :user.go-back-to-bracket]

 ;; window
 [:app "ctrl-q" :workspace.show]
 [:app "ctrl-pageup" :window.zoom-in]
 [:app "ctrl-pagedown" :window.zoom-out]
 [:app "f11" :window.fullscreen]
 [:app "esc" :find.clear :find.hide :eval.cancel-all!]
 [:app "ctrl-shift-c" :toggle-console :clear-console]

]
```