branch: externals/matlab-mode
commit 5cbe5042286f02c8890c27f2790be084f395ff26
Author: John Ciolfi <[email protected]>
Commit: John Ciolfi <[email protected]>
matlab-ts-mode: indent fixes for incomplete matrix/cell/switch
---
contributing/treesit-mode-how-to.org | 84 ++++++-
matlab-ts-mode.el | 260 +++++++++++++++-----
tests/t-utils.el | 11 +-
.../indent_xr_cell1.m | 2 +
.../indent_xr_cell1_expected.org | 272 +++++++++++++++++++++
.../indent_xr_fun.m | 2 +
.../indent_xr_fun_expected.org | 139 +++++++++++
.../indent_xr_mat0.m | 6 +
.../indent_xr_mat0_expected.org | 81 ++++++
.../indent_xr_mat1.m | 8 +
.../indent_xr_mat1_expected.org | 119 +++++++++
.../indent_xr_mat2.m | 7 +
.../indent_xr_mat2_expected.org | 65 +++++
.../indent_xr_mat3.m | 6 +
.../indent_xr_mat3_expected.org | 67 +++++
.../indent_xr_mat4.m | 14 ++
.../indent_xr_mat4_expected.org | 167 +++++++++++++
.../indent_xr_switch.m | 16 ++
.../indent_xr_switch_expected.org | 162 ++++++++++++
tests/test-matlab-ts-mode-indent-xr.el | 67 +++++
tests/test-matlab-ts-mode-indent.el | 10 +-
21 files changed, 1497 insertions(+), 68 deletions(-)
diff --git a/contributing/treesit-mode-how-to.org
b/contributing/treesit-mode-how-to.org
index 6d2f42e4ca..caf44f8ac8 100644
--- a/contributing/treesit-mode-how-to.org
+++ b/contributing/treesit-mode-how-to.org
@@ -711,6 +711,9 @@ We use a looping pattern similar to the font-lock test for
our indent tests:
./tests/test-LANGUAGE-ts-mode-indent.el
./tests/test-LANGUAGE-ts-mode-indent-files/indent_test1.lang
./tests/test-LANGUAGE-ts-mode-indent-files/indent_test1_expected.lang //
generated for you
+ ./tests/test-LANGUAGE-ts-mode-indent-files/indent_test2.lang
+ ./tests/test-LANGUAGE-ts-mode-indent-files/indent_test2_expected.lang //
generated for you
+ ....
#+end_example
where test-LANGUAGE-ts-mode-indent.el contains:
@@ -752,6 +755,85 @@ where test-LANGUAGE-ts-mode-indent.el contains:
(t-utils-test-indent test-name)))
#+end_src
+** Test: Indent as you type
+
+Code should be indented correctly as you type. Consider
+
+ : someVariable = {
+ : ^ <== Cursor should move here when RET is typed at end
of prior line
+
+To test this we use =t-utils-xr= to execute and record editing commands. The
test setup:
+
+#+begin_example
+ ./LANGUAGE-ts-mode.el
+ ./tests/test-LANGUAGE-ts-mode-indent-xr.el
+ ./tests/test-LANGUAGE-ts-mode-indent-xr-files/indent_test1.lang
+ ./tests/test-LANGUAGE-ts-mode-indent-xr-files/indent_test1_expected.org //
generated for you
+ ....
+#+end_example
+
+where =test-LANGUAGE-ts-mode-indent-xr.el= contains:
+
+#+begin_src emacs-lisp
+ (require 't-utils)
+ (require 'LANGUAGE-ts-mode)
+
+ (defvar test-LANGUAGE-ts-mode-indent-xr--file nil)
+
+ (defun test-LANGUAGE-ts-mode-indent-xr--file (lang-file)
+ "Test an individual LANG-FILE.
+ This is provided for debugging.
+ M-: (test-LANGUAGE-ts-mode-indent-xr--file
+ \"test-LANGUAGE-ts-mode-indent-xr-files/LANG-FILE\")"
+ (let ((test-LANGUAGE-ts-mode-indent-xr--file lang-file))
+ (ert-run-tests-interactively "test-LANGUAGE-ts-mode-indent-xr")))
+
+ (ert-deftest test-LANGUAGE-ts-mode-indent-xr ()
+ "Test indent using ./test-LANGUAGE-ts-mode-indent-xr-files/NAME.lang.
+ Using ./test-LANGUAGE-ts-mode-indent-xr-files/NAME.lang, compare typing
+ commands via `t-utils-xr' Lisp commans in the *.lang files and compare
+ agains ./test-LANGUAGE-ts-mode-indent-xr-files/NAME_expected.org. This
+ loops on all ./test-LANGUAGE-ts-mode-indent-xr-files/NAME.lang files.
+
+ To add a test, create
+ ./test-LANGUAGE-ts-mode-indent-xr-files/NAME.lang
+ and run this function. The baseline is saved for you as
+ ./test-LANGUAGE-ts-mode-indent-xr-files/NAME_expected.org~
+ after validating it, rename it to
+ ./test-LANGUAGE-ts-mode-indent-xr-files/NAME_expected.org"
+
+ (let* ((test-name "test-LANGUAGE-ts-mode-indent-xr")
+ (lang-files (t-utils-get-files
+ test-name
+ (rx ".lang" eos)
+ nil
+ test-LANGUAGE-ts-mode-indent-xr--file)))
+ (t-utils-error-if-no-treesit-for 'LANGUAGE test-name)
+ (t-utils-test-xr test-name lang-files)))
+#+end_src
+
+An example =./tests/test-LANGUAGE-ts-mode-indent-xr-files/indent_test1.lang=
where =%= is starts a
+comment:
+
+#+begin_example
+ % -*- LANGAUAGE-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "someVariable = {") "C-e" "C-m" (insert
"1234") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+#+end_example
+
+The execute and record function, =t-utils-xr= runs the Emacs commands which
creates below the
+comment line.
+
+#+begin_example
+ someVariable = {
+ 1234
+ }
+#+end_example
+
+The commands are recorded into
+=./tests/test-LANGUAGE-ts-mode-indent-xr-files/indent_test1_expected.org~= and
compared against
+baseline =indent_test1_expected.org=. If the baseline doesn't exist you are
asked to review
+=indent_test1_expected.org~= and rename it to indent_test1_expected.org if it
looks good.
+
** Sweep test: Indent
We define a sweep test to be a test that tries an action on a large number of
files and reports
@@ -1545,7 +1627,7 @@ the color marker is) to see messages that were displayed
by your test.
If the =./tests/test-LANUGAGE-ts-mode-file-encoding-files/NAME*_expected.txt~=
files look good
rename them to
=./tests/test-LANUGAGE-ts-mode-file-encoding-files/NAME*_expected.txt= (per the
messages shown by ert).
-
+
* Final version
TODO
diff --git a/matlab-ts-mode.el b/matlab-ts-mode.el
index e7c3ec8bd0..873fd898e9 100644
--- a/matlab-ts-mode.el
+++ b/matlab-ts-mode.el
@@ -838,7 +838,8 @@ For optional _NODE, PARENT, and _BOL see
`treesit-simple-indent-rules'."
;; - Otherwise, matlab-ts-mode--function-indent-level is 0, we will
"upgrade" it to
;; matlab-ts-mode--indent-level if function end's appear.
- (let ((root (if (and parent (string= (treesit-node-type parent)
"function_definition"))
+ (let ((root (if (and parent
+ (string= (treesit-node-type parent)
"function_definition"))
parent
(treesit-buffer-root-node))))
(if (treesit-search-subtree (treesit-buffer-root-node) "\\`ERROR\\'")
@@ -849,7 +850,7 @@ For optional _NODE, PARENT, and _BOL see
`treesit-simple-indent-rules'."
(let ((first-fcn (treesit-search-subtree root (rx bos
"function_definition" eos))))
(if (not first-fcn)
;; assume that if functions are added they will have ends
- (setq-local matlab-ts--function-indent-level t)
+ (setq-local matlab-ts-mode--function-indent-level
matlab-ts-mode--indent-level)
(let ((have-end (string= (treesit-node-type (treesit-node-child
first-fcn -1)) "end")))
(if (equal matlab-ts-mode--function-indent-level 'unset)
(setq-local matlab-ts-mode--function-indent-level
@@ -869,34 +870,6 @@ For optional _NODE, PARENT, and _BOL see
`treesit-simple-indent-rules'."
;; A 0 indicates functions are not terminated by an end keyword
(not (= matlab-ts-mode--function-indent-level 0)))
-(defun matlab-ts-mode--prev-real-line (_n _p bol &rest _)
- "Return point of first non-whitespace looking backward.
-BOL, beginning-of-line point, is where to start from."
- (save-excursion
- (goto-char bol)
- (forward-line -1)
- (while (and (not (bobp))
- (looking-at "^[ \t]*$"))
- (forward-line -1))
- (skip-chars-forward " \t")
- (point)))
-
-(defun matlab-ts-mode--prev-real-line-is (node-type prev-real-line-node-type)
- "Node type matcher and previous real line type matcher.
-Returns non-nil if the current tree-sitter node matches NODE-TYPE and
-the previous non-empty line tree-sitter node type matches
-PREV-REAL-LINE-NODE-TYPE. NODE-TYPE can be nil when there's no current
-node or a regular expression. PREV-REAL-LINE-NODE-TYPE is a regular
-expression."
- (lambda (node parent bol &rest _)
- (when (or (and (not node-type)
- (not node))
- (and node-type
- (string-match-p node-type (or (treesit-node-type node)
""))))
- (let* ((prev-real-line-bol (matlab-ts-mode--prev-real-line node parent
bol))
- (p-node (treesit-node-at prev-real-line-bol)))
- (string-match-p prev-real-line-node-type (or (treesit-node-type
p-node) ""))))))
-
(defvar matlab-ts--indent-debug-rule
'((lambda (node parent bol)
(message "-->N:%S P:%S BOL:%S GP:%S NPS:%S"
@@ -961,9 +934,167 @@ cell or matrix row."
(- first-column array-column))
matlab-ts-mode--array-indent-level)))
+(defvar matlab-ts-mode--error-switch-matcher-pair)
+
+(defun matlab-ts-mode--error-switch-matcher (node parent bol &rest _)
+ "Is NODE PARENT in an ERROR node for a switch statement?
+If so, set `matlab-ts-mode--error-switch-matcher-pair'. BOL,
+beginning-of-line point, is where we start looking for the error node."
+ (when (or (not node)
+ (string= (treesit-node-type parent) "ERROR"))
+ (save-excursion
+ (goto-char bol)
+ (re-search-backward "[^ \t\n\r]" nil t)
+
+ (let ((check-node (treesit-node-at (point))))
+
+ ;; ;; when on "\n" move to prior node
+ ;; (when (and (string= (treesit-node-type check-node) "\n")
+ ;; (re-search-backward "[^ \t\n\r]" nil t))
+ ;; (setq check-node (treesit-node-at (point))))
+
+ (let ((error-node (treesit-node-parent check-node)))
+ (while (and error-node
+ (not (string= (treesit-node-type error-node) "ERROR")))
+ (setq error-node (treesit-node-parent error-node)))
+
+ ;; In an error-node, see if this error is due to an incomplete
switch statement.
+ (when error-node
+ (let ((child-node (treesit-node-child error-node 0)))
+ (when (and child-node
+ (string-match-p (rx bos (or "switch" "case"
"otherwise") eos)
+ (treesit-node-type child-node)))
+ (setq matlab-ts-mode--error-switch-matcher-pair
+ (cons (treesit-node-start child-node)
+ matlab-ts-mode--switch-indent-level))))))))))
+
+(defun matlab-ts-mode--error-switch-anchor (&rest _)
+ "Return the anchor computed by `matlab-ts-mode--error-switch-matcher'."
+ (car matlab-ts-mode--error-switch-matcher-pair))
+
+(defun matlab-ts-mode--error-switch-offset (&rest _)
+ "Return the offset computed by `matlab-ts-mode--error-switch-matcher'."
+ (cdr matlab-ts-mode--error-switch-matcher-pair))
+
+
+(defvar matlab-ts-mode--error-row-matcher-pair)
+
+(defun matlab-ts-mode--error-row-matcher (_node _parent bol &rest _)
+ "Is s point within an ERROR node and can we determine indent?
+If so, set `matlab-ts-mode--error-row-matcher-pair' to the anchor and
+offset we should use and return non-nil. BOL, beginning-of-line point,
+is where we start looking for the error node."
+ ;; 1) Given
+ ;; mat = [ [1, 2]; [3, 4];
+ ;; TAB>
+ ;; we have parse tree
+ ;; (ERROR (identifier) = [
+ ;; (row
+ ;; (matrix [
+ ;; (row (number) , (number))
+ ;; ]))
+ ;; ;
+ ;; (row
+ ;; (matrix [
+ ;; (row (number) , (number))
+ ;; ]))
+ ;; ;)
+ ;;
+ ;; 2) Now add ellipsis continuation:
+ ;; mat = [ [1, 2]; [3, 4]; ...
+ ;; TAB>
+ ;; we'll have parse tree
+ ;; (source_file
+ ;; (ERROR (identifier) = [
+ ;; (row
+ ;; (matrix [
+ ;; (row (number) , (number))
+ ;; ]))
+ ;; ;
+ ;; (row
+ ;; (matrix [
+ ;; (row (number) , (number))
+ ;; ]))
+ ;; ;)
+ ;; (line_continuation))
+ ;; Notice the line_continuation is not under the ERROR node, so we need to
find that,
+ ;; hence below we navigate over line_continuation's.
+ ;;
+ ;; See https://github.com/acristoffers/tree-sitter-matlab/issues/46
+
+ (save-excursion
+ (goto-char bol)
+
+ ;; Move inside the error node if at an error node.
+ (when (string= (treesit-node-type (treesit-node-at (point))) "ERROR")
+ (re-search-backward "[^ \t\n\r]" nil t))
+
+ ;; If on a "[" or "{" move back (we don't want to shift the current line)
+ (when (string-match-p (rx bos (or "[" "{") eos) (treesit-node-type
(treesit-node-at (point))))
+ (re-search-backward "[^ \t\n\r]" nil t))
+
+ ;; Walk over line_continuation, ",", ";" and identify the "check node" we
should be looking
+ ;; at.
+ (let ((check-node (treesit-node-at (point))))
+ (while (string-match-p (rx bos (or "line_continuation" "," ";") eos)
+ (treesit-node-type check-node))
+ (goto-char (treesit-node-start check-node))
+ (if (re-search-backward "[^ \t\n\r]" nil t)
+ (setq check-node (treesit-node-at (point)))
+ ;; at start of buffer
+ (setq check-node nil)))
+
+ (when check-node
+ ;; Look to see if we are under an ERROR node
+ (let ((error-node (treesit-node-parent check-node)))
+ (while (and error-node
+ (not (string= (treesit-node-type error-node) "ERROR")))
+ (setq error-node (treesit-node-parent error-node)))
+
+ ;; In an error-node, see if this error is due to an incomplete cell
or matrix,
+ ;; if so return the start point of the row to anchor against.
+ (when error-node
+ (while (and check-node
+ (not (string-match-p (rx bos (or "row" "[" "{") eos)
+ (treesit-node-type check-node))))
+ (setq check-node (treesit-node-parent check-node)))
+
+ (when check-node
+ (cond
+ ((string-match-p (rx bos (or "[" "{") eos) (treesit-node-type
check-node))
+ (setq matlab-ts-mode--error-row-matcher-pair
+ (cons (treesit-node-start check-node) 2)))
+ ;; Case: looking at row?
+ (t
+ ;; Find first row to anchor against
+ (let ((prev-sibling (treesit-node-prev-sibling check-node)))
+ (while prev-sibling
+ (when (string= (treesit-node-type prev-sibling) "row")
+ (setq check-node prev-sibling))
+ (setq prev-sibling (treesit-node-prev-sibling
prev-sibling))))
+ ;; In an ERROR node of a matrix or cell, return anchor
+ (setq matlab-ts-mode--error-row-matcher-pair
+ (cons (treesit-node-start check-node) 0)))))))))))
+
+(defun matlab-ts-mode--error-row-anchor (&rest _)
+ "Return the anchor computed by `matlab-ts-mode--error-row-matcher'."
+ (car matlab-ts-mode--error-row-matcher-pair))
+
+(defun matlab-ts-mode--error-row-offset (&rest _)
+ "Return the offset computed by `matlab-ts-mode--error-row-matcher'."
+ (cdr matlab-ts-mode--error-row-matcher-pair))
+
(defvar matlab-ts-mode--indent-rules
`((matlab
+ ;; I-Rule: cell/matrix row matcher when in an error node
+ ;; mat0 = [1, 2
+ ;; ^ <-- TAB or RET on prior line goes here
+ ;; See: tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat*.m
+ (,#'matlab-ts-mode--error-row-matcher
+ ,#'matlab-ts-mode--error-row-anchor
+ ,#'matlab-ts-mode--error-row-offset)
+
;; I-Rule: classdef's, function's, or code for a script that is at the
top-level
((parent-is ,(rx bos "source_file" eos)) column-0 0)
@@ -1046,8 +1177,8 @@ cell or matrix row."
eos))
parent ,matlab-ts-mode--indent-level)
- ;; I-Rule: function a<RET>
- ;; end
+ ;; I-Rule: function a = indent_xr_fun()<RET>
+ ;; See: tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun.m
((n-p-gp nil ,(rx bos "\n" eos) ,(rx bos (or "function_definition") eos))
grand-parent ,matlab-ts-mode--indent-level)
@@ -1085,14 +1216,6 @@ cell or matrix row."
;; <TAB> y = 2;
((parent-is ,(rx bos "block" eos)) parent 0)
- ;; I-Rule: "switch var" and we type RET after the var
- (,(matlab-ts-mode--prev-real-line-is (rx bos "\n" eos) (rx bos "switch"
eos))
- ,#'matlab-ts-mode--prev-real-line ,matlab-ts-mode--switch-indent-level)
-
- ;; I-Rule: "function foo()" and we type RET after the ")"
- (,(matlab-ts-mode--prev-real-line-is nil (rx bos "function" eos))
- ,#'matlab-ts-mode--prev-real-line ,matlab-ts-mode--indent-level)
-
;; I-Rule: a = ...
;; <TAB> 1;
((parent-is ,(rx bos "assignment" eos)) parent
,matlab-ts-mode--indent-level)
@@ -1115,6 +1238,11 @@ cell or matrix row."
;; See: tests/test-matlab-ts-mode-indent-files/indent_matrix.m
((parent-is ,(rx bos (or "cell" "matrix") eos)) parent
,#'matlab-ts-mode--row-indent-level)
+ ;; I-Rule: cell1 = { ...
+ ;; See: ./test-matlab-ts-mode-indent-xr-files/indent_xr_cell1.m
+ ((n-p-gp nil ,(rx bos "line_continuation" eos) ,(rx bos (or "cell"
"matrix") eos))
+ grand-parent ,#'matlab-ts-mode--row-indent-level)
+
;; I-Rule: function [ ... | function name ( ...
;; <TAB> a, ... % comment | a, ... %
comment
((parent-is ,(rx bos (or "multioutput_variable" "function_arguments")
eos)) parent 1)
@@ -1145,13 +1273,6 @@ cell or matrix row."
(string= (treesit-node-type parent) "\n")))
grand-parent 0)
- ;; I-Rule: In an empty line, string, etc. just maintain indent
- ;; switch in
- ;; case 10
- ;; disp('11');
- ;; <TAB>
- (no-node ,#'matlab-ts-mode--prev-real-line 0)
-
;; I-Rule: comments in classdef's
((parent-is ,(rx bos "class_definition" eos)) parent
,matlab-ts-mode--indent-level)
@@ -1177,6 +1298,15 @@ cell or matrix row."
;; parent ,matlab-ts-mode--indent-level)
parent ,#'matlab-ts-mode--indent-continuation-level)
+ ;; I-Rule: In an empty line, string, etc. just maintain indent
+ ;; switch fcn1(a)
+ ;; ^ <== TAB or RET on prior line goes
here
+ ;; Parent node could be "source_file", so must be before
+ ;; ((parent-is ,(rx bos "source_file" eos)) column-0 0)
+ (,#'matlab-ts-mode--error-switch-matcher
+ ,#'matlab-ts-mode--error-switch-anchor
+ ,#'matlab-ts-mode--error-switch-offset)
+
;; I-Rule: handle syntax errors by not indenting
;; See: tests/test-matlab-ts-mode-indent-files/indent_nested_error.m
((lambda (node &rest _)
@@ -1348,8 +1478,8 @@ cell or matrix row."
"methods"
"events"
"enumeration")))
-
- (text ,(rx bos (or "comment" "string") eos))
+ ;; TODO is "line_continuation" correct here - add test
+ (text ,(rx bos (or "comment" "string" "line_continuation") eos))
))
"Tree-sitter things for movement.")
@@ -1779,8 +1909,8 @@ is t, add the following to an Init File (e.g.
`user-init-file' or
;; Indent.
;; See: ./tests/test-matlab-ts-mode-indent.el
- (matlab-ts-mode--set-function-indent-level)
- (setq-local indent-tabs-mode nil) ;; for consistency between Unix and
Windows we don't use TABs.
+ (matlab-ts-mode--set-function-indent-level) ;; Set function indent level
on file load
+ (setq-local indent-tabs-mode nil) ;; For consistency between Unix and
Windows we don't use TABs.
(setq-local treesit-simple-indent-rules
(if treesit--indent-verbose ;; add debugging print as first
rule?
(list (append `,(list (caar matlab-ts-mode--indent-rules))
@@ -1838,22 +1968,9 @@ is t, add the following to an Init File (e.g.
`user-init-file' or
;; TODO double check t-utils.el help, extract the help and put in treesit
how to
;;
;; TODO double check indent rules to see if they can be simplified
- ;; TODO update --indent-rules to have See: test file comments.
- ;;
- ;; TODO indent
- ;; mat = [1, 2
- ;; ^ <== RET on previous line or TAB should be
here
+ ;; TODO update --indent-rules to have "See: test file" comments.
;;
;; TODO indent
- ;; c = { ...
- ;; {'one' <== TAB to here (first RET or TAB, then
type)
- ;;
- ;; TODO indent (good add test?):
- ;; c = { ...
- ;; {'one', 'two'}, ...
- ;; {'three', 'four'}, ...
- ;; }
- ;; TODO indent
;; function a=foo
;; a = ...
;; ^ <== RET on previous line or TAB should be
here
@@ -1884,6 +2001,19 @@ is t, add the following to an Init File (e.g.
`user-init-file' or
;; s = sprintf("see %d:%d", 1, 2)
;; ^^ ^^ <== font-lock
formatting_sequence
;;
+ ;; TODO Mismatched parentheses
+ ;; Start with:
+ ;; Line1: mat = [ [1, 2]; [3, 4];
+ ;; Line2:
+ ;; then type a ']' on the 2nd line, in echo area, see: Mismatched
parentheses
+ ;;
+ ;; TODO improve formatting t-utils-xr print's, e.g. improve:
+ ;; standard-output:
+ ;; "function a = indent_xr_fun()
+ ;; a = 1;
+ ;; end
+ ;; "
+
(treesit-major-mode-setup)
;; Correct forward-sexp setup created by `treesit-major-mode' so that in
comments we do normal
diff --git a/tests/t-utils.el b/tests/t-utils.el
index 7f59fc3406..09fb1e2dc4 100644
--- a/tests/t-utils.el
+++ b/tests/t-utils.el
@@ -980,7 +980,8 @@ See `t-utils-test-indent' for LINE-MANIPULATOR."
;; result is nil or an error message list of strings
error-msg))))
-(defun t-utils-test-indent (test-name lang-files &optional line-manipulator
error-nodes-regexp)
+(defun t-utils-test-indent (test-name lang-files
+ &optional indent-checker
line-manipulator error-nodes-regexp)
"Test indent on each file in LANG-FILES list.
Compare indent of each NAME.LANG in LANG-FILES against NAME_expected.LANG.
TEST-NAME is used in messages.
@@ -999,6 +1000,9 @@ Two methods are used to indent each file in LANG-FILES,
1. (indent-region (point-min) (point-man))
+ If optional INDENT-CHECKER function is provided, that is called with
+ the temporary buffer in context after the `indent-region'.
+
2. Indent via typing simulation. If lang-file has no error nodes in the
parse tree, indent is simulated by \"typing lang-file\" to exercise
TAB and RET, see `t-utils--test-indent-typing'. In tree-sitter
@@ -1086,7 +1090,12 @@ To debug a specific indent test file
(message "START: %s <indent-region> %s" test-name lang-file)
(setq lang-file-major-mode major-mode)
+
(indent-region (point-min) (point-max))
+
+ (when indent-checker
+ (funcall indent-checker))
+
(t-utils--trim)
(let ((got (buffer-substring (point-min) (point-max)))
(got-file (concat expected-file "~")))
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_cell1.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_cell1.m
new file mode 100644
index 0000000000..3c9aff68c1
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_cell1.m
@@ -0,0 +1,2 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_cell1_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_cell1_expected.org
new file mode 100644
index 0000000000..19cb7cded6
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_cell1_expected.org
@@ -0,0 +1,272 @@
+#+startup: showall
+
+* Executing commands from indent_xr_cell1.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 300
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m"
(insert "{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m"
(insert "{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell")
(print (buffer-substring-no-properties (point) (point-max))))
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 301
+ : 3:0:
+ : ^
+ No buffer modifications
+
+- Invoking : (insert "cell1 = { ...")
+ Start point : 301
+ Moved to point: 314
+ : 3:13: cell1 = { ...
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,2 +1,3 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
++cell1 = { ...
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 314
+ No point movement
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 314
+ Moved to point: 325
+ : 4:10:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,3 +1,4 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+-cell1 = { ...
+\ No newline at end of file
++cell1 = { ...
++
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : (insert "{'one', ...")
+ Start point : 325
+ Moved to point: 336
+ : 4:21: {'one', ...
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,4 +1,4 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+ cell1 = { ...
+-
+\ No newline at end of file
++ {'one', ...
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 336
+ Moved to point: 348
+ : 5:11:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,4 +1,5 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+ cell1 = { ...
+- {'one', ...
+\ No newline at end of file
++ {'one', ...
++
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : (insert "'two'}, ...")
+ Start point : 348
+ Moved to point: 359
+ : 5:22: 'two'}, ...
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,4 +2,4 @@
+ % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+ cell1 = { ...
+ {'one', ...
+-
+\ No newline at end of file
++ 'two'}, ...
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 359
+ Moved to point: 370
+ : 6:10:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,4 +2,5 @@
+ % (t-utils-xr "C-a" "C-n" (insert "cell1 = { ...") "C-e" "C-m" (insert
"{'one', ...") "C-m" (insert "'two'}, ...") "C-m" (insert "...") "C-m" (insert
"{'three'}") "C-m" (insert "};") "C-m" (re-search-backward "^cell") (print
(buffer-substring-no-properties (point) (point-max))))
+ cell1 = { ...
+ {'one', ...
+- 'two'}, ...
+\ No newline at end of file
++ 'two'}, ...
++
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : (insert "...")
+ Start point : 370
+ Moved to point: 373
+ : 6:13: ...
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,4 +3,4 @@
+ cell1 = { ...
+ {'one', ...
+ 'two'}, ...
+-
+\ No newline at end of file
++ ...
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 373
+ Moved to point: 384
+ : 7:10:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,4 +3,5 @@
+ cell1 = { ...
+ {'one', ...
+ 'two'}, ...
+- ...
+\ No newline at end of file
++ ...
++
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : (insert "{'three'}")
+ Start point : 384
+ Moved to point: 393
+ : 7:19: {'three'}
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -4,4 +4,4 @@
+ {'one', ...
+ 'two'}, ...
+ ...
+-
+\ No newline at end of file
++ {'three'}
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 393
+ Moved to point: 404
+ : 8:10:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -4,4 +4,5 @@
+ {'one', ...
+ 'two'}, ...
+ ...
+- {'three'}
+\ No newline at end of file
++ {'three'}
++
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : (insert "};")
+ Start point : 404
+ Moved to point: 406
+ : 8:12: };
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -5,4 +5,4 @@
+ 'two'}, ...
+ ...
+ {'three'}
+-
+\ No newline at end of file
++ };
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 406
+ Moved to point: 405
+ : 9:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -5,4 +5,4 @@
+ 'two'}, ...
+ ...
+ {'three'}
+- };
+\ No newline at end of file
++ };
+ #+end_src diff
+
+- Invoking : (re-search-backward "^cell")
+ Start point : 405
+ Moved to point: 301
+ : 3:0: cell1 = { ...
+ : ^
+ No buffer modifications
+
+- Invoking : (print (buffer-substring-no-properties (point) (point-max)))
+ Start point : 301
+ No point movement
+ standard-output:
+ "cell1 = { ...
+ {'one', ...
+ 'two'}, ...
+ ...
+ {'three'}
+ };
+ "
+ No buffer modifications
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun.m
new file mode 100644
index 0000000000..4dcd0b5684
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun.m
@@ -0,0 +1,2 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun_expected.org
new file mode 100644
index 0000000000..8f635e30a8
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_fun_expected.org
@@ -0,0 +1,139 @@
+#+startup: showall
+
+* Executing commands from indent_xr_fun.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 227
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()")
"C-m" (insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun")
(print (buffer-substring-no-properties (point) (point-max))))
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 228
+ : 3:0:
+ : ^
+ No buffer modifications
+
+- Invoking : (insert "function a = indent_xr_fun()")
+ Start point : 228
+ Moved to point: 256
+ : 3:28: function a = indent_xr_fun()
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,2 +1,3 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
++function a = indent_xr_fun()
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 256
+ Moved to point: 257
+ : 4:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,3 +1,3 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
+-function a = indent_xr_fun()
+\ No newline at end of file
++function a = indent_xr_fun()
+ #+end_src diff
+
+- Invoking : (insert "a = 1;")
+ Start point : 257
+ Moved to point: 263
+ : 4:6: a = 1;
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,3 +1,4 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
+ function a = indent_xr_fun()
++a = 1;
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 263
+ Moved to point: 268
+ : 5:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,4 +1,4 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
+ function a = indent_xr_fun()
+-a = 1;
+\ No newline at end of file
++ a = 1;
+ #+end_src diff
+
+- Invoking : (insert "end")
+ Start point : 268
+ Moved to point: 271
+ : 5:3: end
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,3 +2,4 @@
+ % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
+ function a = indent_xr_fun()
+ a = 1;
++end
+\ No newline at end of file
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 271
+ Moved to point: 272
+ : 6:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,4 +2,4 @@
+ % (t-utils-xr "C-a" "C-n" (insert "function a = indent_xr_fun()") "C-m"
(insert "a = 1;") "C-m" (insert "end") "C-m" (re-search-backward "^fun") (print
(buffer-substring-no-properties (point) (point-max))))
+ function a = indent_xr_fun()
+ a = 1;
+-end
+\ No newline at end of file
++end
+ #+end_src diff
+
+- Invoking : (re-search-backward "^fun")
+ Start point : 272
+ Moved to point: 228
+ : 3:0: function a = indent_xr_fun()
+ : ^
+ No buffer modifications
+
+- Invoking : (print (buffer-substring-no-properties (point) (point-max)))
+ Start point : 228
+ No point movement
+ standard-output:
+ "function a = indent_xr_fun()
+ a = 1;
+ end
+ "
+ No buffer modifications
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat0.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat0.m
new file mode 100644
index 0000000000..c7e7e1045d
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat0.m
@@ -0,0 +1,6 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "3, 4]") "C-m")
+mat0 = [1, 2
+
+
+
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat0_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat0_expected.org
new file mode 100644
index 0000000000..14947d9fae
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat0_expected.org
@@ -0,0 +1,81 @@
+#+startup: showall
+
+* Executing commands from indent_xr_mat0.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "3, 4]") "C-m")
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 82
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "3, 4]") "C-m")
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 83
+ : 3:0: mat0 = [1, 2
+ : ^
+ No buffer modifications
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 83
+ Moved to point: 95
+ : 3:12: mat0 = [1, 2
+ : ^
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 95
+ Moved to point: 104
+ : 4:8:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,6 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "3, 4]") "C-m")
+ mat0 = [1, 2
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "3, 4]")
+ Start point : 104
+ Moved to point: 109
+ : 4:13: 3, 4]
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,7 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "3, 4]") "C-m")
+ mat0 = [1, 2
+-
++ 3, 4]
+
+
+
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 109
+ Moved to point: 110
+ : 5:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -5,3 +5,4 @@
+
+
+
++
+ #+end_src diff
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat1.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat1.m
new file mode 100644
index 0000000000..ce724a2c82
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat1.m
@@ -0,0 +1,8 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" "C-n" "C-i" "C-n" "C-i" "C-e" "C-m" (insert "];\n"))
+mat1 = [ [1, 2], [3, 4], ...
+ ...
+ ...
+
+
+
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat1_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat1_expected.org
new file mode 100644
index 0000000000..14113a7171
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat1_expected.org
@@ -0,0 +1,119 @@
+#+startup: showall
+
+* Executing commands from indent_xr_mat1.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" "C-n" "C-i" "C-n" "C-i" "C-e" "C-m" (insert "];\n"))
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 99
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" "C-n" "C-i" "C-n" "C-i" "C-e" "C-m" (insert
"];\n"))
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 100
+ : 3:0: mat1 = [ [1, 2], [3, 4], ...
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 100
+ Moved to point: 129
+ : 4:0: ...
+ : ^
+ No buffer modifications
+
+- Invoking : "C-i" = indent-for-tab-command
+ Start point : 129
+ Moved to point: 138
+ : 4:9: ...
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,7 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-n" "C-i" "C-n" "C-i" "C-e" "C-m" (insert "];\n"))
+ mat1 = [ [1, 2], [3, 4], ...
+- ...
++ ...
+ ...
+
+
+ #+end_src diff
+
+- Invoking : "C-n" = next-line
+ Start point : 138
+ Moved to point: 146
+ : 5:4: ...
+ : ^
+ No buffer modifications
+
+- Invoking : "C-i" = indent-for-tab-command
+ Start point : 146
+ Moved to point: 154
+ : 5:12: ...
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,7 +2,7 @@
+ % (t-utils-xr "C-a" "C-n" "C-n" "C-i" "C-n" "C-i" "C-e" "C-m" (insert "];\n"))
+ mat1 = [ [1, 2], [3, 4], ...
+ ...
+- ...
++ ...
+
+
+
+ #+end_src diff
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 154
+ No point movement
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 154
+ Moved to point: 164
+ : 6:9:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,6 +3,7 @@
+ mat1 = [ [1, 2], [3, 4], ...
+ ...
+ ...
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "];
+")
+ Start point : 164
+ Moved to point: 167
+ : 7:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,7 +3,8 @@
+ mat1 = [ [1, 2], [3, 4], ...
+ ...
+ ...
+-
++ ];
++
+
+
+
+ #+end_src diff
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat2.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat2.m
new file mode 100644
index 0000000000..2be12925e5
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat2.m
@@ -0,0 +1,7 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[5, 6]];"))
+mat2 = [ [1, 2]; [3, 4];
+
+
+
+
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat2_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat2_expected.org
new file mode 100644
index 0000000000..bae21b672a
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat2_expected.org
@@ -0,0 +1,65 @@
+#+startup: showall
+
+* Executing commands from indent_xr_mat2.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[5, 6]];"))
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 79
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[5, 6]];"))
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 80
+ : 3:0: mat2 = [ [1, 2]; [3, 4];
+ : ^
+ No buffer modifications
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 80
+ Moved to point: 104
+ : 3:24: mat2 = [ [1, 2]; [3, 4];
+ : ^
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 104
+ Moved to point: 114
+ : 4:9:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,6 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[5, 6]];"))
+ mat2 = [ [1, 2]; [3, 4];
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "[5, 6]];")
+ Start point : 114
+ Moved to point: 122
+ : 4:17: [5, 6]];
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,7 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[5, 6]];"))
+ mat2 = [ [1, 2]; [3, 4];
+-
++ [5, 6]];
+
+
+
+ #+end_src diff
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat3.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat3.m
new file mode 100644
index 0000000000..74e0176422
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat3.m
@@ -0,0 +1,6 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[3, 4]];\n"))
+mat3 = [[1, 2]
+
+
+
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat3_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat3_expected.org
new file mode 100644
index 0000000000..00dd5075d2
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat3_expected.org
@@ -0,0 +1,67 @@
+#+startup: showall
+
+* Executing commands from indent_xr_mat3.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[3, 4]];\n"))
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 81
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[3, 4]];\n"))
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 82
+ : 3:0: mat3 = [[1, 2]
+ : ^
+ No buffer modifications
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 82
+ Moved to point: 96
+ : 3:14: mat3 = [[1, 2]
+ : ^
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 96
+ Moved to point: 105
+ : 4:8:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,6 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[3, 4]];\n"))
+ mat3 = [[1, 2]
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "[3, 4]];
+")
+ Start point : 105
+ Moved to point: 114
+ : 5:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,7 +1,8 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[3, 4]];\n"))
+ mat3 = [[1, 2]
+-
++ [3, 4]];
++
+
+
+
+ #+end_src diff
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat4.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat4.m
new file mode 100644
index 0000000000..3e1e7c93d8
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat4.m
@@ -0,0 +1,14 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i" (insert "[3,
4];") "C-m" (insert "];") "C-m")
+mat4 = [
+
+
+
+
+
+
+
+
+
+
+
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat4_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat4_expected.org
new file mode 100644
index 0000000000..2889ab5593
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_mat4_expected.org
@@ -0,0 +1,167 @@
+#+startup: showall
+
+* Executing commands from indent_xr_mat4.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i" (insert "[3,
4];") "C-m" (insert "];") "C-m")
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 131
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i"
(insert "[3, 4];") "C-m" (insert "];") "C-m")
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 132
+ : 3:0: mat4 = [
+ : ^
+ No buffer modifications
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 132
+ Moved to point: 140
+ : 3:8: mat4 = [
+ : ^
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 140
+ Moved to point: 150
+ : 4:9:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,6 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i" (insert "[3,
4];") "C-m" (insert "];") "C-m")
+ mat4 = [
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "[1, 2];
+")
+ Start point : 150
+ Moved to point: 158
+ : 5:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,7 +1,8 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i" (insert "[3,
4];") "C-m" (insert "];") "C-m")
+ mat4 = [
+-
++ [1, 2];
++
+
+
+
+ #+end_src diff
+
+- Invoking : "C-i" = indent-for-tab-command
+ Start point : 158
+ Moved to point: 167
+ : 5:9:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,7 +2,7 @@
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i" (insert "[3,
4];") "C-m" (insert "];") "C-m")
+ mat4 = [
+ [1, 2];
+-
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "[3, 4];")
+ Start point : 167
+ Moved to point: 174
+ : 5:16: [3, 4];
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,7 +2,7 @@
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "[1, 2];\n") "C-i" (insert "[3,
4];") "C-m" (insert "];") "C-m")
+ mat4 = [
+ [1, 2];
+-
++ [3, 4];
+
+
+
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 174
+ Moved to point: 184
+ : 6:9:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,6 +3,7 @@
+ mat4 = [
+ [1, 2];
+ [3, 4];
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "];")
+ Start point : 184
+ Moved to point: 186
+ : 6:11: ];
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,7 +3,7 @@
+ mat4 = [
+ [1, 2];
+ [3, 4];
+-
++ ];
+
+
+
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 186
+ Moved to point: 185
+ : 7:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,7 +3,8 @@
+ mat4 = [
+ [1, 2];
+ [3, 4];
+- ];
++ ];
++
+
+
+
+ #+end_src diff
diff --git a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_switch.m
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_switch.m
new file mode 100644
index 0000000000..c4b0a5a8a1
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_switch.m
@@ -0,0 +1,16 @@
+% -*- matlab-ts -*-
+% (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+switch fcn1(a)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git
a/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_switch_expected.org
b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_switch_expected.org
new file mode 100644
index 0000000000..fc310ced69
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr-files/indent_xr_switch_expected.org
@@ -0,0 +1,162 @@
+#+startup: showall
+
+* Executing commands from indent_xr_switch.m:2:2:
+
+ (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+
+- Invoking : "C-a" = move-beginning-of-line
+ Start point : 132
+ Moved to point: 21
+ : 2:0: % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+ : ^
+ No buffer modifications
+
+- Invoking : "C-n" = next-line
+ Start point : 21
+ Moved to point: 133
+ : 3:0: switch fcn1(a)
+ : ^
+ No buffer modifications
+
+- Invoking : "C-e" = move-end-of-line
+ Start point : 133
+ Moved to point: 147
+ : 3:14: switch fcn1(a)
+ : ^
+ No buffer modifications
+
+- Invoking : "C-m" = newline
+ Start point : 147
+ Moved to point: 150
+ : 4:2:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,6 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+ switch fcn1(a)
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "case 1")
+ Start point : 150
+ Moved to point: 156
+ : 4:8: case 1
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -1,7 +1,7 @@
+ % -*- matlab-ts -*-
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+ switch fcn1(a)
+-
++ case 1
+
+
+
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 156
+ Moved to point: 161
+ : 5:4:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,6 +2,7 @@
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+ switch fcn1(a)
+ case 1
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "disp('1');")
+ Start point : 161
+ Moved to point: 171
+ : 5:14: disp('1');
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -2,7 +2,7 @@
+ % (t-utils-xr "C-a" "C-n" "C-e" "C-m" (insert "case 1") "C-m" (insert
"disp('1');") "C-m" (insert "end") "C-m")
+ switch fcn1(a)
+ case 1
+-
++ disp('1');
+
+
+
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 171
+ Moved to point: 172
+ : 6:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -5,6 +5,7 @@
+ disp('1');
+
+
++
+
+
+
+ #+end_src diff
+
+- Invoking : (insert "end")
+ Start point : 172
+ Moved to point: 175
+ : 6:3: end
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -3,7 +3,7 @@
+ switch fcn1(a)
+ case 1
+ disp('1');
+-
++end
+
+
+
+ #+end_src diff
+
+- Invoking : "C-m" = newline
+ Start point : 175
+ Moved to point: 176
+ : 7:0:
+ : ^
+ Buffer modified:
+ #+begin_src diff
+--- start_contents
++++ end_contents
+@@ -6,6 +6,7 @@
+ end
+
+
++
+
+
+
+ #+end_src diff
diff --git a/tests/test-matlab-ts-mode-indent-xr.el
b/tests/test-matlab-ts-mode-indent-xr.el
new file mode 100644
index 0000000000..a5074fd796
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-xr.el
@@ -0,0 +1,67 @@
+;;; test-matlab-ts-mode-indent-xr.el --- -*- lexical-binding: t -*-
+;;
+;; Copyright 2025 Free Software Foundation, Inc.
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;;
+
+;;; Commentary:
+;;
+;; Run indent tests using `t-utils-xr' in
+;; ./test-matlab-ts-mode-indent-xr-files/NAME.m
+;; comparing against
+;; ./test-matlab-ts-mode-indent-xr-files/NAME_expected.org
+;;
+
+;;; Code:
+
+(require 't-utils)
+(require 'matlab-ts-mode)
+
+(defvar test-matlab-ts-mode-indent-xr--file nil)
+
+(defun test-matlab-ts-mode-indent-xr--file (m-file)
+ "Test an individual M-FILE.
+This is provided for debugging.
+ M-: (test-matlab-ts-mode-indent-xr--file
+ \"test-matlab-ts-mode-indent-xr-files/M-FILE\")"
+ (let ((test-matlab-ts-mode-indent-xr--file m-file))
+ (ert-run-tests-interactively "test-matlab-ts-mode-indent-xr")))
+
+(ert-deftest test-matlab-ts-mode-indent-xr ()
+ "Test indent using ./test-matlab-ts-mode-indent-xr-files/NAME.m.
+Using ./test-matlab-ts-mode-indent-xr-files/NAME.m, compare typing
+commands via `t-utils-xr' Lisp commans in the *.m files and compare
+agains ./test-matlab-ts-mode-indent-xr-files/NAME_expected.org. This
+loops on all ./test-matlab-ts-mode-indent-xr-files/NAME.m files.
+
+To add a test, create
+ ./test-matlab-ts-mode-indent-xr-files/NAME.m
+and run this function. The baseline is saved for you as
+ ./test-matlab-ts-mode-indent-xr-files/NAME_expected.org~
+after validating it, rename it to
+ ./test-matlab-ts-mode-indent-xr-files/NAME_expected.org"
+
+ (let* ((test-name "test-matlab-ts-mode-indent-xr")
+ (m-files (t-utils-get-files
+ test-name
+ (rx ".m" eos)
+ nil
+ test-matlab-ts-mode-indent-xr--file)))
+ (t-utils-error-if-no-treesit-for 'matlab test-name)
+ (t-utils-test-xr test-name m-files)))
+
+(provide 'test-matlab-ts-mode-indent-xr)
+;;; test-matlab-ts-mode-indent-xr.el ends here
diff --git a/tests/test-matlab-ts-mode-indent.el
b/tests/test-matlab-ts-mode-indent.el
index bad995bbf9..4708fff80e 100644
--- a/tests/test-matlab-ts-mode-indent.el
+++ b/tests/test-matlab-ts-mode-indent.el
@@ -30,6 +30,8 @@
(require 't-utils)
(require 'matlab-ts-mode)
+(defvar test-matlab-ts-mode-indent--current-indent-level nil)
+
(defvar test-matlab-ts-mode-indent--file nil)
(defun test-matlab-ts-mode-indent--file (m-file)
@@ -59,7 +61,13 @@ after validating it, rename it to
(rx ".m" eos)
(rx "_expected.m" eos) ;; skip our *_expected.m baselines
test-matlab-ts-mode-indent--file))
+ (indent-checker (lambda ()
+ (setq
test-matlab-ts-mode-indent--current-indent-level
+ matlab-ts-mode--function-indent-level)))
(line-manipulator (lambda ()
+ ;; Set the indent level to what the m-file has
+ (setq matlab-ts-mode--function-indent-level
+
test-matlab-ts-mode-indent--current-indent-level)
;; Workaround
;;
https://github.com/acristoffers/tree-sitter-matlab/issues/32
(goto-char (point-min))
@@ -70,7 +78,7 @@ after validating it, rename it to
(insert " ")))
(forward-line)))))
(t-utils-error-if-no-treesit-for 'matlab test-name)
- (t-utils-test-indent test-name m-files line-manipulator)))
+ (t-utils-test-indent test-name m-files indent-checker line-manipulator)))
(provide 'test-matlab-ts-mode-indent)
;;; test-matlab-ts-mode-indent.el ends here