microsoft / cascadia-code

This is a fun, new monospaced font that includes programming ligatures and is designed to enhance the modern look and feel of the Windows Terminal.
Other
25.11k stars 796 forks source link

Emacs Ligatures #153

Open arkhan opened 4 years ago

arkhan commented 4 years ago

Regards,

Great job with this font, you can add instructions to enable ligatures in Emacs, something similar to FiraCode:

https://github.com/tonsky/FiraCode/wiki/Emacs-instructions

Thank you

jilen commented 4 years ago

I've managed to make it possible of the first release of Cascadia.

The font CascadiaEmacs.zip

And setup code

(defun my-correct-symbol-bounds (pretty-alist)
    "Prepend a TAB character to each symbol in this alist,
this way compose-region called by prettify-symbols-mode
will use the correct width of the symhttps://github.com/johnw42/fira-code-emacs/tree/217f3f540d8d25fb825da484b076d1e4345e6150bols
instead of the width measured by char-width."
    (mapcar (lambda (el)
              (setcdr el (string ?\t (cdr el)))
              el)
            pretty-alist))

  (defun cascadia-ligature-list (ligatures codepoint-start)
    "Create an alist of strings to replace with
codepoints starting from codepoint-start."
    (let ((codepoints (-iterate '1+ codepoint-start (length ligatures))))
      (-zip-pair ligatures codepoints)))

(setq cascadia-ligatures
      (let* ((ligs '("x" "www" "*" ":" "-" "--" "---" "-->" "-|" "->"
                     "->>" "--<" "-<<" "-~" "{|" ")#" "[|" "]#" "[|" "]#"
                     "..." "..=" "..<" ".?" ".=" "::" ":::" "::=" ":=" ":>"
                     ":<" ";;" "!!" "!!." "!=" "!==" "?." "?:" "??" "?="
                     "**" "***" "*>" "*/" "#(" "#{" "#[" "#:" "#!" "#?"
                     "##" "###" "####" "#=" "#_" "#_(" "/*" "/=" "/==" "/>"
                     "//" "///" "_|_" "__" "+" "@" "&&" "|-" "|}" "|]"
                     "||" "|||>" "||=" "||>" "|=" "|>" "$>" "++" "+++" "+>"
                     "=:=" "=!=" "==" "===" "==>" "=>" "=>>" "=<<" "=/=" ">-"
                     ">->" ">:" ">=" ">=>" ">>" ">>-" ">>=" ">>>" "<-" "<--"
                     "<->" "<-<" "<:" "<!--" "<*" "<*>" "<|" "<||" "<|||" "<|>"
                     "<$" "<$>" "<+" "<+>" "<=" "<==" "<==>" "<=>" "<=<" "<>"
                     "<<" "<<-" "<<=" "<<<" "<~" "<~>" "<~~" "</" "</>" "~-"
                     "~@" "~=" "~>" "~~" "~~>" "^=" "%%")))
      (my-correct-symbol-bounds (cascadia-ligature-list ligs #Xe100))))

  ;; nice glyphs for haskell with hasklig
  (defun set-cascadia-ligatures ()
    "Add hasklig ligatures for use with prettify-symbols-mode."
    (set-fontset-font t '(#Xe100 . #Xe189) "Cascadia Emacs")
    (setq prettify-symbols-alist
          (append cascadia-ligatures prettify-symbols-alist))
    (prettify-symbols-mode))

(add-hook 'prog-mode-hook #'set-cascadia-ligatures)

Note the font was made with https://github.com/johnw42/fira-code-emacs/tree/217f3f540d8d25fb825da484b076d1e4345e6150 Unluckily , this script seems not work with latest release.

kiennq commented 4 years ago

Emacs 27 now has harfbuzz used as font renderer back-end, which support rendering all ligatures. You can use auto-composition-mode with following setup to make Cascadia ligature works without custom font.

(use-package composite
  :defer t
  :init
  (defvar composition-ligature-table (make-char-table nil))
  :hook
  (((prog-mode conf-mode nxml-mode markdown-mode help-mode)
    . (lambda () (setq-local composition-function-table composition-ligature-table))))
  :config
  ;; support ligatures, some toned down to prevent hang
  (when (version<= "27.0" emacs-version)
    (let ((alist
           '((33 . ".\\(?:\\(==\\|[!=]\\)[!=]?\\)")
             (35 . ".\\(?:\\(###?\\|_(\\|[(:=?[_{]\\)[#(:=?[_{]?\\)")
             (36 . ".\\(?:\\(>\\)>?\\)")
             (37 . ".\\(?:\\(%\\)%?\\)")
             (38 . ".\\(?:\\(&\\)&?\\)")
             (42 . ".\\(?:\\(\\*\\*\\|[*>]\\)[*>]?\\)")
             ;; (42 . ".\\(?:\\(\\*\\*\\|[*/>]\\).?\\)")
             (43 . ".\\(?:\\([>]\\)>?\\)")
             ;; (43 . ".\\(?:\\(\\+\\+\\|[+>]\\).?\\)")
             (45 . ".\\(?:\\(-[->]\\|<<\\|>>\\|[-<>|~]\\)[-<>|~]?\\)")
             ;; (46 . ".\\(?:\\(\\.[.<]\\|[-.=]\\)[-.<=]?\\)")
             (46 . ".\\(?:\\(\\.<\\|[-=]\\)[-<=]?\\)")
             (47 . ".\\(?:\\(//\\|==\\|[=>]\\)[/=>]?\\)")
             ;; (47 . ".\\(?:\\(//\\|==\\|[*/=>]\\).?\\)")
             (48 . ".\\(?:\\(x[a-fA-F0-9]\\).?\\)")
             (58 . ".\\(?:\\(::\\|[:<=>]\\)[:<=>]?\\)")
             (59 . ".\\(?:\\(;\\);?\\)")
             (60 . ".\\(?:\\(!--\\|\\$>\\|\\*>\\|\\+>\\|-[-<>|]\\|/>\\|<[-<=]\\|=[<>|]\\|==>?\\||>\\||||?\\|~[>~]\\|[$*+/:<=>|~-]\\)[$*+/:<=>|~-]?\\)")
             (61 . ".\\(?:\\(!=\\|/=\\|:=\\|<<\\|=[=>]\\|>>\\|[=>]\\)[=<>]?\\)")
             (62 . ".\\(?:\\(->\\|=>\\|>[-=>]\\|[-:=>]\\)[-:=>]?\\)")
             (63 . ".\\(?:\\([.:=?]\\)[.:=?]?\\)")
             (91 . ".\\(?:\\(|\\)[]|]?\\)")
             ;; (92 . ".\\(?:\\([\\n]\\)[\\]?\\)")
             (94 . ".\\(?:\\(=\\)=?\\)")
             (95 . ".\\(?:\\(|_\\|[_]\\)_?\\)")
             (119 . ".\\(?:\\(ww\\)w?\\)")
             (123 . ".\\(?:\\(|\\)[|}]?\\)")
             (124 . ".\\(?:\\(->\\|=>\\||[-=>]\\||||*>\\|[]=>|}-]\\).?\\)")
             (126 . ".\\(?:\\(~>\\|[-=>@~]\\)[-=>@~]?\\)"))))
      (dolist (char-regexp alist)
        (set-char-table-range composition-ligature-table (car char-regexp)
                              `([,(cdr char-regexp) 0 font-shape-gstring]))))
    (set-char-table-parent composition-ligature-table composition-function-table))
  )
hoangtrann commented 4 years ago

I tried your solution @kiennq , but have no luck. I'm currently using emacs 26.3 on Ubuntu 18.04. Any suggestion?

kiennq commented 4 years ago

I tried your solution @kiennq , but have no luck. I'm currently using emacs 26.3 on Ubuntu 18.04. Any suggestion?

You should probably try to switch to emacs 27 (available either through self-built or emacs snapshot PPA). It has harfbuzz supported so it can rendered -> and other ligatures. Without harfbuzz, you still get == and similar ligatures, I guess.

Also, for emacs 26 to work, you probably need to remove the version<= check

qazxwecvr commented 3 years ago

@kiennq I tried this with JetBrains Mono on Emacs 27 with doom. It works only in my init.el file. I did comment out the (set-char-table-parent composition-ligature-table composition-function-table) because it was causing an error. Do you know why I may be having these issues? Thank you for any help you can provide.

Edit: Nevermind, I looked closely at your code and realized the issue was that I was not in prog-mode. (I just saw prog-mode in the code and assumed that it must be necessary to allow the ligatures.) Thank you for your code; this is one of my favorite features of programming fonts, and I'm glad I can keep it when switching to emacs!

kiennq commented 3 years ago

@qazxwecvr Yes, you can add additional major modes to the hook, I only put some limited modes there since with emacs rendering, sometimes ligatures can hang your Emacs.

qazxwecvr commented 3 years ago

@kiennq I just switched to Doom emacs, put your code in the config.el file, and -> and some other ligatures are not working. Is there a package I need to include or something? Sorry to bother you. I'm new to emacs. Should I put it in the .emacs.d/init.el file? That worked before I started using doom, but I thought I wasn't supposed to do that. Thank you.

kiennq commented 3 years ago

@qazxwecvr You can take a look at thi https://github.com/hlissner/doom-emacs/blob/develop/modules/ui/pretty-code/config.el Doom emacs has similar table but only enable for emacs 28. You should open an issue there

kasteph commented 3 years ago

Emacs 27 now has harfbuzz used as font renderer back-end, which support rendering all ligatures. You can use auto-composition-mode with following setup to make Cascadia ligature works without custom font.

Thanks @kiennq! This is the only solution that did not crash Emacs 27.1 for me.

DogLooksGood commented 2 years ago

https://github.com/mickeynp/ligature.el

This package works nice for me.