Subject: Re: bug#68054: [PATCH] Add tree-sitter indent rule for lexical decls in js/typescript

From: Noah Peart <[email-masked]>
Date: Wed, 17 Apr 2024 13:21:10 -0700

Sorry, I forgot about this. I've just added a rule to align the
variable_declarators
in let, var, and const declarations, but I need some feedback about the
indentation
for values in the variable_declarators following dangling '='.

For example, which of the following would be preferable?

1) indent the dangling values with respect to start of the declaration

    const a =
        (x: string): string => {
            return x + x;
        },
          bbb =
        {
            "x": 0
        },
          cccc =
        1,
          ddddd = 0;

2) indent them with respect to the start of the variable_declarator

    const a =
              (x: string): string => {
                  return x + x;
              },
          bbb =
              {
                  "x": 0
              },
          cccc =
              1,
          ddddd = 0;

3) align with the variable declarators (this is the same as js-mode)

    const a =
          (x: string): string => {
              return x + x;
          },
          bbb =
          {
              "x": 0
          },
          cccc =
          1,
          ddddd = 0;

I've attached a patch with with the rules for the 3 options here.

On Sun, Dec 31, 2023 at 8:56 PM Yuan Fu <[email-masked]> wrote:

>
>
> > On Dec 31, 2023, at 5:41 AM, Dmitry Gutov <[email-masked]> wrote:
> >
> > On 31/12/2023 07:35, Noah Peart wrote:
> >> Yea, I agree that would be better - would you align on start the
> variable names, or '=' like
> >> `c-lineup-assignments`?
> >
> > Like js-mode would be good.
> >
> > I'm not familiar with c-lineup-assignments, but we could add different
> variations later.
>
> Also, if you are feeling adventurous, I noticed that the second variable
> in a lexical_declaration isn’t fontified in variable-name-face. It’d be
> nice to fix that as well.
>
> Yuan
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index ab1d76ab20e..9dbe5df8368 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -91,6 +91,16 @@ tsx-ts-mode--indent-compatibility-b893426
      `(((match "<" "jsx_text") parent 0)
        ((parent-is "jsx_text") parent typescript-ts-mode-indent-offset)))))
 
+(defun typescript-ts-mode--anchor-decl (_n parent &rest _)
+  "Return the position after the declaration keyword before PARENT.
+
+This anchor allows aligning variable_declarators in variable and lexical
+declarations, accounting for the length of keyword (var, let, or const)."
+  (let ((decl (treesit-parent-until
+               parent (rx (or "variable" "lexical") "_declaration") t)))
+    (+ (treesit-node-start decl)
+       (length (treesit-node-text (treesit-node-child decl 0))))))
+
 (defun typescript-ts-mode--indent-rules (language)
   "Rules used for indentation.
 Argument LANGUAGE is either `typescript' or `tsx'."
@@ -113,7 +123,24 @@ typescript-ts-mode--indent-rules
      ((parent-is "switch_case") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "switch_default") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "type_arguments") parent-bol typescript-ts-mode-indent-offset)
-     ((parent-is "variable_declarator") parent-bol typescript-ts-mode-indent-offset)
+
+     ;; 1. indent with respect to declaration start:
+     ((parent-is "variable_declarator") grand-parent typescript-ts-mode-indent-offset)
+     ((parent-is ,(rx (or "variable" "lexical") "_declaration"))
+      typescript-ts-mode--anchor-decl 1)
+
+     ;; 2. indent with respect to variable_declarator start:
+     ((match nil "variable_declarator" nil 0 1)
+      parent-bol typescript-ts-mode-indent-offset)
+     ((n-p-gp nil "variable_declarator" ,(rx (or "variable" "lexical") "_declaration"))
+      parent typescript-ts-mode-indent-offset)
+     ((parent-is ,(rx (or "variable" "lexical") "_declaration"))
+      typescript-ts-mode--anchor-decl 1)
+
+     ;; 3. align with variable declarator (like js-mode)
+     ((parent-is ,(rx (or "variable" "lexical") "_" (or "declaration" "declarator")))
+      typescript-ts-mode--anchor-decl 1)
+
      ((parent-is "arguments") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "array") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "formal_parameters") parent-bol typescript-ts-mode-indent-offset)