如何让 Emacs 在启动时从标准输入读取缓冲区?

sas*_*nin 46 unix vim emacs

使用 Vim 我可以轻松做到

$ echo 123 | vim -
Run Code Online (Sandbox Code Playgroud)

可以用 Emacs 做吗?

$ echo 123 | emacs23
... Emacs starts with a Welcome message

$ echo 123 | emacs23 -
... Emacs starts with an empty *scratch* buffer and “Unknown option”

$ echo 123 | emacs23 --insert -
... “No such file or directory”, empty *scratch* buffer
Run Code Online (Sandbox Code Playgroud)

从unix管道读取缓冲区真的不可能吗?

编辑:作为解决方案,我编写了一个名为的 shell 包装器emacspipe

#!/bin/sh
TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP
Run Code Online (Sandbox Code Playgroud)

And*_*ood 40

您可以使用流程替换

$ emacs --insert <(echo 123)
Run Code Online (Sandbox Code Playgroud)


Tre*_*son 15

正确,从标准输入读取缓冲区是不可能的。

Emacs 信息页面中唯一提到的 stdin 是this,它说:

在批处理模式下,Emacs 不显示正在编辑的文本,标准终端中断字符如C-zC-c继续发挥其正常作用。函数prin1,princprint 输出到stdout而不是回显区域,而 whilemessage和错误消息输出到stderr。通常从 minibuffer 读取的函数stdin取而代之的是它们的输入。

并且该read函数可以从 读取stdin,但只能在批处理模式下读取。

因此,您甚至无法通过编写自定义 elisp 来解决此问题。

  • 我没有不尊重任何人的意思,但这是可恶的。这是一个非常基本的编辑器功能,GNU EMACS 已经存在了几十年。应该是内置的。 (17认同)

Ric*_*ins 14

您可以重定向到一个文件,然后打开该文件。例如

echo 123 > temp; emacs temp
Run Code Online (Sandbox Code Playgroud)

jweede 指出,如果您希望自动删除临时文件,您可以:

echo 123 > temp; emacs temp; rm temp
Run Code Online (Sandbox Code Playgroud)

Emacsy 执行此操作的方法是在 Emacs 中运行 shell 命令

M-! echo 123 RET
Run Code Online (Sandbox Code Playgroud)

这为您提供了一个名为 *Shell Command Output* 的缓冲区,其中包含命令的结果。

  • 一般来说,Emacs 和 Unix 之间存在高阻抗。或者至少在 Emacs 和传统的 Unix 工作流程之间。 (2认同)
  • @jweede 如果您想添加 M-!我对你的回答的一部分,然后我可以删除我的回答。我们的答案有很大的重叠,但我认为元爆炸对未来的读者很重要。 (2认同)

小智 10

有可能,请参阅/sf/ask/201582251/

这是emacs脚本中的echo(从上面的链接复制):

#!/usr/bin/emacs --script
(condition-case nil
    (let (line)
      (while (setq line (read-from-minibuffer ""))
        (princ line)
        (princ "\n")))
  (error nil))
Run Code Online (Sandbox Code Playgroud)

或将其读入缓冲区,然后一次性打印出来

#!/usr/bin/emacs --script
(with-temp-buffer
  (progn
    (condition-case nil
    (let (line)
      (while (setq line (read-from-minibuffer ""))
        (insert line)
        (insert "\n")))
      (error nil))
    (princ (buffer-string))
    ))
Run Code Online (Sandbox Code Playgroud)


Tom*_*ski 7

这有效:

echo 123 | emacs --insert <(cat)
Run Code Online (Sandbox Code Playgroud)

但是,出于某种原因,只能使用图形模式的 emacs(Gnome、Konsole、GNU Emacs 23.4.1)。命令:

echo 123 | emacs -nw --insert <(cat)
Run Code Online (Sandbox Code Playgroud)

生成错误“emacs:标准输入不是 tty”。在原始文本控制台中尝试时出现相同的错误。


kas*_*erd 7

之前的任何答案中都没有提到的另一种可能性是,/dev/stdin如果您选择的 Unix 变体具有它,则使用它。

简单地尝试/dev/stdin直接打开是行不通的,因为 Emacs 做了一些检查然后报告Symbolic link that points to nonexistent file. (如果 Emacs 允许您加载文件,那么尝试再次保存它,/dev/stdin很少会像用户期望的那样。)

然而/dev/stdin,与--insert论点结合确实有效:

echo 123 | emacs --insert /dev/stdin
Run Code Online (Sandbox Code Playgroud)

应该注意的是,此版本仅在使用 X 时有效。如果您需要在终端中工作的解决方案,我建议您查看另一个答案


dsh*_*erd 6

可以创建一个简单的shell功能,因为它是从标准输入读取(尽管事实上它写入临时文件,然后读取),它的工作原理。这是我正在使用的代码:

# The emacs or emacsclient command to use
function _emacsfun
{
    # Replace with `emacs` to not run as server/client
    emacsclient -c -n $@
}

# An emacs 'alias' with the ability to read from stdin
function e
{
    # If the argument is - then write stdin to a tempfile and open the
    # tempfile.
    if [[ $# -ge 1 ]] && [[ "$1" == - ]]; then
        tempfile="$(mktemp emacs-stdin-$USER.XXXXXXX --tmpdir)"
        cat - > "$tempfile"
        _emacsfun --eval "(find-file \"$tempfile\")" \
            --eval '(set-visited-file-name nil)' \
            --eval '(rename-buffer "*stdin*" t))'
    else
        _emacsfun "$@"
    fi
}
Run Code Online (Sandbox Code Playgroud)

您只需将该函数用作 emacs 的别名,例如

echo "hello world" | e -
Run Code Online (Sandbox Code Playgroud)

或者像往常一样来自文件

e hello_world.txt
Run Code Online (Sandbox Code Playgroud)

在函数中替换emacsbyemacsclient也有效。