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


動機

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

目標

texファイルを編集している最中、alt-enterで改行して\itemalt-shift-enterで改行して

\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や既存のパッケージを参考に作る。

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'

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

パッケージの作成

雛形の作成

Atom内でcmd-shift-PPackage 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本来のものと重複していることが判明。

Overriding core keybindings? - support - Atom Discussionを参考に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'

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

公開編へ