Skip to content

Instantly share code, notes, and snippets.

@melborne
Created March 22, 2014 09:16
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melborne/9703653 to your computer and use it in GitHub Desktop.
Save melborne/9703653 to your computer and use it in GitHub Desktop.
Atom.io Document Translations

パッケージの作り方(Creating Packages)

パッケージ(Package)はAtomのコアです。エディターのメイン機能以外のほぼすべては、パッケージによって扱われます。これには、ファイルツリーステータスバーシンタックスハイライトのような「コア」の部分が含まれています。

パッケージには、Atomの動作を変更する多様な異なるリソースタイプを含めることができます。基本的なパッケージのレイアウトは次のとおりです。

my-package/
  grammars/
  keymaps/
  lib/
  menus/
  spec/
  snippets/
  stylesheets/
  index.coffee
  package.json

すべてのパッケージがこれらすべてのディレクトリを持つ(あるいは必要とする)わけではありません。

初めてのパッケージ作成のためのチュートリアルがあります。

また、TextMateバンドル、およびTextMateテーマの変換ガイドがあり、これらをAtomで使えるようになります。

package.json

npmパッケージと同じように、Atomパッケージにはトップレベルディレクトリにpackage.jsonファイルが含まれています。このファイルには、パッケージに関するメタデータ、つまり「メイン」モジュールへのパス、ライブラリの依存関係、そのリソースがロードされる順序を指定するマニフェストのようなものを含んでいます。

基本のnpm package.jsonキーが利用可能であることに加えて、Atom package.jsonファイルには独自に追加されたものがあります。

  • main(必須): CoffeeScriptファイルのパスで、これがパッケージのエントリポイントになる。

  • stylesheets(オプション): パッケージが必要とするスタイルシートの読み込み順を指定する文字列の配列。指定がない場合は、stylesheetsディレクトリのスタイルシートがアルファベット順で追加される。

  • keymaps(オプション): パッケージが必要とするキーマップの読み込み順を指定する文字列の配列。指定がない場合は、keymapsディレクトリのマッピングがアルファベット順で追加される。

  • menus(オプション): パッケージが必要とするメニューマップの読み込み順を指定する文字列の配列。指定がない場合は、menusディレクトリのマッピングがアルファベット順で追加される。

  • snippets(オプション): パッケージが必要とするスニペットの読み込み順を指定する文字列の配列。指定がない場合は、snippetsディレクトリのスニペットがアルファベット順で追加される。

  • activationEvents(オプション): パッケージのアクティベーションをトリガーするイベントを指定する文字列の配列。パッケージの読み込みをこれらのイベントの一つがトリガーされるまで遅延させることができる。

ソースコード(Source Code)

Atomの動作を拡張したい場合は、パッケージに一つのトップレベルに置かれるモジュールを含める必要がありますが、このモジュールはindex.coffee(またはpackage.jsonファイルのmainキーで指定されたファイル)からエクスポートします。コードの残りの部分はlibディレクトリに配置され、トップレベルファイルから読み込まれます。

パッケージのトップレベルモジュールは、Atomにおける拡張機能の寿命を管理するシングルトンオブジェクトです。パッケージが10の異なるビューを生成し、DOMの異なる部分に適用されたとしても、それらすべてはトップレベルのオブジェクトから管理されます。

パッケージのトップレベルのモジュールは、次のメソッドを実装する必要があります。

  • activate(state): この必須のメソッドは、あなたのパッケージがアクティブになったときに呼び出されます。モジュールがserialize()メソッドを実装している場合は、ウィンドウがシリアライズされた最後の時からの状態データが渡されます。これを使用して、パッケージの開始時の初期化作業を行います(DOM要素を設定したり、イベントをバインドするなど)。

  • serialize(): このオプションのメソッドは、ウィンドウがシャットダウンされるときに呼び出され、これによりコンポーネントの状態を表すJSONを返すことができるようになります。ウィンドウが後に復元されたとき、返されたデータはモジュールのactivateメソッドに渡されるので、ユーザーが残した最後の状態にビューを復元できます。

  • deactivate(): このオプションのメソッドは、ウィンドウがシャットダウンされるときに呼び出されます。パッケージが任意のファイルを見ているか他の方法で外部リソースを保持している場合、ここでそれらを解放します。ちょうどウィンドウで何かを読み込んでいる場合でも、解放されることになるので心配する必要はありません。

シンプルなパッケージのコード

ディレクトリはこのようになります。

my-package/
  package.json
  index.coffee
  lib/
    my-package.coffee

index.coffeeは、次のようになります。

module.exports = require "./lib/my-package"

my-package/my-package.coffeeは次のように開始されます。

