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.
Related
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).
I don't think that running a process on foreground is any way useful. So I'd like to run all process on background. Is that possible?
Also tell me if there is any problem associated with doing so.
You can adapt the code from this question: https://superuser.com/questions/175799/does-bash-have-a-hook-that-is-run-before-executing-a-command
Basically this uses the DEBUG trap to run a command before whatever you've typed on the command line. So, this:
preexec () { :; }
preexec_invoke_exec () {
[ -n "$COMP_LINE" ] && return # do nothing if completing
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
local this_command=$(HISTTIMEFORMAT= history 1);
preexec "$this_command" &
}
trap 'preexec_invoke_exec' DEBUG
Runs the command, but with & afterwards, backgrounding the process.
Note that this will have other rather weird effects on your terminal, and anything supposed to run in the foreground (command line browsers, mail readers, interactive commands, anything requiring input, etc.) will have issues.
You can try this out by just typing bash, which will execute another shell. Paste the above code, and if things start getting weird, just exit out of the shell and things will reset.
Do you mean bash script? Jush add & at the end. Example :
$ ./myscript &
While it might be possible to do something clever like suggested by #pgl, it's not a good idea. Processes running in the background don't show you their output in a useful way. So, if all processes are automatically sent to the background, your terminal will be flooded with their various standard output and standard error messages but you will have no way of knowing what came from what, your terminal will be next to useless and confusion will ensue.
So, yes there is a very good reason to keep processes in the foreground: to see what they're doing and be able to control them easily. To give an even more concrete example, any program that requires you to interact with it can't be run in the background. This includes things that ask for Continue [Y/N]? or things like sudo that ask for your password. If you just blindly make everything run int the background such commands will just silently hang.
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)'
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.
I recently discovered 'comint-show-output' in emacs shell mode, which jumps to the first line of shell output, which I find incredibly handy when looking at shell output that exceeds a screen length. The advantages of this command over scrolling with 'page up' are A) you don't have to scan with your eyes for the first line of the output B) you only have to hit the key combo once (instead of 'page up' a number of times which probably is not known beforehand).
I thought about ending all my commands with '| more' but actually this is not what I want since most of the time, I want to retain all output in the terminal buffer, and I usually want to see the end of the shell output first.
I use OSX. Is there a terminal app (on os x) and shell (on remote linux) combination equivalent (so I can do something similar without using emacs all the time - I know, crazy talk)? I normally use bash, but would be fine with switching shells just for this feature.
The way I do this sort of thing is by sending my output to a file and then watching the file as it is written. You still get the results of the command dumped to terminal history in real time and can still inspect the output's actual contents further after the fact (or in another terminal, etc...)
command > output &
tail -f output
head output
You could always do something in bash like this:
alias foo='!! | more'
which would make foo run the previous command with more. I'm not sure of any way to do exactly what you are suggesting.
If you're expecting a lot of output and don't want to run your command twice, you can use tee(1) to fork the output:
my-command | tee /tmp/my-command.log | less
This will pipe the output to a paginator (less), while simultaneously logging the output to a file (in this case, a file named /tmp/my-command.log). If you need to review the output after you've quit from less, you can just cat the log file instead of re-running the command.