;;; ui/ligatures/config.el -*- lexical-binding: t; -*- (defvar +ligatures-extra-symbols '(;; org :name "»" :src_block "»" :src_block_end "«" :quote "“" :quote_end "”" ;; Functional :lambda "λ" :def "ƒ" :composition "∘" :map "↦" ;; Types :null "∅" :true "𝕋" :false "𝔽" :int "ℤ" :float "ℝ" :str "𝕊" :bool "𝔹" :list "𝕃" ;; Flow :not "¬" :in "∈" :not-in "∉" :and "∧" :or "∨" :for "∀" :some "∃" :return "⟼" :yield "⟻" ;; Other :union "⋃" :intersect "∩" :diff "∖" :tuple "⨂" :pipe "" ;; FIXME: find a non-private char :dot "•") "Maps identifiers to symbols, recognized by `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 +ligatures-extra-alist '((t)) "A map of major modes to symbol lists (for `prettify-symbols-alist').") (defvar +ligatures-prog-mode-list '("|||>" "<|||" "<==>" "" "---" "-<<" "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->" "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "" "###" "#_(" "..<" "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~=" "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|" "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:" ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:" "<$" "<=" "<>" "<-" "<<" "<+" "" "++" "?:" "?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)" "\\\\" "://") "A list of ligatures to enable in all `prog-mode' buffers.") (defvar +ligatures-all-modes-list '() "A list of ligatures to enable in all buffers.") (defvar +ligatures-in-modes '(not special-mode comint-mode eshell-mode term-mode vterm-mode Info-mode elfeed-search-mode elfeed-show-mode) "List of major modes where ligatures should be 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 ligatures anywhere.") (defvar +ligatures-extras-in-modes t "List of major modes where extra ligatures should be enabled. Extra ligatures are mode-specific substituions, defined in `+ligatures-extra-symbols' 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 correct width of the symbols instead of the width measured by `char-width'." (let ((len (length (car ligature-alist))) (acc (list (cdr ligature-alist)))) (while (> len 1) (setq acc (cons #X00a0 (cons '(Br . Bl) acc)) len (1- len))) (cons (car ligature-alist) acc))) (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))))) (defun +ligatures-init-buffer-h () "Set up ligatures for the current buffer. Extra ligatures are mode-specific substituions, defined in `+ligatures-extra-symbols', 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 (let ((in-mode-p (+ligatures--enable-p +ligatures-in-modes)) (in-mode-extras-p (and (modulep! +extra) (+ligatures--enable-p +ligatures-extras-in-modes)))) (when in-mode-p ;; If ligature-mode has been installed, there's no ;; need to do anything, we activate global-ligature-mode ;; later and handle all settings from `set-ligatures!' later. (unless (fboundp #'ligature-mode-turn-on) (run-hooks '+ligatures--init-font-hook) (setq +ligatures--init-font-hook nil))) (when in-mode-extras-p (prependq! prettify-symbols-alist (alist-get major-mode +ligatures-extra-alist))) (when (and (or in-mode-p in-mode-extras-p) prettify-symbols-alist) (when prettify-symbols-mode (prettify-symbols-mode -1)) (prettify-symbols-mode +1))))) ;; ;;; Bootstrap ;;;###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 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. ((if (featurep :system 'macos) (fboundp 'mac-auto-operator-composition-mode)) (add-hook 'doom-init-ui-hook #'mac-auto-operator-composition-mode 'append)) ;; NOTE: the module does not support Emacs 27 and less, but if we still try to enable ligatures, ;; it will end up in catastrophic work-loss errors, so we leave the check here for safety. ((and (> emacs-major-version 27) (or (featurep 'ns) (string-match-p "HARFBUZZ" system-configuration-features)) (featurep 'composite)) ; Emacs loads `composite' at startup (use-package! ligature :config ;; Enable all `+ligatures-prog-mode-list' ligatures in programming modes (ligature-set-ligatures 'prog-mode +ligatures-prog-mode-list) (ligature-set-ligatures 't +ligatures-all-modes-list)) (add-hook! 'doom-init-ui-hook :append (defun +ligature-enable-globally-h () "Enables ligature checks globally in all buffers. You can also do it per mode with `ligature-mode'." (global-ligature-mode t)))))