GNU bug report logs - #77901
tsx-ts-mode: ternary chains are indented as a tree

Previous Next

Package: emacs;

Reported by: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>

Date: Fri, 18 Apr 2025 14:26:06 UTC

Severity: normal

To reply to this bug, email your comments to 77901 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#77901; Package emacs. (Fri, 18 Apr 2025 14:26:08 GMT) Full text and rfc822 format available.

Acknowledgement sent to Konstantin Kharlamov <Hi-Angel <at> yandex.ru>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Fri, 18 Apr 2025 14:26:08 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
To: bug-gnu-emacs <at> gnu.org
Subject: tsx-ts-mode: ternary chains are indented as a tree
Date: Fri, 18 Apr 2025 17:06:34 +0300
Given this correctly indented code:

    const a = cond1 ? 1
      : cond2 ? 2
      : cond3 ? 3
      : 4;

if you reindent it, it turns into:

    const a = cond1 ? 1
      : cond2 ? 2
        : cond3 ? 3
          : 4;

Basically, for every colon it increases indentation. This is different
from other c-like languages (it's is indented as the first form
instead), and it's also different from Python. The "tree-indentation"
is not readable, so there's a reason other modes indent it as the
first example. Would it be possible to change in typescript mode as
well?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77901; Package emacs. (Thu, 01 May 2025 13:40:06 GMT) Full text and rfc822 format available.

Message #8 received at 77901 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
To: 77901 <at> debbugs.gnu.org
Subject: bug#77901: tsx-ts-mode: ternary chains are indented as a tree
Date: Thu, 01 May 2025 20:39:02 +0700
[Message part 1 (text/plain, inline)]
After poking around I wrote a patch (attached). Worth noting though, for
some reason it doesn't work for ternary without starting colon, e.g.:

    const a = cond1 ? 1 :
      cond2 ? 2 :
      cond3 ? 3 : 4;

I'm unclear why, per my understanding the "standalone-parent" of the
whole ternary chain (disregarding where the point is) is the `const a
=` declaration.

