When using Orgzly Revived with the git repository features on Android and git-sync on other machines, format changes by Orgzly to the underlying org file cause frequent merge conflicts.
Enforces blank-line and whitespace conventions that keep org files byte-for-byte identical between Emacs and Orgzly Revived (the Android org client), eliminating spurious git diffs produced by Orgzly’s own auto-formatter.
Orgzly silently reformats org files on every edit. Even for entries not changed by Orgzly:
- Adds a blank line after entries that have content
- Adds a blank line after entries that have only a properties drawer
- Puts exactly one blank line between an entry’s heading (or its planning line) and the body text under it
- Removes extra trailing blank lines at end-of-file
Each of these appears as a one-line diff in git, causing merge conflicts when the same file is edited in both Emacs and Orgzly.
orgzly-formatter runs as a before-save-hook and pre-emptively applies the
same rules Orgzly would, so the files Emacs writes are already in Orgzly’s
preferred format. Orgzly then has nothing to change.
| Rule | Description |
|---|---|
| R1 | Exactly one blank line before each heading (except at buffer start). A heading immediately preceded by another empty heading gets no blank line. |
| R2 | One blank line between a drawer :END: and the body text that follows it. A drawer that ends a section (no body follows) is left unchanged, and so is a drawer before the first heading, which Orgzly keeps as written. After the property drawer of an entry’s head, R5 sets the gap. |
| R3 | Exactly one blank line at the end of every entry that has content (planning, drawer, or body). Heading-only entries get no trailing blank. |
| R4 | Planning keywords (CLOSED / DEADLINE / SCHEDULED) on the line after a heading are rewritten in Orgzly’s canonical order — CLOSED DEADLINE SCHEDULED, single-space separated. Existing indentation is preserved. |
| R5 | Exactly one blank line between an entry’s head (its heading line, any planning line under it, which needs a timestamp, and a :PROPERTIES: drawer under those) and the body text that follows; surplus blank lines are removed. Orgzly writes a drawer, a CLOCK: line or a log note (- State …, - Note taken on …) directly under the head, so the blank lines before one are removed. Matching is case-sensitive, as in Orgzly. An entry whose planning line Org reads but Orgzly does not (a diary sexp such as <%%(diary-float t 4 2)>) is left alone, so Emacs keeps it scheduled. |
| WS | Trailing whitespace stripped from every line, including a carriage return before the newline. Exception: =* NEXT = (keyword-only heading with a single trailing space) is preserved — org needs it. |
| EOF | Buffer ends with exactly one blank line. |
The formatter is idempotent: running it on an already-correct buffer produces no changes.
Formatting in Orgzly can be changed via Settings -> Sync -> Org file format. This package considers the default settings of:
- Separate note with an empty line
- Multiline notes only
- Separate header and content
- true
- Emacs 27.1+
- Org 9.7+
(use-package orgzly-formatter
:straight (:host github :repo "stfl/orgzly-formatter.el")
:hook (org-mode . orgzly-formatter-mode))In packages.el:
(package! orgzly-formatter
:recipe (:host github :repo "stfl/orgzly-formatter.el"))In config.el:
(use-package orgzly-formatter
:hook (org-mode . orgzly-formatter-mode))Then run doom sync and restart Emacs.
;; Activates orgzly-formatter-mode in every org-mode buffer via hook.
(orgzly-formatter-global-setup)M-x orgzly-formatter-buffer(with-eval-after-load 'ws-butler
(add-to-list 'ws-butler-global-exempt-modes 'org-mode))