diff options
-rw-r--r-- | lisp/sqlite-mode.el | 69 |
1 files changed, 54 insertions, 15 deletions
diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el index e33a040f7ed..5e0410e4830 100644 --- a/lisp/sqlite-mode.el +++ b/lisp/sqlite-mode.el @@ -28,16 +28,19 @@ (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) @@ -62,10 +65,11 @@ (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 () @@ -129,7 +134,8 @@ (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 @@ -142,7 +148,8 @@ (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)) @@ -150,16 +157,48 @@ (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) |