1

As I'm running out of easy key bindings I'm trying to overload C-SPC to either call set-mark-command or er/expand-region depending on if I have moved since I set the mark. However the two functions take slight different prefix constructs "P" vs "p". How can I declare a function that wraps the two functions and passes the right sort of prefix to them?

Here is the code I have so far:

(defun my-mark-or-expand-dwim (arg)
  "Set the mark or if mark already set call expand-region."
  (interactive "P")
  (if (and mark-active
           (eq (point) (mark)))
      (er/expand-region arg)
    (set-mark-command arg)))

EDIT TO EXPLAIN ANSWER: I accepted my own answer as that solved the question as-posed however using call-interactively is the solution I ended up using in my own init file.

stsquad
  • 4,626
  • 28
  • 45
  • 1
    My understanding is that you should be able to pass the raw prefix argument to both functions as you are doing now. Those functions can either keep the raw arg or convert that to a numerical arg depending on if that function's `interactive` code is `"P"` or `"p"`. – Kaushal Modi Jul 13 '15 at 19:36
  • 1
    [Related - What is a raw prefix argument? (capital P in interactive)](http://emacs.stackexchange.com/q/13886/115) – Kaushal Modi Jul 13 '15 at 19:38
  • @kaushalmodi: close thanks - I needed to convert the raw prefix for the sake of er/expand-region or it got confused. – stsquad Jul 13 '15 at 19:47

2 Answers2

3

Try the below snippet.. it uses call-interactively. So the arguments to the wrapper function will be passed on to the inner functions and then the interactive forms in those functions should do their job.

(defun my-mark-or-expand-dwim ()
  "Set the mark or if mark already set call expand-region."
  (interactive)
  (if (or (use-region-p)
          (and mark-active
               (eq (point) (mark))))
      (call-interactively #'er/expand-region)
    (call-interactively #'set-mark-command)))
Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
1

So (interactive "P") provides the function with the raw prefix which can be converted into the other types. So in my case I did the following:

(defun my-mark-or-expand-dwim (arg)
  "Set the mark or if mark already set call expand-region."
  (interactive "P")
  (if (or (use-region-p)
          (and mark-active
               (eq (point) (mark))))
      (er/expand-region (prefix-numeric-value arg))
    (set-mark-command arg)))

The (prefix-numeric-value arg) converts from raw to what an (interactive "p") function would get. The addition of the (use-region-p) clause is a allows me to keep repeating the er/expand-region call.

stsquad
  • 4,626
  • 28
  • 45
  • It doesn't make sense why this would work.. the `(interactive "p")` inside `er/expand-region` is anyways going to call `prefix-numeric-value`. The `interactive` code doesn't tell what type of argument the function expects.. it tells how the argument is going to get interpreted in the function. – Kaushal Modi Jul 13 '15 at 20:11
  • Ah! Because you are not calling them interactively... – Kaushal Modi Jul 13 '15 at 20:15
  • You are allowed to accept your own answer. Doing that lets readers know that the question has been answered. – Drew Jul 15 '15 at 01:27