(lsdb-read) [Emacs]: Don't create temp buffer.
[elisp/lsdb.git] / lsdb.el
diff --git a/lsdb.el b/lsdb.el
index 845a664..718a214 100644 (file)
--- a/lsdb.el
+++ b/lsdb.el
@@ -73,7 +73,7 @@
   :group 'lsdb
   :type 'file)
 
-(defcustom lsdb-file-coding-system (find-coding-system 'iso-2022-jp)
+(defcustom lsdb-file-coding-system (find-coding-system 'ctext)
   "Coding system for `lsdb-file'."
   :group 'lsdb
   :type 'symbol)
@@ -229,6 +229,11 @@ Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
   :group 'lsdb
   :type 'string)
 
+(defcustom lsdb-verbose t
+  "If non-nil, confirm user to submit changes to lsdb-hash-table."
+  :type 'boolean
+  :group 'lsdb)
+
 ;;;_. Faces
 (defface lsdb-header-face
   '((t (:underline t)))
@@ -355,22 +360,19 @@ This is the current number of slots in HASH-TABLE, whether occupied or not."
 
 (eval-and-compile
   (condition-case nil
-      (progn
-       ;; In XEmacs, hash tables can also be created by the lisp reader
-       ;; using structure syntax.
-       (read-from-string "#s(hash-table)")
-       (defalias 'lsdb-read 'read))
+      (and
+       ;; In XEmacs, hash tables can also be created by the lisp reader
+       ;; using structure syntax.
+       (read-from-string "#s(hash-table)")
+       (defalias 'lsdb-read 'read))
     (invalid-read-syntax
      (defun lsdb-read (&optional marker)
        "Read one Lisp expression as text from MARKER, return as Lisp object."
        (save-excursion
         (goto-char marker)
         (if (looking-at "^#s(")
-            (with-temp-buffer
-              (buffer-disable-undo)
-              (insert-buffer-substring (marker-buffer marker) marker)
-              (goto-char (point-min))
-              (delete-char 2)
+            (progn
+              (forward-char 2) ;skip "#s"
               (let ((object (read (current-buffer)))
                     hash-table data)
                 (if (eq 'hash-table (car object))
@@ -383,7 +385,8 @@ This is the current number of slots in HASH-TABLE, whether occupied or not."
                       (while data
                         (lsdb-puthash (pop data) (pop data) hash-table))
                       hash-table)
-                  object)))))))))
+                  object)))
+          (read marker)))))))
 
 (defun lsdb-load-hash-tables ()
   "Read the contents of `lsdb-file' into the internal hash tables."
@@ -416,7 +419,8 @@ This is the current number of slots in HASH-TABLE, whether occupied or not."
          " test equal data (")
   (lsdb-maphash
    (lambda (key value)
-     (insert (prin1-to-string key) " " (prin1-to-string value) " "))
+     (let (print-level print-length)
+       (insert (prin1-to-string key) " " (prin1-to-string value) " ")))
    hash-table)
   (insert "))"))
 
@@ -773,8 +777,7 @@ This is the current number of slots in HASH-TABLE, whether occupied or not."
                   (marker-position lsdb-complete-marker))
              (save-excursion
                (re-search-backward "\\(\\`\\|[\n:,]\\)[ \t]*")
-               (goto-char (match-end 0))
-               (point))))
+               (set-marker lsdb-complete-marker (match-end 0)))))
         pattern
         (case-fold-search t)
         (completion-ignore-case t))
