]> git.eshelyaron.com Git - emacs.git/commitdiff
Add an sqlite-mode-delete command
authorLars Ingebrigtsen <larsi@gnus.org>
Sat, 11 Dec 2021 07:11:10 +0000 (08:11 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Sat, 11 Dec 2021 07:18:09 +0000 (08:18 +0100)
* lisp/sqlite-mode.el (sqlite-mode-delete): New command.
(sqlite--mode--list-data, sqlite-mode-list-data): Adjust to new
command.

lisp/sqlite-mode.el

index e33a040f7ed5998a1b7128e2ae8104a418948ffa..5e0410e4830979d0138ac69ef8407a4d45634af9 100644 (file)
 (defvar-keymap sqlite-mode-map
   "g" #'sqlite-mode-list-tables
   "c" #'sqlite-mode-list-columns
-  "RET" #'sqlite-mode-list-data)
+  "RET" #'sqlite-mode-list-data
+  "DEL" #'sqlite-mode-delete)
 
 (define-derived-mode sqlite-mode special-mode "Sqlite"
   "This mode lists the contents of an .sqlite3 file"
   :interactive nil
   (buffer-disable-undo)
   (setq-local buffer-read-only t
-              truncate-lines t))
+              truncate-lines t
+              sqlite-mode--statements nil))
 
 (defvar sqlite--db nil)
+(defvar sqlite-mode--statements nil)
 
 ;;;###autoload
 (defun sqlite-mode-open-file (file)
                                                   (car table)))))
             entries))
     (sqlite-mode--tablify '("Table Name" "Number of Rows")
-                          (nreverse entries))
+                          (nreverse entries)
+                          'table)
     (goto-char (point-min))))
 
-(defun sqlite-mode--tablify (columns rows &optional prefix)
+(defun sqlite-mode--tablify (columns rows type &optional prefix)
   (let ((widths
          (mapcar
           (lambda (i)
@@ -94,6 +98,7 @@
                                 (nth i row)
                               (string-replace "\n" " " (or elem "")))))))
         (put-text-property start (point) 'sqlite--row row)
+        (put-text-property start (point) 'sqlite--type type)
         (insert "\n")))))
 
 (defun sqlite-mode-list-columns ()
 (defun sqlite-mode-list-data ()
   "List the data from the table under poing."
   (interactive nil sqlite-mode)
-  (let ((row (get-text-property (point) 'sqlite--row)))
+  (let ((row (and (eq (get-text-property (point) 'sqlite--type) 'table)
+                  (get-text-property (point) 'sqlite--row))))
     (unless row
       (user-error "No table under point"))
     (let ((stmt (sqlite-select sqlite--db
             (delete-region (point) (if (re-search-forward "^[^ ]" nil t)
                                        (match-beginning 0)
                                      (point-max)))
-          (sqlite--mode--list-data stmt))))))
+          (sqlite--mode--list-data (list stmt (car row)))
+          (push stmt sqlite-mode--statements))))))
 
 (defun sqlite-mode--more-data (stmt)
   (let ((inhibit-read-only t))
     (delete-region (point) (progn (forward-line 1) (point)))
     (sqlite--mode--list-data stmt)))
 
-(defun sqlite--mode--list-data (stmt)
-  (let ((rows
-         (cl-loop for i from 0 upto 1000
-                  for row = (sqlite-next stmt)
-                  while row
-                  collect row)))
-    (sqlite-mode--tablify (sqlite-columns stmt) rows "  ")
+(defun sqlite--mode--list-data (data)
+  (let* ((stmt (car data))
+         (table (cadr data))
+         (rows
+          (cl-loop for i from 0 upto 1000
+                   for row = (sqlite-next stmt)
+                   while row
+                   collect row)))
+    (sqlite-mode--tablify (sqlite-columns stmt) rows (cons 'row table) "  ")
     (when (sqlite-more-p stmt)
-      (insert (buttonize "  More data...\n"
-                         #'sqlite-mode--more-data stmt)))))
+      (insert (buttonize "  More data...\n" #'sqlite-mode--more-data data)))))
+
+(defun sqlite-mode-delete ()
+  "Delete the row under point."
+  (interactive nil sqlite-mode)
+  (let ((table (get-text-property (point) 'sqlite--type))
+        (row (get-text-property (point) 'sqlite--row))
+        (inhibit-read-only t))
+    (when (or (not (consp table))
+              (not (eq (car table) 'row)))
+      (user-error "No row under point"))
+    ;; We have to remove all open statements before we can delete something.
+    (dolist (stmt sqlite-mode--statements)
+      (ignore-errors (sqlite-finalize stmt)))
+    (setq sqlite-mode--statements nil)
+    (save-excursion
+      (goto-char (point-min))
+      (let (match)
+        (while (setq match (text-property-search-forward 'button-data))
+          (delete-region (prop-match-beginning match)
+                         (prop-match-end match)))))
+    (sqlite-execute
+     sqlite--db
+     (format "delete from %s where %s"
+             (cdr table)
+             (string-join
+              (mapcar (lambda (column)
+                        (format "%s = ?" (car (split-string column " "))))
+                      (sqlite-mode--column-names (cdr table)))
+              " and "))
+     row)
+    (delete-region (line-beginning-position) (progn (forward-line 1) (point)))))
 
 (provide 'sqlite-mode)