Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for font ligatures #192

Closed
klingtnet opened this issue Nov 19, 2015 · 25 comments
Closed

Add support for font ligatures #192

klingtnet opened this issue Nov 19, 2015 · 25 comments
Milestone

Comments

@klingtnet
Copy link

Fira Code and others are monospaced fonts that use ligatures to combine multi-character symbols, e.g. -> will result in an arrow symbol . This is quite nice and atom supports this font feature since 1.2.0, so it should work with vscode, too.

@jordwalke
Copy link

👍

@TheInitializer
Copy link

+1

@coreh
Copy link

coreh commented Nov 28, 2015

👍 I would really like this feature.

@bgashler1
Copy link
Contributor

I'm looking into this with the team and will keep you guys updated :). Thanks for the idea!

@egamma egamma modified the milestone: Backlog Dec 10, 2015
@satya164
Copy link

+1

@clojj
Copy link

clojj commented Dec 15, 2015

👍 coming from Atom... there's really no going back after getting used to beatiful code with Ligatures (Fira Code)

@bgashler1
Copy link
Contributor

Good News

I got ligatures to work by changing my user settings in VS Code with "editor.fontFamily": "Fira Code" and then adding the simple CSS rule below

div.monaco-editor.vs-dark {    
text-rendering: optimizeLegibility;
}

Temporary Bad News

There's a side-effect we need to work through.
test

The problem I’m getting is that when I use this rule I get a glitch when clicking at the end of a line. Clicking at the end of a line past the last character normally would put the cursor after the last cursor on the line, but as you can see, it’s putting my cursor at the beginning of the line. However, when I enter text, it is appearing at the end of the line as it should (except the cursor is not in the right spot).

Atom had a similar problem in September for a while, when they enabled ligatures. Apparently ligatures can cause problems with character spacing, even though they are still multiple ASCII characters, they render differently and this can affect spacing. Perhaps this anchor on the page is relevant. @alexandrudima could you help with this?

By the way, this is only a problem if you click past the last character of any line (as if it is making the cursor position undefined???). Anywhere else it’s fine.

@clojj
Copy link

clojj commented Dec 15, 2015

How can I add this CSS rule permanently ?

I can see the ligatures working :) but I have to add that in the temporary Developer Tools

By the way, this is only a problem if you click past the last character of any line (as if it is making the cursor position undefined???). Anywhere else it’s fine.

yep,same here

@mattblagden
Copy link

With that CSS style, the editing cursor renders in an incorrect position when the insertion point is at the end of a line.

Moving the cursor to the end of a line makes it (visually) jump to an earlier point in the line. It remains at the incorrect point (or sometimes jumps back and forth) as you type characters. This happens regardless of whether it was placed there with the mouse or the keyboard.

broken cursor

This is the result of a Chromium bug that has been fixed, so it should eventually make it into a release of VS Code (which is the proper solution to the problem).


If you're like me, you want those sweet sweet ligatures right now! Let's get to it.

I put up a hacky pull request with a workaround. If you build VS Code locally, you can include #1510 to use it.

If you don't want to run a dev build, you can cram the workaround into existing versions of VS Code.

For example, on OSX:

  1. Close VS Code.

  2. Enable ligature rendering by opening /Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/workbench.main.css and adding the following to the end:

    .monaco-editor {
            text-rendering: optimizeLegibility;
    }
    

    Now you have ligatures and a broken editing cursor.

  3. Apply the broken-cursor-workaround by opening Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/workbench/workbench.main.js and changing:

    u.setStart(h,n),u.setEnd(p,r);var f=u.getClientRects(),m=null;return f.length>0&&(m=this._createRawVisibleRangesFromClientRects(f,o,s,a)),m
    

    to

    u.setStart(h,n),u.setEnd(p,r);var f=u.getClientRects(),m=null;return f.length>0&&(m=this._createRawVisibleRangesFromClientRects(f,o,s,a)),(h === p && n === r && r === p.textContent.length) ? (m[0].left = Math.max(0, p.parentElement.getBoundingClientRect().right - a)) : 0,m
    

    Of course, the exact code to be replaced depends on the result of minification, so you may have to adjust accordingly if you have a different version (this example is from the latest version of VS Code for OSX as of the time of writing, 0.10.5. EDIT: It appears to still be the same in 0.10.6). You can refer to Render ligatures #1510 to get a better idea of what the change is doing, if you need to apply it to other minifications.

  4. Configure your VS Code preferences to use a font with ligatures (a couple are mentioned in the original issue).

If all went well, you now have some lovely ligatures, with a functioning editing cursor.

working cursor

@klingtnet
Copy link
Author

u.setStart(h,n),u.setEnd(p,r);var f=u.getClientRects(),m=null;return f.length>0&&(m=this._createRawVisibleRangesFromClientRects(f,o,s,a)),m

Does anybody have an idea where this line (above) is in the unminified source code?
All I can say is, that it's not in /src/vs/workbench/workbench.main.js.

@mattblagden
Copy link

The line of code you pasted is the minified version of the code here.

The original workaround is implemented in #1510; you can refer to the files changed in #1510 to see the change in its un-minified form, and in its original context.

The steps listed in my earlier comment are simply back-porting #1510 change to existing (compiled and minified) versions of VS Code.

I haven't checked other versions (or even the current version on other platforms), but I wouldn't be surprised if the minified code differed in each build. That's the trouble with trying to patch minified code, heh.


