2

My aim is to get the output from a process in Emacs.

For example, M-x run-python gives me a python shell *Python* that I can send python code to. If I send print "hello world" to *Python*, I hope Emacs can know the result once the execution is finished and echo it in the mini-buffer.

Is it possible to add something like a callback?

Wenshan
  • 690
  • 6
  • 13
  • 2
    The function `start-process` has an argument to specify an output buffer, or `nil` if no output buffer is desired. In lieu of an output buffer, it is possible to use a `filter` that can send the information anywhere you want (e.g., a `*Messages*` buffer or a temporary buffer, etc.) -- including restrict what information is sent. http://www.gnu.org/software/emacs/manual/html_node/elisp/Filter-Functions.html and http://www.gnu.org/software/emacs/manual/html_node/elisp/Asynchronous-Processes.html Filters can also be used to specify what to do when certain output is matched, etc. – lawlist Sep 23 '14 at 01:43
  • 1
    See also `set-process-sentinel` to trigger action when the process has finished, etc. -- http://www.gnu.org/software/emacs/manual/html_node/elisp/Sentinels.html – lawlist Sep 23 '14 at 04:15
  • 1
    See a list of available functions: http://wikemacs.org/wiki/Emacs_Lisp_Cheat_Sheet#Processes – Ehvince Sep 23 '14 at 08:12
  • @lawlist I created a filter function to solve the problem, thanks a million – Wenshan Sep 24 '14 at 02:35
  • @Ehvince thanks for the nice pointer – Wenshan Sep 24 '14 at 02:36

1 Answers1

1

Thanks to the comments from @lawlist , I solved my problem by creating the following filter function and assigning it to the process (*MozRepl* in my case) with (set-process-filter (get-buffer-process "*MozRepl*") 'moz-controller-repl-filter)

(defun moz-controller-repl-filter (proc string)
  "Filter function of *MozRepl*.

It gets the useful output of *MozRepl*, store it in `moz-controller-repl-output` and `kill-ring`"
  (when (buffer-live-p (process-buffer proc))
    (unless (string= string "repl> ")   ; ignore empty output (page up, page down, etc)
      (setq moz-controller-repl-output
            (replace-regexp-in-string "\"\\(.+\\)\"\nrepl> " "\\1" string))
      (kill-new moz-controller-repl-output) ; append to kill-ring
      (message moz-controller-repl-output) ; show the copied content in echo area
      )
    (with-current-buffer (process-buffer proc)
      (let ((moving (= (point) (process-mark proc))))
        (save-excursion
          ;; Insert the text, advancing the process marker.
          (goto-char (process-mark proc))
          (insert string)
          (set-marker (process-mark proc) (point)))
        (if moving (goto-char (process-mark proc)))))))
Wenshan
  • 690
  • 6
  • 13
  • If you want `moz-controller-repl-output` to be a global variable, or a buffer-local variable, then yes, use `setq` and perhaps add a definition outside of the function -- e.g., `(defvar moz-controller-repl-output nil "My global or buffer-local variable . . . .")`. And, if applicable, `(make-variable-buffer-local 'moz-controller-repl-output)`. But keep in mind, you may need to use something like `with-current-buffer . . .` to obtain the value of a buffer-local variable if you are in a different buffer. Alternatively, you can use `(let ((moz-controller-repl-output . . .` short-term variables. – lawlist Sep 24 '14 at 02:53
  • 1
    @lawlist Thanks for your comment. Yes, I have `(defvar moz-controller-repl-output "" "comments...")`. – Wenshan Sep 25 '14 at 02:07