概要

Mac で Cocoa アプリケーションや iPhone アプリケーションを開発する場合通常 XCode を利用します。

しかしながら、 普段 Emacs を利用している人は XCode に違和感を感じるはずです。

XCode は Emacs 風キーバインドに対応しているのでなんとかごまかしながら頑張っている人もいるかもしれませんが、 Emacs 使いはやっぱり本物の Emacs でないとプログラムのわくわく感が減少してしまうでしょう。

ここでは iPhone アプリケーションのプログラムを、なるべく Emacs でコーディングするための設定を記述していきます。

Cocoa アプリケーションを開発する場合は文章を参考に設定を多少変更してください。

前提知識

検証環境

この文書は以下の環境で検証した上で記述しています。他の環境だと記述と異なる場合がありますので注意してください。

  • Emacs
    • GNU Emacs23.2(Cocoa 64bit)
    • GNU Emacs23.1(Cocoa 64bit)
  • Mac OS X 10.6.2
  • XCode 3.2.1
  • Interface Builder 3.2.1
  • iPhone Simulator 3.1
  • auto-complete v1.3
  • company-mode 0.5
  • ac-company February 3, 2010

Warning

この文章の内容には Emacs22以下、 Carbon Emacs パッケージ(2010年版) では上手く動作しない部分があります。

XCode の外部エディタ設定

まずは XCode から Emacs を起動する設定をします。「外部エディタ」を設定すると XCode でソースをダブルクリックした時に該当のエディタでソースが開かれます。

「環境設定」->「ファイルタイプ」->「file」->「text」-> 「sourcecode」-> 「sourcecode.c」->「外部エディタ」-> 「その他」

を選択するとファイル選択ダイアログが出ますので、「Emacs.app」を選択してください。

選択し終ると以下のようになります。

../shared/images/emacsobjectivec/xcodefiletype.png

必ず 「その他」 を選択してください。最初からある emacs は Terminal 内で起動します。

../shared/images/emacsobjectivec/outereditor.png

開発プロジェクトは基本的に XCode で開いておく前提です。

Emacs での Objective-C 関連付け

Emacs を利用して Objective-C で開発する場合、 objc-mode を有効にする必要があります。

最も簡単な設定は以下を ~/.emacs.d/init.el (以後 init.el と記述) に記述することです。これは 拡張子 .m.mm.h に objc-mode を割り当てます。

(add-to-list 'auto-mode-alist '("\\.mm?$" . objc-mode))
(add-to-list 'auto-mode-alist '("\\.h$" . objc-mode))

しかし、この設定は通常単純すぎます。なぜならば、拡張子 .m のファイルは Objective-C 以外にも、 matlab 等で利用しますし、 拡張子 .h は C/C++ を始め様々な物で利用されています。

こうした拡張子によるモードの決め打ちは、Emacs を日常的に利用している人にとってはあまり便利な物ではない可能性があります。

Emacs22 以上ではこうした事態を避けるため、ファイルの内容を解析してモードを確定する機能がそなわっています。 magic-mode-alist を設定することでファイル内容でモードを設定することが可能です。

以下では @implementation@interface@protocol が行頭に出てくる行が存在するファイルを開くと、 objc-mode になるように設定しています。

これを利用すれば必要に応じてモードを設定することができ、便利です。ただし、当然ファイル内容で自動判定しますので、気を付けないと無関係なファイルが objc-mode になってしまう可能性もあります。

以下の設定では誤判定が出ることは少ないと思いますが、誤判定が頻繁に出るようであれば auto-mode-alist で設定してください。

(add-to-list 'magic-mode-alist '("\\(.\\|\n\\)*\n@implementation" . objc-mode))
(add-to-list 'magic-mode-alist '("\\(.\\|\n\\)*\n@interface" . objc-mode))
(add-to-list 'magic-mode-alist '("\\(.\\|\n\\)*\n@protocol" . objc-mode))

