我喜欢使用start-process-shell-command
从emacs中启动子进程,例如编译,渲染或单元测试。我知道我可以通过给出缓冲区名称将输出重定向到缓冲区。
(start-process-shell-command "proc-name" "output-buffer-name" command)
许多进程将使用回车进行实时进度条,以便在终端中进度条在最终输出中只占用一行。但是,当此进度条重定向到emacs缓冲区时,将保留回车符,因此缓冲区显示所有状态更新,这使得读取输出变得很麻烦。
有没有办法让emacs以与终端处理回车相同的方式处理输出缓冲区中的回车?也就是说,将指针返回到行的开头并覆盖现有文本。
答案 0 :(得分:4)
您可以使用a filter function执行此操作。
这有点工作,但你只需要在输出中找到由\ r \ n终止的行,然后找到缓冲区中的旧行,删除行,并用新行替换它。这是一个玩具版本:
// 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))
答案 1 :(得分: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))))))