branch: externals/matlab-mode
commit 340fcd85920b9abcd692f84de31d4aa4e6d4d150
Author: John Ciolfi <[email protected]>
Commit: John Ciolfi <[email protected]>
matlab-ts-mode.el: on load add a final newline if needed to non-empty *.m
files
---
matlab-ts-mode.el | 33 ++++++++++++++++++----
.../parser_no_final_newline.m | 4 +++
.../parser_no_final_newline_expected.txt | 11 ++++++++
tests/test-matlab-ts-mode-parser.el | 7 +++++
4 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/matlab-ts-mode.el b/matlab-ts-mode.el
index 6aa7150085..2ab2c27ae4 100644
--- a/matlab-ts-mode.el
+++ b/matlab-ts-mode.el
@@ -258,7 +258,7 @@ content can crash Emacs via the matlab tree-sitter parser."
(goto-char bad-char-point)
(user-error
"Not entering matlab-ts-mode due to non-printable utf8 character \"%c\"
at point %d"
- (char-before) bad-char-point ))))
+ (char-before) bad-char-point))))
;;; Syntax table
@@ -3560,6 +3560,28 @@ THERE-END MISMATCH) or nil."
unread-command-events))
))))
+(defun matlab-ts-mode--add-final-newline (&optional restore-readonly)
+ "Add a final newline to non-empty buffer to make tree-sitter happy.
+If a final new-line is missing, matlab tree-sitter can generate a parse
+error because it looks for the newline to finish statements.
+
+If optional RESTORE-READONLY is non-nil, then if the buffer is read-only
+upon calling this function, it will be restored back to read-only if a
+final newline was inserted."
+ (save-excursion
+ (goto-char (point-max))
+ (when (and (< (point-min) (point-max))
+ (not (= (char-before) ?\n)))
+ (let ((is-read-only buffer-read-only))
+ (when is-read-only
+ (read-only-mode 0))
+ (insert "\n")
+ (when (and restore-readonly
+ is-read-only)
+ (set-buffer-modified-p nil))
+ (when is-read-only
+ (read-only-mode 1))))))
+
(defun matlab-ts-mode--post-insert-callback ()
"Callback attached to `post-self-insert-hook'.
@@ -3575,11 +3597,7 @@ This callback also implements
`matlab-ts-mode-electric-ends'."
(when (eq major-mode 'matlab-ts-mode)
(let ((ret-typed (eq last-command-event ?\n)))
- ;; Add final newline to the buffer?
- (save-excursion
- (goto-char (point-max))
- (when (not (= (char-before) ?\n))
- (insert "\n")))
+ (matlab-ts-mode--add-final-newline)
;; Add "end" (for `matlab-ts-mode-electric-ends')
(when (and ret-typed
@@ -4062,6 +4080,9 @@ so configuration variables of that mode, do not affect
this mode.
(matlab-ts-mode--check-file-encoding)
(when (treesit-ready-p 'matlab)
+
+ (matlab-ts-mode--add-final-newline 'restore-readonly)
+
(treesit-parser-create 'matlab)
;; Syntax table - think of this as a "language character descriptor". It
tells us what
diff --git a/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline.m
b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline.m
new file mode 100644
index 0000000000..bc28fd1bbf
--- /dev/null
+++ b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline.m
@@ -0,0 +1,4 @@
+% -*- matlab-ts -*-
+if a
+ disp('b')
+end
\ No newline at end of file
diff --git
a/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline_expected.txt
b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline_expected.txt
new file mode 100644
index 0000000000..877dcb3517
--- /dev/null
+++
b/tests/test-matlab-ts-mode-parser-files/parser_no_final_newline_expected.txt
@@ -0,0 +1,11 @@
+# -*- t-utils-ts-parse-tree -*-
+(source_file (comment[1,20]@{% -*- matlab-ts -*-}@)
+ (if_statement if[21,23] condition: (identifier[24,25]@{a}@)
+ (block
+ (function_call name: (identifier[30,34]@{disp}@) ([34,35]
+ (arguments
+ argument: (string '[35,36] (string_content[36,37]@{b}@) '[37,38]))
+ )[38,39])
+ \n[39,40])
+ end[40,43])
+ \n[43,44])
diff --git a/tests/test-matlab-ts-mode-parser.el
b/tests/test-matlab-ts-mode-parser.el
index 09b6d614c8..763313b3de 100644
--- a/tests/test-matlab-ts-mode-parser.el
+++ b/tests/test-matlab-ts-mode-parser.el
@@ -60,6 +60,13 @@ To understand the format of NAME_expected.txt files, see
(should (equal (test-matlab-ts-mode-parser--all-files) ""))
+ ;; Validate following file does not have a final newline. matlab tree-sitter
requires a final
+ ;; newline for a valid parse because it uses newlines to identify the end of
statements.
+ (with-temp-buffer
+ (insert-file-contents-literally
"test-matlab-ts-mode-parser-files/parser_no_final_newline.m")
+ (goto-char (point-max))
+ (should (equal (= (char-before) ?\n) nil)))
+
(let* ((test-name "test-matlab-ts-mode-parser")
(m-files (t-utils-get-files test-name
:recursively t