ヘッダファイル等を簡単に開く

例えば #import <UIKit/UIKit.h> 等の記述から簡単にヘッダファイルを開きたい場合があります。

ffap を利用すると C-x C-f するとカーソルがある部分を解析してファイルとして開こうとします。

ffap は C-x C-f の挙動が変化するので注意してください。

(ffap-bindings)
;; 探すパスは ffap-c-path で設定する
;; (setq ffap-c-path
;;     '("/usr/include" "/usr/local/include"))
;; 新規ファイルの場合には確認する
(setq ffap-newfile-prompt t)
;; ffap-kpathsea-expand-path で展開するパスの深さ
(setq ffap-kpathsea-depth 5)

また、 .h を開いている時に対応する .m を開いたり、 .m を開いている時に対応する .h を開いたりしたい場合、 ff-find-other-file を利用します。

以下のように設定すると C-c o で対応するファイルを開いてくれます。

(setq ff-other-file-alist
     '(("\\.mm?$" (".h"))
       ("\\.cc$"  (".hh" ".h"))
       ("\\.hh$"  (".cc" ".C"))

       ("\\.c$"   (".h"))
       ("\\.h$"   (".c" ".cc" ".C" ".CC" ".cxx" ".cpp" ".m" ".mm"))

       ("\\.C$"   (".H"  ".hh" ".h"))
       ("\\.H$"   (".C"  ".CC"))

       ("\\.CC$"  (".HH" ".H"  ".hh" ".h"))
       ("\\.HH$"  (".CC"))

       ("\\.cxx$" (".hh" ".h"))
       ("\\.cpp$" (".hpp" ".hh" ".h"))

       ("\\.hpp$" (".cpp" ".c"))))
