이맥스 프레임 중간에 미니 버퍼의 내용을 표시하는 방법?


20

최대화 된 Emacs 프레임에서 작업 할 때 화면 하단에 미니 버퍼 / 에코 영역 디스플레이의 내용을 표시하기 어려울 수 있지만 명령을 입력 할 때 편집중인 텍스트에 초점을 잃을 수도 있습니다. 사용성 측면에서 문제.

현재 이맥스 버퍼의 중앙에서 미니 버퍼 / 에코 영역을 이동하거나 미니 버퍼가 활성화되어있을 때 편집중인 텍스트 위로 이동하거나 더 나은 방법으로 미니 버퍼의 내용을 캡처하여 중앙에 표시하는 방법이 있습니까? 명령을 입력하는 동안 현재 버퍼의


완성도를 높이기 위해이 유용성 문제에 대한 현재 솔루션은 미니 버퍼의 글꼴 크기를 늘리는 것이지만 최대화되지 않은 프레임에서는 바보처럼 보입니다.
Sébastien Le Callonnec

답변:


10

센터에서 팝업 미니 버퍼

요청한 내용을 정확하게 수행하는 방법은 다음과 같습니다 . 화면 중앙에 미니 버퍼를 표시합니다 .

  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-addad-add-advice
Stefan

6

상단의 미니 버퍼

화면 중간에 미니 버퍼를 표시하는 것은 복잡합니다. 합리적인 대안 (더 읽기 쉬울 수도 있고 찾지 못할 수도 있음)은 맨 위로 이동하는 것입니다.

minibuffer변수 의 frame 매개 변수를 사용하여 프레임 미니 버퍼의 위치 (또는 존재)를 구성 할 수 있습니다 initial-frame-alist .

별도의 프레임

매개 변수를 설정하면 nil미니 버퍼가 없도록 프레임이 구성되고 이맥스는 자동으로 별도의 미니 버퍼 프레임을 만듭니다. OS의 창 관리자를 사용하여이 두 프레임을 배치하거나 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원하는 기준 (현재 창 / 프레임 크기 및 위치, 달의 위상 등)에 따라 원하는 위치를 계산하는 함수 를 정의하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.