如何在emacs帧中间显示minibuffer的内容?


20

在最大化的Emacs框架上工作时,很难看到屏幕底部显示的minibuffer / echo区域的内容,但是当键入命令时,这也会导致失去对正在编辑的文本的关注–这相当可用性方面的问题

有没有办法在minibuffer处于活动状态时将当前minimacs缓冲区的minibuffer / echo区域移至正在编辑的文本上方,或者更好地捕获minibuffer的内容并将其显示在中心键入命令时当前缓冲区的大小?


为了完整起见,我应该补充一点,我当前针对此可用性问题的解决方案是增加小型缓冲区的字体大小,但在非最大化帧上看起来很愚蠢。
塞巴斯蒂安乐Callonnec

Answers:


10

中心弹出式迷你缓冲区

这是一种完全按照您的要求执行的方法:在屏幕中央显示迷你缓冲区

  1. 为minibuffer有一个单独的框架
  2. 将其放置在中心
  3. 每当微型缓冲区获得焦点时,请升高此帧。

这是相对容易实现的,并且可以从oneonone.el软件包中获得 (正如@Drew所指出的)。这种方法的问题在于,微型缓冲区也用于消息,因此将其隐藏起来不是很方便。不用担心!我想出了另一种解决方案。

  1. 第二小缓冲区上的单独的帧显示。
  2. 将其放置在中央。
  3. 将第二帧用于交互式命令,而原始(第一个)微型缓冲区用于回显消息。

实作

为此,我们需要在emacs启动时创建minibuffer框架。

(defvar endless/popup-frame-parameters
  '((name . "MINIBUFFER")
    (minibuffer . only)
    (height . 1)
    ;; Ajust this one to your preference.
    (top . 200))
  "Parameters for the minibuffer popup frame.")

(defvar endless/minibuffer-frame
  (let ((mf (make-frame endless/popup-frame-parameters)))
    (iconify-frame mf) mf)
  "Frame holding the extra minibuffer.")

(defvar endless/minibuffer-window
  (car (window-list endless/minibuffer-frame t))
  "")

然后,我们打补丁read-from-minibuffer以使用第二个微型缓冲区,而不是原始帧的微型缓冲区。

(defmacro with-popup-minibuffer (&rest body)
  "Execute BODY using a popup minibuffer."
  (let ((frame-symbol (make-symbol "selected-frame")))
    `(let* ((,frame-symbol (selected-frame)))
       (unwind-protect 
           (progn 
             (make-frame-visible endless/minibuffer-frame)
             (when (fboundp 'point-screen-height)
               (set-frame-parameter
                endless/minibuffer-frame 
                'top (point-screen-height)))
             (select-frame-set-input-focus endless/minibuffer-frame 'norecord)
             ,@body)
         (select-frame-set-input-focus ,frame-symbol)))))

(defun use-popup-minibuffer (function)
  "Rebind FUNCTION so that it uses a popup minibuffer."
  (let* ((back-symb (intern (format "endless/backup-%s" function)))
         (func-symb (intern (format "endless/%s-with-popup-minibuffer"
                                    function)))
         (defs `(progn
                  (defvar ,back-symb (symbol-function ',function))
                  (defun ,func-symb (&rest rest)
                    ,(format "Call `%s' with a poupup minibuffer." function)
                    ,@(list (interactive-form function))
                    (with-popup-minibuffer 
                     (apply ,back-symb rest))))))
    (message "%s" defs)
    (when (and (boundp back-symb) (eval back-symb))
      (error "`%s' already defined! Can't override twice" back-symb))
    (eval defs)
    (setf (symbol-function function) func-symb)))

;;; Try at own risk.
(use-popup-minibuffer 'read-from-minibuffer)
;;; This will revert the effect.
;; (setf (symbol-function #'read-from-minibuffer) endless/backup-read-from-minibuffer)
;; (setq endless/backup-read-from-minibuffer nil)

这可能不是绝对的一切工作,但它的工作对我试过到目前为止一切--- find-fileido-switch-buffereval-expression。如果你发现任何异常,您可以通过调用上打补丁的情况下,逐个这些功能 use-popup-minibuffer在他们身上。

位置近点

要将这个微型缓冲区框架定位在点的高度附近,只需定义以下函数即可。它不是完美的(实际上,在很多情况下它是可怕的),但是在估计点高方面做得不错。

(defun point-screen-height ()
  (* (/ (face-attribute 'default :height) 10) 2
     (- (line-number-at-pos (point))
        (line-number-at-pos (window-start)))))

(setf (symbol-function function) ...)最好不要使用advice-add(或较旧的ad-add-advice),而不是弄乱您。
Stefan 2014年

6

顶部的迷你缓冲区

在屏幕中间显示迷你缓冲区很复杂。一个合理的选择(您可能会或可能不会觉得它更具可读性)是将其移至顶部。

您可以使用 变量中的minibufferframe参数 配置帧的微型缓冲区的位置(或存在)initial-frame-alist

分开的框架

将该参数设置为,nil将配置框架没有小缓冲区,Emacs将自动为您创建一个单独的小缓冲区帧。您可以使用操作系统的窗口管理器来定位这两个框架,也可以从Emacs进行定位。

下面的代码片段说明了如何将微型缓冲区框架放置在顶部,而普通框架则位于其下方,但是您绝对必须更改数字以适应监视器的大小。

(setq initial-frame-alist
      '((left . 1) (minibuffer . nil)
        ;; You'll need to adjust the following 3 numbers.
        (top . 75) ; In pixels
        (width . 127) ; In chars
        (height . 31)))

(setq minibuffer-frame-alist
      '((top . 1) (left . 1) (height . 2)
        ;; You'll need to adjust the following number.
        (width . 127)))

调整此速度最快的方法是在窗口管理器中调整框架的大小,然后进行评估(frame-parameters)以查看所拥有的参数值。

同一帧

另一种可能性是将minibuffer参数设置为窗口。不幸的是,我无法使它在同一框架的窗口中工作。


5

oneonone.el为您提供了开箱即用的功能。

只需将选项自定义1on1-minibuffer-frame-top/bottom到独立微型缓冲区框架所需的位置即可。该值是从显示器的顶部(如果不是负数)或底部(如果是负数)起的像素数。例如,将值设置为显示高度除以2,以使其垂直居中。

如果您希望将其动态定位,例如在当前帧的垂直中心放置,则可以通过(a)保留1on1-minibuffer-frame-top/bottom= nil和(b)建议函数 1on1-set-minibuffer-frame-top/bottom将该变量动态绑定到适当位置来实现。例如:

(defadvice 1on1-set-minibuffer-frame-top/bottom (around center activate)
  (let ((1on1-minibuffer-frame-top/bottom  (my-dynamic-position ...)))
    ad-do-it))

(定义函数my-dynamic-position以根据所需的任何条件(当前的窗口/帧大小和位置,月相...)来计算所需的位置。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.