From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Jackson Ray Hamilton Newsgroups: gmane.emacs.devel Subject: Re: Comprehensive JSX support in Emacs Date: Sun, 17 Feb 2019 23:17:10 -0800 Message-ID: <0a0f1acb-8d44-2a4f-e648-f596fa8dcfb5@jacksonrayhamilton.com> References: <1423022755.65233.1550120813763@privateemail.com> <4f6a7f78-caaf-4d1d-bf7a-d8415141efe6@www.fastmail.com> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="------------2C2CD036FBD685CE1DFA3E91" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="113215"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 Cc: emacs-devel@gnu.org To: jostein@kjonigsen.net Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Feb 18 08:17:43 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1gvdBP-000TLq-5Y for ged-emacs-devel@m.gmane.org; Mon, 18 Feb 2019 08:17:43 +0100 Original-Received: from localhost ([127.0.0.1]:51974 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gvdBO-0002Eb-0L for ged-emacs-devel@m.gmane.org; Mon, 18 Feb 2019 02:17:42 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:57247) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gvdBA-0002EQ-BL for emacs-devel@gnu.org; Mon, 18 Feb 2019 02:17:29 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gvdB8-0004QI-DS for emacs-devel@gnu.org; Mon, 18 Feb 2019 02:17:28 -0500 Original-Received: from mta-08-4.privateemail.com ([198.54.122.58]:22442) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gvdB7-0004Et-0E for emacs-devel@gnu.org; Mon, 18 Feb 2019 02:17:26 -0500 Original-Received: from MTA-08.privateemail.com (localhost [127.0.0.1]) by MTA-08.privateemail.com (Postfix) with ESMTP id 0C25F60044; Mon, 18 Feb 2019 02:17:11 -0500 (EST) Original-Received: from [192.168.88.227] (unknown [10.20.151.231]) by MTA-08.privateemail.com (Postfix) with ESMTPA id D078F60033; Mon, 18 Feb 2019 07:17:10 +0000 (UTC) In-Reply-To: <4f6a7f78-caaf-4d1d-bf7a-d8415141efe6@www.fastmail.com> Content-Language: en-US X-Virus-Scanned: ClamAV using ClamSMTP X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 198.54.122.58 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:233439 Archived-At: This is a multi-part message in MIME format. --------------2C2CD036FBD685CE1DFA3E91 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Hi Jostein, Thank you for bringing this use case to my attention. I haven=E2=80=99t worked with TypeScript before, but I took a look at the= docs,=20 and read through the whole JSX page.=C2=A0 It looks like the syntax for J= SX=20 is exactly the same in TS as in JS, so my work may have a chance of=20 integrating with typescript-mode. However, skimming through the rest of the docs, there could be=20 challenges dealing with code that uses angle brackets that look like=20 =E2=80=9Ctags,=E2=80=9D e.g.: |let list: Array =3D [1, 2, 3];| |let square =3D {};| |let counter =3D function (start: number) { };| |let output =3D identity("myString");| |function loggingIdentity(arg: Array): Array {=20 console.log(arg.length);return arg; }| |function loggingIdentity(arg: T): T {=20 console.log(arg.length);return arg; }| || |class GenericNumber { zeroValue: T; add: (x: T, y: T) =3D> T; }| I understand that =E2=80=9Ctype assertions=E2=80=9D will be written with = an |as| keyword=20 in TSX, but it looks like angle brackets are still used in other places=20 in TSX: |class Component extends React.Component { render() {=20 return (

{this.props.children}

) } }| The parser I=E2=80=99ve written to disambiguate JSX from JS in js-mode ma= kes the=20 assumption that matching angle brackets around identifiers indicate the=20 presence of JSX with certainty.=C2=A0 In order to adapt that code for TS,= one=20 solution could be to parse more, looking at the surrounding context of=20 the angle brackets to determine whether the thing is a TS type or if=20 it=E2=80=99s JSX.=C2=A0 If you=E2=80=99re up for that challenge, hooks co= uld be added to the=20 parser to perform additional context checks defined by your mode. Disclaimer: Maybe =E2=80=9Cparsing more=E2=80=9D won=E2=80=99t work, in w= hich case a different=20 strategy might be necessary.=C2=A0 Maybe it=E2=80=99s impossible to know = the=20 difference between a TS type and JSX without an AST=E2=80=A6 I dunno.=C2=A0= In any=20 case, as long as you can figure out what is JSX in TS, and the JSX is=20 marked with the same text properties that js-mode will use, then=20 integration with the rest of the JSX code (which indents and font-locks)=20 should be possible. Since typescript-mode doesn=E2=80=99t derive from js-mode, I expect you=E2= =80=99ll=20 manually pull in the JSX functions and variables from js-mode, and call=20 the functions and use the variables in similar ways, mirroring js-mode=E2= =80=99s=20 ways.=C2=A0 I expect you will do these things: * Merge JSX font-lock keywords into TypeScript=E2=80=99s * Use JSX syntax propertizing * Delegate to Emacs=E2=80=99 JSX indentation inside JSX, and go back to typescript-mode=E2=80=99s TS indenting inside JSX expressions * Enable JSX features for =E2=80=9C.tsx=E2=80=9D files I will try to keep the code modular to make it easy for you to pull in=20 the parts you need. Jackson --------------2C2CD036FBD685CE1DFA3E91 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable

Hi Jostein,

Thank you for bringing this use case to my attention.

I haven=E2=80=99t worked with TypeScript before, but I took a look= at the docs, and read through the whole JSX page.=C2=A0 It looks like the syntax for JSX is exactly the same in TS as in JS, so my work may have a chance of integrating with typescript-mode.

However, skimming through the rest of the docs, there could be challenges dealing with code that uses angle brackets that look like =E2=80=9Ctags,=E2=80=9D e.g.:

let list: Array<<=
span class=3D"hljs-built_in">number> =3D [1, 2, 3];
let square =3D <Square>{};
let counter =3D <Counter>function (sta=
rt: number) { };
let output =3D identity<=
string>("myString");<=
/pre>
    
function loggingIdentity<T>=
;(arg: Array<T>): Array<T> {
    console.log(arg.length);
    return arg;
}
function loggingIdentity<T extends Length=
wise>(arg: T): T {
    console.log(arg.length);
    return arg;
}
class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) =3D> T;
}

I understand that =E2=80=9Ctype assertions=E2=80=9D will be writte= n with an as keyword in TSX, but it looks like angle brackets are still used in other places in TSX:

class Component extends React.Component<PropsType, {}&=
gt; {
  render() {
    return (
      <h2>
        {this.props.children}
      </h2&=
gt;
    )
  }
}

The parser I=E2=80=99ve written to disambiguate JSX from JS in js-= mode makes the assumption that matching angle brackets around identifiers indicate the presence of JSX with certainty.=C2=A0 In o= rder to adapt that code for TS, one solution could be to parse more, looking at the surrounding context of the angle brackets to determine whether the thing is a TS type or if it=E2=80=99s JSX.=C2= =A0 If you=E2=80=99re up for that challenge, hooks could be added to the p= arser to perform additional context checks defined by your mode.

Disclaimer: Maybe =E2=80=9Cparsing more=E2=80=9D won=E2=80=99t wor= k, in which case a different strategy might be necessary.=C2=A0 Maybe it=E2=80=99s imp= ossible to know the difference between a TS type and JSX without an AST=E2=80=A6= I dunno.=C2=A0 In any case, as long as you can figure out what is JSX= in TS, and the JSX is marked with the same text properties that js-mode will use, then integration with the rest of the JSX code (which indents and font-locks) should be possible.

Since typescript-mode doesn=E2=80=99t derive from js-mode, I expec= t you=E2=80=99ll manually pull in the JSX functions and variables fro= m js-mode, and call the functions and use the variables in similar ways, mirroring js-mode=E2=80=99s ways.=C2=A0 I expect you will do = these things:

  • Merge JSX font-lock keywords into TypeScript=E2=80=99s
  • Use JSX syntax propertizing
  • Delegate to Emacs=E2=80=99 JSX indentation inside JSX, and go b= ack to typescript-mode=E2=80=99s TS indenting inside JSX expressions
  • Enable JSX features for =E2=80=9C.tsx=E2=80=9D files

I will try to keep the code modular to make it easy for you to pull in the parts you need.

Jackson

--------------2C2CD036FBD685CE1DFA3E91--