# Category Archives: org

## Turning an Org Mode outline into an HTML table with a column for more notes

The last time A- had a babysitter, I quickly scribbled down some ideas for activities that A- might enjoy. The babysitter found the list very helpful, so I figured I’d make a list that I could easily update as A-‘s interests change. I wanted a two-column table with space for notes, but I didn’t want to fiddle with LibreOffice or manually writing HTML. Org Mode to the rescue! To turn something like this:

* Activity ideas  :noexport:
** Gross motor
*** Balance on one leg
*** Coast on the balance bike
** Fine motor
*** Cut along a curve or shape
...


into a table like this:

I wrote this bit of code inside a #+begin_src emacs-lisp :exports results :results value html#+end_src block:

(let* ((elements (org-element-parse-buffer))
(activity-ideas
(org-element-contents
"Activity ideas"
(:parse-tree ,elements)))))
(format
"<table><tr><th width=\"50%%\">Activity ideas</th><th width=\"50%%\">Notes</th></tr>%s</table>"
(mapconcat
(lambda (section)
(format "<tr><td><h2>%s</h2><ul>%s</ul></td><td></td></tr>"
(org-element-property :raw-value section)
(mapconcat (lambda (idea)
(format "<li>%s</li>"
(org-element-property :raw-value idea)))
(org-element-contents section)
"")))
(org-element-contents activity-ideas)
"")))


I can then export the buffer to HTML and get my nice neat table by itself, since the data comes from a subtree with the :noexport: tag. The code parses the elements in the buffer, looks at the children under the “Activity ideas” header, turns each child into a table row, and turns the children of those nodes into list items.

The code coincidentally takes advantage of the org-export-resolve-link I wrote to help someone with an Org feature request. Yay for multipurpose code!

For the next step, I’ll probably put TODO state filtering in so that I can keep a long list of activities and then select a few for each category. It’s nice to have an outline I can easily update!

## Making a numpad-based hydra for categorizing Org list items

I like to categorize links for Emacs News so that it’s not an overwhelmingly long wall of text. After I’ve deleted duplicate links, there are around a hundred links left to categorize. I used to use Helm and some custom code to simplify moving Org list items into different categories in the same list. Then I can type “org” to move something to the Org Mode category and “dev” to move something to the Emacs development category.

When I don’t have a lot of computer time, I usually do this categorization by SSHing into my server from my phone. It’s hard to type on my phone, though. I thought a numpad-based Hydra might be better for quick entry, like a phone system. I wanted to be able to use the numeric keypad to sort items into the most common categories, with a few shortcuts for making it easier to organize. Here’s a list of shortcuts:

 0-9 Select options from the list, with 0 for other. \/ Opens the URL in a web browser , Selects a category by name, creating as needed \* Shows the URL in the messages buffer, and toggles it – Deletes the item . Quits

Here’s what the Helm version looked like on the left, and here’s the new numpad-powered one on the right. I liked how fewer buttons made it easier to hit the right one when I’m sorting on my phone. I can add new categories with completion. Because I assigned numbers to specific categories instead of having them automatically calculated based on the headings in the list, it was easy to get into the rhythm of tapping 6 for Org, 7 for coding, and so on.

Here’s the code that makes it happen. I experimented with dynamically defining a hydra using eval and defmacro so that I could more easily define the menu in a variable. It seems to work fine so far.

(defvar my/org-categorize-emacs-news-menu
'(("0" . "Other")
("1" . "Emacs Lisp")
("2" . "Emacs development")
("3" . "Emacs configuration")
("4" . "Appearance")
("6" . "Org Mode")
("7" . "Coding")
("8" . "Community")
("9" . "Spacemacs")))

(defun my/org-move-current-item-to-category (category)
"Move current list item under CATEGORY earlier in the list.
CATEGORY can be a string or a list of the form (text indent regexp).
Point should be on the next line to process, even if a new category
has been inserted."
(interactive "MCategory: ")
(when category
(let* ((beg (line-beginning-position))
(end (line-end-position))
(string (org-trim (buffer-substring-no-properties beg end)))
(category-text (if (stringp category) category (elt category 0)))
(category-indent (if (stringp category) 2 (+ 2 (elt category 1))))
(category-regexp (if (stringp category) category (elt category 2)))
(pos (point))
s)
(delete-region beg (min (1+ end) (point-max)))
(unless (string= category-text "x")
(if (re-search-backward category-regexp nil t)
(forward-line 1)
(setq s (concat "- " category-text "\n"))
(insert s)
(setq pos (+ (length s) pos)))
(insert (make-string category-indent ?\ )
string "\n")
(goto-char (+ pos (length string) category-indent 1))
(recenter)))))

