怎么通过elisp 实现执行外部函数的功能

elisp

#1

我是从vi转发过来的用户,日常中我会选中一段文本然后通过外部的函数进行处理比如:'<,'>!python -m json.tool

我想问一下,怎么样使用elisp来实现类似的功能,附带的期望能把结果输出到其他的buffer里去

多谢。

I’m vimer, usually I select the text then execute shell command like: :'<,'>!python -m json.tool

how achieve this use the emacs lisp, and with additional I want print the output in the other buffer.

thinks.


#2

你的问题重点是什么?

  1. 如何执行选中的代码,重点在获得结果
  2. 如何用 elip 实现,重点在写 elisp

如果是 1,可以用:

  • org-mode
  • quickrun

#3

你的意思是把选中区域 pipe 给 shell 程序吧?

Emacs 内置的函数 shell-command-on-region 直接就能做到,对应的快捷键是 M-|。默认行为就是输出到新的 buffer。如果按之前加个 C-u(prefix argument)就会用输出替换选中文本。


#4

自己阅读手册?(emacs) Shell


#5

多谢。

怎么样把选中区域pipe给elips程序进行处理?能提供个类似的函数?

再次感谢。


#6

问题的重点是把选中的文本左右参数传递给外部函数进行处理,打印出结果


#7

多谢,问题不是执行shell哦,是期望执行自定义的函数,把选中的文本作为参数


#8

pipe 是 shell 特有的,Emacs Lisp 沒這個概念。你的意思是用 elisp 获得选中区域吧,有两種。

Emacs 中的选中区域是用 “开始点” “结束点” 两个整数表示的。对选中区域操作的函數直接接受两个整数为参数,要获得这两个值:

一是用 interactive,用于能绑定到按鍵和 M-x 的函数。

(defun count-lines-region (start end)
  "Print number of lines and characters in the region."
  (interactive "r")
  (message (buffer-substring start end))) 

buffer-substring 用于获得文本,注意這是有文字属性的,要去掉文字属性的 plain text 用 buffer-substring-no-properties

另一種是直接用 (region-beginning)(region-end)。不推荐。


#9

如果仅仅是要实现这个功能的话,用 evil 啊,操作和 vim 一模一样


#10

你回复的回复已经回答了你的问题。

而且,你的问题只应该是「如何把区域作为输入(STDIN)传给一个外部命令,比如 python -m json.tool?」,而不用提

  • elisp,不要对可能的解决方案作假设,可能内置的命令已经能完成你的需求
  • 外部函数,python 是个外部命令,不是函数
  • pipe,执行外部命令不一定就要用 Shell

#11

自己回答一下后面实现的部分

    (let ((begin (point-min))
          (end (point-max)))
      (if mark-active
          (setq begin (region-beginning)
                end (region-end))
        (save-excursion
          (backward-word)
          (mark-word)
          (setq begin (region-beginning)
                end (region-end))))
      (message "searching for %s ..." (buffer-substring begin end))
      (push 'escape unread-command-events)
      (call-process-shell-command (concat "say -v Alex "
                             (buffer-substring begin end)) nil 0)