help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to interact with a shell-like process behind the scenes?


From: Ship Mints
Subject: Re: How to interact with a shell-like process behind the scenes?
Date: Wed, 21 May 2025 07:10:07 -0400

On Tue, May 20, 2025 at 11:42 PM <mbork@mbork.pl> wrote:

> Hi all,
>
> I have a program which displays a prompt on stdout, accepts a line of
> input, does something with it, displays the results (possibly in many
> lines, in a known format, e.g. JSON), and shows the prompt again.
> I need Emacs to be able to interact with it, as in: send the said line
> of input and receive the said output.  I don't want the /user/ to do
> that, that is, I don't need it to be interactive in any way -- just that
> some Elisp function can "wrap" the process, as in, accept the input,
> send it to the process, and receive the output, most probably via
> a callback.  How do I do that?
>
> I read about `make-process' and `start-process', but I am a bot worried
> about making it robust.  What if the external process gets killed, for
> example?  I probably should detect it and start it anew, etc.  I have
> a feeling that it's probable that Emacs already has something which
> could help me.
>
> I'm reading now about Comint mode.  From what I see, it's not
> necessarily what I want, because I don't really need an interactive,
> REPL-like thing, but something working in the background.
>
> On the other hand, I asked an Internet parrot, and it suggested Comint
> mode with the following (obviously wrong) snippet:
>
> --8<---------------cut here---------------start------------->8---
> (require 'comint)
>
> (defun my/send-to-repl (input callback)
>   (let* ((buffer-name "*my-repl*")
>          (proc-name "my-repl")
>          (command '("my-repl-binary" "--some-arg"))
>          (proc (get-buffer-process buffer-name)))
>     (unless (and proc (process-live-p proc))
>       (setq proc
>             (make-comint-in-buffer proc-name buffer-name
>                                    (car command) nil
>                                    (cdr command))))
>     (with-current-buffer buffer-name
>       (let ((start (point-max)))
>         (goto-char start)
>         (insert input)
>         (comint-send-input)
>         (set-process-filter
>          proc
>          (lambda (proc output)
>            ;; Accumulate and call callback when prompt is detected
>            (with-current-buffer (process-buffer proc)
>              (insert output)
>              (when (string-match "my-repl-prompt>" output)
>                (let ((response (buffer-substring start (point-max))))
>                  (funcall callback response)))))))))
> --8<---------------cut here---------------end--------------->8---
>
> It's wrong because it assigns the output of `make-comint-in-buffer' to
> `proc', while the Elisp manual says that that function returns the
> /buffer/.  Another Internet parrot produced another code which starts
> with defining a minor mode - again, from what I understand, this doesn't
> make much sense, since I don't really need anything but the Fundamental
> mode (the buffer won't be used for user interaction and can even be
> a hidden one).
>
> So, should I use Comint mode for that or something else?  If so, where
> can I find examples of code using it?  From what I grepped in the Emacs
> sources, most if not all cases where Comint mode is used are for
> interactive sessions.
>
> Thanks in advance,
>

Here's someone else addressing something similar
https://github.com/milanglacier/termint.el


reply via email to

[Prev in Thread] Current Thread [Next in Thread]