all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Tassilo Horn <tsdh@gnu.org>
To: Eli Zaretskii <eliz@gnu.org>, help-gnu-emacs@gnu.org
Subject: Re: Emacs 28: Specific TTF font gets loaded with font-backend x instead of ftcrhb
Date: Fri, 07 Feb 2020 10:21:43 +0100	[thread overview]
Message-ID: <82853b4ddf25463b106cc43e64db361cb31ab195.camel@gnu.org> (raw)
In-Reply-To: <83pnerfuq1.fsf@gnu.org>

[Sorry for the second mail, I guess my first is in the moderation queue
because of a too large image attachment which I shouldn't have added
in the first place.  Now replaced with link.]

On Thu, 2020-02-06 at 20:15 +0200, Eli Zaretskii wrote:
> > After evaling that, -> becomes an arrow and ~> becomes an arrow with
> > curvy stroke.  So either there's some issue with PragmataPro or my
> > computer at home.
> 
> Well, it would be interesting to hear what happens with that other
> machine and/or the font.  Be sure to try that in an Emacs built with
> the HarfBuzz library, as it should have the most advanced ligature
> support there is.

I'm pretty sure I had built with HarfBuzz but tried again anyway.  This
time it worked just fine.  Here is a screenshot showing two emacs
frames with ligatures in action.  The left one is with the JetBrains
Mono font, the right one is with the PragmataPro Liga font.

https://imagebin.ca/v/5BUpzkwkgR1k

> > Do I understand it correctly that "overshooting" with the above
> > rules has no bad effect, i.e., if there is a composition rule for ->
> > but the font has no ligature glyph for that, then it just stays the
> > way it is?
> 
> Not exactly.  In Emacs built with HarfBuzz, you will see the original
> ASCII characters displayed, but handled as a single grapheme cluster,
> i.e. the cursor will be "widened" to include all of them, and a single
> C-f will move across all of them.

That doesn't seem to happen.  forward-char moves inside ligature
sequences no matter if the font has a ligature or not.  I.e., even with
a ligature ~= which gets composed to an equal sign with curvy upper line
point move half-by-half.

> However, I believe this is what users should expect when the font
> doesn't include some of the ligatures, no?

It doesn't really matter to me.  Maybe it would be a bit awkward for
longer sequences like =/= if you could edit them only from the
beginning/end.

> > So there could be some ligature-minor-mode which just adds all
> > possible composition rules?  (Just speaking naively, I guess there
> > are several distinct categories of ligatures which you would want to
> > enable/disable on a per-mode basis.)
> 
> The part in parentheses is exactly the non-trivial part: we should
> figure out which ligatures should be in effect in what major modes,
> and probably also as function of some user preferences (such as the
> language used in the buffer).  IOW, we need to design the UI for
> specifying what classes of ligatures to activate.

I've tried categorizing them a bit but this feels like quite a hard
task, and I've just done programming ligatures.  Does -- fit in an
operators category (because of C, Java, ...) or a comment category
(because of SQL) or better forget about concrete language syntaxes and
have a dashes category?

> Burt if you only care about ligatures in programming languages, the
> job becomes much simpler, I think.  Although I'd still expect the
> ligatures in effect to depend on the programming language of the
> current buffer.

Right now I've just enabled anything.  To me it seems like there is some
guideline like "if ligature X is not applicable in programming language
Y then the characted sequence it is composed from won't appear there
anyway".

But one thing which comes to mind is that one might want to suppress
ligature composition inside strings...

> Which means composition-function-table needs to be buffer-local, and
> we should make sure making it buffer-local does TRT.

This doesn't seem to work right now.  See the FIXME at the bottom of
below code.

--8<---------------cut here---------------start------------->8---
(defgroup ligature nil
  "Support for font ligatures"
  :version "28.1"
  :prefix "ligature-")

