I have an Emacs command like following:
(defun query-lisp (word)
(interactive "sType a word to query:")
(message "%s" (query word)))
The query operation is a time-consuming operation. When this command is running Emacs blocks the whole frame. Is there a way to make Emacs run this command in the background or block only a single window such as the minibuffer?
If you plan to use an external process (which you have indicated in a comment to another question), you can use the following:
(start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)
This will return a process object. You can either send the output to a buffer, or you could attach a filter function to the process. In the latter case, this is a function that is called every time your process emits any output.
In addition, you could attach a sentinel function to your process. This function is called everytime the status of your process changes, this is useful to find out when it has exited.
There are several examples of the above in the source code of Emacs, one such example is compile.el.
Emacs doesn't have threads. For long operations you can split up the task into chunks and execute the chunks in idle timers, so emacs can respond to user input between the chunks.
The other possibility is running it as an external process from which emacs accepts the output.
For example, you can use something like this
(shell-command "sleep 10 && echo 'finished' &")
The result will be displayed in *Async Shell Command* buffer.
Related
In emacsclient, is there a way to open a file from the command line such that its buffer will remain open on the server after I close the client?
Alternatively, is there a command I can run from in a client to tell it to effectively detach from a buffer, so that the buffer does not get killed when the client exits?
Normally when closing emacsclient either with C-x C-c or C-x #, the buffer(s) associated with that client get killed, which is usually convenient behavior, but sometimes I would like for buffers to stay alive after closing. So far the only way I have found to accomplish this is to run the client without specifying any files, then visit them with C-x C-f, but I'm wondering if there's a better way to do this.
You should be able to do this by using the -n option. That means that it won't wait for you to "finish" the buffer and it'll just stay in the buffer list. I use this with emacsclient myself.
So, one option is to use emacsclient's eval command line option to run a lisp command to find the file you want.
emacsclient -c -e '(find-file "my_file")'
Obviously this is a lot more to type than the command sequence emacsclient -c, C-x C-f, my_file, but it could pretty easily be wrapped in a script that takes an extra argument to tell it whether to just choose the file or use find-file.
Someone more well versed in elisp than I could probably just add the option directly into emacs.
According the info manual, if you never want to kill emacsclient buffers, when you're done with them, you can customise the server-kill-new-buffers variable (more information at C-h v server-kill-new-buffers).
For you use-case, depending on how often you want the buffers killed or not, you could set the above variable to nil and then manually kill the buffers that you do want killed.
I want to write an eshell function that sort of wraps an existing command-line script. In order to do this, I want to be able to execute a shell command from an eshell function. My first instinct was to do something like
(defn eshell/myfunc ()
(shell-command "mycommand"))
And this sort of works, except for a few problems. It runs in an inferior shell instead of behaving like a real "exec" command. This means that, among other things, the command "myfunc" in eshell appears to block while the command is running. The output of "mycommand" is collected an appears in a Shell Output buffer at the end, but it doesn't replicate the behavior of a normal shell function, where the standard output appears while it runs.
So, what's the correct way to do this?
Try
(start-process-shell-command "foo" (current-buffer) "mycommand")
If you need more control, see Emacs Lisp Referece Manual, Sectioin 37.4 Creating an Asynchronous Process.
In windows shell it's possible to pause the output just by selecting a text in the shell window (a QuickEdit mode must be enabled). The same is possible in the cygwin shell (again with a QuickEdit mode).
How can I pause the output in emacs shell?
I need to pause it because some tasks are very verbose and it's difficult to search the necessary text in a big buffer.
When I execute M-x comint-stop-subjob I get a message "No SIGTSTP support"
As an example try to pause the following:
find . -type f -name "*.txt" -exec cat {} ';'
Not exactly what you asked for, but clone-buffer will get you close to what you want. After binding it to a convenient key and running your find command, calling clone-buffer will copy the contents of the buffer to a new buffer. The find command in the original buffer keeps running, but the cloned buffer contains only the output of find up to the point that you cloned it.
You can invoke this command multiple times in the original window, giving you a series of stop points to examine. I don't know how to actually pause the original window though.
Note that the newly cloned buffers are fully functional shell buffers.
You can stop the job by pressing C-c C-z. Then just enter fg to make it work again.
I don't know about pausing the output, but you can presumably just narrow the buffer?
C-xnn to narrow-to-region
C-xnn to narrow-to-page
C-xnw to widen to full buffer
How to make Emacs run a program and don't wait for output/respond? I tried to open a pdf in an external program:
(shell-command (concat "start sumatrapdf " (shell-quote-argument path) " -page " search))))
But it won't open another files until the existing sumatrapdf process is closed. I tried async-shell-command, but it opens a new buffer with Async output which I don't need.
What is the right way to open files in external programs?
start-process function can handle that:
(start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS)
Start a program in a subprocess. Return the process object for it.
NAME is name for process. It is modified if necessary to make it unique.
BUFFER is the buffer (or buffer name) to associate with the process.
Process output (both standard output and standard error streams) goes
at end of BUFFER, unless you specify an output stream or filter
function to handle the output. BUFFER may also be nil, meaning that
this process is not associated with any buffer.
PROGRAM is the program file name. It is searched for in `exec-path'
(which see). If nil, just associate a pty with the buffer. Remaining
arguments are strings to give program as arguments.
If you want to separate standard output from standard error, invoke
the command through a shell and redirect one of them using the shell
syntax.
If you don't want to associate bufer with open process — pass nil as BUFFER argument
See C-h k M-!
...
If COMMAND ends in ampersand, execute it asynchronously. The output
appears in the buffer `Async Shell Command'. That buffer is in shell
mode.
...
IOW, M-! my_command --opt=foo arg1 arg2 & will start my_command and create a *Async Shell Command* buffer with my_command running in it but emacs will give control back to you right away.
I would like to write a small script in ELisp that would:
send a command to a given buffer
get its output
parse it
send it to another buffer
I am struggling with point 2: I cant get the output of a command. For example, if I have a shell buffer on, I can use
(process-send-string "shell" "help\n")
to send "help" to my shell buffer. It will then show the list of the commands available. But how can I get this list to use it somewhere else?
Thanks,
S4m
(buffer-string) returns the contents of the current buffer, so (with-current-buffer <buf> (buffer-string)) will return the contents of <buf>.
I don't know the exact emacs commands for this off the top of my head, but one option would be to do the following:
Set the mark in the shell buffer right below the command line
Execute the command.
Move the point to the end of the file and kill the text between there and the mark.
Move to the destination buffer and yank the text into there.
Have you considered using the shell-command or shell-command-to-string functions?
The don't "send a command to a buffer" like you asked, but they do both allow running a command through a process that will be started just for that purpose and either dumping the output into a target buffer or collecting it into a string.