Atomのコード読みまくったので、git-grepの結果へジャンプできる拡張を作ってみた

ここしばらく気が狂ったようにGithubAtomのコードを読んでた。

コードリーディングの成果はここに貼ってる。まだ更新するかもしれない atom-reading.md

で、大体のコードを読んだのはいいとしてなんか作らないと勿体無い気がしたので、エディタ内でgit-grepの結果見てジャンプできるやつ作った。

mizchi/atom-git-grep

自分で作っといてなんだけどくっそ便利だと思う。Sublimeで作りたかった。

プラグインの作り方の大雑把な概要

nodeのモジュール使って、普通のブラウザっぽいUIを組む。基本パーツはatom側に揃ってるので継承して使う。

必要なインスタンスはだいたいatom変数以下に入ってる。shift+cmd+I でデバッガ開いて叩きまくるとだいたい察することができる。

プラグインのスケルトン生成

shift+cmd+p でコマンドパレット出して、

Package Generator: Generate package

を入力すると雛形が作られる。

atom-git-grepからコード例。Space-penっていうBackbone.View風のAPIを持ったテンプレートエンジンがあるので、それを継承して使う。たぶん使わなくてもどうにかなるが、使ったほうが圧倒的に楽。

{View} = require 'atom'
{SelectListView} = require 'atom'
path = require 'path'
{$$, Point, SelectListView} = require 'atom'

module.exports =
class GitGrepView extends SelectListView
  getFilterKey: -> 'filePath'

  initialize: (serializeState) ->
    super
    @addClass('git-grep overlay from-top')

  viewForItem: (line) ->
    """<li>
      <span style="color:white">#{line.filePath}</span>
      :
      <span style="color:linen">L#{line.line}</span>
      :
      <span style="color:grey">#{line.content}</span>
    </li>"""

  confirmed: (item) ->
    @openPath (path.join atom.project.rootDirectory.path, item.filePath), item.line-1
    @hide()

  serialize: ->

  openPath: (filePath, lineNumber) ->
    if filePath
      atom.workspaceView.open(filePath).done => @moveToLine(lineNumber)

  moveToLine: (lineNumber=-1) ->
    return unless lineNumber >= 0
    if editorView = atom.workspaceView.getActiveView()
      position = new Point(lineNumber)
      editorView.scrollToBufferPosition(position, center: true)
      editorView.editor.setCursorBufferPosition(position)
      editorView.editor.moveCursorToFirstCharacterOfLine()

  destroy: ->
    @detach()

なんか適当にatom/fuzzy_finderとか参考にopenPathとmoveToLine実装した

困ったこと

標準でダイアログやプロンプトの仕組みがない。他のライブラリ見ると毎回作ってるっぽい。しょうがないのでatom/tree-viewを参考に自分も自前で用意した。

あと、スケルトン生成時にテストも一緒につくられるんだけど、テストが通らないとapm publish minorを受け付けてくれない!なので適当にごまかした。やったぜ。

今からiframeでlocalhostを開く拡張作る。