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

    matlab-ts-mode.el: indent level for end-less functions is 0
---
 contributing/treesit-mode-how-to.org               | 40 ++++++++++++
 matlab-ts-mode.el                                  | 75 ++++++++++++++++++++--
 .../indent_end_less_function.m                     | 15 +++++
 .../indent_end_less_function_expected.m            | 15 +++++
 4 files changed, 140 insertions(+), 5 deletions(-)

diff --git a/contributing/treesit-mode-how-to.org 
b/contributing/treesit-mode-how-to.org
index 64cf9c125c..9800eef50a 100644
--- a/contributing/treesit-mode-how-to.org
+++ b/contributing/treesit-mode-how-to.org
@@ -223,6 +223,8 @@ You should now be able to use:
 
 * Font-lock
 
+TODO - add FIXME, XXX, and TODO marker coloring.
+
 Queries are needed to identify syntax tree nodes to semantically color 
language elements
 (font-lock). See 
[[https://www.gnu.org/software/emacs/manual/html_node/elisp/Pattern-Matching.html][Emacs
 manual - Pattern Matching Tree-sitter Nodes]]. You can use =M-x
 treesit-explore-mode= to see the nodes of the syntax tree.
@@ -1593,3 +1595,41 @@ well worth writing a tree-sitter mode.
 
   TODO verify
 
