Emacs/Emacs Lisp:我可以在交互式表单之前插入建议吗?或者如何智能地预先设置编译命令?

Che*_*eso 6 emacs elisp defadvice advising-functions

我想要做的是智能地为compile函数的字符串参数预先设置缓冲区本地默认值.

现在compile.el默认使用"make"作为命令.我可以通过设置来设置它compile-command.我甚至可以将变量缓冲区本地化.如果我想要相同的静态值,那就行.

但我想compile-command根据缓冲区的内容,缓冲区的名称,文件的包含目录的内容(如果有的话)以及月亮的相位来智能地选择.基本上我想控制默认值,然后允许交互式用户覆盖该预设值.

我希望通过以前的建议来做到这一点.但这并不像我预期的那样有效.

阅读advice.el文件,我明白了

假设一个函数/宏/子/特殊形式有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))
Run Code Online (Sandbox Code Playgroud)

这对我说的是,当建议的函数是交互式的时,`call-interactively'在调用before建议或任何建议之前调用交互式表单.

而且,当我添加建议时compile,我观察到的行为证实了这一点.处理交互式表单后将调用该通知.交互式表单建议用于编译的字符串,我的建议有机会猜测它应该是什么之前,并预先设置它.

所以...

  • 如何在交互式表单之前运行我的代码?可以建议吗?如果不是建议,还有其他什么?要么
  • 如何compile-command为任何缓冲区动态预设?

想法赞赏.

Tre*_*son 5

一种选择是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))))
Run Code Online (Sandbox Code Playgroud)

我有时会添加专门的命令来调整当前的编译行(打开/关闭调试标志,优化标志等),然后将这些命令绑定到迷你缓冲区中的方便按键.

关于在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))
Run Code Online (Sandbox Code Playgroud)


小智 5

compile-command不必是字符串.编译函数可以避免它,因此它可以是一个函数,它返回一个特定于缓冲区的字符串,或者取决于一天中的时间等等:

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

此外,虽然可能对您的特定需求没有用,但您始终可以在文件变量部分中定义compile-command:

/* -*- compile-command: "make -DFOO"; -*- */
Run Code Online (Sandbox Code Playgroud)

要么

// Local Variables:
// compile-command: "make -DSOMETHING_SPECIAL"
// End:
Run Code Online (Sandbox Code Playgroud)

compile-command实际上用作手册中文件变量的示例.


Che*_*eso 4

啊,你知道我做了什么吗?我使用了倾斜策略。

我已将 C-xC-e 全局设置为compile。我没有使用建议,而是定义了一个包装 的函数compile,然后将 C-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))
Run Code Online (Sandbox Code Playgroud)

猜测函数是这样的:

(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 "))))
Run Code Online (Sandbox Code Playgroud)