Atomでlatex用パッケージを作成する

##動機
Atomでlatexを書いてるけど、多用する`\itemize`とか`\item`を出すのがスニペットを使っても面倒。Atomならどうにか出来るだろうしやってみるか。

##目標
texファイルを編集している最中、`alt-enter`で改行して`\item`、`alt-shift-enter`で改行して

```latex
\begin{itemize}
  \item %ここにカーソル
\end{itemize}
```

みたいな感じにしたい。

##環境
```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G65
$ atom -v
Atom    : 1.29.0
Electron: 2.0.5
Chrome  : 61.0.3163.100
Node    : 8.9.3
```

##プログラムの作成
[AtomのAPI](https://atom.io/docs/api/v1.29.0/AtomEnvironment)や既存のパッケージを参考に作る。

```init.coffee
atom.commands.add 'atom-text-editor[data-grammar~="latex"]', 'custom:newline-item', ->
  editor = atom.workspace.getActiveTextEditor()
  view = atom.views.getView editor
  editor.transact =>
    atom.commands.dispatch view, 'editor:newline'
    editor.insertText('\\item ')

atom.commands.add 'atom-text-editor[data-grammar~="latex"]', 'custom:newline-itemize', ->
  editor = atom.workspace.getActiveTextEditor()
  cursor = editor.getLastCursor()
  view = atom.views.getView editor
  editor.transact =>
    atom.commands.dispatch view, 'editor:newline'
    editor.insertText('\\begin{itemize}')
    atom.commands.dispatch view, 'editor:newline'
    editor.insertText('\\item ')
    pos = cursor.getBufferPosition()
    atom.commands.dispatch view, 'editor:newline'
    editor.insertText('\\end{itemize}')
    cursor.setBufferPosition(pos)
```

```keymap.cson
'atom-text-editor[data-grammar~="latex"]':
  'alt-enter': 'custom:newline-item'
  'alt-shift-enter': 'custom:newline-itemize'
```

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/186959/49073d7f-cc88-90ef-cff9-4267f261d5d1.gif)


`custom:newline-itemize`の`'\\item '`や`'\\end{itemize}'`のインデントが自動で行われるので、調べたら`language-latex`パッケージによるものだと判明。

##パッケージの作成
###雛形の作成
Atom内で`cmd-shift-P`→`Package Generator: Generate Package`→`/Users/aaaa/github/latex-itemizer`

```
$ tree
.
|-- keymaps          # ショートカットキー
|   `-- latex-itemizer.json
|-- lib              # 実装
|   |-- latex-itemizer-view.js
|   `-- latex-itemizer.js
|-- menus            # メニューバーとコンテキストメニュー
|   `-- latex-itemizer.json
|-- package.json     # パッケージの基本情報
|-- spec             # テスト
|   |-- latex-itemizer-spec.js
|   `-- latex-itemizer-view-spec.js
`-- styles           # スタイル
    `-- latex-itemizer.less
```

###移植
既存のパッケージを参考にして作り、今回のプログラムはこんな感じに。

```
$ tree
.
|-- keymaps
|   `-- latex-itemizer.cson
|-- lib
|   `-- latex-itemizer.coffee
`-- package.json
```

```lib/latex-itemizer.coffee
{CompositeDisposable} = require 'atom'

module.exports =
  subscriptions: null

  activate: ->
    @subscriptions = new CompositeDisposable
    @subscriptions.add atom.commands.add 'atom-workspace', {
      'latex-itemizer:newline-item'    : => @newline_item()
      'latex-itemizer:newline-itemize' : => @newline_itemize()
    }

  deactivate: ->
    @subscriptions.dispose()

  newline_item: ->
    editor = atom.workspace.getActiveTextEditor()
    view = atom.views.getView editor
    editor.transact =>
      atom.commands.dispatch view, 'editor:newline'
      editor.insertText('\\item ')

  newline_itemize: ->
    editor = atom.workspace.getActiveTextEditor()
    cursor = editor.getLastCursor()
    view = atom.views.getView editor
    editor.transact =>
      atom.commands.dispatch view, 'editor:newline'
      editor.insertText('\\begin{itemize}')
      atom.commands.dispatch view, 'editor:newline'
      editor.insertText('\\item ')
      pos = cursor.getBufferPosition()
      atom.commands.dispatch view, 'editor:newline'
      editor.insertText('\\end{itemize}')
      cursor.setBufferPosition(pos)
```

```keymaps/latex-itemizer.cson
'atom-text-editor[data-grammar~="latex"]':
  'alt-enter': 'latex-itemizer:newline-item'
  'alt-shift-enter': 'latex-itemizer:newline-itemize'
```

```package.json
{
  "name": "latex-itemizer",
  "main": "./lib/latex-itemizer",
  "version": "0.0.0",
  "description": "For latex-itemizer",
  "activationCommands": {
    "atom-text-editor[data-grammar~=\"latex\"]": [
      "latex-itemizer:newline-item",
      "latex-itemizer:newline-itemize"
    ]
  },
  "repository": "https://github.com/atom/latex-itemizer",
  "license": "MIT",
  "engines": {
    "atom": ">=1.0.0 <2.0.0"
  },
  "dependencies": {
    "atom-package-dependencies": "latest"
  },
  "package-dependencies": {
    "language-latex": "1.1.1"
  }
}
```

- `newline_itemize`を綺麗に書きたいけど、動くので…。
- `package.json`に依存パッケージの部分`"package-dependencies"`を忘れずに。

###テスト
`ctrl-alt-cmd-L`でAtomを再読み込みしてtexファイルで試すが、`'alt-enter': 'latex-itemizer:newline-item'`が作動しない。
キーマップがAtom本来のものと重複していることが判明。
![スクリーンショット.png](https://qiita-image-store.s3.amazonaws.com/0/186959/4cd35ef3-37f1-4929-73b4-543aedc8ecc7.png)

[Overriding core keybindings? - support - Atom Discussion](https://discuss.atom.io/t/overriding-core-keybindings/10180)を参考に`keymaps/latex-itemizer.cson`を修正。

```keymaps/latex-itemizer.cson
'.editor[data-grammar~="latex"]:not([mini])':
  'alt-enter': 'latex-itemizer:newline-item'
  'alt-shift-enter': 'latex-itemizer:newline-itemize'
```

これで上手くいったので終わり。

[公開編へ](https://qiita.com/_-----------_/items/7212999a5e6cfedf41a8)