Emacs Lisp: read-from-minibuffer Propels Deep Questions
slightly frustrated with emacs lisp read-from-minibuffer
. Spent now about a hour on this.
what i want is simple, like this:
(read-from-minibuffer (format "Directory (default %s):" default-directory) default-directory )
prompt user to enter a dir, with default of current dir.
however, according to inline doc of read-from-minibuffer
, the second arg for default input is obsolete “mostly deprecated”. Instead, you have to use the 6th arg. Quote:
(read-from-minibuffer PROMPT &optional INITIAL-CONTENTS KEYMAP READ HIST DEFAULT-VALUE INHERIT-INPUT-METHOD)
the doc is long so i won't paste here. See it by calling describe-function
.
Text from Minibuffer (ELISP Manual)
Now, so i do:
(read-from-minibuffer (format "Directory (default %s):" default-directory) nil nil nil nil default-directory)
doesn't work. Read the doc again, it turns out that the 4th arg must be true in order for the default value to work, else you get empty string if the user just press Enter.
So i do:
(read-from-minibuffer (format "Directory (default %s):" default-directory) nil nil t nil default-directory)
No go! because if the 4th arg is true, it means the input as a string will be fed to lisp reader, then interpreted as a lisp object. Hot damn. This means, if you want a string, you have to feed it "\"mystring\""
. (the outter quote pair makes it a lisp string to be fed to lisp reader, then, the inner quote pair gets you a lisp string object)
So, now i have to do this:
(read-from-minibuffer (format "Directory (default %s):" default-directory) nil nil t nil (format "\"%s\"" default-directory) )
But no! Because, now if user actually enter a value, for example, type mary
, lisp reader freaks out. Again, it doesn't undertand what the letter sequence mary
is. It wants a string "\"mary\""
. So, user will have to actually type "mary"
for this to work.
WTF?
This line is supposed to be done in 20 seconds. I think i've spent 40 min on this. Now, my mind wanders to the deep question of humanity….
Xah
Solution
You should use read-file-name
or read-directory-name
. Like this:
(defun test-fun (arg) "Prompt user to enter a file path, with file name completion and input history support." (interactive (list (read-file-name "Open directory:")) ) (message "Path is 「%s」." arg) )
If you really want to use read-from-minibuffer
, you can simply:
(read-from-minibuffer "Directory: " default-directory)
Or, check if the return string is empty.
(let ((directory (read-from-minibuffer (format "Directory (default %s): " default-directory) nil nil nil nil default-directory))) (if (equal directory "") default-directory directory))
Thanks to Kevin Rodgers,
Drew Adams
http://emacswiki.org/emacs/DrewAdams,
[Elias Mårtenson https://plus.google.com/115209488640908180409/posts].
Source groups.google.com
- LISP is Not Functional
- Guy Steele Says: Don't Iterate, Recurse, and Get rid of lisp cons!
- Fundamental Problems of Lisp, Syntax Irregularity
- Programing Language: The Glory of Lisp's cons
- Lisp's List Problem
- Lisp Macros and Practical Common Lisp (rant)
- Byte Magazine Cover on LISP, A Space Odyssey, Nietzsche