background
I had elisp code (in this very small git repo) like
(defun bulk-replace-file (filepath)
(interactive "FPath to file to bulk-replace: ")
(bulk-replace-file-non-interactive filepath)
)
That worked. Then I decided to parameterize the prompt, producing code like
(defconst BULK-REPLACE-FILEPATH-PROMPT "Path to file to bulk-replace: ")
(defun bulk-replace-file (filepath)
; (interactive "FPath to file to bulk-replace: ") ; should always work
(interactive (concat "F" BULK-REPLACE-FILEPATH-PROMPT))
(bulk-replace-file-non-interactive filepath)
)
However that fails with (in *Messages*)
command-execute: Wrong type argument: listp, "FPath to file to bulk-replace: "
Which frankly stuns me, esp since I'm positive this code formerly worked, but that's why one does regression testing :-(.
questions
- How is
(interactive)getting a list from"FPath to file to bulk-replace: ", given that the latter surely looks like a string? Am I missing something? - Why is
(interactive)not getting a list from(concat "F" BULK-REPLACE-FILEPATH-PROMPT), given that(concat "F" BULK-REPLACE-FILEPATH-PROMPT)returns a string (I have checked with(type-of))(concat "F" BULK-REPLACE-FILEPATH-PROMPT)=="FPath to file to bulk-replace: "(per the error message above)(interactive "FPath to file to bulk-replace: ")works (see first code snippet)
- What's "the right way" to parameterize a prompt used for
(interactive)?
über-answer
Given that, as Drew points out, (interactive) is quite demanding, an easier (and working) way to achieve the desired functionality avoids prompting via (interactive):
(defconst BULK-REPLACE-FILEPATH-PROMPT "Path to file to bulk-replace: ")
(defun bulk-replace-file ()
(interactive) ; Purely to enable `M-x`: let `read-file-name` get the filepath
(bulk-replace-file-non-interactive
(read-file-name BULK-REPLACE-FILEPATH-PROMPT)))
)