+(defun elpher-make-bookmark (type display-string address)
+ (list type display-string address))
+
+(defun elpher-bookmark-type (bookmark)
+ (elt bookmark 0))
+
+(defun elpher-bookmark-display-string (bookmark)
+ (elt bookmark 1))
+
+(defun elpher-bookmark-address (bookmark)
+ (elt bookmark 2))
+
+(defun elpher-save-bookmarks (bookmarks)
+ (with-temp-file (locate-user-emacs-file "elpher-bookmarks")
+ (erase-buffer)
+ (pp bookmarks (current-buffer))))
+
+(defun elpher-load-bookmarks ()
+ (with-temp-buffer
+ (insert-file-contents (locate-user-emacs-file "elpher-bookmarks"))
+ (goto-char (point-min))
+ (read (current-buffer))))
+
+(defun elpher-add-bookmark (bookmark)
+ (let ((bookmarks (elpher-load-bookmarks)))
+ (add-to-list 'bookmarks bookmark)
+ (elpher-save-bookmarks bookmarks)))
+
+(defun elpher-remove-bookmark (bookmark)
+ (elpher-save-bookmarks
+ (seq-filter (lambda (this-bookmark)
+ (not (equal bookmark this-bookmark)))
+ (elpher-load-bookmarks))))
+
+(defun elpher-display-bookmarks ()
+ (interactive)
+ (elpher-with-clean-buffer
+ (insert
+ "---- Bookmark list ----\n\n"
+ "Use 'u' to return to the previous page.\n\n")
+ (dolist (bookmark (elpher-load-bookmarks))
+ (let ((type (elpher-bookmark-type bookmark))
+ (display-string (elpher-bookmark-display-string bookmark))
+ (address (elpher-bookmark-address bookmark)))
+ (elpher-insert-index-record-helper type display-string
+ (elpher-address-selector address)
+ (elpher-address-host address)
+ (elpher-address-port address))))
+ (goto-char (point-min))
+ (elpher-next-link)))
+
+(defun elpher-bookmark-link ()
+ "Bookmark the link at point."
+ (interactive)
+ (let ((button (button-at (point))))
+ (if button
+ (let ((node (button-get button 'elpher-node))
+ (type (button-get button 'elpher-node-type)))
+ (if node
+ (elpher-add-bookmark
+ (elpher-make-bookmark type
+ (button-label button)
+ (elpher-node-address node)))
+ (error "Can only bookmark gopher links, not general URLs.")))
+ (error "No link selected."))))
+
+(defun elpher-unbookmark-link ()
+ "Remove bookmark for the link at point."
+ (interactive)
+ (let ((button (button-at (point))))
+ (if button
+ (let ((node (button-get button 'elpher-node))
+ (type (button-get button 'elpher-node-type)))
+ (if node
+ (elpher-remove-bookmark
+ (elpher-make-bookmark type
+ (button-label button)
+ (elpher-node-address node)))
+ (error "Can only bookmark gopher links, not general URLs.")))
+ (error "No link selected."))))
+
+;;; Interactive navigation procedures