come ottenere buffer (non solo file) per onorare l'auto-mode-alist?


13

D: come posso ottenere nuovi buffer per onorare la mappatura auto-mode-alist?

Quando trova un file , Emacs confronta l'estensione del file con quella auto-mode-alistper determinare quale modalità principale utilizzare per il buffer del file. Esiste un modo per utilizzare le informazioni auto-mode-alistper determinare la modalità di un buffer a cui non è (ancora) associato un file?

Cioè: se apro un nuovo buffer il cui nome ha qualcosa che assomiglia a un'estensione di file, posso farlo aprire automaticamente nella modalità prevista? Ad esempio, se dovessi aprire un nuovo buffer a-new-buffer.elche non è ancora associato a un file, voglio che si apra emacs-lisp-modeanziché nella modalità predefinita.


2
Solo curioso: qual è il caso d'uso? IOW, perché / quando / in quale contesto vuoi fare questo? In genere, se si desidera associare un buffer a un file e quindi scegliere la sua modalità auto-mode-alist, si fa in modo che il buffer " visiti " il file (e che si occupi di tutto).
Drew

5
Esempi di casi d'uso tipici per me sono: a) un orgbuffer temporaneo per testare nuove funzioni in cui sto scrivendo org-mode; b) un Rbuffer temporaneo per eseguire alcune manipolazioni statistiche rapide da eliminare; c) un buffer di testo temporaneo per comporre un messaggio di posta elettronica. In ogni caso, non voglio creare un file da visitare, voglio solo un buffer usa e getta che si apre comunque nella modalità appropriata.
Dan

2
Comandi del file di visitare, come C-x C-fnon non " creare un file da visita ". Questo è un malinteso fondamentale. Fanno semplicemente esattamente quello che stai cercando. È solo se e quando si tenta di salvare il buffer che viene creato un file. Se non si tenta di salvare il buffer, non viene creato alcun file. Quello che vuoi, da quello che ho capito finora, è "visitare un file" (il che significa davvero aprire un buffer nella modalità corretta).
Drew

8
Come Dan, creo continuamente buffer temporanei che non voglio associare a un percorso file effettivo. Visitando un percorso di file fasullo funzionerebbe ma c'è almeno una piccola quantità di attrito nella scelta di una directory (o nell'accettazione di quella corrente). Potrebbero esserci altri effetti collaterali a seconda del resto della configurazione: comportamento del salvataggio automatico? Gruppi di Ibuffer o progetti proiettili determinati dal percorso? Ido conferma le richieste? Dato che i buffer devono comunque avere un nome, usare il nome per impostare automaticamente la modalità per un buffer temporaneo ha senso per me.
Glucas,

@Drew, sì, ha senso e sarebbe la risposta più semplice a questa domanda - potresti pubblicarla come risposta, per favore? Merita un aggiornamento.
Dan

Risposte:


8

Comandi di visita ai file come C-x C-f non creare un file da visitare. Fanno quello che stai cercando.

È solo se e quando si tenta di salvare il buffer che viene creato un file .

Se non si tenta di salvare il buffer, non viene creato alcun file. Quello che vuoi, da quello che ho capito finora, è " visitare un file " (il che significa davvero aprire un buffer nella modalità corretta).


4
Cosa succede se si dispone di un dito iperattivo che salva costantemente il file corrente ogni 3 secondi indipendentemente da ciò che si desidera?
Malabarba,

1
@Malabarba: In realtà, ho quel dito! ;-) Forse la maggior parte di noi vecchi scoregge lo fanno - un'abitudine ripresa quando le cose si sono schiantate continuamente. Ma comunque, faccio proprio quello che ho suggerito: modifica in un buffer di file visitato da buttare via. Se la mia memoria muscolare iperattiva si mette in mezzo e cerca di salvare, così sia: o ho colpito nper non salvare o (spesso) ho solo salvato il buffer. E più tardi lancio il file creato ... o no.)
Disegnato il

1
@Malabarba È esattamente per prevenire il disordine dei file temporanei, che ho iniziato a utilizzare i buffer di memoria virtuale specifici della modalità principale. Se lo scratch merita un file, puoi sempre salvarlo come in un secondo momento.
Kaushal Modi,

1
@kaushalmodi: niente contro i tuoi buffer specifici per la modalità, ma un " disordine di file temporanei " è facile da eliminare come un disordine di buffer . ;-) E il dito iperattivo in un buffer di memoria specifico per la modalità presenta lo stesso problema, presumibilmente - lo stesso che fa in *scratch*: ti viene chiesto di salvare quando quel dito colpisce automaticamente C-x C-s.
Disegnò il

9

Se uso la soluzione di Juri Linkov da anni.

Creo buffer temporanei con qualcosa del genere C-x b test.org C-j. Il major-modeè determinato dall'estensione del file tramite 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)))))

Per testare l'effetto puoi provare (prog1 (and (switch-to-buffer "my-new.org") major-mode) (kill-buffer "my-new.org")) => org-mode. In una pulizia emacs -qil test ritornerebbe fundamental-mode.


1
È molto intelligente! È anche più ordinato advicedell'opzione che stavo usando. Non sono sicuro di seguire a cosa (prog1...)serve la parte, ma la (setq-default major-mode ...)parte è piuttosto carina.
Dan

