73

在 vi[m] 中,有一个!命令可以让我通过 shell 命令管道文本——比如排序或缩进——并将过滤后的文本返回到缓冲区。在 emacs 中是否有等价物?

4

3 回答 3

122

您可以选择一个区域并输入`Cu M-| command RET',并且由于 shell-command-on-region 的交互式前缀参数,它用同一缓冲区中的命令输出替换了该区域。

于 2008-10-16T00:27:06.460 回答
18

几年前我写了这个,它可能会对你有所帮助:

(defun generalized-shell-command (command arg)
  "Unifies `shell-command' and `shell-command-on-region'. If no region is
selected, run a shell command just like M-x shell-command (M-!).  If
no region is selected and an argument is a passed, run a shell command
and place its output after the mark as in C-u M-x `shell-command' (C-u
M-!).  If a region is selected pass the text of that region to the
shell and replace the text in that region with the output of the shell
command as in C-u M-x `shell-command-on-region' (C-u M-|). If a region
is selected AND an argument is passed (via C-u) send output to another
buffer instead of replacing the text in region."
  (interactive (list (read-from-minibuffer "Shell command: " nil nil nil 'shell-command-history)
                     current-prefix-arg))
  (let ((p (if mark-active (region-beginning) 0))
        (m (if mark-active (region-end) 0)))
    (if (= p m)
        ;; No active region
        (if (eq arg nil)
            (shell-command command)
          (shell-command command t))
      ;; Active region
      (if (eq arg nil)
          (shell-command-on-region p m command t t)
        (shell-command-on-region p m command)))))

我发现这个功能非常有用。如果您发现它也有用,我建议将其绑定到某个功能键以方便使用,我个人使用F3

(global-set-key [f3] 'generalized-shell-command)
于 2008-10-16T00:58:28.707 回答
10

后期编辑:尽管我很欣赏这些赞成票,但 Jurta 的回答是要走的路。Greg 的 hack 比我的更简洁。

我会把剩下的留在这里,因为它可能是值得的,但是......


M-x shell-command-on-region,默认情况下似乎绑定到M-|


我看到这并不完全符合 Rohit 的要求。使用C-h f shell-command-on-region表明所需的行为在命令的非交互式版本中可用(通过将参数设置replace为非零)。我们应该能够编写一个包装器来做到这一点。

试试这个(加载它*scratch*并运行M-x eval-buffer,如果它工作,将它复制到你的 .emacs 文件):

(defun shell-command-on-region-replace (start end command)
  "Run shell-command-on-region interactivly replacing the region in place"
  (interactive (let (string) 
         (unless (mark)
           (error "The mark is not set now, so there is no region"))
         ;; Do this before calling region-beginning
         ;; and region-end, in case subprocess output
         ;; relocates them while we are in the minibuffer.
         ;; call-interactively recognizes region-beginning and
         ;; region-end specially, leaving them in the history.
         (setq string (read-from-minibuffer "Shell command on region: "
                            nil nil nil
                            'shell-command-history))
         (list (region-beginning) (region-end)
               string)))
  (shell-command-on-region start end command t t)
  )

请注意,正如我在评论中所说,这不是一件非常容易做的事情。但我认为它有效。


对于不知道如何选择区域的任何读者:

  1. 将“点”(当前光标位置)移动到区域的一端,并使用C-space激活“标记”
  2. 将点移动到区域的另一端
  3. 大功告成,调用命令
于 2008-10-15T22:43:29.977 回答