protesilaos / show-font

Show font features in an Emacs buffer
GNU General Public License v3.0
22 stars 2 forks source link

Handle fonts that can't display ASCII #4

Open Stebalien opened 2 weeks ago

Stebalien commented 2 weeks ago

At the moment, fonts that can't display ASCII show up like this:

screen

It would be great if these could be handled somehow. It would be great if it were possible to show an actual preview, but that would require some way to determine what characters are displayable and I'm not sure if there's a good way to do that inside Emacs other than scanning the entire font.

But, TBH, simply hiding said fonts would be enough for most people.

In terms of detecting this, you can insert a character with the given font and then ask Emacs how it displays it:

(describe-char-display (point) (char-after))

If Emacs can't display it, that code will return nil. There may be better ways to go about this, but that's the only one I'm aware of.


Off topic but I really appreciate this package. It's much lighter-weight than the Gnome, etc. font viewers, has no dependencies, starts up instantly, and is generally a great way to just browse the locally installed fonts.

Stebalien commented 2 weeks ago

(I'm happy to submit a patch if you'd like)

protesilaos commented 2 weeks ago

From: Steven Allen @.***> Date: Sun, 13 Oct 2024 07:18:00 -0700

(I'm happy to submit a patch if you'd like)

Yes, please!

-- Protesilaos Stavrou https://protesilaos.com

protesilaos commented 2 weeks ago

From: Steven Allen @.***> Date: Sun, 13 Oct 2024 07:17:33 -0700

At the moment, fonts that can't display ASCII show up like this:

screen

Indeed, this is not nice.

It would be great if these could be handled somehow. It would be great if it were possible to show an actual preview, but that would require some way to determine what characters are displayable and I'm not sure if there's a good way to do that inside Emacs other than scanning the entire font.

I could not think of a good way to handle this, so I thought I would leave it as-is for the time being.

But, TBH, simply hiding said fonts would be enough for most people.

This is a good option as well. But if we can somehow figure out the subset of characters supported by the given font, then that is the best solution.

In terms of detecting this, you can insert a character with the given font and then ask Emacs how it displays it:

(describe-char-display (point) (char-after))

Sure, though I wonder how costly this will be. Maybe we can make it an opt-in feature if it is too slow and hide those fonts by default?

[... 5 lines elided]

Off topic but I really appreciate this package. It's much lighter-weight than the Gnome, etc. font viewers, has no dependencies, starts up instantly, and is generally a great way to just browse the locally installed fonts.

Thank you! It was a really fun project for me.

-- Protesilaos Stavrou https://protesilaos.com

Stebalien commented 2 weeks ago

Ok, I have a working-ish example but it requires Emacs 29 (and needs to be cleaned up). Ideally it would also have, e.g., CJK support.

(defun show-font--can-latin (font)
  "Returns t if the FONT can display Latin."
  (and (font-has-char-p font ?a)
       (font-has-char-p font ? )))

(defun show-font--can-emoji (font)
  "Returns t if the FONT can display Latin."
  (font-has-char-p font ?🐸))

;;;###autoload
(defun show-font-list ()
  "Produce a list of installed fonts with their preview.
The preview text is that of `show-font-pangram'."
  (declare (interactive-only t))
  (interactive)
  ;; FIXME 2024-09-06: Here we should only list fonts that can display
  ;; the pangram OR, better, we should have something appropriate to
  ;; show for them (e.g. emoji for the Emoji font).
  (show-font-with-preview-buffer "*show-font preview of all installed fonts*"
    (save-excursion
      (let* ((counter 0)
             (pangram (concat (show-font--get-pangram) "\n")))
        (dolist (family (show-font--get-installed-font-families))
          (let* ((font (find-font (font-spec :family family)))
                 (can-latin (show-font--can-latin font))
                 (can-emoji (show-font--can-emoji font))
                 (counter-string (format "%d. " counter)))
            (insert (propertize counter-string 'face 'show-font-misc)
                    (propertize family 'face
                                (cons 'show-font-title-small
                                      (when can-latin
                                        (list :family family))))
                    "\n"
                    (make-string (length counter-string) ?\s)
                    (if (or can-latin can-emoji)
                        (propertize
                         (concat
                          (when can-latin pangram)
                          (when can-emoji "πŸ™‚πŸ‚πŸΈπŸš\n"))
                         'face (list 'show-font-regular :family family))
                      (propertize "[no preview available]\n"
                                  'face 'show-font-regular))
                    "\n"))
          (setq counter (+ counter 1)))))
    (setq-local revert-buffer-function
                (lambda (_ignore-auto _noconfirm)
                  (show-font-list)))))

Thoughts?