Simpler and I now have hooks to make it look like what I want.
14 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 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… to change how org renders a collapsed heading.
(setq org-pretty-entities t
org-ellipsis "⤵" ; …, ➡, ⚡, ▼, ↴, , ∞, ⬎, ⤷, ⤵
org-agenda-breadcrumbs-separator " ❱ "
org-catch-invisible-edits 'show-and-error
org-special-ctrl-a/e t ; Note: Need to get this working with Evil!
org-src-fontify-natively t ; Pretty code blocks
org-hide-emphasis-markers t)
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.")))
Typographic Quotes
According to Artur Malabarba of 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 Orgzly and Orgro.
Stealing his function so that “quotes” just work to insert rounded quotation marks:
(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))))
Stealing function for automatically adding a single quote (not in pairs):
(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)))))
Quote: “From this time forward, I shouldn’t have to worry about quotes.”
Note: I still need to worry about how quotes affect spell checking.
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)
(set-face-attribute 'org-level-2 nil :height 1.8)
(set-face-attribute 'org-level-3 nil :height 1.4)
(set-face-attribute 'org-level-4 nil :height 1.1))
While we are at it, let’s make sure the code blocks are using my fixed with font:
(when window-system
(dolist (face '(org-block org-code org-verbatim org-table org-drawer
org-special-keyword org-property-value org-document-info-keyword))
(set-face-attribute face nil :inherit 'fixed-pitch)))
Not sure why the above code removes the color of org-verbatim
, so let’s make it stand out slightly:
(set-face-attribute 'org-verbatim nil :foreground "#aaaacc")
And some slight adjustments to the way blocks are displayed:
(set-face-attribute 'org-block-begin-line nil :background "#282828")
(set-face-attribute 'org-block nil :height 0.95)
(set-face-attribute 'org-block-end-line nil :background "#262626")
And decrease the prominence of the property drawers:
(set-face-attribute 'org-drawer nil :height 0.8 :line-height 0.8)
(set-face-attribute 'org-property-value nil :height 0.85)
(set-face-attribute 'org-special-keyword nil :height 0.85)
This process allows us to use variable-pitch
mode for all org documents.
(use-package org
:hook (org-mode . variable-pitch-mode))
SVG-Based Prettiness
While I'm intrigued with Nicolas P. Rougier's notebook project, I really just want to steal their 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.
(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")
:config
(setq svg-tag-tags
'(("TODO:" . ((lambda (tag) (svg-tag-make "TODO" :face 'org-tag
:radius 2 :inverse t
:margin 0 :padding 0 :height 0.8))))
("NOTE:" . ((lambda (tag) (svg-tag-make "NOTE" :face 'font-lock-comment-face
:inverse nil :margin 0 :radius 2 :height 0.8))))
; The org-modern overrides this:
; ("#\\+RESULTS:" . ((lambda (tag) (svg-tag-make tag :beg 0 :end -1 :height 0.6))))
("\\(:[A-Z-]+\\):[a-zA-Z#0-9]+:" . ((lambda (tag)
(svg-tag-make tag :beg 1 :inverse t
:margin 0 :crop-right t))))
(":[A-Z-]+\\(:[a-zA-Z#0-9]+:\\)" . ((lambda (tag)
(svg-tag-make tag :beg 1 :end -1
:margin 0 :crop-left t))))
("\\(:[A-Z-]+:\\)[ \n]" . ((lambda (tag) (svg-tag-make tag :beg 1 :end -1 :margin 0))))))
(global-svg-tag-mode 1))
What does do? Here are some examples: TODO: Marks comments for tasks (this can be in source files too). NOTE: Highlights comments and other notes. :PROP:tag: are highlighted as two parts of the same tag And :TAG: with colons are highlighted, which include :PROPERTY: drawers.
When the project is more complete, I need to dive into this:
(use-package notebook
:straight (:type git :protocol ssh :host github :repo "rougier/notebook")
:after org
:hook (org-mode . notebook-mode))
In the interim, let’s use org-modern mode:
(use-package org-modern
:straight (:type git :protocol ssh :host github :repo "minad/org-modern")
:custom (org-modern-label-border 0.1
org-modern-variable-pitch t
org-modern-tag nil ; Letting svg-tag do this
org-modern-list . '((?+ . "◦")
(?- . "•")
(?* . "●")))
:config
(setq org-auto-align-tags nil
org-tags-column 0)
:hook
(org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda))
I liked the approach to the org-padding project in how it allowed granular tweaks to add extra padding. This package doesn’t work with org-modern
, but I may look more into it later.
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
Used to use org-tree-slide for showing org files as presentations. Converted to use org-present. I love the hooks as that makes it easier to pull out much of my demo-it
configuration. My concern with org-present
is that it only jumps from one top-level to another top-level header.
(use-package org-present
:init
(defvar ha-org-present-mode-line mode-line-format "Cache previous mode-line format state")
:config
(defun org-blocks-hide-headers ()
"Make the headers and other block metadata invisible. See `org-blocks-show-headers'."
(add-to-invisibility-spec 'ha-org-block-headers)
(defun hide-this (regexp)
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(let ((start (match-beginning 0)) (end (1+ (match-end 0))))
(overlay-put (make-overlay start end) 'invisible 'ha-org-block-headers))))
(defun hide-these (patterns)
(when patterns
(hide-this (car patterns))
(hide-these (cdr patterns))))
(save-excursion
(hide-these (list (rx bol (zero-or-more space)
"#+" (or "begin" "end") "_"
(one-or-more any) eol)
(rx bol (zero-or-more space)
"#+" (or "name" "header" "results" "property" "options"
"filetags") ":"
(zero-or-more any) eol)
(rx bol (zero-or-more space)
":" (or "properties" "header-args" "end") ":"
(zero-or-more any) eol)))))
(defun org-blocks-show-headers ()
"Un-invisibilize the headers and other block metadata invisible.
In other words, this undoes what `org-blocks-hide-headers' did."
(remove-from-invisibility-spec 'ha-org-block-headers))
(defun org-present-start ()
(goto-char (point-min)) (re-search-forward (rx bol "*"))
(org-blocks-hide-headers)
(org-present-big)
(setq mode-line-format nil)
(org-display-inline-images)
(blink-cursor-mode -1)
(setq cursor-type nil))
(defun org-present-end ()
(org-present-small)
(org-blocks-show-headers)
(setq mode-line-format ha-org-present-mode-line-format)
(setq cursor-type t)
(blink-cursor-mode 1)
(org-present-read-write))
:hook
(org-present-mode . org-present-start)
(org-present-mode-quit . org-present-end))