Emacs如何使用回车符覆盖已有文本

3

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

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

许多进程会使用回车符来实时显示进度条,以便在终端中,进度条仅占用最终输出的一行。然而,当这个进度条被重定向到emacs缓冲区时,回车符会被保留,因此缓冲区会显示所有状态更新,使得阅读输出变得困难。
有没有办法让emacs以与终端相同的方式处理输出缓冲区中的回车符?也就是说,将指针返回到行的开头并覆盖现有的文本。
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))

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))))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接