emacs - after-change-functions are not executed after buffer modification - emacs

I have added a function to after-change-functions list using this code
(defun test-func ()
(message "foo"))
(add-hook 'after-change-functions 'test-func nil t)
Now whenever i change buffer manually, test-func is getting called. But when i programatically modify the buffer using insert, the contents of buffer are getting updated, but test-func is not getting called.
Any pointers on how to activate test-func everytime buffer is updated?
Update:
I am trying to convert markdown to html and serve that on browser, so that whenever user types some markdown, html will be updated automatically.
Here is original implementation of test-func
(defun impatient-markup-update (&rest args)
"Update html buffer if markup buffer updates."
(save-buffer impatient-markup-buffer)
(with-current-buffer (get-buffer impatient-markup-html-buffer)
(erase-buffer)
(insert (shell-command-to-string
(format "%s %s" impatient-markup-pandoc impatient-markup-buffer)))))

Use sleep-for after the call to message, as a test, to see whether you see the message then.
after-change-functions does not necessarily run your hook in the buffer you expect. And as the doc says:
*Buffer changes made while executing the after-change-functions don't call any before-change or after-change functions. That's because inhibit-modification-hooks is temporarily set non-nil.
Check what else is on that hook, etc. IOW, do a little debugging.

Related

How to bulk copy in org agenda

