config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

corfu-info.el (4681B)


      1 ;;; corfu-info.el --- Show candidate information in separate buffer -*- lexical-binding: t -*-
      2 
      3 ;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
      4 
      5 ;; Author: Daniel Mendler <mail@daniel-mendler.de>
      6 ;; Maintainer: Daniel Mendler <mail@daniel-mendler.de>
      7 ;; Created: 2022
      8 ;; Package-Requires: ((emacs "28.1") (compat "30") (corfu "1.5"))
      9 ;; URL: https://github.com/minad/corfu
     10 
     11 ;; This file is part of GNU Emacs.
     12 
     13 ;; This program is free software: you can redistribute it and/or modify
     14 ;; it under the terms of the GNU General Public License as published by
     15 ;; the Free Software Foundation, either version 3 of the License, or
     16 ;; (at your option) any later version.
     17 
     18 ;; This program is distributed in the hope that it will be useful,
     19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     21 ;; GNU General Public License for more details.
     22 
     23 ;; You should have received a copy of the GNU General Public License
     24 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     25 
     26 ;;; Commentary:
     27 
     28 ;; This Corfu extension provides commands to show additional information to the
     29 ;; candidates in a separate buffer.  The commands `corfu-info-location' and
     30 ;; `corfu-info-documentation' are bound by default in the `corfu-map' to M-g and
     31 ;; M-h respectively.
     32 
     33 ;;; Code:
     34 
     35 (require 'corfu)
     36 (eval-when-compile
     37   (require 'subr-x))
     38 
     39 (defun corfu-info--restore-on-next-command ()
     40   "Restore window configuration before next command."
     41   (let ((config (current-window-configuration))
     42         (other other-window-scroll-buffer)
     43         (restore (make-symbol "corfu--restore")))
     44     (fset restore
     45           (lambda ()
     46             (setq other-window-scroll-buffer other)
     47             (unless (memq this-command '(scroll-other-window scroll-other-window-down))
     48               (when (memq this-command '(corfu-quit corfu-reset))
     49                 (setq this-command #'ignore))
     50               (remove-hook 'pre-command-hook restore)
     51               (set-window-configuration config))))
     52     (add-hook 'pre-command-hook restore)))
     53 
     54 (defun corfu-info--display-buffer (buffer name)
     55   "Display BUFFER and return window displaying the buffer.
     56 Make the buffer persistent with NAME if non-nil."
     57   (if name
     58       (unless (buffer-local-value 'buffer-file-name buffer)
     59         (if-let ((old (get-buffer name)))
     60             (setq buffer (prog1 old (kill-buffer buffer)))
     61           (with-current-buffer buffer
     62             (rename-buffer name))))
     63     (corfu-info--restore-on-next-command))
     64   (setq other-window-scroll-buffer buffer)
     65   (display-buffer buffer t))
     66 
     67 ;;;###autoload
     68 (defun corfu-info-documentation (&optional arg)
     69   "Show documentation of current candidate.
     70 If called with a prefix ARG, the buffer is persistent."
     71   (interactive "P")
     72   ;; Company support, taken from `company.el', see `company-show-doc-buffer'.
     73   (when (< corfu--index 0)
     74     (user-error "No candidate selected"))
     75   (let ((cand (nth corfu--index corfu--candidates)))
     76     (if-let ((extra (nth 4 completion-in-region--data))
     77              (fun (plist-get extra :company-doc-buffer))
     78              (res (funcall fun cand)))
     79         (set-window-start (corfu-info--display-buffer
     80                            (get-buffer (or (car-safe res) res))
     81                            (and arg (format "*corfu doc: %s*" cand)))
     82                           (or (cdr-safe res) (point-min)))
     83       (user-error "No documentation available for `%s'" cand))))
     84 
     85 ;;;###autoload
     86 (defun corfu-info-location (&optional arg)
     87   "Show location of current candidate.
     88 If called with a prefix ARG, the buffer is persistent."
     89   (interactive "P")
     90   ;; Company support, taken from `company.el', see `company-show-location'.
     91   (when (< corfu--index 0)
     92     (user-error "No candidate selected"))
     93   (let ((cand (nth corfu--index corfu--candidates)))
     94     (if-let ((extra (nth 4 completion-in-region--data))
     95              (fun (plist-get extra :company-location))
     96              ;; BUG: company-location may throw errors if location is not found
     97              (loc (ignore-errors (funcall fun cand))))
     98         (with-selected-window
     99             (corfu-info--display-buffer
    100              (or (and (bufferp (car loc)) (car loc))
    101                  (find-file-noselect (car loc) t))
    102              (and arg (format "*corfu loc: %s*" cand)))
    103           (without-restriction
    104             (goto-char (point-min))
    105             (when-let ((pos (cdr loc)))
    106               (if (bufferp (car loc))
    107                   (goto-char pos)
    108                 (forward-line (1- pos))))
    109             (set-window-start nil (point))))
    110       (user-error "No location available for `%s'" cand))))
    111 
    112 (provide 'corfu-info)
    113 ;;; corfu-info.el ends here