This a follow up to my earlier question Why does multiple-cursors use the same char for all cursors with iy-go-to-char, but not with zap-up-to-char?.

As I describe in that question, for some commands that prompt for a character in the mini-buffer multiple-cursors will repeat the prompting for each cursor, but for others it will happily prompt only once and use that character for all cursors. In particular, for iy-go-to-char multiple-cursors prompts only once, but for zap-up-to-char it prompts per cursor.

Now, oddly enough for zap-to-char the prompting also happens only once, not once per cursor! My question is why does this happen? As far as I can tell the difference is caused by their different calls to interactive:

  • zap-up-to-char uses the seemingly sensible (interactive "p\ncZap up to char: "),

  • zap-to-char instead has:

    (interactive (list (prefix-numeric-value current-prefix-arg)
                       (read-char "Zap to char: " t)))

That is indeed the cause because taking the implementation of zap-up-to-char from misc.el and replacing the interactive call with one similar to the one zap-to-char uses produces a version of zap-up-to-char that, when used with multiple-cursors, only prompts once (not once per cursor):

(defun mc-friendly/zap-up-to-char (arg char)
  (interactive (list (prefix-numeric-value current-prefix-arg)
                     (read-char "Zap up to char: " t)))
  (let ((direction (if (>= arg 0) 1 -1)))
    (kill-region (point)
                   (forward-char direction)
                       (search-forward (char-to-string char) nil nil arg)
                     (backward-char direction))

Why does changing the call to interactive have that effect?


This is because read-char is advised to have special behaviour. When running in 'multiple-cursors-mode' it caches the character read the first time. If this cache is full then it does not ask for a character again.

Whatever function is called by "c" in the interactive description is not advised in this way.

The implementation is incredibly hackish: for example if you have multiple calls to read-char in the same interactive specification you get nonsense. unfortunately I don't see how to improve the situation.

  • 5
    As far as I can tell, the only real solution to this problem is to remove the read-char special handling and have everything behave worse, but the same. I'd be happy to see alternative solutions.
    – Magnar
    Dec 16 '15 at 8:51
  • 1
    "c" in the interactive call seems to directly call the C function Fread_char (that's the C primitive underlying the Emacs Lisp function read-char).
    – Omar
    Dec 18 '15 at 21:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.