I'm trying to write an emacs function that executes a shell command every 5 seconds. However, I can't get the pause to work. Here's what I have:
(while '(test)
(insert (format "echo hello"))
(comint-send-input))
(sleep-for 0 5000)
I suspect that the sleep is ignored for reasons related to functional evaluation of Lisp. Any advice on how to get the pause to occur after each command evaluation?
As mentioned in the comment, the issue is with a paren.
Also, I've just tried sit-for in *scratch* and it performs smoother compared to sleep-for.
(while 1
(insert "hello")
(sit-for 1))
But both lock up Emacs, since it's single threaded, so you should be careful with this sort of activity.
Consider using async package or something similar instead.
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.
In my .emacs file, I have:
(defadvice narrow-to-region (around test activate)
(message "advice")
ad-do-it)
When I call narrow-to-region, the advice runs and prints 'advice' before narrowing.
When I call narrow-to-defun, it does not.
I found where narrow-to-defun is defined - in lisp.el, and re-evaluated the function. At this point, the advice started running.
What could cause this?
The problem is, apparently, due to byte-compilation and therefore the inability to advise the narrowing primitives (narrow-to-region is the primitive, narrow-to-defun calls narrow-to-region).
The following post on Null Program ("The Limits of Emacs Advice") goes into detail about this problem. Here's the shortish version from deep in the post:
It turns out narrow-to-region is so special -- probably because it's used very frequently -- that it gets its own bytecode. The primitive function call is being compiled away into a single instruction. This means my advice will not be considered in byte-compiled code. Darnit. The same is true for widen (code 126).
As to why the advice started working after you re-evaluated narrow-to-defun: I'm guessing it's because you ended up replacing the byte-compiled version when you re-evaluated.
#Dan described the problem well. Here is some info that might help you work around it.
What you can do is to advise (or to redefine) also narrow-to-defun (and perhaps narrow-to-page), so it acts similarly.
FWIW, I do something similar in library wide-n.el (see Multiple Narrowings).
I advise narrow-to-region. But I also redefine narrow-to-defun and narrow-to-page. In all 3 cases I make the same change, to record the details of each narrowing so you can return to them later. Here is the advice, for example:
(defadvice narrow-to-region (before push-wide-n-restrictions activate)
"Push the region limits to `wide-n-restrictions'.
You can use `C-x n x...' to widen to previous buffer restrictions."
(when (or (interactive-p) wide-n-push-anyway-p)
(wide-n-push (ad-get-arg 0) (ad-get-arg 1)))) ; Args START and END.
And here is the relevant part of the narrow-to-defun redefinition:
...
(goto-char end)
(re-search-backward "^\n" (- (point) 1) t)
(when (or (interactive-p) wide-n-push-anyway-p) (wide-n-push beg end)) ; <=====
(narrow-to-region beg end))))
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'm currently running an asynchronous emacs command with a fair degree of regularity like this:
(save-window-excursion
(async-shell-command
cmd
(generate-new-buffer "async")))
This works well and all, but it clutters up my emacs instance with a whole ton of async<5> and async<11> buffers. How can I automatically kill these buffers when their corresponding asynchronous command finishes executing?
While it won't kill them when the command completes, you can have the buffers killed after a period of time - this assumes that the async commands are shotr-lived ( or have a fairly-known runtime). Something like:
(save-window-excursion
(let ((buf (generate-new-buffer "async")))
(async-shell-command cmd buf)
(run-with-timer 10 nil (lambda (buf) (kill-buffer buf)) buf)))
Please have a look at
http://news.gmane.org/find-root.php?message_id=%3cloom.20120517T145957%2d51%40post.gmane.org%3e
The second proposal there starts a sentinel along with the shell process.
When this sentinel detects the process status 'exit you can kill the process buffer right away or you can start dying-mode for the process buffer as it is proposed in the cited posting.
Within the dying time you can inspect the process output, cancel dying or prolong the life-time of the buffer.
Best regards,
Tobias
I'm assuming that (for this particular use-case) you are rarely interested in looking at the output that is put in the "async" buffer and that you just want to prevent the creation of the extraneous buffers. If so, you could do:
(save-window-excursion
(when (get-buffer "async")
(kill-buffer "async"))
(async-shell-command
cmd
(generate-new-buffer "async")))
This will kill the "async" buffer prior to running the "async-shell-command" and thus prevent the additional "async" buffers from being created.
Is there any way to write something like this without taking over emacs?
(defun dumb-wait (seconds)
(let ((done (+ (second (current-time)) seconds)))
(while (< (second (current-time)) done)
(message "waiting"))))
(dump-wait 5) will block emacs from 5 seconds. Is there anyway to write this so it doesn't block? I just want to be in a loop and check some condition from time to time, and still be able to use emacs.
Thanks!
(run-at-time time repeat function &rest args) should do it. nil as time means now.
(setq my-timer
(run-at-time nil 5 (lambda () (message "waiting")))) ; returns timer object
;; or
(setq my-timer
(run-at-time nil 5 'message "waiting"))
(cancel-timer my-timer) ; use timer object from above
Edit:
The parameter repeat expects a number as seconds, however there's a function timer-duration, which you can use instead of the number. It returns the number of seconds as provided with a string parameter. This is somewhat easier to read for big intervals.
(timer-duration "3 hours 2 seconds 1 millisec") ; => 10802.001
Possible word you can use are defined in the variable timer-duration-words.
On a related note, there's no general way to write Emacs Lisp code that doesn't block because the language doesn't have features like coroutines, continuations and threading (yet). Instead, you've got to look for asynchronous inbuilts that do something closest to what you want. Example: url-retrieve and async-shell-command. Some applications like SLIME have managed to work around this issue and have implemented a sort of threading on their own, while others like gnus are waiting for Emacs Lisp to improve.