From 7081d833f6d9926b9d6cfbc2ee237535f9ad121f Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 12 Aug 2020 18:52:14 -0400 Subject: [PATCH] Move :ui pretty-code to :ui ligatures Includes a major refactor of the module. --- core/core-modules.el | 3 +- docs/faq.org | 4 +- docs/modules.org | 2 +- init.example.el | 2 +- modules/lang/cc/config.el | 2 +- modules/lang/dart/config.el | 2 +- modules/lang/elixir/config.el | 2 +- modules/lang/elm/config.el | 2 +- modules/lang/emacs-lisp/config.el | 2 +- modules/lang/javascript/config.el | 4 +- modules/lang/ocaml/README.org | 2 +- modules/lang/ocaml/config.el | 2 +- modules/lang/org/config.el | 2 +- modules/lang/php/config.el | 2 +- modules/lang/python/config.el | 2 +- modules/lang/racket/config.el | 2 +- modules/lang/rust/config.el | 2 +- modules/lang/scala/config.el | 2 +- modules/lang/sh/config.el | 2 +- modules/ui/ligatures/+fira.el | 123 +++++++++ modules/ui/ligatures/+hasklig.el | 62 +++++ modules/ui/ligatures/+iosevka.el | 244 +++++++++++++++++ modules/ui/ligatures/+pragmata-pro.el | 249 +++++++++++++++++ .../ui/{pretty-code => ligatures}/README.org | 60 ++-- modules/ui/ligatures/autoload/install.el | 58 ++++ .../autoload/ligatures.el} | 29 +- .../ui/{pretty-code => ligatures}/config.el | 177 ++++++------ modules/ui/pretty-code/+fira.el | 127 --------- modules/ui/pretty-code/+hasklig.el | 58 ---- modules/ui/pretty-code/+iosevka.el | 232 ---------------- modules/ui/pretty-code/+pragmata-pro.el | 259 ------------------ modules/ui/pretty-code/autoload/install.el | 98 ------- 32 files changed, 899 insertions(+), 920 deletions(-) create mode 100644 modules/ui/ligatures/+fira.el create mode 100644 modules/ui/ligatures/+hasklig.el create mode 100644 modules/ui/ligatures/+iosevka.el create mode 100644 modules/ui/ligatures/+pragmata-pro.el rename modules/ui/{pretty-code => ligatures}/README.org (63%) create mode 100644 modules/ui/ligatures/autoload/install.el rename modules/ui/{pretty-code/autoload/pretty-code.el => ligatures/autoload/ligatures.el} (60%) rename modules/ui/{pretty-code => ligatures}/config.el (54%) delete mode 100644 modules/ui/pretty-code/+fira.el delete mode 100644 modules/ui/pretty-code/+hasklig.el delete mode 100644 modules/ui/pretty-code/+iosevka.el delete mode 100644 modules/ui/pretty-code/+pragmata-pro.el delete mode 100644 modules/ui/pretty-code/autoload/install.el diff --git a/core/core-modules.el b/core/core-modules.el index 7ac3b4abc..917393412 100644 --- a/core/core-modules.el +++ b/core/core-modules.el @@ -47,7 +47,8 @@ run before `doom-init-modules-hook'. Relevant to `doom-module-init-file'.") (:ui (doom-modeline (:ui modeline)) (fci (:ui fill-column)) (evil-goggles (:ui ophints)) - (tabbar (:ui tabs))) + (tabbar (:ui tabs)) + (pretty-code (:ui ligatures))) (:app (email (:email mu4e)) (notmuch (:email notmuch))) (:lang (perl (:lang raku)))) diff --git a/docs/faq.org b/docs/faq.org index 903d0916f..a29bb0444 100644 --- a/docs/faq.org +++ b/docs/faq.org @@ -492,7 +492,7 @@ What can you do about it? but can be a bit of a hassle to set up. There are packages available for [[https://aur.archlinux.org/packages/emacs-native-comp-git/][Arch Linux]], [[https://github.com/flatwhatson/guix-channel][Guix]] and [[https://github.com/nix-community/emacs-overlay][Nix users]]. [[https://www.emacswiki.org/emacs/GccEmacs][More information available on EmacsWiki]]. 3. Disable some of Doom's slowest modules. The biggest offenders tend to be: - =:ui tabs=, =:ui indent-guides=, =:ui pretty-code=, =:ui word-wrap= and =:ui + =:ui tabs=, =:ui indent-guides=, =:ui ligatures, =:ui word-wrap= and =:ui vc-gutter=. 4. Turn off line numbers ~(setq display-line-numbers-type nil)~. It's known to slow down scrolling, in particular. @@ -1213,7 +1213,7 @@ Here are a few common causes for random crashes: Or disable the =:ui doom-dashboard= & =:tools magit= modules (see [[https://github.com/hlissner/doom-emacs/issues/1170][#1170]]). + Ligatures and some fonts can cause Emacs to crash. You may want to try a - different font, or disable the =:ui pretty-code= module. + different font, or disable the =:ui ligatures module. ** Can't load my theme; ~unable to find theme file for X~ errors This means Emacs can't find the X-theme.el file for the theme you want to load. diff --git a/docs/modules.org b/docs/modules.org index 25c1ac8af..c3ed648d7 100644 --- a/docs/modules.org +++ b/docs/modules.org @@ -201,13 +201,13 @@ Aesthetic modules that affect the Emacs interface or user experience. + [[file:../modules/ui/hl-todo/README.org][hl-todo]] - TODO + [[file:../modules/ui/hydra/README.org][hydra]] - TODO + indent-guides - TODO ++ [[file:/mnt/projects/conf/doom-emacs/modules/ui/ligatures/README.org][ligatures]] =+extra +fira +hasklig +iosevka +pragmata-pro= - Ligature support for Emacs + [[file:../modules/ui/minimap/README.org][minimap]] - TODO + [[file:../modules/ui/modeline/README.org][modeline]] =+light= - TODO + [[file:../modules/ui/nav-flash/README.org][nav-flash]] - TODO + [[file:../modules/ui/neotree/README.org][neotree]] - TODO + [[file:../modules/ui/ophints/README.org][ophints]] - TODO + [[file:../modules/ui/popup/README.org][popup]] =+all +defaults= - Makes temporary/disposable windows less intrusive -+ [[file:../modules//ui/pretty-code/README.org][pretty-code]] =+fira +hasklig +iosevka +pragmata-pro= - TODO + [[file:../modules/ui/tabs/README.org][tabs]] - TODO + treemacs - TODO + [[file:../modules/ui/unicode/README.org][unicode]] - TODO diff --git a/init.example.el b/init.example.el index f03e1169f..01d9f7594 100644 --- a/init.example.el +++ b/init.example.el @@ -34,13 +34,13 @@ hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW ;;hydra ;;indent-guides ; highlighted indent columns + ;;ligatures ; ligatures and symbols to make your code pretty again ;;minimap ; show a map of the code on the side modeline ; snazzy, Atom-inspired modeline, plus API ;;nav-flash ; blink cursor line after big motions ;;neotree ; a project drawer, like NERDTree for vim ophints ; highlight the region an operation acts on (popup +defaults) ; tame sudden yet inevitable temporary windows - ;;pretty-code ; ligatures or substitute text with pretty symbols ;;tabs ; a tab bar for Emacs ;;treemacs ; a project drawer, like neotree but cooler ;;unicode ; extended unicode support for various languages diff --git a/modules/lang/cc/config.el b/modules/lang/cc/config.el index 82843472f..a24ccf8c8 100644 --- a/modules/lang/cc/config.el +++ b/modules/lang/cc/config.el @@ -51,7 +51,7 @@ This is ignored by ccls.") (set-rotate-patterns! 'c++-mode :symbols '(("public" "protected" "private") ("class" "struct"))) - (set-pretty-symbols! '(c-mode c++-mode) + (set-ligatures! '(c-mode c++-mode) ;; Functional ;; :def "void " ;; Types diff --git a/modules/lang/dart/config.el b/modules/lang/dart/config.el index ca4509edc..74e90b814 100644 --- a/modules/lang/dart/config.el +++ b/modules/lang/dart/config.el @@ -7,7 +7,7 @@ (when (and (featurep! +flutter) IS-LINUX) (when-let (path (doom-glob "/opt/flutter/bin/cache/dart-sdk")) (setq flutter-sdk-path path))) - (set-pretty-symbols! '(dart-mode) + (set-ligatures! '(dart-mode) ;; Functional :def "Function" :lambda "() =>" diff --git a/modules/lang/elixir/config.el b/modules/lang/elixir/config.el index 565e60c65..34bb0abc9 100644 --- a/modules/lang/elixir/config.el +++ b/modules/lang/elixir/config.el @@ -14,7 +14,7 @@ ;; a subset of them (defined below). (provide 'smartparens-elixir) :config - (set-pretty-symbols! 'elixir-mode + (set-ligatures! 'elixir-mode ;; Functional :def "def" :lambda "fn" diff --git a/modules/lang/elm/config.el b/modules/lang/elm/config.el index 504adbce8..6d2f40029 100644 --- a/modules/lang/elm/config.el +++ b/modules/lang/elm/config.el @@ -6,7 +6,7 @@ (set-company-backend! 'elm-mode 'company-elm)) (set-repl-handler! 'elm-mode #'run-elm-interactive) - (set-pretty-symbols! 'elm-mode + (set-ligatures! 'elm-mode :null "null" :true "true" :false "false" :int "Int" :str "String" diff --git a/modules/lang/emacs-lisp/config.el b/modules/lang/emacs-lisp/config.el index dcbc77df3..1a97e1c27 100644 --- a/modules/lang/emacs-lisp/config.el +++ b/modules/lang/emacs-lisp/config.el @@ -33,7 +33,7 @@ employed so that flycheck still does *some* helpful linting.") :definition #'+emacs-lisp-lookup-definition :documentation #'+emacs-lisp-lookup-documentation) (set-docsets! '(emacs-lisp-mode lisp-interaction-mode) "Emacs Lisp") - (set-pretty-symbols! 'emacs-lisp-mode :lambda "lambda") + (set-ligatures! 'emacs-lisp-mode :lambda "lambda") (set-rotate-patterns! 'emacs-lisp-mode :symbols '(("t" "nil") ("let" "let*") diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index 1f7532ee3..e2f589845 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -7,7 +7,7 @@ "MarionetteJS" "MomentJS" "NodeJS" "PrototypeJS" "React" "RequireJS" "SailsJS" "UnderscoreJS" "VueJS" "ZeptoJS") - (set-pretty-symbols! '(js2-mode rjsx-mode web-mode) + (set-ligatures! '(js2-mode rjsx-mode web-mode) ;; Functional :def "function" :lambda "() =>" @@ -95,7 +95,7 @@ :config (set-electric! 'typescript-mode :chars '(?\} ?\)) :words '("||" "&&")) - (set-pretty-symbols! 'typescript-mode + (set-ligatures! 'typescript-mode ;; Functional :def "function" :lambda "() =>" diff --git a/modules/lang/ocaml/README.org b/modules/lang/ocaml/README.org index ac89cab0f..e9d1b07f2 100644 --- a/modules/lang/ocaml/README.org +++ b/modules/lang/ocaml/README.org @@ -87,7 +87,7 @@ tools. | =utop-eval-region= | =SPC c e= | evaluate selected region in =utop= | ** Hacks -+ =set-pretty-symbols!= is called with the full tuareg prettify symbol list, this ++ =set-ligatures!= is called with the full tuareg prettify symbol list, this can cause columns to change as certain keywords are shortened (e.g. =fun= becomes \lambda. + =tuareg-opam-update-env= is called the first time =tuareg= is loaded diff --git a/modules/lang/ocaml/config.el b/modules/lang/ocaml/config.el index 490e4eb1f..e5a1e709d 100644 --- a/modules/lang/ocaml/config.el +++ b/modules/lang/ocaml/config.el @@ -10,7 +10,7 @@ (after! tuareg ;; tuareg-mode has the prettify symbols itself - (set-pretty-symbols! 'tuareg-mode :alist + (set-ligatures! 'tuareg-mode :alist (append tuareg-prettify-symbols-basic-alist tuareg-prettify-symbols-extra-alist)) ;; harmless if `prettify-symbols-mode' isn't active diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 8b7eacfe0..4c565cb96 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -183,7 +183,7 @@ This forces it to read the background before rendering." ;; Automatic indent detection in org files is meaningless (add-to-list 'doom-detect-indentation-excluded-modes 'org-mode) - (set-pretty-symbols! 'org-mode + (set-ligatures! 'org-mode :name "#+NAME:" :name "#+name:" :src_block "#+BEGIN_SRC" diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index a13b7dc8d..aaacd0876 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -21,7 +21,7 @@ (set-repl-handler! 'php-mode #'php-boris) (set-lookup-handlers! 'php-mode :documentation #'php-search-documentation) (set-formatter! 'php-mode #'php-cs-fixer-fix) - (set-pretty-symbols! 'php-mode + (set-ligatures! 'php-mode ;; Functional :lambda "function()" :def "function" diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index 95f351a32..302b8d38a 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -31,7 +31,7 @@ called.") (set-repl-handler! 'python-mode #'+python/open-repl :persist t) (set-docsets! 'python-mode "Python 3" "NumPy" "SciPy") - (set-pretty-symbols! 'python-mode + (set-ligatures! 'python-mode ;; Functional :def "def" :lambda "lambda" diff --git a/modules/lang/racket/config.el b/modules/lang/racket/config.el index 124cc434f..70b4d2506 100644 --- a/modules/lang/racket/config.el +++ b/modules/lang/racket/config.el @@ -16,7 +16,7 @@ :definition #'+racket-lookup-definition :documentation #'+racket-lookup-documentation) (set-docsets! 'racket-mode "Racket") - (set-pretty-symbols! 'racket-mode + (set-ligatures! 'racket-mode :lambda "lambda" :map "map" :dot ".") diff --git a/modules/lang/rust/config.el b/modules/lang/rust/config.el index 1b81f31a5..cb850f6e9 100644 --- a/modules/lang/rust/config.el +++ b/modules/lang/rust/config.el @@ -69,7 +69,7 @@ (use-package! racer :unless (featurep! +lsp) - :hook (rustic-mode . racer-mode) + :hook (rustic-mode-local-vars . racer-mode) :init ;; HACK Fix #2132: `racer' depends on `rust-mode', which tries to modify ;; `auto-mode-alist'. We make extra sure that doesn't stick, especially diff --git a/modules/lang/scala/config.el b/modules/lang/scala/config.el index 11f3f06e3..1329f9202 100644 --- a/modules/lang/scala/config.el +++ b/modules/lang/scala/config.el @@ -18,7 +18,7 @@ (when (featurep! +lsp) (add-hook 'scala-mode-local-vars-hook #'lsp!)) - (set-pretty-symbols! 'scala-mode + (set-ligatures! 'scala-mode ;; Functional :def "def" :composition "compose" diff --git a/modules/lang/sh/config.el b/modules/lang/sh/config.el index 04fa8213e..b6a0b270b 100755 --- a/modules/lang/sh/config.el +++ b/modules/lang/sh/config.el @@ -16,7 +16,7 @@ :config (set-electric! 'sh-mode :words '("else" "elif" "fi" "done" "then" "do" "esac" ";;")) (set-repl-handler! 'sh-mode #'+sh/open-repl) - (set-pretty-symbols! 'sh-mode + (set-ligatures! 'sh-mode ;; Functional :def "function" ;; Types diff --git a/modules/ui/ligatures/+fira.el b/modules/ui/ligatures/+fira.el new file mode 100644 index 000000000..191dabe1e --- /dev/null +++ b/modules/ui/ligatures/+fira.el @@ -0,0 +1,123 @@ +;;; ui/ligatures/+fira.el -*- lexical-binding: t; -*- + +(+ligatures--def-font fira + ("Fira Code Symbol" + :range '(#Xe100 . #Xe16f) + :url "https://github.com/tonsky/FiraCode/raw/13234c0/distr/ttf/%s" + :files '("FiraCode-Bold.ttf" + "FiraCode-Light.ttf" + "FiraCode-Medium.ttf" + "FiraCode-Regular.ttf" + "FiraCode-Retina.ttf")) + ("www" . #Xe100) + ("**" . #Xe101) + ("***" . #Xe102) + ("**/" . #Xe103) + ("*>" . #Xe104) + ("*/" . #Xe105) + ("\\\\" . #Xe106) + ("\\\\\\" . #Xe107) + ("{-" . #Xe108) + ("[]" . #Xe109) + ("::" . #Xe10a) + (":::" . #Xe10b) + (":=" . #Xe10c) + ("!!" . #Xe10d) + ("!=" . #Xe10e) + ("!==" . #Xe10f) + ("-}" . #Xe110) + ("--" . #Xe111) + ("---" . #Xe112) + ("-->" . #Xe113) + ("->" . #Xe114) + ("->>" . #Xe115) + ("-<" . #Xe116) + ("-<<" . #Xe117) + ("-~" . #Xe118) + ("#{" . #Xe119) + ("#[" . #Xe11a) + ("##" . #Xe11b) + ("###" . #Xe11c) + ("####" . #Xe11d) + ("#(" . #Xe11e) + ("#?" . #Xe11f) + ("#_" . #Xe120) + ("#_(" . #Xe121) + (".-" . #Xe122) + (".=" . #Xe123) + (".." . #Xe124) + ("..<" . #Xe125) + ("..." . #Xe126) + ("?=" . #Xe127) + ("??" . #Xe128) + (";;" . #Xe129) + ("/*" . #Xe12a) + ("/**" . #Xe12b) + ("/=" . #Xe12c) + ("/==" . #Xe12d) + ("/>" . #Xe12e) + ("//" . #Xe12f) + ("///" . #Xe130) + ("&&" . #Xe131) + ("||" . #Xe132) + ("||=" . #Xe133) + ("|=" . #Xe134) + ("|>" . #Xe135) + ("^=" . #Xe136) + ("$>" . #Xe137) + ("++" . #Xe138) + ("+++" . #Xe139) + ("+>" . #Xe13a) + ("=:=" . #Xe13b) + ("==" . #Xe13c) + ("===" . #Xe13d) + ("==>" . #Xe13e) + ("=>" . #Xe13f) + ("=>>" . #Xe140) + ("=<" . #Xe141) + ("=<<" . #Xe142) + ("=/=" . #Xe143) + (">-" . #Xe144) + (">=" . #Xe145) + (">=>" . #Xe146) + (">>" . #Xe147) + (">>-" . #Xe148) + (">>=" . #Xe149) + (">>>" . #Xe14a) + ("<*" . #Xe14b) + ("<*>" . #Xe14c) + ("<|" . #Xe14d) + ("<|>" . #Xe14e) + ("<$" . #Xe14f) + ("<$>" . #Xe150) + ("" . #Xe101) + ("<--->" . #Xe102) + ("<---->" . #Xe103) + ("<----->" . #Xe104) + ;; Double-ended equals arrows + ("<=>" . #Xe105) + ("<==>" . #Xe106) + ("<===>" . #Xe107) + ("<====>" . #Xe108) + ("<=====>" . #Xe109) + ;; Double-ended asterisk operators + ("<**>" . #Xe10a) + ("<***>" . #Xe10b) + ("<****>" . #Xe10c) + ("<*****>" . #Xe10d) + ;; HTML comments + ("" . #Xe152) + ("-->-" . #Xe153) + ("-->--" . #Xe154) + ("-->>" . #Xe155) + ("-->>-" . #Xe156) + ("-->>--" . #Xe157) + ("-->>>" . #Xe158) + ("-->>>-" . #Xe159) + ("-->>>--" . #Xe15a) + (">-" . #Xe15b) + (">--" . #Xe15c) + (">>-" . #Xe15d) + (">>--" . #Xe15e) + (">>>-" . #Xe15f) + (">>>--" . #Xe160) + ("=>" . #Xe161) + ("=>=" . #Xe162) + ("=>==" . #Xe163) + ("=>>" . #Xe164) + ("=>>=" . #Xe165) + ("=>>==" . #Xe166) + ("=>>>" . #Xe167) + ("=>>>=" . #Xe168) + ("=>>>==" . #Xe169) + ("==>" . #Xe16a) + ("==>=" . #Xe16b) + ("==>==" . #Xe16c) + ("==>>" . #Xe16d) + ("==>>=" . #Xe16e) + ("==>>==" . #Xe16f) + ("==>>>" . #Xe170) + ("==>>>=" . #Xe171) + ("==>>>==" . #Xe172) + (">=" . #Xe173) + (">==" . #Xe174) + (">>=" . #Xe175) + (">>==" . #Xe176) + (">>>=" . #Xe177) + (">>>==" . #Xe178) + ("<-" . #Xe179) + ("-<-" . #Xe17a) + ("--<-" . #Xe17b) + ("<<-" . #Xe17c) + ("-<<-" . #Xe17d) + ("--<<-" . #Xe17e) + ("<<<-" . #Xe17f) + ("-<<<-" . #Xe180) + ("--<<<-" . #Xe181) + ("<--" . #Xe182) + ("-<--" . #Xe183) + ("--<--" . #Xe184) + ("<<--" . #Xe185) + ("-<<--" . #Xe186) + ("--<<--" . #Xe187) + ("<<<--" . #Xe188) + ("-<<<--" . #Xe189) + ("--<<<--" . #Xe18a) + ("-<" . #Xe18b) + ("--<" . #Xe18c) + ("-<<" . #Xe18d) + ("--<<" . #Xe18e) + ("-<<<" . #Xe18f) + ("--<<<" . #Xe190) + ("<=" . #Xe191) + ("=<=" . #Xe192) + ("==<=" . #Xe193) + ("<<=" . #Xe194) + ("=<<=" . #Xe195) + ("==<<=" . #Xe196) + ("<<<=" . #Xe197) + ("=<<<=" . #Xe198) + ("==<<<=" . #Xe199) + ("<==" . #Xe19a) + ("=<==" . #Xe19b) + ("==<==" . #Xe19c) + ("<<==" . #Xe19d) + ("=<<==" . #Xe19e) + ("==<<==" . #Xe19f) + ("<<<==" . #Xe1a0) + ("=<<<==" . #Xe1a1) + ("==<<<==" . #Xe1a2) + ("=<" . #Xe1a3) + ("==<" . #Xe1a4) + ("=<<" . #Xe1a5) + ("==<<" . #Xe1a6) + ("=<<<" . #Xe1a7) + ("==<<<" . #Xe1a8) + ;; Monadic operators + (">=>" . #Xe1a9) + (">->" . #Xe1aa) + (">-->" . #Xe1ab) + (">==>" . #Xe1ac) + ("<=<" . #Xe1ad) + ("<-<" . #Xe1ae) + ("<--<" . #Xe1af) + ("<==<" . #Xe1b0) + ;; Composition operators + (">>" . #Xe1b1) + (">>>" . #Xe1b2) + ("<<" . #Xe1b3) + ("<<<" . #Xe1b4) + ;; Lens operators + (":+" . #Xe1b5) + (":-" . #Xe1b6) + (":=" . #Xe1b7) + ("+:" . #Xe1b8) + ("-:" . #Xe1b9) + ("=:" . #Xe1ba) + ("=^" . #Xe1bb) + ("=+" . #Xe1bc) + ("=-" . #Xe1bd) + ("=*" . #Xe1be) + ("=/" . #Xe1bf) + ("=%" . #Xe1c0) + ("^=" . #Xe1c1) + ("+=" . #Xe1c2) + ("-=" . #Xe1c3) + ("*=" . #Xe1c4) + ("/=" . #Xe1c5) + ("%=" . #Xe1c6) + ;; Logical + ("/\\" . #Xe1c7) + ("\\/" . #Xe1c8) + ;; Semigroup/monoid operators + ("<>" . #Xe1c9) + ("<+" . #Xe1ca) + ("<+>" . #Xe1cb) + ("+>" . #Xe1cc)) diff --git a/modules/ui/ligatures/+pragmata-pro.el b/modules/ui/ligatures/+pragmata-pro.el new file mode 100644 index 000000000..8759f73b2 --- /dev/null +++ b/modules/ui/ligatures/+pragmata-pro.el @@ -0,0 +1,249 @@ +;;; ui/ligatures/+pragmata-pro.el -*- lexical-binding: t; -*- + +(+ligatures--def-font pragmata-pro + ("PragmataPro") + ;; Double-ended hyphen arrows + ("[ERROR]" . #XE2C0) + ("[DEBUG]" . #XE2C1) + ("[INFO]" . #XE2C2) + ("[WARN]" . #XE2C3) + ("[WARNING]" . #XE2C4) + ("[ERR]" . #XE2C5) + ("[FATAL]" . #XE2C6) + ("[TRACE]" . #XE2C7) + ("[FIXME]" . #XE2C8) + ("[TODO]" . #XE2C9) + ("[BUG]" . #XE2CA) + ("[NOTE]" . #XE2CB) + ("[HACK]" . #XE2CC) + ("[MARK]" . #XE2CD) + ("# ERROR" . #XE2F0) + ("# DEBUG" . #XE2F1) + ("# INFO" . #XE2F2) + ("# WARN" . #XE2F3) + ("# WARNING" . #XE2F4) + ("# ERR" . #XE2F5) + ("# FATAL" . #XE2F6) + ("# TRACE" . #XE2F7) + ("# FIXME" . #XE2F8) + ("# TODO" . #XE2F9) + ("# BUG" . #XE2FA) + ("# NOTE" . #XE2FB) + ("# HACK" . #XE2FC) + ("# MARK" . #XE2FD) + ("// ERROR" . #XE2E0) + ("// DEBUG" . #XE2E1) + ("// INFO" . #XE2E2) + ("// WARN" . #XE2E3) + ("// WARNING". #XE2E4) + ("// ERR" . #XE2E5) + ("// FATAL" . #XE2E6) + ("// TRACE" . #XE2E7) + ("// FIXME" . #XE2E8) + ("// TODO" . #XE2E9) + ("// BUG" . #XE2EA) + ("// NOTE" . #XE2EB) + ("// HACK" . #XE2EC) + ("// MARK" . #XE2ED) + ("!!" . #XE900) + ("!=" . #XE901) + ("!==" . #XE902) + ("!!!" . #XE903) + ("!≡" . #XE904) + ("!≡≡" . #XE905) + ("!>" . #XE906) + ("!=<" . #XE907) + ("#(" . #XE920) + ("#_" . #XE921) + ("#{" . #XE922) + ("#?" . #XE923) + ("#>" . #XE924) + ("##" . #XE925) + ("#_(" . #XE926) + ("%=" . #XE930) + ("%>" . #XE931) + ("%>%" . #XE932) + ("%<%" . #XE933) + ("&%" . #XE940) + ("&&" . #XE941) + ("&*" . #XE942) + ("&+" . #XE943) + ("&-" . #XE944) + ("&/" . #XE945) + ("&=" . #XE946) + ("&&&" . #XE947) + ("&>" . #XE948) + ("$>" . #XE955) + ("***" . #XE960) + ("*=" . #XE961) + ("*/" . #XE962) + ("*>" . #XE963) + ("++" . #XE970) + ("+++" . #XE971) + ("+=" . #XE972) + ("+>" . #XE973) + ("++=" . #XE974) + ("--" . #XE980) + ("-<" . #XE981) + ("-<<" . #XE982) + ("-=" . #XE983) + ("->" . #XE984) + ("->>" . #XE985) + ("---" . #XE986) + ("-->" . #XE987) + ("-+-" . #XE988) + ("-\\/" . #XE989) + ("-|>" . #XE98A) + ("-<|" . #XE98B) + (".." . #XE990) + ("..." . #XE991) + ("..<" . #XE992) + (".>" . #XE993) + (".~" . #XE994) + (".=" . #XE995) + ("/*" . #XE9A0) + ("//" . #XE9A1) + ("/>" . #XE9A2) + ("/=" . #XE9A3) + ("/==" . #XE9A4) + ("///" . #XE9A5) + ("/**" . #XE9A6) + (":::" . #XE9AF) + ("::" . #XE9B0) + (":=" . #XE9B1) + (":≡" . #XE9B2) + (":>" . #XE9B3) + (":=>" . #XE9B4) + (":(" . #XE9B5) + (":-(" . #XE9B6) + (":)" . #XE9B7) + (":-)" . #XE9B8) + (":/" . #XE9B9) + (":\\" . #XE9BA) + (":3" . #XE9BB) + (":D" . #XE9BC) + (":P" . #XE9BD) + (":>:" . #XE9BE) + (":<:" . #XE9BF) + ("<$>" . #XE9C0) + ("<*" . #XE9C1) + ("<*>" . #XE9C2) + ("<+>" . #XE9C3) + ("<-" . #XE9C4) + ("<<" . #XE9C5) + ("<<<" . #XE9C6) + ("<<=" . #XE9C7) + ("<=" . #XE9C8) + ("<=>" . #XE9C9) + ("<>" . #XE9CA) + ("<|>" . #XE9CB) + ("<<-" . #XE9CC) + ("<|" . #XE9CD) + ("<=<" . #XE9CE) + ("<~" . #XE9CF) + ("<~~" . #XE9D0) + ("<<~" . #XE9D1) + ("<$" . #XE9D2) + ("<+" . #XE9D3) + ("" . #XE9D4) + ("<@>" . #XE9D5) + ("<#>" . #XE9D6) + ("<%>" . #XE9D7) + ("<^>" . #XE9D8) + ("<&>" . #XE9D9) + ("" . #XE9DA) + ("<.>" . #XE9DB) + ("" . #XE9DC) + ("<\\>" . #XE9DD) + ("<\">" . #XE9DE) + ("<:>" . #XE9DF) + ("<~>" . #XE9E0) + ("<**>" . #XE9E1) + ("<<^" . #XE9E2) + ("" . #XE9EF) + ("" . #XE9F8) + ("<<==" . #XE9F9) + ("<==" . #XE9FA) + ("=<<" . #XEA00) + ("==" . #XEA01) + ("===" . #XEA02) + ("==>" . #XEA03) + ("=>" . #XEA04) + ("=~" . #XEA05) + ("=>>" . #XEA06) + ("=/=" . #XEA07) + ("=~=" . #XEA08) + ("==>>" . #XEA09) + ("≡≡" . #XEA10) + ("≡≡≡" . #XEA11) + ("≡:≡" . #XEA12) + (">-" . #XEA20) + (">=" . #XEA21) + (">>" . #XEA22) + (">>-" . #XEA23) + (">>=" . #XEA24) + (">>>" . #XEA25) + (">=>" . #XEA26) + (">>^" . #XEA27) + (">>|" . #XEA28) + (">!=" . #XEA29) + (">->" . #XEA2A) + ("??" . #XEA40) + ("?~" . #XEA41) + ("?=" . #XEA42) + ("?>" . #XEA43) + ("???" . #XEA44) + ("?." . #XEA45) + ("^=" . #XEA48) + ("^." . #XEA49) + ("^?" . #XEA4A) + ("^.." . #XEA4B) + ("^<<" . #XEA4C) + ("^>>" . #XEA4D) + ("^>" . #XEA4E) + ("\\\\" . #XEA50) + ("\\>" . #XEA51) + ("\\/-" . #XEA52) + ("@>" . #XEA57) + ("|=" . #XEA60) + ("||" . #XEA61) + ("|>" . #XEA62) + ("|||" . #XEA63) + ("|+|" . #XEA64) + ("|->" . #XEA65) + ("|-->" . #XEA66) + ("|=>" . #XEA67) + ("|==>" . #XEA68) + ("|>-" . #XEA69) + ("|<<" . #XEA6A) + ("||>" . #XEA6B) + ("|>>" . #XEA6C) + ("|-" . #XEA6D) + ("||-" . #XEA6E) + ("~=" . #XEA70) + ("~>" . #XEA71) + ("~~>" . #XEA72) + ("~>>" . #XEA73) + ("[[" . #XEA80) + ("]]" . #XEA81) + ("\">" . #XEA90) + ("_|_" . #XEA97)) diff --git a/modules/ui/pretty-code/README.org b/modules/ui/ligatures/README.org similarity index 63% rename from modules/ui/pretty-code/README.org rename to modules/ui/ligatures/README.org index 1d3ce55ea..569a2e8ff 100644 --- a/modules/ui/pretty-code/README.org +++ b/modules/ui/ligatures/README.org @@ -1,4 +1,4 @@ -#+TITLE: ui/pretty-code +#+TITLE: ui/ligatures #+DATE: June 16, 2018 #+SINCE: v2.0.9 #+STARTUP: inlineimages nofold @@ -10,28 +10,31 @@ - [[#font-ligatures-module-flags][Font ligatures module flags]] - [[#plugins][Plugins]] - [[#prerequisites][Prerequisites]] - - [[#ligatures][Ligatures]] - - [[#emacs-mac-port-or-emacs-28][Emacs-mac port or Emacs 28+]] - - [[#not-emacs-mac-and-emacs--27][Not Emacs-mac and Emacs <= 27]] + - [[#mutsuharus-emacs-mac-port-or-emacs-28-with-harfbuzz-support][Mutsuharu's emacs-mac port or Emacs 28+ with Harfbuzz support]] + - [[#not-emacs-mac-and-emacs--27][Not Emacs-mac and Emacs <= 27]] - [[#features][Features]] - [[#mathematical-symbols-replacement][Mathematical symbols replacement]] - [[#coding-ligatures][Coding ligatures]] - [[#configuration][Configuration]] - - [[#set-pretty-symbols][~set-pretty-symbols!~]] + - [[#set-ligatures][~set-ligatures!~]] - [[#troubleshooting][Troubleshooting]] * Description -This module enables ligatures and/or arbitrary symbol substitutions with -~prettify-symbols-mode~. +This module enables ligatures and arbitrary symbol substitutions with +~mac-auto-operator-composition-mode~ (on supported macOS systems) or composition +tables (harfbuzz on Emacs 28), falling back on ~prettify-symbols-mode~ +otherwise. ** Maintainers This module has no dedicated maintainers. ** Module Flags ++ =+extra= Enables extra symbol substitutions in certain modes, for example + ~lambda~ in lisps are replaced with ~λ~. + *** Font ligatures module flags -Those flags are ignored on emacs-mac and on other platforms if running emacs 28+ -with harfbuzz feature. In those cases, ligatures are handled without needing the -extra configuration provided by those flags. +This module provides four flags for enabling fall-back ligature support for a +particular font. They are: + =+fira= Enables =Fira Code= ligatures. This requires Fira Code Symbol and a patched version of Fira Code (see below). @@ -42,32 +45,35 @@ extra configuration provided by those flags. + =+pragmata-pro= Enable =Pragmata Pro= ligatures. This requires the [[https://www.fsd.it/shop/fonts/pragmatapro/][Pragmata Pro font]]. +#+begin_quote +All these flags are ignored _if_ you're sporting either a) Emacs 28+ with +Harfbuzz support (which can compose ligatures natively), or b) Mitsuharu's +=emacs-mac= build on macOS (which uses ~mac-auto-operator-composition-mode~). +#+end_quote + ** Plugins This module installs no packages. * Prerequisites -** Ligatures -For ligatures to work, you must either: +This module requires one of three setups for ligatures to work: -- Have a recent enough version of Emacs which will compose ligatures - automatically, or -- Use one of our font-specific configurations. +- A recent enough version of Emacs which will compose ligatures automatically + (Emacs 28 with Harfbuzz support), or +- Mitsuharu's =emacs-mac= build on macOS (available on homebrew), or +- A patched font for Doom's fallback ligature support. -*** Emacs-mac port or Emacs 28+ -Ligatures are handled without needing additional configuration. If this doesn't -work, report a bug with your current version of emacs and the ligatures which -aren't working. +** Mutsuharu's emacs-mac port or Emacs 28+ with Harfbuzz support +Ligatures should be handled without any additional configuration. -*** Not Emacs-mac and Emacs <= 27 +** Not Emacs-mac and Emacs <= 27 1. Enable one of the four ligature font flags: =+fira=, =+hasklig=, =+iosevka= or =+pragmata-pro=. 2. Install the patched version of the associated font with ~M-x - +pretty-code/install-patched-font~. Note: Pragmata Pro cannot be installed - this way because it is a non-free font and must be purchased and installed + +ligatures/install-patched-font~. Note: Pragmata Pro cannot be installed this + way because it is a non-free font and must be purchased and installed manually. * TODO Features -# An in-depth list of features, how to use them, and their dependencies. ** TODO Mathematical symbols replacement ** Coding ligatures This module includes configuration to compose combinations like =->= or =::= @@ -80,8 +86,8 @@ emacs, this is implemented in two different ways : with the correct symbol. The mapping between =->=-like sequences and unicode values in the font are font-specific ; therefore =+fira=, =+iosevka=... files and specific fonts are necessary for it to work. -- composition-function-table method :: regexes are used to match all the usual - sequences which are composed into ligatures. These regexes are passed to emacs +- composition-function-table method :: regexps are used to match all the usual + sequences which are composed into ligatures. These regexps are passed to emacs directly, which asks Harfbuzz to shape it. Ligatures are obtained automatically depending on the capabilities of the font, and no font-specific configuration is necessary. @@ -96,9 +102,7 @@ Even though harfbuzz has been included in emacs 27, there is currently a [[https emacs 27. * TODO Configuration -# How to configure this module, including common problems and how to address them. - -** TODO ~set-pretty-symbols!~ +** TODO ~set-ligatures!~ * TODO Troubleshooting # Common issues and their solution, or places to look for help. diff --git a/modules/ui/ligatures/autoload/install.el b/modules/ui/ligatures/autoload/install.el new file mode 100644 index 000000000..3040f8a24 --- /dev/null +++ b/modules/ui/ligatures/autoload/install.el @@ -0,0 +1,58 @@ +;;; ui/ligatures/autoload/install.el -*- lexical-binding: t; -*- +;;;###if (or (featurep! +fira) (featurep! +hasklig) (featurep! +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... ") + (shell-command-to-string "fc-cache -f -v")) + (if IS-WINDOW + (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 &keys _range url files) + (or (alist-get font-id +ligatures--font-alist) + (user-error "%S is not a valid font" font-id)) + (+ligatures--install-font prefix font-name url files))) diff --git a/modules/ui/pretty-code/autoload/pretty-code.el b/modules/ui/ligatures/autoload/ligatures.el similarity index 60% rename from modules/ui/pretty-code/autoload/pretty-code.el rename to modules/ui/ligatures/autoload/ligatures.el index bdd3ce46b..f9f4b761c 100644 --- a/modules/ui/pretty-code/autoload/pretty-code.el +++ b/modules/ui/ligatures/autoload/ligatures.el @@ -1,16 +1,15 @@ -;;; ui/pretty-code/autoload/pretty-code.el -*- lexical-binding: t; -*- +;;; ui/ligatures/autoload/ligatures.el -*- lexical-binding: t; -*- -;;;###autoload -(defvar +pretty-code-symbols-alist '((t)) - "An alist containing a mapping of major modes to its value for -`prettify-symbols-alist'.") +;; DEPRECATED +;;;###autodef +(define-obsolete-function-alias 'set-pretty-symbols! 'set-ligatures! "3.0.0") ;;;###autodef -(defun set-pretty-symbols! (modes &rest plist) +(defun set-ligatures! (modes &rest plist) "Associates string patterns with icons in certain major-modes. MODES is a major mode symbol or a list of them. - PLIST is a property list whose keys must match keys in `+pretty-code-symbols', + PLIST is a property list whose keys must match keys in `+ligatures-classes', 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. @@ -19,33 +18,33 @@ This function accepts one special property: :alist ALIST Appends ALIST to `prettify-symbols-alist' literally, without mapping text to - `+pretty-code-symbols'. + `+ligatures-classes'. For example, the rule for emacs-lisp-mode is very simple: - (set-pretty-symbols! '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 `+pretty-code-symbols'. +assicated with :lambda in `+ligatures-classes'. Pretty symbols can be unset for emacs-lisp-mode with: - (set-pretty-symbols! 'emacs-lisp-mode nil)" + (set-ligatures! 'emacs-lisp-mode nil)" (declare (indent defun)) (if (null (car-safe plist)) (dolist (mode (doom-enlist modes)) - (assq-delete-all mode +pretty-code-symbols-alist)) + (assq-delete-all mode +ligatures-extra-alist)) (let (results) (while plist (let ((key (pop plist))) (if (eq key :alist) (prependq! results (pop plist)) - (when-let (char (plist-get +pretty-code-symbols key)) + (when-let (char (plist-get +ligatures-classes key)) (push (cons (pop plist) char) results))))) (dolist (mode (doom-enlist modes)) - (setf (alist-get mode +pretty-code-symbols-alist) - (if-let (old-results (alist-get mode +pretty-code-symbols-alist)) + (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)))))) diff --git a/modules/ui/pretty-code/config.el b/modules/ui/ligatures/config.el similarity index 54% rename from modules/ui/pretty-code/config.el rename to modules/ui/ligatures/config.el index 195e0fe7a..015481716 100644 --- a/modules/ui/pretty-code/config.el +++ b/modules/ui/ligatures/config.el @@ -1,6 +1,6 @@ -;;; ui/pretty-code/config.el -*- lexical-binding: t; -*- +;;; ui/ligatures/config.el -*- lexical-binding: t; -*- -(defvar +pretty-code-symbols +(defvar +ligatures-classes '(;; org :name "»" :src_block "»" @@ -38,23 +38,13 @@ :tuple "⨂" :pipe "" ;; FIXME: find a non-private char :dot "•") - "Options plist for `set-pretty-symbols!'. + "Options plist for `set-ligatures!'. This should not contain any symbols from the Unicode Private Area! There is no universal way of getting the correct symbol as that area varies from font to font.") -(defvar +pretty-code-enabled-modes t - "List of major modes in which `prettify-symbols-mode' should be enabled. -If t, enable it everywhere. If the first element is 'not, enable it in any mode -besides what is listed.") - -(defvar +pretty-code-symbols-alist '((t)) - "An alist containing a mapping of major modes to its value for -`prettify-symbols-alist'.") - -;;; Automatic font-specific ligatures -(defvar +prog-ligatures-alist +(defvar +ligatures-composition-alist '((?! . "\\(?:!\\(?:==\\|[!=]\\)\\)") ; (regexp-opt '("!!" "!=" "!==")) (?# . "\\(?:#\\(?:###?\\|_(\\|[#(:=?[_{]\\)\\)") ; (regexp-opt '("##" "###" "####" "#(" "#:" "#=" "#?" "#[" "#_" "#_(" "#{")) (?$ . "\\(?:\\$>>?\\)") ; (regexp-opt '("$>" "$>>")) @@ -83,27 +73,42 @@ besides what is listed.") (?_ . "\\(?:_\\(?:|?_\\)\\)") ; (regexp-opt '("_|_" "__")) (?\( . "\\(?:(\\*\\)") ; (regexp-opt '("(*")) (?~ . "\\(?:~\\(?:~>\\|[=>@~-]\\)\\)")) ; (regexp-opt '("~-" "~=" "~>" "~@" "~~" "~~>")) - "An alist of all ligatures used by `+prog-ligatures-modes'. + "An alist of all ligatures used by `+ligatures-extras-in-modes'. The car is the character ASCII number, cdr is a regex which will call `font-shape-gstring' when matched. -Because of the underlying code in :ui pretty-code module, the regex should match -a string starting with the character contained in car. +Because of the underlying code in :ui ligatures module, the regex should match a +string starting with the character contained in car. This variable is used only if you built Emacs with Harfbuzz on a version >= 28") -(defvar +prog-ligatures-modes '(not org-mode) - "List of major modes in which ligatures should be enabled. +(defvar +ligatures-extra-alist '((t)) + "An alist mapping major modes to `prettify-symbols-alist' values.") -If t, enable it everywhere. Fundamental mode, and modes derived from special-mode, -comint-mode, eshell-mode and term-mode are *still* excluded. +(defvar +ligatures-in-modes + '(not special-mode comint-mode eshell-mode term-mode vterm-mode) + "List of major modes where ligatures should be enabled. -If the first element is 'not, enable it in any mode besides what is listed. + If t, enable it everywhere (except `fundamental-mode'). + If the first element is 'not, enable it in any mode besides what is listed. + If nil, don't enable ligatures anywhere.") -If nil, fallback to the prettify-symbols based replacement (add +font features to pretty-code).") +(defvar +ligatures-extras-in-modes t + "List of major modes where extra ligatures should be enabled. -(defun +pretty-code--correct-symbol-bounds (ligature-alist) +Extra ligatures are mode-specific substituions, defined in `+ligatures-classes' +and assigned with `set-ligatures!'. This variable controls where these are +enabled. + + If t, enable it everywhere (except `fundamental-mode'). + If the first element is 'not, enable it in any mode besides what is listed. + If nil, don't enable these extra ligatures anywhere (though it's more +efficient to remove the `+extra' flag from the :ui ligatures module instead).") + +(defvar +ligatures--init-font-hook nil) + +(defun +ligatures--correct-symbol-bounds (ligature-alist) "Prepend non-breaking spaces to a ligature. This way `compose-region' (called by `prettify-symbols-mode') will use the @@ -115,86 +120,94 @@ correct width of the symbols instead of the width measured by `char-width'." len (1- len))) (cons (car ligature-alist) acc))) -(defun +pretty-code-init-pretty-symbols-h () - "Enable `prettify-symbols-mode'. +(defun +ligatures--enable-p (modes) + "Return t if ligatures should be enabled in this buffer depending on MODES." + (unless (eq major-mode 'fundamental-mode) + (or (eq modes t) + (if (eq (car modes) 'not) + (not (apply #'derived-mode-p (cdr modes))) + (apply #'derived-mode-p modes))))) -If in fundamental-mode, or a mode derived from special, comint, eshell or term -modes, this function does nothing. +(defun +ligatures-init-buffer-h () + "Set up ligatures for the current buffer. -Otherwise it builds `prettify-code-symbols-alist' according to -`+pretty-code-symbols-alist' for the current major-mode." - (unless (or (eq major-mode 'fundamental-mode) - (eq (get major-mode 'mode-class) 'special) - (derived-mode-p 'comint-mode 'eshell-mode 'term-mode)) - (when (or (eq +pretty-code-enabled-modes t) - (if (eq (car +pretty-code-enabled-modes) 'not) - (not (memq major-mode (cdr +pretty-code-enabled-modes))) - (memq major-mode +pretty-code-enabled-modes))) - (setq prettify-symbols-alist - (append (cdr (assq major-mode +pretty-code-symbols-alist)) - (default-value 'prettify-symbols-alist))) - (when prettify-symbols-mode - (prettify-symbols-mode -1)) +Extra ligatures are mode-specific substituions, defined in +`+ligatures-classes', assigned with `set-ligatures!', and made possible +with `prettify-symbols-mode'. This variable controls where these are enabled. +See `+ligatures-extras-in-modes' to control what major modes this function can +and cannot run in." + (when after-init-time + (when (+ligatures--enable-p +ligatures-in-modes) + (if (boundp '+ligature--composition-table) + (setq-local composition-function-table +ligature--composition-table) + (run-hooks '+ligatures--init-font-hook) + (setq +ligatures--init-font-hook nil))) + (when (and (featurep! +extra) + (+ligatures--enable-p +ligatures-extras-in-modes)) + (prependq! prettify-symbols-alist (alist-get major-mode +ligatures-extra-alist))) + (when prettify-symbols-alist + (if prettify-symbols-mode (prettify-symbols-mode -1)) (prettify-symbols-mode +1)))) -(defun +pretty-code-init-ligatures-h () - "Enable ligatures. - -If in fundamental-mode, or a mode derived from special, comint, eshell or term -modes, this function does nothing. - -Otherwise it sets the buffer-local composition table to a composition table enhanced with -`+prog-ligatures-alist' ligatures regexes." - (unless (or (eq major-mode 'fundamental-mode) - (eq (get major-mode 'mode-class) 'special) - (derived-mode-p 'comint-mode 'eshell-mode 'term-mode)) - (when (or (eq +prog-ligatures-modes t) - (if (eq (car +prog-ligatures-modes) 'not) - (not (memq major-mode (cdr +prog-ligatures-modes))) - (memq major-mode +prog-ligatures-modes))) - (setq-local composition-function-table composition-ligature-table)))) - ;; ;;; Bootstrap -(add-hook 'after-change-major-mode-hook #'+pretty-code-init-pretty-symbols-h) - ;;;###package prettify-symbols ;; When you get to the right edge, it goes back to how it normally prints (setq prettify-symbols-unprettify-at-point 'right-edge) +(add-hook! 'doom-init-ui-hook :append + (defun +ligatures-init-h () + (add-hook 'after-change-major-mode-hook #'+ligatures-init-buffer-h))) + (cond - ;; The emacs-mac build of Emacs appear to have built-in support for ligatures, + ;; The emacs-mac build of Emacs appears to have built-in support for ligatures, ;; using the same composition-function-table method ;; https://bitbucket.org/mituharu/emacs-mac/src/26c8fd9920db9d34ae8f78bceaec714230824dac/lisp/term/mac-win.el?at=master#lines-345:805 ;; so use that instead if this module is enabled. ((and IS-MAC (fboundp 'mac-auto-operator-composition-mode)) - (mac-auto-operator-composition-mode)) + (add-hook 'doom-init-ui-hook #'mac-auto-operator-composition-mode 'append)) ;; Harfbuzz and Mac builds do not need font-specific ligature support - ;; if they are above emacs-27 + ;; if they are above emacs-27. ((and EMACS28+ (or (featurep 'ns) (string-match-p "HARFBUZZ" system-configuration-features)) - +prog-ligatures-modes - (require 'composite nil t)) - (defvar composition-ligature-table (make-char-table nil)) + (featurep 'composite)) ; Emacs loads `composite' at startup + (defvar +ligature--composition-table (make-char-table nil)) + (add-hook! 'doom-init-ui-hook :append + (defun +ligature-init-composition-table-h () + (dolist (char-regexp +ligatures-composition-alist) + (set-char-table-range + +ligature--composition-table + (car char-regexp) `([,(cdr char-regexp) 0 font-shape-gstring]))) + (set-char-table-parent +ligature--composition-table composition-function-table) + (add-hook 'after-change-major-mode-hook #'+ligatures-init-buffer-composition-table-h)))) - (dolist (char-regexp +prog-ligatures-alist) - (set-char-table-range composition-ligature-table (car char-regexp) - `([,(cdr char-regexp) 0 font-shape-gstring]))) - (unless doom-reloading-p - (set-char-table-parent composition-ligature-table composition-function-table)) + ;; Fallback ligature support for certain, patched fonts. Install them with + ;; `+ligatures/install-patched-font' + ((defmacro +ligatures--def-font (id font-plist &rest alist) + (declare (indent 2)) + (let ((alist-var (intern (format "+ligatures-%s-font-alist" id))) + (setup-fn (intern (format "+ligatures-init-%s-font-h" id)))) + `(progn + (setf (alist-get ',id +ligatures--font-alist) (list ,@font-plist)) + (defvar ,alist-var ',alist ,(format "Name of the %s ligature font." id)) + (defun ,setup-fn (&rest _) + (cl-destructuring-bind (name &key _url files range) + (or (alist-get ',id +ligatures--font-alist) + (error "No ligature font called %s" ',id)) + (when range + (set-fontset-font t range name nil 'prepend)) + (setq-default prettify-symbols-alist + (append (default-value 'prettify-symbols-alist) + (mapcar #'+ligatures--correct-symbol-bounds ,alist-var))))) + (add-hook '+ligatures--init-font-hook #',setup-fn)))) - (add-hook 'after-change-major-mode-hook #'+pretty-code-init-ligatures-h)) + (defvar +ligatures--font-alist ()) - ;; Font-specific ligature support - ((featurep! +fira) - (load! "+fira")) - ((featurep! +iosevka) - (load! "+iosevka")) - ((featurep! +hasklig) - (load! "+hasklig")) - ((featurep! +pragmata-pro) - (load! "+pragmata-pro"))) + (cond ((featurep! +fira) (load! "+fira")) + ((featurep! +iosevka) (load! "+iosevka")) + ((featurep! +hasklig) (load! "+hasklig")) + ((featurep! +pragmata-pro) (load! "+pragmata-pro"))))) diff --git a/modules/ui/pretty-code/+fira.el b/modules/ui/pretty-code/+fira.el deleted file mode 100644 index b92f30f3c..000000000 --- a/modules/ui/pretty-code/+fira.el +++ /dev/null @@ -1,127 +0,0 @@ -;;; ui/pretty-code/+fira.el -*- lexical-binding: t; -*- - -(defvar +pretty-code-fira-code-font-name "Fira Code Symbol" - "Name of the fira code ligature font.") - -(defvar +pretty-code-fira-code-font-ligatures - '(("www" . #Xe100) - ("**" . #Xe101) - ("***" . #Xe102) - ("**/" . #Xe103) - ("*>" . #Xe104) - ("*/" . #Xe105) - ("\\\\" . #Xe106) - ("\\\\\\" . #Xe107) - ("{-" . #Xe108) - ("[]" . #Xe109) - ("::" . #Xe10a) - (":::" . #Xe10b) - (":=" . #Xe10c) - ("!!" . #Xe10d) - ("!=" . #Xe10e) - ("!==" . #Xe10f) - ("-}" . #Xe110) - ("--" . #Xe111) - ("---" . #Xe112) - ("-->" . #Xe113) - ("->" . #Xe114) - ("->>" . #Xe115) - ("-<" . #Xe116) - ("-<<" . #Xe117) - ("-~" . #Xe118) - ("#{" . #Xe119) - ("#[" . #Xe11a) - ("##" . #Xe11b) - ("###" . #Xe11c) - ("####" . #Xe11d) - ("#(" . #Xe11e) - ("#?" . #Xe11f) - ("#_" . #Xe120) - ("#_(" . #Xe121) - (".-" . #Xe122) - (".=" . #Xe123) - (".." . #Xe124) - ("..<" . #Xe125) - ("..." . #Xe126) - ("?=" . #Xe127) - ("??" . #Xe128) - (";;" . #Xe129) - ("/*" . #Xe12a) - ("/**" . #Xe12b) - ("/=" . #Xe12c) - ("/==" . #Xe12d) - ("/>" . #Xe12e) - ("//" . #Xe12f) - ("///" . #Xe130) - ("&&" . #Xe131) - ("||" . #Xe132) - ("||=" . #Xe133) - ("|=" . #Xe134) - ("|>" . #Xe135) - ("^=" . #Xe136) - ("$>" . #Xe137) - ("++" . #Xe138) - ("+++" . #Xe139) - ("+>" . #Xe13a) - ("=:=" . #Xe13b) - ("==" . #Xe13c) - ("===" . #Xe13d) - ("==>" . #Xe13e) - ("=>" . #Xe13f) - ("=>>" . #Xe140) - ("=<" . #Xe141) - ("=<<" . #Xe142) - ("=/=" . #Xe143) - (">-" . #Xe144) - (">=" . #Xe145) - (">=>" . #Xe146) - (">>" . #Xe147) - (">>-" . #Xe148) - (">>=" . #Xe149) - (">>>" . #Xe14a) - ("<*" . #Xe14b) - ("<*>" . #Xe14c) - ("<|" . #Xe14d) - ("<|>" . #Xe14e) - ("<$" . #Xe14f) - ("<$>" . #Xe150) - ("" . #Xe101) - ("<--->" . #Xe102) - ("<---->" . #Xe103) - ("<----->" . #Xe104) - ;; Double-ended equals arrows - ("<=>" . #Xe105) - ("<==>" . #Xe106) - ("<===>" . #Xe107) - ("<====>" . #Xe108) - ("<=====>" . #Xe109) - ;; Double-ended asterisk operators - ("<**>" . #Xe10a) - ("<***>" . #Xe10b) - ("<****>" . #Xe10c) - ("<*****>" . #Xe10d) - ;; HTML comments - ("" . #Xe152) - ("-->-" . #Xe153) - ("-->--" . #Xe154) - ("-->>" . #Xe155) - ("-->>-" . #Xe156) - ("-->>--" . #Xe157) - ("-->>>" . #Xe158) - ("-->>>-" . #Xe159) - ("-->>>--" . #Xe15a) - (">-" . #Xe15b) - (">--" . #Xe15c) - (">>-" . #Xe15d) - (">>--" . #Xe15e) - (">>>-" . #Xe15f) - (">>>--" . #Xe160) - ("=>" . #Xe161) - ("=>=" . #Xe162) - ("=>==" . #Xe163) - ("=>>" . #Xe164) - ("=>>=" . #Xe165) - ("=>>==" . #Xe166) - ("=>>>" . #Xe167) - ("=>>>=" . #Xe168) - ("=>>>==" . #Xe169) - ("==>" . #Xe16a) - ("==>=" . #Xe16b) - ("==>==" . #Xe16c) - ("==>>" . #Xe16d) - ("==>>=" . #Xe16e) - ("==>>==" . #Xe16f) - ("==>>>" . #Xe170) - ("==>>>=" . #Xe171) - ("==>>>==" . #Xe172) - (">=" . #Xe173) - (">==" . #Xe174) - (">>=" . #Xe175) - (">>==" . #Xe176) - (">>>=" . #Xe177) - (">>>==" . #Xe178) - ("<-" . #Xe179) - ("-<-" . #Xe17a) - ("--<-" . #Xe17b) - ("<<-" . #Xe17c) - ("-<<-" . #Xe17d) - ("--<<-" . #Xe17e) - ("<<<-" . #Xe17f) - ("-<<<-" . #Xe180) - ("--<<<-" . #Xe181) - ("<--" . #Xe182) - ("-<--" . #Xe183) - ("--<--" . #Xe184) - ("<<--" . #Xe185) - ("-<<--" . #Xe186) - ("--<<--" . #Xe187) - ("<<<--" . #Xe188) - ("-<<<--" . #Xe189) - ("--<<<--" . #Xe18a) - ("-<" . #Xe18b) - ("--<" . #Xe18c) - ("-<<" . #Xe18d) - ("--<<" . #Xe18e) - ("-<<<" . #Xe18f) - ("--<<<" . #Xe190) - ("<=" . #Xe191) - ("=<=" . #Xe192) - ("==<=" . #Xe193) - ("<<=" . #Xe194) - ("=<<=" . #Xe195) - ("==<<=" . #Xe196) - ("<<<=" . #Xe197) - ("=<<<=" . #Xe198) - ("==<<<=" . #Xe199) - ("<==" . #Xe19a) - ("=<==" . #Xe19b) - ("==<==" . #Xe19c) - ("<<==" . #Xe19d) - ("=<<==" . #Xe19e) - ("==<<==" . #Xe19f) - ("<<<==" . #Xe1a0) - ("=<<<==" . #Xe1a1) - ("==<<<==" . #Xe1a2) - ("=<" . #Xe1a3) - ("==<" . #Xe1a4) - ("=<<" . #Xe1a5) - ("==<<" . #Xe1a6) - ("=<<<" . #Xe1a7) - ("==<<<" . #Xe1a8) - ;; Monadic operators - (">=>" . #Xe1a9) - (">->" . #Xe1aa) - (">-->" . #Xe1ab) - (">==>" . #Xe1ac) - ("<=<" . #Xe1ad) - ("<-<" . #Xe1ae) - ("<--<" . #Xe1af) - ("<==<" . #Xe1b0) - ;; Composition operators - (">>" . #Xe1b1) - (">>>" . #Xe1b2) - ("<<" . #Xe1b3) - ("<<<" . #Xe1b4) - ;; Lens operators - (":+" . #Xe1b5) - (":-" . #Xe1b6) - (":=" . #Xe1b7) - ("+:" . #Xe1b8) - ("-:" . #Xe1b9) - ("=:" . #Xe1ba) - ("=^" . #Xe1bb) - ("=+" . #Xe1bc) - ("=-" . #Xe1bd) - ("=*" . #Xe1be) - ("=/" . #Xe1bf) - ("=%" . #Xe1c0) - ("^=" . #Xe1c1) - ("+=" . #Xe1c2) - ("-=" . #Xe1c3) - ("*=" . #Xe1c4) - ("/=" . #Xe1c5) - ("%=" . #Xe1c6) - ;; Logical - ("/\\" . #Xe1c7) - ("\\/" . #Xe1c8) - ;; Semigroup/monoid operators - ("<>" . #Xe1c9) - ("<+" . #Xe1ca) - ("<+>" . #Xe1cb) - ("+>" . #Xe1cc)) - "Defines the character mappings for ligatures for Iosevka.") - -(defun +pretty-code-setup-iosevka-ligatures-h () - (set-fontset-font t '(#Xe100 . #Xe1cc) +pretty-code-iosevka-font-name nil 'prepend) - (setq-default prettify-symbols-alist - (append prettify-symbols-alist - +pretty-code-iosevka-font-ligatures))) - -(add-hook 'doom-init-ui-hook #'+pretty-code-setup-iosevka-ligatures-h) diff --git a/modules/ui/pretty-code/+pragmata-pro.el b/modules/ui/pretty-code/+pragmata-pro.el deleted file mode 100644 index 45e7b2042..000000000 --- a/modules/ui/pretty-code/+pragmata-pro.el +++ /dev/null @@ -1,259 +0,0 @@ -;;; ui/pretty-code/+pragmata-pro.el -*- lexical-binding: t; -*- - -(defvar +pretty-code-pragmata-pro-font-name "PragmataPro" - "Name of the Pragmata Pro ligature font.") - -(defvar +pretty-code-pragmata-pro-font-ligatures - '(("[ERROR]" . #XE2C0) - ("[DEBUG]" . #XE2C1) - ("[INFO]" . #XE2C2) - ("[WARN]" . #XE2C3) - ("[WARNING]" . #XE2C4) - ("[ERR]" . #XE2C5) - ("[FATAL]" . #XE2C6) - ("[TRACE]" . #XE2C7) - ("[FIXME]" . #XE2C8) - ("[TODO]" . #XE2C9) - ("[BUG]" . #XE2CA) - ("[NOTE]" . #XE2CB) - ("[HACK]" . #XE2CC) - ("[MARK]" . #XE2CD) - ("# ERROR" . #XE2F0) - ("# DEBUG" . #XE2F1) - ("# INFO" . #XE2F2) - ("# WARN" . #XE2F3) - ("# WARNING" . #XE2F4) - ("# ERR" . #XE2F5) - ("# FATAL" . #XE2F6) - ("# TRACE" . #XE2F7) - ("# FIXME" . #XE2F8) - ("# TODO" . #XE2F9) - ("# BUG" . #XE2FA) - ("# NOTE" . #XE2FB) - ("# HACK" . #XE2FC) - ("# MARK" . #XE2FD) - ("// ERROR" . #XE2E0) - ("// DEBUG" . #XE2E1) - ("// INFO" . #XE2E2) - ("// WARN" . #XE2E3) - ("// WARNING". #XE2E4) - ("// ERR" . #XE2E5) - ("// FATAL" . #XE2E6) - ("// TRACE" . #XE2E7) - ("// FIXME" . #XE2E8) - ("// TODO" . #XE2E9) - ("// BUG" . #XE2EA) - ("// NOTE" . #XE2EB) - ("// HACK" . #XE2EC) - ("// MARK" . #XE2ED) - ("!!" . #XE900) - ("!=" . #XE901) - ("!==" . #XE902) - ("!!!" . #XE903) - ("!≡" . #XE904) - ("!≡≡" . #XE905) - ("!>" . #XE906) - ("!=<" . #XE907) - ("#(" . #XE920) - ("#_" . #XE921) - ("#{" . #XE922) - ("#?" . #XE923) - ("#>" . #XE924) - ("##" . #XE925) - ("#_(" . #XE926) - ("%=" . #XE930) - ("%>" . #XE931) - ("%>%" . #XE932) - ("%<%" . #XE933) - ("&%" . #XE940) - ("&&" . #XE941) - ("&*" . #XE942) - ("&+" . #XE943) - ("&-" . #XE944) - ("&/" . #XE945) - ("&=" . #XE946) - ("&&&" . #XE947) - ("&>" . #XE948) - ("$>" . #XE955) - ("***" . #XE960) - ("*=" . #XE961) - ("*/" . #XE962) - ("*>" . #XE963) - ("++" . #XE970) - ("+++" . #XE971) - ("+=" . #XE972) - ("+>" . #XE973) - ("++=" . #XE974) - ("--" . #XE980) - ("-<" . #XE981) - ("-<<" . #XE982) - ("-=" . #XE983) - ("->" . #XE984) - ("->>" . #XE985) - ("---" . #XE986) - ("-->" . #XE987) - ("-+-" . #XE988) - ("-\\/" . #XE989) - ("-|>" . #XE98A) - ("-<|" . #XE98B) - (".." . #XE990) - ("..." . #XE991) - ("..<" . #XE992) - (".>" . #XE993) - (".~" . #XE994) - (".=" . #XE995) - ("/*" . #XE9A0) - ("//" . #XE9A1) - ("/>" . #XE9A2) - ("/=" . #XE9A3) - ("/==" . #XE9A4) - ("///" . #XE9A5) - ("/**" . #XE9A6) - (":::" . #XE9AF) - ("::" . #XE9B0) - (":=" . #XE9B1) - (":≡" . #XE9B2) - (":>" . #XE9B3) - (":=>" . #XE9B4) - (":(" . #XE9B5) - (":-(" . #XE9B6) - (":)" . #XE9B7) - (":-)" . #XE9B8) - (":/" . #XE9B9) - (":\\" . #XE9BA) - (":3" . #XE9BB) - (":D" . #XE9BC) - (":P" . #XE9BD) - (":>:" . #XE9BE) - (":<:" . #XE9BF) - ("<$>" . #XE9C0) - ("<*" . #XE9C1) - ("<*>" . #XE9C2) - ("<+>" . #XE9C3) - ("<-" . #XE9C4) - ("<<" . #XE9C5) - ("<<<" . #XE9C6) - ("<<=" . #XE9C7) - ("<=" . #XE9C8) - ("<=>" . #XE9C9) - ("<>" . #XE9CA) - ("<|>" . #XE9CB) - ("<<-" . #XE9CC) - ("<|" . #XE9CD) - ("<=<" . #XE9CE) - ("<~" . #XE9CF) - ("<~~" . #XE9D0) - ("<<~" . #XE9D1) - ("<$" . #XE9D2) - ("<+" . #XE9D3) - ("" . #XE9D4) - ("<@>" . #XE9D5) - ("<#>" . #XE9D6) - ("<%>" . #XE9D7) - ("<^>" . #XE9D8) - ("<&>" . #XE9D9) - ("" . #XE9DA) - ("<.>" . #XE9DB) - ("" . #XE9DC) - ("<\\>" . #XE9DD) - ("<\">" . #XE9DE) - ("<:>" . #XE9DF) - ("<~>" . #XE9E0) - ("<**>" . #XE9E1) - ("<<^" . #XE9E2) - ("" . #XE9EF) - ("" . #XE9F8) - ("<<==" . #XE9F9) - ("<==" . #XE9FA) - ("=<<" . #XEA00) - ("==" . #XEA01) - ("===" . #XEA02) - ("==>" . #XEA03) - ("=>" . #XEA04) - ("=~" . #XEA05) - ("=>>" . #XEA06) - ("=/=" . #XEA07) - ("=~=" . #XEA08) - ("==>>" . #XEA09) - ("≡≡" . #XEA10) - ("≡≡≡" . #XEA11) - ("≡:≡" . #XEA12) - (">-" . #XEA20) - (">=" . #XEA21) - (">>" . #XEA22) - (">>-" . #XEA23) - (">>=" . #XEA24) - (">>>" . #XEA25) - (">=>" . #XEA26) - (">>^" . #XEA27) - (">>|" . #XEA28) - (">!=" . #XEA29) - (">->" . #XEA2A) - ("??" . #XEA40) - ("?~" . #XEA41) - ("?=" . #XEA42) - ("?>" . #XEA43) - ("???" . #XEA44) - ("?." . #XEA45) - ("^=" . #XEA48) - ("^." . #XEA49) - ("^?" . #XEA4A) - ("^.." . #XEA4B) - ("^<<" . #XEA4C) - ("^>>" . #XEA4D) - ("^>" . #XEA4E) - ("\\\\" . #XEA50) - ("\\>" . #XEA51) - ("\\/-" . #XEA52) - ("@>" . #XEA57) - ("|=" . #XEA60) - ("||" . #XEA61) - ("|>" . #XEA62) - ("|||" . #XEA63) - ("|+|" . #XEA64) - ("|->" . #XEA65) - ("|-->" . #XEA66) - ("|=>" . #XEA67) - ("|==>" . #XEA68) - ("|>-" . #XEA69) - ("|<<" . #XEA6A) - ("||>" . #XEA6B) - ("|>>" . #XEA6C) - ("|-" . #XEA6D) - ("||-" . #XEA6E) - ("~=" . #XEA70) - ("~>" . #XEA71) - ("~~>" . #XEA72) - ("~>>" . #XEA73) - ("[[" . #XEA80) - ("]]" . #XEA81) - ("\">" . #XEA90) - ("_|_" . #XEA97)) - "Defines the character mappings for ligatures for Pragmata Pro.") - -(defun +pretty-code-setup-pragmata-pro-ligatures-h () - (setq-default prettify-symbols-alist - (append prettify-symbols-alist - (mapcar #'+pretty-code--correct-symbol-bounds - +pretty-code-pragmata-pro-font-ligatures)))) - -(add-hook 'doom-init-ui-hook #'+pretty-code-setup-pragmata-pro-ligatures-h) diff --git a/modules/ui/pretty-code/autoload/install.el b/modules/ui/pretty-code/autoload/install.el deleted file mode 100644 index 41fe0b2fb..000000000 --- a/modules/ui/pretty-code/autoload/install.el +++ /dev/null @@ -1,98 +0,0 @@ -;;; ui/pretty-code/autoload/install.el -*- lexical-binding: t; -*- -;;;###if (or (featurep! +fira) (featurep! +hasklig) (featurep! +iosevka)) - -(defvar +pretty-code-font-alist - '(("Fira Code" - :url "https://github.com/tonsky/FiraCode/raw/13234c0/distr/ttf/%s" - :files ("FiraCode-Bold.ttf" - "FiraCode-Light.ttf" - "FiraCode-Medium.ttf" - "FiraCode-Regular.ttf" - "FiraCode-Retina.ttf")) - ("Hasklig" - :url "https://github.com/jsravn/hasklig-emacs/raw/33354a3/%s" - :files ("Hasklig-Black.otf" - "Hasklig-BlackIt.otf" - "Hasklig-Bold.otf" - "Hasklig-BoldIt.otf" - "Hasklig-ExtraLight.otf" - "Hasklig-ExtraLightIt.otf" - "Hasklig-It.otf" - "Hasklig-Light.otf" - "Hasklig-LightIt.otf" - "Hasklig-Medium.otf" - "Hasklig-MediumIt.otf" - "Hasklig-Regular.otf" - "Hasklig-Semibold.otf" - "Hasklig-SemiboldIt.otf")) - ("Iosevka" - :url "https://github.com/jsravn/iosevka-emacs/raw/20fc2c4/%s" - :files ("iosevka-custom-lightoblique.ttf" - "iosevka-custom-thinoblique.ttf" - "iosevka-custom-mediumitalic.ttf" - "iosevka-custom-light.ttf" - "iosevka-custom-heavy.ttf" - "iosevka-custom-bolditalic.ttf" - "iosevka-custom-bold.ttf" - "iosevka-custom-lightitalic.ttf" - "iosevka-custom-thin.ttf" - "iosevka-custom-extralight.ttf" - "iosevka-custom-oblique.ttf" - "iosevka-custom-italic.ttf" - "iosevka-custom-heavyoblique.ttf" - "iosevka-custom-heavyitalic.ttf" - "iosevka-custom-extralightitalic.ttf" - "iosevka-custom-thinitalic.ttf" - "iosevka-custom-medium.ttf" - "iosevka-custom-mediumoblique.ttf" - "iosevka-custom-extralightoblique.ttf" - "iosevka-custom-boldoblique.ttf" - "iosevka-custom-regular.ttf"))) - "An alist of font metadata for `+pretty-code/install-font'.") - -(defun +pretty-code--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... ") - (shell-command-to-string "fc-cache -f -v")) - (message "Successfully %s `%s' fonts to `%s'!" - (if known-dest-p "installed" "downloaded") - name font-dest))) - -;;;###autoload -(defun +pretty-code/install-patched-font (font-name &optional prefix) - "Install FONT-NAME on your system. -When PREFIX is non-nil, ignore the prompt and just install it." - (interactive - (list (completing-read - "Install font: " - (mapcar #'car +pretty-code-font-alist)))) - (if-let (font-files (cdr (assoc font-name +pretty-code-font-alist))) - (cl-destructuring-bind (&key url files) font-files - (+pretty-code--install-font prefix font-name url files)) - (user-error "%S is not a valid font")))