Such bug also persists in c++-ts-mode (as opposed to non-ts plain c++-
mode). I'm not sure if it's me misunderstanding something or not…
[1.patch (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77901; Package emacs. (Sat, 10 May 2025 10:17:01 GMT) Full text and rfc822 format available.

Message #11 received at 77901 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>,
 Yuan Fu <casouri <at> gmail.com>
Cc: 77901 <at> debbugs.gnu.org
Subject: Re: bug#77901: tsx-ts-mode: ternary chains are indented as a tree
Date: Sat, 10 May 2025 13:16:30 +0300
> From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
> Date: Thu, 01 May 2025 20:39:02 +0700
> 
> After poking around I wrote a patch (attached). Worth noting though, for
> some reason it doesn't work for ternary without starting colon, e.g.:
> 
>     const a = cond1 ? 1 :
>       cond2 ? 2 :
>       cond3 ? 3 : 4;
> 
> I'm unclear why, per my understanding the "standalone-parent" of the
> whole ternary chain (disregarding where the point is) is the `const a
> =` declaration.
> 
> Such bug also persists in c++-ts-mode (as opposed to non-ts plain c++-
> mode). I'm not sure if it's me misunderstanding something or not…

Yuan, any comments?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77901; Package emacs. (Tue, 13 May 2025 19:46:02 GMT) Full text and rfc822 format available.

Message #14 received at 77901 <at> debbugs.gnu.org (full text, mbox):

From: Yuan Fu <casouri <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 77901 <at> debbugs.gnu.org, Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
Subject: Re: bug#77901: tsx-ts-mode: ternary chains are indented as a tree
Date: Tue, 13 May 2025 12:45:17 -0700
Hey, sorry for the delay.

> On May 10, 2025, at 3:16 AM, Eli Zaretskii <eliz <at> gnu.org> wrote:
> 
>> From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
>> Date: Thu, 01 May 2025 20:39:02 +0700
>> 
>> After poking around I wrote a patch (attached).

Thanks! LGTM. For some reason I can’t apply the patch on either emacs-30 or master. [1]

>> Worth noting though, for
>> some reason it doesn't work for ternary without starting colon, e.g.:
>> 
>>    const a = cond1 ? 1 :
>>      cond2 ? 2 :
>>      cond3 ? 3 : 4;
>> 
>> I'm unclear why, per my understanding the "standalone-parent" of the
>> whole ternary chain (disregarding where the point is) is the `const a
>> =` declaration.

The standalone rule just keeps going up the parse tree until it finds a node that starts on a new line. In this case, if you start form cond3, it’ll go up until reaching the teneray_expression node containing cond2. This node starts on a new line so standalone-parent stops here. So the cond3 line uses the cond2 line as the anchor, instead of the “const a” line. If you add a cond4 line, it’ll use the cond3 line as anchor.

There’re several ways to fix it. The best way is to add a new anchor to the presets that does what standalone-parent does, but additionally excludes some nodes. Something like (standalone-parent-excluding “regexp”). Then this can be used for both typescript and c/c++ (and java, etc).

>> 
>> Such bug also persists in c++-ts-mode (as opposed to non-ts plain c++-
>> mode). I'm not sure if it's me misunderstanding something or not…
> 
> Yuan, any comments?

Yeah we should fix this in c/c++-ts-mode too. In c/c++, the baseline-indent-rule can handle

  int a = cond1 ? 1
	: cond2 ? 2
	: cond3 ? 3
	: 4;

Which is nice, but the other case needs special case override:

  int a = cond1 ? 1 :
    cond2 ? 2 :
      cond3 ? 3 :
        cond 4: 5;

Yuan

[1] I got this error:

128 git … am --3way -- /Users/yuan/downloads/1-3.patch
Applying: typescript-ts: align ternary-chain branches (bug#78187)
error: sha1 information is lacking or useless (test/lisp/progmodes/typescript-ts-mode-resources/indent.erts).
error: could not build fake ancestor
Patch failed at 0001 typescript-ts: align ternary-chain branches (bug#78187)
hint: Use 'git am --show-current-patch=diff' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#77901; Package emacs. (Wed, 14 May 2025 14:52:01 GMT) Full text and rfc822 format available.

Message #17 received at 77901 <at> debbugs.gnu.org (full text, mbox):

From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
To: Yuan Fu <casouri <at> gmail.com>, Eli Zaretskii <eliz <at> gnu.org>
Cc: 77901 <at> debbugs.gnu.org
Subject: Re: bug#77901: tsx-ts-mode: ternary chains are indented as a tree
Date: Wed, 14 May 2025 21:50:56 +0700
[Message part 1 (text/plain, inline)]
On Tue, 2025-05-13 at 12:45 -0700, Yuan Fu wrote:
> Hey, sorry for the delay.
>
> > On May 10, 2025, at 3:16 AM, Eli Zaretskii <eliz <at> gnu.org> wrote:
> >
> > > From: Konstantin Kharlamov <Hi-Angel <at> yandex.ru>
> > > Date: Thu, 01 May 2025 20:39:02 +0700
> > >
> > > After poking around I wrote a patch (attached).
>
> Thanks! LGTM. For some reason I can’t apply the patch on either
> emacs-30 or master. [1]

Oh, interesting.  I kind of know where the error is coming from, but
only partially.  The reason for the error is that the patch I sent was
applied over the patch for #78121 (which is pending btw 😊) as I'm
using them both for coding.   At the same time, I don't really
understand the source of the error as the same parameters work for me:

    ╰─λ git am --3way -- /tmp/1.patch
    Applying: typescript-ts: align ternary-chain branches (bug#78187)
    Using index info to reconstruct a base tree...
    M       lisp/progmodes/typescript-ts-mode.el
    M       test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
    Falling back to patching base and 3-way merge...
    Auto-merging test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
    Auto-merging lisp/progmodes/typescript-ts-mode.el

Either way, I redone the patch on top of the tree, please try this one

> > > Worth noting though, for
> > > some reason it doesn't work for ternary without starting colon,
> > > e.g.:
> > >
> > >    const a = cond1 ? 1 :
> > >      cond2 ? 2 :
> > >      cond3 ? 3 : 4;
> > >
> > > I'm unclear why, per my understanding the "standalone-parent" of
> > > the
> > > whole ternary chain (disregarding where the point is) is the
> > > `const a
> > > =` declaration.
>
> The standalone rule just keeps going up the parse tree until it finds
> a node that starts on a new line. In this case, if you start form
> cond3, it’ll go up until reaching the teneray_expression node
> containing cond2. This node starts on a new line so standalone-parent
> stops here. So the cond3 line uses the cond2 line as the anchor,
> instead of the “const a” line. If you add a cond4 line, it’ll use the
> cond3 line as anchor.
>
> There’re several ways to fix it. The best way is to add a new anchor
> to the presets that does what standalone-parent does, but
> additionally excludes some nodes. Something like (standalone-parent-
> excluding “regexp”). Then this can be used for both typescript and
> c/c++ (and java, etc).

Oh, I see, thank you!
[3.patch (text/x-patch, attachment)]

This bug report was last modified today.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.