;;; stdio.el -- stdio routines for emacs lisp -*- lexical-binding: t; -*- ;;; Commentary: ;;; Code: (require 'cl-lib) (cl-defstruct (stdio-process (:constructor stdio-process-create) (:copier nil)) emacs-process buffer) (defun stdio-make-filter (process) "Return a filter function for PROCESS." (lambda (_ input) (setf (stdio-process-buffer process) (concat (stdio-process-buffer process) input)))) (defvar stdio--process-counter 0) (defun stdio--make-process-name () "Generate a new uniqe process name." (let* ((num stdio--process-counter) (name (format "stdio-subp-%d" num))) (setq stdio--process-counter (+ stdio--process-counter 1)) name)) (defun stdio-call (command) "Call COMMAND, return stdio-process." (let* ((process (stdio-process-create)) (emacs-process (make-process :name (stdio--make-process-name) :command command :coding 'utf-8-unix :noquery nil :connection-type 'pipe :filter (stdio-make-filter process) ))) (setf (stdio-process-emacs-process process) emacs-process) process)) (defun stdio-read-line (process) "Read next line from PROCESS." (if-let ((stdin-buf (stdio-process-buffer process)) (newline-pos (string-search "\n" stdin-buf)) (line (substring stdin-buf 0 newline-pos)) (rest (substring stdin-buf (+ 1 newline-pos)))) (progn (setf (stdio-process-buffer process) rest) line) ;; no newline character found (if (accept-process-output (stdio-process-emacs-process process)) (stdio-read-line process) ;; no more output from process (when (> (length stdin-buf) 0) (progn (setf (stdio-process-buffer process) "") stdin-buf))))) (provide 'stdio) ;;; stdio.el ends here