diff --git a/etc/init.lisp b/etc/init.lisp index 0e7cb34..b6a5f83 100644 --- a/etc/init.lisp +++ b/etc/init.lisp @@ -363,6 +363,8 @@ (define-key "C-b s" #'display-bookmark *gemini-message-keymap*) +(define-key "C-b d" #'delete-gemini-bookmark *gemini-message-keymap*) + (define-key "U" #'gemini-view-source *gemini-message-keymap*) (define-key "d" #'gemini-open-streams-window *gemini-message-keymap*) diff --git a/src/complete.lisp b/src/complete.lisp index 4f467f4..9ebed3b 100644 --- a/src/complete.lisp +++ b/src/complete.lisp @@ -264,3 +264,9 @@ list af all possible candidtae for completion." (with-simple-complete bookmark-section-complete (lambda () (remove-if #'null (db:bookmark-all-sections)))) + +(defun bookmark-description-complete-clsr (type) + (lambda (hint) + (when-let ((matched (remove-if-not (lambda (a) (cl-ppcre:scan hint a)) + (db:bookmark-description-for-complete type)))) + (values matched (reduce-to-common-prefix matched))))) diff --git a/src/db.lisp b/src/db.lisp index 233c17d..3bb4399 100644 --- a/src/db.lisp +++ b/src/db.lisp @@ -1832,6 +1832,8 @@ row." (gen-access-message-row value :value) +(gen-access-message-row section :section) + (defun row-votes-count (row) (and row (db-getf row :votes-count :default 0))) @@ -3111,15 +3113,23 @@ days in the past" (:type :value :section :description :created-at) (type value section description now))))) -(defun bookmark-delete (type value) - (query (make-delete +table-bookmark+ - (:and (:= :type type) - (:= :value value))))) - (defun bookmark-all-sections () (let ((rows (query (select :section (from +table-bookmark+))))) (mapcar #'second rows))) +(defun bookmark-complete->id (description) + (ignore-errors (parse-integer description :junk-allowed t))) + +(defun bookmark-description-for-complete (type) + (let ((rows (query (select :* (from +table-bookmark+) (where (:= :type type)))))) + (mapcar (lambda (a) (strcat (to-s (row-id a)) + ": -" + (row-section a) + " - " + (row-description a) + (row-value a))) + rows))) + (defun bookmark-all-by-section (section) (if (null section) (query (select :* (from +table-bookmark+) (where (:is-null :section)))) @@ -3130,3 +3140,6 @@ days in the past" (loop for section in sections collect (cons section (bookmark-all-by-section section))))) + +(defun bookmark-delete (id) + (delete-by-id +table-bookmark+ id)) diff --git a/src/package.lisp b/src/package.lisp index 3c2e453..76c6a0b 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -1017,8 +1017,11 @@ :purge-seen-gemlog-entries :bookmark-add :bookmark-delete + :bookmark-complete->id + :bookmark-description-for-complete :bookmark-all-sections - :bookmark-all-grouped-by-section)) + :bookmark-all-grouped-by-section + :bookmark-delete)) (defpackage :date-formatter (:use @@ -1325,7 +1328,8 @@ :make-complete-gemini-iri-fn :complete-chat-message :complete-always-empty - :bookmark-section-complete)) + :bookmark-section-complete + :bookmark-description-complete-clsr)) (defpackage :program-events (:use @@ -2609,7 +2613,8 @@ :ask-input-on-tofu-error :import-gemini-certificate :bookmark-gemini-page - :display-bookmark)) + :display-bookmark + :delete-gemini-bookmark)) (defpackage :scheduled-events (:use diff --git a/src/ui-goodies.lisp b/src/ui-goodies.lisp index 0ec8073..4220cca 100644 --- a/src/ui-goodies.lisp +++ b/src/ui-goodies.lisp @@ -2086,10 +2086,13 @@ gemini page the program is rendering." (source (gemini-viewer:gemini-metadata-source-file metadata)) (description (gemini-parser:gemini-first-h1 source))) (labels ((on-description-completed (new-description) - (setf description new-description) - (ui:ask-string-input #'on-section-completed - :prompt (format nil (_ "Insert bookmark section: ")) - :complete-fn #'complete:bookmark-section-complete)) + (if (text-utils:string-empty-p new-description) + (error-message (_ "Empty description")) + (progn + (setf description new-description) + (ui:ask-string-input #'on-section-completed + :prompt (format nil (_ "Insert bookmark section: ")) + :complete-fn #'complete:bookmark-section-complete)))) (on-section-completed (section) (db-utils:with-ready-database (:connect nil) (db:bookmark-add db:+bookmark-gemini-type-entry+ @@ -2128,3 +2131,15 @@ gemini page the program is rendering." :window *message-window* :payload bookmark-page))) (push-event event))) + +(defun delete-gemini-bookmark () + (flet ((on-description-completed (selected) + (if (text-utils:string-empty-p selected) + (error-message (_ "No entry selected")) + (when-let ((id (db:bookmark-complete->id selected))) + (db-utils:with-ready-database (:connect nil) + (db:bookmark-delete id)))))) + (ui:ask-string-input #'on-description-completed + :prompt (format nil (_ "Delete bookmark: ")) + :complete-fn + (complete:bookmark-description-complete-clsr db:+bookmark-gemini-type-entry+))))