Search code examples
emacselispcompatibilitybackwards-compatibility

backward compatibility for (interactive "^") in Emacs 22


In Emacs 23 and 24, the following works fine:

(defun foo (&optional arg)
  (interactive "^p")
  (message "arg is %i" arg))

In Emacs 22, I get the following error:

Invalid control letter `^' (136) in interactive calling string

I tried this:

(defun foo (&optional arg)
  (interactive (concat (if (> emacs-major-version 22) "^" "") "p"))
  (message "arg is %i" arg))

but I get:

Wrong type argument: listp, "^p"

What is the best way to use ^ in Emacs 23 or 24 but not in Emacs 22?


Solution

  • You could define a macro that expands to a defun, where the interactive form would start with a ^ if shift selection is supported. For example:

    (defmacro my-defun (name args doc inter &rest body)
      "Like `defun' but enables shift selection, if supported.
    
    Note that the documentation string and the `interactive' form
    must be present. Requires a string literal as argument to
    `interactive'.
    
    See `this-command-keys-shift-translated' for the meaning of shift
    translation.
    
    This is implemented by adding the `^' token to the `interactive'
    string, when shift selection is supported."
      `(defun ,name ,args
         ,doc
         ,(progn
            (assert (stringp doc))
            (assert (listp inter))
            (assert (eq (length inter) 2))
            (assert (eq (car inter) 'interactive))
            (let ((s (nth 1 inter)))
              (assert (stringp s))
              (if (fboundp 'handle-shift-selection)
                  (setq s (concat "^" s)))
              (list 'interactive s)))
         ,@body))