2

I'm pretty new to emacs and giving it a shot because it seems to be much better integrated with the OCaml tool chain than any other editor.

Since OCaml uses a lot of symbols, I want to enable ligature support.

If it's relevant, I'm using spacemacs. Here's what I've added to my dotspacemacs/user-config()

  (load "~/.emacs.d/private/local/pragmatapro-prettify-symbols-v0.828.el")
  (add-hook 'tuareg-mode-hook #'prettify-hook)
  (global-prettify-symbols-mode t)

The .el file I'm using is available here for reference and defines prettify-hook.

The strange thing is that after opening a .ml file in Tuareg mode, I can see that prettify-symbols-mode is active, but none of the symbols are converted to ligatures. However, if I toggle prettify-symbols-mode off and then back on, the symbols render correctly.

Has anyone else had this issue or have any ideas how I can get it to work automatically upon opening a the file?

Edit:

So, interestingly enough, after looking again it seems like some sort of symbol replacement is happening, but it isn't happening with the correct glyphs or for all of the patterns defined in the .el file. For example <= is replaced with a reasonable, but incorrect glyph; |> is not replaced at all. After toggling the mode I end up with the correct replacement glyphs.

See the answers section for the solution I came up with.

4
  • 1
    Read carefully the doc-string for global-prettify-symbols-mode and remove the argument t in your code when you are calling this function.
    – Tobias
    Jul 6 '20 at 0:17
  • I don't believe that's relevant. Certainly modes are conventionally enabled or disabled with a numeric argument rather than t; however internally it comes down to (prefix-numeric-value arg), and when arg is t, that will evaluate to 1, just as it does when arg is nil.
    – phils
    Jul 6 '20 at 3:45
  • FWIW it sounds like prettify-symbols-mode has been enabled before prettify-symbols-alist has been configured for the buffer, but the code looks ok -- the sequence should be correct. I don't have tuareg mode, but I tried your code substituting c-mode-hook and it seemed to be working (substitutions were happening for examples from the alist).
    – phils
    Jul 6 '20 at 3:57
  • @phils So, interestingly enough, after looking again it seems like some sort of symbol replacement is happening, but it isn't happening with the correct glyphs or for all of the patterns defined in the .el file. For example <= is replaced with a reasonable, but incorrect glyph; |> is not replaced at all. After toggling the mode I end up with the correct replacement glyphs.
    – Evan
    Jul 8 '20 at 22:47
0

I came up with a working solution after fiddling around and figuring out the information I edited into the original question. I'm not sure if this is the best approach, but it resolved my issue.

After these changes the correct ligatures are displayed within OCaml's Tuareg mode automatically.

First, I deleted

  (global-prettify-symbols-mode t)

from my config file. I'm not 100% sure if this is necessary, but since I only want ligatures in Tuareg mode it seemed cleaner not to enable them globally.

Secondly, I added a function to toggle prettify-symbols-mode off and on in the .el file I linked above and added it to the prettify-hook that runs when Tuareg mode is activated. I'm still not sure why this is necessary, but it does the trick.

(defun refresh-pretty ()
  (prettify-symbols-mode -1)
  (prettify-symbols-mode +1))

;; main hook fn
(defun prettify-hook ()
  (add-pragmatapro-prettify-symbols-alist)
  (setup-compose-predicate)
  (refresh-pretty))
0

I have the same problem, and I'm not sure if this is the correct way to work with it, but it does work for me.

I believe the problem is one of hook order. Because prettify-symbols-alist is buffer local, you either have to setq-default it or have it set via some hook when a buffer is opened. The latter should be the preferred way to do it, as different languages have different ideas of what symbols mean; you probably don't want "and" rendered as "∧" in text-mode.

So, given that:

  1. prettify-symbols-alist is buffer-local (ideally), and,
  2. prettify-symbols-mode only looks at prettify-symbols-alist once, when it starts

you have to ensure that step 1 happens before step 2.

I have two solutions:

  1. Use (global-prettify-symbols-mode 1) in your .emacs (or equivalent). Then set up the prettify-symbols-alist in your programming hook:
(defun bjc/lisp-mode-hook ()
  "Hook when entering ‘lisp-mode’."
  (mapc (lambda (elt) (push elt prettify-symbols-alist))
        '(("<=" . ?≤)
          (">=" . ?≥)
          ("and" . ?∧)
          ("or" . ?∨)
          ("xor" . ?⊕)
          ("->" . ?→)
          ("<-" . ?←))))

(global-prettify-symbols-mode 1)
(add-hook 'emacs-lisp-mode-hook 'bjc/lisp-mode-hook)
  1. Arrange to have prettify-symbols-mode called after your particular major mode hook. The easiest way to do this is to simply call it from the hook that sets up prettify-symbols-alist:
(defun bjc/lisp-mode-hook ()
  "Hook when entering ‘lisp-mode’."
  (mapc (lambda (elt) (push elt prettify-symbols-alist))
        '(("<=" . ?≤)
          (">=" . ?≥)
          ("and" . ?∧)
          ("or" . ?∨)
          ("xor" . ?⊕)
          ("->" . ?→)
          ("<-" . ?←)))

  (prettify-symbols-mode 1))

Personally, I've gone with the former, because it seems cleaner to me, but YMMV.

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.