2

I have this on my init.el

;; magit status
(define-key evil-motion-state-map "gs" 'magit-status)

But I would like to have another binding, for C-u M-x magit-status (C-u is the universal-argument)

Something like (which obviously does not work):

;; magit status
(define-key evil-motion-state-map "ga" 'C-u magit-status)

rationale: with C-u M-x magit-status, magit allows you to supply a directory where a git repo resides, so you do not have to have an opened file that resides inside the git repo where you want to perform git actions.

  • 1
    This question has been asked numerous times. Finding all the duplicates might not be so easy, but is probably worth doing, if someone has the time. The dup I pointed to provides the answer as essentially (for this question) (define-key evil-motion-state-map "ga" (lambda (interactive) (let ((current-prefix-arg 4)) (call-interactively 'magit-status)))) – Drew Oct 7 '16 at 14:59
3

#'magit-status is fun, because its argument to interactive isn't just a string, so running it naively with call-interactively doesn't work.Instead, the function generates its own interactive arguments. Here's the interactive call inside (defun magit-status ...:

(interactive
 (list (and (or current-prefix-arg (not (magit-toplevel)))
            (magit-read-repository
             (>= (prefix-numeric-value current-prefix-arg) 16)))))

So we have to bind current-prefix-arg directly, to pretend it's been called with a prefix arg:

(define-key evil-motion-state-map "ga"
 (lambda () (interactive)
   (let ((current-prefix-arg 4))
     (call-interactively #'magit-status))))

Or, as I tested it (because I don't use evil-mode):

(global-set-key
 (kbd "C-c C-s")
 (lambda () (interactive)
   (let ((current-prefix-arg 4))
     (call-interactively #'magit-status))))

Thanks to @npostavs for the instruction on binding current-prefix-arg. The previous answer (for the purposes of transparency) was:

(global-set-key
 (kbd "C-c C-s")
 (lambda () (interactive)
   (magit-status (magit-read-repository
                  (>= (prefix-numeric-value current-prefix-arg) 16)))))
  • tks. How would you do it using call-interactively? (just so I can test it). – ninrod Oct 6 '16 at 22:33
  • "running it with call-interactively doesn't work" - it works for me, did you try it? – npostavs Oct 6 '16 at 23:43
  • @ninrod what did you want to use call-interactively for that binding it doesn't test? – zck Oct 7 '16 at 3:46
  • @npostavs I did try it. I don't see a way to pass a universal argument to it. So it does not do the desired behavior for the question, but runs magit-status on the current directory (if it's a git repo). I can only find ways to call-interactively it so it does not get a universal argument. – zck Oct 7 '16 at 3:49
  • Oh, I see, in that case just let-bind current-prefix-arg (note that this is not really related to using a string or lisp form as the argument to interactive). – npostavs Oct 7 '16 at 14:34
2

You do not need a separate keybinding to pass the universal argument to the command. Based on your current keybinding, you may simply type C-ugs.

  • I knew that, but really, I use this so often that I would like to bind it to another more comfortable sequence like ga. – ninrod Oct 6 '16 at 22:31
  • suppose I wan't to know, actually, how I can bind a key sequence, like C-x g so that this sequence actually performs another sequence, like C-u g s? But i think that is a diferent question. – ninrod Oct 6 '16 at 22:44
  • @ninrod: sorry, misunderstood your intent! – Dan Oct 6 '16 at 23:11
2

Even better, if you don't want to risk doing the wrong thing when/if magit-status is changed:

(define-key evil-motion-state-map "ga"
  (lambda () (interactive)
    (universal-argument)
    (call-interactively 'magit-status))

or to test without using evil:

(global-set-key
 (kbd "C-c C-s")
 (lambda () (interactive)
   (universal-argument)
   (call-interactively 'magit-status)))

Basically universal-argument sets up the state as if you had pressed C-u (because C-u is actually bound to universal-argument), then the next interactively-called function reads that state. If you wanted to call a function as if C-u had been pressed twice, then you would first call universal-argument and then universal-argument-more. Numeric arguments could be supplied with digit-argument and negative-argument; see simple.el for the actual code that implements all of this.

  • 1
    I just tested and zck's solution works but your's does not. +1 anyway because I did not know how to do the universal-argument stuff. rich info here. – ninrod Oct 6 '16 at 22:52

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