Cum pot redenumi un fișier deschis în Emacs? (Programare, Emacs)

pupeno a intrebat.

Există o modalitate de a redenumi un fișier deschis în Emacs? În timp ce îl vizualizez? Ceva de genul save-as, dar cel original ar trebui să dispară.

12 răspunsuri
Matt Curtis

Încercați această funcție din .emacs al lui Steve Yegge:

;; 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 filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil))))))

Aruncați o privire la acea pagină, există o altă funcție conexă foarte utilă acolo, numită „move-buffer-file”.

Comentarii

  • Notă: această metodă nu este compatibilă cu (setq uniquify-buffer-name-style 'forward) ceea ce înseamnă că dacă aveți un buffer numit usersindex.html (deoarece aveți deja un alt buffer pentru postsindex.html), redenumirea va eșua –  > Por dolzenko.
  • (set-buffer-modified-p nil) pare inutilă. Dacă ați apelat rename-file-and-buffer pe un buffer modificat și apoi ați încercat să îl omorâți, acesta ar face acest lucru cu plăcere fără să vă avertizeze cu privire la modificările nesalvate. –  > Por roldugin.
  • Această funcție vă va cere, de asemenea, (oarecum enervant) un nou nume înainte de de a verifica dacă bufferul curent este asociat cu un fișier (caz în care renunță). –  > Por Thomas.
Chris Conway

Da, cu dired se poate:

  • C-x d pentru a deschide dired
  • RET pentru a selecta directorul fișierului curent
  • C-x C-j (dired-jump la numele fișierului curent, în Dired)
  • R să redenumiți fișierul (sau dired-do-rename).
  • q pentru a reveni la memoria tampon a fișierului (redenumit)

Redenumirea este echivalentă cu un shell mv, dar va actualiza, de asemenea, orice buffer deschis și, spre deosebire de mv nu va schimba timpii de acces și de modificare a fișierului în sistemul de fișiere.

Comentarii

  • Aceasta nu redenumește direct fișierul curent. –  > Por pupeno.
  • C-x b și te întorci în bufferul original. Ați putea scrie o funcție Elisp pentru a face acest lucru, dar mă îndoiesc că veți economisi multe apăsări de taste cu ea. –  > Por Chris Conway.
  • De asemenea, în loc de C-x b, puteți apăsa C-x k pentru a vă întoarce în bufferul original. –  > Por Yoo.
  • 34

  • C-x C-j nu este legat în mod implicit pentru mine. Facând M-x load-library RET dired-x RET mai întâi îl face legat. –  > Por ntc2.
  • O altă alternativă dacă C-x C-j este nelegat, este de a face doar M-x dired-jump prima dată. Se va încărca automat dired-x (ceea ce va determina, de asemenea, ca C-x C-j să fie definită din acest moment). –  > Por Fernando Basso.
Jim G

Doar pentru a fi complet, deoarece unii oameni ar putea vizita această pagină crezând că vor primi un răspuns pentru funcția „save as” din Emacs, asta înseamnă C-x C-w pentru un fișier deschis.

Comentarii

  • C-x C-w sau folosiți meniul File > Save as... –  > Por Yoo.
  • Nu este chiar „save as”, deoarece fișierul pe care îl editați va fi în continuare cel original. –  > Por asmeurer.
  • @asmeurer Te înșeli! După salvare, veți edita noul fișier. –  > Por Joel G Mathew.
  • Din nou, de ce nu există o funcție pentru a vota în jos comentariile!!! –  > Por bearfriend.
  • Poate că asmeurer a vrut să spună: „fișierul pe care îl [editai] va continua să [existe]”. Atunci, este corect? Aș verifica, dar atunci, nu poți să dai downvote la comentariul meu, hahaha. –  > Por Brady Trainor.
The Unfun Cat

Preferata mea este cea de la Magnars (de emacs rocks screencasts (emacs rocks screencasts) faimos.)

Spre deosebire de celelalte alternative, nu trebuie să tastați numele de la zero – primiți numele curent pentru a-l modifica.

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " (file-name-directory filename) basename nil basename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

Mulțumiri lui James Yang pentru o versiune corectă.

Comentarii

  • Aceasta NU funcționează corect. Aceasta adaugă un „/” la sfârșitul fișierului. –  > Por mythicalcoder.
  • Mulțumesc că ai postat asta pentru mine. Modul SO este de a corecta răspunsurile, nu de a posta răspunsuri noi, ușor modificate. –  > Por The Unfun Cat.
Shawn Hoover

Iată o versiune mai robustă adaptată de la stevey.

;; Originally from stevey, adapted to support moving to a new directory.
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive
   (progn
     (if (not (buffer-file-name))
         (error "Buffer '%s' is not visiting a file!" (buffer-name)))
     ;; Disable ido auto merge since it too frequently jumps back to the original
     ;; file name if you pause while typing. Reenable with C-z C-z in the prompt.
     (let ((ido-auto-merge-work-directories-length -1))
       (list (read-file-name (format "Rename %s to: " (file-name-nondirectory
                                                       (buffer-file-name))))))))
  (if (equal new-name "")
      (error "Aborted rename"))
  (setq new-name (if (file-directory-p new-name)
                     (expand-file-name (file-name-nondirectory
                                        (buffer-file-name))
                                       new-name)
                   (expand-file-name new-name)))
  ;; Only rename if the file was saved before. Update the
  ;; buffer name and visited file in all cases.
  (if (file-exists-p (buffer-file-name))
      (rename-file (buffer-file-name) new-name 1))
  (let ((was-modified (buffer-modified-p)))
    ;; This also renames the buffer, and works with uniquify
    (set-visited-file-name new-name)
    (if was-modified
        (save-buffer)
      ;; Clear buffer-modified flag caused by set-visited-file-name
      (set-buffer-modified-p nil)))

  (setq default-directory (file-name-directory new-name))

  (message "Renamed to %s." new-name))

