tonsky / FiraCode

Free monospaced font with programming ligatures
SIL Open Font License 1.1
76.81k stars 3.09k forks source link

Ligature request: ?.( and ?.[ #922

Open Validark opened 4 years ago

Validark commented 4 years ago

TypeScript and ECMAScript have new optional access operators. They look like so:

obj?.id - optional property access obj?.[expr] - optional element access func?.(arg) - optional call

See: https://github.com/tc39/proposal-optional-chaining

?.[ and ?.( were chosen as the optional element access and optional call operators respectively because using ?[ and ?( would have led to parsing difficulties for code like so:

obj?[expr].filter(fun):0;
func?(x - 2) + 3 :1

The problem, however, is that these don't look as nice as ?[ or ?(. A ligature could make it look better. I request that ligatures be added to hide the . or otherwise just blend the characters into a better-looking symbol.

Either way, thank you for making a great font!

Related: #215

tonsky commented 4 years ago

No, I can’t hide the dot, that would be too much. Not sure I know how make those into nice symbol too.

Validark commented 4 years ago

What about something like this but a little more squished together? ?•[ ?•(

Or, make it a question mark with two dots?

tonsky commented 4 years ago

Well logicall obj?.id is just obj? and .id concatenated, right? I don’t think they should be joined into a ligature. But then I have no idea how to interpret obj?.[expr] and fun?.(arg). I mean, what does dot there even mean?

Validark commented 4 years ago

The dot is there so that JS parsers can easily determine whether the question mark is a part of a conditional expression or not, as mentioned above. ?.[ and ?.( should be interpreted as you would interpret ?[ and ?(. The dot there doesn't mean anything.

apollolux commented 4 years ago

The dot there doesn't mean anything.

The dot there literally means the condition is attached to object access like the dot normally means in JS. If a ligature does end up happening the dot should not be removed.

My suggestion would be put the dot under the "umbrella" of the ? and/or enlarge or otherwise elongate that curvy ? hood. The "question mark with two dots" suggestion above would handle the non-bracket portion of the ligature in this way I would guess.

Validark commented 4 years ago

@apollolux No, it doesn't "literally mean" anything. Especially so, in the case of ?.(, which has nothing to do with any "object access" at all.

const foo = new Date().getSeconds() % 2 ? () => "ran!" : null;

// is there an "object access" here? No.
console.log(foo?.());
// the preceding line does:
//    if `foo` exists: call it and evaluate to the return value
//    else: evaluate as undefined
//    then print that to the console
apollolux commented 4 years ago

It IS object access - if the object exists then access the following member from it. Given how JS treats nearly everything as an object, including functions, your example is essentially accessing a zero-parameter constructor even though the foo variable was indeed assigned to be a function and was later called with that intent.

If JS were using arrow syntax to denote object member access like some other languages then it would be more obvious that it is conditional object access (even though the resulting foo?->( ) would probably look super weird to someone who's been programming in said languages for years before that).

osyrisrblx commented 4 years ago

@apollolux I think you might be confused here? foo?.() checks to see if foo is not null or undefined and then calls it. Otherwise, it returns undefined (via void 0).

TypeScript compiles this:

declare const x: (() => void) | undefined;
x?.();

as:

var _a;
(_a = x) === null || _a === void 0 ? void 0 : _a();

The "object access" you're referring to in the case of a.b?.() happens regardless of the ?. operator.