如何使Emacs在启动时从stdin读取缓冲区?


40

有了Vim,我可以轻松做到

$ echo 123 | vim -

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

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

编辑:作为一种解决方案,我写了一个名为emacspipe

#!/bin/sh
TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP

Answers:


15

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

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

在批处理模式下,Emacs不会显示正在编辑的文本,并且标准的终端中断字符(例如C-z和)C-c仍会正常起作用。的功能prin1princprint 输出到stdout替代的回波区,而message和错误消息输出到stderr。通常会从迷你缓冲区读取的函数stdin取而代之。

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

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


10
我的意思是不尊重任何人,但这是可恶的。这是一个非常基本的编辑器功能,GNU EMACS已经存在了数十年。它应该是内置的。
user787832

35

您可以使用流程替换

$ emacs --insert <(echo 123)

这绝对是最接近Vim功能的答案。几乎只是将管道部件移动到子流程替代中。
dbmikus 2015年

@dbmikus我不能决定,我矿和托马斯Obrębski的之间更喜欢..
安德鲁·伍德

Tomasz的结果由于某种原因使我得到以下错误:emacs: standard input is not a tty
dbmikus 2015年

哦,的确如此!我以为他在发布之前已经过测试。
安德鲁·伍德

1
也许取决于月份。
dbmikus 2015年

14

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

echo 123 > temp; emacs temp

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

echo 123 > temp; emacs temp; rm temp

Emacsy的方法是在Emacs中运行shell命令

M-! echo 123 RET

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


是的,我知道这是一种emacsy方式,但是我希望可以使用unixy方式。创建一个临时文件不是一个很好的选择(我必须记得以后将其删除)。
sastanin

1
例如:echo 123 > temp; emacs temp; rm temp
jweede

2
通常,Emacs和Unix之间存在高阻抗。或者至少在Emacs和传统的Unix工作流程之间。
理查德·霍斯金斯

2
@jweede如果要添加M-!我对你的答案的一部分,那么我可以删除我的答案。我们的答案有很多重叠之处,但我认为meta-bang对于未来的读者很重要。
理查德·霍斯金斯

1
temp可能已经存在于当前目录中,这是不安全的;作为解决方案,我写了一个包装器:TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP。谢谢大家!
sastanin

9

有可能,请参阅https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs

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

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

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

#!/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))
    ))

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
}

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

echo "hello world" | e -

或正常情况下从文件

e hello_world.txt

更换emacsemacsclient的功能工作为好。


这对我来说效果很好,但是_emacsfun应该是emacsclient -c -t $@,或者至少删除-n选项。手册页emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (现在您可以helm-swoop走上Man Glory的路!)
Alejandro

1
这是我可以使用emacsclient的唯一答案。我根据基本思想制作了一个Shell脚本,因此可以从i3 config中调用它。+1
ergosys

6

这有效:

echo 123 | emacs --insert <(cat)

但是由于某种原因,仅适用于图形模式emacs(Gnome,Konsole,GNU Emacs 23.4.1)。命令:

echo 123 | emacs -nw --insert <(cat)

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


echo 123 | exec emacs -nw --insert <(cat) </dev/tty应该管用。
–pyrocrasty

这样可行; 为什么要执行?这也适用:emacs -nw --insert <(echo 123)</ dev / tty
RoyM 2015年


5

先前的任何回答中都未提及的另一种可能性是,/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

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


我得到了emacs: standard input is not a tty在linux和bsd上测试它的消息

1
@ Chinggis6看来我的建议仅在使用X11时有效。如果我第一次输入unset DISPLAY,则会收到与您相同的错误消息。
kasperd

1
@ Chinggis6我更新我的回答指出,这需要X工作,并指出其不X.问题的解答
kasperd

2

副手,像:

$ echo 123 > tmp.txt; emacs tmp.txt

要么

$ echo 123 > tmp.txt; emacs tmp.txt; rm tmp.txt

是一个选择。Emacs只是没有像vim那样与UNIX集成。


1
令人惊讶的是,鉴于Emacs的历史以及UNIX的主要宗旨之一是“一切都是文件”,因此Emacs不能更好地与UNIX集成。将输出直接通过管道传递到Emacs感觉很直观。
SabreWolfy 2011年

5
@SabreWolfy虽然GNU Emacs最通常托管在Unix上,但它不是Vim的“ Unix程序”,而是Lisp机器,它实现了很大程度上与平台无关的文本编辑器。(请参阅Richard Hoskins的回答;执行此操作的“ Emacs方法”不是将Shell命令通过管道传递到Emacs中,而是要通过Emacs在Emacs中调用shell命令M-!,该命令会自动将结果输出捕获到临时缓冲区中。)除了战争之外,没有一个编辑比另一个“好”。他们对几乎所有事物都有不同的看法。
亚伦·米勒

除非您在外壳中并且想要做类似curl foo.bar | vim -..的事,对不起。我的意思是curl foo.bar | emacs除了您不能做之外
dylnmc '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.