Multiple asynchronous shell-commands in Emacs-Dired? - shell

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)

Related

How emacs take present file as argument to a function automatically?

I am making my own shell command. What is the command that automatically takes the present file as argument of a function when i press enter (just like % in .vimrc file. basically i want that interactive command should invoke automatically when i don't pass any argument as filename while calling the function and automatically takes the present file as the input to the command.
From how I understood your question, you may be looking for the variant of interactive with a lisp form that produces the arguments:
(defun echo-current-buffer-filename (f)
(interactive (list (buffer-file-name)))
(message "Current buffer filename is %s" f))
See the documentation of the interactive function at https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Interactive.html for more information.

emacs elisp switch to buffer and follow

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).

Sending bash commands to an open terminal buffer in emacs

I've been trying to improve my emacs life lately, and one thing I've done is make use of projectile and perspective to organize my buffers sensibly.
As part of this I wrote an elisp function to open up (or return to) a named ansi-term buffer that is project-specific. This allows me to quickly drop into a bash terminal for the project I'm currently looking at.
What I have been having trouble finding out after plumbing the interwebs is whether or not it is possible to send bash commands to an open ansi-term buffer from within emacs. Specifically, I'm trying to make sure the ansi-term buffer cds to the correct project root directory when it's first opened. This requires grabbing context from the projectile package first, so it's not something I can plop into my .bashrc.
Ideally I would be able to write an elisp function that:
1) selects an ansi-term buffer by name (since I can have one open with a unique name for every project)
2) sends and executes a command in that buffer
Is there any way to do this?
EDIT
Final solution for anyone who is interested:
(defun visit-project-term-buffer ()
"Create or visit a terminal buffer."
(interactive)
(if (not (get-buffer (persp-ansi-buffer-name)))
(progn
(split-window-sensibly (selected-window))
(other-window 1)
(ansi-term (getenv "SHELL"))
(rename-buffer (persp-ansi-buffer-name))
(end-of-buffer)
(insert (format "cd %s" (projectile-project-root)))
(term-send-input))
(switch-to-buffer-other-window (persp-ansi-buffer-name))))
Does this work for you? It switches to a buffer named *terminal* and runs echo hello:
(defun my-echo ()
(interactive)
(switch-to-buffer "*terminal*")
(end-of-buffer)
(insert "echo hello")
(term-send-input))

Emacs how to run command in Interactive command line mode in elisp

I am newbie to Emacs.
I want to define a function in elisp to run a command in interactive command line mode (Asynchronously if possible).
my current code is:
(defun ma () ;run maxima batch on the current file
(interactive)
(let*
((fn (buffer-file-name)) (cmd (concat "maxima -b " fn)))
(message "cmd:%s" cmd)
(shell-command cmd)
)
)
this works fine when I do not have break points in the maxima code. When I have break points "break()", I have to interact with the program. The current shell-command function does not work.
I also like the mechanism of "shell-command" function that the screen will automatically split into two and show the programming running info in a second window. If possible, I still want this feature in the code that you can help me with.
Any help would be appreciated.
I want to define a function in elisp to run a command in interactive
command line mode (Asynchronously if possible).
Maybe async-shell-command is what you are looking for do C-h f async-shell-command RET for help on the function.
Use the built in compile function in commint mode.
(defun ma (&optional filename)
(interactive)
(compile (format "maxima -b %s" (or filename (buffer-file-name))) t))
This will open up a new window and will show you the output of the program running. Commint mode means that the compilation process is interactive, you will be able to send input to the program from the compilation buffer.

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.

Resources