how to use occur in global-set-key - emacs

I'd like to list subroutine and function in fortran.
I think occur-mode looks promising but have to give regexp as a argument whenever I want to get list.
So, I want to make a key binding for automating listing as follows
(global-set-key (kbd "<f6>") (lambda () (occur '^[ ]*\(subroutine\|function\)')))
but I got error as
Wrong type argument: commandp, (lambda nil (occur (quote subroutine)))
I am not familiar Emacs Lisp. Also, it would helpful if I could get this function with neotree.

Related

Why does key binding cause Emacs to execute my function on startup?

I have a function in my Emacs init.el file that lets me rebuild and byte-compile it from a literate source file. It consists of a lambda function wrapped by defun and works exactly as I expect. So far, so good.
(defun tangle-init-and-reload ()
"Tangle the code blocks in init.org, byte-compile, and reload."
(lambda ()
(interactive)
;; Don't run hooks when tangling.
(let ((prog-mode-hook nil))
(org-babel-tangle-file (concat user-emacs-directory "init.org"))
(byte-compile-file (concat user-emacs-directory "init.el"))
(load-file user-init-file))))
When I read about functions in Elisp, it appears to me that I should be able to simply use defun to define a named function and skip the lambda, so I removed the lambda and otherwise left the function intact, like so:
(defun tangle-init-and-reload ()
"Tangle the code blocks in init.org, byte-compile, and reload."
(interactive)
;; Don't run hooks when tangling.
(let ((prog-mode-hook nil))
(org-babel-tangle-file (concat user-emacs-directory "init.org"))
(byte-compile-file (concat user-emacs-directory "init.el"))
(load-file user-init-file)))
Written this way, the function also works as expected -- as long as I call it with M-x tangle-init-and-reload RET. If I assign it a key binding, it executes on startup with one of two different side effects: With some key bindings, it attempts to overwrite init.elc while Emacs still has it open, and with others it successfully overwrites init.elc, but then re-executes on reload, causing an infinite recursion.
I'm perfectly happy to stick with the lambda version, which has no issues with key binding, but I would like to understand what magic lambda is performing and/or what it is about key binding that causes the second version to execute at startup. Can anybody explain?
For whatever it's worth, my key bindings are in a custom minor mode like so:
(defvar custom-map (make-keymap)
"Custom key bindings.")
(define-key custom-map (kbd "C-c C-i") (tangle-init-and-reload))
(define-minor-mode custom-bindings-mode
"Activates custom key bindings."
t nil custom-map)
When you define the key binding, you associate a key to a value, which in your case is:
(tangle-init-and-reload)
This is an expression that is evaluated normally, ie. you call the function when you associate the binding.
In the previous version, evaluating the same function returned a closure, you had one level of indirection, so you established a binding from a key to the function returned by the call to tangle-init-and-reload.
You can simply give the name of the function associated with the binding, by quoting it:
(define-key custom-map (kbd "C-c C-i") 'tangle-init-and-reload)

Programatically insert text into command that normally blocks event loop

I'd like to implement a command that types the first few characters into an existing command and lets me type the rest.
For example, a variant of icicle-execute-extended-command that starts with "icicle-" already entered.
I have tried:
keyboard macros
fail (even on simple things like M-x i c i c l e s) for no apparent reason.
functions
calling icicle-execute-extended-command block the command sequence
How would I go about doing this in a generalized manner?
Nice question.
Here's something generic you can try:
(defun no-mondays ()
(interactive)
(minibuffer-with-setup-hook
(lambda()
(insert "monday"))
(call-interactively 'query-replace)))
And here's a refactoring:
(defun with-initial-minibuffer (str fun)
`(lambda ()
(interactive)
(minibuffer-with-setup-hook
(lambda ()
(insert ,str))
(call-interactively ',fun))))
(defalias 'no-weekends
(with-initial-minibuffer
"\\(?:satur\\|sun\\)day"
'query-replace-regexp))
If you are calling completing-read yourself in your command definition, then just pass the text to insert as the INITIAL-INPUT argument. That's what it's for.
If you use icicle-define-command or icicle-define-file-command (so that your command will be a multi-command), then same thing: pass the INITIAL-INPUT arg.
If you use such a macro, be sure to put something like this in the file that defines the command, so the macro definition is available a byte-compilation time:
(eval-when-compile
(or (condition-case nil
(load-library "icicles-mac") ; Use load-library to ensure latest .elc.
(error nil))
(require 'icicles-mac)))

emacs map several keystrokes and command to one key

I'm trying to map c-u m-x indent-pp-sexp to a single key, like F5, so that working with Emacs doesnt erode my fingerprints.
I use (global-set-key (kbd "C-u M-x indent-pp-sexp") "<f5>") but i'm getting the following error:
global-set-key: Key sequence C-u M-x i n d e n t - p p - s e x p starts with non-prefix key C-u
EDIT
With this lambda function (global-set-key (kbd "<f5>") (lambda (interactive) (universal-argument) (indent-pp-sexp t)))
Getting error:
recursive-edit: Wrong type argument: commandp, (lambda (interactive) (universal-argument) (indent-pp-sexp t))
Weird, because univeral-argument takes no parameters, and indent-pp-sexp takes boolean
You have the arguments the wrong way around, and you bind keys to functions, not to other key sequences. Perhaps you are really looking for a named macro; or you can write some actual Lisp and bind that to F5:
(global-set-key (kbd "<f5>")
(function (lambda () (interactive) (indent-pp-sexp t) )) )
The presence of an argument in the call form appears to be sufficient to select the prefix argument functionality.
You're missing the argument list to the lambda. Additionally I think passing t to indent-pp-sexp negates the need to call universal-argument.
(global-set-key (kbd "<f5>") #'(lambda ()
(interactive)
(indent-pp-sexp t)))
I'm a noob like you, but I already happened to figure basic things like making macros. I don't really know what's wrong with your code, but here's walkthrough of how I do things at home. What you need to do first, is press F3. Then type your keystrokes, and when finished, press F4. Congratulations, you have defined an anonymous macro. You can replay it as many times you wish by pressing F4 again. When you have played enough, enter M-x name-last-keybord-macro, and name it eg. foobar. Go to your ~/.emacs.d/macros/ directory (make it if you don't have one) and visit a file that you will name foobar.el. In its buffer, M-x insert-kbd-macro. When asked about name, say foobar. You will see that emacs has entered the contents of your just recorded macro into the file. Save it. Open your .emacs file, and add lines:
(load (expand-file-name "~/.emacs.d/macros/foobar.el"))
(global-set-key (kbd "M-<f5>") 'foobar)
And things start working for me after restart, with M-F5 as the binding for foobar.el macro.

Why is (commandp '(customize-option 'foo)) nil?

I want to bind customize-option for a certain variable to a key, since I need to change it rather often. I have two options:
(global-set-key (kbd "<f12>") '(lambda() (interactive) (customize-option 'my-variable) ) )
(global-set-key (kbd "<f12>") '(customize-option 'my-variable )
The first one works, the second does not, because commandp complains that customize-option is not a command. Why? As far as I know, customize-option is an interactive function, so commandp should be t:
customize-option is an interactive compiled Lisp function.
It is bound to .
(customize-option SYMBOL)
Customize SYMBOL, which must be a user option variable.
It is the form (customize-option 'my-variable) which is not a command. You cannot bind to an arbitrary quoted form, any more than you can bind to a literal string or an unbound symbol. Some of those would be useful to bind to, but it's not hard to work around the limitations. Write a macro if you find it hard to live with. (As the saying goes, now you have two problems.)
The second argument to global-set-key must be a command definition, typically a symbol naming an interactive function. An interactive function is a function that begins with the (interactive) form. For example:
(defun delete-to-end ()
"Delete text from point to the end of buffer."
(interactive)
(delete-region (point) (point-max)))
This defines an interactive function and assigns it to the symbol delete-to-end. After that, delete-to-end is a valid command that you can pass to global-set-key:
(global-set-key [f12] 'delete-to-end)
Without the (interactive) line, delete-to-end would still name a function callable from Lisp programs, but it would not be a "command". Since it is marked interactive, (commandp 'delete-to-end) returns true, and M-x delete-to-end works.
Interactive functions don't need to be bound to a symbol, they can be anonymous. Like any other anonymous functions, they are created using a lambda form, except that for commands it must also include (interactive). Anonymous commands can be passed as the second argument to global-set-key without assigning them to a symbol, so the following definition is equivalent to the one above:
(global-set-key [f12]
(lambda ()
"Delete text from point to the end of buffer."
(interactive)
(delete-region (point) (point-max))))
...except it's somewhat less readable, and looks uglier when inspected with C-h c
or C-h k.
In your case, the first call to global-set-key is given a valid command (a quoted lambda form is itself a valid function), but the second one isn't, it is given a two-element list that can neither be called nor satisfies the requirement of being marked "interactive".

"Wrong type argument: commandp" error when binding a lambda to a key

I am getting a "Wrong type argument: commandp, (lambda nil (forward-line 5))" here.
(global-set-key [?\M-n] (lambda () (forward-line 5)))
What is the error? I'm fairly sure it's simple & I'm missing something obvious.
global-set-key expects an interactive command. (lambda () (interactive) (forward-line 5)) ought to work.
By the way, C-h f commandp is a pretty good starting point for errors like that.
The correct form should be this -
(global-set-key (kbd "M-n") (lambda () (interactive) (forward-line 5)))
The problem was that you forgot to put (interactive) (as brendan mentioned).
By the way, you will notice that I used the (kbd) function for specifying the key-binding. That function is immensely useful since you can put the key-bindings almost literally.
I've also seen this error on a new machine where I am using my usual .emacs file but haven't installed my packages, and the command to be executed is in one of those packages. (Because a command that can't be executed definitely isn't interactive!)