14

this question actually arises because I like to use non-monospaced fonts, (Sabon, Minion, Garamond, etc.) This cause a problem when use org-indent-mode, since the text under the headlines are now not aligned with the headlines. Example: enter image description here

The font is Georgia. Now,if I change to consolas:

enter image description here

I think the problem is that in non-monospaced fonts, the "space" and the * does not take up the same space. Though I do not know how to solve this. I've searched the internet and couldn't find a tutorial to fine tune the indentation myself. I've tried to read org-indent.el but it's a long shot for me to understand. Help is greatly appreciated!

5
  • I also like to use proportionally-spaced serif fonts in Emacs and have experienced similar issues. I’ve been thinking that perhaps some tweaks to fontification could help, but I have not yet looked into it thoroughly. Commented Jan 16, 2015 at 4:15
  • 1
    Sounds like this has nothing to do with Org mode and you are just wondering how to get non-monospaced fonts to be aligned. The answer is that you need to do that using code - you cannot rely on space chars having the same width as other chars, etc. In short, in general you are out of luck.
    – Drew
    Commented Jan 16, 2015 at 5:44
  • @Drew you may be right "in general". But for this specific issue there is a solution, see my answer. The leading spaces used for indentation by org-indent are not really there, they are just line-prefix properties, so they can be replaced by any other character so long as it is invisible.
    – deprecated
    Commented Jan 16, 2015 at 6:24
  • @deprecated: I see. Thanks for the correction. BTW, perhaps Org itself could, be default, do what you suggest. Or just use SPC chars but with text (or overlay) property that imposes a face that (by default) has a monospaced font. Maybe an Org enhancement request is in order. ;-)
    – Drew
    Commented Jan 16, 2015 at 14:41
  • @Drew it's actually very easy to do that with font-lock, isn't it?
    – Clément
    Commented Jul 27, 2016 at 18:43

4 Answers 4

10

One solution is to modify org-indent-strings to use stars instead of spaces as the indentation character. This means that the width of the indentation will always be correct, even when using a proportional font. The trick then is to set the foreground color of the indentation to be the same as the background color, so that the stars become invisible.

We can achieve this with the following code, which advises the function org-indent-initialize:

