refactor!(ligatures): use ligature.el for Emacs28+

Include ligature.el in a new set-font-ligatures! function, so that
"normal" (read: "font-based") ligatures can
also be controlled on a per-major mode basis from a user function
in configuration.

This commit also drops support for Emacs 27 to reduce the maintenance
burden.

BREAKING CHANGE: font ligatures for Harfbuzz/Coretext composition
table-based ligations are no longer controlled with
`+ligatures-composition-alist`, but is handled with
`+ligatures-prog-mode-list` and `+ligatures-all-modes-list` for most
common cases. See the README for the mode-specific methods

BREAKING CHANGE: the `:ui ligatures` module will not work anymore
with Emacs 27 or older. Also, there is no need to keep patched fonts
(for Fira, Hasklig, Iosevka) if you use the module. Update Emacs if
you want to keep using ligatures, or disable the module (`doom doctor`
will tell you if your current version of Emacs stopped working with
the module)
This commit is contained in:
Gerry Agbobada 2021-05-23 11:27:57 +02:00 committed by Henrik Lissner
parent a44e8d6bfd
commit 46d7404bef
10 changed files with 200 additions and 916 deletions

View file

@ -1,58 +0,0 @@
;;; ui/ligatures/autoload/install.el -*- lexical-binding: t; -*-
;;;###if (or (modulep! +fira) (modulep! +hasklig) (modulep! +iosevka))
(defun +ligatures--install-font (prefix name url-format fonts-alist &optional extra-fonts)
"Install fonts to the local system.
If PREFIX is nil, will prompt whether or not to download. NAME is informational
only. URL-FORMAT is a format string that should be a url and have a single %s,
which is expanded for each font in FONTS-ALIST. FONTS-ALIST should be the
filename of each font. It is used as the source and destination filename."
(unless (or prefix
(yes-or-no-p
(format "This will download and install the %s fonts, continue?"
name)))
(user-error "Aborted"))
(let* ((font-dest
(cond (IS-LINUX
(expand-file-name
"fonts/" (or (getenv "XDG_DATA_HOME")
"~/.local/share")))
(IS-MAC
(expand-file-name "~/Library/Fonts/"))))
(known-dest-p (stringp font-dest))
(font-dest (or font-dest (read-directory-name "Font installation directory: " "~/"))))
(unless (file-directory-p font-dest)
(mkdir font-dest t))
(dolist (font fonts-alist)
(url-copy-file (format url-format font)
(expand-file-name font font-dest)
t))
(when known-dest-p
(message "Font downloaded, updating font cache... <fc-cache -f -v> ")
(shell-command-to-string "fc-cache -f -v"))
(if IS-WINDOWS
(when (y-or-n-p "The %S font was downloaded, but Windows users must install them manually.\n\nShow files in windows explorer?")
(call-process "explorer.exe" nil nil nil font-dest))
(message "Successfully %s %S fonts to %S!"
(if known-dest-p "installed" "downloaded")
name font-dest))))
;;;###autoload
(defun +ligatures/install-patched-font (font-id &optional arg)
"Install the font FONT-ID on your system.
FONT-ID must be a key from `+ligatures--font-alist'.
If PREFIX is non-nil, don't ask for confirmation and install it."
(interactive
(list
(car (cl-find (completing-read
"Install font: "
(mapcar #'cadr +ligatures--font-alist))
+ligatures--font-alist
:key #'cadr
:test #'equal))
current-prefix-arg))
(cl-destructuring-bind (font-name &key _range url files)
(or (alist-get font-id +ligatures--font-alist)
(user-error "%S is not a valid font" font-id))
(+ligatures--install-font arg font-name url files)))

View file

@ -11,40 +11,66 @@
MODES is a major mode symbol or a list of them.
PLIST is a property list whose keys must match keys in
`+ligatures-extra-symbols', and whose values are strings representing the text
to be replaced with that symbol. If the car of PLIST is nil, then unset any
pretty symbols previously defined for MODES.
to be replaced with that symbol.
This function accepts one special property:
:alist ALIST
Appends ALIST to `prettify-symbols-alist' literally, without mapping text to
`+ligatures-extra-symbols'.
If the car of PLIST is nil, then unset any
pretty symbols and ligatures previously defined for MODES.
For example, the rule for emacs-lisp-mode is very simple:
(set-ligatures! 'emacs-lisp-mode
(set-ligatures! \\='emacs-lisp-mode
:lambda \"lambda\")
This will replace any instances of \"lambda\" in emacs-lisp-mode with the symbol
assicated with :lambda in `+ligatures-extra-symbols'.
associated with :lambda in `+ligatures-extra-symbols'.
Pretty symbols can be unset for emacs-lisp-mode with:
(set-ligatures! 'emacs-lisp-mode nil)"
(set-ligatures! \\='emacs-lisp-mode nil)
Note that this will keep all ligatures in `+ligatures-prog-mode-list' active, as
`emacs-lisp-mode' is derived from `prog-mode'."
(declare (indent defun))
(if (null (car-safe plist))
(dolist (mode (ensure-list modes))
(delq! mode +ligatures-extra-alist 'assq))
(let (results)
(let ((results))
(while plist
(let ((key (pop plist)))
(if (eq key :alist)
(prependq! results (pop plist))
(when-let (char (plist-get +ligatures-extra-symbols key))
(push (cons (pop plist) char) results)))))
(push (cons (pop plist) char) results))))
(dolist (mode (ensure-list modes))
(setf (alist-get mode +ligatures-extra-alist)
(if-let (old-results (alist-get mode +ligatures-extra-alist))
(dolist (cell results old-results)
(setf (alist-get (car cell) old-results) (cdr cell)))
results))))))
;;;###autodef
(defun set-font-ligatures! (modes &rest ligatures)
"Associates string patterns with ligatures in certain major-modes.
MODES is a major mode symbol or a list of them.
LIGATURES is a list of ligatures that should be handled by the font,
like \"==\" or \"-->\". LIGATURES is a list of strings.
For example, the rule for emacs-lisp-mode is very simple:
(set-font-ligatures! \\='emacs-lisp-mode \"->\")
This will ligate \"->\" into the arrow of choice according to your font.
Font ligatures can be unset for emacs-lisp-mode with:
(set-font-ligatures! \\='emacs-lisp-mode nil)
Note that this will keep all ligatures in `+ligatures-prog-mode-list' active, as
`emacs-lisp-mode' is derived from `prog-mode'."
(declare (indent defun))
(if (null ligatures)
(dolist (mode (ensure-list modes))
(add-to-list 'ligature-ignored-major-modes mode))
(after! ligature
(dolist (mode (ensure-list modes))
(setq ligature-ignored-major-modes (delq mode ligature-ignored-major-modes)))
(ligature-set-ligatures (ensure-list modes) font-ligatures))))