2

In my .emacs I have

(set-frame-font "Source Code Pro")
(set-face-attribute 'default nil :font "Source Code Pro" :height 140)
(set-face-font 'default "Source Code Pro")

Which sets the fonts to source code pro. To do its job, this code apparently needs to run once after the first frame has been created. How can I achieve that?

  • I'm on MacOS and use emacs-plus.
  • Emacs Deamon is started on boot as a service, I only ever call emacsclient.
  • If I run this code once, all new frames have the right fonts.
  • If Emacs Daemon restarts, I need to run the code again, but after the first frame has been created.
  • Putting it in .emacs runs it too early so it's not working.
  • If I start emacs as emacs, not as the deamon, the code in .emacs works and the first frame uses Source Code Pro.

How can I set the fonts or other frame parameters on deamon start?

1
  • 4
    set-frame-font and similar like having an actual frame to work with, which is why you should set and save the value of the default face using M-x customize-face, which will set the appropriate values that will be used by new graphical frames (where do people get these set-frame-font invocations from?)
    – rpluim
    Jul 23, 2020 at 12:11

2 Answers 2

5

To do its job, this code apparently needs to run once after the first frame has been created. How can I achieve that?

The standard hooks for this are listed under (info "(elisp) Standard Hooks"):

‘after-make-frame-functions’
‘before-make-frame-hook’
‘server-after-make-frame-hook’
     see Creating Frames.

Following the link to (info "(elisp) Creating Frames"):

 -- Variable: before-make-frame-hook
     A normal hook run by ‘make-frame’ before it creates the frame.

 -- Variable: after-make-frame-functions
     An abnormal hook run by ‘make-frame’ after it created the frame.
     Each function in ‘after-make-frame-functions’ receives one
     argument, the frame just created.

   Note that any functions added to these hooks by your initial file are
usually not run for the initial frame, since Emacs reads the initial
file only after creating that frame.  However, if the initial frame is
specified to use a separate minibuffer frame (see Minibuffers and
Frames), the functions will be run for both, the minibuffer-less and
the minibuffer frame.

 -- User Option: server-after-make-frame-hook
     A normal hook run when the Emacs server creates a client frame.
     When this hook is called, the created frame is the selected one.
     See (emacs)Emacs Server.

(Note that the last server- hook is new in Emacs 27.)

To ensure a hook function is run only once, after the first non-daemon frame is created, just remove the function from the hook as its last step. For example:

(defun my-configure-font (frame)
  "Configure font given initial non-daemon FRAME.
Intended for `after-make-frame-functions'."
  ;; Do stuff with FRAME...
  (remove-hook 'after-make-frame-functions #'my-configure-font))

(add-hook 'after-make-frame-functions #'my-configure-font)

Some things to consider:

  • Both after-make-frame-functions and server-after-make-frame-hook are called for non-graphical frames as well, so add appropriate checks for this as needed.
  • Neither of these hooks is run in a non-daemon Emacs session. To also support non-daemon sessions, add your function to window-setup-hook instead (or as well). To check whether the current session is a daemon or not, there's the predicate daemonp.
0

It sounds like you would need a function to run once per server invocation.

You can probably use the information in this post to help you set up a hook that would run a function to set the fonts, and then not run that function for subsequent frames until the next time the server is (re)started.

Your Answer

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

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