1
Sentiti libero di dare un'occhiata al sito Emacs di Juri . Il prog1test mostra solo che ottieni l'atteso major-modequando passi a un buffer. Valutare la setq-defaultparte ed eseguire il test. Tornerà org-mode senza setq-defaultche sarebbe tornato fundamental-mode.
rasmus

Questo è molto più elegante del mio buffer-list-update-hook. Grazie!
glucas,

questa dovrebbe essere la risposta accettata, poiché in realtà risponde alla domanda piuttosto che dirci perché abbiamo torto nel chiederlo :)
Shlomi,

6

Ho escogitato un modo basato sui consigli usando idee che provenivano dai commenti di @ Drew e dalla risposta di @ glucas che registrerò qui nel caso siano utili a chiunque.

La versione breve: utilizzare i afterconsigli per verificare se il buffer ha un nome file associato, impostarne temporaneamente uno in caso contrario, quindi lasciare che il resto del set-auto-modemacchinario si occupi dei dettagli. Dopo un po 'di test (non approfondito), sembra funzionare bene.

Per ido-switch-buffere vaniglia switch-to-buffer, i due consigli sarebbero:

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

Trovo questa opzione utile oltre al find-filepunto che @Drew ha sollevato perché le mie dita riescono a superare il mio cervello: la memoria muscolare spesso mi porta nel territorio di passaggio al buffer prima che mi venga in mente che find-filefarebbe quello di cui ho bisogno. Ora, entrambe le opzioni sono disponibili.

AGGIORNAMENTO: bug piccolo ma potenzialmente irritante nel codice sopra: eseguirà nuovamente l'hook della modalità sul buffer ogni volta che si passa ad esso. Quanto segue fornisce un nome file effettivo fuori dalla /tmpdirectory ed evita quel problema:

(defadvice ido-switch-buffer (after set-mode activate)
  (unless buffer-file-name
    (setq buffer-file-name (concat "/tmp/" (buffer-name)))
    (set-auto-mode t)))

Ha un bell'aspetto e pulisce l'innesto che la mia risposta aveva accumulato in un paio di iterazioni. :-) Ripeterò qui che se non vuoi impostare un percorso di file effettivo per qualche motivo, puoi usare una variabile buffer-local per evitare di impostare la modalità più volte.
Glucas,

5

La set-auto-modefunzione imposta la modalità in base al file associato a un buffer. Ecco una funzione che imposta temporaneamente buffer-file-namedal nome del buffer per impostare la modalità:

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

È possibile eseguire questo quando un buffer viene rinominato usando un consiglio:

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

Non sono sicuro del posto migliore in cui collegarlo per influire sui nuovi buffer. Qui sto usando il buffer-list-update-hook, ma questo viene chiamato in più casi di quanti ne abbiamo bisogno.

(add-hook 'buffer-list-update-hook
      '(lambda ()
         (my/set-buffer-mode (car (buffer-list)))))

La risposta di cui sopra è stata rivista per affrontare alcuni problemi. In particolare, sono tornato a utilizzare il buffer-list-update-hookperché change-major-mode-hooknon era stato chiamato con il buffer corrente previsto. Per la cronaca, probabilmente ha più senso consigliare la funzione switch-buffer come fa @Dan nella sua risposta.
Glucas,

3

È possibile utilizzare i buffer * scratch * allo scopo di creare buffer temporanei con la stessa modalità principale del file su cui si potrebbe lavorare.

Ecco una risposta emacs SE che potrebbe risolvere il tuo problema:

Come posso passare rapidamente da un file a un buffer * scratch * con la stessa modalità principale?

La domanda e la risposta referenziate sono state entrambe pubblicate da me. La risposta nella funzione procede come segue:

  • Se si sta lavorando in X modalità principale in un file, la chiamata a questa funzione crea un nuovo buffer scratch chiamato *scratch-X-mode*se non esiste già e passa a questo buffer appena creato.
  • Se *scratch-X-mode*esiste già, passa semplicemente a quel buffer.
  • Richiamare di nuovo questa funzione mentre ci si trova in quel buffer di memoria vi riporterà al buffer di file su cui stavate lavorando originariamente.

0

Ci sono alcune buone risposte qui, ma volevo aggiungere un'altra cosa. Emacs ha molte funzionalità e spesso ci sono molti modi per fare qualcosa. Puoi aggiungere tag nella parte superiore di qualsiasi file che indichi a emacs di che tipo è, indipendentemente dall'estensione. Ad esempio aggiungendo questo:

# -*-Python-*-

Nella parte superiore di un file, Emacs saprà che è un file Python anche senza l' .pyestensione. Si noti che #all'inizio della riga è un commento in stile Python. Per diversi tipi di file è possibile utilizzare diversi commenti. Ad esempio per specificare un file Lisp che usi ;per iniziare una riga di commento e impostare la modalità in emacs in questo modo:

; -*- mode: Lisp;-*-

Vedere Specifica delle variabili di file e Scelta delle modalità di file .


Sì, ma la domanda qui riguarda in particolare la creazione di un nuovo buffer temporaneo (ad es. Con switch-buffer) e l'impostazione automatica della modalità su qualcosa di diverso da fundamental-mode.
Glucas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.