+* new matlab-ts-mode
+
+  1. Improved font-lock (semantic coloring) performance, making editing even 
more smooth.
+
+  2. More accurate fontification, we now identify language elements accurately 
and use
+     more faces to color them.
+
+  3. Fixes edge-case fontification issues when compared with matlab-mode
+
+     Create issue for this:
+       #+begin_src matlab-ts
+       x = [1 2; 3 4];
+       y = x''               % this is valid double transpose where 
matlab-mode gets it wrong
+       #+end_src
+
+     Function identification, see 
https://github.com/mathworks/Emacs-MATLAB-Mode/issues/48
+
+  4. In comments, we now highlight =FIXME=, =TODO=, and =XXX= markers.
+
+  5. Simplifies the semantics for indent. The indent rules are:
+
+     - TODO
+
+  6. Improved indent performance, making editing even more smooth.
+
+  7. Fixes various edge-case indent issues, some are
+
+     - Auto-indentation of end, see 
https://github.com/mathworks/Emacs-MATLAB-Mode/issues/33
+
+  8. There's no longer prompting if you want functions to have end's. This is 
now computed
+     automatically
+
+  9. Improved fill-paragraph, M-q, which will now fill comments and when not 
in a comment, indent
+     the current function or statement.
+
+  10. Accurate type of m-file detection, which improves 
matlab-sections-minor-mode.
+
+      TODO
diff --git a/matlab-ts-mode.el b/matlab-ts-mode.el
index dd697b8adc..44c1b98d6e 100644
--- a/matlab-ts-mode.el
+++ b/matlab-ts-mode.el
@@ -347,6 +347,8 @@ START and END specify the region to be fontified."
     (goto-char start)
     (let ((case-fold-search nil))
       (while (< (point) end)
+        ;; Note, the markers below have spaces in them so we don't find them 
when typing C-s
+        ;; while editing this file.
         (if (re-search-forward (rx word-start (group (or (seq "FIX" "ME")
                                                          (seq "X" "XX")
                                                          (seq "TO" "DO")))
@@ -481,6 +483,63 @@ START and END specify the region to be fontified."
 (defvar matlab-ts-mode--array-indent-level 2
   "Indentation level for elements in an array.")
 
+;; `matlab-ts-mode--function-indent-level'
+;;
+;; It is recommended that all function statemements have terminating end 
statements.  In some cases
+;; for compatibilty MATLAB doesn't require a function end statement.  When 
functions do not have an
+;; end, we don't indent the body of the function per older MATLAB coding 
standard.  Example:
+;;
+;;     function a = fcn1    |    function a = fcn2
+;;     a = 1;               |        a = 1;
+;;                          |    end
+;;
+;; If a *.m file contains functions, and one of the functions is terminated 
with end, then every
+;; function in the file must be terminated with end.  If a *.m file contains a 
function with one or
+;; more nested functions, then every function in the file must be terminated 
with end.  If a script
+;; contains one or more local functions, then every function in the file must 
be terminated with
+;; end.
+;;
+;; When we enter `matlab-ts-mode', we examine the content and set the state of 
this variable.  If
+;; matlab-ts--function-indent-level is nil, while editing, if functions become 
terminated with
+;; ends, we set this to t.  We never go from t to nil because it's easy to get 
in a temporary nil
+;; state during edits and we don't want to cause unexpected indentation 
behavior.")
+
+(defvar-local matlab-ts-mode--function-indent-level 'unset
+  "Function indent level is 0 or `matlab-ts-mode--indent-level'.")
+
+(defun matlab-ts-mode--set-function-indent-level (&optional _node parent _bol 
&rest _)
+  "Setup the function indent level for end vs end-less functions.
+For optional _NODE, PARENT, and _BOL see `treesit-simple-indent-rules'."
+
+  ;; - When matlab-ts-mode--function-indent-level is 'unset we set this to
+  ;;     0 or matlab-ts-mode--indent-level
+  ;;   based on the buffer content.
+  ;; - 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"))
+                  parent
+                (treesit-buffer-root-node))))
+    (if (treesit-search-subtree (treesit-buffer-root-node) "^ERROR$")
+        ;; If we have syntax errors, assume that functions will have ends when 
entering
+        ;; matlab-ts-mode, otherwise leave matlab-ts--function-indent-level 
unchanged.
+        (when (equal matlab-ts-mode--function-indent-level 'unset)
+          (setq-local matlab-ts-mode--function-indent-level 
matlab-ts-mode--indent-level))
+      (let ((first-fcn (treesit-search-subtree root (rx bol 
"function_definition" eol))))
+        (if (not first-fcn)
+            ;; assume that if functions are added they will have ends
+            (setq-local matlab-ts--function-indent-level t)
+          (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
+                            (if have-end
+                                matlab-ts-mode--indent-level
+                              0))
+              (when have-end
+                (setq-local matlab-ts-mode--function-indent-level 
matlab-ts-mode--indent-level))
+              ))))))
+  matlab-ts-mode--function-indent-level)
+
 (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."
@@ -584,20 +643,25 @@ expression."
       parent ,matlab-ts-mode--switch-indent-level)
 
      ;; I-Rule: nested functions
-     ((n-p-gp ,(rx bol "function_definition" eol) ,(rx bol "block" eol)
+     ((n-p-gp ,(rx bol "function_definition" eol)
+              ,(rx bol "block" eol)
               ,(rx bol "function_definition" eol))
       parent 0)
 
+     ;; I-Rule: elseif, else, catch, end statements go back to parent level
+     ((node-is ,(rx bol (or "elseif_clause" "else_clause" "catch_clause" 
"end") eol)) parent 0)
+
+     ;; I-Rule: function's
+     ((parent-is ,(rx bol "function_definition" eol))
+      parent ,#'matlab-ts-mode--set-function-indent-level)
+
      ;; I-Rule: constructs within classdef or function's.
      ((node-is ,(rx bol (or "arguments_statement" "block" "enumeration" "enum" 
"methods" "events"
                             "function_definition" "property" "properties")
                     eol))
       parent ,matlab-ts-mode--indent-level)
 
-     ;; I-Rule: elseif, else, catch, end statements go back to parent level
-     ((node-is ,(rx bol (or "elseif_clause" "else_clause" "catch_clause" 
"end") eol)) parent 0)
-
-     ;; I-Rule: code in if, for, methods, function, arguments statements
+     ;; I-Rule: code in if, for, methods, arguments statements, etc.
      ((parent-is ,(rx bol (or "if_statement" "for_statement" "while_statement"
                               "methods" "events" "enumeration"
                               "function_definition" "arguments_statement")
@@ -777,6 +841,7 @@ expression."
                                                  (syntax-error)))
 
     ;; 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.
     (setq-local treesit-simple-indent-rules
                 (if treesit--indent-verbose ;; add debugging print as first 
rule?
diff --git a/tests/test-matlab-ts-mode-indent-files/indent_end_less_function.m 
b/tests/test-matlab-ts-mode-indent-files/indent_end_less_function.m
new file mode 100644
index 0000000000..998c8de80a
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-files/indent_end_less_function.m
@@ -0,0 +1,15 @@
+% -*- matlab-ts -*-
+function indent_end_less_function(a)
+% function without a terminating end
+
+   x = {'a', 'c()' 'b'};
+ if a
+       disp('foo');
+           else
+disp('bar');
+end
+
+indent_end_less_function2
+
+function indent_end_less_function2
+       disp('in indent_end_less_function2')
diff --git 
a/tests/test-matlab-ts-mode-indent-files/indent_end_less_function_expected.m 
b/tests/test-matlab-ts-mode-indent-files/indent_end_less_function_expected.m
new file mode 100644
index 0000000000..8720fec481
--- /dev/null
+++ b/tests/test-matlab-ts-mode-indent-files/indent_end_less_function_expected.m
@@ -0,0 +1,15 @@
+% -*- matlab-ts -*-
+function indent_end_less_function(a)
+% function without a terminating end
+
+x = {'a', 'c()' 'b'};
+if a
+    disp('foo');
+else
+    disp('bar');
+end
+
+indent_end_less_function2
+
+function indent_end_less_function2
+disp('in indent_end_less_function2')

Reply via email to