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

簡單寫了一個可以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)))))))