I'm using "M-x compile" several times a day with the following in my ~/.emacs:

(setq compile-command "cd ~/my-dev/linux_build/ && killall gdb ; ~/my-dev/someStuff/.git/hooks/pre-commit; mv -f ../bin/my-exe /tmp 2>&1; echo ---; make -j$(nproc) APP=my-exe MODE=debug SOMEOPTION=value && date")

The main problem is that sometimes I don't want "SOMEOPTION=value" - other times I want it (I know I can just use the cursor keys to change the command before hitting enter, but I'm looking for an even faster/quicker way). So, the question is:

Is there a way to modify "M-x compile" such that it by default runs without SOMEOPTION=value and using just a single key after "M-x compile", it runs with SOMEOPTION=value? Maybe it would be nice also to be able to switch between 2 makefiles, again - using just a single keypress, e.g. the following 3 tasks should be easy and fast/quick to switch between:

  1. "M-x compile + enter" (default): Runs the usual command without SOMEOPTION=value, i.e. cd ~/my-dev/linux_build/ && killall gdb ; ~/my-dev/someStuff/.git/hooks/pre-commit; mv -f ../bin/my-exe /tmp 2>&1; echo ---; make -j$(nproc) APP=my-exe MODE=debug && date
  2. "M-x compile + S": Runs the usual command WITH SOMEOPTION=value, i.e: cd ~/my-dev/linux_build/ && killall gdb ; ~/my-dev/someStuff/.git/hooks/pre-commit; mv -f ../bin/my-exe /tmp 2>&1; echo ---; make -j$(nproc) APP=my-exe MODE=debug SOMEOPTION=value && date
  3. "M-x compile + M": Runs everything but using a different makefile, i.e: cd ~/my-dev/linux_build/ && killall gdb ; ~/my-dev/someStuff/.git/hooks/pre-commit; mv -f ../bin/my-exe /tmp 2>&1; echo ---; make -j$(nproc) -f makefileAlternative APP=my-exe MODE=debug SOMEOPTION=value && date
  4. (maybe something else here in the future, with a relevant keystroke after "M-x compile")

As I'm not very good at emacs programming I'm asking to learn, so I also highly appreciate a few words for background information, e.g. why a solution is good or why this cannot be achieved (if it cannot, but I'm guessing there's a way to do this). I hope some of you can help, I would appreciate it a lot as I do this many times per day...

EDIT: Based on the answer by lawlist, I've updated the first 3 example cases with i.e: "commandline-to-be-executed" in code-tag, I think this should make the question clearer (and the objective is to be able to run each case, with as few keystrokes as possible)...

  • I think you can use history for that (up arrow to get to last command used).
    – JeanPierre
    Commented Aug 6, 2019 at 14:47
  • No, the arrow keys (up/down/left/right) can be used to change the compile command. But you have to manually find the right spot to insert e.g. SOMEOPTION=value or to remove it... So I don't really see this as a solution...
    – Okay Dokey
    Commented Aug 6, 2019 at 15:42
  • @OkayDokey I think JeanPierre's suggestion is better than you give it credit for. You only need to edit the compile command the first time you want to run a different command. After that the modified command will be in the history and you can get at it again going up or down.
    – Omar
    Commented Aug 7, 2019 at 3:49
  • @JeanPierre and Omar: Sorry, it was a misunderstanding from my side. It was first when Omar wrote that if I change the command, there will be different versions in the history, which can be accessed by the up arrow - and then I need to press up not just to switch line but to go up in the history, that I understood the answer... So thanks both - it was merely a misunderstanding, I didn't knew there was history inside M-x compile, I've misunderstood the answer, thanks both...
    – Okay Dokey
    Commented Aug 7, 2019 at 7:58

1 Answer 1


Inasmuch as the function compile can take a command-line string as the argument, the O.P. may wish to consider setting up some custom functions of commonly used options. Here are a few simple examples:

(defun make ()
"Doc-string for `make'."
  (compile "make"))

(defun make-clean ()
"Doc-string for `make-clean'."
  (compile "make clean"))

(defun make-install ()
"Doc-string for `make-install'."
  (compile "make install"))

(defun hello-world ()
"Doc-string for `hello-world'."
  (compile "while :; do echo \"Hello-World\"; sleep 1; done"))

Here is another example where the function prompts the user to specify a string that is incorporated into the command line:

(defun echo-string ()
"Doc-string for `echo-string'."
  (let* ((string (read-string "STRING:  "))
         (command (concat "while :; do echo \""
                          "\"; sleep 1; done")))
    (compile command)))

Here is another example giving the user 3 choices to select; i.e., a, b or c:

(defun echo-choices ()
"Doc-string for `echo-choices'."
  (let* ((choice (read-char-exclusive "[a]pple | [b]eet | [c]arrot)"))
         (command (concat "while :; do echo \""
                            ((eq choice ?a)
                            ((eq choice ?b)
                            ((eq choice ?c)
                              (user-error "Try again ...")))
                         "\"; sleep 1; done")))
    (compile command)))
  • I can see I haven't been completely clear - therefore I felt I had to update the original question. After the first 3 example cases, I've added "i.e: THE-LINES-TO-BE-EXECUTED"... I think what you've shown here doesn't really solve the problem, with as few as possible keystrokes, to run the mentioned commands... Please see the updated question and sorry if I wasn't clear enough...
    – Okay Dokey
    Commented Aug 6, 2019 at 16:43
  • 3
    I do not believe that trying to modify how M-x compile works is the best solution, sorry. I think that a custom function is the best choice, as it can be tailored to your precise needs. You can have it present options such as (a), (b), (c) -- where the user selects the desired option. You can have it accept universal arguments such that '(4) [C-u] does one thing, and '(16) [C-u C-u] does something else. The sky is the limit if you use your imagination. The answer contains some general examples, including, seeking input from the user with the function read-string.
    – lawlist
    Commented Aug 6, 2019 at 16:50
  • I added another example function (echo-choices) that presents the user with three choices; i.e., (a), (b) and (c) -- each option will modify the command line string accordingly. The function can be bound to just one keyboard shortcut such as (global-set-key [f5] 'echo-choices)
    – lawlist
    Commented Aug 6, 2019 at 17:36
  • The "echo-choices" function is really really nice, thank you very much. I agree, I wasn't particularly looking for a way to modify "M-x compile", if this isn't easily obtainable - but something similar as you presented is also really good. I'll mark as answered, but is it possible to modify the "echo-choices" function so it has a default, e.g. "[b]eet" if the user just presses enter without typing in a/b/c? I suppose that is possible, although I'm not experienced enough (if I press enter it just says "Try again ...")... Thanks for your great valuable help!
    – Okay Dokey
    Commented Aug 7, 2019 at 1:53
  • Sure, just replace (user-error "Try again ...") with "beet" and that will be the default/catchall if you press something other than a, b or c. Or, add a new condition that looks for enter/RET -- ((eq choice ?\C-m) "beet") before the catchall that begins with (t ...)
    – lawlist
    Commented Aug 7, 2019 at 2:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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