2015-05-29 17 views
6

Cosa programmatori Emacs Lisp fanno, quando vogliono scrivere qualcosa grosso modo l'equivalente di ...In che modo i programmatori EMACS Lisp leggono i file di testo per scopi non di modifica?

for line in open("foo.txt", "r", encoding="utf-8").readlines(): 
    ...(split on ws and call a fn, or whatever)... 

..?

Quando guardo la guida di EMACS, vedo le funzioni relative all'apertura dei file nei buffer di modifica del testo, non esattamente ciò che intendevo. Suppongo di poter scrivere le funzioni per visitare le righe del file, ma se lo facessi, non vorrei che l'utente lo vedesse, e inoltre, non sembra molto efficiente dal punto di vista dell'elaborazione del testo.

risposta

9

penso che una traduzione più diretta del codice Python originale è la seguente:

(with-temp-buffer 
    (insert-file-contents "foo.txt") 
    (while (search-forward-regexp "\\(.*\\)\n?" nil t) 
    ; do something with this line in (match-string 1) 
    )) 

Penso with-temp-buffer/insert-file-contents è generalmente preferibile with-current-buffer/find-file-noselect, perché gli ex garanzie TH stai lavorando con una nuova copia dell'intero contenuto del file.Con quest'ultima costruzione, se si dispone già di un buffer che visita il file di destinazione, tale buffer viene restituito da find-file-noselect, quindi se il buffer è stato ridotto, vedrai solo quella parte del file quando la elabori.

Tenere presente che potrebbe essere molto più conveniente non elaborare il file riga per riga. Ad esempio, questa è un'espressione che restituisce un elenco di tutte le sequenze di cifre consecutive nel file:

(with-temp-buffer 
    (insert-file-contents "foo.txt") 
    (loop while (search-forward-regexp "[0-9]+" nil t) 
     collect (match-string 0))) 

(require 'cl) primo a portare in loop macro.

+1

Se si elabora il file riga per riga, di solito è più veloce usare 'forward-line' o' end-of-line'. – jch

+1

Secondo la mia esperienza è un po 'difficile identificare la fine del file usando 'forward-line' e parentela se l'ultima riga può o meno terminare con una nuova riga. – Sean

4
  1. Sì, che è ciò che si vuole fare: visitare il file in un buffer, e operare sul testo in quel buffer.

  2. Si non è necessario visualizzare il buffer, vale a dire, l'utente non ha bisogno di vederlo.

  3. E per quanto riguarda l'efficienza: la manipolazione di testo in un buffer è in genere il modo efficiente più per manipolare il testo.


Si può visitare un file in un buffer in diversi modi. Potresti voler utilizzare un buffer di file esistente per questo, a seconda del caso d'uso. Cioè, se il file è già "aperto" in Emacs, potresti voler usare il suo buffer.

Oppure si potrebbe voler ignorare qualsiasi buffer di file esistente per un file già "aperto" e leggere nuovamente il file in un nuovo buffer. Per questo, come cita @Sean, puoi usare insert-file-contents con un buffer che hai creato. È possibile creare il buffer utilizzando with-temp-buffer o generate-new-buffer, a seconda, ancora, su ciò che si desidera/deve fare con esso.

Se si desidera riutilizzare un buffer che sta già visitando il file, è possibile verificare se è stato modificato in memoria, se è ristretto, ecc., E fare tutto ciò che è appropriato per il proprio caso d'uso. È possibile verificare se esiste già un buffer che visita il file (utilizzando qualsiasi percorso/nome file) utilizzando la funzione find-buffer-visiting.

Per visitare il file, sfruttando qualsiasi buffer esistente che lo sta visitando, è possibile utilizzare find-file-noselect. Quella funzione restituisce il buffer che visita il file, quindi è possibile passare quel buffer come primo argomento a with-current-buffer. Qui c'è un semplice esempio.

(with-current-buffer (let ((enable-local-variables ())) (find-file-noselect file)) 
    ;; Do some stuff with the text in the buffer. 
    ;; Optionally save the buffer back to the file. 
) 

(il legame di enable-local-variables-nil è un'ottimizzazione minore, per il caso comune in cui non c'è bisogno di perdere tempo con le variabili del buffer-locale.)

+0

Il problema con 'find-file-noselect' è ciò che accade se l'utente sta già visitando il file. Ecco perché è meglio usare 'insert-file' in un buffer temporaneo, come nella risposta di Sean. – jch

+0

@jch: No, la generalizzazione "è meglio" è sbagliata. Tutto dipende da ciò che vuoi/devi fare - il diavolo della soluzione/implementazione è nei dettagli del problema/requisito. L'importante risposta alla domanda è ciò che ho messo davanti, come 1, 2, 3. La domanda posta è basata su un malinteso, che 1, 2, 3 dovrebbe chiarire. – Drew

Problemi correlati