[英]Emacs/Emacs Lisp: can I insert advice before interactive form? or how to intelligently pre-set the compile-command?
我想做的是為compile
函數的string參數預先設置一個本地緩沖區默認值。
現在,compile.el默認使用“ make”作為命令。 我可以通過設置compile-command
來設置。 我什至可以將該變量設置為局部緩沖區。 如果我一直想要相同的靜態值,那總是可行的。
但是,我想根據緩沖區的內容,緩沖區的名稱,文件的包含目錄的內容(如果有)以及月相來聰明地選擇compile-command
。 基本上,我想控制默認值,然后允許交互式用戶覆蓋該預設值。
我希望可以在事前咨詢。 但是,這不符合我的預期。
讀advice.el文件,我明白了
假設一個函數/宏/ subr /特殊形式有N條前建議,M條周圍建議和K條后建議。 假設沒有任何建議受到保護,則其建議定義將如下所示(體形索引對應於該建議類別中相應建議的位置):
([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))
這對我說的是,當建議的功能是交互式的時,“調用交互式”將在調用之前的建議或任何建議之前調用交互形式。
並且,當我添加compile
建議時,我觀察到的行為證實了這一點。 處理交互式表單后 ,將調用建議。 交互式表單會在我的建議有機會猜測並預先設置之前,建議用於編譯的字符串。
所以...
compile-command
? 想法表示贊賞。
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用作文件變量的示例。
一種選擇是在模式掛鈎中設置變量compile-command
,例如
(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))
啊,你知道我做了什么嗎? 我采用了傾斜策略。
我已全局設置C-xC-e進行compile
。 我沒有使用建議,而是定義了一個包裝compile
的函數,然后將C-xC-e綁定到該函數。 在包裝器中,我猜出了compile命令。
(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 "))))
這是我正在使用的一些代碼,這些代碼可以智能地選擇懷俄明大學的編譯命令。 我目前已經為C, C++
和Fortran
設置了它。 您可以添加更多以滿足您的需求。 如果打開具有C++
擴展名的程序並執行Mx compile ,則編譯命令將彈出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))
根據手冊,您可以通過在建議中包含交互形式來簡單地覆蓋函數的交互形式。 我認為您不能修改或包裝現有的交互式表單,而只能完全覆蓋它。
http://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Advice.html
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.