(eval
(defhydra my/org-categorize-emacs-news (global-map "C-c e")
,@(mapcar
(lambda (x)
(,(car x)
(lambda () (interactive) (my/org-move-current-item-to-category ,(concat (cdr x) ":")))
,(cdr x)))
(","
(lambda () (interactive)
(my/org-move-current-item-to-category
"By string")
("/" (lambda () (interactive)
(save-excursion
(backward-char)
(org-open-at-point)))
"Open")
("*"
(lambda () (interactive)
(if (string= (buffer-name) "*Messages*")
(bury-buffer)
(save-excursion
(message (match-string 1)))
(switch-to-buffer "*Messages*")))
"Show URL")
("-" kill-whole-line "Kill")
("." nil "Done")))

Let’s see how it holds up next week!

## Adding :target option for the TOC keyword in Org Mode

Now that A- can be counted on to happily play with a babysitter for several hours once a week, I’ve decided to alternate consulting and personal projects. Two weeks ago, I used my personal time to make a script that renewed my library books automatically. This week, I set aside time to look at Org Mode. DC had asked me to update the patch I made to allow people to specify a target for the table of contents, and I was curious about whether I could hack something together.

Patch for adding :target to TOC keyword

Here’s a sample file that shows what I mean:

#+OPTIONS: toc:nil
* Not this section
* Target
:PROPERTIES:
:CUSTOM_ID: TargetSection
:END:
* Another section


Here’s the core of how to make it work for HTML exports:

(defun org-html-keyword (keyword _contents info)
"Transcode a KEYWORD element from Org to HTML.
CONTENTS is nil.  INFO is a plist holding contextual information."
(let ((key (org-element-property :key keyword))
(value (org-element-property :value keyword)))
(cond
((string= key "HTML") value)
((string= key "TOC")
(let ((case-fold-search t))
(cond
(let ((depth (and (string-match "\\<[0-9]+\\>" value)
(string-to-number (match-string 0 value))))
(scope
(cond
((string-match ":target +\"\$$[^\"]+\$$\"" value)
(save-excursion
(_ nil))))
;; local
((string-match-p "\\<local\\>" value) keyword))))
(org-html-toc depth info scope)))
((string= "listings" value) (org-html-list-of-listings info))
((string= "tables" value) (org-html-list-of-tables info))))))))


It was a lot of fun Doing the Right Thing(s): writing documentation, adding tests, and making it work for more than just HTML export. I found out where to make the changes by using grep to search for TOC in the Org Mode source code. All the heavy lifting was already done by org-export-collect-headlines, so it was just a matter of passing the right scope. It took me a while to figure out that I needed to pass an Org link element. An easy way of making that element work for both fuzzy and ID-specific links was to insert the target text into a temporary buffer (remembering to use org-make-link-string) and then calling org-element-link-parser.

I tried figuring out how to make it work with a link to another file, but I didn’t get very far, so I figured I’d just wrap things up nicely there.

I wasn’t sure if my original post made it through because I sent it through Gmane and Cc:d DC, who got it with an empty To:, so I ended up submitting it twice. I just realized I forgot to add test-ox-ascii.el. I don’t want to spam the list, so I’ll send that along with other changes if people have feedback.

But look! Open source contributions! I’m so excited. I wonder what I’ll get to do in two weeks from now. =)

## Labeling toy storage bins with photos and text using ImageMagick and org-babel

I wanted to make labels for A-‘s new toy storage: three low Trofast drawer frames all along the wall.

I liked how early childhood drop-in centres labeled their shelves with both pictures and text. That way, kids can find things before she can read, while still being exposed to print. I took pictures of the bin contents and renamed the files to the labels I wanted to put on them, such as 2x2 blocks.jpg. (We have a lot of Duplo.)

This time, I experimented with creating the labels entirely in Imagemagick instead of using LaTeX. First, I used a table in Org Mode to let me easily play with the dimensions and recalculate pixel sizes.

 DPI 300 Columns 3 Rows 5 Paper width 14 4200 Paper height 8.5 2550 Minimum margins 0.5 150 Label width 4.3333333 1300 Label length 1.5 450

