emacs elisp switch to buffer and follow - shell

I am trying to write a command that will cause Emacs to switch to a new buffer and do something (in this case, execute a shell command) that writes output to the buffer.
(defun test-func ()
(interactive)
(let ((bname "*temp*")
(default-directory "/home/me"))
(with-output-to-temp-buffer bname
(switch-to-buffer bname)
(shell-command "ls -l" bname))))
In this case, it "works" except that it doesn't switch the buffer until after the command is done executing. I wanted to switch immediately and then follow the output as it's running. Is there a way to do that?

You need to call redisplay explicitly after switch-to-buffer to make it visible.
Note that ls is a fairly "fast" command, and it is unlikely to show piecemeal. You might want to try a shell script like
while true; do
date
sleep 10
done
and run is asynchronously (either use async-shell-command or add & to the end of the command line).
Note also that the help for shell-command says:
In Elisp, you will often be better served by calling call-process or
start-process directly, since it offers more control and does not impose the use of a shell (with its need to quote arguments).

Related

Emacs Lisp: suppress "Saving file" text while running ELisp file from shell

To start my Emacs Lisp script from shell, I use this command:
emacs --script my-script.el -f my-function
In my script I save 3 buffers to 3 files.
And it's working OK. But when script is running on the shell it prints the text:
Using vacuous schema
Saving file "some-file-to-save"
Wrote "some-file-to-save"
This text prints 3 times. How I can suppress this text?
I don't know offhand how to fix it "properly" in ELisp, but an easy solution would be to just discard output:
emacs --script my-script.el -f my-function > /dev/null
This tells the shell to send all of stdout to /dev/null (which discards all data written to it). Obviously this requires a) an operating system that has /dev/null (i.e. most Unices, including macOS) and b) a shell that doesn't suck (i.e. not cmd.exe).
Identify the function calls that dumps these messages in your script.
Assuming that the first message comes from the function save-buffer which calls the function message (files.el), just override the behavior of message by replacing, in your script, the invocation of save-buffer (or whoever is called) by:
(cl-letf (((symbol-function 'message) #'ignore))
(save-buffer))
Your need to add
(require 'cl-lib)
on top of your script if not already there.

Run emacs lisp command from inferior shell

How do I call an emacs lisp function programmatically from an inferior shell?
For instance, I'm in a shell that uses some characters that emacs recognizes and attempts to autoexpand, so I want to run this command (setq comint-input-autoexpand nil) to apply it to the shell I'm in.
I can do this now by entering the text of the command in the shell and running something like eval-region on it but I want my shell to be able to invoke this command itself.
Thanks to the people who responded but it seems my question is unclear. I can accomplish what I want by entering an elisp expression, selecting it, and calling 'eval-region' on it but this requires manual input. What I want is a way to automate this so my shell can send emacs a command to change its own settings.
The "emacsclient" suggestion seems like it's in the right direction but I'm afraid that Windows does not fully support its options and it's unclear that such a command would affect the buffer from which I invoke it since I would do so via an external "shell" command.
What I want is some sort of escape sequence that signals emacs "This elisp expression is for you". I'm guessing there might be a way to open a socket to emacs and send it commands this way but I still have the problem of selecting the buffer to which to apply the command. Again, this is probably more difficult/impossible in Windows, so I will rely on my command bound to a key sequence for now.
It sounds like you are looking for M-x eval-expression, bound by default to M-: (Alt+Colon, i.e. Alt+Shift+semicolon). The expression is evaluated in whatever context you were in when eval-expression was invoked, so if the expression sets a buffer-local variable, it will be set for your current buffer.
You can use emacsclient to do it. You'll need to have started emacs as a server, either with (server-start) in your .emacs or by starting emacs as a background process with --daemon.
You can evaluate elisp code in your shell like this:
emacsclient --eval '(setq comint-input-autoexpand nil)'

How do I speed up emacs output from an asynchronous shell-command?

I'm running the output of an application in an emacs buffer using shell-command.
(shell-command "verbose-app &" "*verbose-app*")
The problem is this command is extremely verbose. So much so, that it sometimes takes several seconds for the emacs buffer to catch up. It lags by several seconds with the actual output.
Is there any way I can speed up the output scrolling by disabling something? Like regex-matching or syntax highlighting?
For future reference:
The verbose app is adb logcat. I changed my existing function:
(defun adb-logcat ()
(interactive)
(shell-command "adb logcat -v threadtime&" "*adb-logcat*")
(pop-to-buffer "*adb-logcat*")
(buffer-disable-undo))
To the following:
(defun adb-logcat ()
(interactive)
(start-process "*adb-logcat*" "*adb-logcat*" "/bin/sh" "-c" "adb logcat -v threadtime")
(pop-to-buffer "*adb-logcat*")
(buffer-disable-undo))
It scrolls way faster now. Yay!
Like the documentation says, shell-command runs the command in an inferior shell, implying shell-mode. If you just want the output and none of the features, running the command with start-process may be closer to what you want.
(start-process "*verbose-app*" "*verbose-app*"
"/bin/sh" "-c" "verbose-app")
Wrapping this into a function should not be too hard. You might want to look at how shell-command implements async commands; for example, it will ask whether it should terminate an existing process if you attempt to create one when another already exists. http://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/simple.el#n2447 might be a good starting point. (In case the link goes bad, this is a link to inside defun shell-command, pointing to a a comment about handling the ampersand. If it's there, the command will be run asynchronously.)
If the command is that verbose, is there any use in capturing the full output in real time? Maybe you could run verbose-app > app.log in the background and then run something like while true; do tail -n50 app.log; sleep 1; done within emacs to keep updating the buffer to view the last few lines of the log file. Later when you want the full output you can open the log file in emacs.

Multiple asynchronous shell-commands in Emacs-Dired?

Emacs obviously can handle multiple asynchronous sub-processes, otherwise a multi-language programming environment like org-babel, to give an example, wouldn't be possible.
However, when I'm in Dired and start an asynchronous shell command to view a pdf file (& evince), and then try to do the same on a second pdf file, I get the following message:
"A command is running - kill it? Yes or No?"
Is there a way to run several asynchronous shell commands in parallel, when in Dired?
When you use dired-do-async-shell-command Emacs create a *Async Shell Command* buffer. If you want another async command you need to rename this buffer, for example using M-x rename-uniquely
you could try to change the comportment of dired-do-async-shell-command by advising it:
(defadvice shell-command (after shell-in-new-buffer (command &optional output-buffer error-buffer))
(when (get-buffer "*Async Shell Command*")
(with-current-buffer "*Async Shell Command*"
(rename-uniquely))))
(ad-activate 'shell-command)
note that I really advice the shell-command Emacs command because it's called by dired.
I don't think it's possible with dired-do-async-shell-command, but if you just want to open some file is certain external application I suggest using OpenWith, which allows any number of external processes running.
I've just setup the following which erases the current definition of dired-run-shell-command to pass a dedicated buffer name to shell-command:
(defun dired-run-shell-command (command)
(let ((handler
(find-file-name-handler (directory-file-name default-directory)
'shell-command)))
(if handler (apply handler 'shell-command (list command))
(shell-command command
(generate-new-buffer-name
(concat "*Shell Command Output: '" command "'*")))))
;; Return nil for sake of nconc in dired-bunch-files.
nil)

Emacs and Long Shell Commands

Is there a way to run a shell command, have the output show up in a new buffer and have that output show up incrementally? Eshell and other emacs terminal emulators do a find job of this but I see no way to script them.
What I'd like to do is write little elisp functions to do stuff like run unit tests, etc. and watch the output trickle into a buffer.
The elisp function shell-command is close to what I want but it shows all the output at once when the process finishes.
As doublep mentioned, there is M-x compile, and there's also just the simple M-x shell and in that shell you run whatever you want.
You can also use comint-run to execute a command without needing to start a sub-shell first. I believe M-x shell uses comint mode with some modifications, so this won't be a whole lot different from that. But if you want to call a program directly and have its input and output be tied to a buffer, comint-run is the function to call. It is a little tricky to use, so read the documentation: C-h f comint-run.

Resources