How to remove a function from run-with-idle-timer? - emacs

I have added a lambda() function to run-with-idle-timer like this:
(run-with-idle-timer my-configurable-idle-time t
(lambda ()
;;; do something
) )
Is it possible to remove this function at a later point again from the idle timer trigger?

Yes, run-with-idle-timer returns a timer object which you can pass to cancel-timer.
If you did not keep the timer object around, you can modify timer-idle-list by hand.
See also Getting a list of running Emacs timers.

I also came across a similar situation, where I wanted to kill a timer I started with:
(setq my-timer (run-with-timer 5 5 'my-func))
However,
(cancel-timer my-timer)
was not working because it said my-timer was not set (don't know why this was happening).
In addition to the method of the first poster, it can be killed with:
(cancel-function-timers 'my-func)
This cancels all the timers calling function 'my-func.
To kill it by altering timer-list, which I also tested, I did the following:
(length timer-list) ;; I had two timers..one good, one bad
(cdr timer-list) ;; I verified the last was the one I wanted to keep
(setq timer-list (cdr timer-list)) ;; I reset timer-list
Obviously, this list structure will vary, so you'll have to adjust accordingly. Substitute "timer-idle-list" if you started your timer with (run-with-idle-timer)
This should also work if you started your timer with 'gamegrid-start-timer and 'gamegrid-kill-timer is not working, since 'gamegrid-start-timer is essentially just a wrapper for 'run-with-timer

One more solution: if you're out of luck and can't actually cancel the timer, you can always use
(defvar my-timer-enabler t)
(run-with-idle-timer my-configurable-idle-time t
(lambda ()
(when my-timer-enabler
;;; do something
)))
So you can disable the timer by setting my-timer-enabler to nil. And you can later re-enable the timer by simply setting the var back to t.

Related

Track buffer changes and trigger a hook after event in Emacs

I'm trying to add some facilities to my matlab environment within Emacs.
Basically, I want to have an extra buffer (*Matlab Whos*) to display all my variables. The buffer should update automatically after matlab-shell finishes evaluating an expression. In other words, after I press return on the shell, a hook should call a function to update *Matlab Whos*.
The simple solution I came up with is:
(defvar matlab-whos-buffer-name "*Matlab Whos*")
(defun matlab-whos-buffer-update ()
"Create Matlab Whos buffer if it doesn't exist.
If it exists, update its values."
(lambda)
(interactive)
(let ((doc-whos (matlab-shell-collect-command-output "whos")))
(with-current-buffer (get-buffer-create matlab-whos-buffer-name)
(erase-buffer)
(insert doc-whos))))
(add-hook 'matlab-shell-mode-hook
(lambda ()
(define-key matlab-shell-mode-map (kbd "<return>")
(lambda ()
(interactive)
(comint-send-input)
(matlab-whos-buffer-update)))))
The function matlab-whos-buffer-update works fine. However, the problem with this solution is that my hook calls the function before the matlab shell finishes its evaluation (requested by (comint-send-input)). As a consequence, matlab-whos-buffer-update returns an error saying:
Matlab-shell-collect-command-output: MATLAB shell must be non-busy to
do that.
How can I track changes to my Matlab shell buffer, so that my hook knows that it can only trigger matlab-whos-buffer-update, after the result of the evaluation has returned?
You can start with something like
(add-hook 'matlab-shell-mode-hook
(lambda ()
(add-hook 'comint-output-filter-functions
#'matlab-whos-buffer-update
nil 'local)))
But note that this will call your function everytime something is sent from the process. I can foresee two problems with it:
it may fail miserably if matlab-shell-collect-command-output ends up using that same setup (and hence also calling matlab-whos-buffer-update.
it might be run too many times (if your process sends its output in 5 chunks, it will be run 5 times).
Try it and come back with another question if that doesn't work well enough.

How to use a minibuffer-exit-hook with read-string

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.

Emacs - set different intervals for cursor blinking on and off

I want to set different intervals for blinking ON and for blinking OFF. I mean, I want the cursor to stay visible for 1 second and OFF for 0.2 second.
I read the cursor documentation but closest I found is the blink-cursor-interval that changes both ON and OFF blinking.
How can I customize this in Emacs?
There's no such functionality built into Emacs, but you can hack it by adding the following lines to your .emacs file:
(defvar blink-cursor-interval-visible 1)
(defvar blink-cursor-interval-invisible 0.2)
(defadvice internal-show-cursor (before unsymmetric-blink-cursor-interval)
(when blink-cursor-timer
(setf (timer--repeat-delay blink-cursor-timer)
(if (internal-show-cursor-p)
blink-cursor-interval-visible
blink-cursor-interval-invisible))))
(ad-activate 'internal-show-cursor)
Emacs implements the blinking of the cursor with a toggle function called by a timer. Each time the function is called, it either hides the cursor if it is currently visible, or shows it if it is invisible. Unfortunately, the timer calls this function at a fixed interval.
In order to realize different delay times depending on the state of the cursor, the above code advises the internal function that shows or hides the cursor. Each time that function is called, the advice changes the delay time of the timer to either 1 or 0.2, depending on whether the cursor is visible or not. That is, every time the cursor is hidden or shown, the timer's delay time is changed.
Quite hackish, but it does the trick.
I was able to modify the blink-cursor-timer-function function to support what you want I believe.
First, you'll need to modify the value of blink-cursor-interval to .2
then this code should do the trick:
blink-cursor-timer-function is called every blink-cursor-interval seconds.
So this function will be called every .2 seconds, It will keep the cursor ON for 5 calls then turn it off for 1. So 5 calls at .2 seconds per call will give you 1 second of ON time, then only .2 seconds of OFF time.
;; change the interval time to .2
(setq blink-cursor-interval .2)
;; create a variable that counts the timer ticks
(defvar blink-tick-counter 0)
;; this function will be called every .2 seconds
(defun blink-cursor-timer-function ()
"Timer function of timer `blink-cursor-timer'."
(if (internal-show-cursor-p)
(progn
(if (> blink-tick-counter 4)
(progn
(internal-show-cursor nil nil)
(setq blink-tick-counter 0))
(setq blink-tick-counter (1+ blink-tick-counter))))
(internal-show-cursor nil t)))

Emacs Display Effects with Yasnippet

Yasnippet has a nice "run ... after exiting a snippet".
What I would like to do is include some visual effect after each ending snippet (changing background color for, say a second, or more sophisticated stuff).
I did this by switching background colors back and forth in that hook, but it's really short and not efficient, and also ugly.
However, how can this, or something similar be done with a timer?
Optional: Suggestions for fancy effects (including a timer) are welcome.
You can change the background once and then change it again 1 second later by using run-with-timer:
(run-with-timer 1 nil 'my-fun)
where my-fun does the action you want.
My first thought would be to make Emacs "beep". I actually hate that sound, so I have it flash the frame instead.
(setq visible-bell t)
(add-hook 'yas-whatever-hook (lambda () (beep t)))

Can an elisp piece of code "yield" so emacs doesn't block?

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.