emacs lisp call function with prefix argument programmatically - emacs

I want to call a function from some elisp code as if I had called it interactively with a prefix argument. Specifically, I want to call grep with a prefix.
The closest I've gotten to making it work is using execute-extended-command, but that still requires that I type in the command I want to call with a prefix...
;; calls command with a prefix, but I have to type the command to be called...
(global-set-key (kbd "C-c m g")
(lambda () (interactive)
(execute-extended-command t)))
The documentation says that execute-extended-command uses command-execute to execute the command read from the minibuffer, but I haven't been able to make it work:
;; doesn't call with prefix...
(global-set-key (kbd "C-c m g")
(lambda () (interactive)
(command-execute 'grep t [t] t)))
Is there any way to call a function with a prefix yet non-interactively?

If I'm understanding you right, you're trying to make a keybinding that will act like you typed C-u M-x grep <ENTER>. Try this:
(global-set-key (kbd "C-c m g")
(lambda () (interactive)
(setq current-prefix-arg '(4)) ; C-u
(call-interactively 'grep)))
Although I would probably make a named function for this:
(defun grep-with-prefix-arg ()
(interactive)
(setq current-prefix-arg '(4)) ; C-u
(call-interactively 'grep))
(global-set-key (kbd "C-c m g") 'grep-with-prefix-arg)

Or you could just use a keyboard macro
(global-set-key (kbd "s-l") (kbd "C-u C-SPC"))
In this example, the key combination "s-l" (s ("super") is the "windows logo" key on a PC keyboard) will go up the mark ring, just like you if typed "C-u C-SPC".

Related

bind key to negative-argument + command in emacs

I am trying to bind to M-b a command preceded by a negative argument. I post my code.
working
(global-unset-key (kbd "M-f"))
(global-set-key (kbd "M-f") 'forward-whitespace)
not working
(global-unset-key (kbd "M-b"))
(global-set-key (kbd "M-b") (lambda () (interactive) (negative-argument(forward-whitespace))))
How can I make it working?
The specific issue you have is solved easily:
(global-set-key (kbd "M-b") (lambda () (interactive) (forward-whitespace -1)))
You might wonder if you can write a macro that would call an arbitrary command interactively with negative argument.
It is not really hard:
(defmacro call-with-negative-argument (command)
`(lambda ()
(interactive)
(prefix-command-preserve-state)
(setq prefix-arg '-)
(universal-argument--mode)
(call-interactively ,command)))
(global-set-key (kbd "...") (call-with-negative-argument forward-whitespace))
but, really, any compliant function would also work fine like this:
(defmacro call-with-negative-argument (command)
`(lambda ()
(interactive)
(,command -1)))

how to bind helm-do-grep-1 to a key in emacs?

I am using the following.
(global-set-key [f9] 'helm-do-grep-1)
But when I press f9, It complains wrong type argument. I just want it behavior like "C-u C-c h g" to grep recursively. But type so many keys is boring.
update:
I need to grep recursively. helm-do-grep run in non-recursive mode.
You can use
(global-set-key [f9]
(lambda ()
(interactive)
(let ((current-prefix-arg 't))
(call-interactively 'helm-do-grep))))
Upd. If you're interested: the version with kbd sequence
(global-set-key [f9]
(lambda ()
(interactive)
(let ((minibuffer-message-timeout 0))
(execute-kbd-macro (read-kbd-macro "C-u C-c h g C-x Q"))))
See the definition of C-x Q here https://stackoverflow.com/a/28435402/1937596
As the error message already points out, the function helm-do-grep-1 has one argument: https://github.com/emacs-helm/helm/blob/master/helm-grep.el#L810
Probably what you wanted is binding f9 to helm-do-grep which calls helm-do-grep-1 in return with the correct parameters (
https://github.com/emacs-helm/helm/blob/master/helm-grep.el#L1129)
(global-set-key [f9] 'helm-do-grep)
Update:
You can find several solutions to your question here: http://www.reddit.com/r/emacs/comments/2dxj69/how_do_make_helmdogrep_to_do_recursive_always/
To show another possibility you could also do the following:
(global-set-key [f5]
(lambda ()
(interactive)
(call-interactively (key-binding (kbd "C-c h g")))))
In that case, you call helm-do-grep using <f5> and the recursive approach with C-u <f5>. However, this approach will depend on your key bindings.

Emacs: how to get the global shortcut value

I have the following global keyboard shortcut in Emacs:
(global-set-key (kbd "C-<right>") 'forward-word)
For the org-mode I decided to redefine this shortcut. If the cursor stands on a link, then go to the link location. Otherwise - use forward-word function.
(defun is-link-p ()
(if (org-in-regexp org-bracket-link-regexp)
t))
(defun follow-link-or-next-word ()
(interactive)
(if (is-link-p)
(org-open-at-point)
(forward-word)))
(add-hook 'org-mode-hook (lambda ()
(define-key org-mode-map (kbd "C-<right>") 'follow-link-or-next-word)))
Is it possible to change org-mode shortcut in the following manner: instead of calling (forward-word), find what function is globally bound to "C-<right>" and call it instead.
Thus I won't need to change (forward-word) twice in case I decide to change the global shortcut.
I think you're looking for the function (lookup-key keymap key &optional accept-defaults)
This function returns the definition of key in keymap. All the other
functions described in this chapter that look up keys use lookup-key.
Here are examples:
(lookup-key (current-global-map) "\C-x\C-f")
⇒ find-file
(lookup-key (current-global-map) (kbd "C-x C-f"))
⇒ find-file
You could extend your functions:
(defun is-link-p ()
(if (org-in-regexp org-bracket-link-regexp)
t))
(defun follow-link-or-default-action()
(interactive)
(let ((global-default (lookup-key (current-global-map) (kbd "C-<right>"))))
(if (is-link-p)
(org-open-at-point)
(funcall global-default))))
(add-hook 'org-mode-hook (lambda ()
(define-key org-mode-map (kbd "C-<right>") 'follow-link-or-default-action)))

How can I bind compile using comint to a key combination

I currently bind compile to C-x c. I know I can run compile in comint mode by using C-u C-x c but I'd prefer to just bind it to C-x c directly. I can't fathom how to do this without copying the whole of the compile function from compile.el, tweaking it and binding that. Is there a better way?
Edit: To clarify my sloppy language, I don't wish to bind C-x c whilst in comint mode. I wish to cause C-x c to run 'compile using comint mode. I currently have C-x bound to 'compile. I can do what I want by typing C-u C-x c but I'd prefer to just be able to type C-x c to do that.
I think this works...
(defun c-w-c ()
(interactive)
(call-interactively 'compile t (vector 21 (this-command-keys-vector))))
(global-set-key (kbd "C-x c") 'c-w-c)
the '21' prepended into the vector is the ctrl-u prefix key, and it seems to fool the compile function into thinking it was called with C-u C-x c.
Edit:
It didn't work, but this does:
(defun c-w-c ()
(interactive)
(setq current-prefix-arg '(4))
(call-interactively 'compile))
You can do something like this :
(global-set-key [(C-f5)] 'compile)
(global-set-key [(f5)] 'recompile)
It binds compile to C-f5 and each time you want to recompile with the same command as you've given in compile, just type f5. It works whatever the major mode you're currently in.
For your case, do like this :
(global-set-key [?\C-x ?c] 'compile)
Are you asking for this?
(define-key comint-mode-map (kbd "C-x c") 'compile)
This works too:
(define-key comint-mode-map (kbd "C-x c")
(lambda (command)
(interactive
(list
(let ((command (eval compile-command)))
(if (or compilation-read-command current-prefix-arg)
(compilation-read-command command)
command))))
(compile command t)))
It's ugly because it duplicates the "interactive" spec from the compile command.

.emacs global-set-key and calling interactive function with argument

In my .emacs i have the following function that transposes a line
(defun move-line (n)
"Move the current line up or down by N lines."
(interactive "p")
(let ((col (current-column))
start
end)
(beginning-of-line)
(setq start (point))
(end-of-line)
(forward-char)
(setq end (point))
(let ((line-text (delete-and-extract-region start end)))
(forward-line n)
(insert line-text)
;; restore point to original column in moved line
(forward-line -1)
(forward-char col))))
And I bind a key to it like this
(global-set-key (kbd "M-<down>") 'move-line)
;; this is the same as M-x global-set-key <return>
However, I want to bind M-up to move-line (-1) But I cant seem to be able to do it correctly:
;; M-- M-1 M-x global-set-key <return>
How do I define the above using global-set-key to call move-line -1?
Not minutes after asking the question I figured it out by copy+pasting code. However I have no clue how it works.
(global-set-key (kbd "M-<up>") (lambda () (interactive) (move-line -1)))
global-set-key only takes 2 arguments: the key sequence and the command you want to bind to it. So
(global-set-key (kbd "M-<down>") 'move-line)
works fine. But if you want to use move-line with an argument you need to wrap it in an anonymous (aka lamba) function so that it presents itself to global-set-key as one value.
You can simply ask for the number of lines you want and convert the input string into an integer:
(global-set-key (kbd "M-<up>")
(lambda ()
(interactive)
(move-line (string-to-int (read-string "Lines: ")))))
I found this when I had the same problem, but I ended up solving it in another way.
(global-set-key (kbd "M-<down>") 'move-line)
(global-set-key (kbd "M-<up>") (kbd "C-u -1 M-<down>"))
Definitely not a perfect solution, since M-<down> could be reassigned and C-u -1 might not make sense on it, but since it's just my local init file, it should be no problem.
Also this obvious only works well for keyboard commands that you want to have reversed.
You might want to check out the "transpose-lines" built-in function.