emacsフレームの中央にミニバッファーのコンテンツを表示する方法は?


20

最大化されたEmacsフレームで作業している場合、画面の下部にミニバッファー/エコーエリアの内容を表示するのは見にくい場合がありますが、コマンドを入力するときに編集中のテキストにフォーカスを失います。使いやすさの点で問題。

現在のemacsバッファーの中央にあるミニバッファー/エコー領域を、ミニバッファーがアクティブなときに編集中のテキスト上に移動する方法、またはミニバッファーの内容をキャプチャして中央に表示する方法がありますか?コマンドを入力しながら、現在のバッファの?


完全を期すために、このユーザビリティの問題に対する私の現在の解決策は、ミニバッファのフォントサイズを増やすことですが、最大化されていないフレームでは愚かに見えることを付け加える必要があります。
セバスチャンルカロネック14年

回答:


10

中央のポップアップミニバッファ

まさにあなたが求めたことをする方法があります:画面の中央にミニバッファを表示します

  1. ミニバッファー用に別のフレームを用意する
  2. 中央に配置する
  3. ミニバッファーがフォーカスを取得するたびに、このフレームを上げます。

これは比較的簡単に実現でき、oneonone.elパッケージで得られるものです (@Drewが指摘しているように)。このアプローチの問題点は、ミニバッファーがメッセージにも使用されるため、非表示にしておくことはあまり便利ではないことです。心配無用!別の解決策を思いつきました。

  1. 持っている第二ミニバッファ別のフレームに表示されます。
  2. 中央に配置します。
  3. 対話型コマンドには2番目のフレームを使用し、メッセージのエコーには元の(最初の)ミニバッファーを使用します。

実装

これを実装するには、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、元のフレームのミニバッファーではなく、この2番目のミニバッファーを使用するようにパッチを適用します。

(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-addad-add-advice
ステファン14

6

上部のミニバッファー

画面の中央にミニバッファーを表示するのは複雑です。合理的な代替手段(読みやすいかどうかわからない場合)は、最上部に移動します。

変数のminibufferframeパラメーターを使用して 、フレームのミニバッファーの場所(または存在)を構成できますinitial-frame-alist

別枠

パラメータをnilに設定すると、フレームにミニバッファーがないように構成され、Emacsは自動的に別のミニバッファーフレームを作成します。これらの2つのフレームは、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.