Complete Computing Environment: Long Form

Table of Contents

Long Form writing with Org-mode

I really enjoy, when I have the time, to do long-form writing on my blog1 and in a private Org-mode journal. One of my biggest struggles has always been trying to externalize my thoughts and feelings, and long-form writing has been the thing that causes the biggest single improvement. Even here, distilling why I do what I do in to words has made these choices all the more clear to myself, and have given me ideas on how to expand this, not even considering the usefulness this will have for others.

My long-form lives in a few places at this point, primarily blog and a private journal, as mentioned above. The blog is built on top of Org-page2, a neat little static site generate built on top of Org's export system. You can do this directly with Org's export system3, but generating RSS from individual pages isn't a thing that can happen apparently, and things like automatic blog index generation don't happen and, well, those are things I shouldn't need to do. And org-page does them, and does a pretty decent job at it.

The rest of my long-form simply lives in an ~/org/ along with personal information, plans, and short thoughts, which since it's encrypted doesn't end up in my Agendas or anything like that. Emacs's EPG library4 makes editing GPG encrypted files entirely seamless, just make sure /tmp is a ramdisk :)

(provide 'cce-writing)

Spell checking is the code linting of prose; flyspell does a good job at it, though it requires ispell to be installed.

(require 'flyspell)
(diminish 'flyspell-mode "✓")
(add-hook 'text-mode-hook 'turn-on-flyspell)
(add-hook 'org-mode-hook 'turn-on-flyspell 'append)
- name: ispell installed
    name: iamerican-huge
    state: installed
  when: ansible_pkg_mgr == "apt"

Sometimes I work with Markdown mode, markdown should always open in markdown-mode.

(install-pkgs '(markdown-mode))
(autoload 'markdown-mode "markdown-mode"
  "Major mode for editing Markdown files" t)
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.mkd\\'" . markdown-mode))

Configuring Org-page itself is kind of, well, underdocumented. Thankfully, all of the variables are mostly self-documenting in regards to their names.

(install-pkgs '(org-page))
(require 'org-page)
(setq op/repository-directory "/home/rrix/Projects/")
(setq op/site-domain "")
(setq op/theme-root-directory "/home/rrix/Projects/")
(setq op/site-main-title "Computer :(")
(setq op/site-sub-title "/home/rrix")
(setq op/theme 'mdo)
(setq op/personal-github-link "")
(setq op/personal-google-analytics-id "UA-30162624-1")

These are the Export formats that I use regularly: HTML, Markdown and ASCII. I want to write one for Phabricator's remarkup5 bullshit, some day.

(require 'ox-html)
(require 'ox-md)
(require 'ox-ascii)
(require 'ox-org)

Display inline images after you run a Babel execution.

(add-hook 'org-babel-after-execute-hook 'bh/display-inline-images 'append)
(defun bh/display-inline-images ()
  (condition-case nil
    (error nil)))

Configure what languages we want to use for org-babel

(org-babel-do-load-languages 'org-babel-load-languages
                             '((emacs-lisp . t)
                               (dot . t)
                               (ditaa . t)
                               (python . t)
                               (ledger . t)
                               (ruby . t)
                               (gnuplot . t)
                               (clojure . t)
                               (shell . t)
                               (org . t)
                               (js . t)))

Output to a lowercase'd results block.

(setq org-babel-results-keyword "results")

Do not prompt to confirm evaluation. This may be dangerous - make sure you understand the consequences. I'm of two minds here; on the one hand, hanging to confirm every source block is terrible, but on the other hand, I'd like to have some modicum of security. In reality, I should set this only for my own files somehow.

(setq org-confirm-babel-evaluate nil)

Always show inline images on startup and in HTML output.

(setq org-startup-with-inline-images t)
(setq org-html-inline-images t)
(defun bh/make-org-scratch ()
  (find-file "/tmp/publish/")
  (gnus-make-directory "/tmp/publish"))

Create footnotes inline instead of in a separate heading at the end of the file.

(setq org-footnote-define-inline t)

Install emoji support in to Emacs, very very important. 🔥

(install-pkgs '(company-emoji))
- name: symbola installed
    name: "gdouros-symbola-fonts"
    state: installed
  when: ansible_pkg_mgr == "dnf"

- name: symbola installed
    name: "ttf-ancient-fonts"
    state: installed
  when: ansible_distribution == "Debian"

- name: symbola installed
    name: "fonts-symbola"
    state: installed
  when: ansible_distribution == "Ubuntu"

Use Symbola for the Emojis. 🙌 🙌 🙌

(when (version< emacs-version "25.0")
    (install-pkgs '(emoji-fontset))
    (emoji-fontset-enable "Symbola"))

We insert a CSS file in to the files I org-export.

(defun cce/org-inline-css-hook (exporter)
  "Insert custom inline css"
  (when (eq exporter 'html)
    (let* ((dir (ignore-errors (file-name-directory (buffer-file-name))))
           (path (concat dir "style.css"))
           (homestyle (or (null dir) (null (file-exists-p path))))
           (final (if homestyle "~/org/style.css" path))) ;; <- set your own style file path
      (setq org-html-head-include-default-style nil)
      (setq org-html-head (concat
                           "<style type=\"text/css\">\n"
                             (insert-file-contents final)

(add-hook 'org-export-before-processing-hook 'cce/org-inline-css-hook)

Publishing Projects

I should use publishing projects as a site to showcase my projects, and a way to showcase my org-mode config. In the long term, I'd like to move all of my sites to this model, but I think that the blog is going to be tough; I can generate the blog index and stuff via org-page, and then do the org bits using Publish, but for now we'll minimize that, since it seems pretty pointless.

Project list

  • projects -> -> an index of my projects
  • org -> -> a published version of my org-mode literate configuration
(setq org-publish-project-alist
         :base-directory "~/Code/"
         :publishing-directory "/"
         :recursive t
         :table-of-contents nil
         :section-numbers nil
         :base-extension "org"
         :publishing-function org-html-publish-to-html)
         :base-directory "~/Code/"
         :publishing-directory "/"
         :base-extension "css\\|pdf\\|png\\|jpg\\|gif\\|html"
         :publishing-function org-publish-attachment
         :recursive t
         :author nil)
         :components ("portfolio-org" "portfolio-extra"))
         :base-directory "~/Code/"
         :publishing-directory "/"
         :recursive t
         :table-of-contents nil
         :section-numbers nil
         :base-extension "org"
         :publishing-function org-html-publish-to-html)
         :base-directory "~/Code/"
         :publishing-directory "/"
         :base-extension "css\\|pdf\\|png\\|jpg\\|gif"
         :publishing-function org-publish-attachment
         :recursive t
         :author nil)
         :components ("projects-org" "projects-extra"))
         :base-directory "/tmp/publish/"
         :publishing-directory "/"
         :recursive t
         :section-numbers nil
         :table-of-contents nil
         :base-extension "org"
         :publishing-function (org-html-publish-to-html org-org-publish-to-org)
         :plain-source t
         :htmlized-source t
         :style-include-default nil
         :auto-sitemap t
         :sitemap-filename "index.html"
         :sitemap-title "Test Publishing Area"
         :sitemap-style tree
         :author-info t
         :creator-info t)
         :base-directory "~/sync/cce/"
         :publishing-directory "/"
         :recursive t
         :table-of-contents t
         :section-numbers nil
         :base-extenshion "org"
         :publishing-function org-html-publish-to-html)
         :base-directory "~/sync/cce/"
         :publishing-directory "/"
         :base-extension "css\\|pdf\\|png\\|jpg\\|gif"
         :publishing-function org-publish-attachment
         :recursive t
         :author nil)
         :components ("org-org" "org-extra"))))

This function is bound to C-S-F12 and will publish the project which a file belongs to.

(defun bh/save-then-publish (&optional force)
  (interactive "P")
  (let ((org-html-head-extra)
        (org-html-validation-link "<a href=\"\">Validate XHTML 1.0</a>"))
    (org-publish-current-project force)))
(global-set-key (kbd "C-s-<f12>") 'bh/save-then-publish)

(setq org-html-xml-declaration '(("html" . "")
                                 ("was-html" . "<?xml version=\"1.0\" encoding=\"%s\"?>")
                                 ("php" . "<?php echo \"<?xml version=\\\"1.0\\\" encoding=\\\"%s\\\" ?>\"; ?>")))
(setq org-export-allow-BIND t)

Medium-form writing with Org-mode

One thing that I am experimenting with right now, is a sort of "short-notes" system, similar to a blog but limited to exporting a single paragraph, and to be heavily marked up with microformats so that IndieWeb sites can use them; in the long-term these will supersede my direct usage of Twitter/Facebook/Instagram, with content coming out of my Org-mode, exported to HTML and RSS, and then syndicated to other sites via Bridgy.

It currently just lives in my home directory, not even pushed to git:

(add-to-list 'load-path (expand-file-name "~/Code/notes"))
(condition-case nil
  (require 'arcology)
  (error (message (format "I guess we don't have arcology available."))

Using it is quite simple: I hit C-c _ to call the mfblog capture template, I write my shortnote, and then mark it as DONE with C-t d, and then call mfblog:gen, which will generate the site and push it to my server.

This function, cce/insert-image takes a URL, downloads it locally and attaches it to the current task; I use this to quickly copy files from my phone in to Arcology.

(defun cce/insert-image (url)
  (interactive "sURL? ")
  (let ((id (org-id-new)))
    (shell-command (format "wget '%s' -O /tmp/%s.jpg" url id))
    (org-attach-attach (format "/tmp/%s.jpg" id))))

Thinking and Feeling with org-brain

(install-pkgs '(org-brain))

Capture template

(push '("b" "Brain" plain (function org-brain-goto-end)
        "* %i%?" :empty-lines 1)


(defhydra cce/hydra-brain ()
  "Org Brain's limbs"
  ("v" org-brain-visualize "Visualize")
  ("o" org-brain-goto-current "Open")
  ("c" org-brain-add-child "Child")
  ("h" org-brain-add-child-headline "Child Headline")
  ("f" org-brain-add-friendshpi "Friendship"))

(evil-leader/set-key "v" 'cce/hydra-brain/body)

(define-key org-brain-visualize-mode-map
            (kbd "<SPC>v")


Author: Ryan Rix

Created: 2019-11-26 Tue 04:20

Validate XHTML 1.0