(require 'cl)
(defun org-indent-use-stars-for-strings ()
  "Initialize the indentation strings with stars instead of spaces."
  (setq org-indent-strings (make-vector (1+ org-indent-max) nil))
  (aset org-indent-strings 0 nil)
  (loop for i from 1 to org-indent-max do
    (aset org-indent-strings i
          (org-add-props
          (concat (make-string (1- i) ?*) ; <- THIS IS THE ONLY CHANGE
              (char-to-string org-indent-boundary-char))
          nil 'face 'org-indent))))

(advice-add 'org-indent-initialize :after #'org-indent-use-stars-for-strings)
(set-face-foreground 'org-indent "white")

The result looks like this for me on Mac OS X using emacs -Q and (set-face-font 'default :family "Gill Sans"):

enter image description here

3
  • Hi @deprecated, thank you very much for providing the answer! This is a silly question but should I place your code in org-indent.el or my init.el? Neither seem to work for me. I am using Emacs 24.4 under windows, - do I need to compile anything or what? Thanks!
    – Alex
    Commented Jan 17, 2015 at 9:39
  • alright I did ask a stupid question. I need to compile org-indent.el. For future reference: the easiest way would be to change this line: (concat (make-string (1- i) ?\ ) to (concat (make-string (1- i) ?*) in the definition of org-indent-initialize i.e. (defun org-indent-initialize... then use M-x byte-compile-file to compile org-indent.el to org-indent.elc. Then restart emacs.
    – Alex
    Commented Jan 17, 2015 at 10:23
  • error: Invalid face, org-indent
    – rofrol
    Commented Aug 11, 2021 at 9:04
7

Somehow I couldn't get the other answers to work for my setup, but the fastest and easiest fix that worked for me was:

`M-x customize-face org-hide`

Then, just change the Font Family attribute to your monospace font (in my case, Iosevka).

And that's literally all you have to do, since org-indent (face for outline indentation) automatically inherits from org-hide (face used to hide leading stars in headlines)

An alternative to customize-face if you prefer not to use it, is to set the org-hide face to inherit the fixed-pitch face:

(set-face-attribute 'org-hide nil :inherit 'fixed-pitch)

enter image description here

5

deprecated's answer is very good, but it didn't quite work for me. I'm currently on Emacs 24.4 and org 8.2.4, and advising org-indent-initialize didn't do anything. I had to redefine the function with the changed indent character, and that worked. Maybe when I upgrade to Emacs 24.5 and org 8.3 the advising will work.

But I also had to make a few other adjustments, because I use different size variable-width fonts for different heading levels, which means that a level-1 heading's * is not the same width as a level-2's, and so on.

So I also had to do this:

  1. Set the faces org-hide (used to indent headline lines) and org-indent (used to indent non-headline lines) to make sure they use the same font at the same size.
  2. Set the variable org-indent-boundary-character to * instead of the default (a space). This is the character that is inserted after the indentation characters but before the content. I'm not sure if changing this is a necessity, but it seems to help consistency. It might depend on the font you're using, sizes, etc.

Doing those things in addition to making the change to org-indent-initialize as deprecated provided seems to have done it. I end up with a buffer looking like this:

screenshot

You can see that, as the headline level goes down, the indentation doesn't line up perfectly with the heading text. I think that's because of using smaller fonts for lower-level headings, and I don't think there's an easy way to fix that. It might be possible to do something with text-properties like line-prefix and wrap-prefix, because those can be set to images and special characters, but that would probably be complicated and slow. If you use the same font size for all heading levels, this probably won't be an issue.

Anyway, this is probably good enough. :)

P.S. As requested, here are my org-level faces. These are copied from custom-set-faces, but if you don't use customize you can set them outside of it.

 '(org-level-1 ((t (:inherit variable-pitch :foreground "#cb4b16" :weight bold :height 1.3))))
 '(org-level-2 ((t (:inherit variable-pitch :foreground "#859900" :weight bold :height 1.2))))
 '(org-level-3 ((t (:inherit variable-pitch :foreground "#268bd2" :weight bold :height 1.15))))
 '(org-level-4 ((t (:inherit variable-pitch :foreground "#b58900" :weight bold :height 1.1))))
 '(org-level-5 ((t (:inherit variable-pitch :foreground "#2aa198" :weight bold))))
 '(org-level-6 ((t (:inherit variable-pitch :foreground "#6c71c4" :weight bold))))
 '(org-level-7 ((t (:inherit variable-pitch :foreground "#d33682" :weight bold))))
 '(org-level-8 ((t (:inherit variable-pitch :foreground "#dc322f" :weight bold))))
4
  • @bluejay I like how this looks. Do you have the complete config to get this posted somewhere?
    – erikstokes
    Commented Sep 27, 2015 at 0:01
  • Well, I'm using the solarized-dark theme, which is part of the solarized-theme package which you can install from ELPA. As for the org-level-* faces, I'll add them to the answer above.
    – user3871
    Commented Sep 27, 2015 at 6:59
  • This looks super cool. How do you replace the default * with those special symbols?
    – Alex
    Commented Oct 7, 2015 at 18:27
  • That's from the org-bullets package. Run package-list-packages and check out all the packages starting with org-. :)
    – user3871
    Commented Oct 10, 2015 at 2:51
2

A much simpler solution: in org mode, press M-: and run the following

(font-lock-add-keywords 
 nil 
 '(("^[[:space:]*]+" 0 '(face (:family "Ubuntu Mono")) append))
 'append)

You may need M-x font-lock-fontify-buffer after that. This solution simply forces leading characters (spaces and stars) to use a monospace font.

Also, you'll want to replace "Ubuntu Mono" with a monospace font of your choosing,

1
  • This is no longer necessary considering the other solutions. :)
    – user3871
    Commented Dec 29, 2018 at 2:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.