3

I have an emacs shell buffer which may or may not be running a certain interactive program such as ftp or python. I wish to write a lisp function which will interact with this program, but I would first like to make sure that said program is indeed running. My question is therefore:

Is there a Lisp function designed to inquire which program, if any, is running inside a given shell buffer?

Such programs often set their own prompt, so I thought of using

(buffer-substring (car comint-last-prompt) (cdr comint-last-prompt)) 

to determine the current prompt, but prompts often get garbled, so I found this not to be the ideal solution. Another attempt involved using

(shell-command-to-string "pgrep -fa MYPROGRAM")

but this would risk a false positive in case MYPROGRAM is running somewhere else in the system, other than under my shell buffer.

migrated from stackoverflow.com Aug 6 at 15:05

This question came from our site for professional and enthusiast programmers.

  • @sds, thanks for migrating my question to the apropriate forum! Next time I'll try to research which forum to use more carefully! – Ruy Aug 6 at 22:41
5

Here's a simple function that gets the pid of the process running in the current buffer and then calls the pstree command to get the process tree of that process:

(defun iproc ()
  (interactive)
  (let ((pid (process-id (get-buffer-process (current-buffer)))))
    (shell-command (format "pstree -p %d" pid))))

If I have a *shell* buffer running bash, run bash again to create a subshell and then run python3 in the subshell, I do M-x iproc and get the following output:

bash(4231)---bash(12567)---python3(12603)

Of course, the pids are going to be different. Also the function needs some error checking: if the current buffer does not have a process running, the function fails. Here's a slightly better version:

(defun iproc ()
  (interactive)
  (let ((process (get-buffer-process (current-buffer))))
    (if process
        (shell-command (format "pstree -p %d" (process-id process)))
      (message "No process"))))
  • That is it! Thanks a lot! – Ruy Aug 8 at 11:16
  • Glad it helped! – NickD Aug 8 at 19:44
1

You should start with Process Information:

(process-command (get-buffer-process "*Python*"))
==> ("python3" "-i")
(process-status (get-buffer-process "*Python*"))
==> run

You should not be running ftp and python under bash under Emacs, but rather use the specific modes for them (e.g., M-x run-python &c).

If you insist on doing it your way, you should use process sentinels.

  • 1
    If I understand the question, that won't give us the right information. The process-command tells us the top-level process for a comint buffer (i.e., bash in usual circumstances), but it won't tell us if that bash process is currently running a python or ftp interactive session. – Tyler Aug 6 at 17:37
  • I should have known M-x ftp existed! (I knew M-x python) – Tyler Aug 6 at 18:41
  • @Tyler: 10 years ago someone complained to me that doing grep in *shell* and copy/pasting the file names into C-x C-f prompt was tedious. I pointed them to M-x grep. ;-) – sds Aug 6 at 18:49
  • The reference to "ftp" and "python" in my question is simply supposed to illustrate what I mean by an interactive program. The fundamental point of the question is whether or not it is possible to use elisp to determine if a certain subprocess of "shell" is running. – Ruy Aug 6 at 22:35
  • @Ruy: okay, and the answer is to use sentinels. – sds Aug 7 at 2:34
0

Updated, integrated solution from @Nickd

(defun ar-process-at-point (&optional arg)
  "Report state of current process buffer.

With optional \\[universal-argument]: keep previous reports"
  (interactive "P")
  (get-buffer-create "Report Process")
  (let ((proc (format "Process: %s\n" (process-name (get-buffer-process (current-buffer)))))
    (proc-command (format "Process: %s\n" (process-command (get-buffer-process (current-buffer)))))
        (pid (progn (shell-command (format "pstree -p %d" (process-id (get-buffer-process (current-buffer)))) "Report Process")
            (with-current-buffer "Report Process" (buffer-substring-no-properties (point-min) (point-max)))))
    (fe (format "field-end (point): %s\n" (field-end (point))))
    (fb (format "field-beginning (point): %s\n" (field-beginning (point))))
    (fap (format "(field-at-pos (point)): %s\n" (field-at-pos (point))))
    (po (format "(point): %s\n" (point)))
    (lbp (format "(line-beginning-position): %s\n" (line-beginning-position)))
    (iftm (format "inhibit-field-text-motion lbp: %s\n" (let ((inhibit-field-text-motion t)) (line-beginning-position))))
    (pf (format "process-filter: %s\n" (ignore-errors process-filter)))
    (pm (format "(process-mark process): %s\n" (ignore-errors (process-mark (get-buffer-process (current-buffer)))))))
    (save-excursion
      (delete-other-windows)
      (split-window)
      (set-buffer (get-buffer-create "Report Process"))
      (unless (eq 4 (prefix-numeric-value arg)) (erase-buffer))
      (goto-char (point-max))
      (insert proc)
      (insert proc-command)
      (insert pm)
      (insert pid)
      (insert fe)
      (insert fb)
      (insert fap)
      (insert po)
      (insert lbp)
      (insert iftm)
      (insert pf)
      (newline 1)
      (unless (eq 4 (prefix-numeric-value arg)) (goto-char (point-min)))
      (display-buffer "Report Process")
      (other-buffer))))
  • 1
    Unfortunately I could not make it work, perhaps because I am not too knowledgeable about elisp. But here is what I did: in an emacs shell buffer I am running an interactive program. In that buffer I issued "ESC-x my-current-process-command RET". The minibuffer then showed "(/bin/bash -i)" but it did not mention the interactive program running under my shell, which is precisely what I am looking for. Did I do anything wrong? – Ruy Aug 7 at 12:21
  • @Ruy Updated. Originally written for use-cases, where Emacs connects to Python directly. – Andreas Röhler Aug 8 at 11:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.