6

私がやりたいことは、compile関数への文字列引数のバッファローカルデフォルト値をインテリジェントに事前設定することです。

現在、compile.el はデフォルトでコマンドとして「make」を使用しています。これは、設定で設定できますcompile-command。その変数をバッファローカルにすることもできます。これは、常に同じ静的値が必要な場合に機能します。

compile-commandしかし、バッファの内容、バッファの名前、ファイルを含むディレクトリの内容 (存在する場合)、および月の満ち欠けに応じて、インテリジェントに選択したいと思います。基本的に、デフォルト値を制御してから、インタラクティブなユーザーがその事前設定値をオーバーライドできるようにします。

私は事前のアドバイスでこれを行うことを望んでいました。しかし、これは私が期待したように機能していません。

advice.el ファイルを読むと、なるほど

function/macro/subr/special-form に N 個の before アドバイス、M 個の around アドバイス、K 個の after アドバイスがあるとします。どのアドバイスも保護されていないと仮定すると、アドバイスされた定義は次のようになります (body-form インデックスは、そのアドバイス クラス内のそれぞれのアドバイスの位置に対応します)。

([macro] lambda <arglist>
   [ [<advised-docstring>] [(interactive ...)] ]
   (let (ad-return-value)
 {<before-0-body-form>}*
       ....
 {<before-N-1-body-form>}*
 {<around-0-body-form>}*
    {<around-1-body-form>}*
      ....
       {<around-M-1-body-form>}*
      (setq ad-return-value
        <apply original definition to <arglist>>)
       {<other-around-M-1-body-form>}*
      ....
    {<other-around-1-body-form>}*
 {<other-around-0-body-form>}*
 {<after-0-body-form>}*
       ....
 {<after-K-1-body-form>}*
 ad-return-value))

これが私に言っていることは、アドバイスされた関数がインタラクティブな場合、「call-interactively」はビフォア アドバイスまたはその他のアドバイスを呼び出す前にインタラクティブ フォームを呼び出すということです。

そして、アドバイスを に追加するとcompile、私が観察した動作がこれを確認します。アドバイスは、インタラクティブ フォームが処理された後に呼び出されます。インタラクティブなフォームは、コンパイルに使用する文字列を提案してから私のアドバイスがそれを推測して事前に設定する機会を得る.

そう...

  • インタラクティブフォームの前にコードを実行するにはどうすればよいですか? アドバイスはこれを行うことができますか?アドバイスではない場合、何か他のものはありますか?また
  • compile-command任意のバッファを動的に事前設定するにはどうすればよいですか?

アイデアを歓迎します。

4

5 に答える 5

5

compile-commandは文字列である必要はありません。コンパイル関数はそれを評価するので、バッファーに固有の文字列、または時刻などに依存する文字列を返す関数にすることができます。

