Kill Emacs's Async Shell Command buffer if command is terminated - emacs

Emacs does not kill the *Async Shell Command* buffer if the async command terminates. How can I force this behavior?

What you are looking for is Process Sentinels.
The sentinel for *Async Shell Command* is shell-command-sentinel.
You can advise it:
(defun my-kill-buffer-when-done (process signal)
(when (and (process-buffer process)
(memq (process-status process) '(exit signal)))
(kill-buffer (process-buffer process))))
(defun my-kill-async-buffer-when-done ()
(let ((process (get-buffer-process "*Async Shell Command*")))
(add-function :after (process-sentinel process) #'kill-buffer-when-done)))
(add-function :after #'async-shell-command #'my-kill-async-buffer-when-done)
PS. I did not test the above code, mostly because I think it is a horrible idea: you want to examine the content of *Async Shell Command* before killing it.
However, I hope reading the code and links above will help you become a more proficient Emacs user.

Related

emacs: How to Capture stdout from dired-do-shell-command?

In Emacs, is there a way to capture the stdout of dired-do-shell-command, say to the kill-ring?
Without knowing how, I end up going to the Messages buffer and getting the stdout manually from there.
Help for that command says that output goes to a buffer named *Shell Command Output*, assuming command has not &. If this is the case, this piece of code will do what you want:
(defun do-shell-and-copy-to-kill-ring (command &optional arg file-list)
(interactive
(let ((files (dired-get-marked-files t current-prefix-arg)))
(list
(dired-read-shell-command "! on %s: " current-prefix-arg files)
current-prefix-arg
files)))
(dired-do-shell-command command arg file-list)
(with-current-buffer "*Shell Command Output*"
(copy-region-as-kill (point-min) (point-max))))
For async commands, you need to wait for them and look in *Async Shell Command* buffer.

restart process executed in eshell in emacs

i have started a python process in eshell:
python app.py
i want to restart this with a elisp function, i think comint-quit-subjob when executed with C-c C-\ kills the process but all my attempts to execute comint-quit-subjob have failed
This is what i have so far:
(defun restart-app()
(with-current-buffer "*eshell*"
(interactive)
(comint-quit-subjob)
(eshell-return-to-prompt)
(insert "python app.py")
(eshell-send-input))
)
Hopefully it gives the jist of what i am trying, but it fails. Any ideas?
I would suggest looking for a eshell-ish way of killing a process (I am not a eshell user myself). Comint tries to search something in the buffer. You can workaround that doing something like this (but it is brittle and unelegant):
(defun restart-app()
(with-current-buffer "*eshell*"
(interactive)
(kill-process nil comint-ptyp)
(run-with-timer 0.5 nil
(lambda ()
(with-current-buffer "*eshell*"
(goto-char (point-max))
(insert "python app.py")
(eshell-send-input)))))

How to run multiple shells on Emacs

I am using Emacs 23.3.1 on windows 7. I know that I can run shell from emacs using M-x shell. I would like to have multiple shell windows in the same time, but typing M-x shell a second time just opens me the same shell window.
Is there a way to have different shell windows?
C-u M-x shell will do it.
It will prompt for a name for the new shell, just hit return for the default (which will be something like *shell*<2>.
Also works with eshell.
Another trick, if you use eshell: just as M-x eshell takes you back to *eshell* (rather than starting a new eshell), if you use a numeric prefix argument it will take you to that eshell buffer. For instance, C-3M-xeshell will take you to *eshell*<3>. Sadly if you use shell (rather than eshell), this trick doesn't seem to work (in my Emacs 24.0.50.1 at least.)
You can rename the buffer of your shell with M-x rename-buffer. Then you will be able to launch a second shell.
Look at MultiTerm, it makes managing multiple terminals in Emacs much easier.
After more than four years, I see that some people are still looking at this issue sometimes, so I will publish a quick function I wrote to load a shell and ask for its name. That way you can name a shell "sort-files" if it is dedicated to sorting files and another one "hive" if it's dedicated to run hive queries. I use that everyday now (on emacs 24):
(defun create-shell ()
"creates a shell with a given name"
(interactive);; "Prompt\n shell name:")
(let ((shell-name (read-string "shell name: " nil)))
(shell (concat "*" shell-name "*"))))
It might also be useful to use a screen-like interface to your shells. I've written my own, but there are others out there, like EmacsScreen.
This will autogenerate a new shell instance in whatever buffer you happen to be using; bind it to M-S or somethings like that and instant joy:
(defun new-shell ()
(interactive)
(let (
(currentbuf (get-buffer-window (current-buffer)))
(newbuf (generate-new-buffer-name "*shell*"))
)
(generate-new-buffer newbuf)
(set-window-dedicated-p currentbuf nil)
(set-window-buffer currentbuf newbuf)
(shell newbuf)
)
)
Many thanks to phils for recommending a rewrite using let, even though the result is even more awful parentheses...:\
This will open a new shell each time you invoke the function and rename it automatically if needed.
The added plus is if you are editing files remotely (dired/tramp...), this will open a shell on the remote host and rename it automatically with the remote hostname:
(defun ggshell (&optional buffer)
(interactive)
(let* (
(tramp-path (when (tramp-tramp-file-p default-directory)
(tramp-dissect-file-name default-directory)))
(host (tramp-file-name-real-host tramp-path))
(user (if (tramp-file-name-user tramp-path)
(format "%s#" (tramp-file-name-user tramp-path)) ""))
(new-buffer-nameA (format "*shell:%s*" host))
(new-buffer-nameB (generate-new-buffer-name new-buffer-nameA))
(currentbuf (get-buffer-window (current-buffer)))
)
(generate-new-buffer new-buffer-nameB)
(set-window-dedicated-p currentbuf nil)
(set-window-buffer currentbuf new-buffer-nameB)
(shell new-buffer-nameB)
))

How do I define an Emacs Lisp function to spawn a shell buffer with a particular command executed in the shell?

I am doing Rails development and find that I need to spawn a shell, rename the buffer (e.g. webrick), then kick off the command (rails s) and then do the whole thing over again if I want a rails console or rails dbconsole, rspec, spork, etc. every time I start up emacs.
I am hoping for something like this:
(defun spawn-shell ()
"Invoke shell test"
(with-temp-buffer
(shell (current-buffer))
(process-send-string nil "echo 'test1'")
(process-send-string nil "echo 'test2'")))
I don't want the shell to go away when it exits because the output in the shell buffer is important and some times I need to kill it and restart it but I don't want to lose that history.
Essentially, I want to take the manual process and make it invokable.
Any help is much appreciated
Tom
Perhaps this version of spawn-shell will do what you want:
(defun spawn-shell (name)
"Invoke shell test"
(interactive "MName of shell buffer to create: ")
(pop-to-buffer (get-buffer-create (generate-new-buffer-name name)))
(shell (current-buffer))
(process-send-string nil "echo 'test1'\n")
(process-send-string nil "echo 'test2'\n"))
It prompts for a name to use when you run it interactively (M-x spawn-shell). It creates a new buffer based on the input name using generate-new-buffer-name, and you were missing the newlines on the end of the strings you were sending to the process.
If your only problem is that the shell buffer disappears after the commands have been executed, why not use get-buffer-create instead of with-temp-buffer?

How to (automatically) remove or prevent popping up *Async Shell Command* in emacs?

As is asked in here. I could run vi or mate within emacs.
The problem is that after running (async-shell-command "vi"), I always have the *Async Shell Command" popped up as a window.
Can I prevent popping up this windows? Or, can I modify the emacs code to remove the window as soon as it pops up?
(defun runvi ()
(interactive)
(let (filename (file-truename buffer-file-name))
(setq cmd (format "/Users/smcho/bin/mvim %s" (file-truename buffer-file-name)))
(async-shell-command cmd)))
This will work (assuming cmd is bound to the command you want, like you have above):
(save-window-excursion
(async-shell-command cmd))