Creating and maintaining a database in Emacs?

I read the Simple Database section in Peter Siebel's book Practical General Lisp with the idea of ​​supporting a small database of about 50,000 records. I thought that doing this in Emacs could be an interesting and useful exercise. Emacs Lisp is somewhat compatible with CL, with the exception of a few notable differences . The format function used in the above example is one of the main differences.

Here is the code that contains everything you need to create, save and load the database in the CL. Can this be changed to work well in Emacs? I omitted the select functions and where , but I would like to include them. Maybe there is a better way to create and maintain an Emacs database? Personally, I use this as an exercise to learn about CL and solve an existing problem.

  ;;  Simple Common Lisp database
 ;;  http://www.gigamonkeys.com/book/practical-a-simple-database.html
 ;;
 (defvar * db * nil)

 (defun make-cd (title artist rating ripped)
   (list: title title: artist artist: rating rating: ripped ripped))

 (defun add-record (cd) (push cd * db *))

 (defun dump-db ()
   (dolist (cd * db *)
     (format t "~ {~ a: ~ 10t ~ a ~% ~} ~%" cd)))

 (defun save-db (filename)
   (with-open-file (out filename
                    : direction: output
                    : if-exists: supersede)
     (with-standard-io-syntax
       (print * db * out))))

 (defun load-db (filename)
   (with-open-file (in filename)
     (with-standard-io-syntax
       (setf * db * (read in)))))
 ;  ===
 ;
 ;  Add some records
 ;
 (add-record (make-cd "Roses" "Kathy Mattea" 7 t))
 (add-record (make-cd "Fly" "Dixie Chicks" 8 t))
 (add-record (make-cd "Home" "Dixie Chicks" 9 t))

 ;  (dump-db)
 ;  (save-db "cd.db")
 ;  (load-db "cd.db")

+6
emacs elisp
source share
2 answers

When I tried to write an e-book for Emacs, I saved the entries in a list, from time to time saving it to disk. When the length of the list exceeded about five thousand entries, performance suffered.

Here are some functions from the code:

(defun bread-library-load-db () "Loads the list of books from disk file to the variable bread-library-db" (if (file-exists-p bread-library-file) (with-temp-buffer (insert-file-contents bread-library-file) (setq bread-library-db (read (current-buffer)))) (setq bread-library-db '()))) (defun bread-library-add-book (file) "Attempts to get metadata from file, then prompts for confirmation (or modification) of these metadata, then adds the book to the database and saves it. Intended use: from dired." (if (assoc file bread-library-db) (error "File is already in the database") (progn (let ((metadata (bread-get-metadata file))) (let ((filename (nth 0 metadata)) (author (read-from-minibuffer "Author: " (nth 1 metadata))) (title (read-from-minibuffer "Title: " (nth 2 metadata))) (genre (read-from-minibuffer "Genre: " (nth 3 metadata))) (tags (read-from-minibuffer "Tags (separated and surrounded by colons): " ":")) (desc (nth 4 metadata))) (setq bread-library-db (cons (list filename author title tags "TOREAD" genre nil desc) bread-library-db)))) (bread-library-save-db bread-library-db)))) (defun bread-library-save-db (db) "Save the library database to a file." (message "Saving Bread library database...") (with-temp-buffer (insert "; 1.path 2.author 3.title 4.tags 5.state 6.genre 7.priority 8.description") (print db (current-buffer)) (write-file bread-library-file)) (message "Saving Bread library database...done")) 
+2
source share

Here is my solution:

 (defvar *db* nil) (setq *db* ()) (defun make-cd (title artist rating ripped) (list :title title :artist artist :rating rating :ripped ripped)) (defun add-record (cd) (push cd *db*)) (defun init () (progn (add-record (make-cd "Roses" "Kathy Mattea" 7 t)) (add-record (make-cd "Fly" "Dixie Chicks" 8 t)) (add-record (make-cd "Home" "Dixie Chicks" 9 t)) )) (defun save-db (filename) (with-temp-buffer (print *db* (current-buffer)) (write-file filename)) (message "Saving database...done") ) (defun load-db (filename) (with-temp-buffer (insert-file-contents filename) (setq *db* (read (current-buffer))))) (defun dump-db () (dolist (cd *db*) (print cd))) ;; Test in Mx lisp-interaction-mode ;;(init) ;;(save-db "cd.db") ;*db* ;(add-record (make-cd "Born To Run" "Bruce Springsteen" 10 t)) ;(add-record (make-cd "The River" "Bruce Springsteen" 10 t)) ;(add-record (make-cd "Nebraska" "Bruce Springsteen" 10 t)) ;(add-record (make-cd "Human Touch" "Bruce Springsteen" 10 nil)) ;;(save-db "cd.db") ;(setq *db* ()) ;;(load-db "cd.db") ;*db*
(defvar *db* nil) (setq *db* ()) (defun make-cd (title artist rating ripped) (list :title title :artist artist :rating rating :ripped ripped)) (defun add-record (cd) (push cd *db*)) (defun init () (progn (add-record (make-cd "Roses" "Kathy Mattea" 7 t)) (add-record (make-cd "Fly" "Dixie Chicks" 8 t)) (add-record (make-cd "Home" "Dixie Chicks" 9 t)) )) (defun save-db (filename) (with-temp-buffer (print *db* (current-buffer)) (write-file filename)) (message "Saving database...done") ) (defun load-db (filename) (with-temp-buffer (insert-file-contents filename) (setq *db* (read (current-buffer))))) (defun dump-db () (dolist (cd *db*) (print cd))) ;; Test in Mx lisp-interaction-mode ;;(init) ;;(save-db "cd.db") ;*db* ;(add-record (make-cd "Born To Run" "Bruce Springsteen" 10 t)) ;(add-record (make-cd "The River" "Bruce Springsteen" 10 t)) ;(add-record (make-cd "Nebraska" "Bruce Springsteen" 10 t)) ;(add-record (make-cd "Human Touch" "Bruce Springsteen" 10 nil)) ;;(save-db "cd.db") ;(setq *db* ()) ;;(load-db "cd.db") ;*db* 
+2
source share

All Articles