Як відобразити вміст мінібуфера посередині кадру emacs?


20

Працюючи над максимальним кадром Emacs, вміст дисплея області мінібуфера / ехо в нижній частині екрана може бути важко помітним, але також призводить до втрати уваги на редагуваному тексті під час введення команди - що цілком питання з точки зору зручності використання.

Чи є можливість перемістити область minibuffer / echo в центрі поточного буфера emacs над текстом, який редагується, коли minibuffer активний, або, що краще, захопити вміст minibuffer і відобразити його також у центрі поточного буфера під час введення команди?


Для повноти слід додати, що моє поточне рішення цього питання щодо юзабіліті - збільшити розмір шрифту мінібуфера, але це виглядає нерозумно на не максимізованих кадрах.
Sébastien Le Callonnec

Відповіді:


10

Popup Minibuffer у центрі

Ось спосіб зробити саме те, що ви просили: відобразити мінібуфер у центрі екрана .

  1. Мають окремий каркас для мінібуфера
  2. Розташуйте його в центрі
  3. Піднімайте цей кадр, коли мінібуфер отримує фокус.

Це порівняно легко досягти, і це ви отримаєте з oneonone.elпакетом (як вказує @Drew). Проблема такого підходу полягає в тому, що мінібуфер також використовується для повідомлень, тому зберігати його приховано - це не щось дуже зручне. Не хвилюйся! Я придумав інше рішення.

  1. Є другий мінібуфер відображається на окремій рамі.
  2. Розташуйте його в центрі.
  3. Використовуйте другий кадр для інтерактивних команд, тоді як оригінальний (перший) мінібуфер використовується для ехо-повідомлень.

Впровадження

Для цього нам потрібно створити кадр мінібуфера при запуску emacs.

(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-file, ido-switch-buffer, eval-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).
Стефан

6

Мінібуфер вгорі

Відображення мінібуфера посередині екрану є складним. Доцільною альтернативою (яка може бути чи не зручною для вас читати) є переміщення її до вершини.

Ви можете налаштувати розташування (або існування) мінібуфера minibufferкадру з параметром кадру у 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для обчислення потрібної позиції, виходячи з будь-яких критеріїв, які ви хочете (поточний розмір вікна / рамки та положення, фаза Місяця, ...).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.