ここ1ヶ月ほどlanguage-context-freeというAtom editorのContext Free用パッケージを開発していたので、その足跡を残しておきたい。qiitaとどちらに載せようか考えたけど、Context Freeの記事ははてなダイアリーに載せていたので、こちらに載せることにした。

TextMate bundleからコンバート

まずは、Converting a TextMate Bundleの手順にしたがって、Context FreeのTextMate bundleをコンバートした。この状態で、シンタックスハイライトとスニペットが付いているはずである。

apm publish minorとやって、v0.1.0をリリース。

レンダリング機能

TextMate版では、cfdgコマンドが同梱されていてこれを使ってレンダリングが出来るようだったので、こちらでも入れてみることにした。

パッケージ開発の参考にしたのは、Markdown PreviewImage Viewである。libの下の3つのcoffeeスクリプトファイルはこのときに作成されたものである。

v0.2.0

実際に使ってみると、cfdgのコマンドを呼び出したまま戻ってこないケースがあったので、タイムアウトまでの時間を設定できるようにして、v0.3.0とした。

v0.3.0

また、Linuxでもレンダリングできるよう、cfdgのパスとLD_LIBRARY_PATHをオプションの設定項目にして、v0.4.0とした。 Linuxは環境も様々なのでcfdg自体は自前でビルドしてこれらの設定項目で調整できるようにと配慮したつもりである。

v0.4.0

cfdg Homebrew Tap

OS X用のcfdgコマンドを同梱したものの、正常に動作する環境とそうでない環境があるようだった。 どの環境でもソースからビルドしたcfdgコマンドを使うと上手くいくようなので、個々の環境でビルドできるようHomebrewのformulaを作ることにした。

class Cfdg < Formula
  homepage "http://www.contextfreeart.org/"
  url "http://www.contextfreeart.org/download/ContextFreeSource3.0.8.tgz"
  sha1 "bbd90c74fd0e66cb071c342da52ad016e023da2b"

  depends_on "bison" => :build
  depends_on "libpng"

  def install
    system "make"
    bin.install "cfdg"
  end

  test do
    (testpath/"test.cfdg").write <<-EOS.undent
    startshape SPIKE

    CF::Symmetry = CF::Dihedral, 6

    shape SPIKE
    rule {
      SQUARE []
      SPIKE [y 0.95 s 0.97]
    }
    rule 0.03 {
      SQUARE []
      SPIKE [r 60]
      SPIKE [r -60]
      SPIKE [y 0.95 s 0.97]
    }
    EOS
    system "cfdg", "-s", "700", "test.cfdg", "test.cfdg.png"
  end
end

bison(ビルド時にのみ依存する)とlibpngの記述を付けたのと、make installのルールが無いので、cfdgのコピーを追加している。 また、テストはソースのtarballに含まれていたものを使用した。

Formula Cookbookを見ながら、brew install --verbose --debug foobrew auditを実行して、問題のある箇所は修正した。

最終的に、本家にpull request出してみたのだが、 JenkinsのCIでOS X 10.8(Mountain Lion)でビルドに失敗するようだったので、仕方なくTapリポジトリにした。

https://github.com/kn1kn1/homebrew-cfdg

Atomパッケージ側もcfdgパスをMandatoryの設定項目に変更して、v0.5.0とした。

v0.5.0

Variation機能の追加とテストの追加

本家のContext Freeでは、cfdgに与える"A"〜"ZZZZZZ"のVariationの値があって、レンダリングする度に値が1ずつインクリメントしたりするのだけど、その機能を実装したいと考えていた。 と、その前にそろそろテストが必要な感じがしてきたので、specを追加した。

https://github.com/kn1kn1/language-context-free/commit/eefec53d2eb84fc1b2c6c8454a3f4879a24d05e9

その後、設定画面からVariation値を変更できるようにするなどして、v0.6.0とした。

v0.6.0

CI

テストを入れたので次はCIである。

https://github.com/atom/ci

MacとWindowsではCIの方法が確立されているようである。Windowsはサポートしていないので、Mac用に.travis.ymlを用意した。Linuxは簡単にはできそうになかった。

CI on Linux

調べて行くと、LinuxでのCIはフォーラムで議論されている最中だった。

https://discuss.atom.io/t/testing-ci-for-packages-on-linux/13070

go-plusの作者が、wercker + dockerで試しているが上手く行っていないとのことだそうだ。

