Elisp 中 interactive 总结

Table of Contents


一个例子

在开始之前我们先看一个例子:

(defun say-hello(name)
        (message "Hello %s" name))

我们 C-x C-e 执行一下这个代码,然后 M-x say-hello, 是不是提示没有找到这个命令,这就对了。我们再看看下面的例子。

(defun say-hello(name)
        (interactive "sEnter your name: ")
        (message "Hello %s" name))

通过 C-x C-e 执行完上面的代码以后,我们输入 M-x say-hello , 然后 minibuffer 会提示: Enter your name: ,你输入一个名称,minibuffer 就会打印出一条消息。

通过 interactive 我们就可以把一个函数变成一个可交互的命令。这样的命令我们可以通过 M-x 来执行。另一方面来说,如果一个函数没有使用 interactive, 它就不能通过 M-x 来调用,也不能通过 key binding 来使用,只能通过代码来调用。

interactive 使用

语法规则

interactive 的使用主要是:

(interactive arg-descriptor)

关于 arg-descriptor 有很多,下面一一道来。

缺省或 nil

这种情况下的命名不能带参数,如果这个命令要求有参数就会出错。例如:

(interactive)
(interactive nil)

带 string 类型参数

类似(interactive "…"), 然后 emacs 会根据第一个字符来解释用户的输入。 大约有 30 个的这个解释来做这种处理。但是常用的不是太多,这里 可以了解更多。

  • P and b
    (interactive "P\nbFrobnicate buffer: ")
    

    其中字母 P 会把命令的第一个参数设置为 raw command perfix (this), 'bFrobnicate buffer: '提示用户输入一个 buffer 的名字。

    这个提示的字符串可以使用 '%' 来包含前一个参数值。例如下面是你读入已经存在的 buffer 名称,然后跟着一个新的名字。

    (interactive "bBuffer to rename: \nsRename buffer %s to: ")
    

    P The raw prefix argument. (Note that this ‘P’ is upper case.)

    b The name of an existing buffer. By default, uses the name of the current buffer

  • n

    以一个数字作为参数

    (defun ask-age (x)
      "Ask age."
      (interactive "nEnter your age: ")
      (message "Name: %d" x))
    
  • r

    这个是表示这个函数要接受当前选中区域的开始和结束位置。这里 有更多的例子。

    (defun myMark-elisp-region (rStart rEnd)
      "Mark region as Elisp source code for org mode export."
      (interactive "r")
      (message "Region begin at: %d, end at: %d" rStart rEnd)
      (save-excursion
        (goto-char rEnd) (insert "\n#+END_SRC\n")
        (goto-char rStart) (insert "#+BEGIN_SRC emacs-lisp -n\n")))
    
  • a

    函数名称

    (defun call-a-func (x)
      (interactive "aEnter a function:")
      (funcall x))
    
  • s

    字符串

    (defun say-hello(name)
            (message "Hello %s" name))
    

传递一个 List

(defun do-something (x y)
  "Ask name and age"
  (interactive
   ;; complex code here that returns a list
   (list "Mary" 22))
  (message "Name is: %s, Age is: %d" x y))
(defun ff (name age)
  "Prompt user to enter a string, with input history support."
  (interactive
   (list
    (read-string "Enter your name:")
        (read-string "Enter your age:")))
  (message "Name is %s." name)
  (message "Age is: %s" age))