branch: externals/matlab-mode
commit a6c8ed6df9f51677411098ce264b2203aeda3580
Author: John Ciolfi <[email protected]>
Commit: John Ciolfi <[email protected]>

    matlab-ts-mode-ei: for struct alignment, handle multi-line field values
---
 matlab-ts-mode--ei.el                              | 50 +++++++++++++---------
 ...ric_indent_struct_with_multiline_field_values.m | 10 +++++
 ...t_struct_with_multiline_field_values_expected.m | 10 +++++
 ...uct_with_multiline_field_values_expected_msgs.m | 10 +++++
 ...ric_indent_struct_with_multiline_field_values.m | 10 +++++
 ...struct_with_multiline_field_values_expected.txt | 38 ++++++++++++++++
 6 files changed, 107 insertions(+), 21 deletions(-)

diff --git a/matlab-ts-mode--ei.el b/matlab-ts-mode--ei.el
index 5ea2acb034..1a0926ef32 100644
--- a/matlab-ts-mode--ei.el
+++ b/matlab-ts-mode--ei.el
@@ -947,14 +947,14 @@ column."
 
 (cl-defun matlab-ts-mode--ei-is-m-struct (struct)
   "Is function_call STRUCT node a multi-line struct that can be aligned?
-If so return the max field width of the struct."
+If so return `(max-field-width . arguments-node), else nil."
 
   (let* ((start-linenum (line-number-at-pos (treesit-node-start struct)))
          (cache-value (alist-get start-linenum 
matlab-ts-mode--ei-is-m-struct-alist))
          (max-field-width 0))
 
-    (when cache-value ;; 0 or max-field-width
-      (cl-return-from matlab-ts-mode--ei-is-m-struct (when (> cache-value 0) 
cache-value)))
+    (when cache-value ;; '(0 . nil) or (max-field-width . assignment-node)
+      (cl-return-from matlab-ts-mode--ei-is-m-struct (when (> (car 
cache-value) 0) cache-value)))
 
     (let* ((end-line (line-number-at-pos (treesit-node-end struct)))
            arguments-node
@@ -1000,18 +1000,21 @@ If so return the max field width of the struct."
           (when (and n-args-on-tracking-line (= n-args-on-tracking-line 1)) ;; 
0 or 2 is good
             (setq is-m-struct nil))))
 
-      (when matlab-ts-mode--ei-is-m-struct-alist
-        ;; Use 1 or 0 so we can differentiate between nil and not a multi-line 
struct
-        (push `(,start-linenum . ,(if is-m-struct max-field-width 0))
-              matlab-ts-mode--ei-is-m-struct-alist))
-
-      (when (and is-m-struct (> max-field-width 0))
-        max-field-width))))
+      (let ((ans (when (and is-m-struct (> max-field-width 0))
+                   `(,max-field-width . ,arguments-node))))
+        (when matlab-ts-mode--ei-is-m-struct-alist
+          ;; Use 1 or 0 so we can differentiate between nil and not a 
multi-line struct
+          (push `(,start-linenum . ,(if ans ans '(0 . nil)))
+                matlab-ts-mode--ei-is-m-struct-alist))
+        ans))))
 
-(cl-defun matlab-ts-mode--ei-align-line-in-m-struct (struct-assign-node 
max-field-width ei-info)
-  "Align multi-line struct in STRUCT-ASSIGN-NODE to MAX-FIELD-WIDTH.
+(cl-defun matlab-ts-mode--ei-align-line-in-m-struct (tuple ei-info)
+  "Align multi-line struct.
+TUPLE = (list struct-assign-node max-field-width arguments-node) where
 See `matlab-ts-mode--ei-get-new-line' for EI-INFO."
   (let* ((ei-line (nth 0 ei-info))
+         (struct-assign-node (nth 0 tuple))
+         (max-field-width (nth 1 tuple))
          (assign-linenum (line-number-at-pos (treesit-node-start 
struct-assign-node)))
          comma-offset
          new-comma-offset)
@@ -1033,7 +1036,12 @@ See `matlab-ts-mode--ei-get-new-line' for EI-INFO."
             new-comma-offset (+ (string-match-p "[^ \t]" ei-line) 
max-field-width))
       (when (not comma-offset) ;; Ending ");" by itself on a line
         ;; TopTester: electric_indent_struct_in_prop2.m
-        (cl-return-from matlab-ts-mode--ei-align-line-in-m-struct ei-info)))
+        (cl-return-from matlab-ts-mode--ei-align-line-in-m-struct ei-info))
+      (let ((first-node-in-line (nth 3 ei-info))
+            (arguments-node (nth 2 tuple)))
+        (when (not (equal (treesit-node-parent first-node-in-line) 
arguments-node))
+          ;; TopTester: xxx
+          (cl-return-from matlab-ts-mode--ei-align-line-in-m-struct ei-info))))
 
     (let ((n-spaces-to-add (- new-comma-offset comma-offset)))
       (when (not (= n-spaces-to-add 0))
@@ -1057,7 +1065,7 @@ assignment node when A-TYPE is met, else nil.  A-TYPE can 
be:
  - \\='m-struct    : varName = struct(...       % struct on multiple lines
                         \\='field1\\', value1, ...
                         \\='otherField2\\', value2);
-Note, \\='m-struct returns (cons assignment-node max-field-width) or nil."
+Note, \\='m-struct returns (list assignment-node max-field-width 
arguments-node) or nil."
   (when (not assign-node)
     (setq assign-node (treesit-parent-until first-node (rx bos "assignment" 
eos))))
 
