Hasklig icon indicating copy to clipboard operation
Hasklig copied to clipboard

works for emacs

Open esjmb opened this issue 7 years ago • 15 comments

Hi, just noticed that your readme does not list emacs as an editor your font works with. I can confirm that it works very well, stable and with no problems at all, for emacs 25.2.1.

thanks, Stephen.

Ps. For Haskell, I love your '***'. I wonder could you do something similar for '&&&' ?

esjmb avatar Apr 26 '17 07:04 esjmb

Does that mean emacs has ligature support now? What version of hasklig did you install?

Profpatsch avatar May 01 '17 13:05 Profpatsch

Emacs has ligature support. I'm using Emacs 25.2.1, using the emacs-mac port for mac. Note that I have not got ligatures working for emacs in a terminal shell, so can't comment on that.

I've been using Hasklig for about 6 months now. I did initially have some problems, and I recall some reports of occasional hangs etc. from mid 2016, but I can happily report that for about 4 months I've had absolutely no problems. Can't say for certain whether it was a problem with ligatures or something else - stability just improved vastly.

The Hasklig font files sugest that they were created December 31st 2015. I think I downloaded them at some point about 6 months ago.

esjmb avatar May 02 '17 09:05 esjmb

It does indeed work for Emacs, with a little work.

We first define a function that can work around this problem which caused the multi-column symbols to have a width of only one column and being moved to the left.

Then my-ligature-list turns a list of ligature strings to an alist with the correct code-points as values.

Finally we combine all that, starting from code point #Xe100 and set up prettify-symbols-mode correctly for haskell-mode.

  (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 symbols
instead of the width measured by char-width."
    (mapcar (lambda (el)
              (setcdr el (string ?\t (cdr el)))
              el)
            pretty-alist))

  (defun my-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)))

  ; list can be found at https://github.com/i-tu/Hasklig/blob/master/GlyphOrderAndAliasDB#L1588
  (setq my-hasklig-ligatures
    (let* ((ligs '("&&" "***" "*>" "\\\\" "||" "|>" "::"
                   "==" "===" "==>" "=>" "=<<" "!!" ">>"
                   ">>=" ">>>" ">>-" ">-" "->" "-<" "-<<"
                   "<*" "<*>" "<|" "<|>" "<$>" "<>" "<-"
                   "<<" "<<<" "<+>" ".." "..." "++" "+++"
                   "/=" ":::" ">=>" "->>" "<=>" "<=<" "<->")))
      (my-correct-symbol-bounds (my-ligature-list ligs #Xe100))))

  ;; nice glyphs for haskell with hasklig
  (defun my-set-hasklig-ligatures ()
    "Add hasklig ligatures for use with prettify-symbols-mode."
    (setq prettify-symbols-alist
          (append my-hasklig-ligatures prettify-symbols-alist))
    (prettify-symbols-mode))

  (add-hook 'haskell-mode-hook 'my-set-hasklig-ligatures)

Profpatsch avatar May 03 '17 01:05 Profpatsch

@Profpatsch The code fixes the ligatures but whenever emacs uses italic font all characters are somehow separated by two spaces...

alexvorobiev avatar Jul 25 '17 03:07 alexvorobiev

@alexvorobiev I’ve basically given up on Emacs rendering. The two-space problem is a general Spacemacs problem that has existed for ages. No idea how it can be fixed.

Profpatsch avatar Jul 27 '17 10:07 Profpatsch

I think I fixed the two-space problem by changing how we compose the region for prettify-symbols-alist. I used the suggestion here and use spaces to compose instead of tabs. A symbol composure now looks like this

`("&&" . (?\s (Br . Bl) ?\s (Br . Br) ,(decode-char 'ucs #XE100)))

I am sure you could integrate it into your fancy function if it works for you. Works perfect for me

CeleritasCelery avatar Jan 20 '18 06:01 CeleritasCelery

@CeleritasCelery Yeah, that’s an improvement over the code, since the width is a bit off with the leading tab solution.

The problem with too widely spaced italics is a different one. To be honest I haven’t seen that lately, so maybe it was fixed? @alexvorobiev do you still see that with a recent emacs and spacemacs config?

Profpatsch avatar Jan 20 '18 22:01 Profpatsch

@Profpatsch I do not see any problems with italics in the current emacs (25.3.1 from Nix).

alexvorobiev avatar Jan 22 '18 19:01 alexvorobiev

Here's a modification that adds padding based on the number of chars in the input sequence, so that alignment stays intact at the cost of extra whitespace. Basically I combined @CeleritasCelery's idea and @Profpatsch's.

Also, I've never written elisp before so the code is rather ugly. In particular, there has to be a builtin for replicate but i wasn't able to find it.

  (defun replicate (list num)
    "Creates a list with `num` replicas of `list`"
    (if (<= num 0) '() (append list (replicate list (- num 1)))))

  (defun make-spaces (el)
    (let ((space-width (string-width (car el))))
         (append (replicate '(?\s (Br . Bl)) (- space-width 1))
                 '(?\s (Br . Br))
                  (list (decode-char 'ucs (cdr el))))))

  (defun make-tabs (el) (string ?\t (cdr el)))

  (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 symbols
instead of the width measured by char-width."
    ;(let ((out (mapcar (lambda (el) (setcdr el (make-tabs el)) el) pretty-alist)))
    (let ((out (mapcar (lambda (el) (setcdr el (make-spaces el)) el) pretty-alist)))
      (progn (print out) out)))

rohit507 avatar Jun 27 '18 21:06 rohit507

rohit507 [email protected] čálii:

Also, I've never written elisp before so the code is rather ugly. In particular, there has to be a builtin for replicate but i wasn't able to find it.

This should do it:

(make-list (- space-width 1) '(?\s (Br . Bl)))

(there's also make-string, if you ever need to do that)

Note also that elisp doesn't have tail-call optimisation, cf. the recursion.

unhammer avatar Jun 28 '18 07:06 unhammer

I took the code from here and put it into a minor mode. It works well on emacs 26.

https://github.com/minad/hasklig-mode/blob/master/hasklig-mode.el

minad avatar Nov 08 '18 16:11 minad

@Profpatsch can you specify where the code you provided above should be placed. I.e. for a total emacs newbie... Would be much appreciated.

ezmiller avatar Dec 24 '18 01:12 ezmiller

can you specify where the code you provided above should be placed.

In your Emacs configuration, that is ~/.emacs if you use plain Emacs and ~/.spacemacs if you use Spacemacs.

Profpatsch avatar Dec 24 '18 01:12 Profpatsch

I don't know how spac/emacs works, but I got it to work. This is with emacs-plus, on a mac, using spacemacs. Some steps might be redundant, or plain mistakes. What I did:

  1. Downloaded and installed the font.
  2. Copied this https://github.com/minad/hasklig-mode/blob/master/hasklig-mode.el file to ~/.elisp/
  3. Went to ~/.spacemacs file (SPC f e d) and added this line: (push "~/.elisp/" load-path)
  4. In the same config file changed the font to hasklig: dotspacemacs-default-font '("Hasklig"
  5. In the same file, changed the user config function like this:
(defun dotspacemacs/user-config ()
  (use-package hasklig-mode
    :hook (haskell-mode))
)
  1. Reloaded, and worked as expected.

I also have haskell in the dotspacemacs-configuration-layers'( function, which is probably necessary for this config to work.

adrianloma avatar Jul 10 '19 17:07 adrianloma

It should definitively be written in the README that hasklig-mode makes it easy to support Hasklig in Emacs.

smonff avatar Feb 10 '20 10:02 smonff