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?

2
  • 1
    Does this answer your question? custom-set-faces not working for client
    – shynur
    Commented Aug 26, 2023 at 9:02
  • 1
    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
    Commented Aug 28, 2023 at 15:08

2 Answers 2

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

3
  • 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
    Commented Dec 12, 2018 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. Commented Dec 12, 2018 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
    Commented Dec 12, 2018 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!

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.