Comentarii

  • Frumos. Acum se răcește în funcțiile mele.el. –  > Por Felix D..
Bozhidar Batsov

Iată o altă versiune, care este destul de robustă și conștientă de VC:

(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)))))))

Puteți citi mai multe despre ea aici.

Jason Axelson

Dacă utilizați Spacemacs atunci primiți acest comportament gratuit, deoarece vine cu o implementare a lui rename-current-buffer-file (bazată pe magnars) care, în mod implicit, este legată de SPC-f-R.

https://github.com/syl20bnr/spacemacs/blob/bd7ef98e4c35fd87538dd2a81356cc83f5fd02f3/layers/%2Bdistributions/spacemacs-base/funcs.el#L294

Comentarii

  • Tocmai am testat acest lucru în Doom Emacs (v27.1) și funcționează la fel de bine. Vă mulțumesc. –  > Por flarkmarup.
Rafael Nascimento

Există o modalitate foarte ușoară, apăsați comanda M-x și apoi tastați vc-rename-file, după care trebuie doar să selectați fișierul curent din director și apoi să alegeți noul nume. Buf-ul care conține fișierul modificat va fi actualizat.

Sursă:https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html

Comentarii

  • Acest lucru are efectul secundar (nu neapărat de dorit) de a adăuga fișierele vechi și noi care urmează să fie trimise în controlul versiunilor. Dar +1, deoarece folosește o funcție încorporată pentru a răspunde (în mare parte) la întrebarea lui OP. –  > Por dinosaur.
  • Funcționează chiar și astăzi cu GNU Emacs 25.3.2 (x86_64-pc-linux-gnu, GTK+ Version 3.18.9) –  > Por agent18.
James Yang

pe baza versiunii magnars, am modificat ca mai jos, am fixat partea cu numele fișierului INIT:

(defun rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let* ((name (buffer-name))
        (filename (buffer-file-name))
        (basename (file-name-nondirectory filename)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " (file-name-directory filename) basename nil basename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

Comentarii

  • Aceasta este mai bună. Versiunea magnars dată mai sus NU funcționează corect. Adăugați un caracter „/” la sfârșit –  > Por mythicalcoder.
Jay Rajput

Emacs 26.3 (2020-04-03) are rename-file care poate fi invocată cu ajutorul funcției M-x rename-file pentru redenumirea fișierului curent sau a oricărui alt fișier.

Alan

Excelentul crux pachet are crux-rename-file-and-buffer (împreună cu multe alte funcții utile).

Eric_Chen

Se poate realiza prin copiere. shift+c pe fișier și emacs vă va cere să denotați un nume pentru calea de acces, inclusiv numele fișierului, deci trebuie doar să furnizați noul nume,și să introduceți…desigur, trebuie să îl ștergeți pe cel anterior.

Comentarii

  • Se pare că vă referiți la „C” în modul dired? Asta înseamnă copierea fișierului, nu redenumirea acestuia, care (după cum a observat @ChrisConway) în dired se face cu „R”. Și, în plus, OP a cerut o redenumire a bufferului curent. –  > Por Davor Cubranic.

Tags: