How to rename a file by editing its current name? - emacs

For example: I have a file longest_substring_no_repeating_chars.cc. One day I want to rename it to longest_substr_no_repeating_chars.cc. How do I do it by editing the old name? Or is there any convenient way to do it?

Assuming you want to rename the file you're currently editing you can define a function like this one:
(defun rename-file-and-buffer ()
"Renames current buffer and file it is visiting."
(interactive)
(let ((name (buffer-name))
(filename (buffer-file-name)))
(if (not (and filename (file-exists-p filename)))
(message "Buffer '%s' is not visiting a file!" name)
(let ((new-name (read-file-name "New name: " filename)))
(cond ((get-buffer new-name)
(message "A buffer named '%s' already exists!" new-name))
(t
(rename-file name new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil)))))))
And the you can bind it to a key combo like C-c r
(global-set-key (kbd "C-c r") 'rename-file-and-buffer)
Otherwise, #Oleg's suggestion to use dired is a great option.

You can do this in dired mode. R shortcut invokes dired-do-rename where you
can press down to get back the old name.
It's even easier if you use dired-x, just add to your init file.
(require 'dired-x)
Then you can press C-x C-j R to edit as you need to, then
q to go back to your buffer.
Another possibility: M-x wdired-change-to-wdired-mode. In this mode you can
edit files directly. Press C-c C-c when you want to commit your changes or
C-c ESC to cancel them.

Related

a function that lets you change the name of the currently open file and buffer, how do I make the current name the default

This was written by Steve Yegge (at least I found it on his blog). It lets you change the name of the currently open file in emacs. Would it be possible to make the current name of the file the default name in the new name dialog? I often have one little typo in the filename and would rather just edit it than writing the entire name over again.
;; Never understood why Emacs doesn't have this function.
(defun rename-file-and-buffer (new-name)
"Renames both current buffer and file it's visiting to NEW-NAME."
(interactive "sNew name: ")
(let ((name (buffer-name))
(filename (buffer-file-name)))
(if (not filename)
(message "Buffer '%s' is not visiting a file!" name)
(if (get-buffer new-name)
(message "A buffer named '%s' already exists!" new-name)
(rename-file name new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil))))))
You need to use read-from-minibuffer:
(interactive (list (read-from-minibuffer "New name: " (buffer-name))))
I also recommend error instead of message for reporting errors.
PS. If you want completion based on existing files, you might prefer
(interactive (list (read-file-name "New name: " nil nil nil (buffer-name))))
PPS. The reason why this function is not present in the core is that most people prefer to manipulate files from specialized buffers, specifically, dired for "directory editing" and vc-dir for version control, where you can rename files and the corresponding buffers are treated appropriately.
This robust renaming is already handled by dired.
To facilitate jumping to the current buffer's file directly, add this to your init:
(autoload 'dired-jump "dired-x" nil t)
(define-key ctl-x-map [(control j)] 'dired-jump)
Now C-x C-j R renames the current buffer. You're also on your way
to discovering all the other useful things that dired can do.
EDIT: From there M-n fills in the old name.

Rename current buffer and related file in Emacs

I want to rename a file that is bound current buffer in Emacs.
I found following elisp from this article:
How do I rename an open file in Emacs?
;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun rename-file-and-buffer (new-name)
"Renames both current buffer and file it's visiting to NEW-NAME."
(interactive "sNew name: ")
(let ((name (buffer-name))
(filename (buffer-file-name)))
(if (not filename)
(message "Buffer '%s' is not visiting a file!" name)
(if (get-buffer new-name)
(message "A buffer named '%s' already exists!" new-name)
(progn
(rename-file name new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil))))))
It works fine, but if possible I want to set current file name as a default value.
How would I write this?
There recently was a
post on the
Emacs Redux blog on this subject.
Basically it is implemented in the Prelude
configuration (by the same author) which you can install to get this behaviour and tons of other interesting stuff. Otherwise, you can put in your configuration file only the relevant snippet (taken from the blog post above):
(defun rename-file-and-buffer ()
"Rename the current buffer and file it is visiting."
(interactive)
(let ((filename (buffer-file-name)))
(if (not (and filename (file-exists-p filename)))
(message "Buffer is not visiting a file!")
(let ((new-name (read-file-name "New name: " filename)))
(cond
((vc-backend filename) (vc-rename-file filename new-name))
(t
(rename-file filename new-name t)
(set-visited-file-name new-name t t)))))))
(global-set-key (kbd "C-c r") 'rename-file-and-buffer)
Could you elaborate more on why you need to do it?
What are the conditions?
Because this has never come up since I started using Emacs.
But here's what I do sometimes when I want to rename something:
Say I'm editing spam-spom-spam.cc. And I want to fix the name.
C-x d
C-s spo
C-x C-q
DEL a
C-c C-c
This may seem like a lot of commands, but they flow quite naturally.
As a bonus, you get an overview of your directory and of how the
newly renamed file looks there.
No external tool needed for this. See
http://www.gnu.org/software/emacs/manual/html_node/emacs/Wdired.html
After changing the file-name in the dired-buffer, the buffer-name is changed too.

The function to show current file's full path in mini buffer

I need to get the full path of the file that I'm editing with emacs.
Is there a function for that?
If not, what would be the elisp function for getting that?
How can I copy the result (path name) to a clipboard so that I can reuse it?
I'm using Mac OS X and Aqumacs.
(setq filepath (get-fullpath-current-file)) ???
(copy-to-clipboard 'filepath) ???
ADDED
(defun show-file-name ()
"Show the full path file name in the minibuffer."
(interactive)
(message (buffer-file-name))
(kill-new (file-truename buffer-file-name))
)
(global-set-key "\C-cz" 'show-file-name)
Combining the two answers that I got, I could get what I want. Thanks for the answers. And some more questions.
What's for (file-truename)?
Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?
It's the built-in function buffer-file-name that gives you the full path of your file.
The best thing to do is to have your emacs window to always show your system-name and the full path of the buffer you're currently editing :
(setq frame-title-format
(list (format "%s %%S: %%j " (system-name))
'(buffer-file-name "%f" (dired-directory dired-directory "%b"))))
You can also do something like this :
(defun show-file-name ()
"Show the full path file name in the minibuffer."
(interactive)
(message (buffer-file-name)))
(global-set-key [C-f1] 'show-file-name) ; Or any other key you want
To borrow from Jérôme Radix's answer, if you just want to quickly see the file path of the current buffer, you can do M-: buffer-file-name.
Alternately, type (buffer-file-name) in the buffer somewhere and run C-x C-e on the closing parenthesis (this will work in any mode, not just lisp-mode).
My trick is to do a C-x C-f like to open a file, it wil prefill the minibuff with the current file path, C-g to quit. Faster than M-: buffer-file-name but far far uglier than any other methods.
The direct implementation of what you want is:
(defun copy-full-path-to-kill-ring ()
"copy buffer's full path to kill ring"
(interactive)
(when buffer-file-name
(kill-new (file-truename buffer-file-name))))
That said, I find it incredibly useful to be able to get the full path of what is in the minibuffer, and this is what I use:
(define-key minibuffer-local-completion-map "\C-r" 'resolve-sym-link)
(defun resolve-sym-link ()
"Try to resolve symbolic links into true paths."
(interactive)
(beginning-of-line)
(let* ((file (buffer-substring (point)
(save-excursion (end-of-line) (point))))
(file-dir (file-name-directory file))
(file-true-dir (file-truename file-dir))
(file-name (file-name-nondirectory file)))
(delete-region (point) (save-excursion (end-of-line) (point)))
(insert (concat file-true-dir file-name))))
And then if I want it in the clipboard, I just kill the line (C-a C-k). But we could easily copy the truename to the clipboard in the above command, just change the last line to be:
(insert (kill-new (concat file-true-dir file-name)))))
The new part is the call to 'kill-new which puts the string in the kill ring.
No need for extra function, just
M-! pwd
C-x C-b shows a list of buffers and the file path for each buffer where applicable.
C-x C-d, also callable via M-x list-directory, will show you the directory for your current file, and you only need to hit the "Enter" key to clear the minibuffer. Additional details are available here.
I have the following code already in use for a long time.
It copies the full file path to the kill ring when I press the middle mouse button on the buffer name in the mode-line. It copies just the buffer name to the kill-ring when I press shift-mouse-2 on the buffer-name in the mode-line.
(defun copy-buffer-file-name (event &optional bufName)
"Copy buffer file name to kill ring.
If no file is associated with buffer just get buffer name.
"
(interactive "eP")
(save-selected-window
(message "bufName: %S" bufName)
(select-window (posn-window (event-start event)))
(let ((name (or (unless bufName (buffer-file-name)) (buffer-name))))
(message "Saved file name \"%s\" in killring." name)
(kill-new name)
name)))
(define-key mode-line-buffer-identification-keymap [mode-line mouse-2] 'copy-buffer-file-name)
(define-key mode-line-buffer-identification-keymap [mode-line S-mouse-2] '(lambda (e) (interactive "e") (copy-buffer-file-name e 't)))
C-u C-x C-b lists buffers currently visiting files.
Can I copy the path name to System(OS)'s clipboard, not the kill ring so that I can use the info with the other apps?
You can if you shell out to something like xclip (Linux), pbcopy (Mac), putclip (Cygwin).
I personally use wrapper scripts c and p for copy and paste respectively, the first reading from standard input, the latter writing to standard output. That way, this works on all my development platforms:
(shell-command (format "echo '%s' | c" buffer-file-name))
I find this more reliable and configurable than using the Emacs clipboard support. For example, my c command copies the input to all 3 clipboards on Linux (primary, secondary, clipboard), so I can paste with either Ctrl-V or middle click.
The simplest way and would be
(buffer-name)<(C-x)(C-e)> for the file name to appear in the echo area
(buffer-name)<(C-u)(C-x)(C-e)> would print the location <here>
Borrowing from Trey Jackson
I came up with this:
(defun buffer-kill-path ()
"copy buffer's full path to kill ring"
(interactive)
(kill-new (buffer-file-name)))
You can find more information on site
copy-buffer-file-name-as-kill from [0] does exactly what you need I think. It also has the option to copy just directory name, or just file name.
[0] http://www.emacswiki.org/emacs/download/buffer-extension.el
To do what the title says (show the current file path in the minibuffer) you can do this:
M-x buffer-file-name
To permanently show it in the mode-line, you can use this:
(setq-default mode-line-buffer-identification
(list 'buffer-file-name
(propertized-buffer-identification "%12f")
(propertized-buffer-identification "%12b")))
Or this (color + abbrev) :
(setq-default mode-line-buffer-identification
'((:eval
(list (propertize (abbreviate-file-name
(expand-file-name buffer-file-name))
'face 'font-lock-string-face)))))

How to format all files under a dir in emacs?

In emacs, I format a file as:
1) C-x h (or M-x mark-whole-buffer)
2) C-M-\ (or M-x indent-region)
I need help show me how to format all files under a dir?
Here's another way to go about it:
First, evaluate this function definition in your *scratch* buffer:
(defun indent-marked-files ()
(interactive)
(dolist (file (dired-get-marked-files))
(find-file file)
(indent-region (point-min) (point-max))
(save-buffer)
(kill-buffer nil)))
Next, open a Dired buffer at the top level of the directory under which you want to change all of the files. Give the dired command a numeric prefix so that it will ask for the switches to give to the ls command, and add the R (recurse) switch: C-u C-x d R RET your-directory RET.
Next, mark all of the regular files in the recursive directory listing: first * / to mark all the directories, then * t to toggle the selection.
Finally, run the above command: M-x indent-marked-files.
Be aware that if you already have any buffers visiting any of the target files, they'll be killed by indent-marked-files. Also be aware that none of the file changes will be undoable; use with caution! I tested it in a simple case and it seems to work as described, but I make no guarantees.
Create a macro to do it. Open the directory in dired (C-x d), and then:
Put point on the first file.
Press F3 to start recording the macro.
Hit RET to open the file.
Format it with C-x h, C-M-\.
Bury the buffer with M-x bury-buffer. You'll be back in the dired buffer.
Go down one line.
Hit F4 to stop recording the macro.
So now you have a macro that opens the file on the current line, formats it, drops back to dired, and puts point to the next line. Run it with F4 as many times as needed.
I am late in answering this question, but this is still the first result on Google.
I made an improvement to #Sean's answer to remove the need for the complicated Dired interaction.
(defun my/indent-files (directory extension)
(interactive (list (read-directory-name "Directory: ")
(read-string "File extension: ")))
(dolist (file (directory-files-recursively directory extension))
(find-file file)
(indent-region (point-min) (point-max))
(save-buffer)
(kill-buffer nil)))
Sample use: M-x my/indent-files then ~/Dropbox then .org.
This will run indent-region on the all .org files, save the buffer then kill it.
You can try this:
(defun format-all-files (regexp)
"Format multiple files in one command."
(interactive "sFind files matching regexp (default all): ")
(when (string= "" regexp) (setq regexp ""))
(let ((dir (file-name-directory regexp))
(nodir (file-name-nondirectory regexp)))
(when dir (cd dir))
(when (string= "" nodir) (setq nodir "."))
(let ((files (directory-files "." t nodir nil t))
(errors 0))
(while (not (null files))
(let ((filename (car files)))
(if (file-readable-p filename)
(progn
(set-buffer (find-file-noselect filename))
(mark-whole-buffer)
(indent-region-or-balanced-expression)
(save-buffer)
(kill-buffer (current-buffer)))
(incf errors))
(setq files (cdr files))))
(when (> errors 0)
(message (format "%d files were unreadable." errors))))))
But note that this must load the file-specific mode over and over again, which may involve syntax highlighting or whatever initialization happens on a load of that type. For really big formatting jobs, a batch program such as indent which only indents will be much faster.

File path to clipboard in Emacs

What is the most simple way to send current full file name with file path to clipboard?
What I am using now is messages buffer: I copy file name that appears there after saving a file. But, I suppose, there should be much more simple way.
Why no one tell the simple solution.
Just go to your dired buffer then press 0 w or C-u 0 w.
This will call dired-copy-filename-as-kill which gives you full path of a file. If you want current dir, just delete the file at the end of it or you can use the function below, then bind it to any key you like.
(defun my/dired-copy-dirname-as-kill ()
"Copy the current directory into the kill ring."
(interactive)
(kill-new default-directory))
PS: personally I go to current directory from file buffer using dired-jump
I use this:
(defun my-put-file-name-on-clipboard ()
"Put the current file name on the clipboard"
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(with-temp-buffer
(insert filename)
(clipboard-kill-region (point-min) (point-max)))
(message filename))))
In Emacs Prelude I use:
(defun prelude-copy-file-name-to-clipboard ()
"Copy the current buffer file name to the clipboard."
(interactive)
(let ((filename (if (equal major-mode 'dired-mode)
default-directory
(buffer-file-name))))
(when filename
(kill-new filename)
(message "Copied buffer file name '%s' to the clipboard." filename))))
If you want to write the name/path of the current buffer you can type C-u M-: and then either (buffer-file-name) - for the full path - or (buffer-name) for the buffer name.
That is:
M-: + ellisp expression evaluates an ellisp expression in the mini-buffer
C-u write the output to the current buffer
Does not exactly answer to the question but could be useful if someone use this or other function sporadically, and prefers to not initialize the function at every startup.
In the Spacemacs distribution, you can press Spacefyy to display the buffer name in the minibuffer and copy it to the kill ring.
The function spacemacs/show-and-copy-buffer-filename seems to originate from this blog post: Emacs: Show Buffer File Name.
(defun camdez/show-buffer-file-name ()
"Show the full path to the current file in the minibuffer."
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(progn
(message file-name)
(kill-new file-name))
(error "Buffer not visiting a file"))))
There's a buffer-extension - and it has copy-buffer-file-name-as-kill function. It even asks You what to copy: name, full name or a directory name.
Edit:
I use modified version of copy-buffer-file-name-as-kill from buffer-extension.el:
(defun copy-buffer-file-name-as-kill (choice)
"Copyies the buffer {name/mode}, file {name/full path/directory} to the kill-ring."
(interactive "cCopy (b) buffer name, (m) buffer major mode, (f) full buffer-file path, (d) buffer-file directory, (n) buffer-file basename")
(let ((new-kill-string)
(name (if (eq major-mode 'dired-mode)
(dired-get-filename)
(or (buffer-file-name) ""))))
(cond ((eq choice ?f)
(setq new-kill-string name))
((eq choice ?d)
(setq new-kill-string (file-name-directory name)))
((eq choice ?n)
(setq new-kill-string (file-name-nondirectory name)))
((eq choice ?b)
(setq new-kill-string (buffer-name)))
((eq choice ?m)
(setq new-kill-string (format "%s" major-mode)))
(t (message "Quit")))
(when new-kill-string
(message "%s copied" new-kill-string)
(kill-new new-kill-string))))
If you use Doom Emacs, it can be done with SPC f y.
To paste the current file path in the buffer, the most simple way I see is to do: C-u M-! pwd (this might not work on Windows systems though).
Alternatively, you can use C-x C-b to show the file paths of all opened buffers.
This is what has worked for me on MacOS 10.15.7, GNU Emacs 27.1
(defun copy-current-buffer-file-name ()
(interactive)
(shell-command (concat "echo " (buffer-file-name) " | pbcopy")))
set keybinding to "C-x M-f":
(global-set-key (kbd "C-x M-f") 'copy-current-buffer-file-name)
FYI: For a real beginner reading this, you need to add those lines to your init.el file.
Lots of good answers here, though I think for the "most simple way", as described in the question, there's room for improvement. Here's what I came up with (with thanks to other answers for the bits and pieces):
M-: (kill-new (buffer-file-name)) RET
This does precisely what you asked for -- takes the filename of the current buffer, and puts it in the "kill ring" and, depending on your settings, also the system clipboard. (See emacswiki/CopyAndPaste for more details on that part.)
If you want to do this regularly, then setting up a function like listed in the other answers, and binding it to an available key sequence, would make it easier to do frequently. But the above works with no prior setup, which I'm interpreting to be more "simple".