直接回答这个问题,你肯定可以使用
start-process
和
set-process-filter
解析异步 shell 命令的输出:
(let ((proc (start-process "find" "find" "find"
(expand-file-name "~") "-name" "*el")))
(set-process-filter proc (lambda (proc line)
(message "process output: %s" line))))
(过滤函数文档)
但是,请注意上面的line
不一定是一行,可能包括多行或者断开的行。当进程或emacs决定刷新一些输出时,会调用你的过滤器:
...
/home/user/gopath/src/github.com/gongo/json-reformat/test/json-reformat-test.el
/home/user/gopath/src/github.com/gongo/json-reformat/test/test-
进程输出:helper.el
在你的情况下,这可能意味着你的端口号可能被分成两个单独的process-filter调用。
为了解决这个问题,我们可以引入一个行缓冲和行拆分的包装器,为每个进程输出行调用你的过滤器:
(defun process-filter-line-buffer (real-filter)
(let ((cum-string-sym (gensym "proc-filter-buff"))
(newline (string-to-char "\n"))
(string-indexof (lambda (string char start)
(loop for i from start below (length string)
thereis (and (eq char (aref string i))
i)))))
(set cum-string-sym "")
`(lambda (proc string)
(setf string (concat ,cum-string-sym string))
(let ((start 0) new-start)
(while (setf new-start
(funcall ,string-indexof string ,newline start))
;;does not include newline
(funcall ,real-filter proc (substring string start new-start))
(setf start (1+ new-start)));;past newline
(setf ,cum-string-sym (substring string start))))))
然后,您可以放心地期望您的代码行是完整的:
(let* ((test-output "\nREPL server started on port 59795 on host 127.0.0.1 - \nrepl://127.0.0.1:59795 Implicit target dir is deprecated, please use the target task instead. Set BOOT_EMIT_TARGET=no to disable implicit target dir.")
(proc (start-process "echo-test" "echo-test" "echo" test-output)))
(set-process-filter proc (process-filter-line-buffer
(lambda (proc line)
(when (string-match
"REPL server started on port \\([0-9]+\\)"
line)
(let ((port (match-string 1 line)))
(message "port found: %s" port)))))))
最后,我对苹果酒并不熟悉,但这种低级别的工作可能属于一种较低的模式,并且可能已经被解决了。