+;; URL retrieval
+
+(defun elpher-get-url-node ()
+ "Getter which attempts to open the URL specified by the current node."
+ (let* ((address (elpher-node-address elpher-current-node))
+ (selector (elpher-address-selector address)))
+ (elpher-visit-parent-node) ; Do first in case of non-local exits.
+ (let ((url (elt (split-string selector "URL:") 1)))
+ (if elpher-open-urls-with-eww
+ (browse-web url)
+ (browse-url url)))))
+
+;; Telnet node connection
+
+(defun elpher-get-telnet-node ()
+ "Getter which opens a telnet connection to the server specified by the current node."
+ (let* ((address (elpher-node-address elpher-current-node))
+ (host (elpher-address-host address))
+ (port (elpher-address-port address)))
+ (elpher-visit-parent-node)
+ (telnet host port)))
+
+
+;;; Bookmarks
+;;
+
+(defun elpher-make-bookmark (display-string address)
+ "Make an elpher bookmark.
+DISPLAY-STRING determines how the bookmark will appear in the
+bookmark list, while ADDRESS is the address of the entry."
+ (list display-string address))
+
+(defun elpher-bookmark-display-string (bookmark)
+ "Get the display string of BOOKMARK."
+ (elt bookmark 0))
+
+(defun elpher-bookmark-address (bookmark)
+ "Get the address for BOOKMARK."
+ (elt bookmark 1))
+
+(defun elpher-save-bookmarks (bookmarks)
+ "Record the bookmark list BOOKMARKS to the user's bookmark file.
+Beware that this completely replaces the existing contents of the file."
+ (with-temp-file (locate-user-emacs-file "elpher-bookmarks")
+ (erase-buffer)
+ (pp bookmarks (current-buffer))))
+
+(defun elpher-load-bookmarks ()
+ "Get the list of bookmarks from the users's bookmark file."
+ (with-temp-buffer
+ (ignore-errors
+ (insert-file-contents (locate-user-emacs-file "elpher-bookmarks"))
+ (goto-char (point-min))
+ (read (current-buffer)))))
+
+(defun elpher-add-node-bookmark (node)
+ "Add bookmark to NODE to the saved list of bookmarks."
+ (let ((bookmark (elpher-make-bookmark (elpher-node-display-string node)
+ (elpher-node-address node)))
+ (bookmarks (elpher-load-bookmarks)))
+ (add-to-list 'bookmarks bookmark)
+ (elpher-save-bookmarks bookmarks)))
+
+(defun elpher-remove-node-bookmark (node)
+ "Remove bookmark to NODE from the saved list of bookmarks."
+ (let ((bookmark (elpher-make-bookmark (elpher-node-display-string node)
+ (elpher-node-address node))))
+ (elpher-save-bookmarks
+ (seq-filter (lambda (this-bookmark)
+ (not (equal bookmark this-bookmark)))
+ (elpher-load-bookmarks)))))
+
+(defun elpher-display-bookmarks ()
+ "Display saved bookmark list."
+ (interactive)
+ (elpher-with-clean-buffer
+ (insert "Use 'r' to return to the previous page.\n\n"
+ "---- Bookmark list ----\n\n")
+ (let ((bookmarks (elpher-load-bookmarks)))
+ (if bookmarks
+ (dolist (bookmark bookmarks)
+ (let ((display-string (elpher-bookmark-display-string bookmark))
+ (address (elpher-bookmark-address bookmark)))
+ (elpher-insert-index-record display-string
+ (elpher-address-type address)
+ (elpher-address-selector address)
+ (elpher-address-host address)
+ (elpher-address-port address))))
+ (insert "No bookmarks found.\n")))
+ (insert "\n-----------------------")
+ (goto-char (point-min))
+ (elpher-next-link)))
+
+(defun elpher-bookmark-current ()
+ "Bookmark the current node."
+ (interactive)
+ (elpher-add-node-bookmark elpher-current-node))
+
+(defun elpher-bookmark-link ()
+ "Bookmark the link at point."
+ (interactive)
+ (let ((button (button-at (point))))
+ (if button
+ (elpher-add-node-bookmark (button-get button 'elpher-node))
+ (error "No link selected"))))
+
+(defun elpher-unbookmark-current ()
+ "Remove bookmark for the current node."
+ (interactive)
+ (elpher-remove-node-bookmark elpher-current-node))