Track buffer changes and trigger a hook after event in Emacs - matlab

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.

Related

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.

how do I run this Emacs M-x command "wg-update-workgroup" automatically before emacs closes?

I would like this to happen when I right click the launcher...icon..and select quit..and choose file exit. I would like this command to be run right before emacs exits....so when I right click the launcher icon and select quit then this command "wg-update-workgroup" is run then Emacs exits..I've tried learning about hooks but don't get how to add one....If someone can give me exact code I put into my initialization file I would be very grateful....tried binding a function to a key but get weird command p error.
Here's the code:
(add-hook 'kill-emacs-hook
(lambda ()
(wg-update-workgroup)))
UPD
It seems that the code isn't working for you since wg-update-workgroup needs an argument.
You have to test this yourself, since I don't really want to get familiar with the package.
Solution 1:
(add-hook 'kill-emacs-hook
(lambda ()
(wg-update-all-workgroups)))
Solution 2:
(add-hook 'kill-emacs-hook
(lambda ()
(call-interactively 'wg-update-workgroup)))
UPD: disregard everything from above:)
I'm pretty sure this is what you want:
(setq wg-query-for-save-on-emacs-exit nil)
(push (lambda()(or (ignore-errors
(wg-update-all-workgroups-and-save)) t))
kill-emacs-query-functions)
The first statement removes the extremely annoying y/n query about saving
workgroups on exit. The second statement saves everything unconditionally on exit.
Just to list my full configuration:
(require 'workgroups)
(workgroups-mode 1)
(setq wg-query-for-save-on-emacs-exit nil)
(wg-load "~/wg")
(push (lambda()(or (ignore-errors
(wg-update-all-workgroups-and-save)) t))
kill-emacs-query-functions)
You're right to be baffled. The issue is this: when Emacs begins exiting, workgroups.el cleans itself up earlier than 'kill-emacs-hook. What you want is this:
(add-hook 'kill-emacs-query-functions 'wg-update-all-workgroups)
The hook variable should then look something like this:
(wg-update-all-workgroups wg-emacs-exit-query)
I recommend using 'wg-update-all-workgroups rather than 'wg-update-workgroup if, like me, you have more than one workgroup saved in a given workgroups file.
IMO workgroups.el is the best Emacs session manager. Somebody new has just taken it over. I'm excited that a new version with even more features may be forthcoming:
https://github.com/pashinin/workgroups2/

How does the following statement is interpreted by emacs

https://stackoverflow.com/a/663636/391104
(defun my-c++-mode-hook ()
(setq c-basic-offset 4)
(c-set-offset 'substatement-open 0))
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
Based on my investigation, I just need to add the above code into my .emacs and then it works magically.
Q1> What does defun my-c++-mode-hook () mean? a function definition in lisp?
Q2> What is the usage of following line? where should I trigger it or it is run automatically by emacs
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
Thank you
Q1: Yes, this is a function definition (hence defun). The second symbol is the name, which has the suffix '-hook' to indicate to humans that it is intended to be used as a hook. It could be given (almost) any arbitrary name without changing its behaviour. The empty () indicates the function takes no arguments. Everything else is the body of the function.
Q2: Basically, this adds a pointer to the previous function to the list of functions that are called when ever c++-mode is started. Whenever you start a mode, the Emacs looks for the mode hook, running all the functions in it. Both the function definition and the add-hook line need to go in your .emacs, and they will be run automatically when you start emacs.
To wrap your head around elisp, the introduction is highly recommended. It ships with emacs, and can be accessed from the info system: C-h i, then look for Elisp Introduction.

before defadvice not executing before the function?

[I apologize for the poor title, but couldn't come up with a better one.]
bin chen asked on Google+:
How to input relative path of (buffer-file-name) in minibuffer after M-! in #emacs?
I thought if the buffer-file-name is saved in a register, it should be accessible by invoking insert-register (C-x r i) while at the shell-command prompt.
(defun save-buffer-file-name-in-register ()
(set-register ?F (buffer-file-name))
(set-register ?D (file-name-directory buffer-file-name)))
(defadvice shell-command (before save-buffer-file-name)
"Save buffer-file-name to register F before running shell-command"
(save-buffer-file-name-in-register))
(ad-activate 'shell-command)
When I invoke shell-command (M-!) followed by insert-register (C-x r i), I get the error message: Register does not contain any text.
But when I run list-registers I do see that the registers F and D are set with the appropriate values. If I run the shell-command again, I can access the values from the registers previously saved.
Is it possible that the registers are being set too late for the first time? How can I fix the code to do what I want?
Edit: Changed around to before (Thanks to #phils)
n.b. You have defined around advice, not before advice.
Around advice acts as a wrapper, and must include the token ad-do-it to execute the code of the function it is wrapping.
You have effectively replaced the body of the shell-command function with a call to save-buffer-file-name-in-register
As to your main question, I'd need to check the documentation, but I suspect that because the arguments to the advised function are available to advice, the original function's interactive declaration probably executes before the advice does, which would explain why your register values are not visible at the interactive shell-command prompt.
(If the around in the above code is indeed what you were using, the fact that you were still being prompted for a shell command would seem to verify this sequence.)
When the interactive form runs, your advice hasn't executed yet. See: this question
You need to specify an interactive form in your advice that redefines the original if you want to stick with this approach. However, this approach is a little fancy-pants for the sake of fancy-pants-ness.
Just define your own interactive function which does what you want without registers.
(defun insert-cur-dir ()
(interactive)
(let ((dir-name (file-name-directory (buffer-file-name (window-buffer (minibuffer-selected-window))))))
(insert (or dir-name ""))))
(define-key minibuffer-local-map (kbd "C-c i") 'insert-cur-dir)
An alternative, but way awesomer approach is to use yasnippet.

How to automatically evaluate certain lisp code after starting an emacsclient?

When starting Emacs, init.el (or .emacs.el) is evaluated. However, when starting emacsclient, no similar lisp code is evaluated.
How can I get a lisp file to be evaluated every time I open a new emacsclient?
(This would be handy for frame specific customizations.)
I assume the answer is to use some hook, but I can't seem to find the correct hook to use.
I look forward to your answers.
You can add a function to the hook 'server-visit-hook, which is run every time the server is called (every time you call emacsclient).
I use the following code to automatically change the behavior of server buffers. I use it especially with the Firefox extension It's All Text. In that extension, buffers are named according to the domain name, so you can figure out which rule to apply by using string-match to match the name of the file.
(defun server-edit-presets ()
(cond
;; When editing mail, set the goal-column to 72.
((string-match "mail\\.google\\.com\\.[0-9a-z]+\\.txt" (buffer-name))
(longlines-mode-off)
(auto-fill-mode 1)
(set-fill-column 72)
(save-excursion
;; Don't know if this is necessary, but it seems to help.
(set-buffer (buffer-name))
(goto-char (point-min))
;; Replace non-breaking strange space characters
(while (search-forward (char-to-string 160) nil t)
(replace-match " "))))))
(add-hook 'server-visit-hook 'server-edit-presets)
(add-hook 'server-visit-hook '(lambda () (longlines-mode 1)))
If you really want new frame customizations, there's create-frame-hook which takes one arg (the new frame)...
If you mean gnuclient, you can use the command-line option "-eval" to evaluate something (and then just make an alias to always eval your customizations).
#LSW:
Try 'window-setup-hook. This addresses the annoyance since it is called even if emacsclient is not passed a file.
It seems that those hooks are no more, so here's the new version.
(add-hook 'server-after-make-frame-hook 'consult-recent-file)