Emacs(Mac)でC#の開発する その1

MacC#を開発するためには、.NetFrameworkの開発・実行環境(CLI)が必要になります。
.NetFrameworkはMicrosoft製なので、デフォルトでMacには環境がなく
Unix(ライク)OS に移植された CLI の開発・実行環境のMonoを利用します
Monoはオープンソースのプロジェクトで誰でも無償で利用できます。
CLI(Common Language Infrastructure)

Monoを利用してみる

まず以下からMonoをダンウンロード→インストールします
http://mono-project.com/Main_Page

インストール後、以下のようにmcs(コンパイラー)、mono(実行)のコマンドが
利用ようできるようになります

% vim test.cs
class test
{
    static void Main () {
        System.Console.WriteLine ("hello world");
    }
};

% mcs test.cs
% ls
test.cs    test.exe*
% mono test.exe
hello world

Emacsで開発できるようにする

Emacsで実践的な開発を行うにあたって以下の機能がほしい

  • c#用のモードを導入
  • imenu
  • 自動補完(動的略語展開)
  • tagジャンプ(gtags)
  • コードスタイルチェック(flymake)
  • シンタックスチェック(flymake)
  • カジュアルな実行環境(quickrun)
c#用のモードを導入

googleが出してるcsharp-modeを入れた
https://code.google.com/p/csharpmode/downloads/list

imenu

導入方法不明。
csharp-modeに機能が入ってるっぽいけど動かない...
保留。

自動補完(動的略語展開)

(auto-complete-mode)を利用。
csharp用の辞書も作成した
https://github.com/fujimisakari/.emacs.d/blob/master/share/ac-dict/csharp-mode

tagジャンプ(gtags)

まだ試してない。保留。

コードスタイルチェック(flymake)

C#のコードスタイルはstylecopが一般的らしい。(pythonでいうpep8みたいなやつ)
flymakeを利用するので、mac環境のコマンドラインから結果を返してるもの探してて
stylecop CLIっというのを見つけた。けど、windows用だった...
binとsrcで配布されててmacで両方試してみたけど動かなかったorz
ということでこれも保留。

シンタックスチェック(flymake)

これは、mcsコマンド利用してとりあえずチェックできた。
以下のようなcsharp-checkerスクリプトを用意した

#! /bin/bash

/usr/bin/mcs $1
exe_file=`echo $1 | sed -e "s/\.cs/.exe/"`
ls ${exe_file} && rm ${exe_file}

true

でも、これは開いてるファイルだけしか見てくれないので
using(import)してる先は、mcsコマンドのオプション(-r)で教えないとエラーになる

カジュアルな実行環境(quickrun)

これは、quickrun-add-commandとmonoコマンドを利用して設定できた

っで、今のところの設定は以下の通り
(require 'csharp-mode)
(setq auto-mode-alist
   (append '(("\\.cs$" . csharp-mode)) auto-mode-alist))

;; C#モードフック
(add-hook 'csharp-mode-hook
          '(lambda()
             (setq comment-column 40)
             (setq c-basic-offset 4)
             ;; (font-lock-add-magic-number)
             ;; オフセットの調整
             (c-set-offset 'substatement-open 0)
             (c-set-offset 'case-label '+)
             (c-set-offset 'arglist-intro '+)
             (c-set-offset 'arglist-close 0)
             (hl-line-mode)
             (skk-mode)
             (auto-complete-mode)
             (flymake-mode)
             )
          )

;; Flymake
(defun flymake-csharp-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 "~/.emacs.d/bin/csharp-checker" (list local-file))))
(add-to-list 'flymake-allowed-file-name-masks
             '("\\.cs$" flymake-csharp-init))
(add-to-list 'flymake-err-line-patterns
             '("cs\(\\([0-9]+\\),\\([0-9]+\\)\)\: \\(error\\|warning\\) \\(.+\\)$" nil 1 2 4))

;; csharpの実行環境
(add-to-list 'quickrun-file-alist '("\\.cs$" . "c#/mono"))
(quickrun-add-command "c#/mono"
                      '((:command . "mono")
                        (:exec    . ("mcs %s" "%c %n.exe"))
                        (:remove  . ("%n.exe")))
                      :mode 'csharp-mode)