@@ -1101,9 +1109,9 @@ Note, \\='m-struct returns (cons assignment-node 
max-field-width) or nil."
                                (string= (treesit-node-text 
(treesit-node-child-by-field-name
                                                             next-node "name"))
                                         "struct"))
-                      (let ((max-field-width (matlab-ts-mode--ei-is-m-struct 
next-node)))
-                        (when max-field-width
-                          (cons assign-node max-field-width)))))))))
+                      (let ((pair (matlab-ts-mode--ei-is-m-struct next-node))) 
;; cdr => arguments
+                        (when (and pair (> (car pair) 0)) ;; max-field-width > 
0?
+                          (list assign-node (car pair) (cdr pair))))))))))
 
              (t
               (error "Assert: bad a-type %S" a-type)))))))))
@@ -1384,9 +1392,9 @@ See `matlab-ts-mode--ei-get-new-line' for EI-INFO 
contents."
   (let ((matrix-assign-node (matlab-ts-mode--ei-point-in-m-type ei-info 
'm-matrix)))
     (if matrix-assign-node
         (setq ei-info (matlab-ts-mode--ei-align-line-in-m-matrix 
matrix-assign-node ei-info))
-      (let ((pair (matlab-ts-mode--ei-point-in-m-type ei-info 'm-struct)))
-        (if pair
-            (setq ei-info (matlab-ts-mode--ei-align-line-in-m-struct (car 
pair) (cdr pair) ei-info))
+      (let ((tuple (matlab-ts-mode--ei-point-in-m-type ei-info 'm-struct)))
+        (if tuple
+            (setq ei-info (matlab-ts-mode--ei-align-line-in-m-struct tuple 
ei-info))
           ;; else do single-line alignments
           (setq ei-info (matlab-ts-mode--ei-align-assignments ei-info))
           (setq ei-info (matlab-ts-mode--ei-align-properties ei-info))
@@ -1699,4 +1707,4 @@ This expansion of the region is done to simplify electric 
indent."
 
 ;; LocalWords:  SPDX gmail treesit defcustom bos eos isstring defun eol eobp 
setq curr cdr xr progn
 ;; LocalWords:  listp alist dolist setf tmp buf utils linenum nums bobp pcase 
untabify SPC
-;; LocalWords:  linenums reindent bol fubar
+;; LocalWords:  linenums reindent bol fubar repeat:ans
diff --git 
a/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values.m
 
b/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values.m
new file mode 100644
index 0000000000..d17ea1e5bd
--- /dev/null
+++ 
b/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values.m
@@ -0,0 +1,10 @@
+% -*- matlab-ts -*-
+
+% t-utils-test-indent: no-line-by-line-indent - line-by-line typing results in 
error nodes
+
+foobar = struct('type'   , {'one', 'two', ...
+'three', 'four'}, ...
+                   'fooport', {1, 2, 3, 4, 4, 4, 4, 4, 4, 1, 2}, ...
+         't',1                  , ...
+ 'x'      ,    struct('a', 1, ...
+                                 'foo', 10));
diff --git 
a/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected.m
 
b/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected.m
new file mode 100644
index 0000000000..7d11eec04e
--- /dev/null
+++ 
b/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected.m
@@ -0,0 +1,10 @@
+% -*- matlab-ts -*-
+
+% t-utils-test-indent: no-line-by-line-indent - line-by-line typing results in 
error nodes
+
+foobar = struct('type'   , {'one', 'two', ...
+                            'three', 'four'}, ...
+                'fooport', {1, 2, 3, 4, 4, 4, 4, 4, 4, 1, 2}, ...
+                't'      , 1, ...
+                'x'      , struct('a', 1, ...
+                                  'foo', 10));
diff --git 
a/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected_msgs.m
 
b/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected_msgs.m
new file mode 100644
index 0000000000..425d78f48c
--- /dev/null
+++ 
b/tests/test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected_msgs.m
@@ -0,0 +1,10 @@
+% -*- matlab-ts -*- %  <{Matched rule: (matlab-ts-mode--i-top-level 
matlab-ts-mode--column-0 0)}>
+
+% t-utils-test-indent: no-line-by-line-indent - line-by-line typing results in 
error nodes %  <{Matched rule: (matlab-ts-mode--i-top-level 
matlab-ts-mode--column-0 0)}>
+
+foobar = struct('type'   , {'one', 'two', ... %  <{Matched rule: 
(matlab-ts-mode--i-top-level matlab-ts-mode--column-0 0)}>
+                            'three', 'four'}, ... %  <{Matched rule: 
((parent-is "\\`\\(?:function_output\\|row\\)\\'") parent 0)}>
+                'fooport', {1, 2, 3, 4, 4, 4, 4, 4, 4, 1, 2}, ... %  <{Matched 
rule: ((parent-is "\\`arguments\\'") parent 0)}>
+                't'      , 1, ... %  <{Matched rule: ((parent-is 
"\\`arguments\\'") parent 0)}>
+                'x'      , struct('a', 1, ... %  <{Matched rule: ((parent-is 
"\\`arguments\\'") parent 0)}>
+                                  'foo', 10)); %  <{Matched rule: ((parent-is 
"\\`arguments\\'") parent 0)}>
diff --git 
a/tests/test-matlab-ts-mode-parser-files/copy-of-test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values.m
 
