Compute the number of universal-arguments before digit argument - emacs

How can I find the number of universal-arguments used to invoke a command prior to a numeric-argument.
For example, how could I differentiate between arg1 and arg2 in the following (wrong) function?
(defun my-func (&optional arg1 arg2)
(interactive "P\nP")
(message "arg1: %S, arg2: %S, value: %S"
arg1 arg2 (prefix-numeric-value current-prefix-arg)))
Use case, transparently passing the numeric prefix value to an advised command depending on the number of prior universal-arguments, eg. dired rename following 2 files in current dired buffer with C-u 2 or to other dired buffer with C-u C-u 2.
Something along the lines of the following advice, but that actually passes the 2 properly to dired-do-rename instead of either 1 or 4.
(define-advice dired-do-rename (:around (fun &rest args) "defer-dwim")
(let ((dired-dwim-target (equal '(4) current-prefix-arg)))
(apply fun (list (max 1 (prefix-numeric-value current-prefix-arg))))))
I see there is a prefix-command-preserve-state-hook, but it seems like significant additional effort to make that work.

Sorry, but your question is quite unclear to me - so this might not answer it.
You say "How can I find the number of universal-arguments used to invoke a command prior to a numeric-argument." I'll answer that.
It doesn't matter how many times you write "P" in an interactive string spec. The value is the same each time, and multiple such occurrences do NOT correspond to multiple uses of C-u.
So (interactive "P\nP\nP") just produces three arguments that all have the same value - the value that comes from a single use of a prefix argument key sequence, whether that sequence is C-u, C-9, M--3, C-u 360, or C-u C-u C-u.
If you want your function to distinguish, say, C-u, C-u C-u, and C-u C-u C-u then it needs to test the raw prefix argument (what "P" specifies for interactive).
C-u corresponds to the raw prefix arg (4), that is, a list with just the number 4.
C-u C-u corresponds to the raw prefix arg (16).
C-u C-u C-u corresponds to the raw prefix arg (64).
(prefix-numeric-value '(4)) returns 4; (prefix-numeric-value '(16)) returns 16; and (prefix-numeric-value '(64)) returns 64.
See the Elisp manual, node Prefix Command Arguments.
You can practice with something like this command, to see what the resulting raw and numeric prefix arguments are when you type different prefix-arg key sequences:
(defun foo (arg narg)
(interactive "P\np")
(message "ARG: %S, NARG: %S" arg narg))
The rest of your question is completely unclear to me. I don't understand what you're trying to do with "dired-do-rename. If I'm right, please consider posting two separate questions: one asking how to distinguish C-u from C-u C-u and the other asking something (what?) about dired-do-rename.

Related

Default universal argument emacs (C-u)

If I press C-u C-n the cursor goes down of 4 lines.
Can I make the default universal argument to be another number greater than 4?
There might be a better way to do this, but one possibility is to create your own universal argument prefix function. Here is the original function (as you can see 4 is hardcoded in the function):
(defun universal-argument ()
"Begin a numeric argument for the following command.
Digits or minus sign following \\[universal-argument] make up the numeric argument.
\\[universal-argument] following the digits or minus sign ends the argument.
\\[universal-argument] without digits or minus sign provides 4 as argument.
Repeating \\[universal-argument] without digits or minus sign
multiplies the argument by 4 each time.
For some commands, just \\[universal-argument] by itself serves as a flag
which is different in effect from any particular numeric argument.
These commands include \\[set-mark-command] and \\[start-kbd-macro]."
(interactive)
(setq prefix-arg (list 4))
(universal-argument--mode))
In your init file, you can create your own custom version of this, and bind it to C-u:
(defun my-universal-argument ()
(interactive)
(setq prefix-arg (list 10))
(universal-argument--mode))
(global-set-key (kbd "C-u") 'my-universal-argument)
However, see #Drew's comment below about why this might not be a great idea, and may have undesired/unexpected consequences.
Also, keep in mind that you can press C-u multiple times as a prefix argument to multiply the repetitions by 4. For example, using the original default of 4, C-u C-u C-n will move down 16 (4*4) lines, and so on.

How to define key-binding with arguments for defun in Emacs?

I have a defun that conveniently adds / removes parentheses to marked expressions. (see code in the end)
As a neophyte in emacs Lisp, I only know how to make simple key-bindings without argument.
However, I believe the defun would be made more convenient if its key-binding could take two optional arguments to specify whether to add / remove (), [], or {}
My current (simple) key-binding is as below, is there a trivial way to make it argument-taking as described?
(global-set-key (kbd "C-M-( )") 'end-of-statement)
Appreciate any advice or direction tips!
(Code: by Istvan Chung)
(defun surround-with-parens ()
(interactive)
(save-excursion
(goto-char (region-beginning))
(insert "("))
(goto-char (region-end))
(insert ")"))
(defun delete-surrounded-parens ()
(interactive)
(let ((beginning (region-beginning))
(end (region-end)))
(cond ((not (eq (char-after beginning) ?\())
(error "Character at region-begin is not an open-parenthesis"))
((not (eq (char-before end) ?\)))
(error "Character at region-end is not a close-parenthesis"))
((save-excursion
(goto-char beginning)
(forward-sexp)
(not (eq (point) end)))
(error "Those parentheses are not matched"))
(t (save-excursion
(goto-char end)
(delete-backward-char 1)
(goto-char beginning)
(delete-char 1))))))
I assume the question is for surround-with-parens, as delete-surrounded-parens is probably better off just guessing the parentheses used by itself.
I also assume that you are doing this for practice more so than for actually solving the problem. If you enable electric-pair-mode in recent Emacsen, configured pairs will wrap around any active region as your command does. But it's a good mid-level emacs lisp exercise.
As the comments noted, you have multiple options.
Command Argument
A command can take arguments, as you asked for. Commands are no different from other lisp functions, except that they have an interactive spec. The interactive spec tells Emacs how to run the command when it is invoked with a key or via M-x.
Simple (interactive) will pass no arguments to the function. (interactive "r") will pass the beginning and end of the region as two arguments. Etc. You can read about the different options in C-h f interactive. You can even write lisp code to calculate the arguments there.
You could use (interactive "cWrap with: "). This would prompt the user for a key, and pass the key to your function. For example, if the user types (, your function receives 40 as the argument, the character code for the opening parenthesis. ?\( is 40 as well, and (make-string 1 40) returns "(". You'll have to create a map to figure out the closing parenthesis.
The drawback here is that you need to press two keys: The first to invoke the command, and then a key to specify the parenthesis to use.
Multiple keys
You can also bind your command to different keys – for example, C-M-( and C-M-[. You can then use this-single-command-keys to get something that specifies the last key event. Sadly, this can be somewhat tricky to translate back to a key sequence. E.g. C-M-( returns [201326632].
Multiple commands
You could also just define one command per parenthesis type, all of which simply call a common function with arguments, and bind those commands to keys.
post-self-insert-hook
Finally, you can use the same method as electric-indent-mode does: Add a function to post-self-insert-hook and decide based on char-before what you want to do.

emacs multi-keystroke binding [duplicate]

This question already has answers here:
How to write a key bindings in emacs for easy repeat?
(5 answers)
Closed 8 years ago.
I'm still very new to EMACS, but are getting familiar when i'm going through the emacs and elisp manual. But right now i'm stuck on this:
Is there a simple way to bind input sequences in regexp style?
eg: the default binding for function enlarge-window-horizontally is "C-x {", is it possible to rebind it to something like "C-x ({)+" so that enlarge-window-horizontally can be called repeatedly by repeating "{" character, instead of release Ctrl key multiple times?
There is another way to archive what you desire:
The first time you want to repeat the last command, press C-x z, afterwards you may repeat your command as often as desired by just pressing z.
The advantage of this approach is that it works with every command you use and not just for a specific one.
For additional reference here is the output of C-h f
8.11 Repeating a Command
Many simple commands, such as those invoked with a single key or with
M-x COMMAND-NAME , can be repeated by invoking them with a
numeric argument that serves as a repeat count (*note Arguments::).
However, if the command you want to repeat prompts for input, or uses
a numeric argument in another way, that method won't work.
The command C-x z (`repeat') provides another way to repeat an
Emacs command many times. This command repeats the previous Emacs
command, whatever that was. Repeating a command uses the same
arguments that were used before; it does not read new arguments each
time.
To repeat the command more than once, type additional z's: each
z repeats the command one more time. Repetition ends when you type
a character other than z, or press a mouse button.
For example, suppose you type C-u 2 0 C-d to delete 20
characters. You can repeat that command (including its argument) three
additional times, to delete a total of 80 characters, by typing C-x z
z z. The first C-x z repeats the command once, and each subsequent
z repeats it once again.
The "Emacs way" is to use C-u as a prefix key. E.g. C-u20C-x{.
Having said that, it's possible to do what you ask for. However, it would require you to bind C-x { and { separately. The former would be defined like it is today, but the latter would have to look something like:
(defun my-open-brace ()
(interactive)
(if (eq last-command 'shrink-window-horizontally)
(progn
(setq this-command 'shrink-window-horizontally)
(call-interactively 'shrink-window-horizontally))
(call-interactively 'self-insert-command)))
Unfortunately, if you have many sequences ending in {, you would have to write one function to handle them all.
You can also define your own repeatable command and bind it to C-x {. You can then use it exactly as you requested: C-x { { { {..., instead of having to use C-x { C-x z z z z...
Here is what you do:
(defun your-repeat-command (command)
"Repeat COMMAND."
(let ((repeat-message-function 'ignore))
(setq last-repeatable-command command)
(repeat nil)))
(defun your-shrink-window-horizontally ()
"Shrink window horizontally.
You can repeat this by hitting the last key again..."
(interactive)
(require 'repeat nil t)
(my-repeat-command 'shrink-window-horizontally))
(define-key ctl-x-map "{" 'your-shrink-window-horizontally)
You can do this with any command you like --- use my-repeat-command to make a repeatable version of it. I do this all the time, in several of my libraries.
Write a multi repeat command for emacs by using minor mode. I name it smart-repeat-mode
https://github.com/zhsfei/emacs-ext

Interactive command for inserting the string returned by a function

When evaluating elisp symbolic expressions with (eval-last-sexp), bound to C-x C-e, I can just type C-u before that command to insert the result of the expression into the current buffer.
Is there some equivalent to that when calling functions interactively? For example, if I want to insert the string returned by (emacs-version) into the current-buffer, how would I do that? M-x emacs-version only shows the string in the minibuffer and typing C-u before M-x emacs-version won't work either.
If there is no such equivalent, what would be the easiest way to insert a string returned by a function without first having to type the function down before evaluating it?
UPDATE:
C-u M-x emacs-version does actually work. My mistake. But it does not work for emacs-uptime. How come it doesn't work for that one?
(defun my-insert-command-value (command)
"Insert the return value of the command."
(interactive "*C(insert) M-x ")
(print (call-interactively command) (current-buffer)))
emacs-uptime was implemented to output the result only to minibuffer
(defun emacs-uptime (&optional format)
(interactive)
(let ((str
(format-seconds (or format "%Y, %D, %H, %M, %z%S")
(float-time
(time-subtract (current-time) before-init-time)))))
(if (called-interactively-p 'interactive)
(message "%s" str)
str)))
emacs-version has the following code which prints output if called with C-u
(if here
(insert version-string)
(if (called-interactively-p 'interactive)
(message "%s" version-string)
version-string))
If you want to print the result of a particular command (e.g. emacs-uptime) you can wrap it to insert result into the current buffer (similar to emacs-version).
However, I don't know a generic solution - how to output the result of any Emacs command.
C-u M-x pp-eval-expression RET (emacs-uptime) RET
"Evaluate Emacs-Lisp sexp EXPRESSION, and pretty-print its value.
With a prefix arg, insert the value into the current buffer at point.
With a negative prefix arg, if the value is a string, then insert it
into the buffer without double-quotes (`"')."
See pp+.el.

What does (interactive) mean in an Emacs Lisp function?

Emacs Lisp function often start like this:
(lambda () (interactive) ...
What does "(interactive)" do?
Just to clarify (it is in the quoted docs that Charlie cites) (interactive) is not just for key-bound functions, but for any function. Without (interactive), it can only be called programmatically, not from M-x (or via key-binding).
EDIT: Note that just adding "(interactive)" to a function won't necessarily make it work that way, either -- there could be many reasons functions are not interactive. Scoping, dependencies, parameters, etc.
I means that you're including some code for the things you need to make a function callable when bound to a key -- things like getting the argument from CTRL-u.
Have a look at CTRL-h f interactive for details:
interactive is a special form in `C source code'.
(interactive args)
Specify a way of parsing arguments for interactive use of a function.
For example, write
(defun foo (arg) "Doc string" (interactive "p") ...use arg...)
to make ARG be the prefix argument when `foo' is called as a command.
The "call" to `interactive' is actually a declaration rather than a function;
it tells `call-interactively' how to read arguments
to pass to the function.
When actually called, `interactive' just returns nil.
The argument of `interactive' is usually a string containing a code letter
followed by a prompt. (Some code letters do not use I/O to get
the argument and do not need prompts.) To prompt for multiple arguments,
give a code letter, its prompt, a newline, and another code letter, etc.
Prompts are passed to format, and may use % escapes to print the
arguments that have already been read.
Furthermore it’s worth mentioning that interactive's main purpose is, in an interactive context (e.g. when user calls function with key binding), let user specify function arguments that otherwise could be only given programmatically.
For instance, consider function sum returns sum of two numbers.
(defun sum (a b)
(+ a b))
You may call it by (sum 1 2) but you can do it only in a Lisp program (or in a REPL). If you use the interactive special form in your function, you can ask the user for the arguments.
(defun sum (a b)
(interactive
(list
(read-number "First num: ")
(read-number "Second num: ")))
(+ a b))
Now M-x sum will let you type two numbers in the minibuffer, and you can still do (sum 1 2) as well.
interactive should return a list that would be used as the argument list if function called interactively.
(interactive) is for functions meant to interact with the user, be it through M-x or through keybindings.
M-x describe-function RET interactive RET for detailed info on how to use it, including parameter to catch strings, integers, buffer names, etc.
One of the "gotchas" that this clarifies is that the argument to interactive is actually a kind of mini-formatting language (like for printf) that specifies the following (for the surrounding function's input):
schema (number of arguments and their type)
source (e.g., marked-region in buffer and/or user input, etc.)
For example,
'r'
Point and the mark, as two numeric arguments, smallest first.
means that the interactive-annotated function needs exactly two arguments.
e.g. this will work
(defun show-mark (start stop)
(interactive "r")
(print start)
(print stop))
This will break:
(defun show-mark (start)
(interactive "r")
(print start))
Wrong number of arguments: ((t) (start) (interactive "r") (print start)), 2