Open driusan opened 8 years ago
Providing the fancy glyphs via private use area (PUA) codes would resolve #42 via prettify-symbols-mode.
@mordocai I believe this is what you're looking for.
@mordocai Here's a workaround: I've extracted the glyphs that Fira Code adds into a separate font, and assigned each a Unicode ID in the private character area. Download the symbols font: FiraCode-Regular-Symbol.zip
This symbols font should be assigned as a fallback font for either Fira Code or Fira Mono because it does not define the regular characters.
Character map:
www \ue100 ** \ue101 *** \ue102 **/ \ue103
*> \ue104 */ \ue105 \\ \ue106 \\\ \ue107
{- \ue108 [] \ue109 :: \ue10a ::: \ue10b
:= \ue10c !! \ue10d != \ue10e !== \ue10f
-} \ue110 -- \ue111 --- \ue112 --> \ue113
-> \ue114 ->> \ue115 -< \ue116 -<< \ue117
-~ \ue118 #{ \ue119 #[ \ue11a ## \ue11b
### \ue11c #### \ue11d #( \ue11e #? \ue11f
#_ \ue120 #_( \ue121 .- \ue122 .= \ue123
.. \ue124 ..< \ue125 ... \ue126 ?= \ue127
?? \ue128 ;; \ue129 /* \ue12a /** \ue12b
/= \ue12c /== \ue12d /> \ue12e // \ue12f
/// \ue130 && \ue131 || \ue132 ||= \ue133
|= \ue134 |> \ue135 ^= \ue136 $> \ue137
++ \ue138 +++ \ue139 +> \ue13a +> \ue13a
=:= \ue13b == \ue13c === \ue13d ==> \ue13e
=> \ue13f =>> \ue140 <= \ue141 =<< \ue142
=/= \ue143 >- \ue144 >= \ue145 >=> \ue146
>> \ue147 >>- \ue148 >>= \ue149 >>> \ue14a
<* \ue14b <*> \ue14c <| \ue14d <|> \ue14e
<$ \ue14f <$> \ue150 <!-- \ue151 <- \ue152
<-- \ue153 <-> \ue154 <+ \ue155 <+> \ue156
<= \ue157 <== \ue158 <=> \ue159 <=< \ue15a
<> \ue15b << \ue15c <<- \ue15d <<= \ue15e
<<< \ue15f <~ \ue160 <~~ \ue161 </ \ue162
</> \ue163 ~@ \ue164 ~- \ue165 ~= \ue166
~> \ue167 ~~ \ue168 ~~> \ue169 %% \ue16a
x \ue16b : \ue16c + \ue16d * \ue16f
And if you're using the prettify-symbols-mode extension for vscode, you can use the following substitution settings. (prettify-symbols-mode for Emacs should look similar-ish, but you'll combine the pre
, ugly
, and post
into the same regex and \ue00a0
maybe can be replaced with a normal space.)
"prettifySymbolsMode.substitutions": [
{
"language": "*",
"substitutions": [
{ "ugly": "\\{2}", "pretty": "\u03bb", "post": "\\s*(?:\\w|_).*?\\s*->" },
{ "ugly": "\\.=", "pretty": " \ue123", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "\\.-", "pretty": " \ue122", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": ":=", "pretty": " \ue10c", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "=:=", "pretty": "\u00a0 \ue13b", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "==", "pretty": " \ue13c", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "!=", "pretty": " \ue10e", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "===", "pretty": "\u00a0 \ue13d", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "!==", "pretty": "\u00a0 \ue10f", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "=/=", "pretty": "\u00a0 \ue143", "pre": "[^.=:!/<>]|^", "post": "[^.=:!/<>]|$" },
{ "ugly": "<-", "pretty": " \ue152", "pre": "[^<\\->=]|^", "post": "[^<\\-=>]|$" },
{ "ugly": "->", "pretty": " \ue114", "pre": "[^<\\->=]|^", "post": "[^<\\-=>]|$" },
{ "ugly": "<--", "pretty": "\u00a0 \ue153", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "-->", "pretty": "\u00a0 \ue113", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<->", "pretty": "\u00a0 \ue154", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<<-", "pretty": "\u00a0 \ue15d", "pre": "[^<\\->=]|^", "post": "[^<\\-=>]|$" },
{ "ugly": "->>", "pretty": "\u00a0 \ue115", "pre": "[^<\\->=]|^", "post": "[^<\\-=>]|$" },
{ "ugly": "=>", "pretty": " \ue13f", "pre": "[^<\\->=]|^", "post": "[^<\\-=>]|$" },
{ "ugly": "<==", "pretty": "\u00a0 \ue158", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "==>", "pretty": "\u00a0 \ue13e", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<=>", "pretty": "\u00a0 \ue159", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<=<", "pretty": "\u00a0 \ue15a", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<<=", "pretty": "\u00a0 \ue15e", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "=>>", "pretty": "\u00a0 \ue140", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">=>", "pretty": "\u00a0 \ue146", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">>=", "pretty": "\u00a0 \ue149", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">>-", "pretty": "\u00a0 \ue148", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">-", "pretty": " \ue144", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "-<", "pretty": " \ue116", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "-<<", "pretty": "\u00a0 \ue117", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "=<<", "pretty": "\u00a0 \ue142", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<~~", "pretty": "\u00a0 \ue161", "pre": "[^<\\->=~]|^", "post": "[^<\\->=~]|$" },
{ "ugly": "<~", "pretty": " \ue160", "pre": "[^<\\->=~]|^", "post": "[^<\\->=~]|$" },
{ "ugly": "~~", "pretty": " \ue168", "pre": "[^<\\->=~]|^", "post": "[^<\\->=~]|$" },
{ "ugly": "~>", "pretty": " \ue167", "pre": "[^<\\->=~]|^", "post": "[^<\\->=~]|$" },
{ "ugly": "~~>", "pretty": "\u00a0 \ue169", "pre": "[^<\\->=~]|^", "post": "[^<\\->=~]|$" },
{ "ugly": "<<<", "pretty": "\u00a0 \ue15f", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<<", "pretty": " \ue15c", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<=", "pretty": " \ue141", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<>", "pretty": " \ue15b", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">=", "pretty": " \ue145", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">>", "pretty": " \ue147", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": ">>>", "pretty": "\u00a0 \ue14a", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<\\|", "pretty": " \ue14d", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "<\\|>", "pretty": "\u00a0 \ue14e", "pre": "[^<\\->=|]|^", "post": "[^<\\->=|]|$" },
{ "ugly": "\\|>", "pretty": " \ue135", "pre": "[^<\\->=|]|^", "post": "[^<\\->=|]|$" },
{ "ugly": "<\\$", "pretty": " \ue14f", "pre": "[^<\\->=$]|^", "post": "[^<\\->=$]|$" },
{ "ugly": "<\\$>", "pretty": "\u00a0 \ue150", "pre": "[^<\\->=$]|^", "post": "[^<\\->=$]|$" },
{ "ugly": "\\$>", "pretty": " \ue137", "pre": "[^<\\->=$]|^", "post": "[^<\\->=$]|$" },
{ "ugly": "<\\+", "pretty": " \ue155", "pre": "[^<\\->=+]|^", "post": "[^<\\->=+]|$" },
{ "ugly": "<\\+>", "pretty": "\u00a0 \ue156", "pre": "[^<\\->=+]|^", "post": "[^<\\->=+]|$" },
{ "ugly": "\\+>", "pretty": " \ue13a", "pre": "[^<\\->=+]|^", "post": "[^<\\->=+]|$" },
{ "ugly": "<\\*", "pretty": " \ue14b", "pre": "[^<\\->=*]|^", "post": "[^<\\->=*]|$" },
{ "ugly": "<\\*>", "pretty": "\u00a0 \ue14c", "pre": "[^<\\->=*]|^", "post": "[^<\\->=*]|$" },
{ "ugly": "\\*>", "pretty": " \ue104", "pre": "[^<\\->=*]|^", "post": "[^<\\->=*]|$" },
{ "ugly": "\\\\\\\\", "pretty": " \ue106", "pre": "[^<\\\\\\->=]|^", "post": "[^<\\\\\\->=]|$" },
{ "ugly": "\\\\\\\\\\\\", "pretty": "\u00a0 \ue107", "pre": "[^<\\\\\\->=]|^", "post": "[^<\\\\\\->=]|$" },
{ "ugly": "\\{-", "pretty": " \ue108", "pre": "[^<\\\\\\->={}]|^", "post": "[^<\\\\\\->={}]|$" },
{ "ugly": "-}", "pretty": " \ue110", "pre": "[^<\\->={}]|^", "post": "[^<\\->={}]|$" },
{ "ugly": "//", "pretty": " \ue12f", "pre": "[^<\\->=/]|^", "post": "[^<\\->=/]|$" },
{ "ugly": "///", "pretty": "\u00a0 \ue130", "pre": "[^<\\->=/]|^", "post": "[^<\\->=/]|$" },
{ "ugly": "/\\*", "pretty": " \ue12a", "pre": "[^<\\->=/*]|^", "post": "[^<\\->=/*]|$" },
{ "ugly": "/\\*\\*", "pretty": "\u00a0 \ue12b", "pre": "[^<\\->=/*]|^", "post": "[^<\\->=/*]|$" },
{ "ugly": "\\*\\*/", "pretty": "\u00a0 \ue103", "pre": "[^<\\->=/*]|^", "post": "[^<\\->=/*]|$" },
{ "ugly": "\\*/", "pretty": " \ue105", "pre": "[^<\\->=/*]|^", "post": "[^<\\->=/*]|$" },
{ "ugly": "</", "pretty": " \ue162", "pre": "[^<\\->=/]|^", "post": "[^<\\->=/]|$" },
{ "ugly": "<\\!--", "pretty": "\u00a0 \u00a0\ue151", "pre": "[^<\\->=!]|^", "post": "[^<\\->=!]|$" },
{ "ugly": "</>", "pretty": "\u00a0 \ue163", "pre": "[^<\\->=]|^", "post": "[^<\\->=]|$" },
{ "ugly": "/>", "pretty": " \ue12e", "pre": "[^<\\->=/]|^", "post": "[^<\\->=/]|$" },
{ "ugly": "x", "pretty": "\ue16b", "pre": "[0-9a-fA-F]", "post": "[0-9a-fA-F]" },
{ "ugly": ":", "pretty": "\ue16c", "pre": "[0-9]{1,2}", "post": "[0-9]{1,2}" },
{ "ugly": "\\+", "pretty": "\ue16d", "pre": "[0-9a-zA-Z]", "post": "[0-9a-zA-Z]" },
{ "ugly": "-", "pretty": "-", "pre": "[0-9a-zA-Z]", "post": "[0-9a-zA-Z]" },
{ "ugly": "\\*", "pretty": "*", "pre": "", "post": "" },
{ "ugly": "www", "pretty": "\u00a0 \ue100", "pre": "\\b", "post": "\\b" },
{ "ugly": ";;", "pretty": " \ue129", "pre": "[^;]|^", "post": "[^;]|$" },
{ "ugly": "::", "pretty": " \ue10a", "pre": "[^:]|^", "post": "[^:]|$" },
{ "ugly": ":::", "pretty": "\u00a0 \ue10b", "pre": "[^:]|^", "post": "[^:]|$" },
{ "ugly": "!!", "pretty": " \ue10d", "pre": "[^!]|^", "post": "[^!]|$" },
{ "ugly": "\\?{2}", "pretty": " \ue128", "pre": "[^?]|^", "post": "[^?]|$" },
{ "ugly": "%%", "pretty": " \ue16a", "pre": "[^%]|^", "post": "[^%]|$" },
{ "ugly": "&&", "pretty": " \ue131", "pre": "[^&]|^", "post": "[^&]|$" },
{ "ugly": "\\|{2}", "pretty": " \ue132", "pre": "[^|=]|^", "post": "[^|=]|$" },
{ "ugly": "\\.{2}", "pretty": " \ue124", "pre": "[^.<]|^", "post": "[^.<]|$" },
{ "ugly": "\\.{3}", "pretty": "\u00a0 \ue126", "pre": "[^.<]|^", "post": "[^.<]|$" },
{ "ugly": "\\.\\.<", "pretty": "\u00a0 \ue125", "pre": "[^.<]|^", "post": "[^.<]|$" },
{ "ugly": "\\[\\]", "pretty": " \ue109", "pre": "[^[\\]]|^", "post": "[^[\\]]|$" },
{ "ugly": "--", "pretty": " \ue111", "pre": "[^\\-+*=<>~]|^", "post": "[^\\-+*=<>~]|$" },
{ "ugly": "---", "pretty": "\u00a0 \ue112", "pre": "[^\\-+*=<>~]|^", "post": "[^\\-+*=<>~]|$" },
{ "ugly": "\\+{2}", "pretty": " \ue138", "pre": "[^\\-+*=<>~]|^", "post": "[^\\-+*=<>~]|$" },
{ "ugly": "\\+{3}", "pretty": "\u00a0 \ue139", "pre": "[^\\-+*=<>~]|^", "post": "[^\\-+*=<>~]|$" },
{ "ugly": "\\*{2}", "pretty": " \ue101", "pre": "[^\\-+*=<>~]|^", "post": "[^\\-+*=<>~]|$" },
{ "ugly": "\\*{3}", "pretty": "\u00a0 \ue102", "pre": "[^\\-+*=<>~]|^", "post": "[^\\-+*=<>~]|$" },
{ "ugly": "~=", "pretty": " \ue166", "pre": "[^~=\\-]|^", "post": "[^~=\\-]|$" },
{ "ugly": "~-", "pretty": " \ue165", "pre": "[^~=\\-<>]|^", "post": "[^~=\\-<>]|$" },
{ "ugly": "-~", "pretty": " \ue118", "pre": "[^~=\\-<>]|^", "post": "[^~=\\-<>]|$" },
{ "ugly": "~@", "pretty": " \ue164", "pre": "[^~=\\-@~]|^", "post": "[^~=\\-@~]|$" },
{ "ugly": "\\^=", "pretty": " \ue136", "pre": "[^~=\\-^]|^", "post": "[^~=\\-^]|$" },
{ "ugly": "\\?=", "pretty": " \ue127", "pre": "[^~=\\-/?]|^", "post": "[^~=\\-/?]|$" },
{ "ugly": "/=", "pretty": " \ue12c", "pre": "[^~=\\-/]|^", "post": "[^~=\\-/]|$" },
{ "ugly": "/==", "pretty": "\u00a0 \ue12d", "pre": "[^~=\\-/]|^", "post": "[^~=\\-/]|$" },
{ "ugly": "\\|=", "pretty": " \ue134", "pre": "[^~=\\-/|]|^", "post": "[^~=\\-/|]|$" },
{ "ugly": "\\|{2}=", "pretty": "\u00a0 \ue133", "pre": "[^~=\\-/|]|^", "post": "[^~=\\-/|]|$" },
{ "ugly": "##", "pretty": " \ue11b", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "###", "pretty": "\u00a0 \ue11c", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "####", "pretty": "\u00a0\u00a0 \ue11d", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "#{", "pretty": " \ue119", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "#\\[", "pretty": " \ue11a", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "#\\(", "pretty": " \ue11e", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "#\\?", "pretty": " \ue11f", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "#_", "pretty": " \ue120", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" },
{ "ugly": "#_\\(", "pretty": "\u00a0 \ue121", "pre": "[^#_?({[\\]]|^", "post": "[^#_?({[\\]]|$" }
]
}
]
@siegebell There's a bug and i'm not sure whether it is fira code or emacs.
So with font set to Fira Code and setting the fontset to use fira code symbol for \ue100 to \ue16f I'm getting some weird behavior.
The symbols appear to the left of the original text a significant amount. So, for instance, if I do <-- as the first text on the line i'll get most of it rendering off the left side of the screen. Including emacs config and screenshot here, not yet sure what the problem is.
Edit: If there is other text to the left this bug will actually cause the symbol to overlap with the text!
Edit2: Loading it with no other emacs config has the same effect so shouldn't be some package interfering. In addition, it looks like it is about two spaces/characters to the left of where it should be.
Edit3: I see now that you are dealing with this via \u00a0 in the vscode config? Not sure if I can do that with emacs or not.
Emacs config:
;;; Prettify symbols
(setq prettify-symbols-unprettify-at-point t)
(set-fontset-font t '(#Xe100 . #Xe16f) "Fira Code Symbol")
(defconst fira-code-font-lock-symbols-alist
(mapcar (lambda (s)
(cons (car s) (decode-char 'ucs (car (cdr s)))))
(list '("www" #Xe100)
'("<--" #Xe153))))
(add-hook 'prog-mode-hook
(lambda ()
(dolist (alias fira-code-font-lock-symbols-alist)
(push alias prettify-symbols-alist))
(prettify-symbols-mode)))
@siegebell So this definitely looks like it is because emacs expects to be replacing multiple characters with a character with a width of one where as the fira code symbols are designed to take up multiple character widths. Haven't yet figured out a solution.
Found an uglier way that works.
(add-hook 'prog-mode-hook
(lambda ()
(font-lock-add-keywords nil
`(("\\(###\\)"
(0 (prog1 ()
(compose-region (match-beginning 1)
(match-end 1)
;; The first argument to concat is a string containing a literal tab character inserted via C-q <tab>. It is important!
,(concat " " (list (decode-char 'ucs #Xe11c)))))))))))
I'm going to turn it into a helper function then I just need to figure out emacs's awful regex syntax for each thing and we should be good.
@mordocai FYI in Fira symbols visually take multiple character places but marked as taking just one (rightmost) single place:
So in fact when I do ligature substitution in font code, I replace e.g. hyphen
hyphen
greater
with space
space
hyphen_hyphen_greater.liga
(CR
stands for space
):
sub CR CR greater' by hyphen_hyphen_greater.liga;
sub CR hyphen' greater by CR;
sub hyphen' hyphen greater by CR;
The reason for that is that editors will still see result of substitution as three single-width characters, and will allow to “step inside” the ligature glyph. Without that, ligature will act as it’s a single character, which changes editing behaviour which we want to avoid. We want to keep feeling that substitution is purely visual and underlying code is there unchanged.
The downside of that is that glyphs span outside their container. This is usually perfectly fine with all known editors, but might surprise anyone who tries to use them directly without knowing about that gotcha.
Hope that helps.
@tonsky Yeah, I ended up figuring out what was going on! Luckily the new way I'm doing it with emacs knows how to handle things like that by using a special string beginning with a tab.
Everyone: I got it working! Here is the emacs code:
https://gist.github.com/mordocai/50783defab3c3d1650e068b4d1c91495
Linking to gist so I can update it later if necessary.
Edit: Screenshot. Also, sorry for spamming this issue so bad. I kept thinking I was going to give up for the night, but then didn't...
@mordocai thanks for the work! I tried the gist but I get mostly garbage. See the picture. Maybe I'm using the wrong version of the font or something? I'm pretty sure I'm using 0.200 although I did install older versions in the past.
EDIT OK SORRY IT WORKS. Need to install the Fira code symbol font additionnally. The "x" does look weird, in "Text" for instance. It's replaced by a cross. Also the ligature for =<<
doesn't work while fira code appears to support it.
to fix the =<< in the gist =>
("\\(=<<\\)" #Xe142) (changed from ==<)
("[^-=]\\(<<\\)" #Xe15c) (excluded the = before the << as well)
this is for the overzealous cross:
;; ("\\(x\\)" #Xe16b)
would need to require non-word characters before & after but my emacs regex-fu is weak for that, so I just commented that locally.
For example, this should only match 'x' if the preceding character is a number and the subsequent character is either a number or letter:
("[0-9]\\(x\\)[0-9a-fA-F]" #Xe16b)
edit: changed a-F
to a-f
@siegebell i think the ideal would be a "word boundary" regex before & after the x. I was a bit lazy earlier, but this seems to work great =>
("\\b\\(x\\)\\b" #Xe16b)
hmm actually the 'x' just bothers me :-) in haskell we often use the 'x' variable (x:xs) and that triggers it. I'll keep that line commented for my use.
Updated my gist with @emmanueltouzery's changes. I also had ended up commenting out the the X so I included that too.
@emmanueltouzery that's why I didn't use \b
:)
Anyhow, the advantage of prettify-symbols-mode is that every user can easily pick & choose their favorite substitutions. And fancy 0xFF
notation is useful in only a few kinds of projects.
@siegebell ohhh... that 'x' was for hex numbers!!! I totally didn't get it. I thought some languages use it for multiplication or something like that, so I didn't undersand your regex. I thought you were trying to be helpful by showing some generic example of regex =D Then maybe your regex should be used instead.
enabled @siegebell 's 'x' regex for me locally. There is a little typo, @siegebell put a-FA-F
instead of a-fA-F
btw (so it only worked for uppercase hex digits).
otherwise I agree this mode is great. You can enable per-mode and per-glyph. It's just great. And also you can combine the symbols with other fonts. I'm actually using these new symbols in combination with the usual fira mono
, NOT with the base fira code
!
Probably we should update the FiraCode wiki with these instructions? The question is whether this way works also on OSX? Do we have two sets of instructions, OSX & linux or we just put these new instructions for all emacs versions? This way requires to install a separate font which @tonsky may not be willing to support in the future. On the other hand, the OSX-specific way seems to cause all kinds of hangs in all kinds of situations...
@emmanueltouzery there's no particular reason why this needs to be a separate symbols font. I created it this way for expediency/convenience because the free font editor I have access to, Font Forge, is a buggy UI-nightmare to work with. Creating a separate [symbols] font is best suited for when you want to add glyphs to a non-free font that you cannot redistribute, but this approach is limited to text editors that support font fallback.
I think it would be best for @tonsky to merge these changes back into Fira Code to avoid needless forking. (I would submit a PR if only I could run the trial of Glyphs App on Windows...)
some feedback after using @siegebell & @mordocai 's solution daily for a while: it works great, two little things.
I'm still keeping it
@emmanueltouzery It looks like there might be a problem with the widths of the ligatures in your screenshot (they should be an integer multiple of the normal character width)
@emmanueltouzery most of the ugliness in the regex I posted was essentially "blacklisting"; applying a substitution only when it is clearly not part of a larger symbol [which may have no ligature]. Converting it to emacs regex should look something like ("${pre}\\(${ugly}\\)${post}" ${unicodeSymbol})
. Most of it has been left out of @mordocai's translation to emacs, probably because it was very tedious and [I suppose] he chose to only keep "blacklisting" for the more likely collisions in found in Haskell programming.
@siegebell Actually ruby/javascript/lisp programming but otherwise correct :). Since emacs regexes are different it was a pain to copy the originals and modify them so instead I just made new ones from scratch and I didn't check for all such "blacklisting". It hasn't bothered me too much, so far, so I haven't fixed it.
As far as the widths, i've noticed using the "tab as first character to compose-region string argument" method in emacs, described in docs as
If it is a string, the elements are alternate characters. In this case, TAB element has a special meaning. If the first character is TAB, the glyphs are displayed with left padding space so that no pixel overlaps with the previous column. If the last character is TAB, the glyphs are displayed with right padding space so that no pixel overlaps with the following column.
Doesn't seem to line up the columns correctly, which may also be the issue with company. Currently its doing the tab as the first character(so left padding space), i haven't tried tab as last character (so right padding space). If right padding space is just as bad/doesn't work(my guess is it won't work), may be best to try and use the unicode spaces like @siegebell did in the other examples. The function (and configuration) will need to take an extra argument for number of spaces to add though, if that is the case.
@mordocai using TAB doesn't seem to be a perfect solution, either. TAB makes sure that the replacement doesn't overlap with the previous column, but it still gets spacing wrong for the ||
ligature. Doing x||y
will show it noticeably closer to x than to y, as opposed to the centered look it should have.
Okay folks. This is all great. I thank you very much for your work.
But I'm now wondering, would you go about updating @siegebell 's font with the new ligatures? It'd be awesome if this font could be updated with Fira Code.
What about <~>
?
It's inconvenient that emacs users only get a very dated version of the font, is there any reason for not including the ligatures in private area of official releases?
I’m planning to do that in the next Fira Code version
What's the situation on this? Does somebody have an actual and working snippet? The info is quite fragmented and some of gists are deleted. So far, I didn't manage to put everything together to get a properly working solution.
Update: This one works properly and doesn't hang Emacs comparing to the solution from Wiki. https://github.com/Profpatsch/blog/blob/master/posts/ligature-emulation-in-emacs/post.md#appendix-b-update-1-firacode-integration
Thx! Added it to https://github.com/tonsky/FiraCode/wiki/Emacs-instructions
Followed current instructions to make it work for my emacs setup. Results:
(list X#00a0 '(Br . Bl) ... liga-char)
for correct spacing__main__
), double colon works (FirstWord::OtherWord
).Gist with implementation: https://gist.github.com/reiver-dev/82da77ba3f0008c56624661a7375e0e8 Patched font files: FiraCode-private-area.zip
@reiver-dev
Is it possible for you to supply the patched font? Or possibly add it to the emacs-instructions?
@lshoravi
Updated previous comment with an archive with fonts. It lacks some one-symbol ligatures though.
Very cool, @reiver-dev ! Using it right now :) It would be awesome to have this in the standard font, though.
I had been following the instructions at https://github.com/tonsky/FiraCode/wiki/Emacs-instructions to enable FiraCode ligatures in Emacs. Specifically I had followed the 2nd set of instructions that reference this issue and the author had success with emacs 24.5.1 on Debian Linux. I am on macOS (High Sierra) and this had been working for me.
However, I recently updated either Emacs or FiraCode (via Homebrew) or both to Emacs Version 25.3 (9.0) and FiraCode 1.205 and this stopped working. I can't figure out why. I tried reinstalling the FiraCode unicode private area font files, but still no dice. I also tried the other solutions on the wiki without any luck.
Does anyone know how to get FiraCode working with Emacs 25.3 on macOS?
Hey, out of curiosity, what's stopping the ligature glyphs from being moved to the private area? Is there any blocking issue?
Hey, out of curiosity, what's stopping the ligature glyphs from being moved to the private area? Is there any blocking issue?
just lack of time
@reiver-dev Is it possible to alter the script somewhat, such that the cursor, when moving through the code, will consider two-glyph ligatures as two characters wide (and similar for three-glyph ligatures)?
@Qqwy The script just creates references in reserved plane to existing ligature glyphs without any changes to glyphs. It might be possible to automatically modify ligatures, but this looks as a font change.
Is there updated "Fira Code Symbol" font with new ligatures?
@tonsky Yeah, I ended up figuring out what was going on! Luckily the new way I'm doing it with emacs knows how to handle things like that by using a special string beginning with a tab.
Everyone: I got it working! Here is the emacs code:
https://gist.github.com/mordocai/50783defab3c3d1650e068b4d1c91495
Linking to gist so I can update it later if necessary.
Edit: Screenshot. Also, sorry for spamming this issue so bad. I kept thinking I was going to give up for the night, but then didn't...
What was there?! 😢 (link to gist is broken)
What was there?! 😢 (link to gist is broken)
@ogonki-vetochki I did an attempt to put all info on the Wiki: https://github.com/tonsky/FiraCode/wiki/Emacs-instructions
Normally everything is there. It's taken from @reiver-dev's instructions, which I guess is an improved version of the broken gist.
This issue only remains open cause the official "build" of the font does not include symbols in the private Unicode plane (as the title suggests).
How can we generate the fira-symbol font from the current version of fira-code?
Hey, out of curiosity, what's stopping the ligature glyphs from being moved to the private area? Is there any blocking issue?
@tonsky Has there been any update to this request? It'd be great if we could get this for the latest release of FiraCode.
I’ll plan it for the next update
@tonsky Thanks, glad to hear that. I found out only recently, I believe that emacs27 is adding support for HarfBuzz, and also possibly proper ligature support too. [1] Not sure if this change should be made, after finding that out.
emacs27 is still a long way though it feels
And ligatures support is unlikely to be implemented until emacs28 https://www.reddit.com/r/emacs/comments/dcryg1/tab_support_landed_in_emacs_master/f2kevco/
Just given a try, almost everything looks great, but the some symbol like .-
will only work when it is the whole word, it won't work in something like .-a
.
I'm trying to use FiraCode w/ ligatures in a text editor I'm writing (where I'm currently using Deja Vu Sans Mono), but there doesn't seem to be any way to access the ligatures from Go, where the standard font drawing methods are based on converting unicode runes to glyphs and have no knowledge of ligatures.
The Unicode private use area planes is designed for this purpose, according to wikipedia, but doesn't seem to be used by Firacode (at least as far as I can tell by printing runes starting at 0x100000 or 0x0f0000 and visually scanning). Would it be possible to map the ligatures to the supplementary plan? If they were accessible as runes in a private use area with a documented mapping, I could manually do the context-sensitive mapping when rendering.
It's possible that I'm missing something, because all the "how to use the font" documentation seems to be user documentation, and I can't find any developer documentation..