3

我喜欢start-process-shell-command从 emacs 中启动子进程,例如编译、渲染或单元测试。我知道我可以通过提供缓冲区名称将输出重定向到缓冲区。

(start-process-shell-command "proc-name" "output-buffer-name" command)

许多进程会为实时进度条使用回车,因此在终端中,进度条在最终输出中只占一行。但是,当此进度条被重定向到 emacs 缓冲区时,会保留回车符,因此缓冲区会显示所有状态更新,因此阅读输出会很痛苦。

有没有办法让 emacs 以与终端处理回车相同的方式处理输出缓冲区中的回车?也就是说,将指针返回到行首并覆盖现有文本。

4

2 回答 2

4

您可以使用过滤功能来做到这一点。

这有点工作,但您只需要在输出中找到以 \r 终止的行,然后在缓冲区中找到旧行,删除该行,并用新行替换它。这是一个玩具版本:

// foo.c
#include <stdio.h>
main() {
  int i;
  for (i = 0; i < 10; i++) {
    printf("  count: %d\r", i);
    fflush(stdout);
    sleep(1);
  }
  printf("\n");
}

然后,您可以让每个计数行覆盖前一行(在这种情况下,通过擦除整个缓冲区。)

(defun filt (proc string)
  (with-current-buffer "foo"
    (delete-region (point-min) (point-max))
    (insert string)))

(progn 
  (setq proc
        (start-process "foo" "foo" "path/to/foo"))
  (set-process-filter proc 'filt))
于 2013-10-16T15:47:27.683 回答
0

从 seanmcl 的过滤器功能开始,我添加了更多细节,以使过滤器能够以与 bash shell 相同的方式处理回车符和换行符。

;Fill the buffer in the same way as it would be shown in bash
(defun shelllike-filter (proc string)
  (let* ((buffer (process-buffer proc))
         (window (get-buffer-window buffer)))
    (with-current-buffer buffer
      (if (not (mark)) (push-mark))
      (exchange-point-and-mark) ;Use the mark to represent the cursor location
      (dolist (char (append string nil))
    (cond ((char-equal char ?\r)
           (move-beginning-of-line 1))
          ((char-equal char ?\n)
           (move-end-of-line 1) (newline))
          (t
           (if (/= (point) (point-max)) ;Overwrite character
           (delete-char 1))
           (insert char))))
      (exchange-point-and-mark))
    (if window
      (with-selected-window window
        (goto-char (point-max))))))
于 2014-01-10T14:45:53.290 回答