After an agenda search, I want to bulk copy marked entries.
The bulk action dispatcher only allows to bulk refile. (And I do not want to modify the variable org-refile-keep.)
How does a custom function for this bulk action has to look like?
The org manual gives an example for a custom function in http://orgmode.org/manual/Agenda-commands.html#index-B-1429 but simply replacing org-set-property "CATEGORY" "web" by org-copy does not do the trick, as the function will then ask for the destination for each entry it is executed on.
This answer assumes the original poster wants to copy the entire subtree from the master todo file, rather than the excerpt (redacted version) in the *Org Agenda* buffer.
Mark your entries, hit the letter B, then the letter f, then type org-agenda-bulk-copy-subtree, then hit RET. The original poster may wish to modify the data gathering portion to push the entries to a list, etc.
[CAVEAT: In my testing, it appears that org-agenda-bulk-action destroys/moves the markers (invisible to the naked eye) so it will be necessary to rebuild the *Org Agenda* buffer if any additional work needs to be done with markers leading back to the master todo file. Alternatively, perhaps we could clone/duplicate the *Org Agenda* buffer and work with a temporary buffer so that the original is not altered?]
(defun org-agenda-bulk-copy-subtree ()
"Doc-string"
(interactive)
(or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
(let* ((marker (or (org-get-at-bol 'org-marker) (org-agenda-error)))
(buffer (marker-buffer marker))
(pos (marker-position marker))
(output-buf (get-buffer-create "*RESULTS*")))
(with-current-buffer buffer
(goto-char pos)
(org-back-to-heading t)
(org-copy-subtree))
(with-current-buffer output-buf
(insert org-subtree-clip "\n"))
(unless (get-buffer-window output-buf)
(display-buffer output-buf t))))

How to display file while still in find-file-hook

Currently, I use find-file-hook to invoke a lengthy compilation/checking of that file. I have therefore to wait for some time to actually see the file. What I would like to do instead is to be able to view (not edit) the file already while the checker is running, thus creating the illusion of instantaneous compilation. How can I do this?
Using find-file-hook means your code will run on every file you open; are you
sure you want this? It may make more sense to create a new major or minor mode
for the type of file you want to run your validation on and then use the
corresponding mode hook. For instance, if you wanted to check all .chk files
(with your new major mode inheriting from prog-mode):
(define-derived-mode check-mode prog-mode "Checker")
(add-to-list 'auto-mode-alist '("\\.chk\\'" . check-mode))
(add-hook 'check-mode-hook 'check-mode-computation-hook)
As for the actual hook, this code (going off phils' comment) works for me:
;;; -*- lexical-binding: t -*-
(defun slow-computation ()
(dotimes (i 10000000)
(+ i 1)))
(defun check-mode-computation-hook ()
(let ((cb (current-buffer))
(ro buffer-read-only))
(setq-local buffer-read-only t)
(run-at-time .1 nil
(lambda ()
(with-current-buffer cb
(message "Loading...")
(slow-computation)
(setq-local buffer-read-only ro)
(message "Loaded!"))))))
Note, though, that though this will display the file, emacs will still be frozen
until it finishes its processing, as
emacs doesn't actually support multithreading. To get around this, you may
have to use a library like async, deferred, or concurrent.
You should considered using Flycheck which provides async syntax checking for most programming languages and provides a nice API for implementing new/custom checkers.

Don't display *compilation* buffer in Emacs until the process exits with error or warning

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?
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 ()) ....

How to follow the end of *Messages* buffer in Emacs? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In emacs, can I set up the *Messages* buffer so that it tails?
I am playing with Elisp, and I find convenient to have the *Messages* buffer always open in a window in my frame.
I discovered recently that sometimes the buffer stops following the last line in the file. If I want to see the last appended lines in this buffer, I need to go in the buffer and jump to the end manually, with M->. Which quite annoying and disruptive.
I am trying to reproduce the "tail -f" command line, in a buffer. Of course 'auto-revert-tail-mode complains that the *Messages* is not a visited file... As a consequence, this mode does not want to work. But it gave me the idea to add a function hook when the buffer is modified. That function would jump to (point-max) each time that buffer is modified.
Here is my own attempt, invoked from *Messages* buffer, with M-::
(add-hook 'after-change-functions (lambda (s e l) (goto-char (point-max)) nil) nil t)
But it does not work. The (point) remains in the same place while I see the buffer is growing... The lambda function does not produce any error, otherwise it would have been removed from the 'after-change-functions hook and C-h k 'after-change-functions shows it is present.
Any better suggestions?
Modifying the point position from after-change-functions is very dangerous anyway because it can break some types of edit to the buffer (for example, Emacs compresses multiple consecutive messages with the same content). However, for your purposes the post-command-hook is more than sufficient and much safer, so you can just use this:
(add-hook 'post-command-hook
(lambda ()
(let ((messages (get-buffer "*Messages*")))
(unless (eq (current-buffer) messages)
(with-current-buffer messages
(goto-char (point-max)))))))
The hook will make sure the point in *Messages* is at the end of buffer after every command, unless you're currently editing the *Messages buffer itself.
Well I've made my own one with set-window-point.
(defun tail-f-msgs ()
"Go to the end of Messages buffer."
(let ((msg-window (get-buffer-window "*Messages*")))
(if msg-window
(with-current-buffer (window-buffer msg-window)
(set-window-point msg-window (point-max))))))
;; Make the Messages buffer stick to the end.
(add-hook 'post-command-hook 'tail-f-msgs)

ERC - modify incoming messages

I am using the below elisp code to modify incoming messages from ERC
(defun my-modify (msg)
(replace-regexp-in-string "abc" "xyz" msg))
(add-hook 'erc-insert-modify-hook 'my-modify)
I am getting the following error
error in process filter: Wrong number of arguments: (lambda (msg)
(replace-regexp-in-string "abc" "xyz" msg)), 0
I am not sure what's wrong in my previous code, but I was able to modify incoming messages using this code (from http://mwolson.org/projects/emacs-config/erc-init.el)
(defun my-modify (proc parsed)
(let ((msg (erc-response.contents parsed)))
(when (stringp msg)
(setf (erc-response.contents parsed)
(erc-replace-regexp-in-string "abc" "xyz" msg))
nil)))
(add-hook 'erc-server-PRIVMSG-functions 'my-modify)
This works as expected, but what I really wanted was to strip away a particular nick and display only the message. However I don't think that's possible at ERC level. Rather I will have to try it at the buffer level.
Apparently functions invoked from erc-insert-modify-hook do not get the incoming message as an argument, like your code expects.
Quoting http://www.emacswiki.org/emacs/ErcHooks we see:
This hook is run after the actual text is inserted. While it runs, the buffer is narrowed to the inserted text using narrow-to-region. Thus, you can use (point-min) and (point-max) to determine start and end of the inserted text on the modify hooks.
So you should replace in the current buffer instead.