I am looking for a way to have the Emacs compilation buffer triggered by M-x compile, M-x recompile or some compile on save script only appear when the compilation exits either with an error or a warning.
Note that I am not looking for a way to close the compile buffer if there are no errors or warnings as described in [1]. No I want the buffer to never appear until the compilation is fully finished and only appear if there is an error or warning to display.
The reasons are simple: The flickering compile buffer is disturbing and rearranges the position of the code on the screen. This becomes more annoying if you have compile on save turned on.
The compile buffer contains many different types of compile processes from make to pdflatex so it would be great if the function which determines whether the buffer should be displayed works across the board.
[1] emacs compile buffer auto close?
To run make or another compilation command, type M-x compile . This reads a shell command line using the minibuffer, and then executes the command by running a shell as a subprocess (or inferior process) of Emacs.
Emacs can run compilers for languages such as C and Fortran, feeding the compilation log into an Emacs buffer. It can also parse the error messages and show you where the errors occurred.
Compilation mode turns each error message in the buffer into a hyperlink; you can move point to it and type RET, or click on it with the mouse (see Mouse References), to visit the locus of the error message in a separate window. The locus is the specific position in a file where that error occurred.
To execute a file of Emacs Lisp code, use M-x load-file . This command reads a file name using the minibuffer and then executes the contents of that file as Lisp code. It is not necessary to visit the file first; in any case, this command reads the file as found on disk, not text in an Emacs buffer.
Looks like you can achieve what you want through temporarily disabling display-buffer
across compilation-start
.
This is a combination of what sds said and something posted on the comments @ here
The comment there had a nasty problem with point jumping in the original source buffer that I appear to have worked out by also blocking set-window-point
and goto-char
. It feels like a dirty hack, but is working so far. YMMV!
(defun brian-compile-finish (buffer outstr)
(unless (string-match "finished" outstr)
(switch-to-buffer-other-window buffer))
t)
(setq compilation-finish-functions 'brian-compile-finish)
(require 'cl)
(defadvice compilation-start
(around inhibit-display
(command &optional mode name-function highlight-regexp))
(if (not (string-match "^\\(find\\|grep\\)" command))
(flet ((display-buffer)
(set-window-point)
(goto-char))
(fset 'display-buffer 'ignore)
(fset 'goto-char 'ignore)
(fset 'set-window-point 'ignore)
(save-window-excursion
ad-do-it))
ad-do-it))
(ad-activate 'compilation-start)
Now you should see that all compile buffers will only be shown if outstr
doesn't return a successful finish status OR the invoked command started with "find" or "grep."
I edited @assem's answer to use cl-letf
instead of flet
.
(defun brian-compile-finish (buffer outstr)
(unless (string-match "finished" outstr)
(switch-to-buffer-other-window buffer))
t)
(setq compilation-finish-functions 'brian-compile-finish)
(defadvice compilation-start
(around inhibit-display
(command &optional mode name-function highlight-regexp))
(if (not (string-match "^\\(find\\|grep\\)" command))
(cl-letf ((display-buffer #'ignore)
(set-window-point #'ignoreco)
(goto-char #'ignore))
(save-window-excursion
ad-do-it))
ad-do-it))
(ad-activate 'compilation-start)
(provide 'only-display-compile-on-error)
The function compilation-start
calls display-buffer
on the compilation buffer. This should give you all the control you need.
I.e., you need to customize one of the action variables (display-buffer-overriding-action
et al) so that it will handle compilation buffers specially buy displaying it in a separate frame and not displaying the frame itself.
Then you need to customize your compilation-filter-hook
so that, whenever a warning or an error is inserted into the compilation buffer, the compilation buffer is displayed visibly (e.g., by popping up the aforementioned separate frame). Don't forget to bind your action variable to nil
there!
assems answer has been overtaken by events, somewhat.
Emacs core, in their wisdom have decided to deprecate flet
.
The suggested alternative is cl-flet
. However, as discussed in this post, this seems to be lexically scoped rather than dynamically scoped. We explicitly want dynamic scoping.
Should `flet` be replaced with `cl-flet` or `cl-letf` ?
This page suggests replace flet
to noflet
, a third-party library.
This appears to only support the definition of functions and their bodies.
So the flet
in assem's answer becomes
(noflet ((display-buffer ()) ....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With