jak zdobyć bufory (nie tylko pliki), aby uhonorować auto-mode-alist?

13

P: Jak mogę zdobyć nowe bufory, aby uhonorować mapowanie auto-mode-alist?

Podczas wyszukiwania pliku Emacs porównuje rozszerzenie pliku z tym, auto-mode-alistaby określić, który tryb główny ma być używany dla bufora pliku. Czy istnieje sposób wykorzystania tych informacji w auto-mode-alistcelu określenia trybu bufora, który (jeszcze) nie jest powiązany z plikiem?

To znaczy: jeśli otworzę nowy bufor, którego nazwa ma coś, co wygląda jak rozszerzenie pliku, czy mogę uzyskać automatyczne otwieranie go w oczekiwanym trybie? Na przykład, jeśli miałbym otworzyć nowy bufor, a-new-buffer.elktóry nie jest jeszcze powiązany z plikiem, chcę, aby otwierał się w emacs-lisp-modetrybie domyślnym, a nie w trybie domyślnym.

Dan
źródło
2
Ciekawe: jaki jest przypadek użycia? IOW, dlaczego / kiedy / w jakim kontekście chcesz to zrobić? Zazwyczaj, jeśli chcesz, aby bufor był skojarzony z plikiem, a więc auto-mode-alistwybrałeś jego tryb , bufor odwiedza plik (i to wszystko załatwia).
Drew
5
Przykładami typowych przypadków użycia są: a) tymczasowy orgbufor do testowania nowych funkcji, w których piszę do użycia org-mode; b) tymczasowy Rbufor do szybkich, wyrzucanych manipulacji statystycznych; c) tymczasowy bufor tekstowy do tworzenia wiadomości e-mail. W każdym przypadku nie chcę tworzyć pliku do odwiedzenia, chcę tylko bufor usuwania, który mimo to otwiera się w odpowiednim trybie.
Dan
2
Polecenia plików odwiedzenie takich jak C-x C-ftemat nieutworzyć plik do odwiedzenia ”. To podstawowe nieporozumienie. Po prostu robią dokładnie to, czego szukasz. To jest tylko wtedy, gdy próbujesz zapisać bufor , że plik zostanie utworzony. Jeśli nie spróbujesz zapisać bufora, plik nie zostanie utworzony. Z tego, co rozumiem do tej pory, chcesz „odwiedzić plik” (co tak naprawdę oznacza otworzyć bufor w odpowiednim trybie).
Drew
8
Podobnie jak Dan, przez cały czas tworzę tymczasowe bufory, których nie chcę wiązać z rzeczywistą ścieżką pliku. Odwiedzenie fałszywej ścieżki do pliku działałoby, ale wybór katalogu (lub zaakceptowanie bieżącego) jest co najmniej niewielki. Mogą występować inne skutki uboczne w zależności od reszty konfiguracji: zachowanie automatycznego zapisywania? Grupy pocisków lub projekty pocisków określone przez ścieżkę? Czy monit o potwierdzenie? Ponieważ bufory i tak muszą mieć nazwę, używanie tej nazwy do automatycznego ustawiania trybu dla bufora tymczasowego ma dla mnie sens.
glucas
@Drew, tak, to ma sens i byłaby najprostszą odpowiedzią na to pytanie - czy możesz podać to jako odpowiedź, proszę? Zasługuje na aktualizację.
Dan

Odpowiedzi:

8

Polecenia do przeglądania plików, takie jak C-x C-f nie tworzą pliku do odwiedzenia. Robią to, czego szukasz.

Plik jest tworzony tylko wtedy, gdy próbujesz zapisać bufor .

Jeśli nie spróbujesz zapisać bufora, plik nie zostanie utworzony. Z tego, co rozumiem do tej pory, chcesz odwiedzić plik (co tak naprawdę oznacza otworzyć bufor w odpowiednim trybie).

Rysował
źródło
4
Co zrobić, jeśli masz nadpobudliwy palec, który stale zapisuje bieżący plik co 3 sekundy, niezależnie od tego, czego chcesz?
Malabarba
1
@Malabarba: Właściwie mam ten palec! ;-) Być może większość z nas robi stare pierdy - nawyk nabrał nawyku, gdy rzeczy ciągle się rozbijały. Ale w każdym razie robię to, co zasugerowałem: edytuję w buforze plików odwiedzin, które są usuwane. Jeśli moja nadaktywna pamięć mięśni przeszkadza i próbuje zapisać, niech tak będzie: albo uderzę, nżeby nie zapisać, albo (często) po prostu zapiszę bufor. A później podrzucam utworzony plik ... lub nie.)
Drew
1
@Malabarba To właśnie po to, aby zapobiec bałaganowi plików tymczasowych, zacząłem używać buforów scratch specyficznych dla trybu głównego. Jeśli rysa zasługuje na plik, zawsze możesz go zapisać jako jeden później.
Kaushal Modi
1
@kaushalmodi: Nic przeciwko twoim buforom specyficznym dla trybu, ale „ bałagan plików tymczasowych ” jest tak samo łatwy do wyczyszczenia jak bałagan buforów . ;-) A nadpobudliwy palec w specyficznym dla trybu buforze zadrapania przedstawia ten sam problem, prawdopodobnie - tak samo jak w przypadku *scratch*: zostaniesz poproszony o zapisanie, gdy ten palec automatycznie uderzy C-x C-s.
Drew
9

Jeśli od lat korzystasz z rozwiązania Jurija Linkova .

Tworzę tymczasowe bufory z czymś takim C-x b test.org C-j. Jest major-modeto określane przez rozszerzenie pliku za pośrednictwem auto-mode-alist.

;; http://thread.gmane.org/gmane.emacs.devel/115520/focus=115794
(setq-default major-mode
              (lambda () (if buffer-file-name
                          (fundamental-mode)
                            (let ((buffer-file-name (buffer-name)))
                          (set-auto-mode)))))

Aby przetestować efekt, możesz spróbować (prog1 (and (switch-to-buffer "my-new.org") major-mode) (kill-buffer "my-new.org")) => org-mode. Po czyszczeniu emacs -qtest wróciłby fundamental-mode.

rasmus
źródło
1
To bardzo sprytne! Jest także ładniejszy niż adviceopcja, z której korzystałem. Nie jestem pewien, czy śledzę, po co jest ta (prog1...)część, ale ta (setq-default major-mode ...)część jest całkiem fajna.
Dan
1
Zachęcamy do odwiedzenia strony Emacsa Jurija . W prog1-test tylko pokazuje, że można uzyskać oczekiwane major-modepodczas przełączania do bufora. Przejrzyj setq-defaultczęść i uruchom test. Wróci org-mode Bez setq-defaulttego wróci fundamental-mode.
rasmus
Jest to o wiele bardziej eleganckie niż mój hook-list-update-update-hook. Dzięki!
glucas
to powinna być zaakceptowana odpowiedź, ponieważ faktycznie odpowiada ona na pytanie, a nie mówi nam, dlaczego mylimy się, zadając go :)
Shlomi
6

Zrozumiałem sposób na porady, korzystając z pomysłów pochodzących z komentarzy @ Drew i odpowiedzi @ glucas, które tutaj nagrywam, na wypadek, gdyby były przydatne dla kogokolwiek.

Krótka wersja: skorzystaj z afterporady, aby sprawdzić, czy bufor ma powiązaną nazwę pliku, ustaw tymczasowo jeden plik, jeśli nie ma, a następnie pozwól pozostałym set-auto-modemaszynom zająć się szczegółami. Po kilku testach (niezbyt obszernych) wydaje się, że działa dobrze.

W przypadku ido-switch-bufferwanilii switch-to-bufferdwie rady to:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (let ((buffer-file-name (buffer-name)))
      (set-auto-mode t))))

(defadvice switch-to-buffer (after set-mode activate)
  (unless buffer-file-name
    (let ((buffer-file-name (buffer-name)))
      (set-auto-mode t))))

Uważam tę opcję za pomocną w find-filekwestii podniesionej przez @Drew, ponieważ moje palce mogą wyprzedzić mój mózg: pamięć mięśni często przenosi mnie na terytorium przełączania do bufora, zanim w pełni find-fileprzyjdzie mi do głowy, że zrobię to, czego potrzebuję. Teraz obie opcje są dostępne.

AKTUALIZACJA: mały, ale potencjalnie drażniący błąd w powyższym kodzie: ponownie uruchomi zaczep trybu na buforze za każdym razem, gdy do niego przełączysz. Poniżej podano rzeczywistą nazwę pliku z /tmpkatalogu i pozwala uniknąć tego problemu:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (setq buffer-file-name (concat "/tmp/" (buffer-name)))
    (set-auto-mode t)))
Dan
źródło
Wygląda dobrze i oczyszcza cruft, który moja odpowiedź zgromadziła przez kilka iteracji. :-) Powtórzę tutaj, że jeśli z jakiegoś powodu nie chcesz ustawić rzeczywistej ścieżki pliku, możesz użyć zmiennej lokalnej bufora, aby uniknąć wielokrotnego ustawiania trybu.
glucas
5

set-auto-modeFunkcja ustawia tryb oparty na pliku związanego z buforem. Oto funkcja, która tymczasowo ustawia buffer-file-namenazwę bufora w celu ustawienia trybu:

(defun my/set-buffer-mode (buffer &optional again)
  "Set the mode for BUFFER from the name.  
When called repeatedly for the same buffer only set the mode the first
time, unless the optional argument AGAIN is specified.
Does nothing if the buffer is associated with a file."

  (with-current-buffer buffer
    (when again (kill-local-variable 'my/buffer-mode-set))
    (unless (or buffer-file-name 
            (local-variable-p 'my/buffer-mode-set))
      (let ((buffer-file-name (buffer-name)))
        (set-auto-mode t)
        (setq-local my/buffer-mode-set t)))))

Możesz uruchomić to po zmianie nazwy bufora za pomocą porady:

(defadvice rename-buffer (after my/rename-update-mode activate)
  (my/set-buffer-mode (current-buffer) 'again))

Nie jestem pewien, czy jest to najlepsze miejsce, aby podłączyć to do nowych buforów. Tutaj używam buffer-list-update-hook, ale to jest wywoływane w większej liczbie przypadków, niż potrzebujemy.

(add-hook 'buffer-list-update-hook
      '(lambda ()
         (my/set-buffer-mode (car (buffer-list)))))
glucas
źródło
Powyższa odpowiedź została poprawiona, aby rozwiązać niektóre problemy. W szczególności wróciłem do używania, buffer-list-update-hookponieważ change-major-mode-hooknie był wywoływany z oczekiwanym bieżącym buforem. Dla przypomnienia, prawdopodobnie bardziej sensowne jest doradzenie twojej funkcji bufora przełączania, tak jak @Dan w swojej odpowiedzi.
glucas
3

Możesz użyć buforów * scratch * w celu utworzenia buforów tymczasowych, które mają ten sam tryb główny, co plik, nad którym możesz pracować.

Oto odpowiedź emacs SE, która może rozwiązać twój problem:

Jak mogę szybko przełączać między plikiem a buforem * scratch * o tym samym trybie głównym?

Odpowiedzi na pytania i odpowiedzi zostały przeze mnie opublikowane. Odpowiedź w funkcji wykonuje następujące czynności:

  • Jeśli pracujesz w trybie X-dur w pliku, wywołanie tej funkcji tworzy nowy bufor scratch, wywoływany, *scratch-X-mode*jeśli jeszcze nie istnieje, i przełącza się na ten nowo utworzony bufor.
  • Jeśli *scratch-X-mode*już istnieje, po prostu przełącza się na ten bufor.
  • Ponowne wywołanie tej funkcji w tym buforze scratch spowoduje powrót do bufora plików, nad którym pierwotnie pracowałeś.
Kaushal Modi
źródło
0

Jest tu kilka dobrych odpowiedzi, ale chciałem dodać jeszcze jedną rzecz. Emacs ma mnóstwo funkcji i często istnieje kilka sposobów na zrobienie czegoś. Możesz dodać tagi na górze dowolnego pliku, który mówi emacsowi, jakiego typu, niezależnie od rozszerzenia. Na przykład dodając to:

# -*-Python-*-

Na górze pliku poinformuje emacsa, że ​​jest to plik Pythona, nawet bez .pyrozszerzenia. Zauważ, że #na początku linii jest komentarz w stylu Pythona. Dla różnych typów plików możesz użyć różnych komentarzy. Na przykład, aby określić plik Lisp, którego używasz ;do uruchomienia wiersza komentarza i ustaw tryb w emacsie w następujący sposób:

; -*- mode: Lisp;-*-

Zobacz Określanie zmiennych plików i wybieranie trybów plików .

jcoffland
źródło
Tak, ale pytanie dotyczy konkretnie utworzenia nowego bufora tymczasowego (np. Z switch-buffer) i automatycznego ustawienia trybu na inny niż fundamental-mode.
glucas