Mercurial > core / emacs/lib/corfu-terminal.el
changeset 633: |
88a3f078c185 |
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Sun, 01 Sep 2024 21:00:12 -0400 |
permissions: |
-rw-r--r-- |
description: |
add corfu-terminal |
1 ;;; corfu-terminal.el --- Corfu popup on terminal -*- lexical-binding: t; -*- 3 ;; Copyright (C) 2022 Akib Azmain Turja. 5 ;; Author: Akib Azmain Turja <akib@disroot.org> 8 ;; Package-Requires: ((emacs "26.1") (corfu "0.36") (popon "0.13")) 9 ;; Keywords: convenience 10 ;; Homepage: https://codeberg.org/akib/emacs-corfu-terminal 12 ;; This file is not part of GNU Emacs. 14 ;; This file is free software; you can redistribute it and/or modify 15 ;; it under the terms of the GNU General Public License as published by 16 ;; the Free Software Foundation; either version 3, or (at your option) 19 ;; This program is distributed in the hope that it will be useful, 20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 ;; GNU General Public License for more details. 24 ;; For a full copy of the GNU General Public License 25 ;; see <https://www.gnu.org/licenses/>. 29 ;; Corfu uses child frames to display candidates. This makes Corfu 30 ;; unusable on terminal. This package replaces that with popup/popon, 31 ;; which works everywhere. Use M-x corfu-terminal-mode to enable. 32 ;; You'll probably want to enable it only on terminal. In that case, 33 ;; put the following in your init file: 35 ;; (unless (display-graphic-p) 36 ;; (corfu-terminal-mode +1)) 45 (defgroup corfu-terminal nil 46 "Corfu popup on terminal." 48 :link '(url-link "https://codeberg.org/akib/emacs-corfu-terminal") 49 :prefix "corfu-terminal-") 51 (defcustom corfu-terminal-enable-on-minibuffer t 52 "Non-nil means enable corfu-terminal on minibuffer." 55 (defcustom corfu-terminal-resize-minibuffer t 56 "Non-nil means resize minibuffer to show popup." 59 (defcustom corfu-terminal-position-right-margin 0 60 "Number of columns of margin at the right of window. 62 Always keep the popup this many columns away from the right edge of 65 Note: If the popup breaks or crosses the right edge of window, you may 66 set this variable to warkaround it. But remember, that's a *bug*, so 67 if that ever happens to you please report the issue at 68 https://codeberg.org/akib/emacs-corfu-terminal/issues." 71 (defcustom corfu-terminal-disable-on-gui t 72 "Don't use popon UI on GUI." 73 :type '(choice (const :tag "Yes" t) 74 (const :tag "No" nil))) 76 (defvar corfu-terminal--popon nil 79 (defvar corfu-terminal--last-position nil 80 "Position of last popon, and some data to make sure that's valid.") 82 (cl-defmethod corfu--popup-support-p (&context (corfu-terminal-mode 84 "Return whether corfu-terminal supports showing popon now." 85 (or (not (minibufferp)) 86 corfu-terminal-enable-on-minibuffer 87 (and corfu-terminal-disable-on-gui 88 (display-graphic-p)))) 90 (cl-defmethod corfu--popup-hide (&context (corfu-terminal-mode 94 If `corfu-terminal-disable-on-gui' is non-nil and `display-graphic-p' 95 returns non-nil then call FN instead, where FN should be the original 97 (if (and corfu-terminal-disable-on-gui 100 (when corfu-terminal--popon 101 (setq corfu-terminal--popon 102 (popon-kill corfu-terminal--popon))))) 104 (cl-defmethod corfu--popup-show ( pos off width lines 105 &context (corfu-terminal-mode 107 &optional curr lo bar) 108 "Show popup at OFF columns before POS. 110 Show LINES, a list of lines. Highlight CURRth line as current 111 selection. Show a vertical scroll bar of size BAR + 1 from LOth line. 113 If `corfu-terminal-disable-on-gui' is non-nil and `display-graphic-p' 114 returns non-nil then call FN instead, where FN should be the original 115 definition in Corfu." 116 (if (and corfu-terminal-disable-on-gui 118 (cl-call-next-method) 119 (corfu--popup-hide) ; Hide the popup first. 120 (when (and (window-minibuffer-p) 121 (< (/ (window-body-height nil 'pixelwise) 122 (default-font-height)) 124 corfu-terminal-resize-minibuffer 125 (not (frame-root-window-p (selected-window)))) 126 (window-resize nil (- (1+ (length lines)) 127 (/ (window-body-height nil 'pixelwise) 128 (default-font-height))))) 129 (let* ((bar-width (ceiling (* (default-font-width) 131 (margin-left-width (ceiling (* (default-font-width) 132 corfu-left-margin-width))) 133 (margin-right-width (max (ceiling 134 (* (default-font-width) 135 corfu-right-margin-width)) 138 (when (< 0 bar-width) 139 (if (display-graphic-p) 144 :width (,(- margin-right-width bar-width)))) 145 (propertize " " 'display 146 `(space :width (,bar-width)) 149 (make-string (- margin-right-width bar-width) ?\ ) 150 (propertize (make-string bar-width ?\ ) 'face 153 (when (> margin-left-width 0) 154 (if (display-graphic-p) 156 " " 'display `(space :width (,margin-left-width))) 157 (make-string margin-left-width ?\ )))) 159 (when (> margin-right-width 0) 160 (if (display-graphic-p) 162 " " 'display `(space :width (,margin-right-width))) 163 (make-string margin-right-width ?\ )))) 165 (if (display-graphic-p) 166 (+ width (round (/ (+ margin-left-width 168 (default-font-width)))) 169 (+ width margin-left-width margin-right-width))) 171 (if (equal (cdr corfu-terminal--last-position) 172 (list (posn-point pos) popon-width 173 (window-start) (buffer-modified-tick))) 174 (car corfu-terminal--last-position) 175 (let ((x-y (popon-x-y-at-posn pos))) 178 (min (- (car x-y) (+ off margin-left-width)) 179 (- (window-max-chars-per-line) 180 corfu-terminal-position-right-margin 183 (if (and (< (/ (window-body-height nil 'pixelwise) 184 (default-font-height)) 185 (+ (1+ (cdr x-y)) (length lines))) 186 (>= (cdr x-y) (length lines))) 187 (- (cdr x-y) (length lines)) 189 (setq corfu-terminal--last-position 190 (list popon-pos (posn-point pos) popon-width 191 (window-start) (buffer-modified-tick))) 192 (setq corfu-terminal--popon 197 (lambda (line line-number) 201 (make-string (- width (string-width line)) 203 (if (and lo (<= lo line-number (+ lo bar))) 206 (add-face-text-property 0 (length str) 207 (if (eq line-number curr) 219 (define-minor-mode corfu-terminal-mode 220 "Corfu popup on terminal." 222 :group 'corfu-terminal) 224 (provide 'corfu-terminal) 225 ;;; corfu-terminal.el ends here