(setq compile-command (lambda () (if (eq phase-of-moon 'waning) 
                                     "make -DWANING=1" 
                                    "make -DWANING=0")))

また、特定のニーズにはおそらく役に立たないかもしれませんが、ファイル変数セクションでいつでもcompile-commandを定義できます。

/* -*- compile-command: "make -DFOO"; -*- */

また

// Local Variables:
// compile-command: "make -DSOMETHING_SPECIAL"
// End:

compile-commandは、実際にはマニュアルのファイル変数の例として使用されています。

于 2012-12-06T23:29:49.433 に答える
5

compile-command1 つのオプションは、次のようなモード フックで変数を設定することです。

(add-hook 'c++-mode-hook 'my-c++-set-compile-command)
(defun my-c++-set-compile-command ()
   (setq (make-local-variable 'compile-command) (format "gmake %s" (buffer-file-name))))

現在のコンパイル行を微調整する特殊なコマンド (デバッグ フラグ、最適化フラグなどのオン/オフを切り替える) を追加し、それらのコマンドをミニバッファー内の便利なキーストロークにバインドすることがあります。

フォームの前にアドバイスを追加することに関しては、必要なインタラクティブなフォームを持つinteractiveアドバイスを (前または前後に) 作成する必要があります。advice.el ライブラリからの例:

;;(defadvice switch-to-buffer (around confirm-non-existing-buffers activate)
;;  "Switch to non-existing buffers only upon confirmation."
;;  (interactive "BSwitch to buffer: ")
;;  (if (or (get-buffer (ad-get-arg 0))
;;          (y-or-n-p (format "`%s' does not exist, create? " (ad-get-arg 0))))
;;      ad-do-it))
于 2010-11-20T17:39:55.677 に答える
4

ああ、私が何をしたか知っていますか?私は斜めの戦略を使用しました。

私はグローバルに C-xC-e を に設定しましたcompile。アドバイスを使用する代わりに、 をラップする関数を定義し、compileC-xC-e をそのにバインドしました。ラッパー内で、コンパイル コマンドを推測します。

(defun cheeso-invoke-compile-interactively ()
  "fn to wrap the `compile' function.  This simply
checks to see if `compile-command' has been previously guessed, and
if not, invokes `cheeso-guess-compile-command' to set the value.
Then it invokes the `compile' function, interactively."
  (interactive)
  (cond
   ((not (boundp 'cheeso-local-compile-command-has-been-set))
(cheeso-guess-compile-command)
(set (make-local-variable 'cheeso-local-compile-command-has-been-set) t)))
  ;; local compile command has now been set
  (call-interactively 'compile))

そして、推測関数は次のようになります。

(defun cheeso-guess-compile-command ()
  "set `compile-command' intelligently depending on the
current buffer, or the contents of the current directory."
  (interactive)
  (set (make-local-variable 'compile-command)
   (cond
    ((or (file-expand-wildcards "*.csproj" t)
     (file-expand-wildcards "*.vcproj" t)
     (file-expand-wildcards "*.vbproj" t)
     (file-expand-wildcards "*.shfbproj" t)
     (file-expand-wildcards "*.sln" t))
     "msbuild ")

    ;; sometimes, not sure why, the buffer-file-name is
    ;; not set.  Can use it only if set.
    (buffer-file-name
     (let ((filename (file-name-nondirectory buffer-file-name)))
       (cond

    ;; editing a .wxs (WIX Soluition) file
    ((string-equal (substring buffer-file-name -4) ".wxs")
     (concat "nmake "
         ;; (substring buffer-file-name 0 -4) ;; includes full path
         (file-name-sans-extension filename)
         ".msi" ))

    ;; a javascript file - run jslint
    ((string-equal (substring buffer-file-name -3) ".js")
     (concat (getenv "windir")
         "\\system32\\cscript.exe c:\\cheeso\\bin\\jslint-for-wsh.js "
         filename))

    ;; something else - do a typical .exe build
    (t
     (concat "nmake "
         (file-name-sans-extension filename)
         ".exe")))))

    (t
     "nmake "))))
于 2010-11-20T16:48:00.087 に答える
1

以下は、ワイオミング大学の厚意によりコンパイル コマンドをインテリジェントに選択する、私が使用しているコードです。C, C++現在、 、 、に設定していFortranます。必要に応じてさらに追加できます。C++拡張子を持つプログラミングを開いて実行するM-xcompileと、コンパイル コマンドが吐き出されg++ -Wall currentfilename.cpp -o currentfilename -std=c++14ます。あとは を打つだけenterです。

;; M-x compile smarter in order to guess language
(require 'compile)
(defvar compile-guess-command-table
  '((c-mode       . "gcc -Wall -g %s -o %s -lm")
    (c++-mode     . "g++ -Wall %s -o %s -std=c++14")
    (fortran-mode . "gfortran -C %s -o %s")
    ))

(defun compile-guess-command ()
  (let ((command-for-mode (cdr (assq major-mode
                                     compile-guess-command-table))))
    (if (and command-for-mode
             (stringp buffer-file-name))
        (let* ((file-name (file-name-nondirectory buffer-file-name))
               (file-name-sans-suffix (if (and (string-match "\\.[^.]*\\'"
                                                             file-name)
                                               (> (match-beginning 0) 0))
                                          (substring file-name
                                                     0 (match-beginning 0))
                                        nil)))
          (if file-name-sans-suffix
              (progn
                (make-local-variable 'compile-command)
                (setq compile-command
                      (if (stringp command-for-mode)
                          ;; Optimize the common case.
                          (format command-for-mode
                                  file-name file-name-sans-suffix)
                        (funcall command-for-mode
                                 file-name file-name-sans-suffix)))
                compile-command)
            nil))
      nil)))


;; Add the appropriate mode hooks.
(add-hook 'c-mode-hook       (function compile-guess-command))
(add-hook 'c++-mode-hook     (function compile-guess-command))
(add-hook 'fortran-mode-hook (function compile-guess-command))
于 2015-04-18T04:21:50.833 に答える