2016-03-24 4 views
3

Derzeit arbeite ich an einem elisp Major-Modus, der Hash-Tabellen über Sitzungen hinweg verwendet. Jedes Mal, wenn der Hauptmodus initialisiert wird, werden die Tabellen in den Speicher geladen. Während und am Ende der Sitzung werden sie in eine Datei geschrieben. Meine aktuelle Implementierung schreibt die Daten auf folgende Weise:Idiomatische Art und Weise Serialisierung in Emacs lisp

(with-temp-buffer 
    (prin1 hash-table (current-buffer)) 
    (write-file ("path/to/file.el")))) 

die Daten zu Beginn der Sitzung Laden wird über Lesedurchgeführt und ist in etwa so:

(setq name-of-table (car 
     (read-from-string 
     (with-temp-buffer 
      (insert-file-contents path-of-file) 
      (buffer-substring-no-properties 
     (point-min) 
     (point-max)))))))) 

Es funktioniert, aber ich habe die Gefühl, dass dies nicht der schönste Weg ist, es zu tun. Mein Ziel ist: Ich möchte, dass dieser Hauptmodus zu einem schönen, sauberen Paket wird, das seine eigenen Daten in dem Ordner speichert, in dem die anderen Daten des Pakets gespeichert sind.

+1

Setzen Sie den Initialisierer in den Lisp Code, den Sie auf jeden Fall die Bewertung sind? Speichert Sie beim Lesen von irgendwelchen komplizierten Sachen - dann können Sie einfach "eval-buffer" und der Code, den Sie beim Schreiben hinzufügen, einfach "setq variable" und der abschließende Buchstabe am Ende sein. – tripleee

+0

sieht einfach und machbar aus. ^^ Ich werde sehen, wie das funktioniert und wenn es reibungslos geht werde ich Ihren Beitrag als Antwort taggen :) –

+0

Keine Notwendigkeit, in eine Zeichenfolge zu konvertieren, tun Sie einfach '(lesen (current-buffer))' in den temporären Puffer. – Lindydancer

Antwort

2

Dies ist, wie ich

schreiben implementieren Datei:

(defun my-write (file data) 
    (with-temp-file file 
    (prin1 data (current-buffer)))) 

Lesen von Datei:

(defun my-read (file symbol) 
    (when (boundp symbol) 
    (with-temp-buffer 
     (insert-file-contents file) 
     (goto-char (point-min)) 
     (set symbol (read (current-buffer)))))) 

Anruf zu schreiben:

(my-write "~/test.txt" emacs-version) 

Anruf

zu lesen
(my-read "~/test.txt" 'my-emacs-version) 
+1

Sie können '(goto-char (point-min))' gefolgt von '(read (current-buffer))' verwenden, so dass Sie keine Zeichenfolge erstellen müssen. – Lindydancer

+0

@Lindydancer Redigiert mit Ihrem Vorschlag. – tom

+0

Großartig! Ich würde jedoch vorschlagen, das 'goto-char' direkt nach dem' insert-file-content' zu platzieren, damit es einfacher zu lesen ist. Gibt es außerdem einen Grund, warum Sie den gelesenen Wert nicht einfach zurückgeben, anstatt eine Variable zu setzen? Dieser Code wäre sehr einfach: '(defun my-read-from-file (Datei) (with-temp-buffer (Datei einfügen-Datei-Inhalt) (goto-char (point-min)) (lesen (aktuelle buffer)))) ' – Lindydancer

1

ich mit folgenden Lösung kam, durch die erste Antwort inspiriert hier:

(with-temp-buffer 
    (insert "(setq hash-table ") 
    (prin1 hash-table (current-buffer) 
    (insert ")") 
    (write-file (locate-library "my-data-lib")) 

Und während der init des Hauptmodus, das tut ich gerade:

(load "my-data-lib") 

Keine Notwendigkeit for und read-operation und das Plus ist, dass ich auch keinen Dateipfad angeben muss, nur die Tatsache, dass es irgendwo im Ladepfad eine solche Datei gibt, ist genug. Emacs wird es finden. Elisp Felsen. :)

1

Das Paket desktop kann es für Sie tun:

(require 'desktop) 
(unless (memq 'hash-table desktop-globals-to-save) 
    (nconc desktop-globals-to-save (list 'hash-table)))`