I passed the width and the height to the following code block by using header arguments. I liked using 400 pixels as the height instead of 450, so that’s what I used. My source image size was 4032×3024 pixels. If I resize them to a height of 400, that gives me a width of 533. Allowing 20 pixels for the text left and right borders gives me (- 1300 533 20 20) = 727 as the text width.

#+begin_src sh :dir ~/code/labels :var width=1300 :var textwidth=727 :var height=400 :var pointsize=72 :results silent
for x in source/*; do
file=$(basename "$x")
/usr/local/bin/convert $$\( "source/file" -resize x{height}$$ \
$$-background white -fill black -font Alegreya-Regular -bordercolor White \ -gravity West -border 20 -pointsize pointsize -size {textwidth}x caption:"{file%.*}"$$ \
+append \) \
-extent ${width}x${height} \
$$-fill none -stroke gray -draw "rectangle 0 0 (echo width - 1 | bc) (echo height - 1 | bc)"$$ \
"out/\$file.png"
done
#+end_src

Sample resized label:

I moved the ones I wanted from the out directory to a ready directory and combined the ones I wanted to print into a PDF:

#+begin_src sh :dir ~/code/labels :results silent
montage ready/*.png -tile 3x5 -background none -geometry +0+0 print.png
convert print*.png -density 300 -quality 100 print.pdf
#+end_src


Then I printed the labels in colour on an 8.5×14″ sheet of paper (single-sided, landscape), cut them out, and taped them onto the bins with packing tape.

W- suggested taking macro shots that more clearly show the characteristics of things in the bins instead of just aiming down and taking pictures of the contents. Might be a good excuse to show A- basic product photography when we get back.

W- also recommended making the label text bigger. The first time I did it, I just picked a pointsize based on whatever fit the ones I wanted to print. I decided against letting Imagemagick maximize the font size because I didn’t want labels to have very different text sizes. After a little poking around, I figured out how to use caption: instead of label: to give me text that can neatly wrap within a given space, and that will probably let me use 90-point font instead of 72-point font. That will make the next iteration of labels even easier to read.

It’s nice having all these bins. A- is getting pretty good at heading straight for the bin she wants something from, and she even talks about them: “Horse is in animals bin.” I’m glad we labeled the most frequently used bins. I’ll tweak the labels when we get back from our trip. We’ll probably change some of the bin contents anyway.

Hooray for ImageMagick, and hooray for variables in org-babel blocks!

## Making an 8-page 7″x4.25″ captioned photo book with Org Mode and LaTeX

Here’s another technique that makes a simple photo book. I wanted to
make an 8-page book that could be printed 4 pages to a 8.5″x14″ sheet
(duplex, flip along the short edge), with a final page size of
7″x4.25″.

Sample with my own photos:

## Prerequisites

• ImageMagick
• Texlive (probably)
• latex-beamer
• Org Mode and Emacs

## Process

We can define the labels and their captions in a named table like this:

 Let’s Go for a Walk Caption for photo 1 placeholder.png Caption for photo 2 placeholder.png Caption for photo 3 placeholder.png Caption for photo 4 placeholder.png Caption for photo 5 placeholder.png

Note that the first page is row #1 this time, instead of starting with
the last page.

Then we generate the LaTeX code with some Emacs Lisp, like so:

#+begin_src emacs-lisp :var pages=story :results value latex :exports results
(mapconcat (lambda (row) (format "\\graphicframe{%s}{%s}" (cadr row) (org-export-string-as (car row) 'latex t))) pages "\n")
#+end_src


I put that in a subtree for easier exporting with C-c C-e C-s l b (org-export-dispatch, subtree, LaTeX, Beamer).

## Process

• Set up Org Mode export to Beamer
(eval-after-load "ox-latex"
;; update the list of LaTeX classes and associated header (encoding, etc.)
;; and structure
("beamer"
,(concat "\\documentclass[presentation]{beamer}\n"
"[DEFAULT-PACKAGES]"
"[PACKAGES]"
"[EXTRA]\n")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))


This file gets included in the LaTeX file for the children’s book.
Tweak it to change the appearance. In this example, I use black serif
text text on the left side of a picture, both occupying roughly half
of the page. I also experimented with using a different font this time, which you might need to install (for me, I did apt-get install texlive-fonts-extra).

\geometry{paperwidth=7in,paperheight=4.25in,left=0.5in,right=0.5in}
\usepackage{etoolbox}
\usepackage[T1]{fontenc}
\usepackage{Alegreya}
\usefonttheme{serif}
\setbeamercolor{normal text}{fg=black,bg=white}
\setbeamercolor{structure}{fg=black,bg=white}
%% \setbeamertemplate{frametitle}
%% {
%%   \begin{center}
%%   \noindent
%%   \insertframetitle
%%   \end{center}
%% }
\newcommand{\graphicframe}[2] {
{
%% \if #1\empty
%% \usebackgroundtemplate{}
%% \fi
\ifstrempty{#1}{
\begin{frame}[plain]
\begin{center}
\noindent
\textbf{\huge{#2}}
\end{center}
\end{frame}
}{
\begin{frame}[plain]
\begin{columns}
\begin{column}{0.48\textwidth}
\huge{#2}
\end{column}
\begin{column}{0.48\textwidth}
\includegraphics[height=\textheight,width=\textwidth,keepaspectratio=true]{#1}
\end{column}
\end{columns}
\end{frame}
}
}
}
\usepackage[noframe]{showframe}
\renewcommand{\maketitle}{}

• Create the PDF
pdflatex index.tex

• Create one PNG per page
mkdir pages
convert -density 300 index.pdf -quality 100 pages/page%d.png

• Create the 4-up imposition

The diagram at https://pressnostress.com/iw/howto/booklets/1.html was helpful.

montage $$page4.png -rotate 180$$ $$page3.png -rotate 180$$ page7.png page0.png -tile 2x2 -mode Concatenate front.png
montage $$page2.png -rotate 180$$ $$page5.png -rotate 180$$ page1.png page6.png -tile 2x2 -mode Concatenate back.png
convert front.png back.png -density 300 ../print.pdf


## Other notes

Placeholder image from https://en.wikipedia.org/wiki/File:Portrait_placeholder.png – public domain.

## Story

• It’s time to make a smoothie!
• I pour blueberries into the blender.
• Mama blends it all with some water.
• I peel and add a banana.
• Mama blends it again.
• Yum yum!

## Process

• Prerequisites

• ImageMagick
• Texlive (probably)
• latex-beamer
• Org Mode and Emacs
• Set up Org Mode export to Beamer

(eval-after-load "ox-latex"
;; update the list of LaTeX classes and associated header (encoding, etc.)
;; and structure
("beamer"
,(concat "\\documentclass[presentation]{beamer}\n"
"[DEFAULT-PACKAGES]"
"[PACKAGES]"
"[EXTRA]\n")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))


• Set up image directories

mkdir text-pages blank-spreads drawn drawn-pages


 text-pages Will contain one image per page of just the plain text. blank-spreads Will contain text spreads ready for drawing drawn Export one image per spread (without the text layers) from your drawing program drawn-pages Will contain one image per page combining text and drawing

This file gets included in the LaTeX file for the children’s book. Tweak it to change the appearance. In this example, I use black serif text at the bottom of the page.

\geometry{paperwidth=7in,paperheight=8.5in,left=0.5in,top=0.5in,right=0.5in,bottom=0.5in}
\setbeamercolor{normal text}{fg=black,bg=white}
\setbeamercolor{structure}{fg=black,bg=white}
\usefonttheme{serif}
\setbeamertemplate{frametitle}
{
\begin{center}
\vspace{0.7\textheight}
\noindent
\insertframetitle
\end{center}
}
\usepackage[noframe]{showframe}
\renewcommand{\maketitle}{}


• Write the story

I used Org Mode to make it easy to write the story.

Some considerations:

• Because we’re printing this as a saddle-stitched booklet, the number of lines should be a multiple of four. Sixteen is probably a good maximum.
• The first heading is actually for the last page.
• The second heading is for the cover page.
• The third heading is for the first inner page, the fourth heading is for the second inner page, and so on.
#+OPTIONS:   TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc author:nil date:nil
#+OPTIONS: H:1
#+startup: beamer
#+LaTeX_CLASS: beamer
#+LaTeX_CLASS_OPTIONS: [20pt]
#+BEAMER_FRAME_LEVEL: 1

* Story

**
**
**
** It's time to make a smoothie!
** I pour blueberries into the blender.
** Mama blends it all with some water.
** I peel and add a banana.
** Mama blends it again.
** Yum yum!


• Make the tex, PDF, page PNGs, and spread PNGs

1. Go to the subtree for the story and use M-x org-export-dispatch (C-c C-e) with the subtree option (C-s) to export it as a Beamer file (option l b).
2. Use pdflatex to convert the .tex to PDF.

pdflatex index.tex


3. Create one PNG per text page with:

convert -density 300 index.pdf -quality 100 text-pages/page%02d.png


4. Create spreads to draw on with:

montage text-pages/page*.png -tile 2x1 -mode Concatenate blank-spreads/spread%d.png


5. Optionally, create a layered PSD with:

convert blank-spreads/spread*.png $$-clone 1,0 -background white -flatten -alpha off$$ -reverse spreads-for-drawing.psd


• Draw

I imported the PNG layers into MediBang Paint on a Samsung Note 8 Android phone, and then:

• imported photos
• traced them
• hid the text layers
• exported one PNG per spread to QuickPic, renamed them, and uploaded them to Dropbox, because I couldn’t figure out how to export to Dropbox directly

Layer folders were handy for organizing spread-related images. I couldn’t seem to move all of the layers in a layer folder together on Android, but the iPad was able to do so. If I didn’t have the iPad handy, I combined the layers by exporting a PNG and then importeing it back into MediBang Paint.

This was a decent setup that allowed me to draw and paint even when I was in bed nursing A- and waiting for her to fall asleep. I held the phone with one hand and rotated the canvas as needed so that it was easier for me to draw lines with my right. Because of the awkward position and the small screen size, the lines are not as smooth as I might like, but the important thing is that they’re there. Whee! =)

It turns out to be possible to use the free MediBang Pro drawing program under Wine on Linux to import the PSD and save it to the cloud. I was also sometimes able to switch to drawing with iPad Pro with Pencil, but it was harder to find time to do that because that usually made A- want to draw too.

Anyway, after I drew and exported the PNGs, the next step was to…

• Convert the drawn spreads back to pages and combine them with the text

Here’s some code that combines the drawing and the text. Keeping the drawing and the text separate until this stage (instead of exporting the PNGs with the text) makes it easier to change the text later by recreating the text PNGs and running this step.

(defun my/combine-spread-drawing-and-text (page num-pages)
(let ((gravity (if (= (% page 2) 1) "West" "East"))
(spread (/ (% page num-pages) 2)))
(shell-command
(format
(concat "convert \$$" "drawn/spread%d.png -gravity %s " "-chop 50%%x0 +repage \$$ "
"text-pages/page%02d.png -compose darken "
"-composite drawn-pages/page%02d.png")

(cl-loop for i from 0 to (1- pages) do


This code pairs up the drawn pages into a PDF that can be printed duplex. Make sure to choose the option to flip along the short edge. I hard-coded the page orders for 4-, 8-, 12-, and 16-page booklets.

(let* ((page-order
'((0 1 2 3)   ; hard-coded page sequences
(0 1 2 7 6 3 4 5)
(0 1 2 11 10 3 4 9 8 5 6 7)
(0 1 2 15 14 3 4 13 12 5 6 11 10 7 8 9)))
(sequence
(mapconcat (lambda (d) (format "drawn-pages/page%02d.png" d))
(elt page-order (1- (/ pages 4))) " ")))
(shell-command
(format
"montage %s -tile 2x1 -mode Concatenate print-duplex-short-edge-flip.pdf"
sequence)))


• Print and bind

After printing and folding the book, I used tape to make the book hold together. Tada!

• Create on-screen PDF for reading

A little bit of manipulation so that the last page is in the right place:

(shell-command
(format "convert %s onscreen.pdf"
(mapconcat 'identity (cl-loop for i from 1 to pages
collect (format "drawn-pages/page%02d.png" (% i pages))) " ")))


(cl-loop
for i from 0 to (1- (/ pages 2)) do
(shell-command
(format
(concat "convert "
"\$$blank-spreads/spread%d.png " "drawn/spread%d.png " "-compose darken " "-resize %dx -flatten \$$ "
"\$$+clone -background black -shadow 50x1+%d+%d \$$ "
"+swap -compose src-over -composite "
`