I want to automatically rename the buffer name of compilation mode. The default name is *compilation*. Let's call my new compilation command my-compile. So supposing we run my command like this:

M-x my-compile <RET> make -j8

I want to automatically rename the compilation buffer to *compilation-make*.

I am able to rename the buffer but I am stuck in getting the argument from the command compile.

Here is the code I am currently using:

(defun my-compile ()
  (require 'compile)
  (command-execute 'compile)
  (pop-to-buffer (get-buffer "*compilation*"))
  (with-current-buffer (get-buffer "*compilation*" )
    (rename-buffer (concatenate 'string "compile-" "GET_ARG_FROM_COMPILE"))))

In this code now I need to replace the string GET_ARG_FROM_COMPILE to a function that reads the argument passed to (command-execute 'compile).


In this specific case, you could grab the argument from the history that compile uses. But a more generic solution is to separate prompting from the argument from actually running the function. Build a command which has the same interactive specification as the one you want to run, but that just returns its list of arguments. Call that command, then call the underlying function with the list of arguments. Reuse the list of arguments as you see fit.

(defun my-compile ()
  (let* ((fake-command `(lambda (&rest args)
                           ,(interactive-form 'compile)
         (args (call-interactively fake-command))
         (command-string (nth 0 args))
         (first-word (save-match-data
                        (if (string-match "\\S-+" command-string)
                            (match-string 0 command-string)
    (apply 'compile args)
    (pop-to-buffer (get-buffer "*compilation*"))
    (rename-buffer (concat "*compile-" first-word "*"))
  • strange, but using the elisp language tag on your code block doesn't seem to work with the backquote, but lisp does? – Tyler Jun 20 at 21:12
  • @Tyler Right, because it's lang-lisp or lang-el, not lang-elisp. I keep forgetting. – Gilles Jun 20 at 21:26
  • I can't keep them straight either, but just plain lisp seems to work alright – Tyler Jun 20 at 21:47
  • I think you forgot to add the renaming logic in your function: (pop-to-buffer (get-buffer "*compilation*")) (rename-buffer (concat "*compile-" first-word "*")) after (apply 'compile args), please review my edit. – rph Jun 21 at 9:15

There may be a more elegant way to do this, but you could just wrap the call to compile in a (let ...) form, and use that to collect the argument for (compile):

(defun my-compile ()
  (let* ((COMMAND (read-from-minibuffer "Compile command: "))
         (SUF (progn (string-match "\\w+" COMMAND)
                     (match-string 0 COMMAND))))
    (compile COMMAND)
    (pop-to-buffer (get-buffer "*compilation*"))
    (rename-buffer (concat "*compile-" SUF "*"))))

From your question it looks like you just want to grab the first word of the compile command (make), and not include any subsequent arguments (-j8), so I've used string-match to exclude everything past the first word.

  • This answers what I asked, but it does not provide auto-complete as in compile. For instance, if I type M-x compile <RET> make -f Make <TAB>, the command compile would auto-complete based on the working directory and common Linux commands. As @Gilles mentioned, it is better to create an interactive command with same specification as the command we wanna wrap. – rph Jun 21 at 9:12

GET_ARG_FROM_COMPILE can be (car (alist-get 'compile command-history)), it works because (command-execute 'compile) puts the command into the history, I guess. You can use M-x list-command-history or C-h v command-history to inspect the command history.

Personally, if I have such need (I mean my-compile), I will simply ask the command name explicitly like @Tyler's answer since it's simple and reliable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.