読者です 読者をやめる 読者になる 読者になる

Xcodeのマクロ2

mac

Xcodeのテキストマクロについて、分かったことをざっくりと書きます。

  • 他のエディタだとスニペット/テンプレートと呼ばれてるもの
  • コード入力支援の仕組み
  • Xcodeのメニューから呼び出す事ができる
  • 入力補完候補から呼び出す事ができる

サンプル Objective-Cのマクロの場合

  • /Developer/Applications/Xcode.app/Contents/PlugIns/TextMacros.xctxtmacro/Contents/Resources/ObjectiveC.xctxtmacro
(
    //
    // Objective-C language macros (they also show up for Objective-C++)
    //
    {
        Identifier = objc;
        Name = "Objective C";
        IsMenu = YES;
// Can be set (for all languages) with the XCCodeSenseFormattingOptions user default
//        DefaultSettings = {
//            PreExpressionsSpacing = " ";
//            InExpressionsSpacing = "";
//            BlockSeparator = " ";
//            PostBlockSeparator = "\n";
//        };
        IncludeContexts = ( "xcode.lang.objc" );
        ExcludeContexts = ( "xcode.lang.string", "xcode.lang.character", "xcode.lang.comment", "xcode.lang.c.preprocessor" );
    },

        {
            Identifier = objc.log;
            BasedOn = objc;
            IsMenuItem = YES;
            Name = "NSLog() Call";
            TextString = "NSLog$(PreFunctionArgsSpacing)($(InFunctionArgsSpacing)@\"<#message#>\"$(InFunctionArgsSpacing));";
            CompletionPrefix = log;
            IncludeContexts = ( "xcode.lang.objc.block" );
        },
)
  • 拡張子 .. xctxtmacro
  • Key/Value形式
  • 他のマクロを継承できる
  • ブレース { } の中にマクロの定義を書いていく

マクロのプロパティについて ざっくりと。

プロパティはKey/Value形式で定義する

  • Identifier ... マクロの識別子。
  • Name ... Xcodeのメニュー欄に表示する文字列
  • IsMenu ... Xcodeのメニューにマクロを表示するかどうか
  • IncludeContexts / ExcludeContexts ... マクロが有効/無効なコンテキスト(*後述)
  • TextString ... マクロで挿入する文字列
  • CompletionPrefix ... 例えば「hoge」と設定しておくと、「hoge」と入力しているときXcodeの補完候補に出てくれるようになる
  • BasedOn ... マクロの継承元。例えば「 BasedOn = objc」とするとIdentifierがobjcのプロパティを継承するようであります。
  • Hoge = "hoge" 」というプロパティを定義すると、文字列内で $(Hoge)として参照する事ができる
  • DefaultSettings ... ??変数のデフォルト定義??

Xcodeの「コンテキスト」

  • Xcodeはカーソルの位置によってコンテキストを決定している。以下のようなイメージ( Objective-Cの場合 )
/*
 * ここにカーソルがあると xcode.lang.commentコンテキスト
 */

- (void)someMessage
{
    // ここにカーソルがあると xcode.lang.objc.blockコンテキスト
}
  • マクロはコンテキストを判別して、入力補完候補として有効か無効かを決める事ができる

IncludeContextsにxcode.lang.objc.blockコンテキストをもつマクロは、カーソルがメソッドのブロック内(xcode.lang.objc.blockコンテキスト)にあるときに入力補完の候補になる。( 他にもいろんなコンテキストがある。)

Hello,Worldマクロを作ろう

  • 「 NSLog(@"Hello,World"); 」と入力するマクロを作りたい!
        {
            Identifier = objc.hello;
            BasedOn = objc;
            IsMenuItem = YES;
            Name = "HelloWorld";
            HelloString = "Hello,World!";
            TextString = 'NSLog(@"$(HelloString)");';
            CompletionPrefix = "hello";
            IncludeContexts = ( "xcode.lang.objc.block" );
        },

以下のようにして呼び出せます。

  • メニューから


  • 補完候補から

もうちょっと有用なマクロを作る

TextStringのプロパティに "<#! ... !#>" という文字列を挿入すると(...は任意の文字列)、プレースホルダとして展開されます。複雑なマクロを定義した時にプレースホルダを使うとよさげ

        {
            Identifier = objc.message;
            BasedOn = objc;
            IsMenuItem = YES;
            Name = "Method Snippet";
            CompletionPrefix = "m";
            TextString = "[<#!object!#> <#!message!#>]";
        },

のマクロは以下のように展開されます。