branch: externals/frog-menu commit 37ad44b923242aee57b8db93834d5e421c9dc03b Author: Clemens Radermacher <clem...@posteo.net> Commit: Clemens Radermacher <clem...@posteo.net>
Refactor and add new menu type for non graphical displays --- frog-menu.el | 102 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 19 deletions(-) diff --git a/frog-menu.el b/frog-menu.el index c117fc1..efa56c5 100644 --- a/frog-menu.el +++ b/frog-menu.el @@ -70,21 +70,30 @@ :group 'convenience :prefix "frog-menu-") -(defcustom frog-menu-type 'avy-posframe - "The type of menu to be used. +(defvar frog-menu-type nil + "Type of menu to use. -When defining a new menu type, handlers need to be added for +By default types `avy-posframe' and `avy-side-window' are possible. -`frog-menu-init-handler-alist' + When using a new menu type, handlers need to be added for -`frog-menu-display-handler-alist' + `frog-menu-init-handler-alist' -`frog-menu-query-handler-alist' + `frog-menu-display-handler-alist' -and optionally to + `frog-menu-display-option-alist' -`frog-menu-cleanup-handler-alist'." - :type 'symbol) + `frog-menu-query-handler-alist' + + and optionally to + + `frog-menu-cleanup-handler-alist'.") + +(defcustom frog-menu-type-function #'frog-menu-type + "Function which should return the `frog-menu-type' to be used. + +See `frog-menu-type'" + :type 'function) (defcustom frog-menu-after-init-hook '() "Frog menu init hook. @@ -94,7 +103,8 @@ menu buffer is set current when this hook runs." :type '(repeat function)) (defcustom frog-menu-init-handler-alist - '((avy-posframe . frog-menu-init-avy-posframe)) + '((avy-posframe . frog-menu-init-display-buffer) + (avy-side-window . frog-menu-init-display-buffer)) "Maps `frog-menu-type' to an init handler. The init handler is called with the prompt, strings formatted by @@ -106,7 +116,8 @@ hook `frog-menu-after-init-hook' gets executed." :value-type function)) (defcustom frog-menu-display-handler-alist - '((avy-posframe . frog-menu-display-posframe)) + '((avy-posframe . frog-menu-display-posframe) + (avy-side-window . frog-menu-display-side-window)) "Maps `frog-menu-type' to a display handler. The display handler receives the buffer to display as an argument @@ -114,8 +125,18 @@ and should return the window of the displayed buffer." :type '(alist :key-type symbol :value-type function)) +(defcustom frog-menu-display-option-alist + '((avy-posframe . posframe-poshandler-point-bottom-left-corner) + (avy-side-window . (display-buffer-in-side-window (side . bottom)))) + "Maps `frog-menu-type' to a display options. + +The display option is passed to the display handler as second argument." + :type '(alist :key-type symbol + :value-type function)) + (defcustom frog-menu-query-handler-alist - '((avy-posframe . frog-menu-avy-posframe)) + '((avy-posframe . frog-menu-query-with-avy) + (avy-side-window . frog-menu-query-with-avy)) "Maps `frog-menu-type' to a query handler. The query handler receives four arguments. @@ -130,7 +151,8 @@ value. If the user exited the query return nil." :value-type function)) (defcustom frog-menu-cleanup-handler-alist - '((avy-posframe . frog-menu-posframe-hide)) + '((avy-posframe . frog-menu-posframe-hide) + (avy-side-window . frog-menu-side-window-hide)) "Maps `frog-menu-type' to a cleanup handler. The cleanup handler receives the displayed buffer and the window @@ -198,6 +220,14 @@ be drawn by single characters." (defvar frog-menu--buffer " *frog-menu-menu*" "Buffer used for the frog menu.") +(defun frog-menu-type () + "Return `frog-menu-type' to use." + (cond ((display-graphic-p) + 'avy-posframe) + (t + 'avy-side-window))) + + ;; * Init (defun frog-menu--init-buffer (buffer prompt strings actions) @@ -224,7 +254,12 @@ PROMPT, STRINGS and ACTIONS are the args from `frog-menu-read'." "Hide the posframe buffer BUF." (posframe-hide buf)) -(defun frog-menu-init-avy-posframe (prompt formatted-strings formatted-actions) +(defun frog-menu-side-window-hide (_buf window) + "Hide the BUF side window WINDOW." + (delete-window window)) + + +(defun frog-menu-init-display-buffer (prompt formatted-strings formatted-actions) "Init handler for avy-posframe. PROMPT, FORMATTED-STRINGS and FORMATTED-ACTIONS are the args from `frog-menu-read'. @@ -327,12 +362,13 @@ Returns the buffer containing the formatted grid." ;; * Display -(defun frog-menu-display-posframe (buf) +(defun frog-menu-display-posframe (buf &optional display-option) "Display posframe showing buffer BUF. Returns window of displayed buffer." (posframe-show buf - :poshandler #'posframe-poshandler-point-bottom-left-corner + :poshandler(or display-option + #'posframe-poshandler-point-bottom-left-corner) :internal-border-width 1) (set-face-attribute 'internal-border (buffer-local-value 'posframe--frame buf) @@ -340,6 +376,31 @@ Returns window of displayed buffer." (frame-selected-window (buffer-local-value 'posframe--frame buf))) +(defun frog-menu-display-side-window (buf &optional display-option) + "Display posframe showing buffer BUF. + +Returns window of displayed buffer." + (let ((window (display-buffer + buf + (or display-option + '(display-buffer-in-side-window (side . bottom)))))) + (prog1 window + (with-selected-window window + (with-current-buffer buf + ;; see transient/lv + (set-window-hscroll window 0) + (set-window-dedicated-p window t) + (set-window-parameter window 'no-other-window t) + (setq window-size-fixed t) + (setq cursor-type nil) + (setq display-line-numbers nil) + (setq show-trailing-whitespace nil) + (setq mode-line-format nil) + (let ((window-resize-pixelwise t) + (window-size-fixed nil)) + (fit-window-to-buffer nil nil 1)) + (goto-char (point-min))))))) + (defun frog-menu--get-avy-candidates (&optional b w start end) "Return candidates to be passed to `avy--process'. @@ -412,7 +473,7 @@ action result. ACTIONS is the argument of `frog-menu-read'." (define-key frog-menu--avy-action-map (kbd (car action)) (lambda () (interactive) (car (cddr action)))))) -(defun frog-menu-avy-posframe (buffer window actions) +(defun frog-menu-query-with-avy (buffer window actions) "Query handler for avy-posframe. CANDIDATES are the candidates for `avy--process'. ACTIONS is the @@ -473,11 +534,14 @@ DESCRIPTION is a string to be displayed along with KEY to describe the action. RETURN will be the returned value if KEY is pressed." - (let* ((buf (frog-menu--init-buffer (get-buffer-create frog-menu--buffer) + (let* ((frog-menu-type (funcall frog-menu-type-function)) + (buf (frog-menu--init-buffer (get-buffer-create frog-menu--buffer) prompt strings actions)) (dhandler (cdr (assq frog-menu-type frog-menu-display-handler-alist))) - (window (funcall dhandler buf)) + (doption (cdr (assq frog-menu-type + frog-menu-display-option-alist))) + (window (funcall dhandler buf doption)) (qhandler (cdr (assq frog-menu-type frog-menu-query-handler-alist))) (cuhandler (cdr (assq frog-menu-type