2

I am writing an elisp function that sends a command to an existing eshell buffer, waits for the command to finish, and send another command. For example, I would like to send:

python
2+3

So far I have tried the following, unsuccessfully:

1.Getting the eshell process to use process-send-string and accept-process-output:

(process-send-string eshell-proc "python")
(accept-process-output eshell-proc 100)

But I have been unable to get the eshell process. (get-buffer-process (current-buffer)) returns nil when the current buffer is eshell.

2.Inserting the command in the buffer, using (eshell-send-input), and sleeping for a bit before sending the next command:

(progn 
(insert "python")
(eshell-send-input)
(sleep-for 1)
(insert "2+3")
(eshell-send-input))

The problem with this approach is that "2+3" gets sent before the python subprocess has been launched. This happens regardless of the amount of time for which I sleep. It seems that sleeping freezes all of emacs' subprocesses?

3.Using eshell-gather-process-output: If I use either:

(eshell-gather-process-output "/usr/bin/python" nil)

or

(eshell-gather-process-output "/usr/bin/python" (list "somearg"))

I get Debugger entered--Lisp error: (wrong-type-argument arrayp nil)

But if I use:

(eshell-gather-process-output "/usr/bin/python" (vector "somearg"))

I get Debugger entered--Lisp error: (wrong-type-argument listp ["somearg"])

So I am really confused as to what type of argument this command expects. I haven't been able to find a single example of usage of this command.

Why does something so simple become so complicated? Thanks for any inputs

ealfonso
  • 6,622
  • 5
  • 39
  • 67
  • 1 - eshell does not start an external process, so this won't work - there's no process to send to. 2 works for me. – Tyler Apr 10 '13 at 21:56
  • 2 is a pretty fragile solution. Depending on the system's load, the time that it takes to launch the subprocess will vary. Under this solution, I am limited to hard-coding the expected maximum load time that I will encounter, and to wait this time for every time. This is the reason I would like an alternative. – ealfonso May 07 '13 at 05:18

1 Answers1

1

I see what you are saying but this does not seem to really be the "Emacs" way of doing things. You can just open a buffer in python-mode and send regions say 2+2 to the python interpreter. Or you can do

(python-shell-send-string "2 + 2")

or take a look at the source for python-mode, in particular this function:

(defun python-shell-send-string (string &optional process msg)
  "Send STRING to inferior Python PROCESS.
When MSG is non-nil messages the first line of STRING."
  (interactive "sPython command: ")
  (let ((process (or process (python-shell-get-or-create-process)))
      (lines (split-string string "\n" t)))
  (and msg (message "Sent: %s..." (nth 0 lines)))
  (if (> (length lines) 1)
      (let* ((temporary-file-directory
            (if (file-remote-p default-directory)
                (concat (file-remote-p default-directory) "/tmp")
              temporary-file-directory))
           (temp-file-name (make-temp-file "py"))
           (file-name (or (buffer-file-name) temp-file-name)))
      (with-temp-file temp-file-name
        (insert string)
        (delete-trailing-whitespace))
      (python-shell-send-file file-name process temp-file-name))
  (comint-send-string process string)
  (when (or (not (string-match "\n$" string))
            (string-match "\n[ \t].*\n?$" string))
    (comint-send-string process "\n")))))

The process will be similar for interfacing with processes that you want to send commands to from Emacs. If you dig into the code for the function above you will see that the python-mode is responsible for getting/starting the needed process, in this case the python interpreter.

Cory Koch
  • 470
  • 4
  • 8