b/tests/test-matlab-ts-mode-parser-files/copy-of-test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values.m
new file mode 100644
index 0000000000..d17ea1e5bd
--- /dev/null
+++ 
b/tests/test-matlab-ts-mode-parser-files/copy-of-test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values.m
@@ -0,0 +1,10 @@
+% -*- matlab-ts -*-
+
+% t-utils-test-indent: no-line-by-line-indent - line-by-line typing results in 
error nodes
+
+foobar = struct('type'   , {'one', 'two', ...
+'three', 'four'}, ...
+                   'fooport', {1, 2, 3, 4, 4, 4, 4, 4, 4, 1, 2}, ...
+         't',1                  , ...
+ 'x'      ,    struct('a', 1, ...
+                                 'foo', 10));
diff --git 
a/tests/test-matlab-ts-mode-parser-files/copy-of-test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected.txt
 
b/tests/test-matlab-ts-mode-parser-files/copy-of-test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected.txt
new file mode 100644
index 0000000000..1aadb0798c
--- /dev/null
+++ 
b/tests/test-matlab-ts-mode-parser-files/copy-of-test-matlab-ts-mode-electric-indent-files/electric_indent_struct_with_multiline_field_values_expected.txt
@@ -0,0 +1,38 @@
+# -*- t-utils-ts-parse-tree -*-
+(source_file<1,369> (comment[1,20]@{% -*- matlab-ts -*-}@) (comment[22,112]@{% 
t-utils-test-indent: no-line-by-line-indent - li...}@)
+ (assignment<114,367> left: (identifier[114,120]@{foobar}@) =[121,122]
+  right: 
+   (function_call<123,367> name: (identifier[123,129]@{struct}@) ([129,130]
+    (arguments<130,366>
+     argument: (string<130,136> '[130,131] (string_content[131,135]@{type}@) 
'[135,136])
+     ,[139,140]
+     (cell<141,176> {[141,142]
+      (row<142,175>
+       (string<142,147> '[142,143] (string_content[143,146]@{one}@) '[146,147])
+       ,[147,148]
+       (string<149,154> '[149,150] (string_content[150,153]@{two}@) '[153,154])
+       ,[154,155] (line_continuation[156,160]@{...\n}@)
+       (string<160,167> '[160,161] (string_content[161,166]@{three}@) 
'[166,167])
+       ,[167,168]
+       (string<169,175> '[169,170] (string_content[170,174]@{four}@) 
'[174,175]))
+      }[175,176])
+     ,[176,177] (line_continuation[178,182]@{...\n}@)
+     (string<201,210> '[201,202] (string_content[202,209]@{fooport}@) 
'[209,210])
+     ,[210,211]
+     (cell<212,245> {[212,213]
+      (row<213,244> (number[213,214]@{1}@) ,[214,215] (number[216,217]@{2}@) 
,[217,218] (number[219,220]@{3}@) ,[220,221] (number[222,223]@{4}@) ,[223,224] 
(number[225,226]@{4}@) ,[226,227] (number[228,229]@{4}@) ,[229,230] 
(number[231,232]@{4}@) ,[232,233] (number[234,235]@{4}@) ,[235,236] 
(number[237,238]@{4}@) ,[238,239] (number[240,241]@{1}@) ,[241,242] 
(number[243,244]@{2}@))
+      }[244,245])
+     ,[245,246] (line_continuation[247,251]@{...\n}@)
+     (string<260,263> '[260,261] (string_content[261,262]@{t}@) '[262,263])
+     ,[263,264] (number[264,265]@{1}@) ,[283,284] 
(line_continuation[285,289]@{...\n}@)
+     (string<290,293> '[290,291] (string_content[291,292]@{x}@) '[292,293])
+     ,[299,300]
+     (function_call<304,366> name: (identifier[304,310]@{struct}@) ([310,311]
+      (arguments<311,365>
+       argument: (string<311,314> '[311,312] (string_content[312,313]@{a}@) 
'[313,314])
+       ,[314,315] (number[316,317]@{1}@) ,[317,318] 
(line_continuation[319,323]@{...\n}@)
+       (string<356,361> '[356,357] (string_content[357,360]@{foo}@) '[360,361])
+       ,[361,362] (number[363,365]@{10}@))
+      )[365,366]))
+    )[366,367]))
+ ;[367,368] \n[368,369])

Reply via email to