The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.


;; Note: this isn't a pool per command. It's hard coded to use one
;; command, at a time. That's because the command in itself needs to
;; take a single line with a working dir, and a single line of input
;; to work. So that's rather special, limiting the general use.
;;
;;But it could easily become more flexible and general if needed.


(defvar scp/buffer-ready nil "Buffer object ready to run")
(defvar scp/buffer-command-running nil "Buffer object running a command")



(defun shell-command-pool ()
  "Reset a any prepared shell commands"
  (interactive)

  (and scp/buffer-ready (kill-buffer scp/buffer-ready))
  (setq scp/buffer-ready nil)

  (setq scp/buffer-command-running nil)
  (and scp/buffer-command-running (kill-buffer scp/buffer-command-running))
  )



(defun scp/prepare-shell-command (command)
  "Setup a new prepared shell command"
  (if scp/buffer-ready
      (message "Shell Command Pool already set up for (%s)" command)
    ;; TODO: Leading space to make invisible
    (let ((output-buffer (generate-new-buffer " *scp/command-shell*")))
      (start-process command output-buffer shell-file-name shell-command-switch command)
      (setq scp/buffer-ready output-buffer))
    )
  )



(defun scp/shell-command-to-string (dir command stdin-args)
  "Run 'command' using a possibly already prepared shell and
print 'stdin-args' to it. Prepare for the next call.

Return the output of running 'command', or nil on error."
  (let ((abs-dir (expand-file-name dir)))
    (if (not scp/buffer-ready) (scp/prepare-shell-command command))
    (if scp/buffer-command-running (kill-buffer
                                    scp/buffer-command-running))
    (setq scp/buffer-command-running scp/buffer-ready)
    (setq scp/buffer-ready nil)

    (let ((running-process
           (get-buffer-process scp/buffer-command-running)))
      (process-send-string
       scp/buffer-command-running
       (concat abs-dir "\n"))
      (process-send-string
       scp/buffer-command-running
       (concat stdin-args "\n"))
      (while (string= (process-status running-process) "run")
        (accept-process-output running-process)
        (sleep-for 0 100)))

    (with-current-buffer scp/buffer-command-running
      (let* (
             (raw-output (buffer-string))
             (output
             ; Added by some Emacs call-process apparently
              (replace-regexp-in-string "\nProcess[ ]+perly_sense[ ]+--stdin[ ]+\\(<[^>]*?>[ ]+\\)?finished[ ]*?\n" "" raw-output))
             \nProcess perly_sense --stdin <1> finished\n
             )
;;        (message "Pool output: (%s)" output)
        (kill-buffer scp/buffer-command-running)
        (setq scp/buffer-command-running nil)

        (scp/prepare-shell-command command)

        output))))



(provide 'shell-command-pool)