Emacs interactive command getting "wrong number of arguments" - emacs

I have this function in my .emacs file that I thought used to work properly but now doesn't:
(defun insert-date ()
(interactive "i")
(insert (format-time-string "%Y-%m-%d")))
Emacs gives the error when I issue M-x insert-date:
call-interactively: Wrong number of arguments: (lambda nil (interactive "i") (insert (format-time-string "%Y-%m-%d"))), 1
I thought the i argument to interactive tells Emacs to ignore any arguments because none are expected. What is wrong with the command that prevents me from using it like I think it should be used?

The texinfo documentation says:
Just `(interactive)' means pass no args when calling interactively.
You are perhaps confusing an argument that is always nil with no arguments at all. The parameter i would be useful in cases where you want to ignore a particular parameter interactively, passing nil in that case.
There is also more information in the emacs manual: 20.2.1 Using interactive

Related

I'm trying to shadow find-file in Emacs, why is this function yelling at me about arguments?

I'm a recent convert to Evil-mode from Vim and I'm trying to make the environment more familiar. One of the things I miss is the find command in Vim. I'm trying to set up something similar in Emacs by wrapping the find-file command in a function. So far I have this:
(defun find nil
"Shadow vim find command, with helm."
(interactive)
(find-file))
When I run the command it yells at me, Wrong number of arguments {doc string} 0 I've tried adding arguments and had no success. The really confusing bit is that I shadowed a helm function the same way and it worked, like this:
(defun buflist nil
"List buffers in helm."
(interactive)
(helm-buffers-list))
What's different? How do I fix this?
find-file takes a file name as argument, you will want to get familiar with C-h f to lookup up function documentation.
interactive can take arguments, for example,
(defun find (filename)
(interactive "F")
(find-file filename))
find-file needs arguments, you can't call it just like
(find-file)
The debugger shows what arguments are needed:
(filename &optional wildcards)
You can also invoke help to see them: C-hf.
Another option is to use call-interactively:
(call-interactively 'find-file)

Emacs Lisp error "Wrong type argument: commandp"

What is wrong with the following code:
(defun test
(interactive)
(message "hello"))
(global-set-key '[f4] 'test)
When evaluating this with eval-region and then pressing F4 I get the error:
Wrong type argument: commandp, test
You are missing the argument list of your test function, so Emacs interprets the (interactive) form as the arglist. Thus you have defined a non-interactive function of 1 argument instead of interactive command of no arguments.
What you want is:
(defun test ()
"My command test"
(interactive)
(message "hello"))
Lessons learned:
Always add a doc string - if you did, Emacs would have complained
Use elint (comes with Emacs, try C-h a elint RET).

Emacs keylogger

I'm trying to implement a keylogger in Emacs (for my own, non-nefarious purposes).
It seems that I can reliably capture the last command through real-last-command in the pre-command-hook
So, I can do something like:
(setq keylog-list nil)
(defun my-keylogger-function ()
(setq keylog-list (cons real-last-command keylog-list)))
(add-hook 'pre-command-hook 'my-keylogger-function)
After a few movement commands, we get
keylog-list's value is
(describe-variable left-char left-char previous-line previous-line left-char eval-last-sexp)
However, I'm interested in capturing the arguments to these commands as well (e.g. the arguments to left-char, which will by default be 1 but may be different if prefix arguments are used.
Is there a way to access the args as well? Something like real-last-command-arglist?
A keylogger is also built into emacs: (open-dribble-file).
Why do you log the last (i.e. previous) command? If you log this-command instead, you can log current-prefix-arg, which corresponds to the prefix argument used.

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".

Usage of current-buffer in emacs?

I'm using emacs and I have written a script which uses "current-buffer". However the emacs system doesn't recognise "current-buffer". When I try "M - x current-buffer" i get the response:
no match
: Any idea what I'm doing wrong?
current-buffer is not an interactive function. That is, can't be invoked interactively via M-x as you've tried to do. You can execute non-interactive lisp-code directly by using eval-expression as follows:
M-: (current-buffer) RET
Notice that you have to enter a proper lisp expression. If you want to capture the value in a variable, something like this
M-: (setq xyzzy (current-buffer)) RET
will store the current buffer into the variable xyzzy.
Do I interpret you correct that you have created a function named current-buffer that you want to be available with M-x current-buffer?
To enable functions to be called by M-x function-name the function needs to be marked as interactive.
A sample from the emacs manual:
(defun multiply-by-seven (number) ; Interactive version.
"Multiply NUMBER by seven."
(interactive "p")
(message "The result is %d" (* 7 number)))
The (interactive "p") part makes the function callable from the minibuffer (through M-x).
I sounds like you would (also) like to know how to get the name of the current buffer interactively. Use M-: (buffer-name).