go-plusで公開していたDockerfileを参考にして、こちらで色々と試した。

wercker.ymlファイルは、wercker devcenter - Docker Supportwercker-docker-sampleなどを参考にした。

Dockerfileを以下の形にしたところでapm testのpassまで確認できたので、その旨上述のフォーラムに書き込んだ

https://github.com/kn1kn1/language-context-free/blob/v0.6.5/Dockerfile

# Atom Docker Image For Package Testing
FROM ubuntu:trusty
MAINTAINER Kenichi Kanai <kn1kn1@users.noreply.github.com>

# Make Sure We're Up To Date
RUN DEBIAN_FRONTEND=noninteractive apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y

# Install Required Packages For Atom
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y git gconf2 gconf-service libgtk2.0-0 libnotify4 libxtst6 libnss3 python gvfs-bin xdg-utils
#  For downloading deb
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y wget
#  For apm install
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y make g++
#  For apm test
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y xvfb

# Download And Install Atom
RUN wget -nv -O atom-amd64.deb https://atom.io/download/deb
RUN DEBIAN_FRONTEND=noninteractive dpkg -i atom-amd64.deb
RUN DEBIAN_FRONTEND=noninteractive apt-get install -f
RUN rm -rf atom-amd64.deb
RUN apm --version

# Add Package To `/root` Dir
ENV HOME /root
ADD . $HOME
WORKDIR /root

# Install Package Dependencies
RUN apm install

# Start the Xvfb server with a display 99 and a virtual screen(monitor) 0.
RUN start-stop-daemon --start --pidfile /tmp/xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1024x768x24 -ac +extension GLX +extension RANDR +render -noreset && \
    sleep 3 && \
    export DISPLAY=:99 && \
    apm test

実はそれほど問題なくできたのだけど、注意したところと言えばstart-stop-daemonapm testを同じRUNに入れるところくらいだろうか。

Docker Hub Registoryにatom-apm-testレポジトリ作成

上記のDockerfileでも動作自体は問題ないのだが、必要となるpackageを毎回インストールするのは時間が掛かるので、 Docker Hub Registoryにatom-apm-testという名前のレポジトリを作成して、これをFromに使うようにした。

https://registry.hub.docker.com/u/kn1kn1/atom-apm-test/

最終的なDockerfileとしては以下の形になった。

https://github.com/kn1kn1/language-context-free/blob/master/Dockerfile

# Atom Docker Image For Package Testing

# based from the container published at docker hub
# https://registry.hub.docker.com/u/kn1kn1/atom-apm-test/
FROM kn1kn1/atom-apm-test:latest
MAINTAINER Kenichi Kanai <kn1kn1@users.noreply.github.com>

# Make Sure We're Up To Date
RUN \
  apt-get update && \
  DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y

# Download And Install Atom
RUN \
  wget -nv -O atom-amd64.deb https://atom.io/download/deb && \
  DEBIAN_FRONTEND=noninteractive dpkg -i atom-amd64.deb && \
  DEBIAN_FRONTEND=noninteractive apt-get install -f && \
  rm -rf atom-amd64.deb
RUN \
  apm --version

# Add Package To `/root` Dir
ENV HOME /root
ADD . $HOME
WORKDIR /root

# Install Package Dependencies
RUN \
  apm install

# Start the Xvfb server with a display 99 and a virtual screen(monitor) 0.
RUN \
  start-stop-daemon --start --pidfile /tmp/xvfb_99.pid --make-pidfile \
    --background --exec /usr/bin/Xvfb -- :99 -screen 0 1024x768x24 -ac \
    +extension GLX +extension RANDR +render -noreset && \
  sleep 3 && \
  export DISPLAY=:99 && \
  apm test

Atomの最新版のインストールとpackageのインストール、テストを実行するだけにしている。

上記とその他CFDG3の対応などを入れて、v0.7.0とした。

v0.7.0

その後細かい修正を入れ、v0.7.5で開発は一段落というところである。

所感

最初はコンバートだけで他にあまりやることは無いのかなーなどと思っていたのだが、レンダリング機能の開発を始めてからは、Homebrew formulaの作成や、wercker + dockerでのCI、Docker Hubレポジトリ作成など得るものが多かったように感じた。

あまりきちんと調べていないのだけど、TextMateにあってAtomにコンバートされていない言語用パッケージはまだまだあるのかもしれない。また時間ができたら別の言語でもやってみたいところである。