setup emacs (with journaling) on your phone
guide to setup emacs and org-capture shortcut on an android
Hover over a footnote to read it in-place
Install termux and emacs
Where the files lives
Emacs can write in two kinds of places on termux:
- The termux home, for example
~/Documents/org/. It stays inside termux's directory, and other apps can't read it. -
System storage, for example
/storage/emulated/0/Documents/org/. Other apps can read it too. You need to runtermux-setup-storageto get access to ittermux-setup-storage
Its best to keep them in a shared directory if you want your files to be shared or synced2 between devices.
Porting your config over to your phone
Emacs reads its config from the termux home, either ~/.emacs.d/ or ~/.config/emacs/.3 It's easier to keep the same layout as your computer.
You can bring your own existing config, here are some ways:
- git:
git clone <url> ~/.config/emacs - ssh:
scp -r config/ phone:~/.config/emacs, withsshdon the phone.4 - adb:
adb push config /sdcard/Download/, thencp -rvin termux. - USB-OTG: copy with the android file manager, then
cp -rvin termux.
It's best to not copy the packages or cache folders. Let emacs install its packages on the phone.5
Android specific emacs tweaks
Know that you're in termux
(defvar my/termux-p (or (getenv "TERMUX_VERSION")
(file-exists-p "/data/data/com.termux")))The environment variable alone isnt enough as termux only sets it in shells started by it.6
Wrap the GUI-only parts
Fonts, transparency, margins, and image sizes only matter in a GUI. You can wrap them:
(unless my/termux-p
(setq doom-font (font-spec :family "SF Mono" :size 14))
(add-to-list 'default-frame-alist '(alpha-background . 85)))If the journal is on shared storage, you'll also want to keep emacs litter out of it.7
(when my/termux-p
(let ((auto (expand-file-name "auto-save/" user-emacs-directory))
(backup (expand-file-name "backups/" user-emacs-directory)))
(make-directory auto t)
(make-directory backup t)
(setq create-lockfiles nil
backup-directory-alist `(("." . ,backup))
auto-save-file-name-transforms `((".*" ,auto t)))))Clipboard if you like it
Emacs can use the android clipboard through Termux:API.8
pkg install termux-api(when (and my/termux-p (require 'xclip nil t))
(xclip-mode 1))
You can point org-directory at the folder you picked in section 2, and doom users can drop it in ~/.config/doom/config.el.9
Pick a capture method
Your journal can be one or more org files. org-capture appends to one file. org-journal writes multiple files based on your config.
Here's a small setup for each
org-journal: one file per day
org-journal reads the date from the filename, so the format needs %Y, %m, and %d.10
(setq org-journal-dir "~/Documents/org/journal/"
org-journal-file-format "%Y%m%d"
org-journal-date-format "%A, %m/%d/%Y")
Doom's (org +journal) flag turns this on and gives you SPC n j j. Other configs usually bind org-journal-new-entry somewhere.
org-capture: one file
(setq org-capture-templates
`(("j" "Journal Entry" entry
(file+olp+datetree ,(expand-file-name "Journal.org" org-directory))
"* %<%H:%M>\n%?"
:empty-lines 1
:unnarrowed t)))
Newer org deprecates file+datetree, so this uses file+olp+datetree.11 Doom binds SPC X j for it.
Either way, C-c C-c files the entry, and C-c C-k throws it away. Closing the terminal does neither.12
One tap capture
And finally, a home screen shortcut that opens a capture in a new emacs frame.
Prep termux
Install Termux:Widget from the same source as termux. The widget runs scripts through termux, so termux must allow commands from other apps, and a warm daemon to reduce boot times.
echo "allow-external-apps=true" >> ~/.termux/termux.properties
termux-reload-settings
emacs --daemonThe shortcut script
Save this as ~/.shortcuts/Journal and make it executable. The filename becomes the label on the home screen.13
#!/data/data/com.termux/files/usr/bin/bash
export PREFIX=/data/data/com.termux/files/usr
export HOME=/data/data/com.termux/files/home
export PATH=$PREFIX/bin:/system/bin
export LD_LIBRARY_PATH=$PREFIX/lib
export TERM=xterm-256color
# start a daemon if the server is not up yet
emacsclient --eval t >/dev/null 2>&1 || emacs --daemon
for _ in $(seq 1 40); do
emacsclient --eval t >/dev/null 2>&1 && break
sleep 0.25
done
emacsclient -t --eval '(progn (setq my/capture-return-home t) (org-capture nil "j"))'
# a dead frame can leave the daemon stuck inside the capture
if ! timeout 5 emacsclient --eval '(condition-case nil
(dolist (b (buffer-list))
(when (string-prefix-p "CAPTURE-" (buffer-name b))
(with-current-buffer b (org-capture-kill))))
(error nil))' >/dev/null 2>&1; then
pkill -x emacs
fi
am start -a android.intent.action.MAIN -c android.intent.category.HOME >/dev/null 2>&1The script expects a small flag and a hook in your config, so the frame closes after the capture:14
(defvar my/capture-return-home nil)
(defun my/journal-capture-finish (&rest _)
(when my/capture-return-home
(setq my/capture-return-home nil)
(delete-frame)))
(advice-add 'org-capture-finalize :after #'my/journal-capture-finish)
(advice-add 'org-capture-kill :after #'my/journal-capture-finish)Add the widget
Long press the home screen, open the widget list, find Termux:Widget, and drag the shortcut to a free spot. Pick Journal. A tap opens today's entry.15
Footnotes
Other resources
Guides that cover similar teritory:
- Bring your Emacs to Android - If you decide to get the android gui instead
- Surprisingly, Emacs on Android is pretty good
- Capturing an org-mode entry using speech to text - a very cool shortcut, but I prefer not to speak my Journal out loud when I'm out and about lol
- Emacs and Org-Roam on Android with Termux extra keys - absolute ball knowledge, go here after setting up emacs on termux, I love his websites design too
- Use Emacs in GUI mode on Android - tiny article on running emacs x11 version on termux
- Emacs on Android, use with Termux - a cocktail of mixing android app and termux binaries
- Setting up Doom Emacs in Termux
- Emacs: keep journaling on the go - a completely different approach, html instead of emacs
- Emacs with speechd-el on Termux - espeak for emacs, seems platform agnostic
More References:
- GNU Emacs Android manual
- Termux:Widget
- Termux storage
- org-capture manual
- Why F-Droid, not Play Store
- Syncthing-Android fork
- OnyX, an Android Emacs config (archived)
- Orgzly and organice if you want an app instead.
The GUI app is a different emacs. It has its own config directory, so termux config and packages don't carry over. Doom doesn't officially support it yet. It also can't use git, ripgrep, and other termux programs. The terminal one feels more at-home and is easier for things like shortcuts
Some options are Syncthing, git, Nextcloud, or a USB copy. If you sync, it's safer to change one copy at a time and have a versioning system in the sync tool.
If both ~/.emacs.d/ and ~/.config/emacs/ exist, emacs uses ~/.emacs.d/. Doom keeps its own files in ~/.config/emacs and your private config in ~/.config/doom.
If you'd like ssh, run pkg install openssh and then sshd in termux. It listens on port 8022, and you can connect via ssh -p 8022 <user>@<phone-ip>.
You only need the init files and config folders your setup uses, for example init.el, early-init.el, lisp/, and snippets/. It's best to skip .local/, elpa/, eln-cache/, and straight/, since they're machine specific. Doom users can just copy ~/.config/doom and run doom sync 😎
Termux only exports TERMUX_VERSION to the shells it starts. An emacs started over ssh, or by the widget may not see it. The data directory is a more reliable way
Syncthing treats lock files and autosaves as changes. They add noise and can cause conflicts. Keeping them inside user-emacs-directory means they wont reach the shared folder.
Termux:API is an app plus a package. Install both from the same source as termux. xclip.el has a termux backend, and doom's :os tty module loads it for you. For a non-doom config, install xclip from ELPA if not already
The line is (setq org-directory "/storage/emulated/0/Documents/org/") for shared storage, or ~/Documents/org/ for the termux home. Doom's private config is in ~/.config/doom/. In non-doom emacs, put it in init.el.
A daily journal needs %Y, %m, and %d in the filename. A weekly journal needs %G and %V or the date parts, a monthly one needs %Y and %m, and a yearly one only needs %Y. This is also why org-journal can't keep a single lifetime file.
file+olp+datetree is the current name for the old file+datetree. The path can be absolute or built from org-directory with expand-file-name. :unnarrowed keeps the whole file visible, so you can scroll back to earlier entries while you write.
Closing the session leaves the entry unsaved. C-c C-c writes it to the file. C-c C-k aborts, and org may put the text in the kill ring instead of the file. Neither is a save.
~/.shortcuts holds shortcuts that run in a terminal session. The file needs execute permission, so run chmod 700 ~/.shortcuts/Journal. The am start at the end needs "Display over other apps" for termux on android 10 and later, or the launcher can stay behind the terminal.
emacsclient -t opens a terminal frame. Finishing or aborting deletes that frame, so you land back on the launcher. If the frame dies first, the daemon can be stuck inside the capture and stop answering. The timeout clears the capture, or restarts emacs.
For org-journal, replace the org-capture call with org-journal-new-entry. Whatever you use, finish with C-c C-c. The back button and closing the session do not save.
Webmention this page
Leave a comment
Powered by zapiska - webmentions & comments for your IndieWeb needs!