2021-11-02 00:27:14 +00:00
#+TITLE : Org As A Word Processor
#+AUTHOR : Howard X. Abrams
#+DATE : 2020-09-10
#+FILETAGS : :emacs:
A literate programming file for making Org file more readable.
#+BEGIN_SRC emacs-lisp :exports none
2022-03-09 18:45:37 +00:00
;;; ha-org-word-processor --- Making Org file more readable. -*- lexical-binding: t; -* -
;;
;; © 2020-2022 Howard X. Abrams
;; This work is licensed under a Creative Commons Attribution 4.0 International License.
;; See http://creativecommons.org/licenses/by/4.0/
;;
;; Author: Howard X. Abrams <http://gitlab.com/howardabrams >
;; Maintainer: Howard X. Abrams
;; Created: September 10, 2020
;;
;; This file is not part of GNU Emacs.
;;
;; *NB:* Do not edit this file. Instead, edit the original literate file at:
;; ~/other/hamacs/ha-org-word-processor.org
;; Using `find-file-at-point', and tangle the file to recreate this one .
;;
;;; Code:
2021-11-02 00:27:14 +00:00
#+END_SRC
* Introduction
2022-03-10 01:14:21 +00:00
I like having org-mode files look more like a word processor than having it look like programming code. But that is just me.
2021-11-02 00:27:14 +00:00
* General Org Settings
2022-03-10 01:14:21 +00:00
Since I use ellipsis in my writing… to /change/ how org renders a collapsed heading.
2021-11-02 00:27:14 +00:00
#+BEGIN_SRC emacs-lisp
(setq org-pretty-entities t
org-ellipsis "⤵" ; …, ➡, ⚡, ▼, ↴, , ∞, ⬎, ⤷, ⤵
org-agenda-breadcrumbs-separator " ❱ "
org-src-fontify-natively t ;; Pretty code blocks
org-hide-emphasis-markers t)
#+END_SRC
2022-02-17 17:50:34 +00:00
** Typographic Quotes
According to [[http://endlessparentheses.com/prettify-your-quotation-marks.html ][Artur Malabarba ]] of [[http://endlessparentheses.com/prettify-you-apostrophes.html ][Endless Parenthesis ]] blog, I type a /straight quote/ , ", Emacs actually inserts Unicode rounded quotes, like “this”. This idea isn’ t how a file is /displayed/ , but actually how the file is /made/ . Time will tell if this idea works with my auxiliary functions on my phone, like [[https://play.google.com/store/apps/details?id=com.orgzly&hl=en_US&gl=US ][Orgzly ]] and [[https://github.com/amake/orgro ][Orgro ]].
Stealing his function so that “quotes” just work to insert /rounded/ quotation marks:
#+BEGIN_SRC emacs-lisp
(define-key org-mode-map "\"" #'endless/round-quotes)
(defun endless/round-quotes (italicize)
"Insert “” and leave point in the middle.
With prefix argument ITALICIZE, insert /“”/ instead
\(meant for org-mode).
Inside a code-block, just call `self-insert-command'."
(interactive "P")
(if (and (derived-mode-p 'org-mode)
(org-in-block-p '("src" "latex" "html")))
(call-interactively #'self-insert-command)
(if (looking-at "”[/=_\\*]?")
(goto-char (match-end 0))
(when italicize
(if (derived-mode-p 'markdown-mode)
(insert "__")
(insert "//"))
(forward-char -1))
(insert "“”")
(forward-char -1))))
#+END_SRC
Stealing function for automatically adding a single quote (not in pairs):
#+BEGIN_SRC emacs-lisp
(define-key org-mode-map "'" #'endless/apostrophe)
(defun endless/apostrophe (opening)
"Insert ’ in prose or `self-insert-command' in code.
With prefix argument OPENING, insert ‘ ’ instead and
leave point in the middle.
Inside a code-block, just call `self-insert-command'."
(interactive "P")
(if (and (derived-mode-p 'org-mode)
(org-in-block-p '("src" "latex" "html")))
(call-interactively #'self-insert-command)
(if (looking-at "['’ ][=_/\\*]?")
(goto-char (match-end 0))
(if (null opening)
(insert "’ ")
(insert "‘ ’ ")
(forward-char -1)))))
#+END_SRC
Quote: “From this time forward, I shouldn’ t have to worry about quotes.”
*Note:* I still need to worry about how quotes affect [[file:ha-org.org::*Spell Checking ][spell checking ]].
2021-11-02 00:27:14 +00:00
* 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:
#+BEGIN_SRC emacs-lisp
(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
2021-11-12 05:05:41 +00:00
:foreground default-color :weight 'bold :font ha-variable-font))))
2021-11-02 00:27:14 +00:00
#+END_SRC
Next, we just need to change the header sizes:
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
2022-03-09 06:01:59 +00:00
While we are at it, let’ s make sure the code blocks are using my fixed with font:
#+BEGIN_SRC emacs-lisp
(use-package mixed-pitch
:init (setq mixed-pitch-set-height t)
:hook (org-mode . mixed-pitch-mode))
#+END_SRC
2021-11-02 00:27:14 +00:00
* Superstar
Now that headers are noticeable, I have no reason to see a number of asterisks. Once I used the [[https://github.com/sabof/org-bullets ][org-bullets ]] package, but believe we've replaced it with [[https://github.com/integral-dw/org-superstar-mode ][org-superstar-mode ]], so the following is an improvement, especially with the sub-bullets:
#+BEGIN_SRC emacs-lisp
2021-12-27 17:27:25 +00:00
(use-package org-superstar
2021-12-27 18:13:21 +00:00
:after org
2021-12-27 17:27:25 +00:00
:straight (:type git :protocol ssh :host github :repo "integral-dw/org-superstar-mode")
2021-12-27 18:13:21 +00:00
:hook (org-mode . org-superstar-mode)
2021-12-27 17:27:25 +00:00
:init
2022-03-03 23:16:50 +00:00
(setq ; org-superstar-headline-bullets-list '("▶")
2021-12-27 17:27:25 +00:00
org-superstar-special-todo-items nil
org-superstar-todo-bullet-alist t
org-superstar-prettify-item-bullets t
2022-03-03 23:16:50 +00:00
org-superstar-item-bullet-alist '((42 . "●") ; *
(43 . "○") ; +
2021-12-27 18:13:21 +00:00
(45 . "•"))))
2021-11-02 00:27:14 +00:00
#+END_SRC
2021-12-27 18:13:21 +00:00
If this works, then we get the prettier bulleted list:
* Top bullets
* Plus bullets:
+ Apples
+ Oranges
+ Bananas
* Minus bullets:
- Dogs
- Cats
- Birds
2021-11-02 00:27:14 +00:00
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:
#+BEGIN_SRC emacs-lisp
(setq org-list-demote-modify-bullet '(("*" . "+") ("+ " . "-") ("-" . "-")
("1." . "a.") ("a." . "1.")))
#+END_SRC
Since the following code does not work like I would have expected:
#+BEGIN_SRC emacs-lisp :tangle no
(setq org-hide-leading-stars t)
#+END_SRC
I add a hook to standard Org, and since this is a Lisp-2, I can get away with:
2022-03-03 23:16:50 +00:00
#+BEGIN_SRC emacs-lisp :tangle no
2021-11-02 00:27:14 +00:00
(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)
#+END_SRC
* Checkboxes
According to an idea by [[https://jft.home.blog/2019/07/17/use-unicode-symbol-to-display-org-mode-checkboxes/ ][Huy Trần ]], we can prettify the list checkboxes as well:
#+BEGIN_SRC emacs-lisp
2021-11-12 05:05:41 +00:00
(defun ha-org-prettify-checkboxes ()
2021-11-02 00:27:14 +00:00
"Beautify Org Checkbox Symbol"
(push '("[ ]" . "☐") prettify-symbols-alist)
(push '("[X]" . "☒") prettify-symbols-alist)
(push '("[-]" . "☐-") prettify-symbols-alist)
(prettify-symbols-mode))
#+END_SRC
And now we can attach it to a newly loaded org files:
#+BEGIN_SRC emacs-lisp
2021-11-12 05:05:41 +00:00
(add-hook 'org-mode-hook 'ha-org-prettify-checkboxes)
2021-11-02 00:27:14 +00:00
#+END_SRC
To make it more distinguishable, he also changed the colors:
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
2022-03-09 04:43:25 +00:00
* SVG-Based Prettiness
While I'm intrigued with [[https://github.com/rougier ][Nicolas P. Rougier ]]'s [[https://github.com/rougier/notebook-mode ][notebook project ]], I really just want to steal their [[https://github.com/rougier/svg-lib ][svg-lib project ]] that allows me to create and display various SVG objects, namely tags, progress bars, progress pies and icons. Each object fits nicely in a text buffer ensuring width is an integer multiple of character width.
#+BEGIN_SRC emacs-lisp
(use-package svg-lib
:straight (:type git :protocol ssh :host github :repo "rougier/svg-lib"))
(use-package svg-tag-mode
:straight (:type git :protocol ssh :host github :repo "rougier/svg-tag-mode"))
(use-package notebook
:straight (:type git :protocol ssh :host github :repo "rougier/notebook")
:after org
:hook (org-mode . notebook-mode))
#+END_SRC
2021-11-02 00:27:14 +00:00
* Padding
The [[https://github.com/TonCherAmi/org-padding ][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:
#+BEGIN_SRC emacs-lisp
(use-package org-padding
2021-12-27 17:27:25 +00:00
:straight (:type git :protocol ssh :host github :repo "TonCherAmi/org-padding")
2021-11-02 00:27:14 +00:00
: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))))
#+END_SRC
However, I'm just going to have to write a function to clean this.
#+BEGIN_SRC emacs-lisp
2021-11-12 05:05:41 +00:00
(defun ha-remove-superfluous-org-padding ()
2021-11-02 00:27:14 +00:00
(interactive)
(goto-char (point-min))
2021-11-12 05:05:41 +00:00
(ha-remove-org-header-padding)
2021-11-02 00:27:14 +00:00
(goto-char (point-min))
2021-11-12 05:05:41 +00:00
(ha-remove-org-block-padding))
2021-11-02 00:27:14 +00:00
2021-11-12 05:05:41 +00:00
(defun ha-remove-org-header-padding ()
2021-11-02 00:27:14 +00:00
;; (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)))
2021-11-12 05:05:41 +00:00
(defun ha-remove-org-block-padding ()
2021-11-02 00:27:14 +00:00
;; (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)))
#+END_SRC
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:
#+BEGIN_SRC emacs-lisp :results silent
2021-11-12 05:05:41 +00:00
(defun ha-org-paste ()
2021-11-02 00:27:14 +00:00
(interactive)
(if (eq system-type 'gnu/linux)
(shell-command "xclip -t text/html -o | pandoc -r html -w org" t)))
#+END_SRC
* Presentations
The [[https://github.com/takaxp/org-tree-slide ][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.
#+BEGIN_SRC emacs-lisp
(use-package org-tree-slide
:init
(setq org-tree-slide-skip-outline-level 4)
:config
(org-tree-slide-simple-profile))
#+END_SRC
* Technical Artifacts :noexport:
Let's provide a name so that the file can be required:
#+BEGIN_SRC emacs-lisp :exports none
(provide 'ha-org-word-processor)
;;; ha-org-word-processor.el ends here
#+END_SRC
Before you can build this on a new system, make sure that you put the cursor over any of these properties, and hit: ~C-c C-c~
#+DESCRIPTION : A literate programming file for making Org file more readable.
#+PROPERTY : header-args:sh :tangle no
#+PROPERTY : header-args:emacs-lisp :tangle yes
#+PROPERTY : header-args :results none :eval no-export :comments no
#+OPTIONS : num:nil toc:nil todo:nil tasks:nil tags:nil date:nil
#+OPTIONS : skip:nil author:nil email:nil creator:nil timestamp:nil
#+INFOJS_OPT : view:nil toc:nil ltoc:t mouse:underline buttons:0 path:http://orgmode.org/org-info.js