module.exports =
  activate: (state) -> # ...
  deactivate: -> # ...
  serialize: -> # ...

このシンプルな形式から、パッケージはAtomのAPIへアクセスします。私たちはまだ開発の初期にいるのでAPIは変更されることがあり、また私たちはまだ公開するものとしないものの明確な境界を確立していないことに留意してください。また、存在しないAPIで必要なものがある場合は協力をお願いします。私たちの目標は、あなたのようなパッケージの作成者のニーズに基づく自然発生的なAtomのAPIを構築することにあります。

スタイルシート(Stylesheets)

パッケージのためのスタイルシートは、stylesheetsディレクトリに置く必要があります。このディレクトリ内のすべてのスタイルシートは、パッケージがアクティブになったときに読み込まれ、DOMに適用されます。スタイルシートはCSSまたはLESSとして記述することができます。

基本的に、スタイリングをするのにさほど手間はかかりません。任意のパッケージで使えるカラーとUI要素を定義する標準的なコンポーネントのセットが用意されており、これはAtomにシームレスにフィットします。スタイルガイド(styleguide)を開けばAtomのUIコンポーネントのすべてを見ることができます: commandパレットを開き(cmd-shift-P)、styleguideを検索するか、cmd-ctrl-shift-Gとタイプします。

特別なスタイリングが特に必要な場合は、パッケージのスタイルシートにおける構造的スタイルだけは維持するよう心がけましょう。色やサイズを指定することが必須の場合、そのアクティブなテーマのui-variables.lessから採択する必要があります。詳細については、テーマ変数資料を参照してください。このガイドラインに従えば、あなたのパッケージはどんなテーマでもすぐに使える良いものになります!

package.json内のオプションであるstylesheets配列で、スタイルシートの読み込み順序を指定するよう名前をリスティングできます。指定がなければ、スタイルシートはアルファベット順に読み込まれます。

キーマップ(Keymaps)

作成した拡張機能におけるよく使うアクションに、キーバインディングを提供されることをお勧めします(特に、新しいコマンドを追加する場合)。

'.tree-view-scroller':
  'ctrl-V': 'changer:magic'

キーマップはkeymapsサブディレクトリに配置されます。デフォルトでは、すべてのキーマップがアルファベット順に読み込まれます。package.jsonにおけるオプションのkeymaps配列で、ロードするキーマップとその順序を指定できます。

キーバインディングは、キー押下が発生した要素を決定することで実行されます。上記の例では.tree-view-scroller要素上でctrl-Vキーが押されたとき、changer:magicコマンドが実行されます。

キーマップの動作に関するより詳細な情報メインキーマップ資料を参照してください。

メニュー(Menus)

メニューは、menusサブディレクトリに配置されます。デフォルトでは、すべてのメニューがアルファベット順に読み込まれます。package.jsonにおけるオプションのmenus配列で、ロードするメニューとその順序を指定できます。

アプリケーションメニュー(Application Menu)

パッケージに、特定の要素に関連付けられていない、一般的な操作のためのアプリケーションメニュー項目を作成することをお勧めします。

'menu': [
  {
    'label': 'Packages'
    'submenu': [
      {
        'label': 'My Package'
        'submenu': [
          {
            'label': 'Toggle'
            'command': 'my-package:toggle'
          }
        ]
      }
    ]
  }
]

アプリケーションメニューに独自の項目を追加するには、単にmenusにおける任意のメニュー設定ファイルにトップレベルのmenuキーを作成します。これはJSONまたはCSONファイルです。

指定したメニューテンプレートは読み込まれた順序で、他のパッケージによって提供される他のすべてのテンプレートとマージされます。

コンテキストメニュー(Context Menu)

コマンドのコンテキストメニュー項目を、ツリービュー(tree-view)にファイルを追加するようなインターフェイスの特定部分にリンクするよう指定することをお勧めします。

'context-menu':
  '.tree-view':
    'Add file': 'tree-view:add-file'
  '.workspace':
    'Inspect Element': 'core:inspect'

アプリケーションメニューに独自の項目を追加するには、単にmenusにおける任意のメニュー設定ファイルにトップレベルのcontext-menuキーを作成します。これはJSONまたはCSONファイルです。

コンテキストメニューは、選択された要素がどれかを決定することにより生成され、その要素に一致するセレクターをもつすべてのメニュー項目を(読み込まれた順で)追加します。プロセスは、DOMツリーの最上位に到達するまで繰り返されます。

上記の例でAdd fileアイテムは、フォーカスされた項目またはその親の1つが、それに適用されるtree-vewクラスを持っているときにだけ表示されます。

スニペット(Snippets)

