如何優化草稿與發佈版,兩者協同編寫的效率?

困難

  • 假設在持續撰寫一份草稿D的同時,有發佈正式的版本P的需求
    • D與P的內容類似,但P不包含不確定或不完整的信息
      • 由於內容類似,若將D與P分成兩個檔案,修改一個heading時,兩個檔案必需分別修改,這不太方便

嘗試

Meld

  • 不支援超連結
  • 不支援org-mode
  • 不能在emacs裡操作

Drawer 或 Block

  • #+begin #+end 的部分有點妨礙閱讀
  • 當碰到整個heading不需要發佈時,高亮或排版就會出問題 Screenshot from 2023-08-17 21-23-51

在emacs -Q org-mode中的各種情況

  • 就有點亂 :smiling_face_with_tear:

org-noter

  • 基本上同等於將D和P分成兩個檔案

git branch

  • 雖然我不太會操作branch,但感覺跟將D和P分成兩個檔案沒什麼區別

ediff

  • 我摸不懂 :melting_face:
    • control buffer操作不太順手,因為主要會留在撰寫檔案的buffer
      • 可能重綁快捷鍵能夠解決
    • magit中stage可以作用在selection,ediff好像沒有

markup

  • 標記D中P的部分,然後寫一個minor-mode處理掉標記讓其他mode(org-mode)可以正常運作
    • 標記每一行是否為P
    • 若有inline D的需求,用特殊符號(≚)另外標記
  • 要能夠export標記的部分
P * Title
D - this is some draft not going to show
P - pubilsh stuff will be shown on both file
P - I gonna publish this line≚, without this secret≚
  • 總之先試著把P的部分highlight起來
    • export也能夠用相同的方法
(defface publish-mode-publish-face '((t :background "tomato4")) "Face for published content.")

(define-minor-mode publish-mode ()
  "Minor mode for highlighting draft and publish lines."
  :init-value nil
  (if publish-mode
      (progn
        (highlight-regexp  "^P .*$" 'publish-mode-publish-face)
        (highlight-regexp "≚.*?≚" 'default)
        )
    (progn
      (unhighlight-regexp "^P .*$")
      (unhighlight-regexp "≚.*?≚"))
    ))

Screenshot from 2023-08-17 19-56-58

問題

  1. minor-mode該怎麽處理掉開頭的標記 :confounded:
  • 標記放行末則會影響例如org-mode的tag和property等等
  1. 還是其實有其他好方法/工具?
  • 行注释:# this is a comment
  • 块注释:#+BEGIN_COMMENT
  • 保留高亮注释 subtree:加上 :noexport: 标签

参考:

1 个赞

我记得org-mode中可以给headline增加某个标记,可以在导出时忽略这个headline

这样,给草稿状态的D打上这样的标记就应该可以实现你的目标了。

塊註釋文中提到了會有高亮或排版的問題,用tag則可以處理subtree的部分。不過塊的#+BEGIN和#+END還是會有點妨礙閱讀,雖然可以將其隱藏,但行註釋有辦法不破壞高亮和排版嗎?

或是退而求其次全部都以一行為單位進行註釋 :smiling_face_with_tear:

對,tag可以做到,但會有非headline不行的問題 :confounded:

如果能用markup標記的話還可以省略org-mode的依賴,雖然我暫時沒有需求,但感覺能在其他mode底下使用是挺不錯的。

簡單寫了一個可以highlight comment,並隱藏#+begin/end_comment的mode。

寫的有點醜,但目前還堪用就懶得改了。

  • 如果有用其他overlay會衝突到。
  • highlight顯示錯誤就關掉重開 <M-p>。

因為都是用org-mode的註釋,所以輸出直接用org export就行,highlight的部分不會被輸出。

效果

code

(require 'org)

(defface publish-mode-publish-face '((t :background "gray22"))
  "Face for published content.")

(defun publish-mode-sensitive-region-hide (begin end)
  "Hide the text in the region between BEGIN and END."
  (interactive "r")
  (let ((inhibit-read-only t))
    (add-text-properties begin end '(proprietary-bolp t invisible t display ""))
    (font-lock-fontify-region begin end)))

(defun publish-mode-sensitive-region-reveal (begin end)
  "Reveal the hidden text in the region between BEGIN and END."
  (interactive "r")
  (let ((inhibit-read-only t))
    (remove-text-properties begin end '(proprietary-bolp invisible display))
    (font-lock-fontify-region begin end)))

(defun publish-mode-highlight-and-hide-comment-block ()
  "Highlight and hide the region between begin_comment and end_comment."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((points '()))
      (while (re-search-forward "#\\+begin_comment" nil t)
        (let* ((begin-pos (match-beginning 0))
               (begin-pos-end (line-end-position))
               (end-pos-end (re-search-forward "#\\+end_comment" nil t))
               (end-pos (match-beginning 0)))
          (push (list begin-pos begin-pos-end end-pos end-pos-end) points)))
      (dolist (p points)
        (let ((begin-pos (nth 0 p))
              (begin-pos-end (nth 1 p))
              (end-pos (nth 2 p))
              (end-pos-end (nth 3 p)))
          (overlay-put (make-overlay begin-pos end-pos-end) 'face 'publish-mode-publish-face)
          (publish-mode-sensitive-region-hide begin-pos (1+ begin-pos-end))
          (publish-mode-sensitive-region-hide end-pos (1+ end-pos-end)))))
    (message "Highlighted comment regions.")))

(defun publish-mode-remove-comment-highlights ()
  "Remove highlight from all comment regions."
  (interactive)
  (remove-overlays (point-min) (point-max)))

(defun publish-mode-highlight-commented-headlines ()
  "Highlight 'org-mode' commented headlines."
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward "^\\*+.*$" nil t)
      (when (org-in-commented-heading-p)
        (let ((begin-pos (match-beginning 0))
              (end-pos (org-end-of-subtree)))
          (overlay-put (make-overlay begin-pos end-pos) 'face 'publish-mode-publish-face))))))

(define-minor-mode publish-mode ()
  "Minor mode for highlighting draft and publish lines"
  :init-value nil
  (if publish-mode
      (progn
        (publish-mode-highlight-and-hide-comment-block)
        (publish-mode-highlight-commented-headlines))
    (save-excursion
      (publish-mode-remove-comment-highlights)
      (publish-mode-sensitive-region-reveal (point-min) (point-max)))))

(global-set-key (kbd "M-p") 'publish-mode)

(defun publish-mode-un-draft-block ()
  "Remove comment block when current mark is in comment block."
  (interactive)
  (when (org-between-regexps-p "#\\+begin_comment" "#\\+end_comment")
    (save-excursion
      (let ((begin (progn
                     (re-search-backward "#\\+begin_comment" nil t)
                     (delete-line)
                     (match-beginning 0)))
            (end (progn
                   (re-search-forward "#\\+end_comment" nil t)
                   (delete-line)
                   (forward-line -1)
                   (line-end-position))))
        (unless (org-in-commented-heading-p)
          (remove-overlays begin (1+ end)))))))