diff options
| author | Lars Ingebrigtsen | 2021-12-11 08:11:10 +0100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2021-12-11 08:18:09 +0100 |
| commit | 7cbda71617f52adde8872c6d2d260e94e4b52edd (patch) | |
| tree | 8e48aeeab2f54ed82bb09b7fcdd58d94a76567be | |
| parent | 17569c94954dc1d9d47155a8ca987d8ff4855180 (diff) | |
| download | emacs-7cbda71617f52adde8872c6d2d260e94e4b52edd.tar.gz emacs-7cbda71617f52adde8872c6d2d260e94e4b52edd.zip | |
Add an sqlite-mode-delete command
* lisp/sqlite-mode.el (sqlite-mode-delete): New command.
(sqlite--mode--list-data, sqlite-mode-list-data): Adjust to new
command.
| -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 @@ | |||
| 28 | (defvar-keymap sqlite-mode-map | 28 | (defvar-keymap sqlite-mode-map |
| 29 | "g" #'sqlite-mode-list-tables | 29 | "g" #'sqlite-mode-list-tables |
| 30 | "c" #'sqlite-mode-list-columns | 30 | "c" #'sqlite-mode-list-columns |
| 31 | "RET" #'sqlite-mode-list-data) | 31 | "RET" #'sqlite-mode-list-data |
| 32 | "DEL" #'sqlite-mode-delete) | ||
| 32 | 33 | ||
| 33 | (define-derived-mode sqlite-mode special-mode "Sqlite" | 34 | (define-derived-mode sqlite-mode special-mode "Sqlite" |
| 34 | "This mode lists the contents of an .sqlite3 file" | 35 | "This mode lists the contents of an .sqlite3 file" |
| 35 | :interactive nil | 36 | :interactive nil |
| 36 | (buffer-disable-undo) | 37 | (buffer-disable-undo) |
| 37 | (setq-local buffer-read-only t | 38 | (setq-local buffer-read-only t |
| 38 | truncate-lines t)) | 39 | truncate-lines t |
| 40 | sqlite-mode--statements nil)) | ||
| 39 | 41 | ||
| 40 | (defvar sqlite--db nil) | 42 | (defvar sqlite--db nil) |
| 43 | (defvar sqlite-mode--statements nil) | ||
| 41 | 44 | ||
| 42 | ;;;###autoload | 45 | ;;;###autoload |
| 43 | (defun sqlite-mode-open-file (file) | 46 | (defun sqlite-mode-open-file (file) |
| @@ -62,10 +65,11 @@ | |||
| 62 | (car table))))) | 65 | (car table))))) |
| 63 | entries)) | 66 | entries)) |
| 64 | (sqlite-mode--tablify '("Table Name" "Number of Rows") | 67 | (sqlite-mode--tablify '("Table Name" "Number of Rows") |
| 65 | (nreverse entries)) | 68 | (nreverse entries) |
| 69 | 'table) | ||
| 66 | (goto-char (point-min)))) | 70 | (goto-char (point-min)))) |
| 67 | 71 | ||
| 68 | (defun sqlite-mode--tablify (columns rows &optional prefix) | 72 | (defun sqlite-mode--tablify (columns rows type &optional prefix) |
| 69 | (let ((widths | 73 | (let ((widths |
| 70 | (mapcar | 74 | (mapcar |
| 71 | (lambda (i) | 75 | (lambda (i) |
| @@ -94,6 +98,7 @@ | |||
| 94 | (nth i row) | 98 | (nth i row) |
| 95 | (string-replace "\n" " " (or elem ""))))))) | 99 | (string-replace "\n" " " (or elem ""))))))) |
| 96 | (put-text-property start (point) 'sqlite--row row) | 100 | (put-text-property start (point) 'sqlite--row row) |
| 101 | (put-text-property start (point) 'sqlite--type type) | ||
| 97 | (insert "\n"))))) | 102 | (insert "\n"))))) |
| 98 | 103 | ||
| 99 | (defun sqlite-mode-list-columns () | 104 | (defun sqlite-mode-list-columns () |
| @@ -129,7 +134,8 @@ | |||
| 129 | (defun sqlite-mode-list-data () | 134 | (defun sqlite-mode-list-data () |
| 130 | "List the data from the table under poing." | 135 | "List the data from the table under poing." |
| 131 | (interactive nil sqlite-mode) | 136 | (interactive nil sqlite-mode) |
| 132 | (let ((row (get-text-property (point) 'sqlite--row))) | 137 | (let ((row (and (eq (get-text-property (point) 'sqlite--type) 'table) |
| 138 | (get-text-property (point) 'sqlite--row)))) | ||
| 133 | (unless row | 139 | (unless row |
| 134 | (user-error "No table under point")) | 140 | (user-error "No table under point")) |
| 135 | (let ((stmt (sqlite-select sqlite--db | 141 | (let ((stmt (sqlite-select sqlite--db |
| @@ -142,7 +148,8 @@ | |||
| 142 | (delete-region (point) (if (re-search-forward "^[^ ]" nil t) | 148 | (delete-region (point) (if (re-search-forward "^[^ ]" nil t) |
| 143 | (match-beginning 0) | 149 | (match-beginning 0) |
| 144 | (point-max))) | 150 | (point-max))) |
| 145 | (sqlite--mode--list-data stmt)))))) | 151 | (sqlite--mode--list-data (list stmt (car row))) |
| 152 | (push stmt sqlite-mode--statements)))))) | ||
| 146 | 153 | ||
| 147 | (defun sqlite-mode--more-data (stmt) | 154 | (defun sqlite-mode--more-data (stmt) |
| 148 | (let ((inhibit-read-only t)) | 155 | (let ((inhibit-read-only t)) |
| @@ -150,16 +157,48 @@ | |||
| 150 | (delete-region (point) (progn (forward-line 1) (point))) | 157 | (delete-region (point) (progn (forward-line 1) (point))) |
| 151 | (sqlite--mode--list-data stmt))) | 158 | (sqlite--mode--list-data stmt))) |
| 152 | 159 | ||
| 153 | (defun sqlite--mode--list-data (stmt) | 160 | (defun sqlite--mode--list-data (data) |
| 154 | (let ((rows | 161 | (let* ((stmt (car data)) |
| 155 | (cl-loop for i from 0 upto 1000 | 162 | (table (cadr data)) |
| 156 | for row = (sqlite-next stmt) | 163 | (rows |
| 157 | while row | 164 | (cl-loop for i from 0 upto 1000 |
| 158 | collect row))) | 165 | for row = (sqlite-next stmt) |
| 159 | (sqlite-mode--tablify (sqlite-columns stmt) rows " ") | 166 | while row |
| 167 | collect row))) | ||
| 168 | (sqlite-mode--tablify (sqlite-columns stmt) rows (cons 'row table) " ") | ||
| 160 | (when (sqlite-more-p stmt) | 169 | (when (sqlite-more-p stmt) |
| 161 | (insert (buttonize " More data...\n" | 170 | (insert (buttonize " More data...\n" #'sqlite-mode--more-data data))))) |
| 162 | #'sqlite-mode--more-data stmt))))) | 171 | |
| 172 | (defun sqlite-mode-delete () | ||
| 173 | "Delete the row under point." | ||
| 174 | (interactive nil sqlite-mode) | ||
| 175 | (let ((table (get-text-property (point) 'sqlite--type)) | ||
| 176 | (row (get-text-property (point) 'sqlite--row)) | ||
| 177 | (inhibit-read-only t)) | ||
| 178 | (when (or (not (consp table)) | ||
| 179 | (not (eq (car table) 'row))) | ||
| 180 | (user-error "No row under point")) | ||
| 181 | ;; We have to remove all open statements before we can delete something. | ||
| 182 | (dolist (stmt sqlite-mode--statements) | ||
| 183 | (ignore-errors (sqlite-finalize stmt))) | ||
| 184 | (setq sqlite-mode--statements nil) | ||
| 185 | (save-excursion | ||
| 186 | (goto-char (point-min)) | ||
| 187 | (let (match) | ||
| 188 | (while (setq match (text-property-search-forward 'button-data)) | ||
| 189 | (delete-region (prop-match-beginning match) | ||
| 190 | (prop-match-end match))))) | ||
| 191 | (sqlite-execute | ||
| 192 | sqlite--db | ||
| 193 | (format "delete from %s where %s" | ||
| 194 | (cdr table) | ||
| 195 | (string-join | ||
| 196 | (mapcar (lambda (column) | ||
| 197 | (format "%s = ?" (car (split-string column " ")))) | ||
| 198 | (sqlite-mode--column-names (cdr table))) | ||
| 199 | " and ")) | ||
| 200 | row) | ||
| 201 | (delete-region (line-beginning-position) (progn (forward-line 1) (point))))) | ||
| 163 | 202 | ||
| 164 | (provide 'sqlite-mode) | 203 | (provide 'sqlite-mode) |
| 165 | 204 | ||