วิธีการแสดงเนื้อหาของ minibuffer ที่อยู่ตรงกลางเฟรม emacs?


20

เมื่อทำงานกับกรอบ Emacs ที่ขยายใหญ่สุดการมีเนื้อหาของ minibuffer / echo area แสดงที่ด้านล่างของหน้าจออาจมองเห็นได้ยาก แต่ยังทำให้โฟกัสข้อความที่แก้ไขเมื่อพิมพ์คำสั่ง - ซึ่งค่อนข้าง ปัญหาในแง่ของการใช้งาน

มีวิธีการย้ายพื้นที่ minibuffer / echo ในศูนย์กลางของบัฟเฟอร์ emacs ปัจจุบันเหนือข้อความที่แก้ไขเมื่อมีการใช้งาน minibuffer หรือดีกว่าเพื่อจับเนื้อหาของ minibuffer และแสดงมันในศูนย์ ของบัฟเฟอร์ปัจจุบันขณะพิมพ์คำสั่งหรือไม่


เพื่อความสมบูรณ์ฉันควรเพิ่มว่าโซลูชันปัจจุบันของฉันสำหรับปัญหาการใช้งานนี้คือการเพิ่มขนาดตัวอักษรของ minibuffer แต่ดูโง่ในเฟรมที่ไม่ขยาย
Sébastien Le Callonnec

คำตอบ:


10

Popup Minibuffer ที่ศูนย์

นี่คือวิธีการที่จะทำสิ่งที่คุณถาม: แสดง minibuffer ที่ศูนย์ของหน้าจอ

  1. มีเฟรมแยกต่างหากสำหรับ minibuffer
  2. วางตำแหน่งไว้ตรงกลาง
  3. เพิ่มเฟรมนี้เมื่อใดก็ตามที่ minibuffer ได้รับโฟกัส

นั่นเป็นเรื่องที่ทำได้ง่ายและเป็นสิ่งที่คุณจะได้รับจาก oneonone.elแพ็คเกจ (ตามที่ @Drew points) ปัญหาเกี่ยวกับวิธีนี้คือใช้ minibuffer สำหรับข้อความดังนั้นการซ่อนไว้จึงไม่ใช่สิ่งที่สะดวกมาก ไม่ต้องกังวล! ฉันมาด้วยวิธีอื่น

  1. มีminibuffer ที่สองปรากฏขึ้นในเฟรมแยกต่างหาก
  2. วางตำแหน่งไว้ตรงกลาง
  3. ใช้เฟรมที่สองสำหรับคำสั่งแบบอินเทอร์แอคทีฟขณะที่ minibuffer (แรก) ดั้งเดิมใช้สำหรับการแสดงข้อความ

การดำเนินงาน

ในการดำเนินการนี้เราต้องสร้างกรอบ minibuffer เมื่อเริ่มต้น 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ต่อเพื่อใช้ minibuffer ตัวที่สองนี้แทน 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 ที่อยู่ตรงกลางของหน้าจอนั้นซับซ้อน ทางเลือกที่สมเหตุสมผล (ซึ่งคุณอาจจะหรืออาจจะไม่สามารถอ่านได้มากขึ้น) คือการย้ายไปด้านบน

คุณสามารถกำหนดค่าตำแหน่ง (หรือการดำรงอยู่) ของ minibuffer ของเฟรมด้วยminibufferพารามิเตอร์เฟรมใน initial-frame-alist ตัวแปร

เฟรมแยก

การตั้งค่าพารามิเตอร์เป็นnilจะกำหนดค่าเฟรมให้ไม่มี minibuffer และ Emacs จะสร้างเฟรม minibuffer แยกต่างหากสำหรับคุณโดยอัตโนมัติ คุณสามารถจัดตำแหน่งสองเฟรมนี้โดยใช้ตัวจัดการหน้าต่างระบบปฏิบัติการของคุณหรือคุณสามารถทำได้จาก Emacs

ตัวอย่างต่อไปนี้จะตรวจสอบวิธีวางเฟรม minibuffer ที่ด้านบนด้วยกรอบปกติด้านล่าง แต่คุณจะต้องเปลี่ยนตัวเลขเป็นบัญชีสำหรับขนาดจอภาพของคุณ

(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ตามตำแหน่งที่คุณต้องการสำหรับเฟรม minibuffer แบบสแตนด์อโลน ค่าคือจำนวนพิกเซลจากด้านบน (ถ้าไม่ใช่แบบลบ) หรือด้านล่าง (ถ้าเป็นลบ) ของจอแสดงผลของคุณ ตัวอย่างเช่นตั้งค่าเป็นความสูงของจอแสดงผลของคุณหารด้วย 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.