Làm thế nào để kiểm soát nơi bộ đệm từ khóa org todo hiển thị?


9

Q : làm thế nào tôi có thể kiểm soát nơi orgbộ đệm từ khóa todo xuất hiện?

Nhập todotừ khóa bằng C-c C-t( org-todo) sẽ mở bộ đệm mới với các tùy chọn từ khóa và sau đó đóng lại sau khi tôi chọn một từ khóa. Càng xa càng tốt. Tuy nhiên, phải mất một cửa sổ khác để làm như vậy, điều này ít tốt hơn, đặc biệt là vì nó thực sự chỉ cần hiển thị một hoặc hai dòng với các từ khóa.

Vì vậy, với cách bố trí sau, nhấn C-c C-ttrong khi ở cửa sổ bên trái ( some-org-buffer) sẽ mở *Org todo*trong cửa sổ bên phải:

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

Thay vào đó, tôi muốn có một cửa sổ nhỏ bật lên dưới dạng phân chia theo chiều dọc, như dưới đây:

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

Nắm bắt từ câu trả lời này , tôi đã viết một chức năng để đưa vào 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))

Tuy nhiên, điều đó không làm việc. Thở dài. Tôi đã làm gì sai với display-buffer-alist? Hơn nữa, làm cách nào để todobộ đệm từ khóa của tôi bật lên nơi tôi muốn?


Không phải là một câu trả lời cho câu hỏi của bạn, nhưng bạn có thể muốn xem xét sửa đổi org-switch-to-buffer-other-windowđể làm những gì bạn muốn - bạn có thể tạo một điều kiện làm bất cứ điều gì bạn muốn.
luật

@lawlist: cảm ơn, tôi đã đào xung quanh và tìm hiểu về org-switch-to-buffer-other-windowvà một loạt các orgbộ phận xấu xí khác . Xem câu trả lời cho "giải pháp".
Dân

Trong khi kết hợp tất cả những điều này vào .emacs của tôi, tôi đã xem xét kỹ chức năng định vị của bạn và tôi cảm thấy như mình đang thiếu một cái gì đó liên quan đến định nghĩa của bạn win. Có một lý do bạn không thể chỉ sử dụng (selected-window)ở đây?
Aaron Harris

@AaronHarris: chưa thử nó; Tôi đã (nhẹ) điều chỉnh một câu trả lời từ một bài đăng khác sử dụng cơ chế này. Cung cấp cho nó một shot và xem nếu nó hoạt động.
Dan

@Dan: Đúng, nó hoạt động. Tôi chỉ hơi lo lắng rằng một số tình huống phạt góc sẽ khiến nó nổ tung. Và cảm ơn vì chức năng đó, btw. Nó thực hiện chính xác những gì tôi muốn nó làm và tôi không nghĩ mình có thể nói rõ đó là điều tôi muốn trước khi xem câu hỏi này.
Aaron Harris

Câu trả lời:


4

Thở dài. Tôi đã tìm thấy một "giải pháp", nhưng đó là một giải pháp xấu xí đòi hỏi phải ghi đè một orgchức năng hiện có . Tôi muốn một cái không yêu cầu sửa đổi orgmã nguồn, nhưng sẽ đưa kết quả đào khảo cổ của tôi vào đây trong trường hợp bất kỳ ai khác có thể sử dụng nó.

Như tôi đã nhận thấy trong quá khứ với các orgchức năng khác , org-modekhá quan tâm về cách nó xử lý các cửa sổ.

Chôn sâu trong mã nguồn của org-todomột lệnh gọi hàm org-fast-todo-selection. Lần lượt, hàm đó gọi org-switch-to-buffer-other-window, có chuỗi doc đọc, một phần:

Chuyển sang bộ đệm trong cửa sổ thứ hai trên khung hiện tại. Đặc biệt, không cho phép các khung bật lên .

À ồ.

Được rồi, tôi sẽ cắn: chúng ta hãy nhìn vào org-switch-to-buffer-other-window. Nó sử dụng org-no-popups macro. Chuỗi doc của nó đọc, một phần:

Bỏ qua các cửa sổ bật lên. Hãy liên kết một số biến để không xung quanh CƠ THỂ ...

Nó chỉ ra rằng đó display-buffer-alistlà một trong những biến liên letkết đến nil.

( Đầu nổ tung. )

Cuối cùng, chúng ta có thể làm cho nó không bỏ qua display-buffer-alistbằng cách chỉnh sửa org-fast-todo-selectionvà thay thế org-switch-to-buffer-other-windowdòng bằng cũ 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)))))))

Bạn có thể sử dụng cl fletở đây để rebind org-switch-to-buffer-other-window? Tự hỏi nếu bạn có thể tư vấn hoặc bọc khác org-fast-todo-selectionhơn là ghi đè lên nó.
glucas

@glucas: ý kiến ​​hay. Đã thử nó và không thể làm cho nó hoạt động, mặc dù.
Dân

1
@Dan, tôi đã có thể làm cho nó hoạt động bằng cách xác định lại org-switch-to-buffer-other-windowchỉ (switch-to-buffer-other-window args). Tôi cũng loại bỏ &restkhỏi các đối số chức năng.
sk8ingdom

3

Gần đây tôi đã tìm ra cách để chụp chế độ Org trong một khung hình mới . Sửa đổi mã để sử dụng chức năng của bạn là khá đơn giản. Đây là cách tôi làm:

(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)

Để hoàn thiện hơn, đây là định nghĩa của my/with-advicemacro từ câu trả lời khác:

(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

Nhìn vào cấu hình của người khác , tôi tìm thấy một cách để kiểm soát vị trí *Org Src.**Org todo*bộ đệm xuất hiện. Bây giờ khi tôi nhấn C-c C-thoặc C-c 'các bộ đệm này hiển thị trong một cửa sổ mới ở cuối bố cục cửa sổ hiện tại của tôi và chọn trạng thái TODO hoặc nhấn C-c '( org-edit-src-exit) sẽ trả cấu hình cửa sổ của tôi về bố cục ban đầu.

Giải pháp này liên quan đến việc sử dụng cùm và một số Elisp:

Bước 1

Tải xuống shackletừ MELPA. Đây là cách tôi thiết lập nó use-packagetrong tệp init của mình:

(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))

Các cài đặt quan trọng ở đây là:

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

Nguồn

Đặc biệt lưu ý không gian giữa "*Orgtrên dòng dưới cùng. Tôi chưa thử nghiệm cài đặt :alignở các vị trí khác, nhưng shacklecó vẻ khá linh hoạt, vì vậy, đáng để đọc tài liệu và thử nghiệm với nó.

Bước 2

Bây giờ chúng tôi org-modelắng nghe shacklevới một số Elisp trong tệp init của chúng tôi. Để có được *Org Src.*bộ đệm để làm theo shackle-rules:

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

Nguồn

Thật không may org-mode, không cung cấp một thiết lập tương tự cho *Org todo*bộ đệm. Hack này bù đắp cho điều đó (và có thể làm cho (setq org-src-window-setup 'other-window)thừa, nhưng ai đó hiểu biết hơn sẽ phải kêu gọi):

;; 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))

Nguồn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.