@@ -935,7 +938,7 @@ Modify whole identification by side effect."
     (if record
        (progn
          (setq net (car (cdr (assq 'net (cdr record)))))
-         (if (equal net (car record))
+         (if (and net (equal net (car record)))
              (setq lsdb-modeline-string net)
            (setq lsdb-modeline-string (concat (car record) " <" net ">"))))
       (setq lsdb-modeline-string ""))))
@@ -951,28 +954,36 @@ Modify whole identification by side effect."
 
 (defun lsdb-current-record ()
   "Return the current record name."
-  (let ((record (get-text-property (point) 'lsdb-record)))
-    (unless record
-      (error "There is nothing to follow here"))
-    record))
+  (get-text-property (point) 'lsdb-record))
 
 (defun lsdb-current-entry ()
-  "Return the current entry name.
-If the point is not on a entry line, it prompts to select a entry in
-the current record."
+  "Return the current entry name in canonical form."
   (save-excursion
     (beginning-of-line)
-    (if (looking-at "^[^\t]")
-       (let ((record (lsdb-current-record))
-             (completion-ignore-case t))
+    (if (looking-at "^\t\\([^\t][^:]+\\):")
+       (intern (downcase (match-string 1))))))
+
+(defun lsdb-read-entry (record &optional prompt)
+  "Prompt to select an entry in the given RECORD."
+  (let* ((completion-ignore-case t)
+        (entry-name
          (completing-read
-          "Which entry to modify: "
+          (or prompt
+              "Which entry: ")
           (mapcar (lambda (entry)
                     (list (capitalize (symbol-name (car entry)))))
-                  (cdr record))))
-      (end-of-line)
-      (re-search-backward "^\t\\([^\t][^:]+\\):")
-      (match-string 1))))
+                  (cdr record))
+          nil t)))
+    (unless (equal entry-name "")
+      (intern (downcase entry-name)))))
+
+(defun lsdb-delete-entry (record entry)
+  "Delete given ENTRY from RECORD."
+  (setcdr record (delq entry (cdr record)))
+  (lsdb-puthash (car record) (cdr record)
+               lsdb-hash-table)
+  (run-hook-with-args 'lsdb-update-record-functions record)
+  (setq lsdb-hash-tables-are-dirty t))
 
 (defun lsdb-mode-add-entry (entry-name)
   "Add an entry on the current line."
@@ -1008,45 +1019,53 @@ the current record."
                 (point))
               (list 'lsdb-record record)))))))))
 
-(defun lsdb-mode-delete-entry (&optional entry-name dont-update)
+(defun lsdb-mode-delete-entry-1 (entry)
+  "Delete text contents of the ENTRY from the current buffer."
+  (save-restriction
+    (lsdb-narrow-to-record)
+    (let ((case-fold-search t)
+         (inhibit-read-only t)
+         buffer-read-only)
+      (goto-char (point-min))
+      (if (re-search-forward
+          (concat "^\t" (capitalize (symbol-name (car entry))) ":")
+          nil t)
+         (delete-region (match-beginning 0)
+                        (if (re-search-forward
+                             "^\t[^\t][^:]+:" nil t)
+                            (match-beginning 0)
+                          (point-max)))))))
+
+(defun lsdb-mode-delete-entry ()
   "Delete the entry on the current line."
   (interactive)
   (let ((record (lsdb-current-record))
-       entry)
-    (or entry-name
-       (setq entry-name (lsdb-current-entry)))
-    (setq entry (assq (intern (downcase entry-name)) (cdr record)))
+       entry-name entry)
+    (unless record
+      (error "There is nothing to follow here"))
+    (setq entry-name (or (lsdb-current-entry)
+                        (lsdb-read-entry record "Which entry to delete: "))
+         entry (assq entry-name (cdr record)))
     (when (and entry
-              (not dont-update))
-      (setcdr record (delq entry (cdr record)))
-      (lsdb-puthash (car record) (cdr record)
-                   lsdb-hash-table)
-      (run-hook-with-args 'lsdb-update-record-functions record)
-      (setq lsdb-hash-tables-are-dirty t))
-    (save-restriction
-      (lsdb-narrow-to-record)
-      (let ((case-fold-search t)
-           (inhibit-read-only t)
-           buffer-read-only)
-       (goto-char (point-min))
-       (if (re-search-forward
-            (concat "^\t" (or entry-name
-                              (lsdb-current-entry))
-                    ":")
-            nil t)
-           (delete-region (match-beginning 0)
-                          (if (re-search-forward
-                               "^\t[^\t][^:]+:" nil t)
-                              (match-beginning 0)
-                            (point-max))))))))
+              (or (not (interactive-p))
+                  (not lsdb-verbose)
+                  (y-or-n-p
+                   (format "Do you really want to delete entry `%s' of `%s'?"
+                           entry-name (car record)))))
+      (lsdb-delete-entry record entry)
+      (lsdb-mode-delete-entry-1 entry))))
 
 (defun lsdb-mode-edit-entry ()
   "Edit the entry on the current line."
   (interactive)
-  (let* ((record (lsdb-current-record))
-        (entry-name (intern (downcase (lsdb-current-entry))))
-        (entry (assq entry-name (cdr record)))
-        (marker (point-marker)))
+  (let ((record (lsdb-current-record))
+       entry-name entry marker)
+    (unless record
+      (error "There is nothing to follow here"))
+    (setq entry-name (or (lsdb-current-entry)
+                        (lsdb-read-entry record "Which entry to edit: "))
+         entry (assq entry-name (cdr record))
+         marker (point-marker))
     (lsdb-edit-form
      (cdr entry) "Editing the entry."
      `(lambda (form)
@@ -1054,14 +1073,17 @@ the current record."
          (save-excursion
            (set-buffer lsdb-buffer-name)
            (goto-char ,marker)
-           (let* ((record (lsdb-current-record))
-                  (entry (assq ',entry-name (cdr record)))
-                  (inhibit-read-only t)
-                  buffer-read-only)
+           (let ((record (lsdb-current-record))
+                 entry
+                 (inhibit-read-only t)
+                 buffer-read-only)
+             (unless record
+               (error "The entry currently in editing is discarded"))
+             (setq entry (assq ',entry-name (cdr record)))
              (setcdr entry form)
              (run-hook-with-args 'lsdb-update-record-functions record)
              (setq lsdb-hash-tables-are-dirty t)
-             (lsdb-mode-delete-entry (symbol-name ',entry-name) t)
+             (lsdb-mode-delete-entry-1 entry)
              (beginning-of-line)
              (add-text-properties
               (point)
@@ -1077,7 +1099,8 @@ the current record."
       (message "(No changes need to be saved)")
     (when (or (interactive-p)
              dont-ask
-             (y-or-n-p "Save the LSDB now?"))
+             (not lsdb-verbose)
+             (y-or-n-p "Save the LSDB now? "))
       (lsdb-save-hash-tables)
       (setq lsdb-hash-tables-are-dirty nil)
       (message "The LSDB was saved successfully."))))
@@ -1148,8 +1171,6 @@ performed against the entry field."
     (lsdb-maphash
      (if entry-name
         (progn
-          (unless (symbolp entry-name)
-            (setq entry-name (intern (downcase entry-name))))
           (lambda (key value)
             (let ((entry (cdr (assq entry-name value)))
                   found)
@@ -1184,7 +1205,8 @@ performed against the entry field."
           (format "Search records `%s' regexp: " entry-name)
         "Search records regexp: ")
        nil nil nil 'lsdb-mode-lookup-history)
-      entry-name)))
+      (if (and entry-name (not (equal entry-name "")))
+         (intern (downcase entry-name))))))
   (lsdb-maybe-load-hash-tables)
   (let ((records (lsdb-lookup-records regexp entry-name)))
     (if records
@@ -1366,7 +1388,7 @@ always hide."
        (set-window-buffer window buffer)
        (lsdb-fit-window-to-buffer window)))))
 
-;;;_. Interface to Mew written by Hideyuki SHIRAI <shirai@rdmg.mgcs.mei.co.jp>
+;;;_. Interface to Mew written by Hideyuki SHIRAI <shirai@meadowy.org>
 (eval-when-compile
   (autoload 'mew-sinfo-get-disp-msg "mew")
   (autoload 'mew-current-get-fld "mew")
@@ -1600,7 +1622,7 @@ the user wants it."
 (provide 'lsdb)
 
 (product-provide 'lsdb
-  (product-define "LSDB" nil '(0 6)))
+  (product-define "LSDB" nil '(0 7)))
 
 ;;;_* Local emacs vars.
 ;;; The following `outline-layout' local variable setting: