3

I am trying to set my font for emacsclient like so:

(let ((default-font (cond
                     ((member "Inconsolata" (font-family-list))
                      "Inconsolata 14")
                     (t
                      "monospace 20"))))
  (set-default-font default-font)
  (add-to-list 'default-frame-alist `(font . ,default-font)))

I C-x C-e at the cond sexp and it returns "Inconsolata 14". I C-x C-e at the let sexp and the font is updated.

When I launch emacs via

$ emacs

it works (the font is set to Inconsolata 14).

However when I launch the application via

$ emacsclient --alternate-editor="" --create-frame "$@"

the font is monospace 20 instead.

Please advise.

EDIT:

I have discovered that by including

(message "%s" (font-family-list))

in my .emacs file that (font-family-list) returns nil when emacsclient is starting up.

Unfortunately, also during initialization:

;; Both also print `nil` to the `*Messages*` buffer.
(message "%s" (find-font (font-spec :name "inconsolata")))
(message "%s" (find-font (font-spec :name "Inconsolata")))

;; Throws "error: No fonts being used"
(message "%s" (describe-font "Inconsolata"))

I do not know how to detect if a font is installed during initialization. My question has become: How do I reliably check whether a font is available when emacsclient starts up?

EDIT 2:

Echoing in after-init-hook, emacs-startup-hook, window-setup-hook, before-make-frame-hook, and after-make-frame-functions also results in nil.

Jackson
  • 9,188
  • 6
  • 52
  • 77

4 Answers4

3

Sigh... was annoyed with this problem as well, but I found the Emacs Lisp solution. Here is a straight copy/paste of the respective snippet from my Emacs configuration:

(defun frame-font-setup
    (&rest ...)
  ;; (remove-hook 'focus-in-hook #'frame-font-setup)
  (unless (assoc 'font default-frame-alist)
    (let* ((font-family (catch 'break
                          (dolist (font-family
                                   '("Powerline Consolas"
                                     "Consolas for Powerline"
                                     "Consolas"
                                     ;;
                                     "Powerline Inconsolata-g"
                                     "Inconsolata-g for Powerline"
                                     "Inconsolata-g"
                                     ;;
                                     "Powerline Source Code Pro"
                                     "Source Code Pro for Powerline"
                                     "Source Code Pro"
                                     ;;
                                     "Powerline DejaVu Sans Mono"
                                     "DejaVu Sans Mono for Powerline"
                                     "DejaVu Sans Mono"
                                     ;;
                                     "Monospace"))
                            (when (member font-family (font-family-list))
                              (throw 'break font-family)))))
           (font (when font-family (format "%s-12" font-family))))
      (when font
        (add-to-list 'default-frame-alist (cons 'font font))
        (set-frame-font font t t)))))
(add-hook 'focus-in-hook #'frame-font-setup)

Mmmhhh... [Rejoice]

Alexander Shukaev
  • 16,674
  • 8
  • 70
  • 85
  • When I add my font setup function to the focus in hook it only appears to have an effect after the second frame is created. Do you see this too? – Jesse Jun 15 '20 at 11:46
  • Actually I wasn't using "set-frame-font". It all works now, thanks! – Jesse Jun 15 '20 at 12:21
2

I managed to find an answer in this post in emacs subreddit.

Here is the code snippet that I put in in init.el:

(defun rag-set-face (frame)
  "Configure faces on frame creation"
  (select-frame frame)
  (if (display-graphic-p)
      (progn
        (when (member "PragmataPro" (font-family-list))
            (set-frame-font "PragmataPro-13")))))
  • I also needed: (add-hook 'after-make-frame-functions #'me:set-frame-face) (mapc #'me:set-frame-face (frame-list)) where me:set-frame-face is the equivalent of rag-set-face. The second takes care of any existing frames. – ergosys Sep 09 '18 at 00:45
1

When you start Emacs as a daemon (which is done implicitly by emacsclient on-demand), the .emacs is loaded before Emacs has made a connection to any "display device" (aka "terminal"), i.e. it is not connected to any GUI nor any tty. Instead its terminal is a dummy device which reads from stdin and sends the output to stdout (well, at the beginning and soon after, even that communication link is cut), so there are no fonts there.

One way to get what you want is to do something like:

(add-to-list face-font-family-alternatives '("myfont" "Inconsolata" "Monospace"))

and then to customize the default face to use the font family myfont. You may still have problems with the size of the font, in which case you may want to play with face-font-rescale-alist.

Stefan
  • 27,908
  • 4
  • 53
  • 82
  • Tried `(add-to-list face-font-family-alternatives '("myfont" "Inconsolata" "Monospace"))` and `M-x customize` and updated Default face > Font Family to "myfont", but it doesn't work. The font is not Inconsolata, it's not monospace either; when I try to `M-x customize` again the field "Font Family" is set to "Droid Sans". – Jackson Aug 09 '14 at 20:07
  • Then something went wrong in the part where you "set" the font family of the default face. – Stefan Aug 10 '14 at 16:35
0

Seems to be pretty much impossible with elisp alone so I've settled for fc-list. This works.

(let ((default-font (cond
                     ((and
                       (eq system-type 'gnu/linux)
                       (null (string= "" (shell-command-to-string "which fc-list")))
                       (null (string= "" (shell-command-to-string "fc-list inconsolata"))))
                      "Inconsolata 14")
                     (t
                      "monospace 12"))))
  (set-default-font default-font)
  (add-to-list 'default-frame-alist `(font . ,default-font)))
Jackson
  • 9,188
  • 6
  • 52
  • 77