จะควบคุมตำแหน่งที่จะแสดงบัฟเฟอร์คำหลัก org todo ได้อย่างไร


9

ถาม : ฉันจะควบคุมตำแหน่งที่จะให้orgบัฟเฟอร์คำหลักที่ต้องทำปรากฏได้อย่างไร

การป้อนtodoคำหลักด้วยC-c C-t( org-todo) จะเปิดบัฟเฟอร์ใหม่พร้อมตัวเลือกคำหลักแล้วปิดอีกครั้งหลังจากที่ฉันเลือก จนถึงตอนนี้ดีมาก อย่างไรก็ตามจะใช้เวลาข้ามหน้าต่างอื่นในการทำเช่นนั้นซึ่งไม่ค่อยดีนักโดยเฉพาะอย่างยิ่งเนื่องจากต้องการแสดงบรรทัดหนึ่งหรือสองด้วยคำหลัก

ดังนั้นด้วยรูปแบบต่อไปการกดปุ่มC-c C-tในขณะที่อยู่ในหน้าต่างด้านซ้าย ( some-org-buffer) จะเปิด*Org todo*ในหน้าต่างด้านขวา:

+---------------------+---------------------+
|                     |                     |
|                     |                     |
|                     |                     |
|                     |                     |
|   some-org-buffer   |  some-other-buffer  |
|                     |                     |
|                     |                     |
|                     |                     |
|                     |                     |
+---------------------+---------------------+

แต่ฉันต้องการให้มีหน้าต่างเล็ก ๆ ปรากฏขึ้นแยกเป็นแนวตั้งดังนี้:

+---------------------+---------------------+
|                     |                     |
|                     |                     |
|   some-org-buffer   |  some-other-buffer  |
|                     |                     |
|                     |                     |
+---------------------+                     |
|                     |                     |
|     *Org todo*      |                     |
|                     |                     |
+---------------------+---------------------+

จาก คำตอบนี้ฉันเขียนฟังก์ชันเพื่อใส่ลงไปในdisplay-buffer-alist:

(defun org-todo-position (buffer alist)
  (let ((win (car (cl-delete-if-not
                   (lambda (window)
                     (with-current-buffer (window-buffer window)
                       (memq major-mode
                             '(org-mode org-agenda-mode))))
                   (window-list)))))
    (when win
      (let ((new (split-window win -5 'below)))
        (set-window-buffer new buffer)
        new))))

(add-to-list 'display-buffer-alist
             (list " \\*Org todo\\*" #'dan-org-todo-position))

อย่างไรก็ตามนั่นล้มเหลวในการทำงาน ถอนหายใจ ข้าพเจ้าได้กระทำอะไรผิดปกติกับdisplay-buffer-alist? ยิ่งกว่านั้นฉันจะทำให้todoบัฟเฟอร์คำหลักของฉัน ปรากฏขึ้นที่ที่ฉันต้องการได้อย่างไร


ไม่ใช่คำตอบสำหรับคำถามของคุณ แต่คุณอาจต้องการพิจารณาแก้ไขorg-switch-to-buffer-other-windowสิ่งที่คุณต้องการคุณสามารถสร้างเงื่อนไขที่ทำสิ่งที่คุณต้องการ
ฏหมาย

@ ลอว์ลิสต์: ขอบคุณฉันขุดไปรอบ ๆ และพบกับอวัยวะภายในที่org-switch-to-buffer-other-windowน่าเกลียดอื่น orgดูคำตอบสำหรับ "วิธีแก้ปัญหาที่น่าอับอาย"
แดน

ในขณะที่รวมสิ่งเหล่านี้ทั้งหมดลงใน. emacs ของฉันฉันลองดูที่ฟังก์ชันตำแหน่งของคุณอย่างใกล้ชิดและฉันรู้สึกว่าฉันขาดอะไรบางอย่างเกี่ยวกับคำจำกัดความของwinคุณ มีเหตุผลที่คุณไม่สามารถใช้(selected-window)ที่นี่ได้หรือไม่?
Aaron Harris

@AaronHarris: ยังไม่ได้ลอง ฉันมี (เบา ๆ ) ปรับคำตอบจากโพสต์อื่นที่ใช้กลไกนี้ ลองยิงมันดูว่ามันใช้ได้ไหม
แดน

@ ด่าน: ใช่มันใช้งานได้ ฉันเป็นกังวลเพียงเล็กน้อยว่าสถานการณ์มุมคดีบางอย่างจะทำให้มันระเบิด และขอบคุณสำหรับฟังก์ชั่นนั้น btw มันทำในสิ่งที่ฉันต้องการและฉันไม่คิดว่าฉันจะสามารถพูดได้ว่าเป็นสิ่งที่ฉันต้องการก่อนที่จะเห็นคำถามนี้
Aaron Harris

คำตอบ:


4

ถอนหายใจ ฉันพบ "โซลูชัน" แต่เป็นโซลูชันที่น่าเกลียดที่ต้องการแทนที่orgฟังก์ชันที่มีอยู่ ฉันต้องการหนึ่งที่ไม่ต้องแก้ไขorgซอร์สโค้ด แต่กำลังวางผลการขุดค้นทางโบราณคดีของฉันที่นี่ในกรณีที่คนอื่นสามารถใช้งานได้

อย่างที่ฉันเคยสังเกตเห็นในอดีตด้วยorgฟังก์ชั่น อื่น ๆorg-modeค่อนข้างให้ความเห็นเกี่ยวกับวิธีจัดการกับหน้าต่าง

ลึกฝังอยู่ในรหัสที่มาของคือการเรียกร้องให้ฟังก์ชั่นที่org-todo org-fast-todo-selectionฟังก์ชั่นนั้นจะเรียกใช้ org-switch-to-buffer-other-windowซึ่ง docstring อ่านส่วนหนึ่ง:

สลับไปที่บัฟเฟอร์ในหน้าต่างที่สองของเฟรมปัจจุบัน โดยเฉพาะอย่างยิ่งไม่อนุญาตให้เฟรม pop-up

เอ่อโอ้.

โอเคฉันจะกัด: มาดู org-switch-to-buffer-other-windowกัน มันใช้org-no-popups มาโคร มันเป็นส่วนหนึ่งของ docstring อ่าน:

ปราบปรามหน้าต่างป๊อปอัพ ลองผูกตัวแปรบางตัวกับศูนย์รอบ ๆ BODY ...

ปรากฎว่าdisplay-buffer-alistเป็นหนึ่งในตัวแปร let-bound nilไป

( หัวระเบิด )

ท้ายที่สุดเราสามารถทำให้มันไม่สนใจ display-buffer-alistโดยการแก้ไขorg-fast-todo-selectionและแทนที่org-switch-to-buffer-other-windowบรรทัดด้วย old old switch-to-buffer-other-window:

(defun org-fast-todo-selection ()
  "Fast TODO keyword selection with single keys.
Returns the new TODO keyword, or nil if no state change should occur."
  (let* ((fulltable org-todo-key-alist)
     (done-keywords org-done-keywords) ;; needed for the faces.
     (maxlen (apply 'max (mapcar
                  (lambda (x)
                (if (stringp (car x)) (string-width (car x)) 0))
                  fulltable)))
     (expert nil)
     (fwidth (+ maxlen 3 1 3))
     (ncol (/ (- (window-width) 4) fwidth))
     tg cnt e c tbl
     groups ingroup)
    (save-excursion
      (save-window-excursion
    (if expert
        (set-buffer (get-buffer-create " *Org todo*"))
      ;; (org-switch-to-buffer-other-window (get-buffer-create " *Org todo*")))
      (switch-to-buffer-other-window (get-buffer-create " *Org todo*")))
    (erase-buffer)
    (org-set-local 'org-done-keywords done-keywords)
    (setq tbl fulltable cnt 0)
    (while (setq e (pop tbl))
      (cond
       ((equal e '(:startgroup))
        (push '() groups) (setq ingroup t)
        (when (not (= cnt 0))
          (setq cnt 0)
          (insert "\n"))
        (insert "{ "))
       ((equal e '(:endgroup))
        (setq ingroup nil cnt 0)
        (insert "}\n"))
       ((equal e '(:newline))
        (when (not (= cnt 0))
          (setq cnt 0)
          (insert "\n")
          (setq e (car tbl))
          (while (equal (car tbl) '(:newline))
        (insert "\n")
        (setq tbl (cdr tbl)))))
       (t
        (setq tg (car e) c (cdr e))
        (if ingroup (push tg (car groups)))
        (setq tg (org-add-props tg nil 'face
                    (org-get-todo-face tg)))
        (if (and (= cnt 0) (not ingroup)) (insert "  "))
        (insert "[" c "] " tg (make-string
                   (- fwidth 4 (length tg)) ?\ ))
        (when (= (setq cnt (1+ cnt)) ncol)
          (insert "\n")
          (if ingroup (insert "  "))
          (setq cnt 0)))))
    (insert "\n")
    (goto-char (point-min))
    (if (not expert) (org-fit-window-to-buffer))
    (message "[a-z..]:Set [SPC]:clear")
    (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
    (cond
     ((or (= c ?\C-g)
          (and (= c ?q) (not (rassoc c fulltable))))
      (setq quit-flag t))
     ((= c ?\ ) nil)
     ((setq e (rassoc c fulltable) tg (car e))
      tg)
     (t (setq quit-flag t)))))))

คุณสามารถใช้ cl fletที่นี่เพื่อเชื่อมโยงใหม่ได้org-switch-to-buffer-other-windowหรือไม่ สงสัยว่าคุณสามารถให้คำแนะนำหรือห่อorg-fast-todo-selectionมากกว่าการเขียนทับมัน
ลูกัส

@glucas: ความคิดที่ดี แม้ว่าจะพยายามและไม่สามารถใช้งานได้
ด่าน

1
@Dan ผมก็สามารถที่จะได้รับนี้ในการทำงานโดยกําหนดที่จะเพียงแค่org-switch-to-buffer-other-window (switch-to-buffer-other-window args)ฉันยังลบออก&restจากข้อโต้แย้งฟังก์ชั่น
sk8ingdom

3

ฉันเพิ่งคิดออกวิธีที่จะทำให้การจับภาพขององค์กรโหมดในกรอบใหม่ การแก้ไขโค้ดนั้นเพื่อใช้ฟังก์ชั่นของคุณนั้นค่อนข้างตรงไปตรงมา นี่คือวิธีที่ฉันจะทำ:

(defun my/org-todo-window-advice (orig-fn)
  "Advice to fix window placement in `org-fast-todo-selection'."
  (let  ((override '("\\*Org todo\\*" dan-org-todo-position)))
    (add-to-list 'display-buffer-alist override)
    (my/with-advice
        ((#'org-switch-to-buffer-other-window :override #'pop-to-buffer))
      (unwind-protect (funcall orig-fn)
        (setq display-buffer-alist
              (delete override display-buffer-alist))))))

(advice-add #'org-fast-todo-selection :around #'my/org-todo-window-advice)

เพื่อประโยชน์ของความสมบูรณ์นี่คือคำจำกัดความของmy/with-adviceแมโครจากคำตอบอื่น ๆ :

(defmacro my/with-advice (adlist &rest body)
  "Execute BODY with temporary advice in ADLIST.

Each element of ADLIST should be a list of the form
  (SYMBOL WHERE FUNCTION [PROPS])
suitable for passing to `advice-add'.  The BODY is wrapped in an
`unwind-protect' form, so the advice will be removed even in the
event of an error or nonlocal exit."
  (declare (debug ((&rest (&rest form)) body))
           (indent 1))
  `(progn
     ,@(mapcar (lambda (adform)
                 (cons 'advice-add adform))
               adlist)
     (unwind-protect (progn ,@body)
       ,@(mapcar (lambda (adform)
                   `(advice-remove ,(car adform) ,(nth 2 adform)))
                 adlist))))

2

มองในของคนอื่นconfig ของผมพบว่าวิธีการควบคุมที่*Org Src.*และ*Org todo*บัฟเฟอร์ปรากฏ ตอนนี้เมื่อฉันกดปุ่มC-c C-tหรือC-c 'บัฟเฟอร์เหล่านี้แสดงในหน้าต่างใหม่ที่ด้านล่างของเค้าโครงหน้าต่างปัจจุบันของฉันและการเลือกสถานะสิ่งที่ต้องทำหรือการกดปุ่มC-c '( org-edit-src-exit) จะคืนค่าการกำหนดค่าหน้าต่างของฉันกลับไปเป็นรูปแบบดั้งเดิม

โซลูชันนี้เกี่ยวข้องกับการใช้กุญแจมือและ Elisp บางตัว:

ขั้นตอนที่ 1

ดาวน์โหลดshackleจาก MELPA นี่คือวิธีที่ฉันติดตั้งuse-packageในไฟล์ init ของฉัน:

(use-package shackle
    :ensure t
    :diminish shackle-mode  ; hide name in mode-line
    :config
    (setq shackle-rules
          '(("\\*Org Src.*" :regexp t :align below :select t)
            (" *Org todo*" :align below :select t)))
    (shackle-mode t))

การตั้งค่าที่สำคัญมีดังนี้:

(setq shackle-rules
              '(("\\*Org Src.*" :regexp t :align below :select t)
                (" *Org todo*" :align below :select t)))

แหล่งที่มา

โดยเฉพาะช่องว่างระหว่าง"และ*Orgบนบรรทัดล่าง ฉันไม่ได้ทดสอบการตั้งค่า:alignไปยังตำแหน่งอื่น แต่shackleดูเหมือนว่าจะมีความยืดหยุ่นพอสมควรดังนั้นควรอ่านเอกสารและทดสอบกับมัน

ขั้นตอนที่ 2

ตอนนี้เราorg-modeฟังshackleด้วย Elisp เพิ่มเติมในไฟล์ init ของเรา ในการรับ*Org Src.*บัฟเฟอร์ให้ติดตามshackle-rules:

(setq org-src-window-setup 'other-window)

แหล่งที่มา

น่าเสียดายที่org-modeไม่มีการตั้งค่าแบบอะนา*Org todo*ล็อกสำหรับบัฟเฟอร์ การแฮ็กนี้ทำขึ้นเพื่อสิ่งนั้น (และอาจทำให้(setq org-src-window-setup 'other-window)ฟุ่มเฟือย แต่ใครบางคนที่มีความรู้มากกว่าจะต้องตีระฆัง):

;; Re-define org-switch-to-buffer-other-window to NOT use org-no-popups.
;; Primarily for compatibility with shackle.
(defun org-switch-to-buffer-other-window (args)
  "Switch to buffer in a second window on the current frame.
In particular, do not allow pop-up frames.
Returns the newly created buffer.
Redefined to allow pop-up windows."
  ;;  (org-no-popups
  ;;     (apply 'switch-to-buffer-other-window args)))
  (switch-to-buffer-other-window args))

แหล่งที่มา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.