Cosa c'è che non va in `find-file-noselect`?


11

In una recente risposta del lunaryorn , ha affermato:

Tuttavia, raccomanderei contro la maggior parte delle altre parti di Org, per motivi già indicati nei commenti: è vecchio e pieno di pratiche legacy e dannose (ad esempio find-file-noselect per leggere i file in modo non interattivo).

Qualcuno può spiegare perché è find-file-noselectuna cattiva idea leggere i file nei programmi Elisp? Esiste un modo migliore? Lo sto chiedendo perché stavo pensando di usarlo in uno dei miei progetti.


Apparentemente, non c'erano good-practicestag prima; è una buona idea usarlo?
mbork,

Penso che good-practicesrientrerebbe nella categoria del "meta tag", che è disapprovato da SE.
nispio,

1
@nispio Penso che sia un tag valido, ma ovviamente possiamo portarlo al meta.
Malabarba,

1
@nsipio: ho sfogliato quell'articolo e non sono d'accordo. Ma non sono io a decidere. ;-)
mbork,

Risposte:


14

TL; DR : Con find-file-noselectte non hai alcun controllo su ciò che accade realmente e potresti finire con modalità secondarie arbitrarie che si abilitano nel buffer, a seconda di ciò che l'utente ha abilitato nel loro init.el. Inoltre, la pulizia è difficile.

Usa with-temp-buffere insert-file-contentsinvece. Se sono necessarie specifiche modalità principali o secondarie nel buffer, abilitarle esplicitamente . Per scrivere i file, utilizzare with-temp-fileinvece, che, nonostante il nome, consente di scrivere su file arbitrari.

Effetti collaterali

find-file-noselectha molti effetti collaterali, tra cui

  • porre domande interattivamente (che da solo è un non-uso in un uso non interattivo),
  • abilitazione automatica della modalità di visualizzazione per file di sola lettura,
  • entrare in modalità normale altrimenti,
  • e in esecuzione find-file-hook.

Modalità normale stessa

  • seleziona automaticamente una modalità principale appropriata per il buffer corrente,
  • esegue tutti gli hook di modalità principale e secondaria corrispondenti,
  • e legge tutte le variabili locali per il buffer corrente, vale a dire variabili di file e variabili di directory, che potrebbero porre nuovamente domande interattive su variabili locali non sicure.

Poiché tutti gli hook vengono eseguiti, ottieni tutte le modalità secondarie e le funzioni hook che l'utente ha abilitato nelle loro init.el, il che può causare tutto, da piccoli inconvenienti (se le modalità secondarie indesiderabili sono abilitate) al caos maggiore (se l'utente ha aggiunto una funzione hook che si aspetta di essere chiamato da un contesto interattivo).

Vedere https://github.com/flycheck/flycheck/issues/366 per un esempio. L'uso di find-file-noselectun file di dati è stato verificato da Flycheck per la verifica della sintassi e, poiché si stava verificando all'arresto di Emacs, non c'era tempo per ripulire correttamente, lasciando indietro un file temporaneo.

Pulire

Con find-file-noselectè necessario prestare particolare attenzione a eliminare nuovamente il buffer. find-file-noselectnon lo fa per te.

È necessario ricordare il buffer in qualche punto e utilizzarlo attentamente unwind-protectper assicurarsi che il buffer venga ucciso anche in caso di uscite non locali.

alternative

Per leggere i file, utilizzare with-temp-buffere insert-file-contents, che esegue solo le operazioni di base, ad esempio la conversione del sistema di codifica, ma non fa domande, abilita hook o imposta variabili locali:

(with-temp-buffer
  (insert-file-contents (locate-user-emacs-file "foo.el"))
  ;; Enter the major mode explicitly
  (emacs-lisp-mode)
  ;; …
  )

with-temp-buffer si prende cura di uccidere correttamente il buffer temporaneo alla fine del suo corpo.

Per scrivere file, utilizzare with-temp-file, che crea un buffer temporaneo e scrive il contenuto sul nome file specificato alla fine del suo corpo:

(with-temp-file  (locate-user-emacs-file "foo.el")
  (prin1 (list 'my 'data) (current-buffer)))

10

Dalla sezione 24.3 del manuale Elisp:

Per copiare il contenuto di un file in un buffer, utilizzare la funzione insert-file-contents. (Non usare il comando insert-filein un programma Lisp, in quanto imposta il segno.)

Cercare la documentazione di Elisp find-file-noselectè ovvio che fa molto di più che leggere semplicemente un file in un buffer. Forse le persone che pensano che usare questa funzione sia una cattiva idea stanno pensando agli effetti collaterali, forse indesiderati? Immagino che dipenda da cosa vuoi ottenere. Se si desidera avere il contenuto di buffer pulito / intatto possibile, potrebbe essere una buona idea utilizzare la combinazione vecchia e affidabile with-temp-buffer+ insert-file-contents. Se si desidera che il contenuto del buffer di essere il più vicino a quello che find-filela produzione, forse non desidera utilizzare find-file-noselect? O forse stava pensando find-file;)


3
Se qualcosa viene fatto in modo non interattivo, non riesco a vedere alcuno scenario in cui vorresti che "il contenuto del buffer fosse vicino a ciò che avrebbe prodotto il file di ricerca" . find-file è lento perché fa un sacco di cose inutili, inclusi tutti i tipi di hook. L'unica "caratteristica" di find-file che potresti desiderare è la modalità principale, ma dovresti semplicemente attivarla da solo (non puoi nemmeno garantire che find-file accenda la modalità che desideri comunque).
Malabarba,

Malabarba: se intendi che il buffer rimanga disponibile per la modifica da parte dell'utente, potresti voler imitare il find-fileprocesso.
phils,
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.