Emacs Lisp: Get User Input

By Xah Lee. Date: . Last updated: .

This page is a collection of emacs lisp idioms for querying user input.

Get User Input as Arguments

Often you want a command that prompts user to enter some input. The most basic way is using the “interactive” form:

(interactive "code_letter_and_promp_string")

This expression must immediately 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:" is a tells emacs to pass what user typed as a string datatype to your command's argument.

The interactive can be used to get other types of input. Here are some basic examples.

The prompt text can follow the single-letter code.

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))

(info "(elisp) Defining Commands")

Getting Argument from universal-argument

The (interactive "P") will pass the arg from universal-argumentCtrl+u】 as your command's first argument.

See: Emacs Lisp: Get universal-argument.

Getting User Input with Name Completion and Input History

Some commands provide input history, so that user can use key to enter previous input. (➢ for example: shell-command) Also, some commands provide name completion (➢ for example: dired).

The most useful functions for getting user input with completion or history support are:

Here's a example:

(defun ff ()
  "Prompt user to enter a file name, with completion and history support."
  (interactive)
  (let ((x (read-file-name "Enter file name:")))
    (message "String is %s." arg)))

Try it. You'll have file name completion feature. Pressing will show previous file name you used.

These can be used together with interactive. You can call interactive without any special code, but have it return a list. The elements of this list will be fed to your function. Examples:

(defun ff (arg)
  "Prompt user to enter a string, with input history support."
  (interactive
   (list
    (read-string "Enter your name:")))
  (message "String is %s." arg))
(defun ff (arg)
  "Prompt user to enter a file path, with file name completion and input history support."
  (interactive
   (list
    (read-file-name "Open directory:")))
  (message "Path is %s." arg))
(defun ff (arg)
  "Prompt user to enter a elisp regex and input history support."
  (interactive
   (list
    (read-regexp "Type a regex:")))
  (message "Regex is %s." arg))

The most general command is read-from-minibuffer. All the above are implemented on top of it.

(info "(elisp) Minibuffers")

Query User for Yes/No

Sometimes you need to query user with a simple yes/no answer. Here's how:

(if (y-or-n-p "Do it?")
    (progn
      ;; code to do something here
    )
  (progn
    ;; code if user answered no.
  )
)

The y-or-n-p will ask the user to type a “y” or “n” character.

(info "(elisp) Yes-or-No Queries")

Summary

The (interactive …) has 2 important purposes.

  1. make your function callable as interactive command.
  2. a mechanism for passing interactive user input into function's arguments.

When you want your function to be a command callable by execute-extended-commandAlt+x】, add (interactive) right after the inline doc string.

There are 2 ways to use (interactive …):

  1. A string, with first character (or first few character in same cases) as a special code. The first char 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, …)
  2. A list. The most general way for interactive to fill function arguments is to have it return a list, like this (interactive (list …)). This list elements will be passed as arguments to your function.

You can query user in the middle of your function, using {y-or-n-p, read-string, …}, and many others. The most general one is read-from-minibuffer.

Like it? Buy Xah Emacs Tutorial. Thanks.