Side note: The reason you don't see it directly in workbench.main.js is because the source of workbench.main.js has directives to include many other files. One of the many files (eventually) imported into workbench.main.js is the file that needs to be edited: viewLine.ts.

workbench.main.js, the source file you were looking at, imports editor.all, which imports codeEditorWidget, which imports viewImpl, which imports viewLines, which imports viewLine, which is the file that contains the un-minified code in question.

@clojj
Copy link

clojj commented Dec 21, 2015

Will #1510 be compatible with the chromium version, which has fixed this ?
I mean, if Code will eventually update to the fixed chromium.....

@clojj
Copy link

clojj commented Dec 21, 2015

What a great holiday present !!
firacode-vscode

Cursor is not visible in this shot, but now it can be placed anywhere correctly.
Patch works as advertised here (Mac OSX, VSC 0.10.5)

@clojj
Copy link

clojj commented Dec 21, 2015

BTW... I really don't want to bash Atom, it is a great editor.

But...
Opening the minified .js from this patch inside 'Visual Studio Code.app' and searching for that replacement + replacing it worked without a flaw in VSCode.

That same operation crashed Atom (V 1.3.2) unfortunately.
(had other crashes in Atom recently too, so it's not just a problem of minified js I guess)

@jstclair
Copy link

The way I did it without having to fix the editor itself was to edit workbench.main.css and add the text-rendering: optimizeLegibility; to a new selector: token.keyword.operator - if you use Code's Developer Tools, you can see that these are defined per-language/token type (for instance, the span surrounding != in my Javascript file has the class token comparison keyword operator js).

This works, and avoids the broken line-selection in the editor, but there's a small tokenizing bug in JS: !== is not a single span, but rather 2:
<span>!=</span><span>=</span>
and this prevents the ligature from matching.

@mattblagden
Copy link

@clojj Glad you're enjoying it 😄. I just discovered these ligature fonts recently, and had to have them as well, heh. I believe #1510 would continue to work with the newer Chromium as it does with the current version. It doesn't add an offset to correct the bad coordinate; it outright replaces it with a new value calculated via other means (so even if the value provided by Chromium changes, #1510 will continue to produce the same output). The workaround would be wasteful (and probably confusing, heh) with newer Chromium, but shouldn't behave differently.

@jstclair That's an interesting approach as well: trying to select a subset of elements that need the style, but won't appear in locations that break the cursor. Unfortunately, even just applying it to operators can trigger the misplaced cursor, as operators can appear at the end of a line. e.g. in the following code, moving the cursor to the right side of the && makes it render in incorrect locations.

result = something &&
         somethingElse &&
         lastThing;

Additionally, applying it only to the operator class limits the places the fancy symbols show up; ligatures won't be displayed in other JS elements (comments, hexadecimal prefixes, etc.), nor will they appear in other languages (HTML, C#, plaintext, etc.)

@bgashler1
Copy link
Contributor

Just wanted to update everyone. This feature will be supported soon in the main branch. We are planning a temporary fix (based on the one above) while we wait for the fixed Chromium v48 to trickle down through an Electron Shell update soon.

@alexdima
Copy link
Member

IMHO the challenge here is that the implementation of text-rendering: optimizeLegibility in Chromium is buggy. Here's some random excerpt I've found at MDN -- besides the client rects being wrong -- Chromium 487028:

[1] The implementation has known bugs on Windows and Linux, which can break font substitition, small-caps, letter-spacing or cause text to overlap.

So while PR #1510 includes a workaround for Chromium 487028 that works for LTR text, I cannot deliver this change in its current form -- making text-rendering: optimizeLegibility the default for everybody. The unresolved Chromium issues above look like they would cause a lot of issues to CJK text, RTL text, and bi-di.

I am looking into enabling text-rendering: optimizeLegibility via a setting which will be off by default.

@alexdima
Copy link
Member

Kudos to @mattblagden for his PR #1510 that I used as a great inspiration source. ❤️

@sanmai-NL
Copy link

@alexandrudima: You can use the font-variant-ligatures: common-ligatures; CSS property instead. It works for me in Chrome with the Hasklig font. See: http://thenewcode.com/547/Make-Your-Web-Pages-More-Legible-With-Ligatures-and-Kerning-Pairs

@alexdima
Copy link
Member

alexdima commented Feb 2, 2016

@sanmai-NL We ended up with:

.monaco-editor.enable-ligatures {
    -webkit-font-feature-settings: "liga" on, "calt" on;
    font-feature-settings: "liga" on, "calt" on;
}

Let's revisit these and use font-variant-ligatures: common-ligatures if any issues pop up.

@siegebell
Copy link

An alternative to ligatures is to use prettify-symbols-mode, which I've implemented as a plugin for the insider's build of vscode (but note that it is of beta quality right now).

@PunchyRascal
Copy link

I will just leave this here - enable font ligatures in settings with:

"editor.fontLigatures": true

(and also using appropriate font)

@HelloMihai
Copy link

HelloMihai commented Feb 14, 2017

tested in VS CODE 1.9.1
@PunchyRascal is correct. Here are all the settings together.
make sure your system has FiraCode font and add change the following settings

{
    "editor.fontFamily": "FiraCode-Retina",
    "editor.fontLigatures": true
}

FiraCode is an example.. there are other fonts that support Ligatures now

@ConsoleTVs
Copy link

It's diferent on the current version.

{
    "editor.fontFamily": "Fira Code",
    "editor.fontSize": 18,
    "editor.fontLigatures": true
}

@vscodebot vscodebot bot locked and limited conversation to collaborators Nov 17, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.