branch: externals/matlab-mode
commit e75ebf5a88b02833d700bcf9ee4419c5888caf12
Author: John Ciolfi <john.ciolfi...@gmail.com>
Commit: John Ciolfi <john.ciolfi...@gmail.com>

    Improvements to matlab-sections
    
    This commit adds default key bindings, C-c C-<KEY> and C-c M-<KEY>, which 
means code sections key
    bindings work on systems without the super key. The super key bindings can 
be added by customizing
    matlab-sections-use-super-key. This commit also adds "MATLAB -> Code 
Sections" menu.
    
    Details:
    
    1. matlab sections is support is now a minor mode, 
matlab-sections-minor-mode (Eric's patch)
       - The matlab sections support is automatically enabled for scripts.
       - A hook fires whenever the type of script in a given buffer changes. 
For example, when a new
         file is opened, and matlab-mode starts, it changes from nil to 'empty. 
If someone types in %%
         new script and then saves, the hook fires and switches to 'script. If 
instead they typed in
         function myfunc then the hook fires and switches to 'function.
    2. After entering matlab-mode, we run 
matlab-sections-auto-enable-on-mfile-type-fcn and also run it
       when a matlab-mode file is saved. This ensures that the 
matlab-sections-minor-mode is only
       enabled when in a script.
    3. In matlab.el, renamed script-type to mfile-type, e.g. 
matlab-guess-script-type
       matlab-guess-mfile-type.
    4. Reduced number of calls to determining the mfile type 
(matlab-guess-mfile-type) which should give
       a little boost.
    5. Fix: "comment blocks" like the following are not identified as "%% 
sections"
      #+begin_src matlab
       %%%%%%%%%%%%%
       %% comment %%
       %%%%%%%%%%%%%
      #+end_src
    6. Fix "%% section" face handling such that it is only shown when 
matlab-sections-minor-mode
       is true. Also, do not treat "%%%" comment blocks as "%% section" starts.
    7. Fix: section comment face so that it is a bolded comment rather than 
blank and white
       by inheriting from font-lock-comment-face.
    8. Updated the "%% section" start face to be a little bigger to make it 
standout more.
    9. Fix: in matlab-syntax.el, only apply matlab-sections-section-break-face 
if we have
       "%%" and not "%%%". This help prevent comment blocks using lots of '%%%' 
characters
       from being treated as sections.
    10. Fix: if point is at the start of the file before a "%% section",
        matlab-sections-backward-section generates a lisp error. For example,
        if point is in line 1 or 2 in this code, we get an error:
           #+begin_src matlab
             % line 1
             % line 2
             %% section 1
             a = 1;
           #+end_src
    11. Fix: if point is at end of the buffer and you run 
matlab-sections-run-till-point
        it gets stuck in an infinite loop because (while (>= pt (point)) ...) is
        always true when at the end of the buffer.
    12. Consolidate help for matlab-sections into matlab-sections-minor-mode
        and correctly display the key mappings.
    13. Add matlab-sections-run-section keybinding to run current section
    14. Added MATLAB -> Code Sections menu
    15. Added matlab-sections-help to show basics MATLAB -> Sections -> 
Sections Help
    16. Fix: matlab-sections-run-till-point where it would run the
        current section if it was the first section. Now it does nothing 
because there's
        nothing to run.
    17. Fix: matlab-sections-run-till-point where it was not waiting for MATLAB 
to
        finish before running the next section. The fix was to tell emacs to 
run all relevant
        lines.
    18. Renamed matlab-sections-run-till-point to 
matlab-sections-run-prior-sections.
    19. In matlab-sections-forward-section, removed optional AGGRESSIVE 
argument which when
        true made it behave same as matlab-sections-end-of-section. Did same for
        for matlab-sessions-backward-section.
    20. In matlab-sections-forward-section removed (not 
(pos-visible-in-window-p endp))
        because it cause the tests to not work correctly and it wasn't clear 
why it was there.
        I couldn't find a reason for it? Did same for 
matlab-sessions-backward-section.
    21. In matlab-sections-beginning-of-section, move to the first code in the 
section.
        Previously, it didn't handle multiple blank lines.
    22. Cleanup: in matlab.el, for the write-contents-functions, removed the 
unused optional fast
        argument.
    23. Fixed a few typos and spelling issues in matlab.el
    24. Added tests for matlab-sections.el
---
 README.org                                      |  26 +-
 examples/matlab-sections/tryout_matlabsection.m |  38 +-
 matlab-sections.el                              | 415 +++++++++++++---------
 matlab-syntax.el                                |  35 +-
 matlab.el                                       | 440 ++++++++++++------------
 tests/metest.el                                 |  10 +-
 tests/mstest-sections.el                        | 215 ++++++++++++
 tests/mstest.el                                 |   8 +-
 tests/sections.m                                |  12 +
 9 files changed, 771 insertions(+), 428 deletions(-)

diff --git a/README.org b/README.org
index e634e1f4ee..39057840f7 100644
--- a/README.org
+++ b/README.org
@@ -7,16 +7,29 @@
 
 [[https://mathworks.com][MathWorks]] MATLAB® and 
[[https://www.gnu.org/software/emacs/][GNU Emacs]] integration:
 
-1. matlab-mode for editing ~*.m~ files.
+1. *matlab-mode* for editing ~*.m~ files.
 
    - Edit MATLAB code with syntax highlighting and smart indentation.
    - Lint MATLAB code with fix-it's using the MATLAB Code Analyzer.
 
-2. ~M-x matlab-shell~ for running and debugging MATLAB within Emacs 
(Unix-only).
+2. *~M-x matlab-shell~* for running and debugging MATLAB within Emacs 
(Unix-only).
 
    - matlab-shell uses company-mode for completions.
 
-3. MATLAB and [[http://orgmode.org]] for creation of scientific papers, 
theses, and documents.
+3. *Code sections* support. MATLAB script code files often contain many 
commands and lines
+   of text.  You typically focus your efforts on a single part of your code at 
a time, working with
+   the code and related text in sections.  You demarcate sections using /"%% 
description"/ comments.
+
+   - After visiting a MATLAB script, you have the *"MATLAB -> Code Sections"* 
menu and key
+     bindings which lets you can navigate, run, and move code sections.
+
+   - Try out code sections using: 
[[file:examples/matlab-sections/tryout_matlabsection.m][./examples/matlab-sections/tryout_matlabsection.m]].
+
+   - The default keybindings for code sections are ~C-c C-<KEY>~ and ~C-c 
M-<KEY>~. You can add
+     super key bindings for code sections. After visiting a file.m, see menu 
*"MATLAB -> Code
+     Sections -> Help"*.
+
+4. *Creation of scientific papers, theses, and documents* using MATLAB and 
[[http://orgmode.org]].
 
    - Org enables 
[[https://en.wikipedia.org/wiki/Literate_programming][literate programming]] 
which directly supports reproducible research by allowing
      scientists and engineers to write code along with detailed explanations 
in natural language.
@@ -31,7 +44,8 @@
    - See 
[[file:examples/matlab-and-org-mode][./examples/matlab-and-org-mode/]] to get 
started. This directory contains a 
[[file:examples/matlab-and-org-mode/matlab-and-org-mode.pdf][PDF]] generated 
from
      
[[file:examples/matlab-and-org-mode/matlab-and-org-mode.org][./examples/matlab-and-org-mode/matlab-and-org-mode.org]].
 
-4. tlc-mode for editing ~*.tlc~ files. The Target Language Compiler (TLC) is 
part of Simulink® Coder™.
+5. *tlc-mode* for editing ~*.tlc~ files. The Target Language Compiler (TLC) is 
part of Simulink®
+   Coder™.
 
 * Installation
 
@@ -136,11 +150,11 @@ In this case, add the following hook to your config:
               (font-lock-flush)))
 #+end_src
 Ensure that this is included after matlab-mode as well as your syntax
-highlighter are initialized in your config. 
+highlighter are initialized in your config.
 
 * History
 
 matlab-mode has a history dating back many years. Older contributions can be 
found in
 
[[https://sourceforge.net/projects/matlab-emacs/][https://sourceforge.net/projects/matlab-emacs/]].
 
-# LocalWords:  showall nodesktop melpa emacsclient
+# LocalWords:  showall nodesktop melpa emacsclient matlabsection
diff --git a/examples/matlab-sections/tryout_matlabsection.m 
b/examples/matlab-sections/tryout_matlabsection.m
index a9d3013718..aeaf53175d 100644
--- a/examples/matlab-sections/tryout_matlabsection.m
+++ b/examples/matlab-sections/tryout_matlabsection.m
@@ -1,3 +1,22 @@
+%% MATLAB code sections menu and keybindings
+%
+% Try:
+%
+% 1. Run (requires M-x matlab-shell, Unix only)
+%      MATLAB -> Code Sections -> Run section
+%      MATLAB -> Code Sections -> Run prior sections
+% 2. Navigation
+%      MATLAB -> Code Sections -> Backward section
+%      MATLAB -> Code Sections -> Forward section
+%      MATLAB -> Code Sections -> Move to beginning
+%      MATLAB -> Code Sections -> Move to end
+% 3. Move section content
+%      MATLAB -> Code Sections -> Mark/select section
+%      MATLAB -> Code Sections -> Move section up
+%      MATLAB -> Code Sections -> Move section down
+% 4. Super "Windows" key bindings can be enabled or disabled, see
+%      MATLAB -> Code Sections -> Help
+
 %% Preamble
 clc
 clear all
@@ -41,22 +60,3 @@ plot(eig(randn(N,N))/sqrt(N), '.'); hold on
 plot(cos((0:100)*2*pi/100), sin((0:100)*2*pi/100), '-');
 axis equal; grid on
 set(gca, 'FontSize', fsz)
-
-%% Things to try out:
-% 1. Move point to the beginning of the buffer and try out the
-%    function `matlab-sections-forward-section'.
-%    This should take you to the next section (while highlighting). Do
-%    it a couple more times to navigate.
-% 2. Try out `matlab-sections-move-section-down' and this action will be 
reversed.
-% 3. Go to the third section and try the function
-%    `matlab-sections-move-section-up'.
-%    This should move the contents of this section to occur before the
-%    previous section.   
-% 4. Then try out the function `matlab-sections-backward-section'.
-% 5. Next (ensure you have matlab-shell running) try out the
-%    function `matlab-sections-shell-run-section' to run the contents of
-%    the section in the shell.
-%    I rewrote this based on the matlab-sections environ to be
-%    consistent although `matlab-shell-run-section` does something
-%    similar.  
-
diff --git a/matlab-sections.el b/matlab-sections.el
index 00cfaa947b..4bb7b96d13 100644
--- a/matlab-sections.el
+++ b/matlab-sections.el
@@ -1,9 +1,8 @@
 ;;; matlab-sections.el --- Support for code sections in matlab mode -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2024 Free Software Foundation, Inc.
+;; Copyright (C) 2024-2025 Free Software Foundation, Inc.
 
-
-;; Author: Nidish Narayanaa Balaji <nid...@gmail.com>
+;; Author: Nidish Narayanaa Balaji <nid...@gmail.com>, John Ciolfi 
<john.ciolfi...@gmail.com>, Eric Ludlam <za...@gnu.org>
 ;; Created: 2024-05-14
 ;; Renamed: 2024-10-22
 ;;
@@ -22,88 +21,90 @@
 ;;
 ;;; Commentary:
 ;;
-;; NOTE: What is referred to as "sections" herein were previously
-;; referred to as code cells.
-;;
-;; This creates a minor mode called `matlab-sections-mode' that adds
-;; utilities for working with code sections in matlab code.  The basic mechanic
-;; is to redefine the page-delimiter (locally) to any line that starts
-;; with "%%" as the first non-empty characters followed by some
-;; comment strings.
-;; Consequently, the line that is detected in the above manner is
-;; highlighted by the face `matlab-sections-section-break-face'.  By default,
-;; this is bold-faced and has an overline above it.
-;;
-;; The section that point is on is highlighted by the face
-;; `matlab-sections-highlight-face'.  By default this is set to
-;; "extra-bold".  The section-highlight can be toggled using
-;; `matlab-sections-highlight-section' (defaults to "t").
-;;
-;; Another variable, `matlab-sections-sticky-flag' is defined, that
-;; defines whether the current section is highlighted even when point
-;; moves to another window (defaults to "t").
+;; This provides `matlab-sections-minor-mode' contains utilities for working 
with MATLAB code
+;; sections and can be accessed via the keybindings or the "MATLAB -> Code 
Sections" menu
+;; after opening a script_file.m.  See "MATLAB -> Code Sections -> Help" to 
get started.
 ;;
-;; Finally, the minor-mode provides the following interactive
-;; navigation functions (default keybindings provided within []):
-;; 1. `matlab-sections-forward-section' : Move point to the beginning of the
-;;    section right below.  [C-s-<down>]
-;; 2. `matlab-sections-backward-section' : Move point to the end of the section
-;;    right above.  [C-s-<up>]
-;; 3. `matlab-sections-beginning-of-section' : Move point to beginning of
-;;    current section.  Return (point).  [C-s-<left>]
-;; 4. `matlab-sections-end-of-section' : Move point to end of current section.
-;;    Return (point).  [C-s-<right>]
-;; 5. `matlab-sections-move-section-up' : Move the contents of the current 
section
-;;    \"up\", so that it occurs before the previous.  [s-<up>]
-;; 6. `matlab-sections-move-section-down' : Move the contents of the current
-;;    section \"down\", so that it occurs after the next.  [s-<down>]
-;; 7. `matlab-sections-run-till-point' : Run all the sections from beginning
-;;    till previous section.  [s-<return>]
-;; 8. `matlab-sections-mark-section' : Mark the current section.  [s-c]
-;; (Note that some default keybindings may clash with existing
-;; keybindings in the desktop environment)
+;; The standard keybindings are C-c C-<KEY> and C-c M-<KEY> which are 
available on platforms.
+;; For systems that have the super \"Windows\" logo key, you can use that by 
customizing
+;; `matlab-sections-use-super-key'.
 ;;
-;; Other than this, there are some utility functions to help
-;; development.
+;; NOTE: Older MATLAB releases used the term cell to describe sections and 
newer MATLAB releases
+;; use the term section.  See MATLAB help "Create and Run Sections in Code".
 ;;
 ;; Major parts of the code are modified from python-cell.el by Thomas
 ;; Hisch (currently at: https://github.com/twmr/python-cell.el).
-;;
+
 ;;; Code:
 
 (require 'subr-x)
+(require 'cl-macs)
 
 ;;
 ;; Customizable Variables and Faces
 (defgroup matlab-sections nil
-  "MATLAB-GUI-like sections in matlab-mode."
+  "MATLAB \"%% code sections\"."
   :group 'matlab)
 
 (defface matlab-sections-highlight-face
   '((t :weight extra-bold))
-  "Default face for highlighting the current section in matlab-sections minor 
mode."
+  "Default face for highlighting the current section in 
matlab-sections-minor-mode."
   :group 'matlab-sections)
 
 (defface matlab-sections-section-break-face
-  '((t :weight bold :overline t))
-  "Default face for the section separation line in matlab-sections minor mode."
+  '((t :inherit font-lock-comment-face
+       :overline t
+       :height 1.25))
+  "Default face for the section separation line in matlab-sections-minor-mode."
   :group 'matlab-sections)
 
 (defcustom matlab-sections-highlight-section t
-  "Non-nil tells matlab-sections mode to highlight the current section."
+  "Non-nil tells matlab-sections-minor-mode to highlight the current section."
+  :type 'boolean
+  :group 'matlab-sections
+  :safe 'booleanp)
+
+(defcustom matlab-sections-use-super-key nil
+  "Non-nil to add the super \"Windows\" keybindings.
+The `matlab-sections-minor-mode' defines a set of keybindings which work
+on all systems and optionally a set of keybindings using the super
+\"Windows\" logo key.  The super key may not be available or work, hence
+the reason for it being optional."
   :type 'boolean
   :group 'matlab-sections
   :safe 'booleanp)
 
 (defcustom matlab-sections-section-break-regexp
-  (rx line-start (* space)
-      (group "%%" (* (not (any "\n"))) line-end))
-  "Regexp used for detecting the section boundaries of code sections."
+  (concat "^[[:blank:]]*" ;; Can have space or tabs prior to the "%%" 
characters
+          "\\("
+          "%%"            ;; Next must have two "%%" characters
+          "\\(?:"         ;; Optionally followed by a description or blanks
+          "[[:blank:]]+"                        ;; description must start with 
space or tab
+          "[[:graph:][:blank:]]*"               ;; description
+          "\\(?:"
+          "[^[:space:][:cntrl:]%]%[[:blank:]]*" ;; description can end with 
"<CHAR>%"
+          "\\|"
+          "[^[:space:][:cntrl:]%][[:blank:]]*"  ;; description cannot end with 
" %"
+          "\\)"
+          "\\|"
+          "[[:blank:]]+"                        ;; description is: "%% <spaces 
or tabs>"
+          "\\)?"
+          "\\)$")
+  "Regexp identifying a \"%% section\" header comment.
+Section header comments start with \"%%\" and can optionally be followed
+by a description:
+    %% description
+We do not want to match comment \"blocks\" like:
+    %%%%%%%%%%%%%
+    %% comment %%
+    %%%%%%%%%%%%%
+Therefore, we require that the section starts with \"%%\" optionally
+followed by a description that doesn't end with \"%\"."
   :type 'string
   :group 'matlab-sections
   :safe 'stringp)
 
-(defvar matlab-sections-mode)
+(defvar matlab-sections-minor-mode)
 
 (defvar matlab-sections-overlay nil
   "Overlay used by matlab-sections mode to highlight the current section.")
@@ -124,7 +125,7 @@
   "Non-nil means the matlab-sections mode highlight appears in all windows.
 Otherwise matlab-sections mode will highlight only in the selected
 window.  Setting this variable takes effect the next time you use
-the command `matlab-sections-mode' to turn matlab-sections mode on."
+the command `matlab-sections-minor-mode' to turn matlab-sections mode on."
   :type 'boolean
   :group 'matlab-sections)
 
@@ -158,7 +159,7 @@ It should return nil if there's no region to be 
highlighted."
 ;; Navigation
 
 (defun matlab-sections-move-section-up (&optional arg)
-  "Move the contents of the current section up.
+  "Move the current \"%% section\" up.
 Optionally a prefix argument ARG can be provided for repeating it a
 bunch of times."
   (interactive "p")
@@ -174,7 +175,7 @@ bunch of times."
   )
 
 (defun matlab-sections-move-section-down (&optional arg)
-  "Move the contents of the current section down.
+  "Move the current \"%% section\" down.
 Optionally a prefix argument ARG can be provided for repeating it a
   bunch of times."
   (interactive "p")
@@ -190,85 +191,86 @@ Optionally a prefix argument ARG can be provided for 
repeating it a
       (matlab-sections-beginning-of-section)))
   )
 
-(defun matlab-sections-forward-section  (&optional arg aggressive)
-  "Move point forward by a section.
-Optionally provide prefix argument ARG to move by that many sections.
-Optionally provide argument AGGRESSIVE to specify whether to move
-  aggressively to next section or just move to end of current section if
-  next section is not visible."
+(cl-defun matlab-sections-forward-section (&optional arg)
+  "Move point forward to the next \"%% section\".
+Optionally provide prefix argument ARG to move by that many sections."
   (interactive "p")
 
   (dotimes (_ (or arg 1))
-    (let ((endp (save-excursion (matlab-sections-end-of-section))))
-      (if (and (not (eq (point) endp))
-              (not (pos-visible-in-window-p endp))
-              (not aggressive))
-         (goto-char endp)
-       (goto-char endp)
-    (if (re-search-forward matlab-sections-section-break-regexp nil t)
-       (progn (end-of-line)
-              (forward-char 1))
-      (goto-char (point-max)))
-    )))
-  )
-
-(defun matlab-sections-backward-section  (&optional arg aggressive)
-  "Move point backwards by a section.
-Optionally provide prefix argument ARG to move by that many sections.
-Optionally provide argument AGGRESSIVE to specify whether to move
-  aggressively to previous section or just move to beginning of current
-  section if previous section is not visible."
+    (let (next-section-pt)
+      (save-excursion
+        (matlab-sections-end-of-section)
+        (when (re-search-forward matlab-sections-section-break-regexp nil t)
+          (when (not (eobp))
+            (forward-line))
+          (while (and (not (eobp))
+                      (looking-at "^[[:blank:]]*$"))
+            (forward-line))
+          (setq next-section-pt (point))))
+      (when (not next-section-pt)
+        (message "No following \"%%%% section\" to move to")
+        (cl-return-from matlab-sections-forward-section))
+      (goto-char next-section-pt))))
+
+(cl-defun matlab-sections-backward-section  (&optional arg)
+  "Move point backwards to the prior \"%% section\".
+Optionally provide prefix argument ARG to move by that many sections."
   (interactive "p")
 
   (dotimes (_ (or arg 1))
-    (let ((begp (save-excursion (matlab-sections-beginning-of-section))))
-      (if (and (not (eq (point) begp))
-              (not (pos-visible-in-window-p begp))
-              (not aggressive))
-         (goto-char begp)
-       (goto-char begp)
-       (forward-char -1)
-       (beginning-of-line)
-       (and (save-excursion (re-search-backward 
matlab-sections-section-break-regexp
-                                                nil t))
-            (= (match-beginning 0) (save-excursion
-                                     (forward-char -1) (beginning-of-line) 
(point)))
-            (goto-char (match-beginning 0)))
-
-       (if (> (point) (point-min))
-           (forward-char -1))
-       (if (re-search-backward matlab-sections-section-break-regexp nil t)
-           (progn (goto-char (match-end 0))
-                  (end-of-line)
-                  (forward-char 1))
-         (goto-char (point-min)))
-       )))
-  )
+    (let (prev-section-pt)
+      (save-excursion
+        (matlab-sections-beginning-of-section)
+        (when (re-search-backward matlab-sections-section-break-regexp nil t)
+          ;; We are now at the start of the current "%% section" line
+          (if (re-search-backward matlab-sections-section-break-regexp nil t)
+              (progn
+                ;; We are now in the prior section, move to it's start
+                (matlab-sections-beginning-of-section)
+                (setq prev-section-pt (point)))
+            ;; Else if there's code or comments before the first section, go 
there
+            (when (not (= (point) (point-min)))
+              (setq prev-section-pt (point-min))))))
+      (when (not prev-section-pt)
+        (message "No prior \"%%%% section\" to move to")
+        (cl-return-from matlab-sections-backward-section))
+      (goto-char prev-section-pt))))
 
 (defun matlab-sections-beginning-of-section ()
-  "Move point to beginning of section."
+  "Move `point' to the beginning of the current \"%% section\".
+Return `point'."
   (interactive)
-
   (end-of-line)
   (if (re-search-backward matlab-sections-section-break-regexp nil t)
-      (progn (goto-char (match-end 0))
-            (end-of-line)
-            (forward-char 1))
+      (progn
+        (forward-line)
+        (while (and (not (eobp))
+                    (looking-at "^[[:blank:]]*$"))
+          (forward-line)))
+    ;; else consider case where there's code before first section, if so go 
there
     (goto-char (point-min)))
-  (point)
-  )
+  (point))
 
 (defun matlab-sections-end-of-section ()
-  "Move point to end of section."
+  "Move point to end of section.
+Return `point'."
   (interactive)
 
   (end-of-line)
   (if (re-search-forward matlab-sections-section-break-regexp nil t)
-      (progn (goto-char (match-beginning 0))
-            (forward-char -1))
+      (progn
+        (forward-char -1)
+        (beginning-of-line)
+        (when (not (bobp))
+          (forward-line -1))
+        (while (and (not (bobp))
+                    (looking-at "^[[:blank:]]*$"))
+          (forward-line -1))
+        ;; move to the point where we'd start code
+        (forward-line))
+
     (goto-char (point-max)))
-  (point)
-  )
+  (point))
 
 (defun matlab-sections-mark-section ()
   "Mark the contents of the current section.  Replace `mark-page'."
@@ -283,31 +285,102 @@ Optionally provide argument AGGRESSIVE to specify 
whether to move
 
 (declare-function matlab-shell-run-region "matlab-shell.el")
 
-(defun matlab-sections-shell-run-section ()
-  "Run the section point is in, in matlab-shell."
+(defun matlab-sections-run-section ()
+  "Run the current \"%% section\" in `matlab-shell'."
   (interactive)
   (let ((rng (matlab-sections-range-function)))
-    (matlab-shell-run-region (car rng) (cdr rng)))
-  )
-
-(defun matlab-sections-run-till-point ()
-  "Run all sections until point, not including the section point is in."
-  (interactive)
-  (let ((pt (point)))
     (save-excursion
       (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (while (>= pt (point))
-         (save-window-excursion (matlab-sections-shell-run-section))
-         (matlab-sections-forward-section)
-         (matlab-sections-end-of-section))))))
+        (widen)
+        (save-window-excursion
+          (matlab-shell-run-region (car rng) (cdr rng)))))))
+
+(define-obsolete-function-alias 'matlab-sections-run-till-point
+  #'matlab-sections-run-prior-sections "6.3")
+
+(defun matlab-sections-run-prior-sections ()
+  "Run all \"%% sections\" prior to the current section in `matlab-shell'.
+Does not run the section the point is in."
+  (interactive)
+  (save-excursion
+    (save-restriction
+      (widen)
+      (let ((current-section-start-point 
(matlab-sections-beginning-of-section)))
+        (goto-char (point-min))
+        (matlab-sections-beginning-of-section)
+        (when (< (point) current-section-start-point)
+          (save-window-excursion
+            (matlab-shell-run-region (point) current-section-start-point)))))))
+
+(declare-function matlab-mode "matlab.el")
+
+(defun matlab-sections-help ()
+  "Display help for MATLAB \"%% code sections\"."
+  (interactive)
+  (let ((help-buf-name "*MATLAB Code Sections*"))
+    (with-output-to-temp-buffer help-buf-name
+      (with-current-buffer help-buf-name
+        (insert "\
+MATLAB code files often contain many commands and lines of text.  You
+typically focus your efforts on a single part of your code at a time,
+working with the code and related text in sections.  You demarcate
+sections using \"%% description\" comment lines.  For example, this
+sine_wave.m script contains two code sections:
+
+")
+        (insert (with-temp-buffer
+                  (insert "\
+   %% Calculate and plot a sine wave
+   x = 0:1:6*pi;
+   y = sin(x);
+   plot(x,y)
+
+   %% Modify the plot to look nice
+   title(\"Sine Wave\")
+   xlabel(\"x\");
+   ylabel(\"sin(x)\")
+   fig = gcf;
+   fig.MenuBar = \"none\";
+")
+                  (matlab-mode)
+                  (matlab-sections-minor-mode)
+                  (goto-char (point-min))
+                  (font-lock-ensure)
+                  (buffer-substring (point-min) (point-max))))
+
+        (insert "
+You can navigate, run, and move code sections.
+")
+        ;; Add the keybindings
+        (insert (substitute-command-keys "\\{matlab-sections-minor-mode-map}
+
+You can enable / disable super \"Windows\" key bindings by customizing
+`matlab-sections-use-super-key'"))))))
+
+;;; Enable/Disable sections mode automatically
+;;;###autoload
+(defun matlab-sections-auto-enable-on-mfile-type-fcn (mfile-type)
+  "Activate or deactivate sections mode based on MFILE-TYPE.
+This is a noop if `noninteractive' is t."
+  ;; Code sections "%% description" have some cost, thus don't activate in 
batch mode.
+  (unless noninteractive
+    (let ((is-enabled matlab-sections-minor-mode)
+          (enable (eq mfile-type 'script)))
+      (if enable
+          (when (not is-enabled)
+            (matlab-sections-mode-enable)
+            ;; Correctly color "%% section" comments
+            (font-lock-flush))
+        (when is-enabled
+          (matlab-sections-mode-disable)
+          ;; Correctly color "%% section" comments
+          (font-lock-flush))))))
 
 ;;; Section Highlighting
 
 (defun matlab-sections-highlight ()
   "Activate the matlab-sections overlay on the current line."
-  (if matlab-sections-mode  ; Might be changed outside the mode function.
+  (if matlab-sections-minor-mode  ; Might be changed outside the mode function.
       (progn
        (unless matlab-sections-overlay
          (setq matlab-sections-overlay (make-overlay 1 1)) ; to be moved
@@ -339,16 +412,34 @@ Optionally provide argument AGGRESSIVE to specify whether 
to move
   (add-hook 'post-command-hook #'matlab-sections-highlight nil t))
 
 ;;; Keymap
-(defvar matlab-sections-mode-map
+(defvar matlab-sections-minor-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "C-s-<down>") #'matlab-sections-forward-section)
-    (define-key map (kbd "C-s-<up>") #'matlab-sections-backward-section)
-    (define-key map (kbd "C-s-<left>") #'matlab-sections-beginning-of-section)
-    (define-key map (kbd "C-s-<right>") #'matlab-sections-end-of-section)
-    (define-key map (kbd "s-<up>") #'matlab-sections-move-section-up)
-    (define-key map (kbd "s-<down>") #'matlab-sections-move-section-down)
-    (define-key map (kbd "s-<return>") #'matlab-sections-run-till-point)
-    (define-key map (kbd "s-c") #'matlab-sections-mark-section)
+    (define-key map (kbd "C-c C-<return>") #'matlab-sections-run-section)
+    (define-key map (kbd "C-c M-<return>") 
#'matlab-sections-run-prior-sections)
+    (define-key map (kbd "C-C C-<left>") 
#'matlab-sections-beginning-of-section)
+    (define-key map (kbd "C-C C-<right>") #'matlab-sections-end-of-section)
+    (define-key map (kbd "C-C C-<up>") #'matlab-sections-backward-section)
+    (define-key map (kbd "C-c C-<down>") #'matlab-sections-forward-section)
+    (define-key map (kbd "C-c M-<up>") #'matlab-sections-move-section-up)
+    (define-key map (kbd "C-c M-<down>") #'matlab-sections-move-section-down)
+    (define-key map (kbd "C-c C-SPC") #'matlab-sections-mark-section)
+
+    (when matlab-sections-use-super-key
+      ;; We do not add these by default.  When these are added, the "MATLAB -> 
Code Sections" shows
+      ;; the super key bindings instead of the above keys.  Thus, if we were 
to add these by
+      ;; default, then the menu would be incorrect for those that do not have 
the super key.
+      ;; Likewise, matlab-sections-help should not show the super keys if the 
system doesn't have
+      ;; them.
+      (define-key map (kbd "C-s-<return>") #'matlab-sections-run-section)
+      (define-key map (kbd "s-<return>") #'matlab-sections-run-prior-sections)
+      (define-key map (kbd "C-s-<left>") 
#'matlab-sections-beginning-of-section)
+      (define-key map (kbd "C-s-<right>") #'matlab-sections-end-of-section)
+      (define-key map (kbd "C-s-<up>") #'matlab-sections-backward-section)
+      (define-key map (kbd "C-s-<down>") #'matlab-sections-forward-section)
+      (define-key map (kbd "s-<up>") #'matlab-sections-move-section-up)
+      (define-key map (kbd "s-<down>") #'matlab-sections-move-section-down)
+      (define-key map (kbd "s-c") #'matlab-sections-mark-section))
+
     map)
   "Key map for matlab-sections minor mode.")
 
@@ -358,51 +449,31 @@ Optionally provide argument AGGRESSIVE to specify whether 
to move
 ;;; Minor mode:
 
 ;;;###autoload
-(define-minor-mode matlab-sections-mode
-  "Highlight MATLAB-like sections and navigate between them.
-The minor-mode provides the following interactive navigation
-functions.  The default keybindings are provided in square brackets for
-each:
-1. `matlab-sections-forward-section' : Move point to the beginning of the
-   section right below.  \\[matlab-sections-forward-section]
-2. `matlab-sections-backward-section' : Move point to the end of the section
-   right above.  \\[matlab-sections-backward-section]
-3. `matlab-sections-beginning-of-section' : Move point to beginning of
-   current section.  Return (point).  \\[matlab-sections-beginning-of-section]
-4. `matlab-sections-end-of-section' : Move point to end of current section.
-   Return (point).  \\[matlab-sections-end-of-section]
-5. `matlab-sections-move-section-up' : Move the contents of the current section
-   \"up\", so that it occurs before the previous.  
\\[matlab-sections-move-section-up]
-6. `matlab-sections-move-section-down' : Move the contents of the current
-   section \"down\", so that it occurs after the next.  
\\[matlab-sections-move-section-down]
-7. `matlab-sections-run-till-point' : Run all the sections from beginning
-   till previous section.  \\[matlab-sections-run-till-point]
-8. `matlab-sections-mark-section' : Mark the current section.  
\\[matlab-sections-mark-section]"
+(define-minor-mode matlab-sections-minor-mode
+  "Manage MATLAB code sections.
+
+See `matlab-sections-help' for details on MATLAB code sections."
   :init-value nil
-  :keymap matlab-sections-mode-map
+  :keymap matlab-sections-minor-mode-map
 
-  ;; (let ((arg `((,matlab-sections-section-break-regexp 1 
'matlab-sections-section-break-face prepend))))
   (make-local-variable 'page-delimiter)
   (setq page-delimiter matlab-sections-section-break-regexp)
-  ;; (font-lock-add-keywords nil arg)
   (when matlab-sections-highlight-section
-    (matlab-sections-setup-section-highlight))
-  ;; (font-lock-flush))
-  )
+    (matlab-sections-setup-section-highlight)))
 
 ;;;###autoload
 (defun matlab-sections-mode-enable ()
   "Enable matlab-sections-mode."
-  (matlab-sections-mode 1))
+  (matlab-sections-minor-mode 1))
 
 ;;;###autoload
 (defun matlab-sections-mode-disable ()
   "Disable matlab-sections-mode."
-  (matlab-sections-mode 0))
+  (matlab-sections-minor-mode 0))
 
 (provide 'matlab-sections)
 ;;; matlab-sections.el ends here
 
 ;; LocalWords:  Nidish Narayanaa Balaji nidbid gmail cellbreak Hisch subr 
defface defcustom booleanp
-;; LocalWords:  stringp dolist defun cdr progn cp dotimes rngc rngp rngn endp 
begp setq Keymap
-;; LocalWords:  keymap kbd defalias
+;; LocalWords:  stringp dolist defun cdr progn cp dotimes rngc rngp rngn endp 
begp setq Keymap cntrl
+;; LocalWords:  keymap kbd defalias Ludlam zappo prev eobp bobp buf SPC noop 
mfile
diff --git a/matlab-syntax.el b/matlab-syntax.el
index 92f1617cfb..6f24b58cfe 100644
--- a/matlab-syntax.el
+++ b/matlab-syntax.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2024 Free Software Foundation, Inc.
 
-;; Author:  <elud...@mathworks.com>
+;; Author:  <elud...@mathworks.com>, <john.ciolfi...@gmail.com>
 ;;
 ;; This program is free software; you can redistribute it and/or
 ;; modify it under the terms of the GNU General Public License as
@@ -20,7 +20,7 @@
 ;;; Commentary:
 ;;
 ;; Manage syntax handling for `matlab-mode'.
-;; Matlab's syntax for comments and strings can't be handled by a standard
+;; MATLAB's syntax for comments and strings can't be handled by a standard
 ;; Emacs syntax table.  This code handles the syntax table, and special
 ;; scanning needed to augment a buffer's syntax for all our special cases.
 ;;
@@ -28,8 +28,10 @@
 ;; block scanning, and the line.
 
 (require 'matlab-compat)
+(require 'matlab-sections)
 
 ;;; Code:
+
 (defvar matlab-syntax-support-command-dual t
   "Non-nil means to support command dual for indenting and syntax highlight.
 Does not work well in classes with properties with datatypes.")
@@ -58,7 +60,7 @@ Does not work well in classes with properties with 
datatypes.")
     ;;   Unterminated Char V: ' text
     (modify-syntax-entry ?'  "\"" st)
     (modify-syntax-entry ?\" "\"" st)
-    
+
     ;; Words and Symbols:
     (modify-syntax-entry ?_  "_" st)
 
@@ -83,7 +85,7 @@ Does not work well in classes with properties with 
datatypes.")
     (modify-syntax-entry ?\]  ")[" st)
     ;;(modify-syntax-entry ?{  "(}" st) - Handled as part of comments
     ;;(modify-syntax-entry ?}  "){" st)
-    
+
     st)
   "MATLAB syntax table.")
 
@@ -178,7 +180,7 @@ and `matlab--scan-line-for-unterminated-string' for 
specific details."
            (end-of-line)
            (matlab--put-char-category (point) 'matlab--command-dual-syntax)
            ))
-       
+
        ;; Multiple ellipsis can be on a line.  Find them all
        (beginning-of-line)
        (while (matlab--scan-line-for-ellipsis)
@@ -324,10 +326,17 @@ Called when comments found in 
`matlab--scan-line-for-unterminated-string'."
            (t
             'font-lock-string-face))
 
-    ;; Not a string, must be a comment.  Check to see if it is a
-    ;; cellbreak comment.
-    (cond ((and (< (nth 8 pps) (point-max))
-               (= (char-after (1+ (nth 8 pps))) ?\%))
+    ;; Not a string, must be a comment. Pick type of comment face to use.
+    (cond ((and (boundp 'matlab-sections-minor-mode) matlab-sections-minor-mode
+                (< (nth 8 pps) (point-max))
+                (= (char-after (1+ (nth 8 pps))) ?\%) ;; looking-at "%%"?
+                ;; Now see if we have a valid section start comment
+                (save-excursion
+                  (save-restriction
+                    (widen)
+                    (goto-char (nth 8 pps))
+                    (beginning-of-line)
+                    (looking-at matlab-sections-section-break-regexp))))
           'matlab-sections-section-break-face)
          ((and (< (nth 8 pps) (point-max))
                (= (char-after (1+ (nth 8 pps))) ?\#))
@@ -369,7 +378,7 @@ Safe to use in `matlab-mode-hook'."
   (setq paragraph-separate paragraph-start)
   (make-local-variable 'paragraph-ignore-fill-prefix)
   (setq paragraph-ignore-fill-prefix t)
-  
+
   ;; Font lock
   (make-local-variable 'font-lock-syntactic-face-function)
   (setq font-lock-syntactic-face-function 'matlab--font-lock-syntactic-face)
@@ -430,7 +439,7 @@ bounds of the string or comment the cursor is in"
                           'comment
                         'ellipsis))
                      (t nil)))
-         
+
          ;; compute the bounds
          (when (and syntax bounds-sym)
            (if (memq syntax '(charvector string))
@@ -452,7 +461,7 @@ Optional ALL-COMMENTS if t, move to first."
     (prog1
        (when (nth 8 pps)
          (goto-char (nth 8 pps))
-         
+
          t)
       (when all-comments
        (prog1
@@ -583,4 +592,4 @@ If COUNT is negative, travel backward."
 
 ;; LocalWords:  Ludlam eludlam compat booleanp propertize varname defmacro 
oldsyntax progn edebug
 ;; LocalWords:  ppss sexp pps defun eobp mcm blockcomment EOL defconst 
commanddual cds bolp eol
-;; LocalWords:  cellbreak setq defsubst charvector memq sexps posn parens
+;; LocalWords:  cellbreak setq defsubst charvector memq sexps posn parens 
boundp gmail
diff --git a/matlab.el b/matlab.el
index 544b1e1a74..9df901a0a0 100644
--- a/matlab.el
+++ b/matlab.el
@@ -109,7 +109,7 @@ Applies when no other methods are found."
 
 (defcustom matlab-cont-requires-ellipsis t
   "*Specify if ellipses are required at the end of a line for continuation.
-Future versions of Matlab may not require ellipses ... , so a heuristic
+Future versions of MATLAB may not require ellipses ... , so a heuristic
 determining if there is to be continuation is used instead."
   :group 'matlab
   :type 'integer)
@@ -119,13 +119,13 @@ determining if there is to be continuation is used 
instead."
 This can be an integer, which is the distance to indent the CASE and
 OTHERWISE commands, and how far to indent commands appearing in CASE
 and OTHERWISE blocks.  It can also be a cons cell which is of form
-  (CASEINDENT . COMMANDINDENT)
-where CASEINDENT is the indentation of the CASE and OTHERWISE
-statements, and COMMANDINDENT is the indentation of commands appearing
+  (CASE-INDENT . COMMAND-INDENT)
+where CASE-INDENT is the indentation of the CASE and OTHERWISE
+statements, and COMMAND-INDENT is the indentation of commands appearing
 after the CASE or OTHERWISE command.
 
 Note: Currently a bug exists if:
-  CASEINDENT+COMMANDINDENT != `matlab-indent-level'
+  CASE-INDENT + COMMAND-INDENT != `matlab-indent-level'
 so if you customize these variables, follow the above rule, and you
 should be ok."
   :group 'matlab
@@ -222,11 +222,11 @@ If the value is \\='guess, then we guess if a file has 
end when
                          " function...")))
   :keymap: nil ; empty mode-map
   ;; body of matlab-functions-have-end-minor-mode
-  (let ((type (matlab-guess-script-type)))
+  (let ((mfile-type (matlab-guess-mfile-type)))
     (if matlab-functions-have-end-minor-mode
-        (if (eq type 'empty)
+        (if (eq mfile-type 'empty)
             (setq matlab-functions-have-end 'guess)
-          (setq matlab-functions-have-end type))
+          (setq matlab-functions-have-end mfile-type))
       (setq matlab-functions-have-end nil)
       )
     ;; Depending on the kind of end, lets set other variables.
@@ -244,17 +244,17 @@ If the value is \\='guess, then we guess if a file has 
end when
            ))
     ))
 
-(defvar matlab-last-script-type-guess nil
+(defvar matlab-last-mfile-type-guess nil
   "The last time we guessed the script type, what was it?")
 (defun matlab-last-guess-decl-p ()
   "Return non-nil if our last guess at a script type was function or class."
-  (memq matlab-last-script-type-guess '(function class)))
+  (memq matlab-last-mfile-type-guess '(function class)))
 
-(defun matlab-guess-script-type ()
-  "Guess the type of script this `matlab-mode' file is.
+(defun matlab-guess-mfile-type ()
+  "Guess the type `matlab-mode' file is.
 Returns one of \\='empty, \\='script, \\='function, \\='class."
   (setq
-   matlab-last-script-type-guess
+   matlab-last-mfile-type-guess
    (cond
     ((not buffer-file-name)
      ;; Consider the case of exporting an org-mode '#+begin_src matlab' code 
block.  In this case
@@ -284,42 +284,41 @@ Returns one of \\='empty, \\='script, \\='function, 
\\='class."
                 ;; No function or class - just a script.
                 'script))))))))
 
-(defun matlab-do-functions-have-end-p (&optional no-navigate)
+(defun matlab-do-functions-have-end-p (mfile-type &optional no-navigate)
   "Do functions have end statements based on buffer content?
 Look at the contents of the current buffer and decide if functions
 have end.  If the current value of `matlab-functions-have-end' is
 \\='guess, look @ the buffer.  If the value is t, then return that.
+MFILE-TYPE is from `matlab-guess-mfile-type'.
 Specify NO-NAVIGATE to avoid searching."
   (if (eq matlab-functions-have-end 'guess)
       ;; Lets guess what we think the answer is.
-      (let ((type (matlab-guess-script-type)))
-        (cond ((eq type 'empty)
-               'guess) ;; Keep guessing until we get some code.
-              ((eq type 'script)
-               'script) ;; modern scripts can have functions, and they are 
required to have an end.
-              ((eq type 'class)
-               'class)  ;; classes always have ends.
-              (no-navigate
-               ;; Functions, but don't navigate ... stay in guess mode.
-               'guess)
-              (t
-               ;; functions but do navigate - we need to see if there is an 
end.
-               (save-excursion
-                 (goto-char (point-min))
-                 (matlab-find-code-line)
-                 (let ((matlab-functions-have-end t)) ;; pretend we have ends
-                   (back-to-indentation)
-                   (if (eq (matlab-on-keyword-p) 'decl)
-                       ;; If block scanning returns state, then that means
-                       ;; there is a missing end, so value is nil.
-                       ;; If it returns empty, then there is a matching end.
-                       (if (matlab--scan-block-forward)
-                           nil
-                         t)
-                     ;; Not on a decl, therefore just say nil, since block 
scanning would fail.
-                     nil)
-                   ))))
-        )
+      (cond ((eq mfile-type 'empty)
+             'guess) ;; Keep guessing until we get some code.
+            ((eq mfile-type 'script)
+             'script) ;; modern scripts can have functions, and they are 
required to have an end.
+            ((eq mfile-type 'class)
+             'class)  ;; classes always have ends.
+            (no-navigate
+             ;; Functions, but don't navigate ... stay in guess mode.
+             'guess)
+            (t
+             ;; functions but do navigate - we need to see if there is an end.
+             (save-excursion
+               (goto-char (point-min))
+               (matlab-find-code-line)
+               (let ((matlab-functions-have-end t)) ;; pretend we have ends
+                 (back-to-indentation)
+                 (if (eq (matlab-on-keyword-p) 'decl)
+                     ;; If block scanning returns state, then that means
+                     ;; there is a missing end, so value is nil.
+                     ;; If it returns empty, then there is a matching end.
+                     (if (matlab--scan-block-forward)
+                         nil
+                       t)
+                   ;; Not on a decl, therefore just say nil, since block 
scanning would fail.
+                   nil)
+                 ))))
     ;; Else, just return the default.
     matlab-functions-have-end))
 
@@ -342,48 +341,48 @@ See `matlab-indent-function-body' variable."
     ;; Else, just return the variable.
     matlab-indent-function-body))
 
-(defun matlab-guess-function-indentation ()
+(defun matlab-guess-function-indentation (mfile-type)
   "Look at the current buffer and determine if functions are indented.
-Setup various variables based on what we find."
-  (let ((st (matlab-guess-script-type))
-        )
-    (cond
-     ((not (eq st 'function))
-      ;; Anything not a function should follow the mathworks standard.
-      (setq matlab-indent-function-body 'MathWorks-Standard)
-      )
+Setup various variables based on what we find.
+MFILE-TYPE is from `matlab-guess-mfile-type'."
 
-     ;; If we are guessing, keep guessing (vaguely true)
-     ((eq (matlab-do-functions-have-end-p t) 'guess)
-      (setq matlab-indent-function-body 'guess))
+  (cond
+   ((not (eq mfile-type 'function))
+    ;; Anything not a function should follow the mathworks standard.
+    (setq matlab-indent-function-body 'MathWorks-Standard)
+    )
 
-     ;; Here it is a function, and there are no ends.
-     (t
-      ;; Functions in guess mode we need to find the function decl
-      ;; and then look at the first code line and see if it is indented
-      ;; to guess what to do.
-      (save-excursion
-        (goto-char (point-min))
-        (matlab-find-code-line)
-        ;; We are likely on the fcn line.  Scan to end of it.
-        (matlab-scan-end-of-command)
-        ;; Now find next code line after comments
-        (matlab-find-code-line)
-        ;; If it is indented, then we too will indent.
-        (setq matlab-indent-function-body
-              (if (> (current-indentation) 0)
-                  (if (matlab-do-functions-have-end-p t)
-                      ;; if it indented and we have ends, that is std.
-                      'MathWorks-Standard
-                    ;; no ends but indented, not the standard.
-                    t)
-                (if (matlab-do-functions-have-end-p t)
-                    ;; have ends, not indented, force nil.
-                    nil
-                  ;; no ends and not indented, mw standard
-                  'MathWorks-Standard)))
-        )))
-    ))
+   ;; If we are guessing, keep guessing (vaguely true)
+   ((eq (matlab-do-functions-have-end-p mfile-type t) 'guess)
+    (setq matlab-indent-function-body 'guess))
+
+   ;; Here it is a function, and there are no ends.
+   (t
+    ;; Functions in guess mode we need to find the function decl
+    ;; and then look at the first code line and see if it is indented
+    ;; to guess what to do.
+    (save-excursion
+      (goto-char (point-min))
+      (matlab-find-code-line)
+      ;; We are likely on the fcn line.  Scan to end of it.
+      (matlab-scan-end-of-command)
+      ;; Now find next code line after comments
+      (matlab-find-code-line)
+      ;; If it is indented, then we too will indent.
+      (setq matlab-indent-function-body
+            (if (> (current-indentation) 0)
+                (if (matlab-do-functions-have-end-p mfile-type t)
+                    ;; if it indented and we have ends, that is std.
+                    'MathWorks-Standard
+                  ;; no ends but indented, not the standard.
+                  t)
+              (if (matlab-do-functions-have-end-p mfile-type t)
+                  ;; have ends, not indented, force nil.
+                  nil
+                ;; no ends and not indented, mw standard
+                'MathWorks-Standard)))
+      )))
+  )
 
 (defcustom matlab-fill-fudge 10
   "Number of characters around `fill-column' we can fudge filling.
@@ -525,7 +524,6 @@ point, but it will be restored for them."
     km)
   "The help key map for `matlab-mode' and `matlab-shell-mode'.")
 
-;; mode map
 (defvar matlab-mode-map
   (let ((km (make-sparse-keymap)))
     ;; Navigation Commands
@@ -565,12 +563,6 @@ point, but it will be restored for them."
     km)
   "The keymap used in `matlab-mode'.")
 
-;;; TODO - this menu was all about when emacs didn't always have windows (e18 
?)
-;;  turn this into a regular menu definition.
-(defvar matlab-mode-menu-keymap nil
-  "Keymap used in MATLAB mode to provide a menu.")
-
-;; make a menu keymap
 (easy-menu-define matlab-mode-menu matlab-mode-map "MATLAB menu."
   '("MATLAB"
     ["Start MATLAB" matlab-shell
@@ -603,6 +595,37 @@ point, but it will be restored for them."
      ["Fill Comment" fill-paragraph]
      ["Comment Region" matlab-comment-region t]
      ["Uncomment Region" matlab-uncomment-region t])
+    ("Code Sections"
+     ["Run section" matlab-sections-run-section
+      :active matlab-sections-minor-mode
+      :help "Run the current \"%% section\" in `matlab-shell'."]
+     ["Run prior sections" matlab-sections-run-prior-sections
+      :active matlab-sections-minor-mode
+      :help "Run all \"%% sections\" prior to the current section in 
`matlab-shell'"]
+     ["Move to beginning" matlab-sections-beginning-of-section
+      :active matlab-sections-minor-mode
+      :help "Move `point' to the beginning of the current \"%% section\""]
+     ["Move to end" matlab-sections-end-of-section
+      :active matlab-sections-minor-mode
+      :help "Move `point' to the end of the current \"%% section\""]
+     ["Backward section" matlab-sections-backward-section
+      :active matlab-sections-minor-mode
+      :help "Move point backward to the prior \"%% section\""]
+     ["Forward section" matlab-sections-forward-section
+      :active matlab-sections-minor-mode
+      :help "Move point forward to the next \"%% section\""]
+     ["Mark/select section" matlab-sections-mark-section
+      :active matlab-sections-minor-mode
+      :help "Select the current code selection region by placing the
+mark at the beginning of the \"%% section\" and point at the end of the 
section"]
+     ["Move section up" matlab-sections-move-section-up
+      :active matlab-sections-minor-mode
+      :help "Move the current \"%% section\" up."]
+     ["Move section down" matlab-sections-move-section-down
+      :active matlab-sections-minor-mode
+      :help "Move the current \"%% section\" down."]
+     "--"
+     ["Sections help" matlab-sections-help])
     ("Debug"
      ["Edit File (toggle read-only)" matlab-shell-gud-mode-edit
       :help "Exit MATLAB debug minor mode to edit without exiting MATLAB's K>> 
prompt."
@@ -760,12 +783,12 @@ Ignored comments are lines that start with '% $$$'  or 
'%^'.")
 (defface matlab-pragma-face
   '((t :inherit font-lock-comment-face
        :bold t))
-  "*Face to use for cellbreak %% lines.") ;; TODO: Wrong docstring?
+  "*Face to use for pragma %# lines.")
 
 (defface matlab-math-face
   '((t :inherit font-lock-constant-face
        :slant italic))
-  "*Face to use for cellbreak %% lines.") ;; TODO: Wrong docstring?
+  "*Face to use for math functions.")
 
 ;;; Font Lock MLINT data highlighting
 
@@ -1112,7 +1135,7 @@ This matcher will handle a range of variable features."
 
 (defconst matlab-file-class-font-lock-keywords
   (list
-   ;; Classdefs keyword and the class name
+   ;; Classdef keyword and the class name
    (list (concat "^\\s-*\\(classdef\\)\\_>"
                  matlab-class-attributes-list-re
                  "\\s-*\\(?3:\\sw+\\)")
@@ -1282,14 +1305,14 @@ Convenient template insertion commands:
  \\[tempo-template-matlab-switch] - Insert a SWITCH END statement.
  \\[matlab-insert-next-case] - Insert the next CASE condition in a SWITCH.
  \\[matlab-insert-end-block] - Insert a matched END statement.  With \
-optional ARG, reindent.
+optional ARG, re-indent.
  \\[matlab-stringify-region] - Convert plain text in region to a string \
 with correctly quoted chars.
 
 Variables:
   `matlab-indent-level'         Level to indent blocks.
   `matlab-continuation-indent-level' Level to indent after ... continuation
-  `matlab-case-indent-level'            Level to unindent case statements.
+  `matlab-case-indent-level'            Level to un-indent case statements.
   `matlab-indent-past-arg1-functions'
                                 Regexp of functions to indent past the first
                                   argument on continuation lines.
@@ -1320,10 +1343,6 @@ All Key Bindings:
   ;; and font-lock for comments/strings.
   (matlab-syntax-setup)
   (matlab-scan-setup)
-  (unless noninteractive
-    ;; "matlab %% sections" and has some cost, thus don't activate in batch 
mode.
-    ;; TODO: investigate if a hook be better?
-    (matlab-sections-mode-enable))
 
   ;; Indentation setup.
   (setq indent-tabs-mode nil)
@@ -1363,7 +1382,7 @@ All Key Bindings:
   ;; the function in `write-file' and have the change be saved.
   ;; It also lets us fix mistakes before a `save-and-go'.
   (make-local-variable 'write-contents-functions)
-  (add-hook 'write-contents-functions 'matlab-mode-verify-fix-file-fn)
+  (add-hook 'write-contents-functions 'matlab-mode--write-file-callback)
 
   ;; give each file it's own parameter history
   (make-local-variable 'matlab-shell-save-and-go-history)
@@ -1394,32 +1413,30 @@ All Key Bindings:
   (make-local-variable 'electric-pair-pairs)
   (setq electric-pair-pairs '((39 . 39)))
 
-  ;; If first function is terminated with an end statement, then functions have
-  ;; ends.
-  (if (matlab-do-functions-have-end-p)
-      ;; minor mode now treat's 'guess' as true when passing in 1.
-      (matlab-functions-have-end-minor-mode 1)
-    (matlab-functions-have-end-minor-mode -1))
-
-  ;; When matlab-indent-function-body is set to 'MathWorks-Standard,
-  ;;    - we indent all functions that terminate with an end statement
-  ;;    - old style functions (those without end statements) are not
-  ;;      indented.
-  ;; It is desired that all code be terminate with an end statement.
-  ;;
-  ;; When matlab-indent-function-body is set to 'guess,
-  ;;    - look at the first line of code and if indented, keep indentation
-  ;;      otherwise use MathWorks-Standard
-  ;;
-  (cond
-   ((eq matlab-indent-function-body 'MathWorks-Standard)
+  (let ((mfile-type (matlab-guess-mfile-type)))
+
+    ;; If first function is terminated with an end statement, then functions 
have ends.
+    (if (matlab-do-functions-have-end-p mfile-type)
+        ;; minor mode now treat's 'guess' as true when passing in 1.
+        (matlab-functions-have-end-minor-mode 1)
+      (matlab-functions-have-end-minor-mode -1))
+
+    ;; When matlab-indent-function-body is set to 'MathWorks-Standard,
+    ;;    - we indent all functions that terminate with an end statement
+    ;;    - old style functions (those without end statements) are not
+    ;;      indented.
+    ;; It is desired that all functions be terminate with an end statement.
+    ;;
+    ;; When matlab-indent-function-body is set to 'guess,
+    ;;    - look at the first line of code and if indented, keep indentation
+    ;;      otherwise use MathWorks-Standard
+    ;;
+    (when (eq matlab-indent-function-body 'guess)
+      (matlab-guess-function-indentation mfile-type))
+
+    (matlab-sections-auto-enable-on-mfile-type-fcn mfile-type)
     )
 
-   ((eq matlab-indent-function-body 'guess)
-    (matlab-guess-function-indentation)
-    )
-   )
-
   ;; When leaving matlab-mode, turn off mlint
   (add-hook 'change-major-mode-hook #'matlab-mode-leave)
 
@@ -2053,7 +2070,7 @@ LVL2."
         (save-excursion
           (cond
            ((and
-             ;; CONTINUATION with FUNCTIONs that indent past arg1
+             ;; CONTINUATION with FUNCTION's that indent past arg1
              (eq indent-type 'function-call-cont)
              ;; This checks for our special set of functions.
              (save-excursion
@@ -2109,7 +2126,7 @@ LVL2."
                 ;; current column is location on original line where
                 ;; first bit of text is, so line up with that.
                 (setq tmp (current-column))
-                ;; TODO - this disables indentation MAXs
+                ;; TODO - this disables indentation MAX
                 ;;        if we really want to be rid of this
                 ;;        we can dump a bunch of logic above too.
                 ;; apply the maximum limits.
@@ -2224,7 +2241,7 @@ LVL1."
           (setq depthchange (1- depthchange)))
 
         ;; Remove 1 from the close count if there is an END on the beginning
-        ;; of this line, since in that case, the unindent has already happened.
+        ;; of this line, since in that case, the un-indent has already 
happened.
         (when end (setq depthchange (1+ depthchange)))
 
         ;; Calculate the suggested indentation.
@@ -2849,25 +2866,28 @@ Returns a list: \(HERE-BEG HERE-END THERE-BEG THERE-END 
MISMATCH)"
 
 ;;; Verify / Auto-fix ============================================
 
-(defun matlab-mode-verify-fix-file-fn ()
-  "Verify the current buffer from `write-contents-hooks'."
-  (if matlab-verify-on-save-flag
-      (matlab-mode-verify-fix-file (> (point-max)
-                                      matlab-block-verify-max-buffer-size)))
-  ;; Always return nil.
+(defun matlab-mode--write-file-callback ()
+  "Called from `write-contents-functions'.
+When `matlab-verify-on-save-flag' is true, run `matlab-mode-verify-fix-file'.
+Enable/disable `matlab-sections-minor-mode' based on file content."
+  (let ((mfile-type (matlab-guess-mfile-type)))
+    (when matlab-verify-on-save-flag
+      (matlab-mode-verify-fix-file mfile-type))
+    (matlab-sections-auto-enable-on-mfile-type-fcn mfile-type))
+  ;; write-contents-functions expect the callback to return nil for normal 
save.
   nil)
 
-(defun matlab-mode-verify-fix-file (&optional fast)
+(defun matlab-mode-verify-fix-file (&optional mfile-type)
   "Verify the current buffer satisfies all M things that might be useful.
 We will merely loop across a list of verifiers/fixers in
 `matlab-mode-verify-fix-functions'.
-If optional FAST is non-nil, do not perform usually lengthy checks."
+Optional MFILE-TYPE is the result of `matlab-guess-mfile-type'."
   (interactive)
   (save-excursion
     ;; Always re-validate if functions have end.
-    (matlab-mode-vf-guess-functions-have-end fast)
+    (matlab-mode-vf-guess-functions-have-end mfile-type)
     ;; Loop over the options.
-    (mapc (lambda (func) (funcall func fast))
+    (mapc (lambda (func) (funcall func))
           matlab-mode-verify-fix-functions))
   (when (called-interactively-p 'interactive)
     (message "Done.")))
@@ -2875,61 +2895,59 @@ If optional FAST is non-nil, do not perform usually 
lengthy checks."
 ;;
 ;; Add more auto verify/fix functions here!
 ;;
-(defun matlab-mode-vf-guess-functions-have-end (&optional fast)
+(defun matlab-mode-vf-guess-functions-have-end (&optional mfile-type)
   "Look at the current buffer state and decide determine if functions have end.
 If this is already known, no action is taken.
-FAST is ignored."
-  (ignore fast)
-  (let ((filetype (matlab-guess-script-type)))
+Optional MFILE-TYPE is the result of `matlab-guess-mfile-type'."
+  (when (not mfile-type)
+    (setq mfile-type (matlab-guess-mfile-type)))
 
-    ;; Lets if the file if we were in still doesn't know what to do
-    ;; a bout ends, and re-assert what we should do.
-    (cond
-     ;; If the file is empty of code (from before, or just now)
-     ;; then optimize out this step.
-     ((eq filetype 'empty)
-      ;; If user deleted content, go back into guess mode.
-      (setq matlab-functions-have-end 'guess)
-      (matlab-functions-have-end-minor-mode 1)
-      )
+  ;; Lets if the file if we were in still doesn't know what to do
+  ;; a bout ends, and re-assert what we should do.
 
-     ;; If there is just bad syntax somewhere, skip it with a notice.
-     ((save-excursion (goto-char (point-max)) (matlab-in-list-p))
-      (setq matlab-functions-have-end 'guess)
-      (matlab-functions-have-end-minor-mode 1)
-      (message "Unterminated list - skipping block check"))
-
-     ;; If we are in guess mode, but user added content, we can
-     ;; not have a fresh new guess.
-     ((eq matlab-functions-have-end 'guess)
-      (let ((guess (matlab-do-functions-have-end-p 'no-navigate)))
-        (if guess (matlab-functions-have-end-minor-mode 1)
-          (matlab-functions-have-end-minor-mode -1)))
-      )
+  (cond
+   ;; If the file is empty of code (from before, or just now)
+   ;; then optimize out this step.
+   ((eq mfile-type 'empty)
+    ;; If user deleted content, go back into guess mode.
+    (setq matlab-functions-have-end 'guess)
+    (matlab-functions-have-end-minor-mode 1)
+    )
 
-     ;; If we are in no-end mode, BUT the filetype is wrong, say something.
-     ((and (not matlab-functions-have-end) (or (eq filetype 'script) (eq 
filetype 'class)))
-      (message "Type of file detected no longer matches 
`matlab-functions-have-end' of nil, assume t.")
-      (matlab-functions-have-end-minor-mode 1)
-      (sit-for 1)
-      )
+   ;; If there is just bad syntax somewhere, skip it with a notice.
+   ((save-excursion (goto-char (point-max)) (matlab-in-list-p))
+    (setq matlab-functions-have-end 'guess)
+    (matlab-functions-have-end-minor-mode 1)
+    (message "Unterminated list - skipping block check"))
+
+   ;; If we are in guess mode, but user added content, we can
+   ;; not have a fresh new guess.
+   ((eq matlab-functions-have-end 'guess)
+    (let ((guess (matlab-do-functions-have-end-p mfile-type 'no-navigate)))
+      (if guess (matlab-functions-have-end-minor-mode 1)
+        (matlab-functions-have-end-minor-mode -1)))
+    )
 
-     ;; If functions have end but the style changes, re-up the lighter on the 
minor mode.
-     ;; note, we can ignore that 'empty == 'guess b/c handled earlier.
-     ((and matlab-functions-have-end (not (eq matlab-functions-have-end 
filetype)))
-      (matlab-functions-have-end-minor-mode 1))
+   ;; If we are in no-end mode, BUT the mfile-type is wrong, say something.
+   ((and (not matlab-functions-have-end) (or (eq mfile-type 'script) (eq 
mfile-type 'class)))
+    (message "Type of file detected no longer matches 
`matlab-functions-have-end' of nil, assume t.")
+    (matlab-functions-have-end-minor-mode 1)
+    (sit-for 1)
+    )
 
-     ;; If the variable was specified and file is not empty, then do nothing.
-     ;; TODO - maybe we should force to t for scripts and classes?
+   ;; If functions have end but the style changes, re-up the lighter on the 
minor mode.
+   ;; note, we can ignore that 'empty == 'guess b/c handled earlier.
+   ((and matlab-functions-have-end (not (eq matlab-functions-have-end 
mfile-type)))
+    (matlab-functions-have-end-minor-mode 1))
 
-     ) ;; end cond
+   ;; If the variable was specified and file is not empty, then do nothing.
+   ;; TODO - maybe we should force to t for scripts and classes?
 
-    ))
+   ) ;; end cond
+  )
 
-(defun matlab-mode-vf-functionname (&optional fast)
-  "Verify/Fix the function name of this file.
-Optional argument FAST is ignored."
-  (ignore fast)
+(defun matlab-mode-vf-functionname ()
+  "Verify/Fix the function name of this file."
   (matlab-navigation-syntax
     (goto-char (point-min))
     (matlab-find-code-line)
@@ -2945,10 +2963,8 @@ Optional argument FAST is ignored."
           (delete-region (nth 2 fcn) (nth 3 fcn))
           (insert bn))))))
 
-(defun matlab-mode-vf-classname (&optional fast)
-  "Verify/Fix the class name of this file.
-Optional argument FAST is ignored."
-  (ignore fast)
+(defun matlab-mode-vf-classname ()
+  "Verify/Fix the class name of this file."
   (matlab-navigation-syntax
     (goto-char (point-min))
     (matlab-find-code-line)
@@ -2964,14 +2980,11 @@ Optional argument FAST is ignored."
           (delete-region (nth 2 class) (nth 3 class))
           (insert bn))))))
 
-(defun matlab-mode-vf-add-ends (&optional fast)
-  "Verify/Fix adding ENDS to functions.
-Optional argument FAST skips this test in fast mode."
+(defun matlab-mode-vf-add-ends ()
+  "Verify/Fix adding ENDS to functions."
   ;; We used to do extra checking here, but now we do
   ;; checking in the verifier
-  (unless fast
-    (matlab-mode-vf-block-matches-forward nil t)
-    ))
+  (matlab-mode-vf-block-matches-forward nil t))
 
 (defun matlab-mode-vf-block-matches-forward (&optional fast addend)
   "Verify/Fix unterminated (or un-ended) blocks.
@@ -2986,12 +2999,12 @@ by `matlab-mode-vf-add-ends'"
         (exit nil)
         ;; lets avoid asking questions based on id of this file
         ;; and if ends are optional in the first place.
-        (filetype (matlab-guess-script-type))
+        (mfile-type (matlab-guess-mfile-type))
         )
 
     ;; Before checking syntax, lets re-look at the file if we were in
     ;; guess mode and re-assert what we should do.
-    (when (or (eq filetype 'empty)
+    (when (or (eq mfile-type 'empty)
               (save-excursion (goto-char (point-max)) (matlab-in-list-p)))
       ;; In a bad state - go fast.
       (setq fast t))
@@ -3022,7 +3035,7 @@ by `matlab-mode-vf-add-ends'"
                       (matlab-mode-vf-add-end-to-this-block)
                     ;; Else, mark this buffer as not needing ends,
                     ;; but ONLY if a function buffer
-                    (when (eq filetype 'function)
+                    (when (eq mfile-type 'function)
                       (if (matlab-mode-highlight-ask
                            s e
                            "Should functions have end in this file?")
@@ -3081,19 +3094,19 @@ 
switch\\|otherwise\\|case\\|break\\|if\\|else\\|end\\|return\\|disp\\|\
 $\\|%\\)"
   "Regular expression used to detect if a semicolon is needed at the end of a 
line.")
 
-(defun matlab-mode-vf-quiesce-buffer (&optional fast)
+(defun matlab-mode-vf-quiesce-buffer ()
   "Find all commands that do not end in ;, and add one.
 This has the effect of removing any extraneous output that may not be
-desired.  Optional argument FAST is not used."
+desired."
   (interactive)
-  (ignore fast)
   (save-excursion
     (push-mark)
     (goto-char (point-min))
     (let ((msgpos 0) (dir .2))
       (while (not (save-excursion (end-of-line) (eobp)))
         (message (aref [ "Scanning o...." "Scanning .o..." "Scanning ..o.."
-                         "Scanning ...o." "Scanning ....o" ] (floor msgpos)))
+                         "Scanning ...o." "Scanning ....o" ]
+                       (floor msgpos)))
         (setq msgpos (+ msgpos dir))
         (if (or (> msgpos 5) (< msgpos 0)) (setq dir (- dir)
                                                  msgpos (+ (* 2 dir) msgpos)))
@@ -3105,7 +3118,6 @@ desired.  Optional argument FAST is not used."
         (forward-line 1))))
   (message "Scanning .... done"))
 
-
 
 ;;; matlab-mode debugging =====================================================
 
@@ -3140,19 +3152,19 @@ desired.  Optional argument FAST is not used."
 (provide 'matlab)
 ;;; matlab.el ends here
 
-;; LocalWords:  Wette mwette edu Ludlam eludlam defconst compat easymenu 
defcustom mfiles objc elec
-;; LocalWords:  CASEINDENT COMMANDINDENT sexp sg Fns Alist symbolp defun mmode 
setq decl memq progn
-;; LocalWords:  vf functionname booleanp keymap torkel fboundp gud ebstop 
mlgud ebclear mw SPDX Uwe
-;; LocalWords:  ebstatus mlg mlgud's subjob featurep defface commanddual 
cellbreak cellbreaks cdr
-;; LocalWords:  animatedline rlim thetalim cartesian stackedplot bubblechart 
swarmchart wordcloud
-;; LocalWords:  bubblecloud heatmap parallelplot fcontour anim polarplot 
polarscatter polarhistogram
-;; LocalWords:  polarbubblechart goeplot geoscatter geobubble geodensity 
fimplicit fsurf tiledlayout
-;; LocalWords:  nexttile uicontext mld flintmax keywordlist mapconcat vardecl 
flb fle blockmatch bol
-;; LocalWords:  eol tm newmdata Classdefs dem Imenu imenu boundp alist 
reindent unindent vers Sexp's
-;; LocalWords:  Defuns fn minibuffer eobp autoend noerror returnme Unstarted 
parentblock defuns bobp
-;; LocalWords:  noprogress minibufferp bolp eolp calc funcall ci sem prevcmd 
DEPTHNUMBER blockstart
-;; LocalWords:  blockmid blockendless blockend CTXT listp fc pc boc parencol 
parenchar parenpt tmp
-;; LocalWords:  parenindent parenopt FUNCTIONs MAXs prev startpnt depthchange 
bc emacsen afterd md
-;; LocalWords:  befored okpos startlst endlst ellipsify noreturn hs tc hc 
startsym endsym mapc func
-;; LocalWords:  filetype bn nondirectory scanstate sexp's nosemi msgpos 
fullindent nexti defn sw
-;; LocalWords:  classdef's aref parens Brauer oub ucm docstring ppss
+;; LocalWords:  SPDX Wette mwette edu Ludlam eludlam Uwe Brauer oub ucm 
defconst compat easymenu dem
+;; LocalWords:  elec defcustom mfiles objc sexp sg Fns Alist symbolp defun 
mfile
+;; LocalWords:  keymap setq decl memq classdef's progn mw vf functionname 
booleanp torkel fboundp
+;; LocalWords:  gud ebstop mlgud ebclear ebstatus mlg mlgud's subjob featurep 
defface commanddual
+;; LocalWords:  docstring cdr animatedline rlim thetalim cartesian stackedplot 
bubblechart
+;; LocalWords:  swarmchart wordcloud bubblecloud heatmap parallelplot fcontour 
anim polarplot Imenu
+;; LocalWords:  polarscatter polarhistogram polarbubblechart goeplot 
geoscatter geobubble geodensity
+;; LocalWords:  fimplicit fsurf tiledlayout nexttile uicontext mld flintmax 
keywordlist mapconcat
+;; LocalWords:  vardecl flb fle tmp blockmatch md tm newmdata repeat:md sw 
imenu boundp aref alist
+;; LocalWords:  vers Sexp's Defuns parens minibuffer eobp autoend noerror 
returnme Unstarted defuns
+;; LocalWords:  bobp noprogress minibufferp bolp eolp calc funcall ci sem 
prevcmd DEPTHNUMBER prev
+;; LocalWords:  blockstart blockmid blockendless blockend CTXT listp fc pc boc 
parencol parenchar
+;; LocalWords:  parenpt parenindent parenopt FUNCTION's EOL depthchange bc eol 
fn emacsen afterd
+;; LocalWords:  befored okpos startlst endlst ellipsify ppss noreturn hs tc hc 
startsym endsym mapc
+;; LocalWords:  func bn nondirectory scanstate sexp's nosemi msgpos nexti defn
+
diff --git a/tests/metest.el b/tests/metest.el
index 86d5d8a5f9..de500714ce 100644
--- a/tests/metest.el
+++ b/tests/metest.el
@@ -122,8 +122,8 @@
           (let ((st-expect (intern (match-string-no-properties 1)))
                 (end-expect (intern (match-string-no-properties 2)))
                 (indent-expect (intern (match-string-no-properties 3)))
-                (st-actual (matlab-guess-script-type))
-                (end-actual (matlab-do-functions-have-end-p))
+                (st-actual (matlab-guess-mfile-type))
+                (end-actual (matlab-do-functions-have-end-p 
(matlab-guess-mfile-type)))
                 (indent-actual (matlab-indent-function-body-p))
                 )
             (unless (eq st-actual st-expect)
@@ -612,7 +612,11 @@ Do error checking to provide easier debugging."
   (let ((F (expand-file-name file met-testfile-path)))
     (unless (file-exists-p F)
       (error "Test file %s does not exist in %s" file met-testfile-path))
-    (find-file-noselect F)))
+    (let ((buf (find-file-noselect F)))
+      (when (string= file "stringtest.m")
+        (with-current-buffer buf
+          (matlab-sections-minor-mode 1)))
+      buf)))
 
 (defvar metest-error-context-lines 4)
 (defun metest-error (&rest args)
diff --git a/tests/mstest-sections.el b/tests/mstest-sections.el
new file mode 100644
index 0000000000..708ea22bd2
--- /dev/null
+++ b/tests/mstest-sections.el
@@ -0,0 +1,215 @@
+;;; mstest-sections.el --- MATLAB Shell sections tests -*- lexical-binding: t; 
-*-
+
+;; Copyright 2025 Free Software Foundation, Inc.
+;; Author: John Ciolfi <john.ciolfi...@gmail.com>
+
+;; 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 of the
+;; License, 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 this program.  If not, see https://www.gnu.org/licenses/.
+
+;;; Commentary:
+;;    Test matlab-sections.el using ./sections.m
+
+;;; Code:
+
+(require 'matlab-sections)
+
+(declare-function mstest-get-command-output "mstest.el")
+
+(defun mstest-sections-header ()
+  "Exercise the regexp that identifies the \"%% section\" header."
+  (let ((header-comments
+         '("%% description of header" ;; typical section header
+           "%%"   ;; section header without a description
+           "%%  " ;; section header without a description and ending in spaces
+           " \t %% description with starting spaces and tabs"
+           "%% description can end with spaces and tabs  \t  "
+           "%% description ending in 1%" ;; ending in <CHAR>% is a section 
header
+           ))
+        (non-header-comments
+         '("% not a section header"
+           "% this is %% not a section header"
+           "%%% using three or more percents is not a section header"
+           "%%%%%%%%%%%%%%%%%%%" ;; comment block
+           "%% comment block %%" ;; ending in % is a comment block
+           "%%%%%%%%%%%%%%%%%%%" ;; comment block
+           )))
+    (dolist (header-comment header-comments)
+      (when (not (string-match matlab-sections-section-break-regexp 
header-comment))
+        (user-error "Failed to match \"%s\" as a section header comment" 
header-comment)))
+
+    (dolist (non-header-comment non-header-comments)
+      (when (string-match matlab-sections-section-break-regexp 
non-header-comment)
+        (user-error "Matched \"%s\" as a section header comment when it should 
have failed to match"
+                    non-header-comment)))))
+
+(defun mstest-sections ()
+  "Test \"%% section\" support."
+
+  (message "TEST: running (mstest-sections)")
+
+  (mstest-sections-header)
+  
+  (save-excursion
+    (let ((sections-buf (find-file "sections.m")))
+
+      ;; We run in batch, so need to explicitly enable sections
+      (matlab-sections-mode-enable)
+      (when (not matlab-sections-minor-mode)
+        (user-error "Failed to start matlab-sections-minor-mode"))
+
+      (let ((test-point-desc "matlab-sections test case point-min backup"))
+        ;;  at point-min, we shouldn't get a lisp error if we try to backup
+        (goto-char (point-min))
+        (matlab-sections-backward-section)
+        (when (not (= (point) (point-min)))
+          (user-error "Unexpected result for %s" test-point-desc))
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case point-min forward"))
+        (matlab-sections-forward-section)
+        (when (not (looking-at "^sectionOneA = 1"))
+          (user-error "Unexpected result for %s, point=%d" test-point-desc 
(point)))
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case end-of-section"))
+        (matlab-sections-end-of-section)
+        (forward-line -1)
+        (when (not (looking-at "^sectionOneB = 1"))
+          (user-error "Unexpected result for %s" test-point-desc))
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case beginning-of-section"))
+        (matlab-sections-beginning-of-section)
+        (when (not (looking-at "^sectionOneA = 1"))
+          (user-error "Unexpected result for %s" test-point-desc))
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case mark section one"))
+        (save-excursion
+          (matlab-sections-mark-section)
+          (let ((mark-start (mark))
+                (mark-end (point)))
+            (when (or (not (= mark-start 36))
+                      (not (= mark-end 85)))
+              (user-error "Unexpected result for %s" test-point-desc))
+            (deactivate-mark)
+            (message "PASS: %s" test-point-desc))))
+
+      (let ((test-point-desc "matlab-sections test case move section down"))
+        (matlab-sections-beginning-of-section)
+        (matlab-sections-move-section-down)
+        (when (not (string= (buffer-substring (point-min) (point-max))
+                            "\
+sectionZeroA = 1
+sectionZeroB = 1
+
+%% section two
+
+sectionTwoA = 1
+sectionTwoB = 1
+%% section one
+
+sectionOneA = 1
+sectionOneB = 1
+
+"))
+          (user-error "Unexpected result for %s" test-point-desc))
+        (set-buffer-modified-p nil)
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case move section up"))
+        (matlab-sections-move-section-up)
+        (when (not (string= (buffer-substring (point-min) (point-max))
+                            "\
+sectionZeroA = 1
+sectionZeroB = 1
+
+%% section one
+
+sectionOneA = 1
+sectionOneB = 1
+
+%% section two
+
+sectionTwoA = 1
+sectionTwoB = 1
+"))
+          (user-error "Unexpected result for %s" test-point-desc))
+        (set-buffer-modified-p nil)
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case forward to section 
two"))
+        (matlab-sections-forward-section)
+        (when (not (looking-at "^sectionTwoA = 1"))
+          (user-error "Unexpected result for %s" test-point-desc))
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case backup to section 
one"))
+        (save-excursion ;; save-excursion, so we remain at section two when 
test case is done
+          (matlab-sections-backward-section)
+          (when (not (looking-at "^sectionOneA = 1"))
+            (user-error "Unexpected result for %s" test-point-desc))
+          (message "PASS: %s" test-point-desc)))
+
+      (let ((test-point-desc "matlab-sections test case run section two")
+            (got (mstest-get-command-output 'matlab-sections-run-section))
+            (expected "
+sectionTwoA =
+
+     1
+
+
+sectionTwoB =
+
+     1
+"))
+        (when (not (string= got expected))
+          (user-error "Unexpected result for %s. Got '%s' expected '%s'" 
test-point-desc
+                      got expected))
+        (message "PASS: %s" test-point-desc))
+
+      (let ((test-point-desc "matlab-sections test case run prior sections, 
zero and one")
+            (got (mstest-get-command-output 
'matlab-sections-run-prior-sections))
+            (expected "
+sectionZeroA =
+
+     1
+
+
+sectionZeroB =
+
+     1
+
+
+sectionOneA =
+
+     1
+
+
+sectionOneB =
+
+     1
+"))
+        (when (not (string= got expected))
+          (user-error "Unexpected result for %s. Got '%s' expected '%s'" 
test-point-desc
+                      got expected))
+        (message "PASS: %s" test-point-desc))
+
+      (kill-buffer sections-buf)))
+
+  (message "PASSED: (mstest-sections)"))
+
+(provide 'mstest-sections)
+;;; mstest-sections.el ends here
+
+;; LocalWords:  gmail defun buf
diff --git a/tests/mstest.el b/tests/mstest.el
index 00309ace92..d31dc318a9 100644
--- a/tests/mstest.el
+++ b/tests/mstest.el
@@ -40,6 +40,9 @@
 (require 'matlab-shell)
 (require 'matlab-topic)
 
+(add-to-list 'load-path ".")
+(require 'mstest-sections)
+
 ;;; Code:
 (defun mstest-run-all-tests ()
   "Run all the test cases in this test file."
@@ -57,6 +60,7 @@
 
   (mstest-start)
   (mstest-capture)
+  (mstest-sections)
   (mstest-completion)
   (mstest-error-parse)
   (mstest-debugger)
@@ -147,7 +151,9 @@
           (mstest-savestate)
           (message "Expected: [%S]" exp)
           (message "Found: [%S]" txt)
-          (user-error "'WHICH TEST: ls' failed"))))))
+          (user-error "'WHICH TEST: ls' failed")))
+
+      (goto-char (point-max)))))
 
 ;;; Command Sending Tests
 (defun mstest-completion ()
diff --git a/tests/sections.m b/tests/sections.m
new file mode 100644
index 0000000000..e800d36076
--- /dev/null
+++ b/tests/sections.m
@@ -0,0 +1,12 @@
+sectionZeroA = 1
+sectionZeroB = 1
+
+%% section one
+
+sectionOneA = 1
+sectionOneB = 1
+
+%% section two
+
+sectionTwoA = 1
+sectionTwoB = 1

Reply via email to