This package implements a modern style for your Org buffers using font locking
and text properties. The package styles headlines, keywords, tables and source
blocks. The styling is configurable, you can disable or modify the style of each
syntax element individually via the org-modern
customization group.
The screenshots shows example.org with org-modern-mode
turned on and off. The
elegant theme featured in the screenshot is modus-operandi.
Since this package adjusts text styling, it depends on your font settings. You
should ensure that your variable-pitch
and fixed-pitch
fonts combine
harmonically and have approximately the same height. As default font, I
recommend variants of the Iosevka font, e.g., Iosevka Term Curly.
org-modern-mode
tries to adjust the tag label display based on the value of
line-spacing
. This looks best if line-spacing
has a value between 0.1 and 0.4 in
the Org buffer. Larger values of line-spacing
are not recommended, since Emacs
does not center the text vertically (see Emacs bug#76390).
The package is available on GNU ELPA and MELPA. You can install the package with
package-install
. Then org-modern
can be enabled manually in an Org buffer by
invoking M-x org-modern-mode
. In order to enable org-modern
for all your Org
buffers, add org-modern-mode
to the Org mode hooks.
;; Option 1: Per buffer
(add-hook 'org-mode-hook #'org-modern-mode)
(add-hook 'org-agenda-finalize-hook #'org-modern-agenda)
;; Option 2: Globally
(with-eval-after-load 'org (global-org-modern-mode))
Try the following more extensive setup in emacs -Q
to reproduce the looks of the
screenshot above after the installation of org-modern
.
;; Minimal UI
(package-initialize)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(modus-themes-load-operandi)
;; Choose some fonts
;; (set-face-attribute 'default nil :family "Iosevka")
;; (set-face-attribute 'variable-pitch nil :family "Iosevka Aile")
;; (set-face-attribute 'org-modern-symbol nil :family "Iosevka")
;; Add frame borders and window dividers
(modify-all-frames-parameters
'((right-divider-width . 40)
(internal-border-width . 40)))
(dolist (face '(window-divider
window-divider-first-pixel
window-divider-last-pixel))
(face-spec-reset-face face)
(set-face-foreground face (face-attribute 'default :background)))
(set-face-background 'fringe (face-attribute 'default :background))
(setq
;; Edit settings
org-auto-align-tags nil
org-tags-column 0
org-catch-invisible-edits 'show-and-error
org-special-ctrl-a/e t
org-insert-heading-respect-content t
;; Org styling, hide markup etc.
org-hide-emphasis-markers t
org-pretty-entities t
org-agenda-tags-column 0
org-ellipsis "…")
(global-org-modern-mode)
An alternative setup, using use-package
and modifying some of the display entities:
(use-package org-modern
:custom
(org-modern-block-indent t) ; to enable org-modern-indent when org-indent is active
(org-modern-hide-stars nil)
(org-modern-todo-faces
'(("STARTED" :foreground "yellow")
("CANCELED" org-special-keyword :inverse-video t :weight bold)))
(org-modern-list
'((?* . "•")
(?+ . "‣")))
(org-modern-fold-stars
'(("▶" . "▼")
("▷" . "▽")
("▸" . "▾")
("▹" . "▿")))
(org-modern-checkbox
'((?X . "✔")
(?- . "┅")
(?\s . " ")))
(org-modern-label-border 1)
:hook
(org-mode . org-modern-mode)
(org-agenda-finalize . org-modern-agenda))
Since version 2.0, this package also incorporates org-modern-indent
, which
provides block bracket styling when org-indent-mode
is enabled, including
support for “bulk-indented” blocks nested within plain lists:
org-modern-indent
is disabled by org-modern
by default. Configure
org-modern-block-indent=t
to enable. To activate org-indent-mode
in all org
files, set org-startup-indented=t
.
Note: Currently org-modern-indent
requires zero line-spacing
, as it leads to
gaps in the vertical bars drawn to indicate blocks, but hopefully this can be
improved in the future.
Bulk-indented blocks have “real” (space/tab) indentation applied and managed by
org. This extra indentation is applied by org on top of the (fake, prefix-based)
indentation used by org-indent. To nest blocks properly within such indented
content, e.g. in plain list items, you only have to begin the #+begin
at the
same level as the list element’s text.
As an important principle, org-modern-indent
does not alter the contents of the
text in your org documents, not even indentation. It just styles what is there.
To help achieve proper block bulk-indented alignment, here are a few ways to
alter blocks indentation using org and other commands:
- Start things right: Hit return after your last line of text (e.g in a list
item), then immediately hit
C-c C,
to create the desired block. It will be indented at the right level:- This list item contains a: - sublist, which holds a block: [C-c C-,] here
- Move flush left: Note:
M-{
will get you to the start of a block quickly.M-\
at block start will move the block’s first header line to column 0. ThenM-S-left
(orright
) will indent the full block. - Indent rigidly:
M-h
selects the entire block. ThenC-x TAB
enters “rigid indent” mode, after which left/right moves the entire block. - Re-indent a block: If you have a block that is partially aligned, perhaps with
a “hanging end”, like so:
- List 1 - List 2 #+begin_src lang foo_lang(x) #+end_src
you can simply use
M-S-left/right
at block start (or in fact anywhere on the block header/footer) toorg-indent-block
. Note thatorg-src-preserve-indentation=nil
is an important setting, to allow org to (re-)indent blocks to respect the local indentation inside list and other elements. Also note that (fromorg-indent-region
):The function will not indent contents of example blocks, verse blocks and export blocks as leading white spaces are assumed to be significant there.
The default fixed-pitch
font (from which org-meta-line
inherits) has line
spacing >1.0 on some systems. This will introduce gaps even if your default font
is changed, and line-space
is nil. To correct it, add:
(set-face-attribute 'fixed-pitch nil :family "Hack" :height 1.0) ; or whatever font family
If you’d like a different face than org-meta-line
for the “bracket”, configure
the org-modern-indent-bracket-line
face.
org-num-mode
interferes with theorg-modern
prettification of TODO keywords.visual-wrap-prefix-mode
relies on thewrap-prefix
text property which is also used byorg-modern
.org-modern-indent-mode
is incompatible with non-zeroline-spacing
.
The tag style of org-modern
is inspired by Nicholas Rougier’s svg-tag-mode. In
contrast to svg-tag-mode
, the package org-modern
avoids images and uses more
efficient Emacs box text properties. By only styling the text via text
properties, the styled text, e.g., dates or tags stay editable and are easy to
interact with.
The approach used here restricts the flexibility (e.g., no rounded corners) and
creates dependence on the size and alignment of the font. Combining
org-modern-mode
with svg-tag-mode
is possible. You can use SVG tags and use the
table and block styling from org-modern
. If you are interested in further
tweaks, Emacs comes with the builtin prettify-symbols-mode
which can be used for
individual styling of custom keywords.
Alternatives are the older org-superstar and org-bullets packages, which are
more limited and mainly adjust headlines and lists. org-superstar
relies on
character composition, while org-modern
uses text properties, which are
considered more future-proof. Note that org-modern
is a full replacement for
both org-superstar
and org-bullets
. You can disable styling of certain elements,
e.g., org-modern-timestamp
, if you only want to use the subset of org-modern
equivalent to org-superstar
.
Since this package is part of GNU ELPA contributions require a copyright assignment to the FSF.