【Emacs Tips】 compileコマンドの拡張

Emacsでプログラム書いてると、C-ccで compile できるんやけど、この時に*compilation*っていう特殊バッファが作成されます。でもって、通常は現状のwindowを上下半分に分割して下のwindowに*compilation*バッファが表示されるのやけど、実際コンパイルのログ表示にwindowの半分持ってかれるのはちょっと不便。もっと悪いのは、例えばフレームを左右2分割して2種類のソースファイルを編集している時に compile コマンドを実行すると、compileコマンドを実行したwindowと別のwindowが*compilation*バッファに切り替わってしまうのですわ。どういう事かと言うと…

Screenshotmule1cameracpp

こんな感じ。左のwindowでソースファイルを編集中に compile コマンドを実行すると右のwindowにログが表示されてしまうのですわ。でも右は別のソースとか表示してるからそのまま残しておきたい。あと、この*compilation*バッファを閉じるためには、C-x1とするか C-xo C-xk RET みたいにするしかないっすなぁ。これも不便。
ちゅー事で、*compilation*バッファを現在編集中のソースwindowを分割して表示するようにしたいなぁと思ったわけです。ついでに、*compilation*バッファも簡単に閉じれるようにしたいなぁと。そんなこんなでできたのが以下の関数ですわ。

             ;; 自前compilation関数 (windowを固定化する)
             (defun compilation-open ()
               "*compilation*バッファを表示するwindowをオープンする"
               (interactive)
               (let ((cur-window (selected-window))
                     (com-buffer (get-buffer compilation-buffer-name)))
                 (if (null com-buffer)
                     (setq com-buffer (get-buffer-create compilation-buffer-name)))
                 (let ((com-window (get-buffer-window com-buffer)))
                   (if com-window
                       (select-window com-window)
                     (select-window
                      (split-window (selected-window) (- (window-height) 15) nil)))
                   (switch-to-buffer (get-buffer compilation-buffer-name))
                   (select-window cur-window))))
             (defun compilation-close ()
               "*compilation*バッファを表示しているwindowをクローズする"
               (interactive)
               (let ((com-buffer (get-buffer compilation-buffer-name)))
                 (if com-buffer
                     (let ((com-window (get-buffer-window com-buffer)))
                       (if com-window
                           (delete-window com-window))))))
             (defun my-compile (command &optional comint)
               "*compilation*バッファの表示位置を固定化してcompileコマンドを実行する関数。"
               (interactive
                (list
                 (let ((command (eval compile-command)))
                   (if (or compilation-read-command current-prefix-arg)
                       (read-from-minibuffer "Compile command: "
                                             command nil nil
                                             (if (equal (car compile-history) command)
                                                 ‘(compile-history . 1)
                                               ‘compile-history))
                     command))
                 (consp current-prefix-arg)))
               (unless (equal command (eval compile-command))
                 (setq compile-command command))
               (save-some-buffers (not compilation-ask-about-save) nil)
               (setq compilation-directory default-directory)
               (compilation-open)
               (compilation-start command comint))

my-compileはcompile.elのcompileコマンドを持ってきて、compilation-startの前に*compilation*バッファを開くようにしています。ちょっと強引やけどね。ま、突貫工事で書いたコードやし・・・[E:coldsweats01]
動作のスクリーンショット貼っておきます。
Screenshotmule1cameracpp1

