hamacs/ha-org-word-processor.org
Howard Abrams ee2eab464d Increase/Decrease the "font size" of the frame
While the `text-scale-increase` works fine for a single window, if I
want the font for the entire window, I needed something else. Added it
to the "Window" Hydra, so it could be a pink toggle.

While I was at it, I changed more `ha/` to `ha-` ... consistency!
2021-11-11 21:05:41 -08:00

8.8 KiB

Org As A Word Processor

A literate programming file for making Org file more readable.

Introduction

I like having org-mode files look more like editing in a word processor than having it look like programming code. But that is just me.

General Org Settings

Since I use ellipsis in my writing… I like to change how org renders a collapsed heading.

  (setq org-pretty-entities t
        org-ellipsis "⤵"     ; …, ➡, ⚡, ▼, ↴, , ∞, ⬎, ⤷, ⤵
        org-agenda-breadcrumbs-separator " ❱ "
        org-src-fontify-natively t ;; Pretty code blocks
        org-hide-emphasis-markers t)

Org Beautify

I really want to use the Org Beautify package, but it overrides my darker themes (and all I really want is headlines to behave).

First step is to make all Org header levels to use the variable font, and be the same color as the default text:

(when window-system
  (let ((default-color (face-attribute 'default :foreground)))
    (dolist (face '(org-level-1 org-level-2 org-level-3 org-level-4 org-level-5 org-level-6 org-level-7 org-level-8))
      (set-face-attribute face nil
                          :foreground default-color :weight 'bold :font ha-variable-font))))

Next, we just need to change the header sizes:

(when window-system
  (set-face-attribute 'org-level-1 nil :height 2.2 :inherit 'default)
  (set-face-attribute 'org-level-2 nil :height 1.8 :inherit 'default)
  (set-face-attribute 'org-level-3 nil :height 1.4 :inherit 'default)
  (set-face-attribute 'org-level-4 nil :height 1.1 :inherit 'default))

Superstar

Now that headers are noticeable, I have no reason to see a number of asterisks. Once I used the org-bullets package, but believe we've replaced it with org-superstar-mode, so the following is an improvement, especially with the sub-bullets:

(use-package org-superstar
  :init
  (add-hook 'org-mode 'org-superstar-mode)
  (setq org-superstar-headline-bullets-list '("▶")
        org-superstar-special-todo-items t
        org-superstar-todo-bullet-alist t
        org-superstar-prettify-item-bullets t
        org-superstar-item-bullet-alist '((42 . "⊙")   ; *
                                          (43 . "⁍")   ; +
                                          (45 . "•"))))

Oh, and as I indent lists, they should change the bulleting in a particular sequence. If I begin with an * asterisk, I walk down the chain, but with the dashed bullets (my default choice), I just stay with dashed bullets. Numeric bullets should cycle:

(setq org-list-demote-modify-bullet '(("*" . "+") ("+" . "-") ("-" . "-")
                                      ("1." . "a.") ("a." . "1.")))

Since the following code does not work like I would have expected:

(setq org-hide-leading-stars t)

I add a hook to standard Org, and since this is a Lisp-2, I can get away with:

(defun org-hide-leading-stars ()
  (let* ((keyword
          `(("^\\(\\*+ \\)\\s-*\\S-" ; Do not hide empty headings!
             (1 (put-text-property (match-beginning 1) (match-end 1) 'invisible t)
                nil)))))
    (font-lock-add-keywords nil keyword)))

  (add-hook 'org-mode-hook 'org-hide-leading-stars)

Checkboxes

According to an idea by Huy Trần, we can prettify the list checkboxes as well:

(defun ha-org-prettify-checkboxes ()
  "Beautify Org Checkbox Symbol"
  (push '("[ ]" . "☐") prettify-symbols-alist)
  (push '("[X]" . "☒") prettify-symbols-alist)
  (push '("[-]" . "☐-") prettify-symbols-alist)
  (prettify-symbols-mode))

And now we can attach it to a newly loaded org files:

(add-hook 'org-mode-hook 'ha-org-prettify-checkboxes)

To make it more distinguishable, he also changed the colors:

(defface org-checkbox-done-text
  '((t (:foreground "#71696A" :strike-through t)))
  "Face for the text part of a checked org-mode checkbox.")

(font-lock-add-keywords
 'org-mode
 `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)"
    1 'org-checkbox-done-text prepend))
 'append)

Padding

The org-padding project looks places extra space before and after headers and blocks (essentially leading), to create a more word-processor-y experience. Great idea, however, I have spent a lot of extra time entering blank lines before and after my headers and blocks:

(use-package org-padding
  :straight (org-padding :type git :host github :repo "TonCherAmi/org-padding")
  :hook
  (org-mode . org-padding-mode)
  :config
  (setq org-padding-block-begin-line-padding '(0.5 . 0.3)
        org-padding-block-end-line-padding '(0.1 . 0.5)
        org-padding-heading-padding-alist
        '((4.0 . 1.5) (3.0 . 0.5) (3.0 . 0.5) (3.0 . 0.5) (2.5 . 0.5) (2.0 . 0.5) (1.5 . 0.5) (0.5 . 0.5))))

However, I'm just going to have to write a function to clean this.

(defun ha-remove-superfluous-org-padding ()
  (interactive)
  (goto-char (point-min))
  (ha-remove-org-header-padding)
  (goto-char (point-min))
  (ha-remove-org-block-padding))

(defun ha-remove-org-header-padding ()
  ;; (goto-char (point-min))
  (while (re-search-forward (rx (optional bol (zero-or-more space) eol "\n")
                                (group bol (one-or-more "*") (one-or-more space) (one-or-more any) "\n")
                                (optional bol (zero-or-more space) eol "\n")) nil t)
    (replace-match (match-string 1) nil :no-error)))

(defun ha-remove-org-block-padding ()
  ;; (goto-char (point-min))
  (while (re-search-forward (rx (optional bol (zero-or-more space) eol "\n")
                                (group bol (zero-or-more space) "#+BEGIN" (one-or-more any) eol "\n"
                                       (zero-or-more (group bol (zero-or-more any) eol "\n"))
                                       bol (zero-or-more space) "#+END" (zero-or-more any) eol "\n")
                                (optional bol (zero-or-more space) eol "\n")) nil t)
    (replace-match (match-string 1) nil :no-error)))

Now that is some complicated regular expressions.

Pasting

I like the idea that I will paste HTML text from the clipboard and have it converted to org-formatted text:

(defun ha-org-paste ()
  (interactive)
  (if (eq system-type 'gnu/linux)
      (shell-command "xclip -t text/html -o | pandoc -r html -w org" t)))

Presentations

The org-tree-slide still seems to be the best presentation tool for Org files, but I really need to issue a pull request to fix a few warnings.

(use-package org-tree-slide
    :init
    (setq org-tree-slide-skip-outline-level 4)
    :config
    (org-tree-slide-simple-profile))