Elisp: Interactive Form

By Xah Lee. Date: .

The most basic way of getting user input is by the “interactive” form:

(interactive "code_letter_and_promp_string")

The interactive expression must come right after the doc string.

(defun ask-name (x)
  "Ask name."
  (interactive "sEnter your name: ")
  (message "Name: %s" x))

The first letter s in "sEnter your name:" tells emacs to pass what user typed as a string datatype to your function's argument.

Get Number as Argument

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

The first letter n in "sEnter your age:" tells emacs to pass what user typed as a number datatype to your function's argument.

Get Region Begin End Positions as Argument

Here's a function taking region beginning and end positions as argument.

(defun print-region-boundary (x y)
  "Prints region start and end positions"
  (interactive "r")
  (message "Region begin at: %d, end at: %d" x y))

Note the (interactive "r"). The "r" is a code that tells emacs that the function will receive the buffer's begin/end text selection positions as its argument.

Purpose of interactive form

The interactive has 2 purposes.

  1. Make elisp function callable as interactive command.
  2. A mechanism for passing arguments to function when called interactively.

A function with the interactive clause is called a command, and can be called by execute-extended-command (that is, pressing 【Alt+x】).

There are 3 ways to use interactive:

  1. (interactive) → No argument. This simply makes the function as command, and does not pass any argument to the function.
  2. (interactive "…") → Pass it a string, with first character (or first few character in same cases) tells emacs how to interpret the user input (such as string, number, file name, directory name, regex, lisp expression, key stroke, region begin/end position, etc) and what datatype it should be converted to as your function's argument. (string, number, …)
  3. (interactive (list …)) → Pass it a list. The most general way for interactive to fill function arguments is to pass it list, like this (interactive (list …)). This list elements will be passed as arguments to your function. Usually, it's like this (interactive some_lisp_code) where some_lisp_code evaluates to a list.

The (interactive string) form takes a single-letter code in the beginning of string to indicate how the function gets its arguments from user.

The prompt text can follow the single-letter code.

There are about 30 codes for interactive, but the most useful are the following:

If your function takes multiple inputs, you can promp user multiple times, using a single interactive call, with mulitple lines, each line begin with a prompt code.

(defun ask-name-and-age (x y)
  "Ask name and age"
  (interactive "sEnter you name:
nEnter your age: ")
  (message "Name is: %s, Age is: %d" x y))

For complete list of interactive code, see (info "(elisp) Defining Commands")

Passing Interactive a List

Here's a example of using interactive and passing it a 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))
Liket it? Put $1 at patreon. Or Buy Xah Emacs Tutorial. Thanks.