Hasklig icon indicating copy to clipboard operation
Hasklig copied to clipboard

State of Hasklig for emacs?

Open angerman opened this issue 9 years ago • 27 comments

On twitter a few images of hasklig and emacs are floating around. And it says here that emacs support is in progress. What is the current state? And is there a way to help?

angerman avatar Dec 08 '14 09:12 angerman

The pictures you saw were from a modification of Haskell-font-lock (part of Haskell-mode). It works by assigning the ligatures custom unicode code points and substituting to them. (ie. /= to slash_equals) This is not a complete solution as it messes with the font advancement in the console and there's some funny rendering issues in GUI emacs.

As a solution, I'm thinking of splitting all the symbols up in one-character-width sections, assigning all of them unicode points and use something like haskell-font-lock to substitute ligatures to that. (ie. /= to first_slash_equals second_slash_equals)

Chopping up the symbols takes a lot of time and would have to be redone for all changes in each weight, so I've been looking into scripting this in some way. At the same time, I've been distracted by trying to graduate and progress has stalled.

My emacs lisp skills are limited, so if you or some one else can write the, emacs side of things, perhaps so that people can load it up independently of haskell-mode, that would be great!

..also if someone knows how to script Fontlab, that help is much appreciated as well :)

i-tu avatar Dec 08 '14 14:12 i-tu

So if I understand this right, the proper solution would be emacs ligature support. Such that fi would be turned into and likewise -> would be turned into the proper right arrow ligature, which the font would provide, right?

Because emacs lacks ligature support, this whole approach does not work (yet). A solution you tried was to replace the "to be ligatures" with unicode code points substituting the ligatures. Which does not work due to the font handling in emacs (which to me sounds like a bug in emacs).

And lastly you are proposing that the solution could be chopping up the ligatures glyphs into double (or more) characters to be displayed.

How Editing with ligatures works makes kinda sense to me (you are breaking apart the ligature anyway), with the unicode substitution, that would have to work similar to the current symbols approach, while the complely broken apart code points would probably have to work similarly as well.

Do you have any research on the ligature handling in emacs? Or is that something that should be researched in detail, if it's lack of interest by the community or strong technical difficulties supporting that in emacs?

Otherwise maybe one can fix the second approach?

angerman avatar Dec 08 '14 20:12 angerman

So if I understand this right, the proper solution would be emacs ligature support. Such that fi would be turned into fi and likewise -> would be turned into the proper right arrow ligature, which the font would provide, right?

Yes, the proper solution absolutely would be proper support for OpenType ligatures, but it just simply isn't a high priority for most.

A solution you tried was to replace the "to be ligatures" with unicode code points substituting the ligatures. Which does not work due to the font handling in emacs (which to me sounds like a bug in emacs).

Well, it pretty much does work in GUI emacs with Hasklig 0.5 and the script I linked, since there is support for variable-width characters. However, each ligature is treated as just one character once it substitutes. This means it's impossible to select half of a ligature once it's in place, and >>= will be counted as only one character, not three. It's definitely manageable if you're not particular about this and you can start using it today.

The main reason to not settle for this solution is that by chopping the ligature in pieces it's possible to add support for editors that don't support ligatures or variable-width glyphs. In practice it would mean support for every implementation of emacs or vim, command-line or otherwise.

i-tu avatar Dec 09 '14 08:12 i-tu

I'll give Hasklig 0.5 with the adjusted script a try. I will also try to understand the OpenType Ligature support issues with emacs better.

The main reason to not settle for this solution is that by chopping the ligature in pieces it's possible to add support for editors that don't support ligatures or variable-width glyphs. In practice it would mean support for every implementation of emacs or vim, command-line or otherwise.

In that light, the approach makes a lot of sense obviously. Thanks!

angerman avatar Dec 09 '14 08:12 angerman

any news?

yawnt avatar Jul 11 '15 13:07 yawnt

Any way I could contribute to help this go forward?

ticviking avatar Aug 21 '15 16:08 ticviking

@ticviking Thanks for the offer! Making the functionality in the gist I mentioned above available in either haskell-mode or as a standalone emacs module would probably be the best way forward for emacs support.

