开发者

Using Emacs, is it possible to pin the compilation command to a specific buffer/directory?

开发者 https://www.devze.com 2023-04-11 11:00 出处:网络
Right now I am using the following to compile, when I\'m in for example main.cpp C-x b Makefile RET M-x compile RET RET

Right now I am using the following to compile, when I'm in for example main.cpp

C-x b Makefile RET M-x compile RET RET

I actually have M-x compile as a keyboard shortcut, but the problem is I would really like not having to go through all that trouble to simply run my Makefile.

I need to visit Makefile to make sure the compile command is executed using the same directory. Is there any way to pin the directory so I can simply go M-x compile RET RET?

开发者_JAVA百科

Best regards


Use recompile instead. C-u M-x recompile will let you edit the compile command first. Either way the compile will work out of the directory the last compile was done in.


See my answer here

Directory local variables provide an easy way to trigger the compile from a parent directory of any source file in a subdirectory.


I run emacs primarily on windows.
When I have a makefile that is in a parent directory of a C module, I use this as the compile command:

cd .. && nmake <arguments here>

for example:

cd .. && nmake CONFIG=Debug PLATFORM=x64 target

Beyond that, I find that specifying the make command line that I want to run for various modules is sort of a pain. I wanted a way to attach the default compile command to the buffer being edited. So I wrote a little elisp to handle that job. I figured to insert into the header comments of each buffer a line that would stipulate my preferred compile command, like this:

compile: cd .. && nmake CONFIG=Debug PLATFORM=x64 target

And then have a piece of elisp run, before I invoke M-x compile that grabs the line and proposes it as the compile command I would like to run.

This defun pulls a line out of the header comments:

(defun cheeso-c-get-value-from-comments (marker-string line-limit)
    "gets a string from the header comments in the current buffer.

This is used to extract the compile command from the comments. It
could be used for other purposes too.

It looks for \"marker-string:\" and returns the string that
follows it, or returns nil if that string is not found.

eg, when marker-string is \"compile\", and the following
string is found at the top of the buffer:

     compile: cl.exe /I uthash

...then this command will return the string

     \"cl.exe /I uthash\"

It's ok to have whitespace between the marker and the following
colon.

"
  (let (start search-limit found)
    ;; determine what lines to look in
    (save-excursion
      (save-restriction
        (widen)
        (cond ((> line-limit 0)
               (goto-char (setq start (point-min)))
               (forward-line line-limit)
               (setq search-limit (point)))
              ((< line-limit 0)
               (goto-char (setq search-limit (point-max)))
               (forward-line line-limit)
               (setq start (point)))
              (t                        ;0 => no limit (use with care!)
               (setq start (point-min))
               (setq search-limit (point-max))))))

    ;; look in those lines
    (save-excursion
      (save-restriction
        (widen)
        (let ((re-string
               (concat "\\b" marker-string "[ \t]*:[ \t]*\\(.+\\)$")))
          (if (and start
                   (< (goto-char start) search-limit)
                   (re-search-forward re-string search-limit 'move))

              (buffer-substring-no-properties
               (match-beginning 1)
               (match-end 1))))))))

Ok, now I need something to invoke that before I invoke compile.

(defun cheeso-invoke-compile-interactively ()
  "fn to wrap the `compile' function.  This simply
checks to see if `compile-command' has been previously set, 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))

Then of course, the defun that guesses the compile command:

(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
        (buffer-file-name
         (let ((filename (file-name-nondirectory buffer-file-name)))
           (cond
            ;; editing a C-language source file - check for an
            ;; explicitly-specified command
            ((string-equal (substring buffer-file-name -2) ".c")
             (let ((explicit-compile-command
                    (cheeso-c-get-value-from-comments "compile" 34)))
               (or explicit-compile-command
                   (concat "nmake " ;; assume a makefile exists
                           (file-name-sans-extension filename)
                           ".exe"))))

            ;; editing a makefile - just run nmake
            ((string-equal (substring buffer-file-name -8) "makefile")
             "nmake ")

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

The final bit is to bind C-x C-e , normally bound to compile, to the wrapper defun:

(global-set-key "\C-x\C-e"  'cheeso-invoke-compile-interactively)

Now, when I do C-x C-e in the buffer, it searches for the compile command, and proposes to me the command that it finds. I can edit the proposed compile command, then press ENTER and run it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号