Sunflat のブログ

ソフトウェア開発についての話題が多いかも

XCodeで、C++のメンバ関数宣言を支援するマクロ

XCodeC++のクラスを実装する時に、ヘッダファイル(*.h)のメンバ関数の宣言から、実装ファイル(*.cpp)のメンバ関数定義用の宣言を、生成するマクロを作ってみた。(逆も可能)
いちいちコピペして「クラス名::」をつけたり消したりするのが面倒なので。

例えば、このようなヘッダファイルのメンバ関数の宣言から

class MyObject {
public:
  MyObject(int arg1);
  virtual void func1(int arg1);
};

このようなメンバ関数定義用の宣言を生成する。(逆も可能)

MyObject::MyObject(int arg1) {
}

void MyObject::func1(int arg1) { //virtual
}

インストール

  • 適当なディレクトリにconvertCppMethodDecl.rbを置く
  • XCodeの「スクリプトメニュー(巻物みたいなアイコン)→ユーザスクリプトの編集」を選び、+ボタン→スクリプトファイル追加→ convertCppMethodDecl.rb を選ぶ
  • ユーザスクリプトの編集ダイアログで、今追加したconvertCppMethodDecl.rbを選び、
    • 「入力:入力なし、ディレクトリ:ホームディレクトリ、出力:クリップボードに入れる、エラー:警告に表示」に設定
    • 「convertCppMethodDecl.rb」の右側のカラムをダブルクリックして、キーボードショートカットを「Command + Control + ↓」などに設定

使い方

  • 適用したいメンバ関数の宣言の行を選択して、「Command + Control + ↓」を押す。→スクリプトが実行され、クリップボードに結果がコピーされる
  • 「Command + Control + ↑」を押してヘッダファイルと実装ファイルを切り替え、好きな位置に結果を貼付ける

補足

  • 複数の宣言を一度に変換できるが、ヘッダファイル内で選択する時は、メンバ関数の部分だけを選択する。クラス名の部分を選択してはダメ
  • 複数行に渡る宣言はパースできない
  • メンバ関数定義用の宣言で末尾に「{」をつけたくない場合は、24行目最後の「 "{", 」をとればおk
  • 複雑な宣言は多分未対応(テンプレートとか)

スクリプト

convertCppMethodDecl.rb

#!/usr/bin/ruby -Ku

filePath='%%%{PBXFilePath}%%%'
selIndex=%%%{PBXSelectionStart}%%%

allText=<<__EOS__
%%%{PBXAllText}%%%
__EOS__

selText=<<__EOS__
%%%{PBXSelectedText}%%% 
__EOS__

found=false
if filePath =~ /\.h[a-z]*$/
  # when header files (*.h / *.hpp)
  className=''
  allText[0...selIndex].each_line do |line|
    className=$1 if line.chomp =~ /\s*(?:class|struct)\s+([_A-Za-z0-9]+)/
  end
  selText.each_line do |line|
    line.chomp!
    if line =~ /\s*(?:(virtual|static)\s+)?(?:(.+)\s+)?(~?[_A-Za-z0-9]+\(.+)\s*;\s*$/
      print ($2.nil? ? '' : $2+' '), className, '::', $3, " {",
        ($1.nil? ? '' : ' //'+$1), "\n"
      found=true
    end
  end
  
else
  # when implementation files (*.cpp / *.mm)
  selText.each_line do |line|
    line.chomp!
    if line =~ /^([_A-Za-z].+ )?~?[_A-Za-z0-9]+::(.+?)(?:\s*\{)?\s*(?:\/\/\s*(virtual|static)\s*)?$/
      print "\t", ($3.nil? ? '' : $3+' '), ($1.nil? ? '' : $1), $2, ";\n"
      found=true
    end
  end
end
print "[Not found]" unless found