(defcustom ligature-arrows
  (list "-->" "<!--" "->>" "<<-" "->" "<-"
	"<-<" ">>-" ">-" "<~>" "-<" "-<<"
	"<=>" "=>" "<=<" "<<=" "<==" "<==>" "==>" "=>>" ">=>" ">>="
	"<-|" "<=|"  "|=>" "|->" "<~~" "<~"  "~~>"
	"~>" "<->")
  "Arrow ligatures."
  :type '(repeat string))

(defcustom ligature-misc
  (list "..<"  "~-" "-~" "~@"  "-|" "_|_" "|-" "||-" "|=" "||="
	".?" "?="  "<|>" "<:" ":<" ":>" ">:"
	".=" ".-" "__" "<<<" ">>>" "<<" ">>" "~~"
	"<$>" "<$" "$>" "<+>" "<+" "+>" "<*>" "<*" "*>" "</" "</>" "/>"
	"|}" "{|" "[<" ">]" ":?>" ":?"  "[||]" "?:" "?."
	"|>" "<|" "||>" "<||" "|||>" "<|||::=" "|]" "[|"
	"#{" "#[" "]#" "#(" "#?" "#_" "#_(" "#:" "#!" "#=")
  "Miscellaneous ligatures."
  :type '(repeat string))

(defcustom ligature-relations
  (list "==" "!=" "<=" ">=" "=:=" "!==" "===" "<>" "/==" "=!=" "=/=" "~=" ":="
	"/=" "^=")
  "Relation ligatures."
  :type '(repeat string))

(defcustom ligature-operators
  (list "&&" "&&&" "||" "++" "--" "!!" "::" "+++" "??" ":::" "***" "---"
	"/\\" "\\/")
  "Operator ligatures."
  :type '(repeat string))

(defcustom ligature-comments-c-like
  (list "//" "///" "/**" "/*" "*/")
  "Ligatures for comments in C-like languages."
  :type '(repeat string))

(defcustom ligature-comments-xml-like
  (list "<!--" "-->")
  "Ligatures for comments in XML-like languages."
  :type '(repeat string))

(defcustom ligature-hashes
  (list "##" "###" "####")
  "Ligatures for comments in languages with # being the comment character."
  :type '(repeat string))

(defcustom ligature-dots
  (list "..." "..")
  "Dot ligatures."
  :type '(repeat string))

(defcustom ligature-semicolons
  (list ";;" ";;;")
  "Ligatures for comments in lisp languages."
  :type '(repeat string))

(defun ligature--get-all ()
  (append ligature-arrows
	  ligature-relations
	  ligature-operators
	  ligature-misc
	  ligature-dots
	  ligature-comments-c-like
	  ligature-comments-xml-like
	  ligature-hashes
	  ligature-semicolons))

(defun ligature--apply (ligatures)
  (let ((groups (seq-group-by #'string-to-char ligatures)))
    (dolist (group groups)
      (let ((c (car group))
	    (rx (regexp-opt (mapcar (lambda (s) (substring s 1))
				    (cdr group)))))
	(set-char-table-range composition-function-table
			      c `([,(concat "." rx) 0 font-shape-gstring]))))))

(defun ligature-enable-globally ()
  (interactive)
  (ligature--apply (ligature--get-all)))

(define-minor-mode ligature-minor-mode
  "A mode for font ligatures."
  nil "" nil
  (if ligature-minor-mode
      (progn
	;; FIXME: This doesn't work.  When enabled in ~/.emacs, there won't be
	;; a local variable.  When enabled in a buffer manually, there will be
	;; a local variable but the global value is the same (and also includes
	;; the ligature composition rules).
	(make-local-variable 'composition-function-table)
	(ligature--apply (ligature--get-all)))
    ;; FIXME: Even if the above worked, this could remove much more than this
    ;; mode added itself.
    (kill-local-variable 'composition-function-table)))

(provide 'ligature)
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo




  reply	other threads:[~2020-02-07  9:21 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-04 11:12 Emacs 28: Specific TTF font gets loaded with font-backend x instead of ftcrhb Tassilo Horn
2020-02-04 12:15 ` Robert Pluim
2020-02-04 12:25   ` Robert Pluim
2020-02-04 12:58     ` Tassilo Horn
2020-02-04 13:54       ` Robert Pluim
2020-02-04 14:21         ` Tassilo Horn
2020-02-04 16:26           ` Robert Pluim
2020-02-04 18:32             ` Tassilo Horn
2020-02-04 20:11               ` Robert Pluim
2020-02-05 16:51                 ` Tassilo Horn
2020-02-04 15:31     ` Eli Zaretskii
2020-02-04 18:43       ` Tassilo Horn
2020-02-04 19:08         ` Eli Zaretskii
2020-02-05 16:44           ` Tassilo Horn
2020-02-05 17:04             ` Eli Zaretskii
2020-02-06  7:12               ` Tassilo Horn
2020-02-06 18:15                 ` Eli Zaretskii
2020-02-07  9:21                   ` Tassilo Horn [this message]
     [not found]                   ` <b271f1084b17a53ee1583d1f8cd92e9ed21cf360.camel@gnu.org>
2020-02-07  9:48                     ` Eli Zaretskii
2020-02-07 10:41                       ` Tassilo Horn
2020-02-07 13:28                         ` Eli Zaretskii
2020-02-08  9:39                           ` Tassilo Horn
2020-02-08  9:52                             ` Tassilo Horn
2020-02-08 10:16                               ` Eli Zaretskii
2020-02-08 10:36                                 ` Eli Zaretskii
2020-02-08 12:29                                   ` Tassilo Horn
2020-02-08 13:50                                     ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=82853b4ddf25463b106cc43e64db361cb31ab195.camel@gnu.org \
    --to=tsdh@gnu.org \
    --cc=eliz@gnu.org \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.