ほらね、こんな感じで左のwindowの下15行分にコンパイルログが表示されてますだ。もちろん、このwindowは*compilation*バッファやから、C-x`で次のエラー箇所にどんどん飛べますダ。あとこのコンパイルウィンドウもすぐに閉じれるようにcompilation-closeコマンドも用意しました。

設定方法

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; cc-modeに入るときに呼び出す hook の設定
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(add-hook ‘c-mode-common-hook
          ‘(lambda ()
             ;; 自前compilation関数 (windowを固定化する)
             (defun compilation-open ()
               "*compilation*バッファを表示するwindowをオープンする"
               (interactive)
               (let ((cur-window (selected-window))
                     (com-buffer (get-buffer compilation-buffer-name)))
                 (if (null com-buffer)
                     (setq com-buffer (get-buffer-create compilation-buffer-name)))
                 (let ((com-window (get-buffer-window com-buffer)))
                   (if com-window
                       (select-window com-window)
                     (select-window
                      (split-window (selected-window) (- (window-height) 15) nil)))
                   (switch-to-buffer (get-buffer compilation-buffer-name))
                   (select-window cur-window))))
             (defun compilation-close ()
               "*compilation*バッファを表示しているwindowをクローズする"
               (interactive)
               (let ((com-buffer (get-buffer compilation-buffer-name)))
                 (if com-buffer
                     (let ((com-window (get-buffer-window com-buffer)))
                       (if com-window
                           (delete-window com-window))))))
             (defun my-compile (command &optional comint)
               "*compilation*バッファの表示位置を固定化してcompileコマンドを実行する関数。"
               (interactive
                (list
                 (let ((command (eval compile-command)))
                   (if (or compilation-read-command current-prefix-arg)
                       (read-from-minibuffer "Compile command: "
                                             command nil nil
                                             (if (equal (car compile-history) command)
                                                 ‘(compile-history . 1)
                                               ‘compile-history))
                     command))
                 (consp current-prefix-arg)))
               (unless (equal command (eval compile-command))
                 (setq compile-command command))
               (save-some-buffers (not compilation-ask-about-save) nil)
               (setq compilation-directory default-directory)
               (compilation-open)
               (compilation-start command comint))
             ;; cc-modeの自前スタイル設定
             (c-add-style "personal" my-c-style t)
             (setq tab-width 4)
             (setq indent-tabs-mode nil)
             (setq completion-mode t)
             ;; compile-windowの設定
             (setq compilation-buffer-name "*compilation*")
             (setq compilation-scroll-output t)
             (setq compilation-read-command t)
             (setq compilation-ask-about-save nil)
             (setq compilation-window-height 10)
             (setq compile-command "make")
             ;; cc-mode内で定義されるキーバインド
             (define-key c-mode-base-map "C-cC-c"   ‘comment-region)
             (define-key c-mode-base-map "C-cC-M-c" ‘uncomment-region)
             (define-key c-mode-base-map "C-ce"      ‘c-macro-expand)
             (define-key c-mode-base-map "C-cc"      ‘my-compile)
             (define-key c-mode-base-map "C-cM-c"   ‘compilation-close)
             (define-key c-mode-base-map "C-cg"      ‘gdb)
             (define-key c-mode-base-map "C-ct"      ‘toggle-source)
             ;; cc-modeに入る時に自動的にgtags-modeにする
           &nbs
p; (gtags-mode t)
             ))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

c-mode-common-hookでmy-compileコマンドとcompilation-open/compilation-closeコマンドを定義しています。ローカルマップでお好きにキーアサインしてくださいな。僕の環境では

C-cc (my-compile)
C-cM-c (compilation-close)

としました。これで、いつも通りC-ccでコンパイル、C-cM-cで*compilation*バッファをクローズできます。便利になりましたわ。もうちょっと綺麗に書きたいんやけど、まぁそれはそのうち。[E:sweat01]

Author: kan
初めてプログラムらしきものを作ったのは幼稚園の時。それから約40年経ち、現在はデジタル回路設計から信号処理、機械学習まで幅広い経験を活かしてシステムアーキテクトとして活動中。超並列処理、デジタル回路とソフトウェアのバランス設計が得意分野。 Linux/Mac/Windows使い。 C/C++を主要言語として、Unity、Qtなどのフレームワーク興味あり。UI/UXデザイン、STL拡張など。 音声処理、画像処理、技術コンサルは仕事でも請け負います。 一般ソフトウェア開発プロセス、医療機器ソフトウェア開発プロセス作成も進行中。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください