If I have some unsaved buffers, when does kill-emacs-hook call?
Scenario A
User invoke kill-emacs.
Prompt for saving modified buffers.
Cancel kill-emacs operation (C-g).
User continues to use emacs.
Scenario B
User invoke kill-emacs.
Prompt for saving modified buffers.
All modified buffers saved
Emacs killed.
Running kill-emacs-hook is the first thing which kill-emacs does.
Both of your scenarios are invalid. If the user directly invokes kill-emacs the user is not prompted to save buffers (that's only done if save-buffers-kill-emacs is called).
For the latter, if the user aborts the query to save buffers, or if any of the members of kill-emacs-query-functions return nil, then kill-emacs is never called.
I ran this line of code and exited emacs to test what was happening.
(add-hook 'kill-emacs-hook (lambda () (message "test")))
The conclusion was that "test was" not printed in Scenario A but was printed in Scenario B between steps 3. and 4.
There were a few more lines of output after the printing of "text" in example B but there was no more user input.
Related
I have this code:
(defun do-repeated-work (args)
"some work that need executed repeatedly"
(message nil)
(message "doing some repeated work, arg = %s, current time = %s" args (format-time-string "%H:%M:%S")))
(setq timer (run-with-idle-timer 3 t 'do-repeated-work (list "arg1" "arg2" "arg3")))
The purpose of the code above is: print a line of message in minibuffer repeatedly every three seconds. But I found that, when the function do-repeated-work works again, the old message in emacs minibuffer cannot be cleared, so the new message cannot be displayed. I have already tried the way mentioned in this question: how to empty or clear the emacs minibuffer?, but it doesn't work.
My Emacs version is 25.3
How to cope with this problem?
You've made an incorrect assumption, and consequently your problem isn't what you think it is.
The purpose of the code above is: print a line of message in minibuffer repeatedly every three seconds.
That's not what it does.
You've used run-with-idle-timer which will run one time once Emacs has been idle for 3 (in this case) seconds, and will not repeat until some non-idle activity has taken place -- after which it will again run once Emacs has become idle for 3 seconds.
See C-hf run-with-idle-timer
If you want something which repeats at a consistent interval, use run-with-timer.
I have not been able to get the minibuffer-exit-hook to play nice with read-string. As far as I can tell, I should no longer be in the minibuffer after finishing up with read-string. However, the condition (minibufferp) says I'm still in the minibuffer even though read-string finished. read-string is written in C, so I can't add the hook there (i.e., at the tail end of the read-string function).
"Documentation [minibuffer-exit-hook]: Normal hook run just after exit from minibuffer.
[After thinking a little more about this, I'm pretty sure it's a bug -- so I filed a bug report: bug#16524. As I learn more, I'll update this thread.
(defun test ()
(interactive)
(read-string "Prompt: " "testing"))
(add-hook 'minibuffer-exit-hook (lambda ()
(cond
((minibufferp)
(message "Focus is still in the minibuffer: %s" (buffer-name)))
(t (message "Contragulations -- focus is now in: %s." (buffer-name))))))
The doc string is not exact; that's all. The hook is run when inputting text in the minibuffer is done (no longer possible). The buffer that is current when it is run is still the minibuffer. (And that's the way it should be, FWIW.)
Note that the Elisp manual puts it slightly differently (but again, not very precisely):
This is a normal hook that is run whenever the minibuffer is
entered.
("Whenever", meaning about the same time as, not necessarily after.)
If you want to do something after every use of read-string in your code, then define a function that does the following: first (read-string...), then whatever you want done next. And use that function.
If you need to affect also other invocations of read-string, besides those you write in your code, then advise function read-string to perform whatever action after the vanilla code finishes.
For example:
(defadvice read-string (after fooness activate)
(message "buffer: %S" (current-buffer)))
[Note: Yes, you can advise primitives (functions written in C). You used to even be able to advise special forms, but they regressively took away that feature.]
Running a hook after you truly exited the minibuffer is rather pointless: you could be in any kind of buffer (since minibuffer use can be triggered from anywhere) and you hence know very little about the current context (unless you use a buffer-local exit-hook, I guess).
If you want to run a hook when the selected window changes, then your best option is probably to use a post-command-hook that stores the current selected-window in an auxiliary variable and uses it to compare to the previous selected-window.
I am trying to stop the simple-httpd server with its command httpd-stop when I type the C-x C-c command (save-buffers-kill-terminal to quit emacs), cause I would like to get rid of the "Active processes exist; kill them and exit anyway? (yes or no)" message every time I type C-x C-c.
To achieve my aim, I was thinking about writing a hook like:
(add-hook 'save-buffers-kill-terminal
(lambda () (httpd-stop)
))
But it did not work. I continue to get the message "Active processes exist; kill them and exit anyway? (yes or no)" when I type C-x C-c.
How can I achieve my goal?
Thanks!
There is no hook named save-buffers-kill-terminal.
There's a function by that name, but hooks don't automatically exist for every function (the advice mechanism does facilitate that in effect, but you don't need that here (edit: or maybe you do; see below)).
A hook only exists if there is code which explicitly runs it with run-hooks, or similar (e.g. C-u C-h a run.*hook RET). Or more specifically, you can add-hook with any arbitrary variable, but it will never function as a hook unless something runs it.
In general you would use either of kill-emacs-hook (if the callback does not need to interact with the user), or kill-emacs-query-functions if interaction could be necessary. See the help of each of those variables for details.
Edit:
In the case of active processes, a different mechanism is needed, as these queries happen before either of those hooks are run.
If you just want to avoid the query and let the process be killed, you can use set-process-query-on-exit-flag. This sets a per-process flag which determines whether or not this query will happen:
set-process-query-on-exit-flag is a built-in function in `process.c'.
(set-process-query-on-exit-flag PROCESS FLAG)
Specify if query is needed for PROCESS when Emacs is exited.
If the second argument FLAG is non-nil, Emacs will query the user before
exiting or killing a buffer if PROCESS is running. This function
returns FLAG.
You would probably arrange this when you started the process (assuming you have some code which starts httpd), obtaining PROCESS with either (get-process NAME) or (get-buffer-process BUFFER). I'm not using this httpd library, so I don't know specifically what you'll need here.
If you definitely want to call a graceful shut-down function like httpd-stop, I think you'll need to do something custom.
(defadvice save-buffers-kill-emacs (before my-httpd-auto-stop)
(when (httpd-is-running-p) ;; not a real predicate
(httpd-stop)))
(ad-activate 'save-buffers-kill-emacs)
You'll have to figure out what to use in place of my hypothetical httpd-is-running-p, to establish whether or not to call the stop function.
Note that this would run before any other queries, so you might stop httpd this way but then decide not to kill emacs after all (but that sort of thing is possible regardless).
Edit: Alternatively, as it is apparently safe to call this stop function whether or not httpd is running, you could use the following (including an added test to see whether or not httpd-stop is defined, as calling it will be an error otherwise, and I'm not sure how you load the library):
(defadvice save-buffers-kill-emacs (before my-httpd-auto-stop)
(when (fboundp 'httpd-stop)
(httpd-stop)))
(ad-activate 'save-buffers-kill-emacs)
I have a series of functions that execute normally when a file is opened or when a particular mode is activated. The find-file-hook doesn't get triggered if the file is already open, when I try to open a file that is already open (e.g., in another frame), Emacs correctly switches to that buffer. However, under that scenario my custom functions do not activate because there is no trigger. I don't think the standard hooks cover a situation like this one.
What is the alternative, to find-file-hook when a buffer file already exists?
I'd try to use advice for this. You can tell whatever find-file command you use to make sure your tabbar is set up correctly. Simple example, since I use ido-find-file:
(defun my-find-file ()
(interactive)
(call-interactively 'ido-find-file))
(defadvice my-find-file (after do-something)
(message "doing stuff"))
(ad-activate 'my-find-file)
If this does not happen very often, you could just reopen the file to trigger the find-file-hook. To do so, just type C-x C-v <enter>.
I need a check for whether or not a process is still running in my emacs term; started via (term "/bin/bsh") and then renamed to, eg. term-A.
I have tried (term-check-proc "term-A"), but it doesn't show what I what I need, or at least, I don't see how I can use it.
Trying to chase it down by a shell call to ps afx (or the like), is problematic if there is more than one emacs term active and running the same program, (which in my case, is quite quite possible)...
I really need to know if a process in a specific emacs term buffer, term-A, is running or not.
You can get a buffer's process with get-buffer-process:
(get-buffer-process "*shell*") -> #<process shell>
(get-buffer-process "*scratch*") -> nil
After I exit the shell in *shell*, I get nil for that buffer too.