(add-hook 'objc-mode-hook
         (lambda ()
           (define-key c-mode-base-map (kbd "C-c o") 'ff-find-other-file)
         ))

補完

補完を利用するために XCode を利用している人もいるかもしれませんが、 Emacs でも当然のように Objective-C の補完が可能です。

補完には auto-completecompany-modeac-company を利用します。

cd ~/.emacs.d
mkdir lisp
cd lisp
curl -O http://cx4a.org/pub/auto-complete/auto-complete-1.3.tar.bz2
curl -O http://nschum.de/src/emacs/company-mode/company-0.5.tar.bz2
curl -O http://github.com/buzztaiki/auto-complete/raw/master/ac-company.el
tar xvfj auto-complete-1.3.tar.bz2
tar xvfj company-0.5.tar.bz2

init.el に以下を追加します。

;; load-path を通す
(let ((default-directory (expand-file-name "~/.emacs.d/lisp")))
 (add-to-list 'load-path default-directory)
 (if (fboundp 'normal-top-level-add-subdirs-to-load-path)
     (normal-top-level-add-subdirs-to-load-path)))

;; ロード
(require 'auto-complete-config)
(require 'ac-company)
;; 対象の全てで補完を有効にする
(global-auto-complete-mode t)
;; ac-company で company-xcode を有効にする
(ac-company-define-source ac-source-company-xcode company-xcode)
;; objc-mode で補完候補を設定
(setq ac-modes (append ac-modes '(objc-mode)))
;; hook
(add-hook 'objc-mode-hook
         (lambda ()
           (define-key objc-mode-map (kbd "\t") 'ac-complete)
           ;; XCode を利用した補完を有効にする
           (push 'ac-source-company-xcode ac-sources)
           ;; C++ のキーワード補完をする Objective-C++ を利用する人だけ設定してください
           (push 'ac-source-c++-keywords ac-sources)
         ))
;; 補完ウィンドウ内でのキー定義
(define-key ac-completing-map (kbd "C-n") 'ac-next)
(define-key ac-completing-map (kbd "C-p") 'ac-previous)
(define-key ac-completing-map (kbd "M-/") 'ac-stop)
;; 補完が自動で起動するのを停止
(setq ac-auto-start nil)
;; 起動キーの設定
(ac-set-trigger-key "TAB")
;; 候補の最大件数 デフォルトは 10件
(setq ac-candidate-max 20)

XCode 上でプログラムソースをダブルクリックして、開くと Emacs が開きますので一部文字を入力してからタブ(tab)を押すと補完が効きます。

目的の物がうまく補完されない場合は XCode で一回対象のソースをビルドしておくと補完されるようになります。

上記の設定は XCode の xcodeindex コマンドを利用して、その場で動的に補完候補を収集するため最初だけ遅いですが、比較的綺麗な補完が可能です。

しかし常に動的に補完候補を収集する必要はない場合の方が多いかもしれません。その場合は etags を利用します。

etags とは簡単に言うとソースやヘッダ内にある名前(クラス名、メソッド名、関数名等)の索引(タグ)を生成するコマンドです。

まずは etags コマンドで タグファイルを生成します。以下の例ではタグを ~/.emacs.d/share/tags 以下に生成します。

cd ~/.emacs.d
mkdir -p share/tags
cd share/tags
find /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.2.sdk/System/Library/Frameworks -name "*.h" | xargs etags -f objc.TAGS -l objc

これで objc.TAGS という名前のタグファイルが生成されます。タグ内には利用できるクラス名のみ生成されます。

より詳細なタグを生成したい場合は以下のような shell スクリプトを作成して実行してみてください。メソッド等ほぼ全てを収集します。

#!/bin/sh
s="\t "
S="[$s]*"
w="_a-zA-Z0-9"
CN="[A-Z][$w]*"
NM="[$w][$w]*"

SDK="/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.2.sdk/System/Library/Frameworks"

find $SDK -name "*.h" | xargs etags -a --declarations -r "/$S[-+]$S(\($S$NM\)\{1,3\}$S\**$S)?$S\($NM\)$S[:;]/\2/" -f frm.tags
sed "/^@class/d" frm.tags > objc.TAGS

このタグを補完候補として追加します。タグファイルがやや大きめなので、 objc-mode でのみ補完の候補となるように etags-table.el を利用します。

etags-table.el は拡張子に合せて タグファイル柔軟に追加することができます。

cd ~/.emacs.d/lisp
curl -O http://bitbucket.org/sakito/dot.emacs.d/raw/tip/local-lisp/etags-table.el

init.el に以下のような設定をします。

;; etags-table の機能を有効にする
(require 'etags-table)
(add-to-list  'etags-table-alist
              '("\\.[mh]$" "~/.emacs.d/share/tags/objc.TAGS"))
;; auto-complete に etags の内容を認識させるための変数
;; 以下の例だと3文字以上打たないと補完候補にならないように設定してあります。requires の次の数字で指定します
(defvar ac-source-etags
  '((candidates . (lambda ()
         (all-completions ac-target (tags-completion-table))))
    (candidate-face . ac-candidate-face)
    (selection-face . ac-selection-face)
    (requires . 3))
  "etags をソースにする")
;; objc で etags からの補完を可能にする
(add-hook 'objc-mode-hook
          (lambda ()
            (push 'ac-source-etags ac-sources)))

これでタブ(tab)を押すと etags で収集できる物が補完候補になります。生成したタグの内容にしたがって補完されます。詳細なタグの方が詳細に補完されます。

etags は補完以外にも利用でき、 M . するとタグ候補が出てきて、選択することでタグの元になったソースに飛ぶことができます。

Emacs Lisp をバイトコンパイルしておくと動作が早くなるなど利点があります。コマンドラインからバイトコンパイルするなら以下のどちらかでバイトコンパイルできます。

# コマンドライン Emacs でバイトコンパイル
emacs -batch -f batch-byte-compile *.el
# Emacs.app
/Applications/Emacs.app/Contents/MacOS/Emacs -batch -f batch-byte-compile *.el

テキストマクロ(スニペット/テンプレート)

XCode には 「テキストマクロ」と呼ばれる機能が存在しますが、 Emacs では似た機能を YASnippet で実現可能です。

YASnippet は以下のようにするとインストールできます。

cd ~/.emacs.d/lisp
curl -O http://yasnippet.googlecode.com/files/yasnippet-0.6.1c.tar.bz2
tar xvfj yasnippet-0.6.1c.tar.bz2
cd yasnippet-0.6.1c
# バイトコンパイルします
emacs -batch -f batch-byte-compile *.el
# もしくは
/Applications/Emacs.app/Contents/MacOS/Emacs -batch -f batch-byte-compile *.el

init.el には以下のように設定します。 yas/root-directory が snippets の位置を指定します。

;; load-path を通す
(let ((default-directory (expand-file-name "~/.emacs.d/lisp")))
 (add-to-list 'load-path default-directory)
 (if (fboundp 'normal-top-level-add-subdirs-to-load-path)
     (normal-top-level-add-subdirs-to-load-path)))

(require 'yasnippet)
;; スニペットの位置を設定します。
(setq yas/root-directory "~/.emacs.d/lisp/yasnippet-0.6.1c/snippets")
;; メニューは使わない
(setq yas/use-menu nil)
;; 初期化
(yas/initialize)
(yas/load-directory yas/root-directory)

これで objc-mode でタブ(Tab)を押すと、 YASnippet が動作します。試しに for を打ってタブを押してみてください。

YASnippet の objc-mode 用 snippets はそれど多くありませんので、作成した方が便利です。まずは XCode の「テキストマクロ」を参考にして用意してみます。

XCode の 「テキストマクロ」は以下に定義されています。内容はテキストファイルですので、 Emacs で開くと普通に見ることができます。

/Developer/Applications/Xcode.app/Contents/PlugIns/TextMacros.xctxtmacro/Contents/Resources/ObjectiveC.xctxtmacro

元の snippets を上書きしないで 自分用の snippets ディレクトリを用意して、その中に作成した方が良いでしょう。

~/.emacs.d/etc/snippets ディレクトリを作成し、 init.el の設定を以下のよう修正しています。

;; スニペットの位置を複数設定します。同名の snippets はより後ろに設定した方で上書きされます。
(setq yas/root-directory '("~/.emacs.d/lisp/yasnippet-0.6.1c/snippets"
                           "~/.emacs.d/etc/snippets"))
;; 途中省略

;; yas/load-directory も複数ディレクトリに対応した修正をします
(mapc 'yas/load-directory yas/root-directory)

~/.emacs.d/etc/snippets ディレクトリの中に objc-mode ディレクトリを作成し、その中にファイル名 .yas-parents で以下のような内容のファイルを作成します。

cc-mode

これで自分用の設定をする準備が整いました。 ~/.emacs.d/etc/snippets ディレクトリの中に試しに try snippets を作成します。

objc-mode のファイルを開いた状態で M-x yas/new-snippet するとファイル名を聞いてきますので try を入力します。snippet-mode でファイルが開きます。

snippets の内容は以下のようにします。

# -*- mode: snippet -*-
#name : @try { ... } @catch { ... } @finally { ... }
# --
@try {
    $1
}
@catch (NSException * e) {
    $2
}
@finally {
    $3
}$0

snippet 作成中にテストする場合は M-x yas/tryout-snippet (C-c C-t) で動作の確認が可能です。

このようにして作成していきます。

参考として作成した物が以下に置いてあります。XCode のテキストマクロの動作を参考にしましたが、独自に作成したので結構動作の違う物があります。できれば自分に合うように修正してください。

http://bitbucket.org/sakito/dot.emacs.d/src/tip/etc/snippets/text-mode/cc-mode/objc-mode/

対応するカッコの自動挿入

Emacs 標準の機能でカッコの自動挿入を実施したい場合は以下のように設定します。

(add-hook 'c-mode-common-hook
         '(lambda()
            ;; 対応する括弧の挿入
            (make-variable-buffer-local 'skeleton-pair)
            (make-variable-buffer-local 'skeleton-pair-on-word)
            (setq skeleton-pair-on-word t)
            (setq skeleton-pair t)
            (make-variable-buffer-local 'skeleton-pair-alist)
            (local-set-key (kbd "(") 'skeleton-pair-insert-maybe)
            (local-set-key (kbd "[") 'skeleton-pair-insert-maybe)
            (local-set-key (kbd "{") 'skeleton-pair-insert-maybe)
            (local-set-key (kbd "`") 'skeleton-pair-insert-maybe)
            (local-set-key (kbd "\"") 'skeleton-pair-insert-maybe)
            ))

標準の機能より便利にしたい場合は smartchr.el を利用してみると良いでしょう。

例えば以下のような設定を init.el に記述します。

(defun smartchr-custom-keybindings ()
  (local-set-key (kbd "=") (smartchr '(" = " " == "  "=")))
  ;; !! がカーソルの位置
  (local-set-key (kbd "(") (smartchr '("(`!!')" "(")))
  (local-set-key (kbd "[") (smartchr '("[`!!']" "[ [`!!'] ]" "[")))
  (local-set-key (kbd "{") (smartchr '("{\n`!!'\n}" "{`!!'}" "{")))
  (local-set-key (kbd "`") (smartchr '("\``!!''" "\`")))
  (local-set-key (kbd "\"") (smartchr '("\"`!!'\"" "\"")))
  (local-set-key (kbd ">") (smartchr '(">" " => " " => '`!!''" " => \"`!!'\"")))
  )

(defun smartchr-custom-keybindings-objc ()
  (local-set-key (kbd "@") (smartchr '("@\"`!!'\"" "@")))
  )

(add-hook 'c-mode-common-hook 'smartchr-custom-keybindings)
(add-hook 'objc-mode-hook 'smartchr-custom-keybindings-objc)

「=」を打鍵すると「 = 」と前後に自動的に空白を入れてくれます。もう一度「=」を打つと「 == 」にしてくれます。

改行文字等も入れることが可能なので、いろいろ工夫ができると思います。

詳しい使い方は smartchr.el を使って生産性を上げる を参照してください。

インデント

以下の設定を init.el に記述しておくと、 objc インデントが適用されます。

(add-hook 'c-mode-common-hook
         '(lambda()
             (c-set-style "cc-mode")))

以下を設定しておくとタブは空白4つになります。

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)

インデントの設定は cc-mode のカスタマイズにて実施します。 cc-mode に関しては別途記述する予定です。

矩形選択

Objective-C はコーディングしていると矩形選択をしたくなる機会があるかと思います。矩形の選択は cua-mode にて実施できます。

cua-mode は コピーやペーストのキーを Windows や Mac のキーらしくするモードですが、ここでは矩形の機能だけ有効にしてみます。

;; CUA-mode にて矩形選択のみを有効化
(setq cua-enable-cua-keys nil)
(cua-mode t)

C-RET にて矩形選択モードになります。使い方は比較的直感的ですから使ってみると良いでしょう。

縦に連番挿入

cua-mode には連番を挿入する機能があります。

C-RET にて矩形選択モードにした後、 M-n すると連番挿入方法を聞いてきますので、初期値、増分値、形式を指定すると連番を簡単に挿入できます。

文法チェック

文法チェックは flymake にて実施します。 flymake は Emacs22 から標準添付になっています。

以下を init.el に記述します。

(require 'flymake)
(defvar xcode:gccver "4.0")
(defvar xcode:sdkver "3.1.2")
(defvar xcode:sdkpath "/Developer/Platforms/iPhoneSimulator.platform/Developer")
(defvar xcode:sdk (concat xcode:sdkpath "/SDKs/iPhoneSimulator" xcode:sdkver ".sdk"))
(defvar flymake-objc-compiler (concat xcode:sdkpath "/usr/bin/gcc-" xcode:gccver))
(defvar flymake-objc-compile-default-options (list "-Wall" "-Wextra" "-fsyntax-only" "-ObjC" "-std=c99" "-isysroot" xcode:sdk))
(defvar flymake-last-position nil)
(defvar flymake-objc-compile-options '("-I."))
(defun flymake-objc-init ()
  (let* ((temp-file (flymake-init-create-temp-buffer-copy
                    'flymake-create-temp-inplace))
         (local-file (file-relative-name
                     temp-file
                     (file-name-directory buffer-file-name))))
    (list flymake-objc-compiler (append flymake-objc-compile-default-options flymake-objc-compile-options (list local-file)))))

flymake を有効にするために objc-mode の hook に追加します。

(add-hook 'objc-mode-hook
         (lambda ()
           ;; 拡張子 m と h に対して flymake を有効にする設定 flymake-mode t の前に書く必要があります
           (push '("\\.m$" flymake-objc-init) flymake-allowed-file-name-masks)
           (push '("\\.h$" flymake-objc-init) flymake-allowed-file-name-masks)
           ;; 存在するファイルかつ書き込み可能ファイル時のみ flymake-mode を有効にします
           (if (and (not (null buffer-file-name)) (file-writable-p buffer-file-name))
               (flymake-mode t))
         ))

これでエラーが表示されるようになりますが、エラーがポップアップのような感じで表示されるので minibuffer に表示されるようにします。

以下を init.el に記述すると、エラー行にカーソルがあたると自動的に minibuffer にエラーが表示されます。

(defun flymake-display-err-minibuffer ()
  "現在行の error や warinig minibuffer に表示する"
  (interactive)
  (let* ((line-no (flymake-current-line-no))
         (line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no)))
         (count (length line-err-info-list)))
    (while (> count 0)
      (when line-err-info-list
        (let* ((file (flymake-ler-file (nth (1- count) line-err-info-list)))
               (full-file (flymake-ler-full-file (nth (1- count) line-err-info-list)))
               (text (flymake-ler-text (nth (1- count) line-err-info-list)))
               (line (flymake-ler-line (nth (1- count) line-err-info-list))))
          (message "[%s] %s" line text)))
      (setq count (1- count)))))

(defadvice flymake-goto-next-error (after display-message activate compile)
  "次のエラーへ進む"
  (flymake-display-err-minibuffer))

(defadvice flymake-goto-prev-error (after display-message activate compile)
  "前のエラーへ戻る"
  (flymake-display-err-minibuffer))

(defadvice flymake-mode (before post-command-stuff activate compile)
  "エラー行にカーソルが当ったら自動的にエラーが minibuffer に表示されるように
post command hook に機能追加"
  (set (make-local-variable 'post-command-hook)
       (add-hook 'post-command-hook 'flymake-display-err-minibuffer)))

;; 自動的な表示に不都合がある場合は以下を設定してください
;; post-command-hook は anything.el の動作に影響する場合があります
(define-key global-map (kbd "C-c d") 'flymake-display-err-minibuffer)

flymake-goto-next-errorflymake-goto-prev-error は何かキーを割り当てておくと便利です。

もしかしたらエラー表示の色が見ずらいかもしれません。色は以下で変更できます。

(set-face-background 'flymake-errline "red")
(set-face-background 'flymake-warnline "yellow")

色一覧に関しては M-x list-colors-display にて見ることができますので、好みの色に変更してください。

わたしは実際には color-theme を利用して変更しています。

コンパイルと実行

コマンドラインでコンパイルを実行する場合 xcodebuild コマンドを利用します。

iphonesimulator3.1.2 Debug は以下でコンパイルできます。

xcodebuild -configuration Debug -sdk iphonesimulator3.1.2

これを Emacs Lisp から呼べば良いのですが、コンパイルはできますが、実行はできないようです。

実行する場合は AppleScript を利用するのが簡単です。ここではキーコードを直接利用してみます。

Note

XCode は AppleScript が充実していて build コマンドも存在するのですが、キーコードの方が簡単なので手抜きしています

「コンパイルと実行」は以下の AppleScript で実行されます。

tell application "Xcode" to activate
tell application "System Events"
     tell process "Xcode"
          key code 36 using {command down}
     end tell
end tell

key code の行がポイントで、これは XCode のショートカットを押しています。よってショートカットをカスタマイズしていると正常に動作しません。

key code 部分で利用できる code 類を簡単に列挙しておきます。

using の次で利用できる物
using 意味 Unicode メニュー上での記号
command down コマンドキー 0x2318
control down コントロールキー 0x2303
option down オプション(alt)キー 0x2325
shift down シフトキー 0x21E7

キーコードは以下になります。一覧ぽい物がネット上にあったのですが、本当か良くわからないので自分で確認した物です。

kye code
キー コード
a 0
b 11
c 8
d 2
e 14
f 3
g 5
h 4
i 34
j 38
k 40
l 37
m 46
n 45
o 31
p 35
q 12
r 15
s 1
t 17
u 32
v 9
w 13
x 7
y 16
z 6
0 29
1 18
2 19
3 20
4 21
5 23
6 22
7 26
8 28
9 25
F1 122
F2 120
F3 99
F4 118
F5 96
F6 97
F7 98
F8 100
F9 101
F10 109
F11 103
F12 111
esc 53
tab 48
space 49
return 36
delete 51
left arrow 123
right arrow 124
down arrow 125
up arrow 126

よってこの例は Ctr+return キーを押したことになります。

AppleScript を Emacs Lisp に組み込みます。Carbon Emacs もしくは Cocoa Emacs でしか動作しません。

(defun xcode:buildandrun ()
 (interactive)
 (do-applescript
  (format
   (concat
    "tell application \"Xcode\" to activate \r"
    "tell application \"System Events\" \r"
    "     tell process \"Xcode\" \r"
    "          key code 36 using {command down} \r"
    "    end tell \r"
    "end tell \r"
    ))))

これで M-x xcode:buildandrun で実行できます。

キーを割り当てると便利です。 objc-mode-hook を以下のように設定すると C-c C-rxcode:buildandrun が実行されます。

(add-hook 'objc-mode-hook
         (lambda ()
           (define-key objc-mode-map (kbd "C-c C-r") 'xcode:buildandrun)
         ))

ブレークポイントの追加

AppleScript を利用すると Emacs で編集しているファイルにブレークポイントを付与できます。

具体的な AppleScript に関しては以下のサイトを参照してください。

開発ドキュメントの検索

本格的に開発する場合は開発ドキュメントを頻繁に引くことになります。

コマンドラインで開発ドキュメントを検索する場合は docsetutil コマンドを利用します。

/Developer/usr/bin/docsetutil search /Developer/Platforms/iPhoneOS.platform/Developer/Documentation/DocSets/com.apple.adc.documentation.AppleiPhone3_1.iPhoneLibrary.docset -query 'word'

word の部分に検索したい単語を入力すると該当するファイルを検索してくれます。

Emacs からこのコマンドを発行するのに便利な xcode-document-viewer.el が存在します。

動作には emacs-w3m が必要なので w3m と emacs-w3m をインストールします。

w3m は http://sourceforge.net/projects/w3m/files/ からダウンロードしてコンパイルするか 、 fink や MacPorts からインストールしてください。

ソースからインストールするなら以下で可能です。 w3m のコンパイルには Boehm GC が必要ですので一緒にインストールします。

curl -O http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc.tar.gz
tar xvfz gc.tar.gz
cd gc
./configure    # 環境によっては system clock のエラーがでる場合があるようです
make
sudo make install

cd ..

tar xvfz w3m-0.5.2.tar.gz
./configure
make
sudo make install

emacs-w3m は Emacs 上から w3m を動作させるための Emacs Lisp です。開発先端を利用して、 .emacs.d/lisp 等にインストールしています。

cvs -d :pserver:anonymous@cvs.namazu.org:/storage/cvsroot co emacs-w3m
cd emacs-w3m
autoconf
./configure --with-lispdir=~/.emacs.d/lisp/w3m --datarootdir=~/.emacs.d/share --with-icondir=~/.emacs.d/share/icon
make
make install
make install-icons

xcode-document-viewer を取得します。オリジナル作者は id:imakado ですが、ここでは sakito の改造(といってもたいした改造はしてない)物を利用しています。

anything.el も必要なので同時に取得します。

cd ~/.emacs.d/lisp
curl -O http://www.emacswiki.org/emacs/download/anything.el
curl -O http://github.com/sakito/emacs-xcode-document-viewer/raw/master/xcode-document-viewer.el
# オリジナルを取得するなら以下
# curl -O http://github.com/imakado/emacs-xcode-document-viewer/raw/master/xcode-document-viewer.el

init.el には以下のような設定をします。

;; emacs-w3m の自動ロード設定
(autoload 'w3m "w3m" "Interface for w3m on Emacs." t)
;; ドキュメントの参照
(require 'xcode-document-viewer)
(setq xcdoc:document-path "/Developer/Platforms/iPhoneOS.platform/Developer/Documentation/DocSets/com.apple.adc.documentation.AppleiPhone3_1.iPhoneLibrary.docset")
(setq xcdoc:open-w3m-other-buffer t)
;; hook の設定
(add-hook 'objc-mode-hook
         (lambda ()
            ;; C-c w で確認してからドキュメントの検索
            (define-key objc-mode-map (kbd "C-c w") 'xcdoc:ask-search)))

キー等は好みに設定してください。

ToDo

この文書にはいくつか課題が存在しています。順次解決していきます。

  • 快適なデバッグ手法
  • AppleScript が不十分
  • xcodebuild を利用したコンパイルをまとめた Emacs Lisp の公開

更新記録

  • 2010-06-06: auto-complete 1.3 に記述を変更
  • 2010-03-24: auto-complete 等の最新版に追随。Emacs 22 では正常動作しない部分があることを記述。設定をコピペしやすくまとめるのが危険だとわかったので削除。
  • 2010-02-14: typo があったので修正。w3m のコンパイルに Boehm GC が必要なので追記
  • 2010-02-13: etags による補完を追加。flymake 書き込み不可ファイルでも動作していたのを抑止。cc-mode に関しては別途別文書を起すことにした
  • 2010-02-11: flymake の option を 「-x objective-c」から「-ObjC」に変更。 smartchr.el の設定を追加
  • 2010-01-31: 矩形選択に関する記述を追加。
  • 2010-01-30: flymake の設定を修正。対応するカッコの自動挿入に関して追記。
  • 2010-01-23: YASnippet の設定を追加
  • 2010-01-13: Carbon Emacs パッケージに関する注記を修正。ドキュメントの検索を追加
  • 2010-01-11: typo 修正。検証環境を増加。 cons ではなく add-hook に変更。コメントが英語の所を日本語に変更。
  • 2010-01-09: 公開

関連エントリ

Author: sakito Updated: 2010年06月06日() category: /emacs Permalink: Permalink
このエントリーをはてなブックマークする はてなブックマーク数 このエントリーをdel.icio.usに登録する このエントリーを Tumblr する このエントリーに Twitter 経由でコメントする
以下はゲストコメント可能です。名前とメールアドレスは任意の物を入力していただいてかまいません。
blog comments powered by Disqus

このページの先頭へ

copyright (CC-by) 1999-2024 sakito
Powered by pyblosxom. Theme: TheBuckmaker.