Jackson Ray Hamilton
Jackson Ray Hamilton

Reputation: 9466

emacsclient font check not working

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.

Upvotes: 3

Views: 1622

Answers (4)

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")))))

Upvotes: 2

Alexander Shukaev
Alexander Shukaev

Reputation: 17021

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]

Upvotes: 3

Stefan
Stefan

Reputation: 28531

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.

Upvotes: 1

Jackson Ray Hamilton
Jackson Ray Hamilton

Reputation: 9466

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)))

Upvotes: 0

Related Questions