1

I am starting with emacs --daemon in my session, and it seems to trigger some odd behavior regarding themes and faces. I am using this solarized theme but I have found it to have weird cursor issues. My fix was to customize the cursor face:

(custom-set-faces
 ;; https://github.com/bbatsov/solarized-emacs/issues/290
 '(cursor ((t (:background "#990A1B")))))

The strange thing is that works if I start emacs normally (with the emacs command). But when I start emacs as a daemon and open a frame (emacs --daemon ; emacsclient --create-frame /dev/null), the cursor customization is not present.

I have tried to configure a hook like this to run after the theme is loaded but it doesn't seem to take effect either:

(use-package solarized-theme
  :ensure t
  :config
  (progn
    (defvar after-load-theme-hook nil
      "Hook run after a color theme is loaded using `load-theme'.")
    (defadvice load-theme (after run-after-load-theme-hook activate)
      "Run `after-load-theme-hook'."
      (run-hooks 'after-load-theme-hook))
    (defun anarcat/customize-solarized ()
      "Customize theme"
      (message "custom hook config")
      (when (member 'solarized-dark custom-enabled-themes)
          (custom-theme-set-faces
           'solarized-dark
           '(cursor ((t (:background "#990A1B")))))
          (message "tweaked theme"))
      (message "done"))
    (add-hook 'after-load-theme-hook 'anarcat/customize-solarized)))

I know about this question and those answers but they all relate to the theme: the theme loads fine here, it's only the face that fails to load. But it does provide a workaround that actually works:

(if (daemonp)
    (add-hook 'after-make-frame-functions
              (lambda (frame)
                (when (eq (length (frame-list)) 2)
                  (progn
                    (select-frame frame)
                    (custom-set-faces
                     '(cursor ((t (:background "#990A1B"))))))))))

It just feels clunky and weird to run that every time a frame opens. Besides, this feels quite inelegant as it duplicates configuration between my .emacs and my .emacs-custom.

This question is also similar to this one although every settings but the faces load here.

So I'm wondering if that's a bug in Emacs worth reporting, or something I am doing wrong, or that the theme is doing wrong.

Any ideas?

Y. E.
  • 668
  • 4
  • 8
anarcat
  • 133
  • 6
  • 1
    Does this answer your question? [custom-set-faces not working for client](https://emacs.stackexchange.com/questions/77762/custom-set-faces-not-working-for-client) – shynur Aug 26 '23 at 09:02
  • That question and other answers below all fail to provide a solution that properly reloads the normal `.emacs.d/custom.el` file. They all provide hackish workaround that require rewiring the normal "customize" system into a function that gets called at the right time. I don't think that's the right solution, as I would like to keep using customize. Really, this feels like a bug that should be fixed in Emacs instead... – anarcat Aug 28 '23 at 15:08

2 Answers2

1

emacsclient has the frame loaded before the init file and therefore you must have the font configuration further down in the file.

Copy your configuration to the bottom lower down as Emacs is reading it from top to bottom.

I have the following setup borrowed from @Tobias for that purpose:

(defun my-frame-tweaks (&optional frame)                        
  "My personal frame tweaks."                                   
  (unless frame                                                 
    (setq frame (selected-frame)))                              
  (when frame                                                   
    (with-selected-frame frame                                  
      (when (display-graphic-p)                                 
    (tool-bar-mode -1))))                                       
(set-face-font 'default "dejavu sans mono-15"))                 

;; For the case that the init file runs after the frame has been created
;; Call of emacs without --daemon option.                       
(my-frame-tweaks)                                               
;; For the case that the init file runs before the frame is created.
;; Call of emacs with --daemon option.                          
(add-hook 'after-make-frame-functions #'my-frame-tweaks t)      

You can find @Tobias' original here

manandearth
  • 2,068
  • 1
  • 11
  • 23
  • i'm not sure I understand what you're saying here. the `custom-set-faces` i do in the `after-make-frame-functions` hook actually works. what I want is to *avoid* such hooks in the first place and have the `custom-set-faces` from `.emacs-custom` load normally. besides, are you saying that `emacsclient` reloads the `.emacs` file *every* time it starts? – anarcat Dec 12 '18 at 17:26
  • No. I say that it loads the .emacs the first time when you start a daemon, but as Tobias explains in the comment: " the virtual frame of the emacs daemon is not connected to any display. Since the init file runs in the daemon window-system is nil " That is why you should use the hook. I don't know of a more elegant way. – manandearth Dec 12 '18 at 18:04
  • right, ok, thanks for the clarification! :) then i guess one valid answer here would be a way to reload relevant parts of `.emacs-custom`, only once, when display becomes available... – anarcat Dec 12 '18 at 19:18
0

I got answer from the Youtube video "Unlock the Power of the Daemon with emacsclient" and tested that it works.

One common issue when using Emacs as a daemon is that fonts seem to not work correctly when starting a new frame using emacsclient. If you run set-face-attribute in the frame, the font will be applied to future frames too.

Fixing this requires some tweaks to configuration:

(defun efs/set-font-faces ()
  (message "Setting faces!")
  (set-face-attribute 'default nil :font "Fira Code Retina" :height efs/default-font-size)

  ;; Set the fixed pitch face
  (set-face-attribute 'fixed-pitch nil :font "Fira Code Retina" :height efs/default-font-size)

  ;; Set the variable pitch face
  (set-face-attribute 'variable-pitch nil :font "Cantarell" :height efs/default-variable-font-size :weight 'regular))

(if (daemonp)
    (add-hook 'after-make-frame-functions
              (lambda (frame)
                ;; (setq doom-modeline-icon t)
                (with-selected-frame frame
                  (efs/set-font-faces))))
    (efs/set-font-faces))

In Emacs 27 you can use server-after-make-frame-hook so that your function only gets called once!

Y. E.
  • 668
  • 4
  • 8
Frank Wu
  • 51
  • 2