(Chopping the characters into pieces proved to be a dead end.)

i-tu avatar Aug 25 '15 07:08 i-tu

standalone emacs module would be great, so people could reuse it from clojure/other languages

yawnt avatar Aug 25 '15 07:08 yawnt

I agree with @yawnt, standalone is definitely preferable.

i-tu avatar Aug 25 '15 07:08 i-tu

Thanks for the direction.

I'll spend some time at lunch and see what turning that gist into a minor mode would take

ticviking avatar Aug 25 '15 19:08 ticviking

any update on this one ? ^_^

HiCodin avatar Dec 25 '15 15:12 HiCodin

mb this helps https://github.com/tonsky/FiraCode/wiki/Setting-up-Emacs

DmitryBochkarev avatar Dec 25 '15 17:12 DmitryBochkarev

I posted a related question to Emacs StackExchange about a year ago. It's been the top unanswered question for a while now.

matthew-piziak avatar Dec 27 '15 14:12 matthew-piziak

What would be needed for this to happen? Can it be done in ELISP or will it have to be in the Emacs codebase itself?

Tritlo avatar Feb 17 '16 17:02 Tritlo

@Tritlo , see this gist, which shows how to augment haskell-font-lock.el, part of emacs haskell-mode, to enable ligature support: https://gist.github.com/i-tu/3e835955d0db554d76b7#file-gistfile1-el-L112

What that script does is pattern match ligatures and then replace their representation (but not the text itself), with certain arbitrarily assigned unicode code points corresponding to the correct symbols.

If someone would recreate that functionality without haskell-mode, we would be taking tangible steps towards emacs support. There's some complications on the terminal under this scheme because of no support for variable-width fonts, but we would be making progress.

That being said, at this point the easiest way of getting ligatures on emacs is using a terminal which supports ligatures, such as OSX Terminal, Konsole or Black Screen, and using Hasklig 1.0 beta.

i-tu avatar Feb 18 '16 08:02 i-tu

@i-tu Would you mind if I posted that gist as a comment to this StackExchange question? It would provide useful domain information.

matthew-piziak avatar Feb 18 '16 13:02 matthew-piziak

Not at all @matthew-piziak , feel free :)

i-tu avatar Feb 18 '16 15:02 i-tu

Is this version compatible with the latest haskell-font-lock.el https://github.com/haskell/haskell-mode/blob/master/haskell-font-lock.el? I tried to replace just the definition of haskell-font-lock-symbols-alist and got empty rectangles. I am using emacs on Windows with Hasklig 1.0 beta.

alexvorobiev avatar Feb 24 '16 04:02 alexvorobiev

@alexvorobiev, It should be. I opened the otf file in a font editor to make sure the right unicode code points are there. I have no idea what would have changed between now and then.

