Jak zmienić nazwę otwartego pliku w Emacsie?


237

Czy istnieje sposób zmiany nazwy otwartego pliku w Emacsie? Podczas oglądania? Coś jak save-as, ale oryginalny powinien odejść.

Odpowiedzi:


88

Wypróbuj tę funkcję z .emacs Steve'a Yegge :

;; źródło: http://steve.yegge.googlepages.com/my-dot-emacs-file
(unikaj zmiany nazwy pliku i bufora (nowa nazwa)
  „Zmienia nazwę zarówno bieżącego bufora, jak i pliku, który odwiedza na NEW-NAME”.
  (interaktywny „sNew name:”)
  (let ((nazwa (nazwa bufora))
        (nazwa pliku (nazwa-pliku-bufora)))
    (jeśli (nie nazwa pliku)
        (nazwa „Bufor '% s' nie odwiedza pliku!”)
      (if (get-buffer new-name)
          (komunikat „Bufor o nazwie„% s ”już istnieje!” new-name)
        (progn
          (zmień nazwę pliku nazwa_pliku nowa-nazwa 1)
          (rename-buffer new-name)
          (set-visit-file-name new-name)
          (set-buffer-zmodyfikowany-p zero))))))

Spójrz na tę stronę, jest tam jeszcze jedna bardzo przydatna pokrewna funkcja, zwana „plikiem bufora ruchu”.


1
Uwaga: ta metoda nie jest zgodna ze (setq uniquify-buffer-name-style 'forward)znaczeniem, jeśli masz bufor o nazwie users\index.html(ponieważ masz już inny bufor posts\index.html), zmiana nazwy nie powiedzie się
dolzenko

(set-buffer-modified-p nil)wydaje się niepotrzebne. Jeśli wywołałeś rename-file-and-bufferzmodyfikowany bufor, a następnie próbowałeś go zabić, chętnie zrobiłby to bez ostrzeżenia o niezapisanych zmianach.
roldugin

Ta funkcja również (nieco irytująco) poprosi cię o nową nazwę przed sprawdzeniem, czy bieżący bufor jest w ogóle skojarzony z plikiem (w którym to przypadku jest przerywany).
Thomas

338

Tak, w diredtrybie możesz:

  • C-x d otworzyć dired
  • RET aby wybrać katalog bieżącego pliku
  • C-x C-j( dired-jumpdo nazwy bieżącego pliku, w Dired)
  • Rzmienić nazwę pliku (lub dired-do-rename).
  • q wrócić do bufora pliku (o zmienionej nazwie)

Zmiana nazwy jest równoważna powłoce mv, ale zaktualizuje również wszystkie otwarte bufory i, w przeciwieństwie do mvtego, nie zmieni czasu dostępu ani modyfikacji pliku w systemie plików.


9
Nie zmienia to bezpośrednio nazwy bieżącego pliku.
pupeno

4
Cx b i wróciłeś do pierwotnego bufora. Możesz napisać funkcję Elisp, aby to zrobić, ale wątpię, czy zaoszczędzisz dzięki temu wiele naciśnięć klawiszy.
Chris Conway,

6
Ponadto, zamiast Cx b, możesz nacisnąć Cx k, aby powrócić do pierwotnego bufora.
Yoo

32
Nie C-x C-jjest to dla mnie domyślnie związane. Robienie tego M-x load-library RET dired-x RETnajpierw wiąże.
ntc2

4
Inną alternatywą, jeśli C-x C-jjest niezwiązana, jest po prostu M-x dired-jumpza pierwszym razem. Zostanie automatycznie załadowany dired-x(co również spowoduje, C-x C-jże zostanie zdefiniowane od tego momentu).
Fernando Basso,

120

Dla kompletności, ponieważ niektórzy ludzie mogą odwiedzić tę stronę, myśląc, że otrzymają odpowiedź na funkcję „zapisz jako” Emacsa, to Cx Cw dla otwartego pliku.


Cx Cw lub skorzystaj z menuFile > Save as...
Yoo 14.10

Niezupełnie „zapisz jako”, ponieważ edytowany plik nadal będzie oryginalny.
asmeurer

11
@asmeurer Mylisz się! Po zapisaniu będziesz edytować nowy plik.
Joel G Mathew

3
Znowu, dlaczego nie ma funkcji głosowania komentarzy ?!
niedźwiedź

7
Być może asmeurer miał na myśli: „plik, który edytujesz, nadal będzie istniał”. Czy to prawda? Sprawdziłbym, ale nie możesz głosować za moim komentarzem, hahaha.
Brady Trainor

25

Moim ulubionym jest ten z Magnars (sławnych screencastów z Emacsa Rocka ).

W przeciwieństwie do innych alternatyw, nie musisz wpisywać nazwy od zera - musisz zmienić obecną nazwę.

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

Dzięki Jamesowi Yangowi za poprawną wersję.


To NIE działa poprawnie. Ten dodaje „/” na końcu pliku.
mityczny

2
Dzięki za opublikowanie tego dla mnie. Takim sposobem jest poprawianie odpowiedzi, a nie publikowanie nowych, nieco zmodyfikowanych.
Unfun Cat

15

Oto bardziej solidna wersja zaadaptowana ze Steveya.

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

Niezłe. Teraz odpoczywam w moich funkcjach. El.
Felix D.

11

Oto kolejna wersja, która jest dość solidna i świadoma 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)))))))

Możesz przeczytać więcej na ten temat tutaj .



4

Jest bardzo prosty sposób, naciśnij komendę Mx i wpisz vc-rename-file , po czym musisz tylko wybrać swój aktualny plik w katalogu, a następnie wybrać nową nazwę. Buff, który ma zmieniony plik zostanie odświeżony.

Źródło: https://www.gnu.org/software/emacs/manual/html_node/emacs/VC-Delete_002fRename.html


1
Ma to (niekoniecznie pożądany) efekt uboczny polegający na dodaniu starych i nowych plików, które zostaną zatwierdzone do kontroli wersji. Ale +1, ponieważ używa wbudowanej funkcji, aby (głównie) odpowiedzieć na pytanie PO.
dinozaur

3

w oparciu o wersję magnars, zmodyfikowałem jak poniżej, naprawiłem część nazwy pliku 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)))))))

Ten jest lepszy. Podana powyżej wersja Magnars nie działa poprawnie. Dodaj znak „/” na końcu
mityczny

-1

Można to osiągnąć przez kopiowanie. Shift + C na pliku, a emacs poprosi cię o wskazanie nazwy ścieżki, w tym nazwy pliku, więc po prostu podaj nową nazwę i wpisz ... oczywiście, musisz usunąć poprzednią.


1
Wygląda na to, że masz na myśli „C” w trybie dired? To kopiowanie pliku, a nie zmiana jego nazwy, co (jak zauważył @ChrisConway) w dired odbywa się za pomocą „R”. Poza tym OP poprosił o zmianę nazwy bieżącego bufora.
Davor Cubranic,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.