RSS Amplifier

Martin's Blog · Aug 1, 2025

Emacs Writing Experience

0
Sign in to vote or save

Martin Stemplinger · Martin's Blog

  • Note taken on [2025-07-31 Thu 21:03]
    Added icon settings in agenda

A while back the Emacs Carnival started and July’s topic is writing experience. For me writing in Emacs means org-mode like for many others. A pleasant writing experience in org-mode for me includes nice looking org-mode buffers a.k.a. beautifying org-mode. Thus I’d like to share my current org-mode settings for org-mode eye-candy. It’s a follow-up to my older post on Beautify Org mode. Some parts remain the same but some parts changed.

Of course the visual appearance starts with the theme and font settings. Many people recommend the modus theme and it’s indeed great. I have changed a few colors in palette-overrides.

(use-package emacs
  :config
  (require-theme 'modus-themes)
  :custom
  (modus-themes-mixed-fonts t)
  (modus-themes-italic-constructs t)
  (modus-themes-bold-constructs nil)
  (modus-themes-fringes 'subtle)
  (modus-themes-variable-pitch-ui t)
  (modus-themes-custom-auto-reload t)
  (modus-themes-disable-other-themes t)
  (modus-themes-completions
   '((matches . (extrabold underline))
     (selection . (semibold italic))))
  (modus-themes-to-toggle
   '(modus-operandi modus-vivendi))
  (modus-themes-common-palette-overrides
   '((fg-heading-2 fg-main)
     (fg-heading-3 fg-alt)
     (fg-heading-4 fg-active-value)
     (fg-heading-5 fg-active-value)
     (fg-heading-6 fg-dim)))
  (modus-themes-headings
   '((0 . (variable-pitch 1.4))
     (1 . (variable-pitch 1.3))
     (2 . (variable-pitch 1.2))
     (3 . (variable-pitch 1.1))
     (4 . (variable-pitch 1))
     (5 . (variable-pitch 1))
     (agenda-structure . (variable-pitch light 1))))
  :bind (([f5] . modus-themes-toggle))
  :init
  (load-theme 'modus-operandi :no-confirm))

I usually use light-mode but I like it when Emacs follows the OS mode setting. auto-dark achieves that but I can’t get it to work on WSL.

(use-package auto-dark
  :unless  (and (eq system-type 'gnu/linux)
           (getenv "WSLENV"))
  :ensure t
  :custom
  (auto-dark-themes '((modus-vivendi) (modus-operandi)))
  (auto-dark-polling-interval-seconds 5)
  (auto-dark-allow-osascript t)
  :init (auto-dark-mode))

Now on to the specific org-mode settings.

I like variable-pitch-mode and visual-line-mode for org files.

(add-hook 'org-mode-hook
          (lambda ()
            (variable-pitch-mode 1)
            visual-line-mode))

org-mode is a markup language but I prefer a cleaner look and hide some of the markup. I don’t want to see the emphasis markers, change the face of a headline if it’s marked DONE instead of only the TODO keyword, show a nice ellipsis to indicate folded text and show entities as UTF8 characters.

(setq org-hide-emphasis-markers t
      org-fontify-done-headline t
      org-ellipsis "⤵"
      org-pretty-entities t
      org-pretty-entities-include-sub-superscripts nil)

Hiding emphasis markers and the like can confuse me if I need to edit them. org-appear is useful to see if I need to edit it

(use-package org-appear
  :hook
  (org-mode . org-appear-mode))

The next is a setting to automatically change list bullets. I work a lot with bulleted list and I think it emphasises the structure better.

(setq org-list-demote-modify-bullet
      (quote (("-" . "+")
              ("+" . "*")
              ("1." . "-")
              ("1)" . "-")
              ("A)" . "-")
              ("B)" . "-")
              ("a)" . "-")
              ("b)" . "-")
              ("A." . "-")
              ("B." . "-")
              ("a." . "-")
              ("b." . "-")))
      org-list-indent-offset 2)

Next is the package org-modern that forms the largest part of the visual changes. It replaces my previous use of org-bullets. I don’t want to see all the heading stars. I replace the remaining one by unicode numbers showing the level of the heading for the levels 1-4.

org-modern-block-name replaces the src code block names with some symbols. I can never remember if the block names need to be lowercase or uppercase so I set both just in case.

Similarly org-modern-keyword replaces the settings I have at the top of an org-mode buffer and I like a visual clue on the priority of tasks.

I found the package somewhat messes with org-tables and thus don’t want it to style them.

org-modern provides block prettification but not if org-indent-mode is active which I use. org-modern-indent is a replacement. It’s not on MELPA so I install it directly from github.

(use-package org-modern
    :custom
     (org-modern-fold-stars
      '(("①" . "①") ("②" . "②") ("③" . "③") ("④" . "④") ("▸" . "▾")))
    (org-modern--block-fringe nil "Disable problematic setting: Do not style fringe")
    (org-modern-hide-stars 'leading "adds extra indentation")
    (org-modern-block-name '(("src" "✎" "□") ("SRC" "✎" "□") ("quote" "»" "«") ("QUOTE" "»" "«")))
    (org-modern-keyword
     (quote (("options" . "🔧")
             ("setupfile" . "🔧")
             ("startup" . "🔧")
             ("date" . "📆")
             ("author" . "👤")
             ("columns" . "▓")
             ("tags" . "⚙")
             ("typ_todo" . "☑")
             ("html_doctype" . "🚛")
             ("html_head" . "🚛")
             ("html_head_extra" . "🚛")
             (t . t))))
    (org-modern-priority
     (quote ((?A . "⬆")
             (?B . "➡")
             (?C . "⬇"))))
    (org-modern-table nil)
    (org-modern-checkbox nil "I prefer prettify-symbols to set them")
    :hook
    (org-mode . org-modern-mode)
    (org-agenda-finalize . org-modern-agenda))
(use-package org-modern-indent
  :vc (:url "https://github.com/jdtsmith/org-modern-indent"
            :rev :newest)
  :demand t
  :config ; add late to hook
  (add-hook 'org-mode-hook #'org-modern-indent-mode 90))

I also use tags a lot. I replace them by unicode symbols for a cleaner look with the org-pretty-tags package. The name needs to be exactly as in the buffer for this to work.

(use-package org-pretty-tags
   :demand t
   :config
   (setq org-pretty-tags-surrogate-strings
         (quote
          (("TOPIC" . "☆")
           ("PROJEKT" . "💡")
           ("SERVICE" . "✍")
           ("Blog" . "✍")
           ("music" . "♬")
           ("security" . "🔥")
           ("Experiment" . "")
           ("productivity" . "☕"))))
   (org-pretty-tags-global-mode))
(setq org-tags-column 0)

Inspired by a comment in i use markdown rather than org-mode for my notes : emacs I looked at the now builtin mode prettify-symbols-mode. The configuration follows the example given in New in Emacs 25.1: Have prettify-symbols-mode reveal the symbol at point to provide some kind of ligatures.

(setq-default prettify-symbols-alist '((">=" . "≥")
                                        ("=>" . "⇨")
                                        ("[ ]" .  "☐")
                                        ("[X]" . "☑")
                                        ("[-]" . "?⛞")))
(setq prettify-symbols-unprettify-at-point 'right-edge)
(add-hook 'org-mode-hook
          'prettify-symbols-mode)

Beside writing notes I also use org-mode for task management again. The following two settings strike through done tasks and checkboxes. I found the setting for strike through done checkboxes in JFT's Notes - Use unicode symbol to display org-mode checkboxes

(set-face-attribute 'org-headline-done nil :strike-through t)

(defface org-checkbox-done-text
  '((t (:foreground "#71696A" :strike-through t)))
  "Face for the text part of a checked org mode checkbox.")
(font-lock-add-keywords
 'org-mode
 `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)"
    1 'org-checkbox-done-text prepend))
 'append)

I use all-the-icons to show icons e-g- in dired, magit and ediff. I also use them to add icons to my agenda.

(setq org-agenda-category-icon-alist
    `(("Inbox" ,(list (all-the-icons-faicon "check-circle")) nil nil :ascent center)
      ("Termine" ,(list (all-the-icons-material "today")) ni nil :ascent center)
      ("regularly" ,(list (all-the-icons-faicon "cogs")) nil nil :ascent center)
      ("buecher" ,(list (all-the-icons-faicon "book")) nil nil :ascent center)
      ("Journal" ,(list (all-the-icons-faicon "leanpub")) nil nil :ascent center)
      ("tasks" ,(list (all-the-icons-faicon "check-circle-o")) nil nil :ascent center)
      ("Urlaub" ,(list (all-the-icons-faicon "sun-o")) nil nil :ascent center)
      ("weeklyreview" ,(list (all-the-icons-faicon "check-circle")) nil nil :ascent center)
      ("work" ,(list (all-the-icons-faicon "briefcase")) nil nil :ascent center)
      ("tree" ,(list (all-the-icons-faicon "tree")) nil nil :ascent center)
      ("team" ,(list (all-the-icons-faicon "users")) nil nil :ascent center)
      ))

In case you’re interested you can find my complete Emacs configuration here.

Read the original on mstempl.netlify.app

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.