From: Alex Schroeder Date: Mon, 20 Jul 2020 09:27:51 +0000 (+0200) Subject: Implement three commands for history items X-Git-Url: https://thelambdalab.xyz/gitweb/index.cgi?p=elpher.git;a=commitdiff_plain;h=1d6fe009561db2dbc78b8446f025afd3e0f2e911 Implement three commands for history items In the Elpher menu, history are shown when invoking it using a prefix. The history items aren't being shown in a buffer, so switching to those buffers is not possible. Three buffer menu commands have been implemented (RET, o, C-o) such that they work with history items. --- diff --git a/elpher.el b/elpher.el index 6513ee7..87fe007 100644 --- a/elpher.el +++ b/elpher.el @@ -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: \\ \\[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,8 +2192,9 @@ 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" 40 t) @@ -2210,38 +2251,56 @@ 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'." - (let ((separator (list (current-buffer) - (vector - "-" - (make-string 25 ?-) - (make-string 25 ?-))))) + ;; 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) - ;; every section starts with the current page and ends with - ;; the separator - (mapcar (lambda (page) - (if page - (list (current-buffer) + ;; 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-address-to-url - (elpher-page-address page)) "none") - (or (elpher-page-display-string page) "?"))) + (elpher-page-address (cdr pair))) "none") + (or (elpher-page-display-string (cdr pair)) "?"))) separator)) - (cons elpher-current-page elpher-history))) + (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 + ;; No history means a list of one item. Add a separator. (list (list (current-buffer) (vector "E" (or (elpher-address-to-url (elpher-page-address elpher-current-page))) (or (elpher-page-display-string elpher-current-page) - (buffer-name)))))) + (buffer-name)))) + separator)) ((eq major-mode 'eww-mode) - (nconc (mapcar (lambda (data) - (list (current-buffer) - (vector "W" - (or (plist-get data :url) "none") - (or (plist-get data :title) "none")))) - (cons eww-data eww-history)) + ;; 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 :url) "none") + (or (plist-get eww-data :title) "none"))) + (mapcar (lambda (data) + (list + (list (current-buffer) 'eww-restore-history data) + (vector "W" + (or (plist-get data :url) "none") + (or (plist-get data :title) "none")))) + eww-history)) (list separator)))))) ;;; Main start procedure