Emacs 用回车符覆盖

  • 本文关键字:覆盖 回车 Emacs emacs
  • 更新时间 :
  • 英文 :


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

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

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

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

您可以使用过滤器函数执行此操作。

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

// foo.c
#include <stdio.h>
main() {
  int i;
  for (i = 0; i < 10; i++) {
    printf("  count: %dr", 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))

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

最新更新