]> code.delx.au - gnu-emacs-elpa/blobdiff - chess-file.el
Add examples for chess-plain and chess-ics1 to the manual.
[gnu-emacs-elpa] / chess-file.el
index 9667c06294cacb31e1bd470c3ff54f29bec510c4..1b3028b9b4ae1ffc96514c21bb78c5fae978b9d1 100644 (file)
@@ -1,29 +1,86 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; A game database that stores PGN format games in a single file.
-;;
-;; This is basically what you expect from a file ending in .pgn.
+;;; chess-file.el --- Handle chess databases stored in PGN or EPD files
+
+;; Copyright (C) 2002, 2004, 2014  Free Software Foundation, Inc.
+
+;; Author: John Wiegley <johnw@gnu.org>
+;; Maintainer: Mario Lang <mlang@delysid.org>
+;; Keywords: files, games
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; A game database that stores PGN or EPD format positions in a single file.
 ;;
-;; $Revision$
+;; This is basically what you expect from a file ending in .pgn or .epd.
 
-(defvar chess-file-locations)
+;;; Code:
 
+(require 'chess-fen)
+
+(defvar chess-file-locations nil
+  "A list of starting positions of individual records of this collection.")
 (make-variable-buffer-local 'chess-file-locations)
 
+(defvar chess-file-type nil
+  "The file format type of this database instance (a symbol).
+See `chess-file-types' for details.")
+(make-variable-buffer-local 'chess-file-type)
+
+(defvar chess-file-types
+  `((pgn "^\\[Event " chess-pgn-to-game chess-game-to-pgn (?\n ?\n))
+    (epd ,(concat chess-fen-regexp "\\(\\s-+.+\\);\\s-*$")
+        chess-epd-to-game chess-game-to-epd (?\n)))
+  "Alist of different file types.
+Entries have the form (TYPE BEGIN-REGEXP TO-GAME FROM-GAME SEPARATOR)
+where TYPE is a symbol (usually either 'pgn or 'epd),
+BEGIN-REGEXP is the regexp to use for matching the beginning of new records,
+TO-GAME and FROM-GAME are functions to use for reading and writing a game
+object from/into the buffer and SEPARATOR is a list of characters to insert
+inbetween of individual records.")
+
 (defun chess-file-handler (event &rest args)
+  "Event handler for file database objects."
   (cond
    ((eq event 'open)
     (with-current-buffer (find-file-noselect (car args))
-      (chess-file-handler 'rescan)
-      (current-buffer)))
+      (when (setq chess-file-type
+                 (cond
+                  ((or (string-match "\\.pgn\\'" (car args))
+                       (save-excursion (re-search-forward "^\\[Event" nil t)))
+                   'pgn)
+                  ((string-match "\\.epd\\'" (car args))
+                   'epd)))
+       (chess-file-handler 'rescan)
+       (current-buffer))))
 
    ((eq event 'rescan)
-    (goto-char (point-min))
-    (setq chess-file-locations nil)
-    (while (search-forward "[Event" nil t)
-      (goto-char (match-beginning 0))
-      (push (point) chess-file-locations))
-    (setq chess-file-locations (nreverse chess-file-locations)))
+    (save-excursion
+      (goto-char (point-min))
+      (setq chess-file-locations nil)
+      (while (re-search-forward (nth 1 (assq chess-file-type chess-file-types))
+                               nil t)
+       (goto-char (match-beginning 0))
+       (push (point) chess-file-locations)
+       (forward-char 1))
+      (setq chess-file-locations (nreverse chess-file-locations))))
+
+   ((eq event 'read-only-p)
+    buffer-read-only)
+
+   ((eq event 'filename)
+    buffer-file-name)
 
    ((eq event 'save)
     (save-buffer))
       (when (and (>= index 0)
                 (< index (chess-file-handler 'count)))
        (goto-char (nth index chess-file-locations))
-       (when (setq game (chess-pgn-to-game))
+       (when (setq game (funcall (nth 2 (assq chess-file-type
+                                              chess-file-types))))
          (chess-game-set-data game 'database (current-buffer))
          (chess-game-set-data game 'database-index index)
          (chess-game-set-data game 'database-count
-                              (chess-file-handler 'count))))))
+                              (chess-file-handler 'count))
+         game))))
 
    ((eq event 'write)
     (goto-char (point-max))
     (while (memq (char-before) '(?  ?\t ?\n ?\r))
-      (delete-backward-char 1))
-    (insert ?\n ?\n)
+      (delete-char -1))
+    (apply 'insert (nth 4 (assq chess-file-type chess-file-types)))
     (push (point) chess-file-locations)
-    (chess-game-to-pgn (car args))
+    (funcall (nth 3 (assq chess-file-type chess-file-types)) (car args))
     (1- (chess-file-handler 'count)))
 
    ((eq event 'replace)
        (delete-region (point) (if (= (1+ index) count)
                                   (point-max)
                                 (nth (1+ index) chess-file-locations)))
-       (chess-game-to-pgn (car args))
-       (insert ?\n))))))
+       (funcall (nth 3 (assq chess-file-type chess-file-types)) (car args))
+       (when (eq chess-file-type 'pgn) (insert ?\n)))))))
 
 (provide 'chess-file)