Troubleshooting time.

  1. Does the original haskell-font-lock.el work? If not, it's a haskell-font-lock/windows issue, stop here. Otherwise,
  2. Change one of the lines to a code point we know exists for sure, like the letter A, like so: (cons "++" (decode-char 'ucs #X0041)). The text ++ should change into A. If so, it's an issue in Hasklig (or the wrong font being loaded) and you can stop here.
  3. If not, it's a problem in my using the function call (decode-char 'ucs #XE100) and we would need to narrow down further whether this is platform-specific or not. I don't really know Emacs, so someone who knows it better should be able to suggest something in this case, hopefully.

Let me know what you find out.

i-tu avatar Feb 24 '16 09:02 i-tu

@i-tu First of all, let me apologize for the confusion: it turned out my emacs configuration had a line which was re-setting the default font so I didn't use Hasklig at all! With the culprit removed I do see the ligatures but, unfortunately, each ligature gets "overtyped", it appears on top of the preceding character. For instance, if I have (<*>), the * gets positioned on top of (.

alexvorobiev avatar Mar 01 '16 00:03 alexvorobiev

No worries @alexvorobiev, these things happen.

There's two important variables in how Hasklig is rendered on emacs right now.

1. The glyph sideline positions, which are different in Hasklig 0.9 and 1.0

Hasklig 0.9 and 1.0 have the same ligatures, but the difference, due to the substitution scheme in the font (opentype calt vs liga) is that in 0.9 correct width of the characters is reported, in 1.0 the last bounding box is defined around the last "character" of the ligature.

screen shot 2016-03-01 at 10 19 07

The reason for this is a bit obscure, so I won't go into it.

2. Whether you are on the terminal or in emacs GUI?
  • The GUI version will correctly use the bounding box defined in the character, and shift other letters to make room. (Hasklig 0.9 will work, and 1.0 will be overwritten on the left side)
  • The terminal version only respects the anchor of the glyph, and gives it exactly one character-width of space (Hasklig 0.9 will be overwritten on the right, Hasklig 1.0 will be overwritten on the left, I would imagine)

Versions of Hasklig up to 0.9 should look like this when substituted in the emacs terminal and GUI: https://twitter.com/voodoosoop/status/523783970920878080

Next steps

Based on your description, I would imagine you are using Hasklig 1.0. It is possible to add the correctly bounded characters from 0.9 to 1.0, so you can use them in the GUI version. See if 0.9 works, and if so, we can add those and have a somewhat working version for the Emacs GUI!

The ligature from 0.9 will be treated in emacs entirely as one character, and that will likely annoy some. Additionally, this will not bring terminal support, in fact it will break any terminal support which otherwise would be working.

It may be possible to add some spaces when substituting the 1.0 glyph, in order to render everything correctly. Deletion of an added space should result in the ligature getting the corresponding character deleted from it. I don't know how hard this would be to do in emacs.

i-tu avatar Mar 01 '16 08:03 i-tu

@i-tu I installed 0.9 and now have the opposite effect: in (<*>), the * gets positioned on top of ). I am using GUI Emacs in Windows 7.

alexvorobiev avatar Mar 04 '16 05:03 alexvorobiev

Regarding emacs support, I can report that Hasklig works beautifully on a mac, using emacs-mac (eg. brew install emacs-mac) and intero.

Adding the following to you .emacs (apologies to elispers for this hack :) ) disables haskell-font-lock-symbols in favour of Hasklig based rendering if you have Hasklig set as the default font.

(if (string-match-p (regexp-quote "Hasklig")
			(aref (query-font (face-attribute 'default :font)) 0))
	(setq haskell-font-lock-symbols nil)
      (setq haskell-font-lock-symbols 'unicode))

I use the following to set my font, choosing Hasklig if I have it installed, followed by a descending list of preferred fonts:

(use-package cl-lib :ensure t)
(defun font-existsp (font)
  "Check to see if the named FONT is available."
  (if (null (x-list-fonts font))
      nil t))
(defun font-avail (fonts)
  "Finds the available fonts."
  (cl-remove-if-not 'font-existsp fonts))

(defvar font-preferences
  '( "Hasklig"
     "Inconsolata"
     "Source Code Pro"
     "Fira Code"
     "PragmataPro"))

(unless (eq window-system nil)
  (let ((fonts (font-avail font-preferences)))
    (unless (null fonts)
      (progn
	(set-face-attribute 'default nil :font (car fonts))
	(set-face-attribute 'default nil :weight 'thin)))))

Thanks so much for your work on Hasklig.

esjmb avatar Dec 26 '16 16:12 esjmb

The combination that's worked best for me is

  • emacs-mac
  • Hasklig 1.0
  • Putting (mac-auto-operator-composition-mode) in my init.el

Without that last step, it fails to render the ligatures. With Hasklig 0.9, emacs would treat a ligature as a single character, where with 1.0 it works just as expected.

vy-let avatar Jan 12 '17 20:01 vy-let

See #84

minad avatar Nov 08 '18 20:11 minad

I still have no idea how to get the Hasklig ligatures to work on Emacs for macOS.

vastus avatar Nov 23 '18 15:11 vastus

For anyone who randomly found this like me, if you are using emacs within iTerm2 on a Mac, you can easily enable ligatures through in iTerm2 when selecting the font, and ligatures show up in emacs just fine:

image

ddellacosta avatar May 30 '21 20:05 ddellacosta