I need to access the previously entered interactive argument so that I can use it as the initial value of the next argument. To clarify what I mean, consider an example function which renames buffers:
(defun my/rename-buffer (old-name new-name)
(interactive (list (read-buffer "Buffer to rename: " (current-buffer) t)
(read-string "Rename buffer to: ")))
;; Implementation here.
)
How can I access the value which was entered for old-name
so that I can use it as the initial value for the new-name
prompt?
Let me explain in more detail. When we do M-x my/example
, the user is prompted like so (assuming *scratch*
is the current buffer):
Buffer to rename (default *scratch*):
Rename buffer to:
If the user accepts the default for the first prompt (*scratch*
), I would like the second prompt to use *scratch
as the initial value displayed for the user:
Rename buffer to: *scratch*
If the user has instead typed the name of a different buffer for the first prompt, say another-buffer
, the second prompt should have another-buffer
as the initial value:
Rename buffer to: another-buffer
So the second prompt should always use the value of the first parameter as the initial value for the second prompt.
Some notes for clarity:
I am not interested in the specific example of my/rename-buffer
since the standard rename-buffer
works fine. It really is just an example.
I am looking for a solution which does not involve using a string as the arg-descriptor. I need to compose the solution with existing arg-descriptors which are lists of expressions. I don't believe they can be re-implemented as strings, but even if they could be, I not interested in such a solution.
I do not wish to show the last value as part of the read-only prompt string, but instead I wish to use it as the modifiable initial value which is shown after the prompt string.
The user pressing ↑ to access the previous argument is not a solution because I do not want to require user interaction to get the last value. I may also (in the future or for different functions) wish to show a slightly modified version of the last value rather than displaying it verbatim. Such a solution would also not work if the prompts are of different types, since they would not have the same history.
interactive
, when given a lisp form, simply evaluates that form to obtain a list. You can do anything at all in that form, provided that the eventual return value is an appropriate list of values for the function arguments.
(defun my/rename-buffer (old-name new-name)
(interactive
(let* ((old (read-buffer "Buffer to rename: " (current-buffer) t))
(new (read-string "Rename buffer to: " old)))
(list old new)))
;; ...
)