Switch URL and Name position in the menu
[elpher.git] / elpher.el
index 1e46dd9..29687f1 100644 (file)
--- a/elpher.el
+++ b/elpher.el
@@ -2013,7 +2013,7 @@ functions which initialize the gopher client, namely
 (defun elpher-menu (&optional arg)
   "Show a list of all your `elpher' buffers.
 With an optional argument, add all the history items, too."
-  (interactive)
+  (interactive "P")
   (switch-to-buffer (get-buffer-create "*Elpher Menu*"))
   (elpher-menu-mode)
   (elpher-menu-refresh arg)
@@ -2028,9 +2028,9 @@ With an optional argument, add all the history items, too."
     (define-key map "1" 'Buffer-menu-1-window)
     (define-key map "f" 'Buffer-menu-this-window)
     (define-key map "e" 'Buffer-menu-this-window)
-    (define-key map "\C-m" 'Buffer-menu-this-window)
-    (define-key map "o" 'Buffer-menu-other-window)
-    (define-key map "\C-o" 'Buffer-menu-switch-other-window)
+    (define-key map "\C-m" 'elpher-menu-this-window)
+    (define-key map "o" 'elpher-menu-other-window)
+    (define-key map "\C-o" 'elpher-menu-switch-other-window)
     (define-key map "d" 'Buffer-menu-delete)
     (define-key map "k" 'Buffer-menu-delete)
     (define-key map "\C-k" 'Buffer-menu-delete)
@@ -2064,10 +2064,10 @@ With an optional argument, add all the history items, too."
       '(menu-item "Select Current" Buffer-menu-1-window
                 :help "Select this line's buffer, alone, in full frame"))
     (bindings--define-key menu-map [ow]
-      '(menu-item "Select in Other Window" Buffer-menu-other-window
+      '(menu-item "Select in Other Window" elpher-menu-other-window
                 :help "Select this line's buffer in other window, leaving buffer menu visible"))
     (bindings--define-key menu-map [tw]
-      '(menu-item "Select in Current Window" Buffer-menu-this-window
+      '(menu-item "Select in Current Window" elpher-menu-this-window
                 :help "Select this line's buffer in this window"))
     (bindings--define-key menu-map [s2] menu-bar-separator)
     (bindings--define-key menu-map [is]
@@ -2104,17 +2104,20 @@ With an optional argument, add all the history items, too."
 
 (define-derived-mode elpher-menu-mode tabulated-list-mode "Elpher Menu"
   "Major mode for Elpher Menu buffers.
-The Elpher Menu is invoked by the command \\[elpher-menu].
+The Elpher Menu is invoked by the command \\[elpher-menu]. When
+invoked with a prefix, the command also shows history items.
+Since history items are no longer showing in a buffer, many of
+the commands shown below will not work on them.
 
 In Elpher Menu mode, the following commands are defined:
 \\<elpher-menu-mode-map>
 \\[quit-window]    Remove the Buffer Menu from the display.
-\\[tabulated-list-sort]    sorts buffers according to the current
+\\[tabulated-list-sort]    Sorts buffers according to the current
      column. With a numerical argument, sort by that column.
-\\[Buffer-menu-this-window]  Select current line's buffer in place of the buffer menu.
-\\[Buffer-menu-other-window]    Select that buffer in another window,
+\\[elpher-menu-this-window]  Select current line's buffer in place of the buffer menu.
+\\[elpher-menu-other-window]    Select that buffer in another window,
      so the Buffer Menu remains visible in its window.
-\\[Buffer-menu-switch-other-window]  Make another window display that buffer.
+\\[elpher-menu-switch-other-window]  Make another window display that buffer.
 \\[Buffer-menu-mark]    Mark current line's buffer to be displayed.
 \\[Buffer-menu-select]    Select current line's buffer.
      Also show buffers marked with m, in other windows.
@@ -2134,6 +2137,43 @@ In Elpher Menu mode, the following commands are defined:
 \\[Buffer-menu-bury]    Bury the buffer listed on this line."
   (add-hook 'tabulated-list-revert-hook 'elpher-menu-refresh nil t))
 
+(defun elpher-menu-this-window ()
+  "Select this line’s buffer in this window.
+Switch to the buffer, if possible. If there is no buffer, chances
+are that we're looking at a history item. Let's visit the item
+instead of complaining that their buffers have been killed."
+  (interactive)
+  (elpher-menu-handle-buffer-or-data 'switch-to-buffer))
+
+(defun elpher-menu-other-window ()
+  "Select this line’s buffer in other window, leaving buffer menu visible."
+  (interactive)
+  (elpher-menu-handle-buffer-or-data 'switch-to-buffer-other-window))
+
+(defun elpher-menu-switch-other-window ()
+  "Make the other window select this line's buffer.
+The current window remains selected."
+  (interactive)
+  (elpher-menu-handle-buffer-or-data
+   (lambda (buf) (display-buffer buf t))))
+
+(defun elpher-menu-handle-buffer-or-data (buffer-func)
+  "Handle an item in `elpher-menu-mode'.
+Determine the entry ID of the Tabulated List entry at point. If
+ID is a buffer, invoke BUFFER-FUNC on it. Otherwise, ID is a
+list (BUFFER FUNC ARGS...). Switch to BUFFER using BUFFER-FUNC
+and apply FUNC to ARGS."
+  (let ((data (tabulated-list-get-id)))
+    (cond ((bufferp data)
+          (funcall buffer-func data))
+         ((and (listp data)
+               (buffer-live-p (nth 0 data))
+               (fboundp (nth 1 data)))
+          (funcall buffer-func (nth 0 data))
+          (apply (nth 1 data) (nthcdr 2 data)))
+         (t
+          (error "There's no entry on this line of the menu")))))
+
 (defvar elpher-title nil)
 
 (defun elpher-find-title ()
@@ -2152,76 +2192,116 @@ In Elpher Menu mode, the following commands are defined:
 
 (defun elpher-menu-refresh (&optional arg)
   "Refresh the list of buffers.
-With an optional argument, add all the history items, too."
-    ;; Set up `tabulated-list-format'.
+With an optional argument, add all the history items, too. Note
+that there are no buffers for history items so many of the buffer
+menu commands won't work on them."
     (setq tabulated-list-format
          (vector '("T" 1 t)
-                 '("URL" 35 t)
-                 '("Name" 35 t))
+                 '("Name" 30 t)
+                 '("URL" 40 t))
          tabulated-list-sort-key nil)
     ;; Collect info for each buffer we're interested in.
     (let (entries)
       (dolist (buf (buffer-list))
        (with-current-buffer buf
-         (when (memq major-mode '(elpher-mode eww-mode))
-           (setq entries
-                 (nconc (if arg
-                            (elpher-menu-refresh-current)
-                          (elpher-menu-refresh-history))
-                        entries)))))
+         (when (memq major-mode '(elpher-mode eww-mode gemini-mode))
+           (if arg
+               (setq entries (nconc (elpher-menu-refresh-history) entries))
+             (push (elpher-menu-refresh-current) entries)))))
       (setq tabulated-list-entries (nreverse entries)))
     (tabulated-list-init-header))
 
 (defun elpher-menu-refresh-current ()
-  "Return current entries for `elpher-menu-refresh'.
-If we're only interested in the current entries, then this
-function can only return a list of a single item per buffer."
-  (list buf
-       (vector
-        (cond ((eq major-mode 'elpher-mode) "E")
-              ((eq major-mode 'eww-mode) "W"))
-        (cond ((eq major-mode 'elpher-mode)
-               (or (elpher-address-to-url
-                    (elpher-page-address elpher-current-page))
-                   "none"))
-              ((eq major-mode 'eww-mode)
-               (eww-current-url)))
-        (cond ((eq major-mode 'elpher-mode)
-               (or (elpher-find-title)
-                   (elpher-page-display-string elpher-current-page)))
-              ((eq major-mode 'eww-mode)
-               (plist-get eww-data :title))))))
+  "Returns an item for `elpher-menu-refresh'
+based on the current buffer.
+
+An item is a list (BUFFER VECTOR) where BUFFER is the buffer this
+item refers to and VECTOR is what to display in the tabulated
+list established by `elpher-menu-refresh'. See
+`tabulated-list-format'."
+  (list (current-buffer)
+       (cond ((eq major-mode 'elpher-mode)
+              (vector "G"
+                      (or (elpher-find-title)
+                          (elpher-page-display-string elpher-current-page)
+                          (buffer-name))
+                      (or (elpher-address-to-url
+                           (elpher-page-address elpher-current-page))
+                          "none")))
+             ((eq major-mode 'gemini-mode)
+              (vector "E"
+                      (or (elpher-page-display-string elpher-current-page)
+                          (buffer-name))
+                      (or (elpher-address-to-url
+                           (elpher-page-address elpher-current-page))
+                          "none")))
+             ((eq major-mode 'eww-mode)
+              (vector "W"
+                      (or (plist-get eww-data :title)
+                          (buffer-name))
+                      (or (eww-current-url)
+                          "none"))))))
 
 (defun elpher-menu-refresh-history ()
   "Return current entries for `elpher-menu-refresh'.
-If we're only interested in the current entries, then this
-function can only return a list of a single item per buffer."
-  (let ((separator (list (current-buffer)
-                        (vector
-                         "E"
-                         (make-string 25 ?-)
-                         (make-string 25 ?-)))))
-    (if (eq major-mode 'elpher-mode)
-       ;; every section starts with the current page and ends with
-       ;; the separator
-       (mapcar (lambda (page)
-                 (if page
-                     (list (current-buffer)
-                           (vector
-                            "E"
-                            (or (elpher-address-to-url
-                                 (elpher-page-address page)) "none")
-                            (or (elpher-page-display-string page) "?")))
-                   separator))
-               (cons elpher-current-page elpher-history))
-      (nconc (mapcar (lambda (data)
-                      (list (current-buffer)
-                            (vector
-                             "W"
-                             (plist-get data :url)
-                             (plist-get data :title))))
-                    (cons eww-data eww-history))
-            (list separator)))))
+This returns a list of items for the current buffer, based on the
+buffer's history.
+
+An item is a list (BUFFER VECTOR) where BUFFER is the buffer this
+item refers to and VECTOR is what to display in the tabulated
+list established by `elpher-menu-refresh'. See
+`tabulated-list-format'."
+  ;; Every section starts with the current page, followed by some
+  ;; history items, and ends with the separator.
+  (let ((separator (list nil
+                        (vector "-"
+                                (make-string 25 ?-)
+                                (make-string 25 ?-)))))
+    (cond ((eq major-mode 'elpher-mode)
+          ;; A pair is (BUFFER-OR-DATA . PAGE) where BUFFER-OR-DTA is
+          ;; the current buffer, if possible, or list (BUFFER FUNC
+          ;; &rest ARGS) telling us which BUFFER to switch to, and
+          ;; what function to call. The last item of elpher-history
+          ;; has a nil page, so when that shows up, use the separator
+          (mapcar (lambda (pair)
+                    (if (cdr pair)
+                        (list (car pair)
+                              (vector "G"
+                                      (or (elpher-page-display-string (cdr pair)) "?")
+                                      (or (elpher-address-to-url
+                                           (elpher-page-address (cdr pair))) "none")))
+                      separator))
+                  (cons (cons (current-buffer) elpher-current-page)
+                        (mapcar (lambda (page)
+                                  (cons (list (current-buffer) 'elpher-visit-page page)
+                                        page))
+                                elpher-history))))
+         ((eq major-mode 'gemini-mode)
+          ;; No history means a list of one item. Add a separator.
+          (list (list (current-buffer)
+                      (vector "E"
+                              (or (elpher-page-display-string elpher-current-page)
+                                  (buffer-name))
+                              (or (elpher-address-to-url
+                                   (elpher-page-address elpher-current-page)))))
+                separator))
+          ((eq major-mode 'eww-mode)
+          ;; A pair is (BUFFER-OR-DATA . PAGE) where BUFFER-OR-DTA is
+          ;; the current buffer, if possible, or list (BUFFER FUNC
+          ;; &rest ARGS) telling us which BUFFER to switch to, and
+          ;; what function to call. Add the separator at the end.
+           (nconc (cons (list (current-buffer)
+                              (vector "W"
+                                      (or (plist-get eww-data :title) "none")
+                                      (or (plist-get eww-data :url) "none")))
+                        (mapcar (lambda (data)
+                                  (list
+                                   (list (current-buffer) 'eww-restore-history data)
+                                   (vector "W"
+                                           (or (plist-get data :title) "none")
+                                           (or (plist-get data :url) "none"))))
+                                eww-history))
+                  (list separator))))))
 
 ;;; Main start procedure
 ;;