Ligatures in Programming Fonts: Hell No
practicaltypography.com
practicaltypography.com
I'm generally a fan of Practical Typography, but this post is unnecessarily condescending. It's sort of laughable to claim that "this isn’t a matter of taste" when users are making this choice in the privacy of their own editors.
In my experience removing the gaps makes some symbols harder to read. Like distinguishing `==` and `===` without gaps is harder, though admittedly three-bar helps. Also, I find the ligatures I've tried a bit of an eye-sore, but that's just personal taste.
What's a more serious concern is the "dumbness" mentioned in the article and the handling of ambiguous cases. To give my own example, in addition to those in the article, I use a series of more than 3 equals signs as a delimiter in my notes. With programming ligatures it looks distractingly bad. Normally it's a continuous row of two-bars, but with them ligatured they look like morse code divided into short groups of long two-bars. Essentially, when I'm writing code or whatever, I don't want there to be someone guessing what I mean and how I want something to look. Unless he guesses always right, he's a nuisance. Sorry for the personification.
I don't think anecdotes of cases where ligatures fail support a case for them being wrong for all people and all situations.
Personally, I've never had a single instance of them doing something dumb in 2+ years of using them. Never a single instance of them creating any ambiguity or failing to add clarity to my reading of code. Dumb in "theory" might be smart enough 99% of the time.
Just in the last couple months, I had to review code without the aid of a linter and they were invaluable.
So what languages actually benefit from this? haskell, clojure but maybe not the usual C family ones?
Don't forget people read whole words, so they most likely don't spend much time on "==" recognition than they would with "equivalent". And with text completion, token length is an irrelevant metric on productivity as well.
Any non literal symbol used in code is an incentive to use more of them and turn code bases into harder to maintain "smart" obfuscated trick stacks.
On an historical perspective, how much people using "=" know where it comes from (nothing is more equal than two parallel lines), compared to how many people are able to make a good guess of the etymology of "equivalent" (same value)? Add to this observation that in the mid-time with the raise of non-euclidian geometry and topology the former insight is far less relevant nowaday.
And I use profanity (Engineering language) for good reasons here can you imagine any other engineering discipline allowing this to happen - oh yes the CAD system added a ligature in the bridge design blueprints !!
Even moveing excel between countries gets some very strange changes Eg changing diacritical's but they look very very similar.
For example, if I see "fl" in a string, is that "fl" or is it "fl"? That is, is it the codepoint sequence U+0066 U+006C turned into a ligated version visually, or is it U+FB02 the single codepoint?
Then I get paranoid: Did my text editor Helpfully convert the sequence of characters into the ligature character? The paranoia is probably unjustified, and would be seen as a bug if it weren't (probably), but a clear visual distinction would banish it entirely.
Doing it with ligatures is not a great idea, because ligatures are a PITA (not always well supported) and add too much incidental complexity.
And that's how it should be done. If you want something modified visually then you can modify it for yourself without pushing it on the rest of the world.
Edit: Disregard that, I was being dumb.
Fonts with ligatures, such as Fira Code or Hasklig, work by replacing characters with a ligature. The actual source code is still "->" or "===" or "|>" or whatever it may be.
No one is "pushing it on the rest of the world"?
> When we’re using a serifed text font in ordinary body text, we don’t have the same considerations. An fi ligature always means f followed by i. In that case, ligature substitution that ignores context doesn’t change the meaning.
Maybe this is different in English typography - I'm a bit more proficient in German - but ligatures do have semantic meaning. At least in German, they should never cross a word boundary in composite words, for example Kaufleute (merchants) is Kauf-leute (buy-people), so you would not use a "fl" ligature. There are actually words where this resolves an ambiguity, I think. Historically, this is the reason sometimes ss and sometimes ß is used. I always assumed there were similar subtle rules in English.
As to the "ligatures" in programming fonts - I would not call them such, problem solved. Rather, they are substitutions in the tradition of APL or vim conceal mode - to get mathematical notation with a standard keyboard.
Anyway, I too agree with the author; if you want ≥ to appear on your screen, it should be in the source text as the UTF-8 bytes for U+2265 and the tooling should understand it. Programming is too fragile to allow misunderstandings between the bytes that are interpreted by the machine and the glyphs that the programmer understands to be inserted.
Going much further back, there are the C trigraphs '??!' etc, for those whose character sets don't contain '|'. I've not seen editors attempt to automatically show those as the substitute characters either.
(Oh, and if you want to be unpopular, try entering unicode characters in your language variable identifiers or git commit messages and see how much tooling you can break...)
Any git hook processing stuff would just look for stuff it does understand (like '([Cc]lose(s)?|[Ff]ix(es)?) #[0-9]+' or something similar) and ignore the rest.
Scores of developers use non-ASCII characters as part of their native language every day in git commit messages, and even non-BMP Unicode characters like emoji work just fine.
That said, OP is wrong that ligatures would "break Unicode". The only ligatures that are directly encoded exist for historical reasons. Fonts can and should make contextual alternatives, and this is a normal part of typesetting for several languages.
Unicode breaks Unicode, it's not meant to be consistent, only compatible.
The rule provides visual hints for how to pronounce words. I think that is way more useful than slightly increasing the readability by joining glyphs without context.
Kaufleute = Kauf ++ leute (merchant / trader, from kaufen = to buy)
Kaufläche = Kau ++ fläche (chewing surface / morsal surface from kauen = to chew)
But I am sure only professional typographers + a small minority of pedants (in the good sense) would be aware of this.At least in Sublime Text this is not true. We tokenize the text according to the rules in the syntax definition and then pass characters to be shaped, but respecting token boundaries.
In fact, we’ve fielded a number of bug reports about ligatures not working, and it is almost always that the syntax definition was tokenizing the = and the > as separate tokens.
We also made the decision to only pass runs of symbols to the text shaping engine, as opposed to runs of alphanumeric characters. This prevents ligatures like fl that are usually not useful in a monospace layout such as a text editor. There are also options to control the OpenType features for ligature fine tuning.
nope, I still haven't ever run into the described issues. but that's not even why I disagree with the author. if I _did_ run into an issue, it absolutely wouldn't be the font's problem. this is akin to blaming a crypto algorithm for a security flaw caused by a bad implementation. fonts are software and IDEs can simply provide an option to disable ligatures. and, often, they do:
in sublime: https://www.sublimetext.com/docs/3/ligatures.html
in vscode: https://github.com/tonsky/FiraCode/wiki/VS-Code-Instructions
in atom: use CSS
Yeah but the author is suggesting that using a particular font will increase the likelihood of a programmer introducing some syntactically correct but erroneous code. But then he doesn't actually give any examples. So I don't buy it either. Maybe certain languages are more susceptible?
For instance it mentions the pairing => but provides no examples.
After reading I’m far from convinced that carefully curated language specific ligatures are a bad idea.
The Unicode ligatures in the Alphabetic Presentation Forms block (U+0FB00 - U+0FB4F) are only present for compatibility purposes, so that legacy texts in encodings which contain precomposed ligatures can be losslessly reencoded to/from Unicode. They aren't meant to represent the entirety of all ligatures.
Not to mention entire languages that build structure as complex combining sequences, including emoji and its complex ligatures combining the Zero Width Joiner and multiple emoji into single result emoji.
It is, quite unequivocally, a matter of taste. Please don't pass your personal, unsubstantiated opinions as a matter of fact. :-)
I personally see no problem using Fira Code aside from 10 seconds long brain hiccups every once in while (once per year, maybe rarer). I've been using it since 2015, on multiple editors including Xcode, Android Studio, iTerm2, Sublime Text, Atom, VS Mac, VS Code and IntelliJ. I can't even remember which one of these still doesn't support the proper rendering of ligatures, and yet no issues for me so far.
That said, however, the article fails to provide a compelling argument against ligatures.
1. Fonts have nothing to do with Unicode. It's exactly the font's job to provide any glyphs or ligatures it wants on top of provided characters.
2. Programming languages have been long stuck in ASCII-land trying to emulate symbols commonly used in other areas such as mathematics: -> and => are arrows, == and === are equality and congruence, >= and =< are greater than/less than or equal to, and the list goes on. These will never be easy to type in their original form (unless you have APL's custom keyboard), so why not present them as such?
3. Computers have all but destroyed typography, and it's a good thing some of it is coming back. Properly spaced numbers? Properly spaced and aligned punctuation? Contextually correct punctuation? Yes, please, more!
So, what's the beef with ligatures? I don't know :) And yes, I've been using Fira Code for several years now.
Ironically, the article says "well-intentioned amateur ligaturists are adding dozens of new & strange ligatures." and uses what appears a "° DEGREE SIGN U+00B0" that looks like a link to a footnote to denote external links.
Edit: minor corrections to readability
Absolutely agree. Medium.com (as an example) has a bunch of flaws, but some of my favorite articles are their posts about bringing classical typography back to the modern web.
But there is, see Iosevkas ligature sets which switch different ligatures on and off. The editor can just opt-in which one to use.
There might not be sufficient editor support for it but you can work around it by generating different versions of it as default and then configure your editor to use that font. Not elegant but workable.
It's not limited to just programming. Font fallbacks for multi-language texts (for example, English and Russian; that is, Latin and Cyrillic) in most (all?) mediums are usually horrible, and usually revert to whatever the OS provides.
If your IDE (or text editor) can highlight and indent languages differently then it can certainly switch font or toggle a font property to select a ligature variant set.
I do get the point that author is making here, but it's only important for these kinds of discussions in a vacuum, detached from reality, as self-important typography and design blogs usually are.
Still, Perl 6 I think has the better solution: use Unicode well with ASCII fallbacks. Combine it with editor language modes that are aware of the equivalents and do Unicode substitution when the ASCII combo is used, and you get a situation all-around better than ligatures.
But... I have to say that this is the only place I've actually come across it. I eventually decided that I don't like ligatures, personally, in my source code. However, the chance of problems occurring is pretty remote.
But... why? It's obviously not intended for that purpose. You would get awkward results trying to program with a regular serif, too, but that's not a fault of the entire category of serifs.
I'm more looking for an example of where ligatures will cause problems while programming.
It’s not that when they are used, different code is produced. As with the editors color scheme, it’s just a personal choice everyone can live out within the privacy of his or her editor.
Personally I find it nice to represent single logical tokens like => or === with just a single character.
I've often thought that smarter IDEs should be able to recognize the language and display code in the user's preferred style with better use of screen space. For instance, a Java class could be displayed with the class signature in a fixed header; enclosed methods could be displayed starting at the left, instead of indented; stacks of annotations could be replaced by a gutter icon with a hover/click to show/expand/close; methods could be grouped and ordered by particular criteria; etc., all while the underlying source file remains intact.
I never want a programming font without ligatures ever again.
This article, to me, seems like a case where the authors' ire is proportional to a) their understanding of the subject b) how relevant the topic is.
Because really, a) ligatures won't cause catastrophic failures by rendering code illegible and b) it really, really doesn't matter all that much. Non-destructive personal preference.
From the ticket it seems to me that the root cause was not handling text as GUI applications are supposed to do(aka like Wordprocessors).
1. By this reasoning, Unicode contradicts itself. There's lots of codepoints that I can't visually distinguish from one another, even when printed without ligatures. If the quality of visual uniqueness is important, better stick to printable ASCII.
2. Every syntax-highlighter I've ever used, for any language more complex than a Lisp, has been wrong, occasionally. Every IDE "find text" feature finds useless results, occasionally, from lack of context, too. Again, if perfection is your threshold for use, you're going to have to throw out half your editor.
If you want to go all Marie Kondo on your toolchain (like Chuck Moore has been doing for decades), that's neat, but that doesn't sound like what he's advocating here.
> If you don’t believe me, try it for 10 or 15 years.
Every time a programmer tells me this, and I ask around, I find that the population is split. Seriously, you don't believe me that emacs is 1000 times better than vi? Try it for a few years.
Personally, I'd love a keyboard that had a ≤ key and a programming language that recognized that symbol.
say 4 ≤ 5; # True
say 4 ≤ 4; # True
say 4 ≤ 3; # False
say 4 <= 5; # True
say 4 <= 4; # True
say 4 <= 3; # False
Specifically they are the exact same subroutine.
(The normal operators are just subroutines with a special name.) say &infix:« ≤ » =:= &infix:« <= »; # True
(The =:= operator is basically the same as pointer equivalence.)The line which creates this equivalence is the following:
my constant &infix:<≤> := &infix:«<=»;
https://github.com/rakudo/rakudo/blob/b0dd44b006dc44da5695b2...One language that uses unicode symbols liberally is Agda. Since it is a proof assistant, being able to use mathematical symbols helps a lot. They even remap the backspace key on Emacs to act as a sort of Compose key for typing all the symbols.
Get a keyboard with some extra keys (or a small side-board) and just get a ≤ key. Then just program it as a macro for <=.
Wouldn't really solve the "programming language recognizing the symbol" Though that could probably be hacked in as well if you _really_ want to.
I mean, I know this is not ideal. I'm just throwing out bad ideas :D
On a mac, hit option + "<".
I can't help you with the language, though.
If it is consistency and perfection everywhere you are looking to find, software engineering in general might not be the best job for you.
> They contradict Unicode
So what?
The ligatures are only supposed to look good in my editor, with my config, in the programming language I use and for my eyes only. Nothing else matters.
> They’re guaranteed to be wrong sometimes
See previous point.
As long as it's good enough for my purposes in the context I use the font, it doesn't matter if it breaks some edge case that makes the author upset.
> Bottom line: this isn’t a matter of taste.
It is a matter of context, which the author completely misses.
And yes, it's also a matter of taste. Everything design related is in parts taste.
Ligatures always confused me...
OTOH, perhaps because I use a proportional font, I would be curious to try one with operator ligatures. The interesting thing is that a ligature for !== wouldn't have to be three characters in width to preserve alignment, it could actually be the normal ≢ glyph.
This suggests an experiment: I'm already using a modified version of Trebuchet MS (my favorite coding font, but the tilde sucks so I swapped one in from a different font), so I could probably add some ligatures like the one above using existing glyphs instead of having to draw them by hand. I will have to try it sometime!
If the text looks huge, it's because I took the screenshot on a high-DPI device with 200% scaling, sorry about that. Imagine it half the size and you will have a better idea of how it actually looks.
In any case, the point is that code like this just doesn't depend on monospacing. If you viewed the same code in a monospaced font, it would look pretty much the same except for the font choice.
The key is to not do column alignment tricks that assume a monospaced font, like this:
doSomething(oneParam,
anotherParam);
Instead, if you just do indentation like this, your code will look fine with any font: doSomething(
oneParam,
anotherParam
);