0

I have this face definition that applies globally:

(set-face-attribute 'variable-pitch nil :family "Charis SIL Compact" :height 180)

The problem is that Elfeed and Mu4e also use the variable pitch mode and I don't want that.

I would like to create a custom function called distraction-free-writing that is bound to a key and when that key is pressed to activate the variable pitch mode in the current Org buffer and also set olivetti-body-width to a value of 60.

For fixed pitched font the olivetti value is set to 80, however variable pitch font is more condensed, so 80 characters fit in a 60 olivetti width.

Is it possible to make that face attribute local for a function?

Drew
  • 75,699
  • 9
  • 109
  • 225
Zoli
  • 381
  • 1
  • 7

1 Answers1

1

I don't understand exactly what you want to do, but maybe something like this:

(defvar-local my-distraction-free-writing-remap nil)

(defun my-distraction-free-writing ()
  (interactive)
  (if my-distraction-free-writing-remap
      (progn
        (face-remap-remove-relative
         my-distraction-free-writing-remap)
        (setq olivetti-body-width 80)
        (olivetti-mode 1)
        (setq my-distraction-free-writing-remap nil))
    (setq my-distraction-free-writing-remap
          (face-remap-add-relative 'variable-pitch
                                   :family "Charis SIL Compact"
                                   :height 180))
    (variable-pitch-mode 1)    
    (setq olivetti-body-width 60)
    (olivetti-mode 1)))

With face-remap-add-relative you can remap face attributes buffer-locally. So this redefines the face variable-pitch in the current buffer to have the given attributes, then turns on variable-pitch-mode and sets olivetti-body-width.

To bind it to a key: (keymap-set org-mode-map "<f8>" #'my-distraction-free-writing).

orgtre
  • 1,012
  • 4
  • 15
  • Thank you. This is what I was looking for. I just had to add (olivetti-mode 1) otherwise the new width don't take effect. If I want this to be applied to all Org buffer do I need to attach the function to the `org-mode` hook? – Zoli Feb 22 '23 at 14:13
  • I may ask too much but if I decide to bind it to a key, is it possible to make it toggle. For example if I press F8 to call the function as is now, but when I press F8 again to switch back to the previous fixed-pitch font "Hack" and set back olivetti to a width of 80. – Zoli Feb 22 '23 at 14:19
  • 1
    Yes, you need to attach it to the hook. I changed the function so that now it should toggle. – orgtre Feb 22 '23 at 16:56
  • I'm trying to bind it with the new syntax `(keymap-global-set "" 'my-distraction-free-writing)` but the results are not what I want. – Zoli Feb 22 '23 at 17:05
  • 1
    What is the problem? The keybinding has no effect? It works for me. Try another binding, maybe something is overwriting yours. – orgtre Feb 22 '23 at 17:19
  • Thank you. It works but I need to add `(olivetti-mode 1)` after `(setq olivetti-body-width 80)` and move ` `(olivetti-mode 1)` after `(setq olivetti-body-width 60)`. Just for curiosity what is the purpose of the `my-distraction-free-writing-remap` variable? – Zoli Feb 22 '23 at 17:41
  • 1
    OK. I'll make an edit to reflect that. The variable is used both for toggling and to store the active face remapping as this makes removing it again easier. – orgtre Feb 22 '23 at 17:48
  • One more question, what does `org-mode-map` do? Does it restrict the key binding to Org mode buffers only? If so, that is fine. – Zoli Feb 22 '23 at 21:19
  • Yes, exactly, to buffers with Org mode as active major mode. – orgtre Feb 22 '23 at 21:21
  • This does not work properly for me. Toggling on works fine, but toggling `my-distraction-free-writing` off again does not restore the font to what it was before (the size is restored, but I get some non monospace font instead) and does also not turn `olivetti-mode` off. My standard font to which it should go back is set by `(setq doom-font (font-spec :family "DejaVu Sans Mono" :size 11.5) doom-variable-pitch-font (font-spec :family "sans"))` – Christoph90 Aug 11 '23 at 07:06