branch: externals/matlab-mode commit f744cc2bd2fa2b8402a5d3d4229274304033a1d5 Author: John Ciolfi <john.ciolfi...@gmail.com> Commit: John Ciolfi <john.ciolfi...@gmail.com>
matlab-sections: display message when running sections Also add help on sections. --- README.org | 14 ++-------- doc/matlab-code-sections.org | 66 ++++++++++++++++++++++++++++++++++++++++++++ matlab-sections.el | 43 +++++++++++++++++++++++------ matlab.el | 10 ++++--- toolbox/emacsrunregion.m | 32 +++++++++++++++++---- 5 files changed, 137 insertions(+), 28 deletions(-) diff --git a/README.org b/README.org index abd4df2ea0..b1c2b34292 100644 --- a/README.org +++ b/README.org @@ -44,21 +44,13 @@ #+end_example -5. *Code sections* support for MATLAB script files. Script files contain one or more commands, such - as variable assignements, function calls, etc. Script files differ from declaration files such - as those declaring function's or classdef's. 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"/ header comments. +5. *Code sections* support for MATLAB script files. See [[file:doc/matlab-code-sections.org][doc/matlab-code-sections.org]]. - - 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. + - After visiting a MATLAB script, you have a *"MATLAB -> Code Sections"* menu and key bindings + which lets you 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"*. - 6. *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 diff --git a/doc/matlab-code-sections.org b/doc/matlab-code-sections.org new file mode 100644 index 0000000000..8524367862 --- /dev/null +++ b/doc/matlab-code-sections.org @@ -0,0 +1,66 @@ +# File: doc/matlab-code-sections.org + +#+startup: showall +#+options: toc:nil + +# Copyright 2025 Free Software Foundation, Inc. + +* MATLAB Code Sections in Script *.m Files + +MATLAB script files contain one or more commands, such as variable assignments, function calls, etc. +Script files differ from declaration files such as those declaring function's or classdef's. When +working with script files, 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"/ +header comments. + +An example of a script file is ~basic_script.m~: + +#+begin_src matlab + %% First section + + a = 1; + b = 2; + + %% Second section + + c = a + b; + disp(['c = ', num2str(c)]); +#+end_src + +When you visit a script.m file, you will have a *MATLAB -> Code Sections* menu. Help from within +Emacs is available from *"MATLAB -> Code Sections -> Help"* menu item. You can use the menu or key +bindings to modify or run your script. + +#+begin_example + C-c C-SPC Mark/select section. + + C-c C-<up> Move point backward to the prior "% section" + C-c C-<down> Move point forward to the next "% section" + C-c C-<left> Move point to the beginning of the current "%% section" + C-c C-<right> Move point to the end of the current "%% section" + + C-c M-<up> Move the current "%% section" up + C-c M-<down> Move the current "%% section" down + + C-c C-<return> Run the current "%% section" + C-c M-<return> Run all "%% sections" prior to the current section +#+end_example + +Sections are run using the =*MATLAB*= shell buffer created using =M-x matlab-shell= on Unix and the +attached MATLAB using the [[file:matlab-netshell-for-windows.org][matlab netshell on Windows]]. When a section is run, you will see in the +MATLAB Command Window: + +#+begin_example + emacsrunregion('/path/to/your/script.m', startChar, endChar) + + <text displayed by your script.m> +#+end_example + +The sections are run asynchronously. After sending the emacsrunregion command to MATLAB, control is +returned to Emacs. In MATLAB, you'll see the ">>" prompt reappear when emacsrunregion is complete. + +** Customizations + +If you'd like to use super (aka Windows) key bindings instead of the above key bindings, you can + + : M-x customize-variable RET matlab-sections-use-super-key RET diff --git a/matlab-sections.el b/matlab-sections.el index 2be88ba82d..ed88dfe8fe 100644 --- a/matlab-sections.el +++ b/matlab-sections.el @@ -132,6 +132,25 @@ the command `matlab-sections-minor-mode' to turn matlab-sections mode on." ;; Function to obtain range of current code section +(defun matlab-sections--get-heading (&optional range) + "Return the \"%% descrition\" heading or nil if not in a code section. +RANGE is (START-PT . END-PT) of the section or nil. If nil, we'll +determine the RANGE." + (when (not range) + (setq range (matlab-sections-range-function))) + (save-excursion + (save-restriction + (widen) + (goto-char (car range)) + (when (not (looking-at "^[[:blank:]]*%%[[:blank:]]*\\(.*\\)$")) + (error "Assert - failed to match section heading at point %S" (point))) + (let ((heading (string-trim (match-string-no-properties 1)))) + (when (string= heading "") + (setq heading "Empty section heading")) + (setq heading (concat heading (format " (line %d)" + (line-number-at-pos))))) + ))) + (defun matlab-sections-range-function () "Return range (START-PT . END-PT) of current MATLAB code section. nil is returned if there is no code section." @@ -293,11 +312,14 @@ Return `point'." "Run the current \"%% section\" in `matlab-shell'." (interactive) (let ((rng (matlab-sections-range-function))) - (save-excursion - (save-restriction - (widen) - (save-window-excursion - (matlab-shell-run-region (car rng) (cdr rng))))))) + (if rng + (save-excursion + (save-restriction + (widen) + (save-window-excursion + (message "Running section: %s" (matlab-sections--get-heading rng)) + (matlab-shell-run-region (car rng) (cdr rng))))) + (message "Not in a \"%% code section\"")))) (define-obsolete-function-alias 'matlab-sections-run-till-point #'matlab-sections-run-prior-sections "6.3") @@ -312,9 +334,14 @@ Does not run the section the point is in." (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))))))) + (if (< (point) current-section-start-point) + (progn + (save-excursion + (goto-char current-section-start-point) + (message "Running sections prior to: %s" (matlab-sections--get-heading))) + (save-window-excursion + (matlab-shell-run-region (point) current-section-start-point))) + (message "No prior \"%% code sections\"")))))) (declare-function matlab-mode "matlab.el") diff --git a/matlab.el b/matlab.el index dd8235b9b4..3b73f54775 100644 --- a/matlab.el +++ b/matlab.el @@ -602,16 +602,18 @@ point, but it will be restored for them." ("Code Sections" ["Run section" matlab-sections-run-section :active matlab-sections-minor-mode - :help "Run the current \"%% section\" in `matlab-shell'."] + :help "Run the current \"%% section\" in +matlab-shell (Unix) or matlab-netshell (Windows)"] ["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'"] + :help "Run all \"%% sections\" prior to the current section in +matlab-shell (Unix) or matlab-netshell (Windows)"] ["Move to beginning" matlab-sections-beginning-of-section :active matlab-sections-minor-mode - :help "Move `point' to the beginning of the current \"%% section\""] + :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\""] + :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\""] diff --git a/toolbox/emacsrunregion.m b/toolbox/emacsrunregion.m index cce7e2d1ee..5517cd8f81 100644 --- a/toolbox/emacsrunregion.m +++ b/toolbox/emacsrunregion.m @@ -25,7 +25,7 @@ function emacsrunregion(file, startchar, endchar) end % Now figure out if shortFileName is on the path. - [ fullFilePath, shortFileName ] = fileparts(file); + [fullFilePath, shortFileName, extension] = fileparts(file); onpath = ~isempty(which(shortFileName)); % If not on the path, temporarily switch to that directory so it and an files it references are @@ -36,9 +36,31 @@ function emacsrunregion(file, startchar, endchar) cleanup = onCleanup(@()cd(oldpath)); end - txt = fileread(file); - evalTxt = txt(startchar:min(endchar,length(txt))); - evalin('base',evalTxt); + fileContents = fileread(file); + + endchar = min(endchar, length(fileContents)); + evalTxt = fileContents(startchar:endchar); + evalin('base', evalTxt); + + % See if startchar and endchar are on the first column of a lines and if so display that. Note, + % fileContents can contain POSIX newlines (LF) or be Windows CRFL (13, 10) line endings. + if (startchar == 1 || fileContents(startchar-1) == newline) && ... + regexp(fileContents(endchar), '[\r\n]', 'once') + startLineNum = length(strfind(fileContents(1:startchar), newline)) + 1; + endLineNum = length(strfind(fileContents(1:endchar), newline)); + if fileContents(endchar) == 13 || endchar == length(fileContents) + % Looking at CR or end-of-file + endLineNum = endLineNum + 1; + end + + regionInfo = sprintf('lines %d to %d', startLineNum, endLineNum); + else + regionInfo = sprintf('chars %d to %d', startchar, endchar); + end + + % TODO - enable this display after updating tests to pass on Unix. + % fprintf(1, 'emacsrunregion: finished running %s%s %s\n', ... + % shortFileName, extension, regionInfo); end -% LocalWords: Ludlam STARTCHAR ENDCHAR +% LocalWords: STARTCHAR ENDCHAR