拡張機能はsnippetsディレクトリにおいて言語スニペットを提供でき、これによりユーザは素早く反復的なテキストを入力可能になります。

".source.coffee .specs":
  "Expect":
    prefix: "ex"
    body: "expect($1).to$2"
  "Describe":
    prefix: "de"
    body: """
      describe "${1:description}", ->
        ${2:body}
    """

スニペットファイルには、そのトップレベルでスコープセレクターが含まれています(.source.coffee.spec)。各スコープセレクターには、その名前(Expect, Describe)によるキーを持ったスニペットのハッシュが含まれます。各スニペットはまたprefixbodyキーを指定します。prefixは、オートコンプリートのためにtabキーを押す前の、入力の最初の数文字を表します。bodyは、自動挿入テキストを定義します。$1,$2などのプレースホルダを使って、ユーザがtabを打つたびに移動する領域を指示できます。

ディレクトリ内のすべてのファイルは、package.jsonsnippetsキーを提供しない限り、自動的に読み込まれます。すべてのスコープアイテムと同様に、後で読み込まれるスニペットは先に読み込まれるスニペットに、それらが同じ特性のスコープを持つ場合、優先します。

言語の文法(Language Grammars)

新しい言語の文法を開発しているとき、grammarsディレクトリにファイルを置きたくなります。それぞれの文法は2つのキー、matchcapturesの組み合わせです。matchはターゲットとするパターンを識別する正規表現であり、capturesは、各マッチグループに適用することを表現するオブジェクトです。

例:

{
  'match': '(?:^|\\s)(__[^_]+__)'
  'captures':
    '1': 'name': 'markup.bold.gfm'
}

これは、最初に一致したキャプチャ((__[^_]+__))が、それに適用されるmarkup.bold.gfmトークンを持つことを示しています。

1つのグループをキャプチャするには、代わりにnameキーを単に使用します。

{
  'match': '^#{1,6}\\s+.+$'
  'name': 'markup.heading.gfm'
}

これは、Markdownヘッダー行(#, ##, ###)に、markup.heading.gfmトークンが適用されるべきであることを示しています。

これらのトークンの意味についての詳細は、TextMateマニュアルのセクション12.4で見ることができます。

あなたの文法は、また、その文法がサポートするファイル拡張子のリストを含むfiletypes配列を含める必要があります。

'fileTypes': [
  'markdown'
  'md'
  'mkd'
  'mkdown'
  'ron'
]

外部リソースの同梱(Bundle External Resources)

パッケージに画像やフォントのような外部リソースを含め、これらをHTMLやCSSで容易に参照できるようにすることが普通であり、そのためにatomプロトコルURLを使ってリソースをパッケージに読み込ませることができます。

URLはatom://package-name/relative-path-to-package-of-resourceの形式でする必要があり、たとえば、atom://image-view/images/transparent-background.gifは、~/.atom/packages/image-view/images/transparent-background.gifと等しくなります。

テーマにatomプロトコルURLを使用することもできます。

テストを書く(Writing Tests)

パッケージはテストを持つべきであり、テストがspecディレクトリに置かれている場合はそれらはAtomによって実行されます。

内部的にJasminがテストを実行するので、そこで利用できる任意のDSLがパッケージに対しても利用できることを想像できるでしょう。

テストの実行(Running Tests)

テスト一式が書けたら、cmd-alt-ctrl-pを押すか、またはDeveloper > Run Package Specsメニューを通して、これを実行することができます。

また、apm testコマンドを使って、コマンドラインからテストを走らせることもできます。テストの出力と結果がコンソールに印字され、テストがパスかフェイルに応じた適切なステータスコードが返されます。

公開(Publishing)

Atomはapmと呼ばれるコマンドラインユーティリティを同梱しており、Atomパッケージを公開レジストリに公開するためにこれを使用できます。

パッケージが作られ、配布の準備ができたなら、パッケージを公開するために次を実行できます。

cd my-package
apm publish minor

これは、package.jsonが新しいマイナーversionを持つよう更新し、変更をコミットし、新しいGitタグを作り、そしてレジストリにパッケージをアップロードします。

apm help publishを実行して利用可能なすべてのオプションを、apm helpを実行して他の利用可能なすべてのコマンドをそれぞれ確認して下さい。

ガイド(Guides)

高度なトピック(Advanced Topics)

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> <script> $(function() { $("*").contents().filter(function() { return this.nodeType==8 && this.nodeValue.match(/^original/); }).each(function(i, e) { var tooltips = e.nodeValue.replace(/^original *[\n\r]|[\n\r]$/g, ''); $(this).prev().attr('title', tooltips); }); }); </script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment