Wie erhält man Puffer (nicht nur Dateien), um Auto-Mode-Alist zu ehren?

13

F: Wie kann ich neue Puffer erhalten , um die Zuordnung zu berücksichtigen auto-mode-alist?

Beim Auffinden einer Datei vergleicht Emacs die Dateierweiterung mit der, auto-mode-alistum festzustellen, welcher Hauptmodus für den Dateipuffer verwendet werden soll. Gibt es eine Möglichkeit, die Informationen in auto-mode-alistzu verwenden, um den Modus für einen Puffer zu bestimmen, dem (noch) keine Datei zugeordnet ist?

Das heißt: Wenn ich einen neuen Puffer öffne, dessen Name wie eine Dateierweiterung aussieht, kann ich dann veranlassen, dass er automatisch im erwarteten Modus geöffnet wird? Wenn ich beispielsweise einen neuen Puffer öffne a-new-buffer.el, der noch keiner Datei zugeordnet ist, soll er nicht emacs-lisp-modeim Standardmodus geöffnet werden.

Dan
quelle
2
Nur neugierig: Was ist der Anwendungsfall? IOW, warum / wann / in welchem ​​Kontext möchten Sie das tun? Wenn Sie möchten, dass ein Puffer mit einer Datei verknüpft wird, und den Modus abrufen, müssen Sie in der Regel festlegen auto-mode-alist, dass der Puffer die Datei " besucht " (und das erledigt alles).
Drew
5
Beispiele für typische Anwendungsfälle sind: a) ein temporärer orgPuffer zum Testen neuer Funktionen, in denen ich schreibe org-mode; b) einen temporären RPuffer, um einige schnelle, wegwerfbare statistische Manipulationen durchzuführen; c) einen temporären Textpuffer zum Verfassen einer E-Mail. In jedem Fall möchte ich keine zu besuchende Datei erstellen, sondern nur einen Wegwerfpuffer, der sich dennoch im entsprechenden Modus öffnet.
Dan
2
Datei - Besuch Befehle wie C-x C-fsie nichterstellen Sie eine Datei zu Besuch “. Das ist ein grundlegendes Missverständnis. Sie machen einfach genau das, wonach Sie suchen. Es ist nur , wenn und wenn Sie versuchen, den Puffer zu speichern , dass eine Datei erstellt wird. Wenn Sie nicht versuchen, den Puffer zu speichern, wird keine Datei erstellt. Soweit ich weiß, möchten Sie "eine Datei besuchen" (was wirklich bedeutet, einen Puffer im richtigen Modus zu öffnen).
Drew
8
Wie Dan erstelle ich die ganze Zeit temporäre Puffer, die keinem tatsächlichen Dateipfad zugeordnet werden sollen. Das Aufrufen eines falschen Dateipfads würde funktionieren, aber die Auswahl eines Verzeichnisses (oder das Akzeptieren des aktuellen Verzeichnisses) ist zumindest ein wenig umständlich. Abhängig von der restlichen Konfiguration können andere Nebenwirkungen auftreten: Verhalten beim automatischen Speichern? Ipuffergruppen oder Projektilprojekte nach Pfad bestimmt? Ido Bestätigungsaufforderungen? Da Puffer ohnehin einen Namen haben müssen, ist es für mich sinnvoll, den Modus für einen temporären Puffer automatisch über den Namen festzulegen.
Glucas
@Drew, ja, das macht Sinn und wäre die einfachste Antwort auf diese Frage. Könnten Sie sie bitte als Antwort posten? Es verdient ein Upgrade.
Dan

Antworten:

8

C-x C-f Dateibesuchsbefehle wie erstellen keine zu besuchende Datei . Sie tun, wonach Sie suchen.

Nur wenn Sie versuchen, den Puffer zu speichern , wird eine Datei erstellt .

Wenn Sie nicht versuchen, den Puffer zu speichern, wird keine Datei erstellt. Soweit ich weiß, möchten Sie " eine Datei besuchen " (was wirklich bedeutet, einen Puffer im richtigen Modus zu öffnen).

Drew
quelle
4
Was ist, wenn Sie einen hyperaktiven Finger haben, der die aktuelle Datei alle 3 Sekunden speichert, unabhängig davon, was Sie möchten?
Malabarba
1
@ Malabarba: Eigentlich habe ich diesen Finger! ;-) Vielleicht tun es die meisten von uns alten Fürzen - eine Gewohnheit, die zurückkehrte, als die Dinge die ganze Zeit zusammenbrachen. Auf jeden Fall tue ich genau das, was ich vorgeschlagen habe: In einem Wegwerfpuffer für besuchte Dateien bearbeiten. Wenn mein überaktives Muskelgedächtnis in die Quere kommt und versucht zu speichern, dann sei es: Entweder ich drücke, num nicht zu speichern, oder ich speichere (oft) nur den Puffer. Und später werfe ich die erstellte Datei ... oder nicht.)
Drew
1
@Malabarba Genau um das Durcheinander von temporären Dateien zu verhindern, habe ich damit begonnen, spezielle Arbeitsspeicher für den Hauptmodus zu verwenden. Wenn der Kratzer eine Datei verdient, können Sie diese später immer noch speichern.
Kaushal Modi
1
@kaushalmodi: Nichts gegen Ihre modusspezifischen Puffer, aber ein " Durcheinander von temporären Dateien " ist so einfach zu beseitigen wie ein Durcheinander von Puffern . ;-) Und der hyperaktive Finger in einem modusspezifischen Scratch-Buffer weist vermutlich dasselbe Problem auf - genau wie in *scratch*: Sie werden aufgefordert, zu speichern, wenn dieser Finger automatisch trifft C-x C-s.
Drew
9

Ich verwende die Lösung von Juri Linkov seit Jahren.

Ich erstelle temporäre Puffer mit so etwas wie C-x b test.org C-j. Die major-modewird durch die Dateierweiterung über bestimmt 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)))))

Um den Effekt zu testen, können Sie versuchen (prog1 (and (switch-to-buffer "my-new.org") major-mode) (kill-buffer "my-new.org")) => org-mode. In einem sauberen würde emacs -qder Test zurückkehren fundamental-mode.

Rasmus
quelle
1
Das ist sehr schlau! Es ist auch ordentlicher als die adviceOption, die ich verwendet hatte. Ich bin mir nicht sicher, wofür der (prog1...)Teil ist, aber der (setq-default major-mode ...)Teil ist ganz nett.
Dan
1
Besuchen Sie auch die Emacs-Website von Juri . Der prog1-test zeigt nur, dass Sie major-modebeim Umschalten auf einen Puffer die erwarteten Ergebnisse erhalten. Bewerte das setq-defaultTeil und führe den Test aus. Es wird zurückkehren org-mode Ohne das setq-defaultwürde es zurückkehren fundamental-mode.
Rasmus
Das ist viel eleganter als mein Buffer-List-Update-Hook. Vielen Dank!
Glucas
Dies sollte die akzeptierte Antwort sein, da es tatsächlich die Frage beantwortet, anstatt uns zu sagen, warum wir falsch sind, es zu stellen :)
Shlomi
6

Hat einen beratungsbasierten Weg gefunden, indem Ideen aus @ Drews Kommentaren und @ glucas 'Antwort verwendet wurden, die ich hier aufzeichnen werde, falls sie für irgendjemanden nützlich sind.

Die Kurzversion: afterFragen Sie mit Hilfe von Anweisungen ab, ob dem Puffer ein Dateiname zugeordnet ist, und legen Sie einen temporären Namen fest, falls dies nicht der Fall ist. Lassen Sie dann den Rest der set-auto-modeMaschine die Details erledigen. Nach einigem Testen (nicht umfangreich) scheint es gut zu funktionieren.

Für ido-switch-bufferund Vanille switch-to-bufferwären die beiden Ratschläge:

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

Ich finde diese Option zusätzlich zu dem find-filePunkt hilfreich , den @Drew ausgelöst hat, weil meine Finger meinem Gehirn einen Schritt voraus sind: Das Muskelgedächtnis versetzt mich oft in ein Gebiet, in das ich in den Puffer wechseln kann, bevor mir völlig einfällt, dass es find-filedas tut, was ich brauche. Jetzt sind beide Optionen verfügbar.

UPDATE: kleiner, aber möglicherweise irritierender Fehler im obigen Code: Bei jedem Wechsel wird der Modus-Hook des Puffers erneut ausgeführt. Das Folgende gibt einen tatsächlichen Dateinamen aus dem /tmpVerzeichnis und vermeidet dieses Problem:

(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
quelle
Sieht gut aus und räumt den Müll auf, den meine Antwort in ein paar Iterationen angehäuft hat. :-) Ich wiederhole hier nur, dass Sie, wenn Sie aus irgendeinem Grund keinen tatsächlichen Dateipfad festlegen möchten, eine pufferlokale Variable verwenden können, um zu vermeiden, dass der Modus mehrmals festgelegt wird.
Glucas
5

Das set-auto-mode Funktion legt den Modus basierend auf der Datei fest, die einem Puffer zugeordnet ist. Hier ist eine Funktion, die vorübergehend anhand buffer-file-namedes Puffernamens festgelegt wird, um den Modus festzulegen:

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

Sie können dies ausführen, wenn ein Puffer mit dem folgenden Hinweis umbenannt wird:

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

Ich bin mir nicht sicher, wo ich dies am besten einhängen kann, um neue Puffer zu beeinflussen. Hier benutze ich das buffer-list-update-hook, aber das wird in mehr Fällen aufgerufen, als wir brauchen.

(add-hook 'buffer-list-update-hook
      '(lambda ()
         (my/set-buffer-mode (car (buffer-list)))))
Glucas
quelle
Die obige Antwort wurde überarbeitet, um einige Probleme zu lösen. Insbesondere habe ich wieder das verwendet, buffer-list-update-hookweil das change-major-mode-hooknicht mit dem erwarteten aktuellen Puffer aufgerufen wurde. Für die Aufzeichnung ist es wahrscheinlich sinnvoller, Ihre Switch-Buffer-Funktion zu empfehlen, wie dies @Dan in seiner Antwort tut.
Glucas
3

Sie können * scratch * -Puffer verwenden, um temporäre Puffer zu erstellen, die denselben Hauptmodus wie die Datei haben, an der Sie möglicherweise arbeiten.

Hier eine Antwort von emacs SE, die Ihr Problem lösen könnte:

Wie kann ich schnell zwischen einer Datei und einem * scratch * -Puffer mit demselben Hauptmodus wechseln?

Die referenzierte Frage und Antwort wurden beide von mir gepostet. Die Antwort in der Funktion bewirkt Folgendes:

  • Wenn Sie in einer Datei im X-Major-Modus arbeiten, wird durch Aufrufen dieser Funktion ein neuer Arbeitspuffer mit dem Namen erstellt *scratch-X-mode* falls noch keiner vorhanden ist, und zu diesem neu erstellten Puffer gewechselt.
  • Wenn *scratch-X-mode*bereits vorhanden, wird einfach auf diesen Puffer umgeschaltet.
  • Wenn Sie diese Funktion in diesem Arbeitspuffer erneut aufrufen, kehren Sie zu dem Dateipuffer zurück, an dem Sie ursprünglich gearbeitet haben.
Kaushal Modi
quelle
0

Hier gibt es einige gute Antworten, aber ich wollte noch etwas hinzufügen. Emacs hat eine Menge Funktionen und es gibt oft mehrere Möglichkeiten, etwas zu tun. Sie können Tags am Anfang jeder Datei hinzufügen, die unabhängig von der Erweiterung angeben, welcher Typ sie hat. Zum Beispiel dies hinzufügen:

# -*-Python-*-

Am Anfang einer Datei wird Emacs wissen lassen, dass es sich auch ohne die .pyErweiterung um eine Python-Datei handelt . Beachten Sie, dass der #Anfang der Zeile ein Kommentar im Python-Stil ist. Für verschiedene Dateitypen können Sie verschiedene Kommentare verwenden. Um beispielsweise eine Lisp-Datei anzugeben, die Sie ;zum Starten einer Kommentarzeile und zum Festlegen des Modus in Emacs verwenden, gehen Sie wie folgt vor:

; -*- mode: Lisp;-*-

Siehe Angeben von Dateivariablen und Auswählen von Dateimodi .

jcoffland
quelle
Ja, aber die Frage hier bezieht sich speziell auf das Erstellen eines neuen temporären Puffers (z. B. mit switch-buffer) und das automatische Einstellen des Modus auf etwas anderes als fundamental-mode.
Glucas