Elisp: Get universal-argument

By Xah Lee. Date: . Last updated: .

This page shows you how to make your emacs lisp command accept universal-argumentCtrl+u】 given by user.

Problem

You have written a emacs command. You want the command's behavior to be different if user presses 【Ctrl+u】 before calling your command.

Detail

Emacs has a mechanism for a command to have variant behavior if user calls universal-argumentCtrl+u】.

The purpose of universal-argument is:

  1. A convenient way to let user pass numerical argument to a command. (What the command do with number argument depends on the command.)
  2. To simply have a alternate behavior of a command. (e.g. copy file name normally, or copy full path.)

For example, type 【Ctrl+u 5 -】 and it'll insert -----, hyphen 5 times.

Ctrl+u 5 moves cursor to the right 5 times.

For example, in dired, typing w will copy the file name (dired-copy-filename-as-kill), but if you type 【Ctrl+u 0 w】, the copied name will be file full path.

Solution

To make your command aware of universal argument, there are 3 simple ways:

  1. the global variable current-prefix-arg holds the value of universal argument.
  2. Add (interactive "P") to your function. It will pass the value of current-prefix-arg to your function's first argument.
  3. Add (interactive "p") to your function. It will pass converted numerical value of current-prefix-arg to your function's first argument.

Example:

(defun f (x)
  "print argument received"
  (interactive "P")
  (message "%s" x)
  ;; value of x is from universal argument, or nil if universal-argument isn't called
)

Possible Values of Universal Argument

The following table shows the possible values of current-prefix-arg.

Key InputValue of current-prefix-argNumerical Value
No universal arg called.nil1
Ctrl+u -Symbol --1
Ctrl+u - 2Number -2-2
Ctrl+u 1Number 11
Ctrl+u 4Number 44
Ctrl+uList '(4)4
Ctrl+u Ctrl+uList '(16)16
(defun g ()
  "print `current-prefix-arg'"
  (interactive )
  (message "%s" current-prefix-arg))

;; try
;; M-x g
;; C-u M-x g
;; C-u C-u M-x g
;; C-u 1 M-x g
;; C-u 2 M-x g

(info "(elisp) Prefix Command Arguments")

Checking current-prefix-arg

Here's a example that expect all possible use of universal-argument values, by manually checking the value of current-prefix-arg, and feed it to the function's arguments.

(defun xuatest (arg1 &optional arg2 arg3)
  "Sample command to test `universal-argument'."
  (interactive
   (cond
    ((equal current-prefix-arg nil) ; no C-u
     (list 1 nil nil))
    ((equal current-prefix-arg '(4)) ; C-u
     (list 1 2 nil))
    ((equal current-prefix-arg 2) ; C-u 2
     (list 1 2 3))
    ;; more special case here

    (t ; all other cases, prompt
     (list
      (read-string "arg1:" )
      (read-string "arg2:" )
      (read-string "arg3:" )))))

  ;; now, all the parameters of your function is filled.
  ;; code body here

  (message "args are: %s %s %s" arg1 arg2 arg3)
  ;;
  )

The (interactive …) is used to fill out the parameters.

〔►see Elisp: Interactive Form

The read-string is to prompt user for input.

〔►see Elisp: Get User Input

Writing Emacs Command

  1. Elisp: How to Write Commands
  2. Elisp: Region, Active Region
  3. Elisp: Get Buffer String
  4. Elisp: Functions on Line
  5. Elisp: Cut Copy Paste to/from kill-ring
  6. Elisp: Get User Input
  7. Elisp: Get universal-argument
  8. Elisp: Find Replace String in Buffer
  9. Elisp: Using thing-at-point
Like it? Buy Xah Emacs Tutorial. Thanks.