4

Eval this code:

(defun xx-display-filename (filename)
  ""
  (interactive "Ffilename: ")
  (message (concat "Filename is: " filename)))

Let's assume that I am editing a ~/.emacs.d/personal/custom.el file in the current buffer.

The function above, when invoked with M-x xx-display-filename displays a following text in a minibuffer:

filename: ~/.emacs.d/personal/
  1. This is confusing. I can see a valid path but name of the file is missing. I would expect to see this:

    filename: ~/.emacs.d/personal/custom.el
    
  2. This is confusing even more. When executed, this function writes a following line in *Messages* buffer:

    Filename is: ~/.emacs.d/personal/custom.el
    

    I would expect to see the same text as in a minibuffer:

    Filename is: ~/.emacs.d/personal/
    

So, the question is, How can I display whole path and filename of the currently edited file in a minibuffer and pass it as an argument to an interactive function?

Drew
  • 75,699
  • 9
  • 109
  • 225
whysoserious
  • 339
  • 3
  • 9

3 Answers3

2

Please see the documentation for "Reading File Names" with elisp.

There you can read that normally read-file-name and therefore interactive with the code letter F provides the default-directory as initial input. You get the default file name if you press the down-arrow button.

Nevertheless, you can also insert some initial file name for read-file-name with its optional argument initial.

Your code could be modfified as follows to provide an initial file name as you want it.

(defun xx-display-filename (filename)
  ""
  (interactive (list (read-file-name "filename: " nil nil nil (file-name-nondirectory (buffer-file-name)))))
  (message (concat "Filename is: " filename)))

But, also note that using the initial input is depreciated. You should use the default value instead.

Tobias
  • 32,569
  • 1
  • 34
  • 75
1

@Tobias answers most of what your question asks. This bit was missing, however: why do you see a directory name inserted after the prompt for a file name, in the minibuffer?

That is controlled by user option insert-default-directory. C-h v tells you:

insert-default-directory is a variable defined in minibuffer.el.

Its value is t

Documentation:

Non-nil means when reading a filename start with default dir in minibuffer.

When the initial minibuffer contents show a name of a file or a directory, typing RETURN without editing the initial contents is equivalent to typing the default file name.

If this variable is non-nil, the minibuffer contents are always initially non-empty, and typing RETURN without editing will fetch the default name, if one is provided. Note however that this default name is not necessarily the same as initial contents inserted in the minibuffer, if the initial contents is just the default directory.

If this variable is nil, the minibuffer often starts out empty. In that case you may have to explicitly fetch the next history element to request the default name; typing RETURN without editing will leave the minibuffer empty.

For some commands, exiting with an empty minibuffer has a special meaning, such as making the current buffer visit no file in the case of set-visited-file-name.

You can customize this variable.

Drew
  • 75,699
  • 9
  • 109
  • 225
0

The lisp command buffer-file-name give the absolute path of the file a buffer is visiting which is the info you are looking for.

There is another mode for interactive, where you pass a list of arguments (see bullet 3 on https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Interactive.html). We can call buffer-file-name in that list:

(defun yy-display-filename (filename)
  ""
  (interactive (list (buffer-file-name)))
  (message (concat "Filename is: " filename)))

This appears to solve the problem you had.

I do know why the various letter codes to interactive all prompt with the current working directory.

Drew
  • 75,699
  • 9
  • 109
  • 225
Realraptor
  • 1,253
  • 6
  • 17