NTEmacs 内で,cmd.exe とか。

どもです。

ヘッダファイルで宣言したメンバ関数を .cc ファイル内で再度書くのがめんどいです。

なんか便利なのないかなーと探してみたけど,見つからなかった。
けどきっとあるはずだ。まぁいいや。
ほいで,下のようなんを書いてみた。

ヘッダファイル内の宣言をリージョンで選択して,
M-x my-c++-mode:decl->def-on-region すると,
適当にでっちあげた関数定義がキルリングないに入るというもの。
うーん,命名ミスった感たっぷりだな。
これで,.cc ファイルへ行って,貼り付ければ万々歳。


※ 追記 2011/05/18
関数名の行末に余分なスペースが入ってしまうのを修正。

(defun my-c++-mode:decl->def-on-region (start end)
  (interactive "r")
  (let ((classname nil)
        (member-funcs nil)
        (ret nil))
    (save-excursion
      (if (re-search-backward "class \\([^ :;\n\r]+\\).*$" nil t 1)
          (setq classname (match-string 1))
        (error "Classname not found")))
    (setq region (buffer-substring start end))
    (dolist (e (split-string region "[;\n]" t))
      (let ((rettype nil) (fname nil))
        (string-match "^[ \t]*\\([^(]+\\) \\([^ (]+.*\\)" e)
        (setq rettype (match-string 1 e)
              fname (match-string 2 e))
        (push (concat rettype " " classname "::" fname "\n{\n}\n")
              member-funcs)))
    (setq ret (reduce (lambda (x y) (concat x "\n" y)) (reverse member-funcs)))
    (kill-new ret)
    (message "copied into kill-ring")))
  • こんなクラスがあったとします。
class Some
{
public:
  void func1();
  int func2();
  const string& func3(int i);
};

ここで,

  void func1();
  int func2();
  const string& func3(int i);

の部分を選択して,M-x my-c++-mode:decl->def-on-region します。
ほいで,.cc ファイルなどへ飛んでペーストすると下記のようになります。
ヤンクと言わないと怒られるかもしれませんが,ヤングではないので大丈夫なはずです。

void Some::func1() 
{
}

int Some::func2() 
{
}

const string& Some::func3(int i) 
{
}


こういうの専用の elisp がありそう,いや,あるはず! なので,
知っていたら教えていただければ大変うれしいです。
できれば cedet 関連以外で。

Qt で,qmake とかするのに,コマンドプロンプトを使うのがつらいです。

それ,QtCreator 使えばできるよ。
まじでかっ!? ほなおしまい。


QtSDK をインストールした際にできる「Qt 4.7.3 for Desktop (MinGW)」という
ショートカットから,コマンドプロンプトを立ち上げて,この中で qmake とか,
mingw32-make したりしているんですが,これが非常にしんどい。
コンパイルエラーを見る際に,どうやって,マウスなしで
スクロールしてさかのぼるのか知らないし,コマンド履歴にも,もひとつ慣れないし。


で,そういえば,NTEmacs 内で,shell-mode でコマンドプロンプトを使うみたいなのを
どっかでみた気がする。ほいで見つかった。
http://sakito.jp/emacs/emacsshell.html#windows-shell
感謝です。


でも,zsh も使いたい。むしろそっちメインだ。
なので,またまたこりもせずに下記のような関数を書いたお。

※ 2011/5/15 21:16 追記

下記ではうまく動きません。現在解決策を模索中。

(defun my-setup-cmd-prompt ()
  "Set up an environment for cmd.exe, execute it, and swith to
buffer *cmd*."
  (interactive)
  (let* ((shell-file-name (executable-find "cmdproxy"))
         (explicit-shell-file-name shell-file-name)
         (file-name-coding-system 'sjis)
         (buffer-file-coding-system 'sjis))
    (switch-to-buffer (get-buffer-create "*cmd*"))
    (shell (get-buffer "*cmd*"))
    (set-buffer-file-coding-system 'sjis)
    (set-buffer-process-coding-system 'sjis-dos 'sjis-dos)))
※ 追記 2011/05/15 (Sun) 22:44 まともに動くように修正。

問題は,cygwin/bin 以下とかにパスが通っていたので,
mingw32-make 経由で,g++ が呼び出されるときに,
cygwin の方の g++ が呼び出されていたとかそんなんです。
あと,念のために shell 関連の変数を *cmd* バッファでローカルにしています。
let だとだめっぽい。さらに,2回設定しているのは,shell 呼んだ後で,
値が変更されてしまっていたので,もっかい設定しました。
とりあえず,これで,qtenv2.bat を実行して,mingw32-make clean, mingw32-make
してビルドできることを確認しました。
また,その後に,C-u M-x shell して,zsh が起動することも確認したので,
たぶん大丈夫かと。> オレ
了解です。> ボク

;; Execute cmd.exe through cmdproxy.exe
(push '("cmdproxy\\.exe$" sjis-dos . sjis-dos) process-coding-system-alist)
(defun my-setup-cmd-prompt ()
  "Set up an environment for cmd.exe, execute it, and swith to
buffer *cmd*."
  (interactive)
  (let ((process-environment (copy-sequence process-environment)))
    (setenv "PATH" (replace-regexp-in-string "[^;]+cygwin[^;]+;" "" (getenv "PATH")))
    (set-buffer (get-buffer-create "*cmd*"))
    (switch-to-buffer (get-buffer "*cmd*"))
    (set (make-local-variable 'shell-file-name) "cmdproxy.exe")
    (set (make-local-variable 'explicit-shell-file-name) "cmdproxy.exe")
    (set (make-local-variable 'shell-name) "cmdproxy.exe")
    (set (make-local-variable 'shell-command-switch) "/c")
    (set (make-local-variable 'w32-quote-process-args) nil)
    (set (make-local-variable 'file-name-coding-system) 'sjis-dos)
    (switch-to-buffer (get-buffer "*cmd*"))
    (shell (get-buffer "*cmd*"))
    (set (make-local-variable 'shell-file-name) "cmdproxy.exe")
    (set (make-local-variable 'explicit-shell-file-name) "cmdproxy.exe")
    (set (make-local-variable 'shell-name) "cmdproxy.exe")
    (set (make-local-variable 'shell-command-switch) "/c")
    (set (make-local-variable 'w32-quote-process-args) nil)
    (set (make-local-variable 'file-name-coding-system) 'sjis-dos)
    (set-buffer-file-coding-system 'sjis-dos)
    (set-buffer-process-coding-system 'sjis-dos 'sjis-dos)
    (auto-complete-mode t)))

これを実行すると,コマンドプロンプトNTEmacs 内で使えるし,
zsh だって使えるし,なかなか便利なのでは。
とりあえず,qtenv2.bat を実行して適当に Qt プロジェクトをビルドしたところまで
は確認したけど,その他はどうなるかわからん。
一応パス関係は設定されているし,日本語が化けないようです。
そもそも cmdproxy 使うの初めてだから,これからこれから。
それでも,C-v,M-v が使えるだけで,そして more を使わなくてすむ,
さらにはインクリメンタル検索だってできる,それらだけでもすばらしいではないか!!


記念のスクリーンショットです。
これとってみて気づいたけど,help がエコーバック? されているなぁ。
ま,ぼちぼち直していきますたい。