46

PragmataPro is a typeface that comes with a number of programming ligatures. My understanding is that these are OpenType face (OTF) ligatures.

I am aware that Emacs supports programmatic replacement of character combinations (for example -> to or lambda to λ). However, these are unicode faux ligatures, since they have their own code points, which real ligatures do not.

Am I correct that Emacs (as of 25) does not support OTF ligatures automatically? On a lower level, are there options available to manually specify glyph mappings?

If ligatures are unsupported, then what needs to be done for Emacs to support ligatures?

  • 3
    Looks like it's not yet supported: lists.gnu.org/archive/html/emacs-devel/2015-01/msg00024.html – Kaushal Modi Feb 25 '15 at 22:52
  • Out of curiosity, what are some of the "number of useful enhancements" you have in mind? – Dan Jun 8 '15 at 12:16
  • 3
    Improved variable-width rendering in text mode, programming ligatures that make source code more attractive without affecting the shape of the code, and diagrammatic ligatures for boxes and arrows. In hindsight, "attractive" is probably a better descriptor than "useful". – Matthew Piziak Jun 8 '15 at 12:28
  • github.com/i-tu/Hasklig/issues/10 is tracking Emacs support for Hasklig. A partial solution, which works specifically for Hasklig and haskell-mode is detailed in this gist. – Matthew Piziak Feb 19 '16 at 15:36
  • 3
    A recent post on r/emacs posted a workaround using prettify-symbols-mode, and it works pretty good with PragmataPro 0.822. – Kaushal Modi Aug 3 '16 at 16:55
9

emacs for now doesn't support ligatures (on OSX there is some support, but not on other platforms). However, emacs 24.4+ supports prettify-symbols-mode which in some ways is better than normal ligatures support.

That mode allows to subsitute for display any regex with any glyph. I am personnally using this snippet to get Fira Code ligatures to work in emacs on linux. (EDIT: unfortunately the link is now dead, the policy of stackoverflow to always copy inline is obviously the good one...)

The link I originally put is dead and I'm not certain exactly what it contained but I think these links should be good: https://github.com/tonsky/FiraCode/wiki/Emacs-instructions#using-prettify-symbols and https://github.com/tonsky/FiraCode/issues/312#issuecomment-262878734

Given the dead link issue, I'm putting the code inline this time:

(defun fira-code-mode--make-alist (list)
  "Generate prettify-symbols alist from LIST."
  (let ((idx -1))
    (mapcar
     (lambda (s)
       (setq idx (1+ idx))
       (let* ((code (+ #Xe100 idx))
          (width (string-width s))
          (prefix ())
          (suffix '(?\s (Br . Br)))
          (n 1))
     (while (< n width)
       (setq prefix (append prefix '(?\s (Br . Bl))))
       (setq n (1+ n)))
     (cons s (append prefix suffix (list (decode-char 'ucs code))))))
     list)))

(defconst fira-code-mode--ligatures
  '("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\"
    "{-" "[]" "::" ":::" ":=" "!!" "!=" "!==" "-}"
    "--" "---" "-->" "->" "->>" "-<" "-<<" "-~"
    "#{" "#[" "##" "###" "####" "#(" "#?" "#_" "#_("
    ".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*"
    "/**" "/=" "/==" "/>" "//" "///" "&&" "||" "||="
    "|=" "|>" "^=" "$>" "++" "+++" "+>" "=:=" "=="
    "===" "==>" "=>" "=>>" "<=" "=<<" "=/=" ">-" ">="
    ">=>" ">>" ">>-" ">>=" ">>>" "<*" "<*>" "<|" "<|>"
    "<$" "<$>" "<!--" "<-" "<--" "<->" "<+" "<+>" "<="
    "<==" "<=>" "<=<" "<>" "<<" "<<-" "<<=" "<<<" "<~"
    "<~~" "</" "</>" "~@" "~-" "~=" "~>" "~~" "~~>" "%%"
    "x" ":" "+" "+" "*"))

(defvar fira-code-mode--old-prettify-alist)

(defun fira-code-mode--enable ()
  "Enable Fira Code ligatures in current buffer."
  (setq-local fira-code-mode--old-prettify-alist prettify-symbols-alist)
  (setq-local prettify-symbols-alist (append (fira-code-mode--make-alist fira-code-mode--ligatures) fira-code-mode--old-prettify-alist))
  (prettify-symbols-mode t))

(defun fira-code-mode--disable ()
  "Disable Fira Code ligatures in current buffer."
  (setq-local prettify-symbols-alist fira-code-mode--old-prettify-alist)
  (prettify-symbols-mode -1))

(define-minor-mode fira-code-mode
  "Fira Code ligatures minor mode"
  :lighter " Fira Code"
  (setq-local prettify-symbols-unprettify-at-point 'right-edge)
  (if fira-code-mode
      (fira-code-mode--enable)
    (fira-code-mode--disable)))

(defun fira-code-mode--setup ()
  "Setup Fira Code Symbols"
  (set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol"))

(provide 'fira-code-mode)

I said that in some ways this is better than normal ligatures.. That's because it's "a la carte". You can mix-and-match, take only the symbols you like. You can say, I want the ";;" ligature, EXCEPT if the next character is again ";" in that case I don't want it... And about mix-and-matching... I'm using the 'Fira Mono' font, together with the 'Fira Code' ligatures. You don't have to buy in the whole font.

It's worse than pure ligatures because it doesn't work out of the box and it requires the font to be tuned in a certain way to make it possible.

  • Hi! Could you share this snippet to get Fira Code ligatures work? Gist seems to be deleted. – xamenrax Mar 25 at 3:03
  • huh sorry... updated the answer, I hope it helps – Emmanuel Touzery Mar 25 at 6:25
  • 1
    Thank you! Almost 3 years has passed by but something never changes - people desperate about making ligatures work in Emacs... – xamenrax Mar 25 at 7:52
0

If you are on OS X I believe the Carbon Mac Emacs port supports ligatures.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.