Merge the hairycode branch into master. Start testing.
This commit is contained in:
commit
3fbc97b3f2
|
@ -6,6 +6,8 @@
|
|||
.\#*
|
||||
*.orig
|
||||
*.rej
|
||||
*.dat
|
||||
|
||||
# matlab-load.el is generated
|
||||
matlab-load.el
|
||||
parse
|
2
Makefile
2
Makefile
|
@ -16,7 +16,7 @@ LOADPATH= ./
|
|||
LOADDEFS=matlab-load.el
|
||||
LOADDIRS=.
|
||||
misc_MISC=ChangeLog ChangeLog.old1 ChangeLog.old2 INSTALL README dl_emacs_support.m
|
||||
lisp_LISP=matlab-compat.el matlab.el matlab-shell.el matlab-shell-gud.el matlab-netshell.el matlab-complete.el matlab-cgen.el matlab-publish.el matlab-topic.el mlint.el tlc.el linemark.el matlab-maint.el
|
||||
lisp_LISP=matlab-compat.el matlab-syntax.el matlab-scan.el matlab.el matlab-shell.el matlab-shell-gud.el matlab-netshell.el matlab-complete.el matlab-cgen.el matlab-publish.el matlab-topic.el mlint.el tlc.el linemark.el matlab-maint.el
|
||||
cedet_LISP=semantic-matlab.el semanticdb-matlab.el srecode-matlab.el cedet-matlab.el company-matlab-shell.el
|
||||
VERSION=4.0
|
||||
DISTDIR=$(top)matlab-emacs-$(VERSION)
|
||||
|
|
138
NEWS.org
138
NEWS.org
|
@ -1,5 +1,141 @@
|
|||
* Changes and New Features in matlab-emacs
|
||||
|
||||
** New in 5.0
|
||||
|
||||
*** Syntax tables / Strings and Comments / Font lock
|
||||
|
||||
Command and String syntax handling is now managed using syntax-table customization
|
||||
|
||||
This results in:
|
||||
* More flavors of syntax highlighting around commands and strings, including all of:
|
||||
* strings, unterminated strings, commanddual strings
|
||||
* comments, cellbreak comments, pragma comments, ignored comments, ellipssis
|
||||
* Accurate differentiation between 'char arrays' and "strings" and quoted charts.
|
||||
* Performance improvements for comment/string parsing.
|
||||
|
||||
There is a new shorter 'ignore' comment type that starts with: %^
|
||||
|
||||
In addition, font lock of keywords is now more robust, with keywords not being
|
||||
highlighted when they are not being used in the correct scope.
|
||||
|
||||
*** Syntactic block navigation
|
||||
|
||||
With proper syntax table support now available, built-in emacs commands that depend on
|
||||
sexp now work, such as:
|
||||
* up-list
|
||||
* forward-sexp
|
||||
* kill-sexp
|
||||
* mark-sexp
|
||||
|
||||
In addition, commands that work with defuns now all work correctly, such as:
|
||||
* mark-defun
|
||||
* narrow-to-defun
|
||||
|
||||
All custom commands that used to implement these syntax behaviors have been removed, or
|
||||
had their bindings removed, including:
|
||||
* matlab-beginning-of-command
|
||||
* matlab-end-of-command
|
||||
* matlab-forward-sexp
|
||||
* matlab-backward-sexp
|
||||
* matlab-indent-sexp
|
||||
* matlab-beginning-of-defun
|
||||
* matlab-end-of-defn
|
||||
|
||||
In addition syntactic block navigation is faster, where very large files can now be navigated
|
||||
in fractions of a second that used to take a few minutes.
|
||||
|
||||
*** Support for block validation
|
||||
|
||||
Block navigation now does validation, for example, 'property' keywords should only occur
|
||||
inside a classdef, and 'arguments' keywords should only occur inside a function.
|
||||
|
||||
This means that you can now have variables and functions named 'property' and
|
||||
'arguments' of those words occur outside valid locations.
|
||||
|
||||
*** Indentation
|
||||
|
||||
Indentation performance is greatly improved. Based on our tests, large files that used
|
||||
to take 10 minutes to indent will now complete in just 1 or 2 seconds.
|
||||
|
||||
Several new indentation features exist, such as:
|
||||
* correct indentation of arguemnts blocks
|
||||
* improved indentation of function argument lists that span multiple lines.
|
||||
* improved indentation around block comments
|
||||
* improved indentation accuracy in classdef, property, method blocks.
|
||||
* more accurate indentation of continuations
|
||||
|
||||
Some indentation features were removed, such as:
|
||||
* Max indent distance support inside function call args
|
||||
* Max indent distance support inside switch statements
|
||||
* Line-up rules inside ( ), [ ], and { } have changed subtly dependeing on
|
||||
context after the opening (, [, or {.
|
||||
|
||||
Specialty indentation commands have been removed:
|
||||
* matlab-indent-sexp
|
||||
|
||||
Electric indentation has been added to block keywords such as end, else, case, etc.
|
||||
|
||||
Lots of bug fixes and general improvements for handling edge cases.
|
||||
|
||||
*** matlab-return & friends removed
|
||||
|
||||
The 'matlab-return' and related functions have all been removed. Features of these
|
||||
commands are now part of Emacs' built in handling for RETURN and no longer need to be
|
||||
part of matlab mode.
|
||||
|
||||
*** File type detection
|
||||
|
||||
File type detection has been improved. Previously matlab mode detected if functions had
|
||||
ends, and if functions were indented. It now detects more cases, and displays results
|
||||
in the status line.
|
||||
|
||||
The list of detectable features are:
|
||||
* function (with no end)
|
||||
* function .. end
|
||||
* classdef .. end
|
||||
* scripts
|
||||
* empty files
|
||||
|
||||
Functions with ends also detect if function bodies are indented. Other kinds of
|
||||
functions will always indent.
|
||||
|
||||
The check for the type of file is also auto-re-detected on save, so if you change the
|
||||
type of file while editing, it will automatically adjust.
|
||||
|
||||
*** Auto verify changes
|
||||
|
||||
Auto verify on save has been updated.
|
||||
|
||||
1. verify classname added - this will fix class names for you
|
||||
2. verify add ends - this now asks questions less often, or not at all.
|
||||
In addition, it has a more robust algorithm for adding ends.
|
||||
|
||||
*** mlint support questions
|
||||
|
||||
mlint mode now supports many more auto fix behaviors, including:
|
||||
* missing ends - with nicer guess for where the end goes.
|
||||
* function name - auto fix function, class, and method names.
|
||||
|
||||
Plus several minor bug fixes.
|
||||
|
||||
*** Support for older Emacsen
|
||||
|
||||
Support for Emacs older than Emacs 24 has been dropped. Many of the special
|
||||
compatability layers needed to change, and the new code has not been tested against
|
||||
older versions of Emacs. As a result, many compatability layers were removed.
|
||||
|
||||
*** Test suite improvements
|
||||
|
||||
The test suite that is part of matlab-emacs project has many more test points, and has
|
||||
added support for testing font lock, performance, and other features.
|
||||
|
||||
*** matlab-emacs maintenance mode
|
||||
|
||||
There is now a support file 'matlab-maint' that simplifies the task of building and
|
||||
testing matlab-mode during development. Consider using this library if you intend to
|
||||
develop matlab-mode.
|
||||
|
||||
|
||||
** News in 4.0
|
||||
|
||||
*** Debugging
|
||||
|
@ -56,7 +192,7 @@ You have the following capabilities when in a MATLAB M-file:
|
|||
more responsive. For example, in matlab-shell, Emacs is more
|
||||
responsive when processing long output lines from MATLAB.
|
||||
|
||||
*** Bug fixex
|
||||
*** Bug fixes
|
||||
- There are a number of bug fixes.
|
||||
|
||||
*** Quotes
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
(ede-proj-target-elisp "ede-proj-target-elisp"
|
||||
:name "lisp"
|
||||
:path ""
|
||||
:source '("matlab-compat.el" "matlab.el" "matlab-shell.el" "matlab-shell-gud.el" "matlab-netshell.el" "matlab-complete.el" "matlab-cgen.el" "matlab-publish.el" "matlab-topic.el" "mlint.el" "tlc.el" "linemark.el" "matlab-maint.el")
|
||||
:source '("matlab-compat.el" "matlab-syntax.el" "matlab-scan.el" "matlab.el" "matlab-shell.el" "matlab-shell-gud.el" "matlab-netshell.el" "matlab-complete.el" "matlab-cgen.el" "matlab-publish.el" "matlab-topic.el" "mlint.el" "tlc.el" "linemark.el" "matlab-maint.el")
|
||||
:versionsource '("matlab.el")
|
||||
:aux-packages '("matlab"))
|
||||
(ede-proj-target-elisp "ede-proj-target-elisp"
|
||||
|
|
14
linemark.el
14
linemark.el
|
@ -275,7 +275,12 @@ Call the new entrie's activate method."
|
|||
(oset new-entry face (or face (oref g face)))
|
||||
(oset g marks (cons new-entry (oref g marks)))
|
||||
(if (oref g active)
|
||||
(linemark-display new-entry t))
|
||||
(condition-case nil
|
||||
;; Somewhere in the eieio framework this can throw 'end of buffer' error
|
||||
;; after the display function exits. Not sure where that is, but this
|
||||
;; condition-case can capture it and allow things to keep going.
|
||||
(linemark-display new-entry t)
|
||||
(error nil)))
|
||||
new-entry)
|
||||
))
|
||||
|
||||
|
@ -356,7 +361,12 @@ Call the new entrie's activate method."
|
|||
|
||||
(defun linemark-find-file-hook ()
|
||||
"Activate all marks which can benifit from this new buffer."
|
||||
(mapcar (lambda (g) (linemark-display g t)) linemark-groups))
|
||||
(mapcar (lambda (g) (condition-case nil
|
||||
;; See comment in linemark-add-entry for
|
||||
;; reasoning on this condition-case.
|
||||
(linemark-display g t)
|
||||
(error nil)))
|
||||
linemark-groups))
|
||||
|
||||
(defun linemark-kill-buffer-hook ()
|
||||
"Deactivate all entries in the current buffer."
|
||||
|
|
|
@ -77,7 +77,9 @@
|
|||
"Insert and END block based on the current syntax.
|
||||
Optional argument REINDENT indicates if the specified block should be re-indented."
|
||||
(interactive "P")
|
||||
(if (not (matlab-ltype-empty)) (progn (end-of-line) (insert "\n")))
|
||||
(when (not (matlab-line-empty-p (matlab-compute-line-context 1)))
|
||||
(end-of-line) (insert "\n"))
|
||||
|
||||
(let ((valid t) (begin nil))
|
||||
(save-excursion
|
||||
(condition-case nil
|
||||
|
@ -172,7 +174,8 @@ Optional argument REINDENT indicates if the specified block should be re-indente
|
|||
(error (setq valid nil))))
|
||||
(if (not valid)
|
||||
(error "Not in a switch statement")))
|
||||
(if (not (matlab-ltype-empty)) (progn (end-of-line) (insert "\n")))
|
||||
(when (not (matlab-line-empty-p (matlab-compute-line-context 1)))
|
||||
(end-of-line) (insert "\n"))
|
||||
(indent-to 0)
|
||||
(insert "case ")
|
||||
(matlab-indent-line))
|
||||
|
@ -234,14 +237,16 @@ the region. BEGIN and END mark the region to be stringified."
|
|||
"Spell check valid strings in region with Ispell.
|
||||
Argument BEGIN and END mark the region boundary."
|
||||
(interactive "r")
|
||||
(error "This function needs to be reimplemented.")
|
||||
(require 'ispell)
|
||||
(save-excursion
|
||||
(goto-char begin)
|
||||
;; Here we use the font lock function for finding strings.
|
||||
;; Its cheap, fast, and accurate.
|
||||
;; NOTE: This now also does comments
|
||||
(while (and (matlab-font-lock-allstring-comment-match-normal end)
|
||||
(ispell-region (match-beginning 0) (match-end 0))))))
|
||||
;;(while (and (matlab-font-lock-allstring-comment-match-normal end)
|
||||
;; (ispell-region (match-beginning 0) (match-end 0))))
|
||||
))
|
||||
|
||||
(defun matlab-ispell-strings-and-comments ()
|
||||
"Spell check valid strings in the current buffer with Ispell.
|
||||
|
|
|
@ -150,6 +150,11 @@ REGEXP defaults to \"[ \\t\\n\\r]+\"."
|
|||
out))
|
||||
)
|
||||
|
||||
;; OBARRAYS
|
||||
(if (fboundp 'obarray-make)
|
||||
(defalias 'matlab-obarray-make 'obarray-make)
|
||||
(defun matlab-obarray-make (sz) (make-vector sz 0)))
|
||||
|
||||
;; Finding executables
|
||||
(defun matlab-find-executable-directory (program)
|
||||
"Find the executable PROGRAM on the exec path, following any links.
|
||||
|
|
|
@ -30,7 +30,21 @@
|
|||
;; and this can be loaded optionally.
|
||||
|
||||
;;; Code:
|
||||
(require 'cl-macs)
|
||||
(require 'matlab)
|
||||
(require 'matlab-shell)
|
||||
|
||||
(defun matlab-uniquify-list (lst)
|
||||
"Return a list that is a subset of LST where all elements are unique."
|
||||
(if (fboundp 'cl-remove-duplicates)
|
||||
(cl-remove-duplicates lst :test 'string= :from-end t)
|
||||
;; Else, do it by hand.
|
||||
(let ((nlst nil))
|
||||
(while lst
|
||||
(if (and (car lst) (not (member (car lst) nlst)))
|
||||
(setq nlst (cons (car lst) nlst)))
|
||||
(setq lst (cdr lst)))
|
||||
(nreverse nlst))))
|
||||
|
||||
;;; Customizations ===========================================================
|
||||
;;
|
||||
|
@ -181,9 +195,32 @@ This list still needs lots of help.")
|
|||
tl (cdr tl)))
|
||||
r))
|
||||
|
||||
(defun matlab-lattr-semantics (&optional prefix)
|
||||
"Return the semantics of the current position.
|
||||
Values are nil 'solo, 'value, and 'boolean. Boolean is a subset of
|
||||
value. nil means there is no semantic content (ie, string or comment.)
|
||||
If optional PREFIX, then return 'solo if that is the only thing on the
|
||||
line."
|
||||
(cond
|
||||
((or (matlab-line-empty-p (matlab-compute-line-context 1))
|
||||
(and prefix (save-excursion
|
||||
(beginning-of-line)
|
||||
(looking-at (concat "\\s-*" prefix "\\s-*$")))))
|
||||
'solo)
|
||||
((save-excursion
|
||||
(matlab-beginning-of-command)
|
||||
(looking-at "\\s-*\\(if\\|elseif\\|while\\)\\>"))
|
||||
'boolean)
|
||||
((save-excursion
|
||||
(matlab-beginning-of-command)
|
||||
(looking-at (concat "\\s-*\\(" (matlab-property-function)
|
||||
"\\)\\>")))
|
||||
'property)
|
||||
(t
|
||||
'value)))
|
||||
|
||||
;;; Completion Framework ===================================================
|
||||
;;
|
||||
|
||||
(defun matlab-find-recent-variable-list (prefix)
|
||||
"Return a list of most recent variables starting with PREFIX as a string.
|
||||
Reverse searches for the following are done first:
|
||||
|
@ -211,28 +248,28 @@ If the list is empty, then searches continue backwards through the code."
|
|||
(nreverse lst)))
|
||||
(save-excursion
|
||||
(let ((lst nil))
|
||||
(while (and (re-search-backward
|
||||
(concat "\\<\\(" matlab-block-beg-pre-no-if
|
||||
"\\)\\s-+(?\\s-*\\(" prefix
|
||||
"\\w+\\)\\>")
|
||||
bounds t)
|
||||
(< (length lst) 10))
|
||||
(setq lst (cons (match-string 2) lst)))
|
||||
(while (and
|
||||
(< (length lst) 10)
|
||||
(matlab-re-search-keyword-backward (matlab-keyword-regex 'ctrl) bounds t))
|
||||
(when (looking-at (concat "\\w+\\s-+(?\\(" prefix "\\w+\\)\\_>"))
|
||||
(setq lst (cons (match-string 1) lst))))
|
||||
(nreverse lst)))
|
||||
(save-excursion
|
||||
(if (re-search-backward "^\\s-*global\\s-+" bounds t)
|
||||
(let ((lst nil) m e)
|
||||
(while (matlab-re-search-keyword-backward
|
||||
(matlab-keyword-regex 'vardecl) bounds t)
|
||||
(save-excursion
|
||||
(goto-char (match-end 0))
|
||||
(while (looking-at "\\(\\w+\\)\\([ \t]+\\|$\\)")
|
||||
(while (looking-at "\\s-*\\(\\w+\\)\\([ \t]+\\|$\\)")
|
||||
(setq m (match-string 1)
|
||||
e (match-end 0))
|
||||
(if (equal 0 (string-match prefix m))
|
||||
(setq lst (cons m lst)))
|
||||
(goto-char e))
|
||||
(nreverse lst))))
|
||||
(goto-char e))))
|
||||
(nreverse lst)))
|
||||
(save-excursion
|
||||
(if (and (re-search-backward "^\\s-*function\\>" bounds t)
|
||||
(re-search-forward "\\<\\(\\w+\\)("
|
||||
(re-search-forward "\\_<\\(\\w+\\)\\s-*("
|
||||
(matlab-point-at-eol) t))
|
||||
(let ((lst nil) m e)
|
||||
(while (looking-at "\\(\\w+\\)\\s-*[,)]\\s-*")
|
||||
|
@ -278,7 +315,7 @@ In NEXT is non-nil, than continue through the list of elements."
|
|||
(let ((lst nil))
|
||||
(while (re-search-forward "^\\s-*function\\>" nil t)
|
||||
(if (re-search-forward
|
||||
(concat "\\(" prefix "\\w+\\)\\s-*\\($\\|(\\)")
|
||||
(concat "\\_<\\(" prefix "\\w+\\)\\s-*\\($\\|(\\)")
|
||||
(matlab-point-at-eol) t)
|
||||
(setq lst (cons (match-string 1) lst))))
|
||||
(nreverse lst)))
|
||||
|
@ -427,6 +464,32 @@ Use `completion-in-region' to support the completion behavior."
|
|||
))
|
||||
)
|
||||
|
||||
(defun matlab--complete-compute-search-functions (semantics)
|
||||
"Return the search functions for context specified by SEMATNICS."
|
||||
(cond ((eq semantics 'solo)
|
||||
'(matlab-solo-completions
|
||||
matlab-find-user-functions
|
||||
matlab-find-recent-variable))
|
||||
((eq semantics 'boolean)
|
||||
'(matlab-find-recent-variable
|
||||
matlab-boolean-completions
|
||||
matlab-find-user-functions
|
||||
matlab-value-completions))
|
||||
((eq semantics 'value)
|
||||
'(matlab-find-recent-variable
|
||||
matlab-find-user-functions
|
||||
matlab-value-completions
|
||||
matlab-boolean-completions))
|
||||
((eq semantics 'property)
|
||||
'(matlab-property-completions
|
||||
matlab-find-user-functions
|
||||
matlab-find-recent-variable
|
||||
matlab-value-completions))
|
||||
(t '(matlab-find-recent-variable
|
||||
matlab-find-user-functions
|
||||
matlab-value-completions
|
||||
matlab-boolean-completions))))
|
||||
|
||||
(defun matlab-complete-symbol-local (&optional arg)
|
||||
"Complete a partially typed symbol in a MATLAB mode buffer.
|
||||
If the previously entered command was also `matlab-complete-symbol'
|
||||
|
@ -459,29 +522,7 @@ to change it temporarily."
|
|||
(setq matlab-last-prefix prefix
|
||||
matlab-last-semantic sem
|
||||
matlab-completion-search-state
|
||||
(cond ((eq sem 'solo)
|
||||
'(matlab-solo-completions
|
||||
matlab-find-user-functions
|
||||
matlab-find-recent-variable))
|
||||
((eq sem 'boolean)
|
||||
'(matlab-find-recent-variable
|
||||
matlab-boolean-completions
|
||||
matlab-find-user-functions
|
||||
matlab-value-completions))
|
||||
((eq sem 'value)
|
||||
'(matlab-find-recent-variable
|
||||
matlab-find-user-functions
|
||||
matlab-value-completions
|
||||
matlab-boolean-completions))
|
||||
((eq sem 'property)
|
||||
'(matlab-property-completions
|
||||
matlab-find-user-functions
|
||||
matlab-find-recent-variable
|
||||
matlab-value-completions))
|
||||
(t '(matlab-find-recent-variable
|
||||
matlab-find-user-functions
|
||||
matlab-value-completions
|
||||
matlab-boolean-completions)))))
|
||||
(matlab--complete-compute-search-functions sem)))
|
||||
(cond
|
||||
((eq matlab-completion-technique 'increment)
|
||||
(let ((r nil) (donext (eq last-command 'matlab-complete-symbol)))
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
(require 'matlab)
|
||||
(require 'matlab-shell)
|
||||
(require 'matlab-netshell)
|
||||
(require 'semantic/symref)
|
||||
(require 'semantic/symref/list)
|
||||
|
||||
;;; Code:
|
||||
|
||||
|
@ -31,8 +33,14 @@
|
|||
;;
|
||||
(defvar matlab-maint-mode-map
|
||||
(let ((km (make-sparse-keymap)))
|
||||
;; compile debug cycle
|
||||
(define-key km [f8] 'matlab-maint-run-tests)
|
||||
(define-key km [f9] 'matlab-maint-compile-matlab-emacs)
|
||||
(define-key km [f10] 'matlab-maint-reload-mode)
|
||||
;; coding
|
||||
(define-key km [f7] 'matlab-maint-symref-this)
|
||||
;; matlab
|
||||
(define-key km [f5] 'matlab-maint-show-info)
|
||||
km)
|
||||
"Keymap used by matlab mode maintainers.")
|
||||
|
||||
|
@ -67,7 +75,35 @@
|
|||
(matlab-maint-minor-mode 1))))
|
||||
)
|
||||
|
||||
;;; Commands
|
||||
;;; Testing stuff in M buffers
|
||||
;;
|
||||
(defun matlab-maint-show-info ()
|
||||
"Show info about line in current matlab buffer."
|
||||
(interactive)
|
||||
(when (eq major-mode 'matlab-mode)
|
||||
(matlab-show-line-info)
|
||||
))
|
||||
|
||||
;;; HACKING ELISP
|
||||
;;
|
||||
|
||||
(defun matlab-maint-symref-this ()
|
||||
"Open a symref buffer on symbol under cursor."
|
||||
(interactive)
|
||||
(save-buffer)
|
||||
(semantic-fetch-tags)
|
||||
(let ((ct (semantic-current-tag)))
|
||||
;; Must have a tag...
|
||||
(when (not ct) (error "Place cursor inside tag to be searched for"))
|
||||
;; Gather results and tags
|
||||
(message "Gathering References for %s.." (semantic-tag-name ct))
|
||||
(let* ((name (semantic-tag-name ct))
|
||||
(res (semantic-symref-find-references-by-name name)))
|
||||
(semantic-symref-produce-list-on-results res name)
|
||||
(semantic-symref-list-expand-all) )))
|
||||
|
||||
|
||||
;;; COMPILE AND TEST
|
||||
;;
|
||||
;; Helpful commands for maintainers.
|
||||
(defcustom matlab-maint-compile-opts '("emacs" "emacs24" "emacs25" "emacs26")
|
||||
|
@ -112,6 +148,8 @@
|
|||
"Run the tests for matlab mode.
|
||||
With universal ARG, ask for the code to be run with output tracking turned on."
|
||||
(interactive "P")
|
||||
(when (buffer-file-name)
|
||||
(save-buffer))
|
||||
(save-excursion
|
||||
(matlab-maint-set-buffer-to "tests/Makefile")
|
||||
(if (or arg matlab-shell-io-testing)
|
||||
|
@ -123,6 +161,21 @@ With universal ARG, ask for the code to be run with output tracking turned on."
|
|||
(delete-other-windows)
|
||||
(goto-char (point-max)))
|
||||
|
||||
(defun matlab-maint-reload-mode ()
|
||||
"Reload matlab mode, and refresh displayed ML buffers modes."
|
||||
(interactive)
|
||||
(load-library "matlab-syntax")
|
||||
(load-library "matlab-scan")
|
||||
(load-library "matlab")
|
||||
(mapc (lambda (b) (with-current-buffer b
|
||||
(when (eq major-mode 'matlab-mode)
|
||||
(message "Updating matlab mode in %S" b)
|
||||
(matlab-mode))))
|
||||
(buffer-list (selected-frame)))
|
||||
(message "loading done")
|
||||
)
|
||||
;;; MATLAB SHELL tools
|
||||
;;
|
||||
|
||||
(defun matlab-maint-set-buffer-to (file)
|
||||
"Set the current buffer to FILE found in matlab-mode's source.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -89,7 +89,6 @@ Disable this option if the tooltips are too slow in your setup."
|
|||
;; (gud-def gud-print "% gud-print not available" "\C-p" "gud-print not available.")
|
||||
|
||||
(when window-system
|
||||
(matlab-frame-init)
|
||||
|
||||
(setq gud-matlab-tool-bar-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
|
@ -373,7 +372,7 @@ LONGESTNAME specifies the how long the longest name we can expect is."
|
|||
"Specify a NEWSTACK provided by MATLAB to replace the old one."
|
||||
(setq mlg-stack nil)
|
||||
(dolist (L newstack)
|
||||
(push (mlg-stack-frame ""
|
||||
(push (make-instance 'mlg-stack-frame
|
||||
:file (nth 0 L)
|
||||
:name (nth 1 L)
|
||||
:line (nth 2 L))
|
||||
|
@ -598,7 +597,8 @@ LONGESTNAME specifies the how long the longest name we can expect is."
|
|||
(setq found t)))
|
||||
(when (not found)
|
||||
(setq matlab-gud-visible-breakpoints
|
||||
(cons (mlg-breakpoint "" :file file
|
||||
(cons (make-instance 'mlg-breakpoint
|
||||
:file file
|
||||
:name fcn
|
||||
:line line)
|
||||
matlab-gud-visible-breakpoints))
|
||||
|
|
|
@ -204,10 +204,27 @@ If multiple prompts are seen together, only call this once.")
|
|||
;;; Font Lock
|
||||
;;
|
||||
;; Extra font lock keywords for the MATLAB shell.
|
||||
(defvar matlab-shell-font-lock-keywords
|
||||
(defconst matlab-shell-font-lock-keywords
|
||||
(list
|
||||
;; How about Errors?
|
||||
'("^\\(Error in\\|Syntax error in\\)\\s-+==>\\s-+\\(.+\\)$"
|
||||
(1 font-lock-comment-face) (2 font-lock-string-face))
|
||||
;; and line numbers
|
||||
'("^\\(\\(On \\)?line [0-9]+\\)" 1 font-lock-comment-face)
|
||||
;; User beep things
|
||||
'("\\(\\?\\?\\?[^\n]+\\)" 1 font-lock-comment-face)
|
||||
)
|
||||
"Additional keywords used by MATLAB when reporting errors in interactive\
|
||||
mode.")
|
||||
|
||||
(defconst matlab-shell-font-lock-keywords-1
|
||||
(append matlab-basic-font-lock-keywords
|
||||
matlab-shell-font-lock-keywords)
|
||||
"Keyword symbol used for basic font-lock for MATLAB shell.")
|
||||
|
||||
(defconst matlab-shell-object-output-font-lock-keywords
|
||||
(list
|
||||
;; Startup notices
|
||||
;; Various notices
|
||||
'(" M A T L A B " 0 'underline)
|
||||
'("All Rights Reserved" 0 'italic)
|
||||
'("\\(\\(?:(c)\\)?\\s-+Copyright[^\n]+\\)" 1 font-lock-comment-face)
|
||||
|
@ -218,33 +235,38 @@ If multiple prompts are seen together, only call this once.")
|
|||
'("^To get started, type doc.$" 0 font-lock-comment-face prepend)
|
||||
'("For product information, [^\n]+" 0 font-lock-comment-face)
|
||||
|
||||
;; How about Errors?
|
||||
'("^\\(Error in\\|Syntax error in\\)\\s-+==>\\s-+\\(.+\\)$"
|
||||
(1 font-lock-comment-face) (2 font-lock-string-face))
|
||||
;; and line numbers
|
||||
'("^\\(\\(On \\)?line [0-9]+\\)" 1 font-lock-comment-face)
|
||||
;; User beep things
|
||||
'("\\(\\?\\?\\?[^\n]+\\)" 1 font-lock-comment-face)
|
||||
;; Useful user commands, but not useful programming constructs
|
||||
'("\\<\\(demo\\|whatsnew\\|info\\|subscribe\\|help\\|doc\\|lookfor\\|what\
|
||||
\\|whos?\\|cd\\|clear\\|load\\|save\\|helpdesk\\|helpwin\\)\\>"
|
||||
1 font-lock-keyword-face)
|
||||
;; disp of objects usually looks like this:
|
||||
'("^\\s-*\\(\\w+\\) with properties:" (1 font-lock-type-face))
|
||||
;; object output - highlight property names after 'with properties:' indicator
|
||||
;; NOTE: Normally a block like this would require us to use `font-lock-multiline' feature
|
||||
;; but since this is shell output, and not a thing you edit, we can skip it and rely
|
||||
;; on matlab-shell dumping the text as a unit.
|
||||
'("^\\s-*\\(\\w+ with properties:\\)\n\\s-*\n"
|
||||
("^\\s-*\\(\\w+\\):[^\n]+$" ;; match the property before the :
|
||||
;; Extend search region across lines.
|
||||
(save-excursion (re-search-forward "\n\\s-*\n" nil t)
|
||||
(beginning-of-line)
|
||||
(point))
|
||||
nil
|
||||
(1 font-lock-variable-name-face)))
|
||||
'("[[{]\\([0-9]+\\(?:x[0-9]+\\)+ \\w+\\)[]}]" (1 font-lock-comment-face))
|
||||
)
|
||||
"Additional keywords used by MATLAB when reporting errors in interactive\
|
||||
mode.")
|
||||
"Highlight various extra outputs that are typical for MATLAB.")
|
||||
|
||||
(defvar matlab-shell-font-lock-keywords-1
|
||||
(append matlab-font-lock-keywords matlab-shell-font-lock-keywords)
|
||||
"Keyword symbol used for font-lock mode.")
|
||||
(defconst matlab-shell-font-lock-keywords-2
|
||||
(append matlab-shell-font-lock-keywords-1
|
||||
matlab-function-font-lock-keywords
|
||||
matlab-shell-object-output-font-lock-keywords)
|
||||
"Keyword symbol used for gaudy font-lock for MATLAB shell.")
|
||||
|
||||
(defvar matlab-shell-font-lock-keywords-2
|
||||
(append matlab-shell-font-lock-keywords-1 matlab-gaudy-font-lock-keywords)
|
||||
"Keyword symbol used for gaudy font-lock symbols.")
|
||||
|
||||
(defvar matlab-shell-font-lock-keywords-3
|
||||
(defconst matlab-shell-font-lock-keywords-3
|
||||
(append matlab-shell-font-lock-keywords-2
|
||||
matlab-really-gaudy-font-lock-keywords)
|
||||
"Keyword symbol used for really gaudy font-lock symbols.")
|
||||
"Keyword symbol used for really gaudy font-lock for MATLAB shell.")
|
||||
|
||||
;;; ROOT
|
||||
;;
|
||||
|
@ -1575,16 +1597,9 @@ Snatched and hacked from dired-x.el"
|
|||
(search-forward-regexp comint-prompt-regexp)
|
||||
(buffer-substring (point) (matlab-point-at-eol)))))
|
||||
(save-excursion
|
||||
;; In matlab buffer, find all the text for a command.
|
||||
;; so back over until there is no more continuation.
|
||||
(while (save-excursion (forward-line -1) (matlab-lattr-cont))
|
||||
(forward-line -1))
|
||||
;; Go forward till there is no continuation
|
||||
(beginning-of-line)
|
||||
(let ((start (point)))
|
||||
(while (matlab-lattr-cont) (forward-line 1))
|
||||
(end-of-line)
|
||||
(buffer-substring start (point))))))
|
||||
(buffer-substring-no-properties
|
||||
(matlab-scan-beginning-of-command)
|
||||
(matlab-scan-end-of-command)))))
|
||||
|
||||
(defun matlab-non-empty-lines-in-string (str)
|
||||
"Return number of non-empty lines in STR."
|
||||
|
@ -2164,7 +2179,13 @@ Similar to `comint-send-input'."
|
|||
))
|
||||
|
||||
;; If not changing dir, maybe we need to use 'run' command instead?
|
||||
(let ((cmd (concat "run('" dir fn-name "')")))
|
||||
(let* ((match 0)
|
||||
(tmp (while (setq match (string-match "'" param match))
|
||||
(setq param (replace-match "''" t t param))
|
||||
(setq match (+ 2 match))))
|
||||
(cmd (concat "emacsrun('" dir fn-name "'"
|
||||
(if (string= param "") "" (concat ", '" param "'"))
|
||||
")")))
|
||||
(matlab-shell-send-command cmd)))
|
||||
))))
|
||||
|
||||
|
@ -2175,17 +2196,19 @@ Similar to `comint-send-input'."
|
|||
(defun matlab-shell-run-cell ()
|
||||
"Run the cell the cursor is in."
|
||||
(interactive)
|
||||
(let ((start (save-excursion (forward-page -1)
|
||||
(let ((start (save-excursion
|
||||
(forward-page -1)
|
||||
(if (looking-at "function")
|
||||
(error "You are not in a cell. Try `matlab-shell-save-and-go' instead"))
|
||||
(when (matlab-ltype-comm)
|
||||
(when (matlab-line-comment-p (matlab-compute-line-context 1))
|
||||
;; Skip over starting comment from the current cell.
|
||||
(matlab-end-of-command 1)
|
||||
(matlab-end-of-command)
|
||||
(end-of-line)
|
||||
(forward-char 1))
|
||||
(point)))
|
||||
(end (save-excursion (forward-page 1)
|
||||
(when (matlab-ltype-comm)
|
||||
(end (save-excursion
|
||||
(forward-page 1)
|
||||
(when (matlab-line-comment-p (matlab-compute-line-context 1))
|
||||
(beginning-of-line)
|
||||
(forward-char -1))
|
||||
(point))))
|
||||
|
|
|
@ -0,0 +1,573 @@
|
|||
;;; matlab-syntax.el --- Manage MATLAB syntax tables and buffer parsing.
|
||||
;;
|
||||
;; Copyright (C) 2021 Eric Ludlam
|
||||
;;
|
||||
;; Author: <eludlam@mathworks.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:
|
||||
;;
|
||||
;; Manage syntax handling for `matlab-mode'.
|
||||
;; 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.
|
||||
;;
|
||||
;; This file also handles all the special parsing needed to support indentation,
|
||||
;; block scanning, and the line.
|
||||
|
||||
(require 'matlab-compat)
|
||||
|
||||
;;; 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.")
|
||||
(make-variable-buffer-local 'matlab-syntax-support-command-dual)
|
||||
(put 'matlab-syntax-support-command-dual 'safe-local-variable #'booleanp)
|
||||
|
||||
|
||||
(defvar matlab-syntax-table
|
||||
(let ((st (make-syntax-table (standard-syntax-table))))
|
||||
;; Comment Handling:
|
||||
;; Multiline comments: %{ text %}
|
||||
;; Single line comments: % text (single char start)
|
||||
;; Ellipsis omments: ... text (comment char is 1st char after 3rd dot)
|
||||
;; ^ handled in `matlab--syntax-propertize'
|
||||
(modify-syntax-entry ?% "< 13" st)
|
||||
(modify-syntax-entry ?{ "(} 2c" st)
|
||||
(modify-syntax-entry ?} "){ 4c" st)
|
||||
(modify-syntax-entry ?\n ">" st)
|
||||
|
||||
;; String Handling:
|
||||
;; Character vector: 'text'
|
||||
;; String: "text"
|
||||
;; These next syntaxes are handled with `matlab--syntax-propertize'
|
||||
;; Transpose: varname'
|
||||
;; Quoted quotes: ' don''t ' or " this "" "
|
||||
;; Unterminated Char V: ' text
|
||||
(modify-syntax-entry ?' "\"" st)
|
||||
(modify-syntax-entry ?\" "\"" st)
|
||||
|
||||
;; Words and Symbols:
|
||||
(modify-syntax-entry ?_ "_" st)
|
||||
|
||||
;; Punctuation:
|
||||
(modify-syntax-entry ?\\ "." st)
|
||||
(modify-syntax-entry ?\t " " st)
|
||||
(modify-syntax-entry ?+ "." st)
|
||||
(modify-syntax-entry ?- "." st)
|
||||
(modify-syntax-entry ?* "." st)
|
||||
(modify-syntax-entry ?/ "." st)
|
||||
(modify-syntax-entry ?= "." st)
|
||||
(modify-syntax-entry ?< "." st)
|
||||
(modify-syntax-entry ?> "." st)
|
||||
(modify-syntax-entry ?& "." st)
|
||||
(modify-syntax-entry ?| "." st)
|
||||
|
||||
;; Parentheticl blocks:
|
||||
;; Note: these are in standard syntax table, repeated here for completeness.
|
||||
(modify-syntax-entry ?\( "()" st)
|
||||
(modify-syntax-entry ?\) ")(" st)
|
||||
(modify-syntax-entry ?\[ "(]" st)
|
||||
(modify-syntax-entry ?\] ")[" st)
|
||||
;;(modify-syntax-entry ?{ "(}" st) - Handled as part of comments
|
||||
;;(modify-syntax-entry ?} "){" st)
|
||||
|
||||
st)
|
||||
"MATLAB syntax table")
|
||||
|
||||
(defvar matlab-navigation-syntax-table
|
||||
(let ((st (copy-syntax-table matlab-syntax-table)))
|
||||
;; Make _ a part of words so we can skip them better
|
||||
(modify-syntax-entry ?_ "w" st)
|
||||
st)
|
||||
"The syntax table used when navigating blocks.")
|
||||
|
||||
(defmacro matlab-navigation-syntax (&rest forms)
|
||||
"Set the current environment for syntax-navigation and execute FORMS."
|
||||
(declare (indent 0))
|
||||
(list 'let '((oldsyntax (syntax-table))
|
||||
(case-fold-search nil))
|
||||
(list 'unwind-protect
|
||||
(list 'progn
|
||||
'(set-syntax-table matlab-navigation-syntax-table)
|
||||
(cons 'progn forms))
|
||||
'(set-syntax-table oldsyntax))))
|
||||
|
||||
(add-hook 'edebug-setup-hook
|
||||
(lambda ()
|
||||
(def-edebug-spec matlab-navigation-syntax def-body)))
|
||||
|
||||
;;; Buffer Scanning for Syntax Table Augmentation
|
||||
;;
|
||||
;; To support all our special syntaxes via syntax-ppss (parse partial
|
||||
;; sexp), we need to scan the buffer for patterns, and then leave
|
||||
;; behind the hints pps needs to do the right thing.
|
||||
;;
|
||||
;; Support is broken up in these functions:
|
||||
;; * matlab--put-char-category - Apply a syntax category to a character
|
||||
;; * matlab--syntax-symbol - Create a syntax category symbol
|
||||
;; * matlab--syntax-propertize - Used as `syntax-propertize-function' for
|
||||
;; doing the buffer scan to augment syntxes.
|
||||
;; * matlab--scan-line-* - Scan for specific types of syntax occurances.
|
||||
|
||||
(defun matlab--put-char-category (pos category)
|
||||
"At character POS, put text CATEGORY."
|
||||
(when (not (eobp))
|
||||
(put-text-property pos (1+ pos) 'category category)
|
||||
(put-text-property pos (1+ pos) 'mcm t))
|
||||
)
|
||||
|
||||
(defmacro matlab--syntax-symbol (symbol syntax doc)
|
||||
"Create a new SYMBOL used as a text property category with SYNTAX."
|
||||
(declare (indent defun))
|
||||
`(progn (defvar ,symbol ,syntax ,doc)
|
||||
(set ',symbol ,syntax) ;; So you can re-eval it.
|
||||
(put ',symbol 'syntax-table ,symbol)
|
||||
))
|
||||
|
||||
(matlab--syntax-symbol matlab--command-dual-syntax '(15 . nil) ;; Generic string
|
||||
"Syntax placed on end-of-line for unterminated strings.")
|
||||
(put 'matlab--command-dual-syntax 'command-dual t) ;; Font-lock cookie
|
||||
|
||||
(matlab--syntax-symbol matlab--unterminated-string-syntax '(15 . nil) ;; Generic string end
|
||||
"Syntax placed on end-of-line for unterminated strings.")
|
||||
(put 'matlab--unterminated-string-syntax 'unterminated t) ;; Font-lock cookie
|
||||
|
||||
(matlab--syntax-symbol matlab--ellipsis-syntax (string-to-syntax "< ") ;; comment char
|
||||
"Syntax placed on ellipsis to treat them as comments.")
|
||||
|
||||
(matlab--syntax-symbol matlab--not-block-comment-syntax (string-to-syntax "(}") ;; Just a regular open brace
|
||||
"Syntax placed on ellipsis to treat them as comments.")
|
||||
|
||||
(defun matlab--syntax-propertize (&optional start end)
|
||||
"Scan region between START and END for unterminated strings.
|
||||
Only scans whole-lines, as MATLAB is a line-based language.
|
||||
If region is not specified, scan the whole buffer.
|
||||
See `matlab--scan-line-for-ellipsis', `matlab--san-line-bad-blockcomment',
|
||||
and `matlab--scan-line-for-unterminated-string' for specific details."
|
||||
(save-match-data ;; avoid 'Syntax Checking transmuted the match-data'
|
||||
(save-excursion
|
||||
;; Scan region, but always expand to beginning of line
|
||||
(goto-char (or start (point-min)))
|
||||
(beginning-of-line)
|
||||
;; Clear old properties
|
||||
(remove-text-properties (point) (save-excursion (goto-char (or end (point-max)))
|
||||
(end-of-line) (point))
|
||||
'(category nil mcm nil))
|
||||
;; Apply properties
|
||||
(while (and (not (>= (point) (or end (point-max)))) (not (eobp)))
|
||||
|
||||
(when matlab-syntax-support-command-dual
|
||||
;; Commandl line dual comes first to prevent wasting time
|
||||
;; in later checks.
|
||||
(beginning-of-line)
|
||||
(when (matlab--scan-line-for-command-dual)
|
||||
(matlab--put-char-category (point) 'matlab--command-dual-syntax)
|
||||
(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)
|
||||
;; Mark ellipsis as if a comment.
|
||||
(matlab--put-char-category (point) 'matlab--ellipsis-syntax)
|
||||
(forward-char 3)
|
||||
)
|
||||
|
||||
;; Multiple invalid block comment starts possible. Find them all
|
||||
(beginning-of-line)
|
||||
(while (matlab--scan-line-bad-blockcomment)
|
||||
;; Mark 2nd char as just open brace, not punctuation.
|
||||
(matlab--put-char-category (point) 'matlab--not-block-comment-syntax)
|
||||
)
|
||||
|
||||
;; Look for an unterminated string. Only one possible per line.
|
||||
(beginning-of-line)
|
||||
(when (matlab--scan-line-for-unterminated-string)
|
||||
;; Mark this one char plus EOL as end of string.
|
||||
(let ((start (point)))
|
||||
(matlab--put-char-category (point) 'matlab--unterminated-string-syntax)
|
||||
(end-of-line)
|
||||
(matlab--put-char-category (point) 'matlab--unterminated-string-syntax)
|
||||
))
|
||||
|
||||
(beginning-of-line)
|
||||
(forward-line 1))
|
||||
)))
|
||||
|
||||
(defconst matlab-syntax-commanddual-functions
|
||||
'("warning" "disp" "cd"
|
||||
;; debug
|
||||
"dbstop" "dbclear"
|
||||
;; Graphics
|
||||
"print" "xlim" "ylim" "zlim" "grid" "hold" "box" "colormap" "axis")
|
||||
"Functions that are commonly used with commandline dual")
|
||||
(defconst matlab-cds-regex (regexp-opt matlab-syntax-commanddual-functions 'symbols))
|
||||
|
||||
(defun matlab--scan-line-for-command-dual (&optional debug)
|
||||
"Scan this line for command line duality strings."
|
||||
;; Note - add \s$ b/c we'll add that syntax to the first letter, and it
|
||||
;; might still be there during an edit!
|
||||
(let ((case-fold-search nil))
|
||||
(when (and (not (nth 9 (syntax-ppss (point))))
|
||||
(looking-at
|
||||
(concat "^\\s-*"
|
||||
matlab-cds-regex
|
||||
"\\s-+\\(\\s$\\|\\w\\|\\s_\\)")))
|
||||
(goto-char (match-beginning 2)))))
|
||||
|
||||
(matlab--syntax-symbol matlab--transpose-syntax '(3 . nil) ;; 3 = symbol
|
||||
"Treat ' as non-string when used as transpose.")
|
||||
|
||||
(matlab--syntax-symbol matlab--quoted-string-syntax '(9 . nil) ;; 9 = escape in a string
|
||||
"Treat '' or \"\" as not string delimeteres when inside a string.")
|
||||
|
||||
(defun matlab--scan-line-for-unterminated-string (&optional debug)
|
||||
"Scan this line for an unterminated string, leave cursor on starting string char."
|
||||
;; First, scan over all the string chars.
|
||||
(save-restriction
|
||||
(narrow-to-region (point-at-bol) (point-at-eol))
|
||||
(beginning-of-line)
|
||||
(condition-case err
|
||||
(while (re-search-forward "\\s\"\\|\\s<" nil t)
|
||||
(let ((start-str (match-string 0))
|
||||
(start-char (match-beginning 0)))
|
||||
(forward-char -1)
|
||||
(if (looking-at "\\s<")
|
||||
(progn
|
||||
(matlab--scan-line-comment-disable-strings)
|
||||
(forward-comment 1))
|
||||
;; Else, check for valid string
|
||||
(if (or (bolp)
|
||||
(string= start-str "\"")
|
||||
(save-excursion
|
||||
(forward-char -1)
|
||||
(not (looking-at "\\(\\w\\|\\s_\\|\\s)\\|\"\\|\\.\\)"))))
|
||||
(progn
|
||||
;; Valid string start, try to skip the string
|
||||
(forward-sexp 1)
|
||||
;; If we just finished and we have a double of ourselves,
|
||||
;; convert those doubles into punctuation.
|
||||
(when (looking-at start-str)
|
||||
(matlab--put-char-category (1- (point)) 'matlab--quoted-string-syntax)
|
||||
;; and try again.
|
||||
(goto-char start-char)
|
||||
))
|
||||
(when (string= start-str "'")
|
||||
;; If it isn't valid string, it's just transpose or something.
|
||||
;; convert to a symbol - as a VAR'', the second ' needs to think it
|
||||
;; is not after punctuation.
|
||||
(matlab--put-char-category (point) 'matlab--transpose-syntax))
|
||||
;; Move forward 1.
|
||||
(forward-char 1)
|
||||
)))
|
||||
nil)
|
||||
(error
|
||||
t))))
|
||||
|
||||
(defun matlab--scan-line-comment-disable-strings ()
|
||||
"Disable bad string chars syntax from point to eol.
|
||||
Called when comments found in `matlab--scan-line-for-unterminated-string'."
|
||||
(save-excursion
|
||||
(while (re-search-forward "\\s\"" nil t)
|
||||
(save-excursion
|
||||
(matlab--put-char-category (1- (point)) 'matlab--transpose-syntax)
|
||||
))))
|
||||
|
||||
(defun matlab--scan-line-bad-blockcomment ()
|
||||
"Scan this line for invalid block comment starts."
|
||||
(when (and (re-search-forward "%{" (point-at-eol) t) (not (looking-at "\\s-*$")))
|
||||
(goto-char (1- (match-end 0)))
|
||||
t))
|
||||
|
||||
(defun matlab--scan-line-for-ellipsis ()
|
||||
"Scan this line for an ellipsis."
|
||||
(when (re-search-forward "\\.\\.\\." (point-at-eol) t)
|
||||
(goto-char (match-beginning 0))
|
||||
t))
|
||||
|
||||
;;; Font Lock Support:
|
||||
;;
|
||||
;; The syntax specific font-lock support handles comments and strings.
|
||||
;;
|
||||
;; We'd like to support multiple kinds of strings and comments. To do
|
||||
;; that we overload `font-lock-syntactic-face-function' with our own.
|
||||
;; This does the same job as the orriginal, except we scan the start
|
||||
;; for special cookies left behind by `matlab--syntax-propertize' and
|
||||
;; use that to choose different fonts.
|
||||
(defun matlab--font-lock-syntactic-face (pps)
|
||||
"Return the face to use for the syntax specified in PPS."
|
||||
;; From the default in font-lock.
|
||||
;; (if (nth 3 state) font-lock-string-face font-lock-comment-face)
|
||||
(if (nth 3 pps)
|
||||
;; This is a string. Check the start char to see if it was
|
||||
;; marked as an unterminate string.
|
||||
(cond ((get-text-property (nth 8 pps) 'unterminated)
|
||||
'matlab-unterminated-string-face)
|
||||
((get-text-property (nth 8 pps) 'command-dual)
|
||||
'matlab-commanddual-string-face)
|
||||
(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))) ?\%))
|
||||
'matlab-cellbreak-face)
|
||||
((and (< (nth 8 pps) (point-max))
|
||||
(= (char-after (1+ (nth 8 pps))) ?\#))
|
||||
'matlab-pragma-face)
|
||||
((and (< (nth 8 pps) (point-max))
|
||||
(looking-at "\\^\\| \\$\\$\\$"))
|
||||
'matlab-ignored-comment-face)
|
||||
(t
|
||||
'font-lock-comment-face))
|
||||
))
|
||||
|
||||
;;; SETUP
|
||||
;;
|
||||
;; Connect our special logic into a running MATLAB Mode
|
||||
;; replacing existing mechanics.
|
||||
;;
|
||||
;; Delete this if/when it becomes a permanent part of `matlab-mode'.
|
||||
|
||||
(defun matlab-syntax-setup ()
|
||||
"Integrate our syntax handling into a running `matlab-mode' buffer.
|
||||
Safe to use in `matlab-mode-hook'."
|
||||
;; Syntax Table support
|
||||
(set-syntax-table matlab-syntax-table)
|
||||
(make-local-variable 'syntax-propertize-function)
|
||||
(setq syntax-propertize-function 'matlab--syntax-propertize)
|
||||
;; Comment handlers
|
||||
(make-local-variable 'comment-start)
|
||||
(make-local-variable 'comment-end)
|
||||
(make-local-variable 'comment-start-skip)
|
||||
(make-local-variable 'page-delimiter)
|
||||
(setq comment-start "%"
|
||||
comment-end ""
|
||||
comment-start-skip "%\\s-+"
|
||||
page-delimiter "^\\(\f\\|%%\\(\\s-\\|\n\\)\\)")
|
||||
;; Other special regexps handling different kinds of syntax.
|
||||
(make-local-variable 'paragraph-start)
|
||||
(setq paragraph-start (concat "^$\\|" page-delimiter))
|
||||
(make-local-variable 'paragraph-separate)
|
||||
(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)
|
||||
)
|
||||
|
||||
;;; Syntax Testing for Strings and Comments
|
||||
;;
|
||||
;; These functions detect syntactic context based on the syntax table.
|
||||
(defsubst matlab-cursor-in-string-or-comment ()
|
||||
"Return non-nil if the cursor is in a valid MATLAB comment or string."
|
||||
(nth 8 (syntax-ppss (point))))
|
||||
|
||||
(defsubst matlab-cursor-in-comment ()
|
||||
"Return t if the cursor is in a valid MATLAB comment."
|
||||
(nth 4 (syntax-ppss (point))))
|
||||
|
||||
(defsubst matlab-cursor-in-string (&optional incomplete)
|
||||
"Return t if the cursor is in a valid MATLAB character vector or string scalar.
|
||||
Note: INCOMPLETE is now obsolete
|
||||
If the optional argument INCOMPLETE is non-nil, then return t if we
|
||||
are in what could be a an incomplete string. (Note: this is also the default)"
|
||||
(nth 3 (syntax-ppss (point))))
|
||||
|
||||
(defun matlab-cursor-comment-string-context (&optional bounds-sym)
|
||||
"Return the comment/string context of cursor for the current line.
|
||||
Return 'comment if in a comment.
|
||||
Return 'string if in a string.
|
||||
Return 'charvector if in a character vector
|
||||
Return 'ellipsis if after an ... ellipsis
|
||||
Return 'commanddual if in text interpreted as string for command dual
|
||||
Return nil if none of the above.
|
||||
Scans from the beginning of line to determine the context.
|
||||
If optional BOUNDS-SYM is specified, set that symbol value to the
|
||||
bounds of the string or comment the cursor is in"
|
||||
(let* ((pps (syntax-ppss (point)))
|
||||
(start (nth 8 pps))
|
||||
(end 0)
|
||||
(syntax nil))
|
||||
;; Else, inside something if 'start' is set.
|
||||
(when start
|
||||
(save-match-data
|
||||
(save-excursion
|
||||
(goto-char start) ;; Prep for extra checks.
|
||||
(setq syntax
|
||||
(cond ((eq (nth 3 pps) t)
|
||||
(cond ((= (following-char) ?')
|
||||
'charvector)
|
||||
((= (following-char) ?\")
|
||||
'string)
|
||||
(t
|
||||
'commanddual)))
|
||||
((eq (nth 3 pps) ?')
|
||||
'charvector)
|
||||
((eq (nth 3 pps) ?\")
|
||||
'string)
|
||||
((nth 4 pps)
|
||||
(if (= (following-char) ?\%)
|
||||
'comment
|
||||
'ellipsis))
|
||||
(t nil)))
|
||||
|
||||
;; compute the bounds
|
||||
(when (and syntax bounds-sym)
|
||||
(if (memq syntax '(charvector string))
|
||||
;;(forward-sexp 1) - overridden - need primitive version
|
||||
(goto-char (scan-sexps (point) 1))
|
||||
(forward-comment 1)
|
||||
(if (bolp) (forward-char -1)))
|
||||
(set bounds-sym (list start (point))))
|
||||
)))
|
||||
|
||||
;; Return the syntax
|
||||
syntax))
|
||||
|
||||
(defsubst matlab-beginning-of-string-or-comment (&optional all-comments)
|
||||
"If the cursor is in a string or comment, move to the beginning.
|
||||
Returns non-nil if the cursor is in a comment."
|
||||
(let* ((pps (syntax-ppss (point))))
|
||||
(prog1
|
||||
(when (nth 8 pps)
|
||||
(goto-char (nth 8 pps))
|
||||
|
||||
t)
|
||||
(when all-comments (forward-comment -100000)))))
|
||||
|
||||
(defun matlab-end-of-string-or-comment (&optional all-comments)
|
||||
"If the cursor is in a string or comment, move to the end.
|
||||
If optional ALL-COMMENTS is non-nil, then also move over all
|
||||
adjacent comments.
|
||||
Returns non-nil if the cursor moved."
|
||||
(let* ((pps (syntax-ppss (point)))
|
||||
(start (point)))
|
||||
(if (nth 8 pps)
|
||||
(progn
|
||||
;; syntax-ppss doesn't have the end, so go to the front
|
||||
;; and then skip forward.
|
||||
(goto-char (nth 8 pps))
|
||||
(if (nth 3 pps)
|
||||
(goto-char (scan-sexps (point) 1))
|
||||
(forward-comment (if all-comments 100000 1)))
|
||||
;; If the buffer is malformed, we might end up before starting pt.
|
||||
;; so error.
|
||||
(when (< (point) start)
|
||||
(goto-char start)
|
||||
(error "Error navitaging syntax."))
|
||||
t)
|
||||
;; else not in comment, but still skip 'all-comments' if requested.
|
||||
(when (and all-comments (looking-at "\\s-*\\s<"))
|
||||
(forward-comment 100000)
|
||||
t)
|
||||
)))
|
||||
|
||||
;;; Navigating Lists
|
||||
;;
|
||||
;; MATLAB's lists are (), {}, [].
|
||||
;; We used to need to do special stuff, but now I think this
|
||||
;; is just a call striaght to up-list.
|
||||
|
||||
(defun matlab-up-list (count)
|
||||
"Move forwards or backwards up a list by COUNT.
|
||||
When travelling backward, use `syntax-ppss' counted paren
|
||||
starts to navigate upward.
|
||||
When travelling forward, use 'up-list' diretly, but disable
|
||||
comment and string crossing."
|
||||
(save-restriction
|
||||
(matlab-beginning-of-string-or-comment)
|
||||
(if (< count 0)
|
||||
(let ((pps (syntax-ppss)))
|
||||
(when (< (nth 0 pps) (abs count))
|
||||
(error "Cannot navigate up %d lists" (abs count)))
|
||||
;; When travelling in reverse, we can just use pps'
|
||||
;; parsed paren list in slot 9.
|
||||
(let ((posn (reverse (nth 9 pps)))) ;; Location of parens
|
||||
(goto-char (nth (1- (abs count)) posn))))
|
||||
;; Else - travel forward
|
||||
(up-list count nil t)) ;; will this correctly ignore comments, etc?
|
||||
))
|
||||
|
||||
(defsubst matlab-in-list-p ()
|
||||
"If the cursor is in a list, return positions of the beginnings of the lists.
|
||||
Returns nil if not in a list."
|
||||
(nth 9 (syntax-ppss (point))))
|
||||
|
||||
(defsubst matlab-beginning-of-outer-list ()
|
||||
"If the cursor is in a list, move to the beginning of outermost list.
|
||||
Returns non-nil if the cursor moved."
|
||||
(let ((pps (syntax-ppss (point))))
|
||||
(when (nth 9 pps) (goto-char (car (nth 9 pps))) )))
|
||||
|
||||
(defun matlab-end-of-outer-list ()
|
||||
"If the cursor is in a list, move to the end of the outermost list..
|
||||
Returns non-nil if the cursor moved."
|
||||
(let ((pps (syntax-ppss (point)))
|
||||
(start (point)))
|
||||
(when (nth 9 pps)
|
||||
;; syntax-ppss doesn't have the end, so go to the front
|
||||
;; and then skip forward.
|
||||
(goto-char (car (nth 9 pps)))
|
||||
(goto-char (scan-sexps (point) 1))
|
||||
;; This checks for malformed buffer content
|
||||
;; that can cause this to go backwards.
|
||||
(when (> start (point))
|
||||
(goto-char start)
|
||||
(error "Malformed List"))
|
||||
)))
|
||||
|
||||
;;; Useful checks for state around point.
|
||||
;;
|
||||
(defsubst matlab-syntax-keyword-as-variable-p ()
|
||||
"Return non-nil if the current word is treated like a variable.
|
||||
This could mean it is:
|
||||
* Field of a structure
|
||||
* Assigned from or into with ="
|
||||
(or (save-excursion (skip-syntax-backward "w")
|
||||
(skip-syntax-backward " ")
|
||||
(or (= (preceding-char) ?\.)
|
||||
(= (preceding-char) ?=)))
|
||||
(save-excursion (skip-syntax-forward "w")
|
||||
(skip-syntax-forward " ")
|
||||
(= (following-char) ?=))))
|
||||
|
||||
(defsubst matlab-valid-keyword-syntax ()
|
||||
"Return non-nil if cursor is not in a string, comment, or parens."
|
||||
(let ((pps (syntax-ppss (point))))
|
||||
(not (or (nth 8 pps) (nth 9 pps))))) ;; 8 == string/comment, 9 == parens
|
||||
|
||||
;;; Syntax Compat functions
|
||||
;;
|
||||
;; Left over old APIs. Delete these someday.
|
||||
(defsubst matlab-move-simple-sexp-backward-internal (count)
|
||||
"Move backward COUNT number of MATLAB sexps."
|
||||
(let ((forward-sexp-function nil))
|
||||
(forward-sexp (- count))))
|
||||
|
||||
(defsubst matlab-move-simple-sexp-internal(count)
|
||||
"Move over one MATLAB sexp COUNT times.
|
||||
If COUNT is negative, travel backward."
|
||||
(let ((forward-sexp-function nil))
|
||||
(forward-sexp count)))
|
||||
|
||||
(provide 'matlab-syntax)
|
||||
|
||||
;;; matlab-syntax.el ends here
|
100
mlint.el
100
mlint.el
|
@ -188,8 +188,14 @@ be cause for being turned off in a buffer."
|
|||
( NOPRT . mlint-lm-quiet )
|
||||
( NOSEM . mlint-lm-delete-focus )
|
||||
( NOCOM . mlint-lm-delete-focus )
|
||||
( MSNU . mlint-lm-delete-focus )
|
||||
( ST2NM . mlint-lm-str2num )
|
||||
( FDEPR . mlint-lm-entry-deprecated )
|
||||
( ENDCT . mlint-lm-missing-end )
|
||||
( ENDCT2 . mlint-lm-missing-end )
|
||||
( FNDEF . mlint-lm-function-name )
|
||||
( MCFIL . mlint-lm-function-name )
|
||||
( MCSCC . mlint-lm-function-name )
|
||||
)
|
||||
"List of warning IDs and auto-fix functions.
|
||||
If the CAR of an association matches an error id then the linemark entry
|
||||
|
@ -468,7 +474,7 @@ ACTIVE-P if it should be made visible."
|
|||
"Return non-nil if entry E can be automatically fixed."
|
||||
(oref-default e fixable-p))
|
||||
|
||||
(cl-defmethod mlint-fix-entry :AFTER ((e mlint-lm-entry))
|
||||
(cl-defmethod mlint-fix-entry :after ((e mlint-lm-entry))
|
||||
"Stuff to do after a warning is considered fixed.
|
||||
Subclasses fulfill the duty of actually fixing the code."
|
||||
(linemark-display e nil)
|
||||
|
@ -497,6 +503,8 @@ Subclasses fulfill the duty of actually fixing the code."
|
|||
)
|
||||
(goto-char s)
|
||||
(delete-region (point) e)
|
||||
;; If this happened to be at end of line, just delete all left over whitespace.
|
||||
(when (looking-at "\\s-*$") (delete-horizontal-space))
|
||||
(point)
|
||||
))
|
||||
)
|
||||
|
@ -508,13 +516,13 @@ Subclasses fulfill the duty of actually fixing the code."
|
|||
"Class which can replace the focus area."
|
||||
:abstract t)
|
||||
|
||||
(cl-defmethod initialize-instance :AFTER ((this mlint-lm-replace-focus)
|
||||
(cl-defmethod initialize-instance :after ((this mlint-lm-replace-focus)
|
||||
&rest fields)
|
||||
"Calculate the new fix description for THIS.
|
||||
Optional argument FIELDS are the initialization arguments."
|
||||
;; After basic initialization, update the fix description.
|
||||
(oset this fix-description
|
||||
(concat (oref-default mlint-lm-replace-focus fix-description)
|
||||
(concat (oref-default this fix-description)
|
||||
(oref this new-text))))
|
||||
|
||||
(cl-defmethod mlint-fix-entry ((ent mlint-lm-replace-focus))
|
||||
|
@ -533,7 +541,7 @@ Optional argument FIELDS are the initialization arguments."
|
|||
"Entry for anything that is deprecated.
|
||||
Extracts the replacement for the deprecated symbol from the warning message.")
|
||||
|
||||
(cl-defmethod initialize-instance :AFTER ((this mlint-lm-entry-deprecated)
|
||||
(cl-defmethod initialize-instance :after ((this mlint-lm-entry-deprecated)
|
||||
&rest fields)
|
||||
"Calculate the 'new text' for THIS instance.
|
||||
Optional argument FIELDS are the initialization arguments."
|
||||
|
@ -544,10 +552,33 @@ Optional argument FIELDS are the initialization arguments."
|
|||
(oset this new-text newfcn)
|
||||
;; After basic initialization, update the fix description.
|
||||
(oset this fix-description
|
||||
(concat (oref-default mlint-lm-replace-focus fix-description)
|
||||
(concat (oref-default this fix-description)
|
||||
newfcn))
|
||||
))
|
||||
|
||||
(defclass mlint-lm-function-name (mlint-lm-replace-focus)
|
||||
()
|
||||
"When function name is missmatched with the file name."
|
||||
)
|
||||
|
||||
(cl-defmethod initialize-instance :after ((this mlint-lm-function-name) &rest fields)
|
||||
"Compute the 'new text' for THIS to be the file name from the message.
|
||||
Optional arguments FIELDS are the initialization arguments."
|
||||
(let* ((warn (oref this warning))
|
||||
(junk (or (string-match "file name: '\\([a-zA-z][a-zA-z0-9]+\\)'" warn)
|
||||
(string-match "do not agree: '\\([a-zA-z][a-zA-z0-9]+\\)'" warn)
|
||||
(string-match "of the subclass '\\([a-zA-z][a-zA-z0-9]+\\)'" warn))
|
||||
)
|
||||
(newfcn (when junk (match-string 1 warn))))
|
||||
(oset this new-text newfcn)
|
||||
;; After basic initialization, update the fix description.
|
||||
(oset this fix-description
|
||||
(concat (oref-default this fix-description)
|
||||
newfcn))
|
||||
))
|
||||
|
||||
;;; Custom auto-fix entries
|
||||
;;
|
||||
(defclass mlint-lm-entry-logicals (mlint-lm-entry)
|
||||
((fixable-p :initform t)
|
||||
(fix-description :initform "perform a replacement.")
|
||||
|
@ -600,6 +631,53 @@ Optional argument FIELDS are the initialization arguments."
|
|||
(insert ";"))
|
||||
)
|
||||
|
||||
(defclass mlint-lm-missing-end (mlint-lm-entry)
|
||||
((fixable-p :initform t)
|
||||
(fix-description :initform "Add matching end for this line."))
|
||||
"Missing end with guess as to where it might go."
|
||||
)
|
||||
|
||||
(cl-defmethod mlint-fix-entry ((ent mlint-lm-missing-end))
|
||||
"Add semi-colon to end of this line."
|
||||
(save-excursion
|
||||
(let* ((msg (oref ent warning))
|
||||
line blockname)
|
||||
;; Extract info about this.
|
||||
(when (string-match "(after line \\([0-9]+\\))" msg)
|
||||
(setq line (match-string 1 msg)))
|
||||
(when (string-match "possibly matching \\([A-Z]+\\)\\." msg)
|
||||
(setq blockname (match-string 1 msg)))
|
||||
|
||||
;; Did we get the right kind of warning
|
||||
(if line
|
||||
;; We have a line number, just go for it there.
|
||||
(progn
|
||||
(mlint-goto-line (string-to-number line))
|
||||
;; add the end and indent
|
||||
(indent-region (point) (save-excursion (insert "end\n") (point)))
|
||||
)
|
||||
(if (and blockname (string= blockname "FUNCTION"))
|
||||
;; It is a function, but no line number. Let's guess where this end
|
||||
;; should go.
|
||||
(save-excursion
|
||||
(mlint-goto-line (oref ent line)) ;; go to the fcn
|
||||
(end-of-line)
|
||||
(if (re-search-forward "^function " nil t)
|
||||
(progn
|
||||
(beginning-of-line)
|
||||
;; skip over comments that might be headers to the found function.
|
||||
(matlab-previous-command-begin
|
||||
(matlab-compute-line-context 2)) ;;(matlab-find-prev-code-line)
|
||||
(forward-line 1)
|
||||
(save-excursion (insert "end\n\n"))
|
||||
(matlab-indent-line))
|
||||
(goto-char (point-max))
|
||||
(save-excursion (insert "\nend\n\n"))
|
||||
(matlab-indent-line))))
|
||||
)
|
||||
))
|
||||
)
|
||||
|
||||
;;; User functions
|
||||
;;
|
||||
(defun mlint-highlight (err)
|
||||
|
@ -740,10 +818,14 @@ Highlight problems and/or cross-function variables."
|
|||
(if (not n)
|
||||
(message "No warning at point.")
|
||||
(let ((col (matlab-comment-on-line)))
|
||||
(or col (end-of-line))
|
||||
(insert " %#ok")
|
||||
;; Add spaces if there was a comment.
|
||||
(when col (insert " ")))
|
||||
(if col
|
||||
(progn
|
||||
(goto-char col)
|
||||
(skip-chars-forward "% ")
|
||||
(insert "#ok "))
|
||||
(end-of-line)
|
||||
(insert " %#ok"))
|
||||
)
|
||||
;; This causes inconsistencies.
|
||||
;; (linemark-delete n)
|
||||
))
|
||||
|
|
|
@ -206,7 +206,7 @@ Return argument is:
|
|||
(while (re-search-forward semantic-matlab-match-methods-block-re nil end)
|
||||
(save-excursion ;; find end of properties block
|
||||
(goto-char (match-beginning 0))
|
||||
(matlab-forward-sexp nil nil)
|
||||
(matlab-forward-sexp nil)
|
||||
(setq tmpend (point)))
|
||||
|
||||
(setq attrs (semantic-matlab-parse-attributes-and-move))
|
||||
|
@ -239,7 +239,7 @@ Return argument is:
|
|||
(setq attrs (semantic-matlab-parse-attributes-and-move))
|
||||
|
||||
(save-excursion ;; find end of properties block
|
||||
(matlab-forward-sexp nil t)
|
||||
(matlab-forward-sexp t)
|
||||
(beginning-of-line)
|
||||
(setq tmpend (point)))
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
;; Create the database, and add it to searchable databases for matlab mode.
|
||||
(defvar-mode-local matlab-mode semanticdb-project-system-databases
|
||||
(list
|
||||
(semanticdb-project-database-matlab "Matlab"))
|
||||
(make-instance 'semanticdb-project-database-matlab))
|
||||
"Search MATLAB path for symbols.")
|
||||
|
||||
;; NOTE: Be sure to modify this to the best advantage of your
|
||||
|
@ -99,7 +99,7 @@ Create one of our special tables that can act as an intermediary."
|
|||
;; We need to return something since there is always the "master table"
|
||||
;; The table can then answer file name type questions.
|
||||
(when (not (slot-boundp obj 'tables))
|
||||
(let ((newtable (semanticdb-table-matlab "MATLAB system table")))
|
||||
(let ((newtable (make-instance 'semanticdb-table-matlab)))
|
||||
(oset obj tables (list newtable))
|
||||
(oset newtable parent-db obj)
|
||||
(oset newtable tags nil)
|
||||
|
@ -337,8 +337,7 @@ Return a list of tags."
|
|||
(let ((files (semanticdb-matlab-find-name regex 'regex)))
|
||||
(delq nil
|
||||
(mapcar #'(lambda (x)
|
||||
(let ((matlab-vers-on-startup nil))
|
||||
(car (semanticdb-file-stream x))))
|
||||
(car (semanticdb-file-stream x)))
|
||||
files)))))
|
||||
|
||||
(cl-defmethod semanticdb-find-tags-for-completion-method
|
||||
|
@ -378,8 +377,7 @@ Returns a table of all matching tags."
|
|||
;; generate tags
|
||||
(delq nil
|
||||
(mapcar #'(lambda (x)
|
||||
(let ((matlab-vers-on-startup nil))
|
||||
(car (semanticdb-file-stream x))))
|
||||
(car (semanticdb-file-stream x)))
|
||||
compdb)))))
|
||||
|
||||
(provide 'semanticdb-matlab)
|
||||
|
|
|
@ -20,8 +20,11 @@ VERSION=4.0
|
|||
DISTDIR=$(top)matlab-emacs-$(VERSION)/tests
|
||||
|
||||
|
||||
|
||||
ifdef OS # No MATLAB shell tests on windows.
|
||||
all: tests matlab modetests
|
||||
else # The OS variable is only defined on windows, so linux systems can run shell tests.
|
||||
all: tests matlab modetests shelltests
|
||||
endif
|
||||
|
||||
.PHONY: modetests
|
||||
modetests: metest.elc
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
% >>1
|
||||
classdef blocks < handle
|
||||
% !!0
|
||||
|
||||
% >>11
|
||||
properties %!!4
|
||||
normalprop = 1; %!!8
|
||||
end % <<11
|
||||
|
||||
%>>12
|
||||
properties(Access='public') %!!4
|
||||
|
||||
% See if we can create properties using keywords
|
||||
%properties = 1;
|
||||
%methods = 1;
|
||||
%events = 1;
|
||||
arguments %!!8
|
||||
prop = 1;
|
||||
|
||||
end %<<12
|
||||
|
||||
% >> 13
|
||||
events (Access='private') %!!4
|
||||
|
||||
%properties
|
||||
%events
|
||||
%methods
|
||||
arguments %#ok %!!8
|
||||
misc %!!8
|
||||
|
||||
end % <<13
|
||||
|
||||
%>>14
|
||||
methods %!!4
|
||||
|
||||
%>>15
|
||||
function simple_method(obj) %!!8
|
||||
%>>151
|
||||
arguments %!!12
|
||||
obj %!!16
|
||||
end %<<151
|
||||
|
||||
disp(obj.normalprop);
|
||||
end %<<15
|
||||
|
||||
%>>16
|
||||
function obj = blocks(arguments,events,properties,methods,enumeration,normal)%!!8
|
||||
%>>161
|
||||
arguments %!!12
|
||||
arguments%!!16
|
||||
events%!!16
|
||||
properties%!!16
|
||||
methods%!!16
|
||||
enumeration%!!16
|
||||
normal%!!16
|
||||
end %<<161
|
||||
|
||||
obj.prop = arguments;%!!12
|
||||
obj.prop = events;%!!12
|
||||
obj.prop = properties;%!!12
|
||||
obj.prop = methods;%!!12
|
||||
obj.prop = enumeration;%!!12
|
||||
obj.prop = normal;%!!12
|
||||
end %<<16
|
||||
|
||||
%>>17
|
||||
function properties(~)%!!8
|
||||
end %<<17
|
||||
|
||||
%>>18
|
||||
function methods(~)%!!8
|
||||
end %<<18
|
||||
|
||||
%>>19
|
||||
function events(~)%!!8
|
||||
end %<<19
|
||||
|
||||
%>>20
|
||||
function events=arguments(arguments)%!!8
|
||||
arguments, arguments(:,:) {mustBeNumeric}, end %!!12
|
||||
%^ ^kw ^vn ^ty ^df ^kw ^co
|
||||
enumeration ... %!!12
|
||||
...%^ ^df
|
||||
= arguments;
|
||||
%^ ^df
|
||||
|
||||
if enumeration > 0 %!!12
|
||||
arguments = -enumeration; %!!16
|
||||
%^ ^df ^bi ^df
|
||||
end %!!12
|
||||
|
||||
events ... %!!12
|
||||
= arguments + 1;
|
||||
%^ ^df
|
||||
|
||||
end %<<20
|
||||
|
||||
%>>21
|
||||
function enumeration(~)%!!8
|
||||
%^ ^fn
|
||||
end %<<21
|
||||
|
||||
function y = multiple_arg_blocks(a, b, varargin) %!!8
|
||||
|
||||
arguments %!!12
|
||||
%^ ^kw
|
||||
a uint32 %!!16
|
||||
%^ ^vn ^ty
|
||||
b uint32 %!!16
|
||||
%^ ^vn ^ty
|
||||
end %!!12
|
||||
%^ ^kw
|
||||
|
||||
arguments (Repeating) %!!12
|
||||
%^ ^kw ^ty
|
||||
varargin %!!16
|
||||
%^ ^vn
|
||||
end %!!12
|
||||
%^ ^kw
|
||||
|
||||
y = a+b+length(varargin); %!!12
|
||||
|
||||
end
|
||||
|
||||
function linLog(x,y,scale)
|
||||
arguments(Repeating) %!!12
|
||||
x (1,:) double
|
||||
y (1,:) double
|
||||
end %!!12
|
||||
arguments %!!12
|
||||
scale.Plottype(1,1) string %!!16
|
||||
%^ ^vn ^vn ^ty ^ty
|
||||
end %!!12
|
||||
|
||||
sprintf('%d %d %s\n', x, y, scale);
|
||||
end
|
||||
|
||||
|
||||
%>>22
|
||||
function usestuff(obj)%!!8
|
||||
% Try using the methods of this object
|
||||
obj.properties();%!!12
|
||||
obj.methods();%!!12
|
||||
obj. events();%!!12
|
||||
obj. arguments();%!!12
|
||||
obj. enumeration();%!!12
|
||||
normal();%!!12
|
||||
end %<<22
|
||||
|
||||
%>>23
|
||||
function [m,s] = blarg(~, arguments)%!!8
|
||||
% Starter comments.
|
||||
|
||||
%>>231
|
||||
arguments%!!12
|
||||
~%!!16
|
||||
arguments(:,:) {mustBeNumeric}%!!16
|
||||
end %<<231
|
||||
|
||||
m = mean( ...%!!12
|
||||
arguments, 'all'); %!!16
|
||||
|
||||
arguments = 1;%!!12
|
||||
events = arguments;%!!12
|
||||
methods = events;%!!12
|
||||
properties = methods;%!!12
|
||||
enumeration = properties;%!!12
|
||||
|
||||
s = enumeration;%!!12
|
||||
end %<<23
|
||||
|
||||
%>>24
|
||||
function s = simple(~,arguments)%!!8
|
||||
% Simple function
|
||||
|
||||
events = arguments;%!!12
|
||||
methods = events;%!!12
|
||||
properties = methods;%!!12
|
||||
enumeration = properties;%!!12
|
||||
|
||||
s = enumeration; %!!12
|
||||
end %<<24
|
||||
|
||||
function methods=foo3(obj,properties) %!!8
|
||||
methods=obj.arguments(properties); %!!12
|
||||
end %!!8
|
||||
|
||||
function s=struct_stuff(~) %!!8
|
||||
|
||||
s.if = 1; %!!12
|
||||
s.else = 1.5; %!!12
|
||||
s.while = 2; %!!12
|
||||
s.switch = 3; %!!12
|
||||
s.case = 3.1; %!!12
|
||||
s.end = 5; %!!12
|
||||
|
||||
end %!!8
|
||||
|
||||
function tightcomments(~)%!!8
|
||||
if condition%!!12
|
||||
switch thing %!!16
|
||||
case b %!!18
|
||||
end%!!16
|
||||
end%!!12
|
||||
end%!!8
|
||||
|
||||
%!!8
|
||||
end %<<14
|
||||
|
||||
%!!4
|
||||
end % <<1
|
||||
|
||||
%!!0
|
|
@ -0,0 +1,47 @@
|
|||
function complete (a_arg1, b_arg2)
|
||||
% This function is for testing completion tools
|
||||
|
||||
arguments
|
||||
a_arg1 (1,1) double
|
||||
b_arg2 (2,1) int
|
||||
end
|
||||
|
||||
global a_global
|
||||
global b_global
|
||||
|
||||
a_localvar = 1;
|
||||
b_localvar = 1;
|
||||
|
||||
for a_for=1:10
|
||||
end
|
||||
|
||||
if bool_var
|
||||
end
|
||||
|
||||
switch a_switch
|
||||
end
|
||||
|
||||
a_
|
||||
% @@(solo var "a_localvar" "a_switch" "a_for" "a_global" "a_arg1")
|
||||
% @@(solo fcn )
|
||||
|
||||
% Note: For b, there are other test files the completion
|
||||
% engine will find, so they are included.
|
||||
b
|
||||
% @@(solo fcn "blocal_fcn" "blazy_fcn" "buggy" "blocks")
|
||||
% @@(solo var "b_localvar" "bool_var" "b_global" "b_arg2")
|
||||
|
||||
|
||||
% quiet mlint
|
||||
blocal_fcn(a_arg1, b_arg2, a_localvar, b_localvar, a_global, b_global);
|
||||
end
|
||||
|
||||
function blocal_fcn(varargin)
|
||||
|
||||
blazy_fcn(varargin{:});
|
||||
|
||||
end
|
||||
|
||||
function blazy_fcn(varargin)
|
||||
end
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
function continuations(a,b) %!!0
|
||||
% !!0 Help Comment
|
||||
|
||||
arguments (Repeating)
|
||||
a (1,1) ... % !!8
|
||||
double % !!12
|
||||
b (1,1) double { mustBeSomething ... %!!8
|
||||
mustBeSomethingElse } %!!25
|
||||
end
|
||||
|
||||
global var1, ... % !!4
|
||||
var2 % !!8
|
||||
|
||||
localfcn(a,b); % !!4
|
||||
|
||||
localfcn(var1, ... % !!4
|
||||
var2); % !!13
|
||||
|
||||
localfcn(a, localfcn(b, localfcn(var1,... %!!4
|
||||
var2)... %!37
|
||||
)... %!!24
|
||||
); %!!12
|
||||
|
||||
|
||||
code1(), ...
|
||||
code2(); %!!8
|
||||
|
||||
% NOTE: Blank space below should cancel the indent effect of ellipsis.
|
||||
code1() ...
|
||||
|
||||
var1 = 1 + ... %!!4
|
||||
... %!!11
|
||||
2 + ... %!!11
|
||||
3; %!!11
|
||||
|
||||
medvar = 1 + ... %!!4
|
||||
2; %!!13
|
||||
|
||||
long_var_name = 1 + ... %!!4
|
||||
2; %!!8
|
||||
|
||||
localfcn (medvar, ... %!!4
|
||||
long_var_name); %!!19
|
||||
|
||||
localfcn( ... %!!4
|
||||
a,b); %!!8
|
||||
|
||||
|
||||
if true, if true, if true %#ok %!!4
|
||||
localfcn(a,b); ... %!!16
|
||||
end; ... %!!4
|
||||
end; ... %!!4
|
||||
end ... %!!4
|
||||
|
||||
odd_if_location(); %!!4 - this after those continued ends
|
||||
|
||||
|
||||
... % !!4 A continuation with a ctrl block after it
|
||||
for g=1:10 %#ok % !!8 b/c continuation
|
||||
localfcn(a,g) % !!8 b/c not continued, and +4 from comment continuation
|
||||
end % !!4 to match
|
||||
|
||||
% !!4 to undo continuation.
|
||||
|
||||
% Indent past 1st arg for special functions
|
||||
set(myhandle, 'Prop1', value, ... %!!4
|
||||
'Prop2', value, ... %!!18
|
||||
'Prop3', value); %!!18
|
||||
|
||||
% Indent past = sign for assignments.
|
||||
A = 1 + ... % !!4
|
||||
2; % !!8
|
||||
|
||||
medvar = 1 + ... % !!4
|
||||
2; % !!13
|
||||
|
||||
alongvariablename = 1 +... % !!4
|
||||
2; % !!8
|
||||
|
||||
|
||||
fancyfunctionname(arg1, ... %!!4
|
||||
innerfcn(arg2, ... %!!22
|
||||
arg3), ... %!!31
|
||||
{ cell1; %!!22
|
||||
cell2; %!!24
|
||||
[ 1 2 ; %!!24
|
||||
3 4 ] ; %!!26
|
||||
cell 4 },... %!!24
|
||||
arg5); %!!22
|
||||
|
||||
|
||||
... % Continuation by itself just before an end.
|
||||
end %!!0
|
||||
|
||||
function [ a, ... !!0
|
||||
b, ... !!11
|
||||
c, ... !!11
|
||||
d ] ... !!11
|
||||
= continuations_in_return(opt)
|
||||
% H1 Comment Line !!0
|
||||
|
||||
code(); %!! 4
|
||||
|
||||
end %!! 0
|
||||
|
||||
function [ a, b ] = continuation_in_args(a,...
|
||||
b) %!!41
|
||||
% H1 comment line !!0
|
||||
|
||||
end
|
||||
|
||||
function c=expression_cont(a,b)
|
||||
% H1 line !!0
|
||||
|
||||
if (a > 0 && ... %!!4
|
||||
b < 0) %!!8
|
||||
|
||||
% comment one !!8
|
||||
c=1; %!!8
|
||||
elseif (a < 0 && ... %!!4
|
||||
b > 0) %!!12
|
||||
|
||||
% comment two !!8
|
||||
c=2; %!!8
|
||||
end %!!4
|
||||
|
||||
switch a %!!4
|
||||
case 'ert' %!!6
|
||||
b = 1; %!!8
|
||||
case {'sim', ... %!!6
|
||||
'normalsim'} %!!12
|
||||
b=2; %!!8
|
||||
end %!!4
|
||||
|
||||
end
|
||||
|
||||
function a=odd_if_location(n) %!!0
|
||||
|
||||
i=1; while i<10, if xfcn(i,n)==0, i=i+1; %!!4
|
||||
else, i=20; end; end %!!21
|
||||
|
||||
if i<20 %!!4
|
||||
a=1; %!!8
|
||||
else %!!4
|
||||
a=0; %!!8
|
||||
end %!!4
|
||||
|
||||
foo();
|
||||
end %!!0
|
||||
|
||||
function val = localfcn(c,d) %!!0
|
||||
% !!0 Help Comment
|
||||
|
||||
try fclose( fid ); catch, end %!!4
|
||||
|
||||
val = c+d; % !!4
|
||||
|
||||
odd_end_location_from_dspfwiz_load(1);
|
||||
|
||||
end %!!0
|
||||
|
||||
function [z,o,n]=odd_end_location_from_dspfwiz_load(opts) %!!0
|
||||
if opts.zeros, z = 'On'; %!!4
|
||||
else, z = 'Off'; end %!!4
|
||||
|
||||
if opts.ones, o = 'On'; %!!4
|
||||
else, o = 'Off'; end %!!4
|
||||
|
||||
if opts.neg_ones, n = 'On'; %!!4
|
||||
else, n = 'Off'; end %!!4
|
||||
end %!!0
|
||||
|
||||
function a=foo
|
||||
%{
|
||||
for !!2
|
||||
for !!2
|
||||
%}
|
||||
if true %#ok %!!4
|
||||
if true %!!8
|
||||
a = 1; %!!12
|
||||
end end %#ok %!!8
|
||||
end %!!0
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
% Empty M file.
|
||||
% %%%empty guess guess
|
165
tests/fontlock.m
165
tests/fontlock.m
|
@ -1,7 +1,35 @@
|
|||
function [a, b, c] = fontlock(input1, ...
|
||||
input2, ...
|
||||
input3)
|
||||
% FONTLOCK testing function for Emacs & MATLAB.
|
||||
|
||||
% TEST FILE FOR FONT LOCK SPECIAL WORDS
|
||||
function fontlock()
|
||||
%^ ^kw ^fn ^df
|
||||
%^ ^ig
|
||||
|
||||
% $$$ ignored comment
|
||||
%^ ^ig
|
||||
|
||||
persistent var1 % !!4
|
||||
%^ ^kw ^vn ^co
|
||||
|
||||
global var2 % !!4
|
||||
%^ ^kw ^vn ^co
|
||||
|
||||
end
|
||||
%^ ^kw
|
||||
|
||||
function [ var1, var2 ] = local(input1)
|
||||
%^ ^kw ^vn ^fn ^vn ^df
|
||||
|
||||
end
|
||||
|
||||
function [a, b] = local2(input1,...
|
||||
input2)
|
||||
%^ ^vn
|
||||
end
|
||||
|
||||
% TODO - these are cross function variables, but we turn off mlint in
|
||||
% tests, so these aren't tested.
|
||||
function [a, b, c] = localvars(input1, input2, input3)
|
||||
%^ ^kw ^vn ^fn ^vn ^vn ^vn ^df
|
||||
|
||||
nested(input1);
|
||||
|
||||
|
@ -17,5 +45,134 @@ function [a, b, c] = fontlock(input1, ...
|
|||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function keywordstuff()
|
||||
|
||||
while true
|
||||
%^ ^kw ^ma
|
||||
|
||||
for varname=1:10
|
||||
%^ ^kw ^vn ^cn
|
||||
break
|
||||
%^ ^kw
|
||||
end
|
||||
|
||||
if varname == 2
|
||||
%^ ^kw ^df ^bi ^df
|
||||
disp(1)
|
||||
elseif varname==3
|
||||
%^ ^kw ^df ^bi
|
||||
disp(2)
|
||||
else
|
||||
%^ ^kw
|
||||
disp(3)
|
||||
end
|
||||
%^ ^kw
|
||||
|
||||
switch varname
|
||||
%^ ^kw ^cn
|
||||
case 1
|
||||
%^ ^kw ^cn
|
||||
disp(1)
|
||||
continue
|
||||
%^ ^kw
|
||||
case 2
|
||||
%^ ^kw ^cn
|
||||
disp(2)
|
||||
otherwise
|
||||
%^ ^kw
|
||||
disp('other');
|
||||
%^ ^df ^st
|
||||
return
|
||||
%^ ^kw
|
||||
end
|
||||
%^ ^kw
|
||||
|
||||
try
|
||||
%^ ^kw
|
||||
disp(1)
|
||||
catch
|
||||
%^ ^kw
|
||||
disp(2)
|
||||
end
|
||||
%^ ^kw
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function dographics(value)
|
||||
|
||||
f = figure;
|
||||
%^ ^bi
|
||||
ax = axes(f);
|
||||
%^ ^bi
|
||||
|
||||
set ( ax, 'property',value)
|
||||
%^ ^bi ^vn ^st
|
||||
|
||||
s = open_system('foo.mdl');
|
||||
%^ ^si ^st
|
||||
|
||||
set_param(s, 'param', value);
|
||||
%^ ^si ^vn ^st ^df
|
||||
end
|
||||
|
||||
function dodebug()
|
||||
|
||||
dbstop in dodebug
|
||||
%^ ^bo ^cd
|
||||
|
||||
dbclear
|
||||
%^ ^bo
|
||||
|
||||
end
|
||||
|
||||
function mathstuff()
|
||||
|
||||
myvar = eps + pi + nan + ans + i + NaT + true ;
|
||||
%^ ^df ^ma ^bi ^ma ^bi ^ma ^bi ^ma ^bi ^ma ^bi ^ma ^bi ^ma ^df
|
||||
end
|
||||
|
||||
function helptest()
|
||||
% HELPTEXT has fancy fonts in it.
|
||||
%^ ^cn
|
||||
|
||||
end
|
||||
|
||||
function name_no_args
|
||||
%^ ^kw ^fn
|
||||
end
|
||||
|
||||
function retarg = ret_and_name_no_args % comment
|
||||
%^ ^kw ^vn ^df ^fn ^co
|
||||
end
|
||||
|
||||
function retarg = args_have_cont (arg_1, ...
|
||||
arg_2)
|
||||
%^ ^vn
|
||||
end
|
||||
|
||||
function [ retarg1, ...
|
||||
retarg2, ...
|
||||
retarg3 ] ...
|
||||
= name_of_fcn (arg1)
|
||||
%^ ^df ^fn ^vn ^df
|
||||
|
||||
end
|
||||
|
||||
classdef (Abstract) myclass < handle
|
||||
%^ ^kw ^ty ^fn ^bi ^cn
|
||||
end
|
||||
|
||||
classdef (Abstract)myclass<handle
|
||||
%^ ^kw ^ty ^fn ^bi ^ty
|
||||
end
|
||||
|
||||
%{
|
||||
% Local Variables:
|
||||
% matlab-show-mlint-warnings: nil
|
||||
% End:
|
||||
%}
|
||||
|
||||
|
|
194
tests/indents.m
194
tests/indents.m
|
@ -1,4 +1,5 @@
|
|||
function indents(a,b,stuff)
|
||||
|
||||
function indents(a,b,stuff,cmddual1fake,cmddual2fake)
|
||||
% Help text
|
||||
% !!0
|
||||
% of many lines
|
||||
|
@ -11,17 +12,28 @@ function indents(a,b,stuff)
|
|||
a (1,1) {mustBeNumeric} % !!8
|
||||
b (:,:) double % !!8
|
||||
stuff {mustBeMember(stuff, { 'this' 'that' 'other' })} % !!8
|
||||
cmddual1fake double % !!8
|
||||
cmddual2fake int % !!8
|
||||
end % !!4
|
||||
|
||||
persistent var1 % !!4
|
||||
global var2 % !!4
|
||||
persistent var3 % !!4
|
||||
|
||||
|
||||
locala = a; %#ok
|
||||
localb = b; %#ok
|
||||
localstuff = stuff; %#ok
|
||||
|
||||
ends_in_comments_and_strings(); % has end in name
|
||||
if isempty(var1) var1=1; end %#ok !!4
|
||||
if isempty(var3) var3=2; end %#ok !!4
|
||||
|
||||
ends_in_comments_and_strings(var1, var2, var3); % !!4 has end in name
|
||||
|
||||
% !!4
|
||||
|
||||
block_starts_in_comments_and_strings();
|
||||
block_starts_in_comments_and_strings(cmddual1fake,cmddual2fake);
|
||||
array_constant_decls();
|
||||
|
||||
% !!4
|
||||
|
||||
|
@ -30,7 +42,7 @@ function indents(a,b,stuff)
|
|||
% $$$ !!0
|
||||
% $$$ special ignore comments
|
||||
|
||||
has_nested_fcn();
|
||||
has_nested_fcn(); % !!4
|
||||
|
||||
% !!4 - after ignore comments
|
||||
|
||||
|
@ -52,7 +64,8 @@ function B = ends_in_comments_and_strings()
|
|||
|
||||
B = A(1:end); %#ok
|
||||
|
||||
if foo
|
||||
%% cell start comment !!4
|
||||
if foo %!!4
|
||||
C = "this is the end of the line";
|
||||
% !!8
|
||||
else %!!4
|
||||
|
@ -88,12 +101,6 @@ function B = ends_in_comments_and_strings()
|
|||
end ... the other end
|
||||
% !! 4
|
||||
|
||||
code1() ...
|
||||
code2(); %!!8
|
||||
|
||||
% NOTE: Blank space below should cancel the indent effect of ellipsis.
|
||||
code1() ...
|
||||
|
||||
B = [ B A ]; % !!4
|
||||
|
||||
str = 'This is a char array with ... in it';
|
||||
|
@ -102,7 +109,7 @@ function B = ends_in_comments_and_strings()
|
|||
fcncall(arg1, '...', arg3); % !!4
|
||||
1; % !!4
|
||||
|
||||
% Multi-ends
|
||||
% Multi- end s
|
||||
% >>8
|
||||
if foo %#ok
|
||||
if bar %#ok
|
||||
|
@ -119,21 +126,123 @@ function B = ends_in_comments_and_strings()
|
|||
|
||||
end
|
||||
|
||||
function C = block_starts_in_comments_and_strings()
|
||||
function out = array_constant_decls()
|
||||
|
||||
A = [ 1 2 3 ]; %!!4
|
||||
|
||||
Blong = [ 1 2; %!!4
|
||||
3 4; %!!14
|
||||
]; %!!12
|
||||
|
||||
Csep = [
|
||||
1 2; %!!8
|
||||
3 4; %!!8
|
||||
]; %!!11
|
||||
|
||||
multinest = { [ 1 2 %!!4
|
||||
3 4 ]; %!!20
|
||||
{ 5 6 7 ... %!!18
|
||||
8 9 10 ... %!!20
|
||||
}; %!!18
|
||||
fcncall(10, ... %!!18
|
||||
12, ... %!!26
|
||||
[ 13 14; %!!26
|
||||
15 16 ]) %!!28
|
||||
} ; %!!16
|
||||
|
||||
nest = { ... %!!4
|
||||
1 %!!8
|
||||
[ ... %!!8
|
||||
2 3 %!!10
|
||||
] ... %!!8
|
||||
3 %!!8
|
||||
}; %!!11
|
||||
|
||||
cascade_long_name = ... %!!4
|
||||
{ ... %!!8
|
||||
1 %!!10
|
||||
2 %!!10
|
||||
}; %!!8
|
||||
|
||||
% TODO
|
||||
% I don't know why the below indents this way.
|
||||
% It should either do all max indent, or all lined up with parens.
|
||||
thing.thing.long.long.longname({ 'str' %!!4
|
||||
'str' %!!37
|
||||
'str' %!!37
|
||||
'str' %!!37
|
||||
}); %!!35
|
||||
|
||||
thing.thing.long.long.longname('str', ... %!!4
|
||||
'str', ... %!!35
|
||||
'str', ... %!!35
|
||||
'str' ... %!!35
|
||||
); %!!34
|
||||
|
||||
% Line starting with end inside parens
|
||||
disp(Csep(1: ... %!!4
|
||||
end)); %!!14
|
||||
|
||||
% This array has bad syntactic expression parsing due to the
|
||||
% apostrophy
|
||||
Closures = [
|
||||
755009 ; ... % 21-Feb-2067 Washington's Birthday (Mon)
|
||||
755010 ; % !!8
|
||||
];
|
||||
|
||||
dep = [
|
||||
root(info.function, factory, workspace, []), ... % likewise this isn't a keyword
|
||||
fcn3.finalize % the single quote used to break [] scanning
|
||||
];
|
||||
|
||||
% This long fcn name last symbol starts with 'get' which
|
||||
% used to confuse and move to indent past 1st arg.
|
||||
if qesimcheck.utils.GetYesNoAnswer('Do ',... !!4
|
||||
'n',... !!39
|
||||
'once') %!!39
|
||||
code(); %!!8
|
||||
end %!!4
|
||||
|
||||
|
||||
|
||||
% !!4
|
||||
out = { A %!!4
|
||||
Blong %!!12
|
||||
Csep %!!12
|
||||
nest %!!12
|
||||
multinest%!!12
|
||||
cascade_long_name%!!12
|
||||
Closures%!!12
|
||||
dep %!!12
|
||||
}; %!!10
|
||||
|
||||
end
|
||||
|
||||
function C = block_starts_in_comments_and_strings(varargin)
|
||||
% !!0
|
||||
|
||||
C = 0;
|
||||
|
||||
if true % if true
|
||||
if varargin{1} % if true
|
||||
|
||||
% !!8
|
||||
else % !!4
|
||||
|
||||
% !!8
|
||||
end % if true
|
||||
|
||||
|
||||
% see previous function
|
||||
% !!4
|
||||
for x=1:length(C) % !!4
|
||||
if varargin{2} % !!8
|
||||
continue % !!12
|
||||
end % !!8
|
||||
|
||||
% !!8
|
||||
break % !!8
|
||||
% !!14
|
||||
|
||||
%!!8
|
||||
end
|
||||
|
||||
switch foo() %!!4
|
||||
|
@ -160,10 +269,12 @@ function B = continuations_and_block_comments
|
|||
% !!0
|
||||
% !!0
|
||||
|
||||
%{
|
||||
!!6
|
||||
!!6
|
||||
%}
|
||||
%{
|
||||
!!2 { }
|
||||
!!2
|
||||
%}
|
||||
|
||||
arg1=1;
|
||||
|
||||
%{
|
||||
% !!4
|
||||
|
@ -188,9 +299,9 @@ function B = continuations_and_block_comments
|
|||
3 4 ]; % !!10
|
||||
|
||||
foo(['this is a very long string' ... %!!4
|
||||
'with a continution to do something very exciting'])%!!9
|
||||
'with a continution to do something very exciting']);%!!9
|
||||
|
||||
set(gcf,'Position',[ 1 2 3 4],... !!4
|
||||
set(gcf,'Position',[ 1 2 3 4], ... !!4
|
||||
'Color', 'red'); % !!12
|
||||
|
||||
B = A + 1 + 4 ...
|
||||
|
@ -200,6 +311,14 @@ function B = continuations_and_block_comments
|
|||
% continuation-comment !!17
|
||||
|
||||
% !!4 -blank between this & continuation comment
|
||||
% !!4 - more comments
|
||||
|
||||
if condition1 || ... % !!4
|
||||
fcn_call(arg1, ... % !!12
|
||||
arg2) % !!21
|
||||
line_in_if();
|
||||
end % !!4
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
@ -208,15 +327,44 @@ function has_nested_fcn
|
|||
|
||||
plot(1:10); %!!4
|
||||
|
||||
function am_nested_fcn %!!4
|
||||
A = 1;
|
||||
|
||||
function am_nested_fcn() %!!4
|
||||
% help
|
||||
% !!4
|
||||
code();
|
||||
code(A);
|
||||
%!!8
|
||||
end
|
||||
|
||||
%!!4
|
||||
am_nested_fcn();
|
||||
function_end_same_line(1);
|
||||
function_after_end_same_line();
|
||||
end
|
||||
|
||||
function b=function_end_same_line(a), b=a; end %!!0
|
||||
|
||||
function function_after_end_same_line()%!!0
|
||||
%!!0
|
||||
disp('foo');%!!4
|
||||
|
||||
debug_cmd_dual();
|
||||
|
||||
end%!!0
|
||||
|
||||
function debug_cmd_dual ()
|
||||
% These dbstop command dual content have 'if' blocks in them.
|
||||
% The command dual detection needs to block these from being
|
||||
% detected as block initiators which would cause indentaiton.
|
||||
|
||||
dbstop in hRandomFile at 14 if func() % !!4
|
||||
dbstop in hRandomFile at 30@1 if x==1 % !!4
|
||||
dbstop in hPFile % !!4
|
||||
dbstop in hSimpleFile at 2 % !!4
|
||||
dbstop if error % !!4
|
||||
|
||||
%!!4
|
||||
|
||||
debug_cmd_dual(); %!!4
|
||||
|
||||
end
|
|
@ -1,30 +1,39 @@
|
|||
% >>1
|
||||
classdef (abstract) mclass < handle & matlab.mixin.SetGetExactNames % #7#
|
||||
%^ ^kw ^ty ^fn ^cn ^bi ^cn ^co
|
||||
% !!0
|
||||
% %%% class class class
|
||||
|
||||
% >>11
|
||||
properties (Access='public') % #2#
|
||||
%^ ^kw ^ty ^st ^co
|
||||
|
||||
% !!8
|
||||
AP = []; % #2#
|
||||
%^ ^vn ^df ^co
|
||||
AB = 'charvec with space'; % #2#
|
||||
AC = "string with space and ( "; % #2#
|
||||
AD = fun_call(1,2); % #3#
|
||||
AE (1,:) double {mustBePositive} = 1; % #5#
|
||||
%^ ^vn ^ty ^df ^co
|
||||
end % <<11
|
||||
|
||||
% >> 111
|
||||
properties (AbortSet=true, NonCopyable=true) % #2#
|
||||
%^ ^kw ^ty ^ma ^ty ^ma ^co
|
||||
|
||||
% !!8
|
||||
AF (1,1) char {mustBeMember(AF, {'High','Medium','Low'})} = 'Low'; % #5#
|
||||
%^ ^vn ^ty ^df ^st ^df ^st ^co
|
||||
AG (1,1) matlab.lang.OnOffSwitchState = 'on'; % #6#
|
||||
%^ ^vn ^ty ^ty ^st ^co
|
||||
end % <<111
|
||||
|
||||
% >> 112
|
||||
events
|
||||
% !!8
|
||||
Event1
|
||||
%^ ^vn
|
||||
Event2
|
||||
end % <<112
|
||||
|
||||
|
@ -34,11 +43,15 @@ classdef (abstract) mclass < handle & matlab.mixin.SetGetExactNames % #7#
|
|||
|
||||
% >>16
|
||||
function obj = mclass()
|
||||
%^ ^kw ^vn ^fn ^df
|
||||
% !!8
|
||||
|
||||
obj.AB = obj.AP(1:end);
|
||||
% !!12
|
||||
|
||||
unusedvar = 1; %#ok
|
||||
%^ ^df ^pr
|
||||
|
||||
disp('charvect with if and for words [ in it'); % #2#
|
||||
|
||||
% !!12
|
||||
|
@ -46,6 +59,10 @@ classdef (abstract) mclass < handle & matlab.mixin.SetGetExactNames % #7#
|
|||
notify(obj,'Event1',...
|
||||
'indent test');
|
||||
|
||||
notify(obj, 'Event1', 'indent test');
|
||||
%^ ^df ^vn ^st ^st ^df
|
||||
|
||||
|
||||
% >>17
|
||||
while obj.AB % #3#
|
||||
|
||||
|
@ -98,6 +115,45 @@ classdef (abstract) mclass < handle & matlab.mixin.SetGetExactNames % #7#
|
|||
|
||||
end
|
||||
|
||||
methods %!!4
|
||||
|
||||
function end_separate_line(~) %!!8
|
||||
end %!!8
|
||||
|
||||
function end_same_line(~), end %!!8
|
||||
|
||||
function after_end_same_line(~), end %!!8
|
||||
|
||||
end %!!4
|
||||
|
||||
methods %!!4
|
||||
function properties(~) %!!8
|
||||
end %!!8
|
||||
|
||||
function methods(~) %!!8
|
||||
end %!!8
|
||||
|
||||
function events(~) %!!8
|
||||
end %!!8
|
||||
|
||||
function arguments(~) %!!8
|
||||
end %!!8
|
||||
|
||||
function enumeration(~) %!!8
|
||||
end %!!8
|
||||
|
||||
function usestuff(obj) %!!8
|
||||
% Try using the methods of this object
|
||||
obj.properties(); %!!12
|
||||
%^ ^df ^df ^co
|
||||
obj.methods(); %!!12
|
||||
obj.events(); %!!12
|
||||
obj.arguments(); %!!12
|
||||
obj.enumeration(); %!!12
|
||||
end %!!8
|
||||
|
||||
end %!!4
|
||||
|
||||
end % <<1
|
||||
|
||||
% End
|
|
@ -0,0 +1,8 @@
|
|||
classdef mclass_cont < otherThing & ... % !!0 This continuation can case issue for next prop block
|
||||
handle %!!8
|
||||
|
||||
properties (Dependent, SetAccess = private) %!!4
|
||||
TopicName %!!8
|
||||
end %!!4
|
||||
|
||||
end %!!0
|
594
tests/metest.el
594
tests/metest.el
|
@ -34,6 +34,7 @@
|
|||
(require 'matlab-load)
|
||||
(require 'matlab)
|
||||
(require 'cedet-matlab)
|
||||
(require 'matlab-complete)
|
||||
(require 'semantic-matlab)
|
||||
|
||||
;; Enable semantic
|
||||
|
@ -42,68 +43,224 @@
|
|||
|
||||
(defun metest-all-syntax-tests ()
|
||||
"Run all the syntax tests in this file."
|
||||
(metest-comment-string-syntax-test)
|
||||
(metest-sexp-counting-test)
|
||||
(metest-sexp-traversal-test)
|
||||
(metest-indents-test)
|
||||
(metest-parse-test)
|
||||
(setq debug-on-error t)
|
||||
(matlab-scan-stat-reset ) ;; Enable scanner statistics logging.
|
||||
|
||||
(metest-log-init)
|
||||
|
||||
(setq-default matlab-indent-function-body 'guess) ;; Force the guess system to be exercised.
|
||||
(metest-run 'metest-end-detect-test)
|
||||
(setq-default matlab-indent-function-body 'MathWorks-Standard) ;; put it back
|
||||
|
||||
(metest-run 'metest-comment-string-syntax-test)
|
||||
(metest-run 'metest-fontlock-test)
|
||||
(metest-run 'metest-sexp-counting-test)
|
||||
(metest-run 'metest-sexp-traversal-test)
|
||||
|
||||
;; Randomize indentation first before indenting
|
||||
;; to force the indenter to make changes and give
|
||||
;; the cahce and performance a harder problem.
|
||||
(metest-indents-randomize-files)
|
||||
(metest-run 'metest-indents-test)
|
||||
|
||||
;; Parsing and completion are high level tools
|
||||
(metest-run 'metest-parse-test)
|
||||
(metest-run 'metest-complete-test)
|
||||
|
||||
(metest-log-report (metest-log-write))
|
||||
|
||||
(matlab-scan-stats-print)
|
||||
)
|
||||
|
||||
(defun metest-run (test)
|
||||
"Run and time TEST."
|
||||
(let* ((config (symbol-value test))
|
||||
(name (if (stringp config) config (car config)))
|
||||
(files (or (cdr-safe config) '("")))
|
||||
(strlen (apply 'max (mapcar 'length files))))
|
||||
(message ">> Starting %s loop on %S" name files)
|
||||
(dolist (F files)
|
||||
(princ (format (concat "<< %s %-" (number-to-string strlen) "s ") name F) 'external-debugging-output)
|
||||
(let ((old debug-on-error)
|
||||
(out (progn (setq debug-on-error nil)
|
||||
(metest-timeit test F))))
|
||||
(setq debug-on-error old)
|
||||
(when (listp out)
|
||||
(princ (format "passed: %s %.2f s\n" (cdr out) (car out)) 'external-debugging-output)
|
||||
)
|
||||
))
|
||||
(message "")))
|
||||
|
||||
(defvar metest-test-error nil)
|
||||
(defmacro metest-condition-case-error-msg (&rest forms)
|
||||
"Run FORMS, capturing any errors and associating with (point)."
|
||||
(declare (indent 0) (debug t))
|
||||
`(condition-case err
|
||||
,@forms
|
||||
(error (cond (metest-test-error (error (car (cdr err))))
|
||||
(t (metest-error "Lisp: %s" (error-message-string err))))
|
||||
0)
|
||||
))
|
||||
|
||||
(defvar met-end-detect-files '("empty.m" "stringtest.m" "mfuncnoend.m" "mfuncnoendblock.m" "mfuncends.m" "mclass.m" "mfuncspacey.m" "mfuncnoendindent.m" "mfuncnofuncindent.m")
|
||||
"List of files for running end detection tests on.")
|
||||
|
||||
(defvar metest-end-detect-test (cons "END detection" met-end-detect-files))
|
||||
(defun metest-end-detect-test (F)
|
||||
"Run a test to make sure we correctly detect the state of managing 'end'."
|
||||
(let ((buf (metest-find-file F))
|
||||
(ret nil)
|
||||
(cnt 0))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
;;(message ">> Checking END detection in %S" (current-buffer))
|
||||
(if (re-search-forward "%%%\\s-*\\(\\w+\\)\\s-+\\(\\w+\\)\\s-+\\(\\w+\\)$" nil t)
|
||||
(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))
|
||||
(indent-actual (matlab-indent-function-body-p))
|
||||
)
|
||||
(unless (eq st-actual st-expect)
|
||||
(metest-error "Script type detection failure: Expected %s but found %s"
|
||||
st-expect st-actual))
|
||||
(unless (eq end-actual end-expect)
|
||||
(metest-error "Script end detection failure: Expected %s but found %s"
|
||||
end-expect end-actual))
|
||||
(unless (eq indent-actual indent-expect)
|
||||
(metest-error "Script indent detection failure: Expected %s but found %s"
|
||||
indent-expect indent-actual))
|
||||
|
||||
(setq ret (list "script[" st-actual "] end[" end-actual "] indent-p[" indent-actual "]"))
|
||||
;;(message "<< Script type and end detection passed: %s, %s" st-actual end-actual)
|
||||
)
|
||||
;; No expected values found in the file.
|
||||
(metest-error "Test file did not include expected script-type cookie")
|
||||
))
|
||||
ret))
|
||||
|
||||
(defvar met-stringtest-files '("stringtest.m")
|
||||
"List of files for running string tests on.")
|
||||
|
||||
(defun metest-comment-string-syntax-test ()
|
||||
(defvar metest-comment-string-syntax-test (cons "string/comment detection" met-stringtest-files))
|
||||
(defun metest-comment-string-syntax-test (F)
|
||||
"Run a test to make sure string nd comment highlighting work."
|
||||
(dolist (F met-stringtest-files)
|
||||
(let ((buf (find-file-noselect (expand-file-name F met-testfile-path)))
|
||||
(cnt 0))
|
||||
(let ((buf (metest-find-file F))
|
||||
(cnt 0)
|
||||
(noninteractive nil) ;; fake out font lock
|
||||
)
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
(message ">> Starting search loop in %S" (current-buffer))
|
||||
(while (re-search-forward "#\\([csveb]\\)#" nil t)
|
||||
(goto-char (match-end 1))
|
||||
(let ((md (match-data))
|
||||
(mc (match-string 1))
|
||||
(bc (matlab-ltype-block-comm))
|
||||
(qd (matlab-cursor-comment-string-context)))
|
||||
;; Test 1 - what are we?
|
||||
(unless (or (and (string= "b" mc) bc)
|
||||
(and (string= "v" mc) (eq 'charvector qd))
|
||||
(and (string= "s" mc) (eq 'string qd))
|
||||
(and (string= "c" mc) (eq 'comment qd))
|
||||
(and (string= "e" mc) (eq 'elipsis qd))
|
||||
|
||||
(let ((md (match-data)))
|
||||
;; Force font lock to throw catchable errors.
|
||||
(font-lock-mode 1)
|
||||
(font-lock-flush (point-min) (point-max))
|
||||
(font-lock-ensure (point-min) (point-max))
|
||||
(font-lock-fontify-region (point-min) (point-max))
|
||||
|
||||
;; FL test 1: make sure font lock is on and match data didn't change.
|
||||
(unless font-lock-mode
|
||||
(metest-error "Font Lock failed to turn on."))
|
||||
;;(unless (equal md (match-data))
|
||||
;; (metest-error "Font Locking transmuted the match data"))
|
||||
(when (not (get-text-property 2 'fontified))
|
||||
(metest-error "Font Lock Failure: can't run test because font lock failed to fontify region."))
|
||||
)
|
||||
(error "Syntax Test Failure @ line %d: Expected %s but found %S"
|
||||
(line-number-at-pos)
|
||||
|
||||
|
||||
;;(message ">> Starting string/comment detect loop in %S" (current-buffer))
|
||||
(while (re-search-forward "#\\([cCisSvVebdr]\\)#" nil t)
|
||||
(let* ((md (match-data))
|
||||
(pt (match-end 1))
|
||||
(mc (match-string-no-properties 1))
|
||||
(fnt (get-text-property pt 'face))
|
||||
(lv1 (matlab-compute-line-context 1))
|
||||
(bc (metest-condition-case-error-msg (matlab-line-block-comment-start lv1)))
|
||||
(qd (metest-condition-case-error-msg (matlab-cursor-comment-string-context)))
|
||||
)
|
||||
(goto-char pt)
|
||||
|
||||
;; Test 1 - what are we?
|
||||
(unless (or (and (string= "b" mc) (and bc (eq 'comment qd)))
|
||||
(and (string= "v" mc) (eq 'charvector qd))
|
||||
(and (string= "V" mc) (eq 'charvector qd))
|
||||
(and (string= "s" mc) (eq 'string qd))
|
||||
(and (string= "S" mc) (eq 'string qd))
|
||||
(and (string= "c" mc) (eq 'comment qd))
|
||||
(and (string= "C" mc) (eq 'comment qd))
|
||||
(and (string= "i" mc) (eq 'comment qd))
|
||||
(and (string= "e" mc) (eq 'ellipsis qd))
|
||||
(and (string= "d" mc) (eq 'commanddual qd))
|
||||
(and (string= "r" mc) (eq nil qd))
|
||||
)
|
||||
(metest-error "Syntax Test Failure @ char %d: Expected %s but found %S"
|
||||
pt
|
||||
(cond ((string= mc "b") "block comment")
|
||||
((string= mc "v") "charvector")
|
||||
((string= mc "V") "charvector")
|
||||
((string= mc "s") "string")
|
||||
((string= mc "S") "string")
|
||||
((string= mc "c") "comment")
|
||||
((string= mc "e") "elipsis")
|
||||
((string= mc "C") "comment")
|
||||
((string= mc "i") "comment")
|
||||
((string= mc "e") "ellipsis")
|
||||
((string= mc "d") "commanddual")
|
||||
((string= mc "r") "normal code")
|
||||
(t "unknown test token"))
|
||||
qd))
|
||||
;; Test 2 - is match-data unchanged?
|
||||
(unless (equal md (match-data))
|
||||
(error "Syntax checking transmuted the match data"))
|
||||
(metest-error "Syntax checking transmuted the match data"))
|
||||
|
||||
;; FL test 2 - Is the matched location fontified correctly?
|
||||
(when (consp fnt) (setq fnt (car fnt)))
|
||||
(unless (or (and (string= "b" mc) (eq fnt 'font-lock-comment-face))
|
||||
(and (string= "v" mc) (eq fnt 'font-lock-string-face))
|
||||
(and (string= "V" mc) (eq fnt 'matlab-unterminated-string-face))
|
||||
(and (string= "s" mc) (eq fnt 'font-lock-string-face))
|
||||
(and (string= "S" mc) (eq fnt 'matlab-unterminated-string-face))
|
||||
(and (string= "c" mc) (eq fnt 'font-lock-comment-face))
|
||||
(and (string= "C" mc) (eq fnt 'matlab-cellbreak-face))
|
||||
(and (string= "i" mc) (eq fnt 'matlab-ignored-comment-face))
|
||||
(and (string= "e" mc) (eq fnt 'font-lock-comment-face))
|
||||
(and (string= "d" mc) (eq fnt 'matlab-commanddual-string-face))
|
||||
(and (string= "r" mc) (eq fnt nil))
|
||||
)
|
||||
(metest-error "Font Lock Failure @ char %d: Expected %s but found %S"
|
||||
pt
|
||||
(cond ((string= mc "b") "comment face")
|
||||
((string= mc "v") "string face")
|
||||
((string= mc "V") "unterminated string face")
|
||||
((string= mc "s") "string face")
|
||||
((string= mc "S") "unterminated string face")
|
||||
((string= mc "c") "comment face")
|
||||
((string= mc "C") "cellbreak face")
|
||||
((string= mc "i") "ignored comment face")
|
||||
((string= mc "e") "comment face")
|
||||
((string= mc "d") "commanddual string face")
|
||||
((string= mc "r") "regular code / no face")
|
||||
(t "unknown test token"))
|
||||
(get-text-property pt 'face)))
|
||||
;; Track
|
||||
(setq cnt (1+ cnt))
|
||||
))
|
||||
(kill-buffer buf))
|
||||
(message "<< Comment and string syntax test: %d points passed" cnt)
|
||||
))
|
||||
(message ""))
|
||||
|
||||
(defvar met-sexptest-files '("expressions.m" "mclass.m")
|
||||
(list cnt "tests")))
|
||||
|
||||
(defvar met-sexptest-files '("expressions.m" "mclass.m" "blocks.m")
|
||||
"List of files for running syntactic expression tests.")
|
||||
|
||||
(defun metest-sexp-counting-test ()
|
||||
"Run a test to make sure string nd comment highlighting work."
|
||||
(dolist (F met-sexptest-files)
|
||||
(let ((buf (find-file-noselect (expand-file-name F met-testfile-path)))
|
||||
(defvar metest-sexp-counting-test (cons "sexp counting" met-sexptest-files))
|
||||
(defun metest-sexp-counting-test (F)
|
||||
"Run a test to make sure string and comment highlighting work."
|
||||
(let ((buf (metest-find-file F))
|
||||
(cnt 0))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
(message ">> Starting sexp counting loop in %S" (current-buffer))
|
||||
;;(message ">> Starting sexp counting loop in %S" (current-buffer))
|
||||
(while (re-search-forward "#\\([0-9]\\)#" nil t)
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
|
@ -111,13 +268,13 @@
|
|||
(let* ((num (string-to-number (match-string 1))))
|
||||
(save-restriction
|
||||
(narrow-to-region (point-at-bol) (point))
|
||||
(matlab-move-simple-sexp-internal (- num))
|
||||
(metest-condition-case-error-msg
|
||||
(matlab-move-simple-sexp-internal (- num)))
|
||||
(skip-chars-backward " \t;.=%")
|
||||
(if (not (eq (point) (point-min)))
|
||||
(save-restriction
|
||||
(widen)
|
||||
(error "error at %d: Backward Sexp miscount tried %d, point %d, min %d"
|
||||
(line-number-at-pos)
|
||||
(metest-error "Backward Sexp miscount tried %d, point %d, min %d"
|
||||
num (point) (point-at-bol))))
|
||||
(skip-chars-forward " \t;.=%")
|
||||
(matlab-move-simple-sexp-internal num)
|
||||
|
@ -125,88 +282,108 @@
|
|||
(if (not (eq (point) (point-max)))
|
||||
(save-restriction
|
||||
(widen)
|
||||
(error "Error at %d: Forward Sexp miscount tried %d, point %d, dest %d"
|
||||
(line-number-at-pos)
|
||||
(metest-error "Forward Sexp miscount tried %d, point %d, dest %d"
|
||||
num (point) (point-at-eol)))))
|
||||
))
|
||||
(end-of-line)
|
||||
(setq cnt (1+ cnt))))
|
||||
(kill-buffer buf)
|
||||
(message "<< Sexp counting syntax test: %d points passed" cnt)
|
||||
))
|
||||
(message ""))
|
||||
(list cnt "tests")))
|
||||
|
||||
(defun metest-sexp-traversal-test ()
|
||||
(defvar metest-sexp-traversal-test (cons "sexp block traversal" met-sexptest-files))
|
||||
(defun metest-sexp-traversal-test (F)
|
||||
"Run a test to make sure high level block navigation works."
|
||||
(dolist (F met-sexptest-files)
|
||||
(let ((buf (find-file-noselect (expand-file-name F met-testfile-path)))
|
||||
(let ((buf (metest-find-file F))
|
||||
(cnt 0))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
(message ">> Starting sexp traversal loop in %S" (current-buffer))
|
||||
;;(message ">> Starting sexp traversal loop in %S" (current-buffer))
|
||||
(while (re-search-forward ">>\\([0-9]+\\)" nil t)
|
||||
(let* ((num (string-to-number (match-string 1)))
|
||||
(num2 0)
|
||||
(begin nil))
|
||||
(skip-chars-forward " \n\t;%")
|
||||
(setq begin (point))
|
||||
(matlab-forward-sexp)
|
||||
(metest-condition-case-error-msg (matlab--scan-block-forward))
|
||||
(save-excursion
|
||||
(skip-chars-forward " \n\t;%")
|
||||
(if (not (looking-at "<<\\([0-9]+\\)"))
|
||||
(error "Error at %d: Failed to find matching test end token for %d"
|
||||
(line-number-at-pos) num)
|
||||
(metest-error "Failed to find matching test end token for %d"
|
||||
num)
|
||||
(setq num2 (string-to-number (match-string 1)))
|
||||
(when (/= num num2)
|
||||
(error "Error at %d: Failed to match correct test token. Start is %d, end is %d"
|
||||
(line-number-at-pos) num num2)))
|
||||
(matlab-backward-sexp)
|
||||
(metest-error "Failed to match correct test token. Start is %d, end is %d"
|
||||
num num2))))
|
||||
(metest-condition-case-error-msg (matlab--scan-block-backward))
|
||||
(when (/= (point) begin)
|
||||
(error "Error at %d: Failed to reverse navigate sexp for %d"
|
||||
(line-number-at-pos) num))
|
||||
(metest-error "Failed to reverse navigate sexp for %d"
|
||||
num))
|
||||
)
|
||||
(end-of-line)
|
||||
(setq cnt (1+ cnt))))
|
||||
(kill-buffer buf)
|
||||
(message "<< Sexp counting syntax test: %d points passed" cnt)
|
||||
))
|
||||
(message ""))
|
||||
(list cnt "test")))
|
||||
|
||||
|
||||
(defvar met-indents-files '("indents.m" "mclass.m")
|
||||
(defvar met-indents-files '("indents.m" "continuations.m" "mclass.m" "blocks.m" "mfuncends.m" "mfuncnoendblock.m" "mclass_cont.m" "mfuncnofuncindent.m")
|
||||
"List of files for running syntactic indentation tests.")
|
||||
|
||||
(defun metest-indents-test ()
|
||||
"Run a test to make sure high level block navigation works."
|
||||
(defun metest-indents-randomize-files ()
|
||||
"Randomize the indentation in the inents test files."
|
||||
(interactive)
|
||||
(message "<< Flattening indentation ...")
|
||||
(let ((matlab-scan-temporal-cache nil)) ;; disable cache for file load
|
||||
(dolist (F met-indents-files)
|
||||
(let ((buf (find-file-noselect (expand-file-name F met-testfile-path)))
|
||||
(cnt 0))
|
||||
(with-current-buffer buf
|
||||
(with-current-buffer (metest-find-file F)
|
||||
(goto-char (point-min))
|
||||
;; (indent-region (point-min) (point-max))
|
||||
(message ">> Starting indents loop in %S" (current-buffer))
|
||||
(while (re-search-forward "!!\\([0-9]+\\)" nil t)
|
||||
(let* ((num (string-to-number (match-string 1)))
|
||||
(calc (matlab-calc-indent))
|
||||
(begin nil))
|
||||
(when (not (= num calc))
|
||||
(error "Error at %d: Indentation found is %d, expected %d"
|
||||
(line-number-at-pos) calc num))
|
||||
(while (not (eobp))
|
||||
(beginning-of-line)
|
||||
(if (looking-at "^\\s-*$")
|
||||
(matlab--change-indentation 0)
|
||||
(matlab--change-indentation 3)) ;;(random 13)?
|
||||
(forward-line 1)
|
||||
)
|
||||
(end-of-line)
|
||||
(setq cnt (1+ cnt))))
|
||||
(kill-buffer buf)
|
||||
(message "<< Indentation syntax test: %d points passed" cnt)
|
||||
;; And don't delete - leave it to find for the next test.
|
||||
;; but we do want to restart the mode and force a re-guess of the file type.
|
||||
(matlab-mode)
|
||||
))))
|
||||
|
||||
(defvar metest-indents-test (cons "indenting" met-indents-files))
|
||||
(defvar metest-indent-counts 0)
|
||||
(defun metest-indents-test (F)
|
||||
"Run a test to make sure high level block navigation works."
|
||||
(with-current-buffer (metest-find-file F)
|
||||
(goto-char (point-min))
|
||||
(let ((metest-indent-counts 0)
|
||||
(matlab--change-indentation-override #'metest-indents-test-hook-fcn))
|
||||
(metest-condition-case-error-msg
|
||||
(matlab-indent-region (point-min) (point-max) nil t))
|
||||
(kill-buffer (current-buffer))
|
||||
(list metest-indent-counts "tests"))))
|
||||
|
||||
(defun metest-indents-test-hook-fcn (indent)
|
||||
"Hook fcn used to capture indents from `indent-region'."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
|
||||
(when (re-search-forward "!!\\([0-9]+\\)" (point-at-eol) t)
|
||||
(let ((num (string-to-number (match-string 1))))
|
||||
(setq metest-indent-counts (1+ metest-indent-counts))
|
||||
(when (not (eq num indent))
|
||||
(metest-error "Indentation computed is %s, expected %s"
|
||||
indent num))))
|
||||
|
||||
;; Now do the indent in case a bad indent will trigger a bug later.
|
||||
(matlab--change-indentation indent)
|
||||
))
|
||||
(message ""))
|
||||
|
||||
(defvar met-parser-files '("mpclass.m")
|
||||
"List of files for running semantic parsing tests.")
|
||||
|
||||
(defun metest-parse-test ()
|
||||
(defvar metest-parse-test (cons "semantic parser" met-parser-files))
|
||||
(defun metest-parse-test (F)
|
||||
"Run the semantic parsing test to make sure the parse works."
|
||||
|
||||
(dolist (F met-parser-files)
|
||||
(let ((buf (find-file-noselect (expand-file-name F met-testfile-path)))
|
||||
(let ((buf (metest-find-file F))
|
||||
exp act
|
||||
(cnt 0))
|
||||
(with-current-buffer buf
|
||||
|
@ -217,12 +394,12 @@
|
|||
|
||||
;; Do the test
|
||||
(goto-char (point-min))
|
||||
(message ">> Starting semantic parser test in %S" (current-buffer))
|
||||
;;(message ">> Starting semantic parser test in %S" (current-buffer))
|
||||
|
||||
(unless (re-search-forward "^%%\\s-*>>\\s-+SEMANTIC TEST" nil t)
|
||||
(error "Semantic parser test: Failed to find test cookie."))
|
||||
(metest-error "Semantic parser test: Failed to find test cookie."))
|
||||
(unless (re-search-forward "^%{[ \t\n]+\\(((\\)" nil t)
|
||||
(error "Semantic parser test: Failed to find expected values."))
|
||||
(metest-error "Semantic parser test: Failed to find expected values."))
|
||||
(goto-char (match-beginning 1))
|
||||
(setq exp (read (buffer-substring (point)
|
||||
(save-excursion (re-search-forward "%}" nil t)
|
||||
|
@ -232,25 +409,262 @@
|
|||
;; Compare the two lists ... simply.
|
||||
(while (and exp act)
|
||||
(unless (metest-compare-tags (car exp) (car act))
|
||||
(error "Expected tag %s, found %s" (semantic-format-tag-prototype (car exp))
|
||||
(metest-error "Expected tag %s, found %s" (semantic-format-tag-prototype (car exp))
|
||||
(semantic-format-tag-prototype (car act))))
|
||||
(setq exp (cdr exp) act (cdr act) cnt (1+ cnt))
|
||||
)
|
||||
(when (or exp act)
|
||||
(error "Found tags and expected tag lists differnet lengths.\nExpected Remains: %S\nActual Remains: %S"
|
||||
(metest-error "Found tags and expected tag lists differnet lengths.\nExpected Remains: %S\nActual Remains: %S"
|
||||
exp act))
|
||||
|
||||
)
|
||||
|
||||
(message ">> Semantic parser test: %d tags matched" cnt))))
|
||||
(list cnt "tests")))
|
||||
|
||||
|
||||
(defun metest-compare-tags (EXP ACT)
|
||||
"Return non-nil if EXP tag is similiar to ACT"
|
||||
(semantic-tag-similar-p EXP ACT :documentation)
|
||||
|
||||
)
|
||||
|
||||
(defconst met-kw-font-alist '(( "kw" . font-lock-keyword-face )
|
||||
( "ty" . font-lock-type-face )
|
||||
( "fn" . font-lock-function-name-face )
|
||||
( "vn" . font-lock-variable-name-face )
|
||||
( "vc" . (font-lock-variable-name-face
|
||||
matlab-cross-function-variable-face) )
|
||||
( "cn" . font-lock-constant-face )
|
||||
( "co" . font-lock-comment-face )
|
||||
( "st" . font-lock-string-face )
|
||||
( "bi" . font-lock-builtin-face )
|
||||
|
||||
( "cb" . matlab-cellbreak-face )
|
||||
( "ig" . matlab-ignored-comment-face )
|
||||
( "pr" . matlab-pragma-face )
|
||||
( "cd" . matlab-commanddual-string-face )
|
||||
( "us" . matlab-unterminated-string-face )
|
||||
( "ma" . matlab-math-face )
|
||||
( "si" . matlab-simulink-keyword-face )
|
||||
|
||||
( "bo" . bold )
|
||||
( "df" . nil )
|
||||
)
|
||||
"List of testing keywords and associated faces.")
|
||||
|
||||
|
||||
(defvar met-complete-files '("complete.m")
|
||||
"List of files for running font completion tests.")
|
||||
|
||||
(defvar met-complete-tools '((var . matlab-find-recent-variable)
|
||||
(fcn . matlab-find-user-functions)
|
||||
)
|
||||
"List of tools that generate completions.")
|
||||
|
||||
(defvar metest-complete-test (cons "completion" met-complete-files))
|
||||
(defun metest-complete-test (F)
|
||||
"Test the completion tools in matlab-complete.el"
|
||||
(let ((buf (metest-find-file F))
|
||||
exp act
|
||||
(cnt 0))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
|
||||
(while (re-search-forward "%\\s-*@@" nil t)
|
||||
(setq exp (read (buffer-substring-no-properties (point) (scan-sexps (point) 1))))
|
||||
;; Move to end of previous line, and try to do a complete
|
||||
(matlab-with-context-line (matlab-previous-code-line (matlab-compute-line-context 2))
|
||||
(end-of-line)
|
||||
(let* ((prefix (buffer-substring-no-properties
|
||||
(save-excursion (forward-word -1) (point))
|
||||
(point)))
|
||||
(sem (matlab-lattr-semantics prefix))
|
||||
)
|
||||
;; Did we get the expected semantics of this location?
|
||||
(when (not (eq sem (car exp)))
|
||||
(metest-error "Completion Semantic Missmatch: Expected %s but found %s" (car exp) sem))
|
||||
|
||||
(let* ((expR (nthcdr 2 exp))
|
||||
(fcn (assoc (nth 1 exp) met-complete-tools))
|
||||
(act (funcall (cdr fcn) prefix)))
|
||||
(when (not (equal act expR))
|
||||
(metest-error "Completion Missmatch: Expected %S but found %S using function %S"
|
||||
expR act fcn))
|
||||
)
|
||||
))
|
||||
(setq cnt (1+ cnt))
|
||||
;; Skip this match, find the next.
|
||||
(end-of-line)))
|
||||
(list cnt "tests")))
|
||||
|
||||
|
||||
(defvar met-fontlock-files '("fontlock.m" "mclass.m" "blocks.m")
|
||||
"List of files for running font lock tests.")
|
||||
|
||||
(defvar metest-fontlock-test (cons "font lock" met-fontlock-files))
|
||||
(defun metest-fontlock-test (F)
|
||||
"Run the semantic parsing test to make sure the parse works."
|
||||
(let ((buf (metest-find-file F))
|
||||
(noninteractive nil) ;; fake out font lock
|
||||
(cnt 0) (fntcnt 0))
|
||||
(with-current-buffer buf
|
||||
|
||||
(goto-char (point-min))
|
||||
|
||||
(let ((md (match-data)))
|
||||
;; Force font lock to throw catchable errors.
|
||||
(font-lock-mode 1)
|
||||
(font-lock-flush (point-min) (point-max))
|
||||
(font-lock-ensure (point-min) (point-max))
|
||||
(font-lock-fontify-region (point-min) (point-max))
|
||||
|
||||
;; FL test 1: make sure font lock is on and match data didn't change.
|
||||
(unless font-lock-mode
|
||||
(metest-error "Font Lock failed to turn on."))
|
||||
;;(unless (equal md (match-data))
|
||||
;; (metest-error "Font Locking transmuted the match data"))
|
||||
(when (not (get-text-property 2 'fontified))
|
||||
(metest-error "Font Lock Failure: can't run test because font lock failed to fontify region."))
|
||||
)
|
||||
|
||||
;; Lines that start with %^ comments are FL keyword test features.
|
||||
;; Find the line, then look for every ^ and find it's column and match
|
||||
;; to previous line's column.
|
||||
(while (re-search-forward "^\\s-*%\\(?: \\$\\$\\$\\)?\\^" nil t)
|
||||
(let ((next (point-at-eol))
|
||||
(prevstart (save-excursion (forward-line -1) (point-at-bol)))
|
||||
)
|
||||
(while (re-search-forward "\\^\\(\\w\\w\\)\\>" (point-at-eol) t)
|
||||
(let* ((col (- (match-beginning 0) (point-at-bol)))
|
||||
(fk (match-string-no-properties 1))
|
||||
(pt (+ prevstart col))
|
||||
(fnt (get-text-property pt 'face))
|
||||
(fnt1 (if (consp fnt) (car fnt) fnt))
|
||||
(fnt2 (if (consp fnt) (nth 1 fnt) nil))
|
||||
(exp (cdr (assoc fk met-kw-font-alist))))
|
||||
|
||||
(cond
|
||||
((consp exp)
|
||||
(when (not (eq (car exp) fnt1))
|
||||
(metest-error "Bad font layer 1 found @ col %d: Expected %S but found %S"
|
||||
col (car exp) fnt1))
|
||||
(when (not (eq (nth 1 exp) fnt2))
|
||||
(metest-error "Bad font layer 2 found @ col %d: Expected %S but found %S"
|
||||
col (nth 1 exp) fnt2)))
|
||||
(t
|
||||
(when (not (eq exp fnt1))
|
||||
(metest-error "Bad font found @ col %d: Expected %S but found %S"
|
||||
col exp fnt))))
|
||||
|
||||
(setq fntcnt (1+ fntcnt))
|
||||
))
|
||||
(goto-char next)
|
||||
(setq cnt (1+ cnt))))
|
||||
|
||||
(list cnt "lines with " fntcnt "fonts tested"))))
|
||||
|
||||
;;; UTILS
|
||||
;;
|
||||
|
||||
(defun metest-find-file (file)
|
||||
"Read FILE into a buffer and return it.
|
||||
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)))
|
||||
|
||||
(defvar metest-error-context-lines 4)
|
||||
(defun metest-error (&rest args)
|
||||
"Produce an err with standardized file/line prefix."
|
||||
(declare (indent 1))
|
||||
(let* ((lineno (line-number-at-pos))
|
||||
(fname (file-name-nondirectory (buffer-file-name)))
|
||||
(pre (format "\n%s:%d: Error: " fname lineno))
|
||||
(post (apply 'format args))
|
||||
(prelines (min lineno metest-error-context-lines)))
|
||||
(message "\n--vv buffer snip: %s vv--" fname)
|
||||
(save-excursion
|
||||
(forward-line (- prelines))
|
||||
(while (> prelines 0)
|
||||
(message "|%s" (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
|
||||
(forward-line 1)
|
||||
(setq prelines (1- prelines)))
|
||||
(message ">%s" (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
|
||||
(forward-line 1)
|
||||
(while (and (> metest-error-context-lines prelines) (not (eobp)))
|
||||
(message "|%s" (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
|
||||
(forward-line 1)
|
||||
(setq prelines (1+ prelines))))
|
||||
(message "---^^ buffer snip ^^---")
|
||||
(setq metest-test-error t)
|
||||
(error (concat pre post))))
|
||||
|
||||
;;; Logging prormance data for the tests
|
||||
;;
|
||||
(defvar metest-log-file "metest_timing_log.dat"
|
||||
"File to store timing data to.")
|
||||
|
||||
(defvar metest-time-log nil
|
||||
"Data stored for each run.")
|
||||
|
||||
(defun metest-log-init ()
|
||||
"Init the log file and data variable."
|
||||
(setq metest-time-log nil)
|
||||
)
|
||||
|
||||
(defun metest-shorten (sym)
|
||||
"Convert SYM into a column header."
|
||||
(let ((str (symbol-name sym)))
|
||||
(substring str 7 -5)))
|
||||
|
||||
(defun metest-log-write ()
|
||||
"Write dta into our log file."
|
||||
(save-current-buffer
|
||||
(set-buffer (find-file-noselect metest-log-file))
|
||||
(let ((LOG (reverse metest-time-log)))
|
||||
(when (= (point-min) (point-max))
|
||||
;; Initialize the new buffer
|
||||
(insert "Time\t")
|
||||
(insert (mapconcat (lambda (log) (metest-shorten (car log))) LOG "\t")))
|
||||
;; Insert our measurements
|
||||
(goto-char (point-max))
|
||||
(newline)
|
||||
(insert (format-time-string "\"%Y/%m/%d %H:%M\"\t" (current-time)))
|
||||
(insert (mapconcat (lambda (log2) (format "%f" (cdr log2))) LOG "\t"))
|
||||
(save-buffer)
|
||||
;; Go back and find our baseline and return it.
|
||||
(goto-char (point-min))
|
||||
(forward-line 1)
|
||||
(read (concat "(" (buffer-substring-no-properties (point-at-bol) (point-at-eol)) ")"))
|
||||
)))
|
||||
|
||||
(defun metest-log-report (baseline)
|
||||
"Report via message what happened during the test suite."
|
||||
(let ((log (reverse metest-time-log))
|
||||
(base (cdr baseline)))
|
||||
(princ "Baseln\tRun\tImprovement\tTest\n")
|
||||
(while (and log base)
|
||||
(princ (format "%.4f\t" (car base)))
|
||||
(princ (format "%.4f\t" (cdr (car log))))
|
||||
(princ (format "%.4f\t\t" (- (car base) (cdr (car log)))))
|
||||
(princ (metest-shorten (car (car log))))
|
||||
(princ "\n")
|
||||
(setq log (cdr log)
|
||||
base (cdr base)))
|
||||
))
|
||||
|
||||
(defun metest-timeit (fcn &optional file)
|
||||
"Time running FCN and save result in LOGFILE.
|
||||
Use this to track perforamnce improvements during development automatically."
|
||||
(let* ((start (current-time))
|
||||
(out (funcall fcn file))
|
||||
(end (current-time))
|
||||
(diff (float-time (time-subtract end start))))
|
||||
(if (eq fcn (car-safe (car-safe metest-time-log)))
|
||||
;; Same fcn, append our number
|
||||
(setcdr (car metest-time-log) (+ diff (cdr (car metest-time-log))))
|
||||
(push (cons fcn diff) metest-time-log))
|
||||
(cons diff out)))
|
||||
|
||||
(provide 'metest)
|
||||
|
||||
;;; metest.el ends here
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
function mfuncends( )
|
||||
% Test function that has ends for each function. !!0
|
||||
% !!0
|
||||
% Used with test harness to validate indentation and end detection. !!0
|
||||
% !!0
|
||||
% %%%function function function
|
||||
|
||||
fcn_call(); %!!4
|
||||
|
||||
if condition %!!4
|
||||
fcn_call(); %!!8
|
||||
fcn_call ... !!8
|
||||
(); %!!12
|
||||
end %!!4
|
||||
|
||||
end%!!0 - also no space after end
|
||||
|
||||
function a=fcn_call(inp) %!!0
|
||||
|
||||
while inp > 0 %!!4
|
||||
fcn_call(inp-1); %!!8
|
||||
a = [ 1 2 ... !!8
|
||||
3 4 ]; %!!14
|
||||
end %!!4
|
||||
|
||||
end %!!0
|
|
@ -0,0 +1,15 @@
|
|||
function mfuncnoend
|
||||
% A function file that does not have ends at the end of functions.
|
||||
%
|
||||
% %%% function nil nil
|
||||
|
||||
fcn_call(1)
|
||||
|
||||
|
||||
function fcn_call(idx)
|
||||
|
||||
if idx > 0
|
||||
fcn_call(ix-1)
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
%{
|
||||
Add a block comment at the beginning to skip over.
|
||||
x % !!2
|
||||
% !! 0
|
||||
%}
|
||||
function mfuncnoendblock
|
||||
% A function file that does not have ends at the end of functions.
|
||||
% !!0
|
||||
% %%% function nil nil
|
||||
|
||||
fcn_call(1) %!!0
|
||||
|
||||
|
||||
function fcn_call(idx) %!!0
|
||||
|
||||
if idx > 0 %!!0
|
||||
fcn_call(ix-1) %!!4
|
||||
goo(3);
|
||||
end %!!0
|
||||
|
||||
function c=goo(p3) %!!0
|
||||
if p3 < 3 %!!0
|
||||
if p3 < 0 %!!4
|
||||
c = p3 * -3; %!!8
|
||||
else %!!4
|
||||
c = p3 * 3; %!!8
|
||||
for i=1:10 %!!8
|
||||
c = c + i; %!!12
|
||||
end %!!8
|
||||
end %!!4
|
||||
else %!!0
|
||||
c=p3*4; %!!4
|
||||
end %!!0
|
|
@ -0,0 +1,15 @@
|
|||
function mfuncnoendindent
|
||||
% A function file that does not have ends at the end of functions.
|
||||
%
|
||||
% %%% function nil t
|
||||
|
||||
fcn_call(1)
|
||||
|
||||
|
||||
function fcn_call(idx)
|
||||
|
||||
if idx > 0
|
||||
fcn_call(ix-1)
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
function mfuncnofuncindent( )
|
||||
% Test function that has ends for each function. !!0
|
||||
% !!0
|
||||
% Used with test harness to validate indentation and end detection. !!0
|
||||
% !!0
|
||||
% %%%function function nil
|
||||
|
||||
fcn_call(); %!!0
|
||||
|
||||
if condition %!!0
|
||||
fcn_call(); %!!4
|
||||
fcn_call ... !!4
|
||||
(); %!!8
|
||||
end %!!0
|
||||
|
||||
end%!!0 - also no space after end
|
||||
|
||||
function a=fcn_call(inp) %!!0
|
||||
|
||||
while inp > 0 %!!0
|
||||
fcn_call(inp-1); %!!4
|
||||
a = [ 1 2 ... !!4
|
||||
3 4 ]; %!!10
|
||||
end %!!0
|
||||
|
||||
end %!!0
|
||||
|
||||
%{
|
||||
% Local Variables:
|
||||
% matlab-indent-function-body: nil
|
||||
% End:
|
||||
%}
|
|
@ -0,0 +1,11 @@
|
|||
function mfuncspacey( )
|
||||
% Test function that has ends for each function.
|
||||
%
|
||||
% Used with test harness to validate indentation and end detection.
|
||||
%
|
||||
% %%%function function function
|
||||
|
||||
fcn_call();
|
||||
|
||||
end
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
%% Tests for char vector and string handling.
|
||||
%
|
||||
% #c#
|
||||
%
|
||||
% %%%script script script
|
||||
|
||||
%% Basic strings
|
||||
|
||||
|
@ -13,8 +15,8 @@ stringscalar = "string scalar #s#";
|
|||
% Comment with 'character vector #c#' in it.
|
||||
% Comment with "string scalar #c#" in it.
|
||||
|
||||
charvi = 'char vector incomplete #v#
|
||||
stringi = "string scalar incomplete #s#
|
||||
charvi = 'char vector incomplete #V#
|
||||
stringi = "string scalar incomplete #S#
|
||||
|
||||
% Comment with 'char vector incomplete #c#
|
||||
% Comment with "string scalar incomplete #c#
|
||||
|
@ -27,16 +29,16 @@ stringcv = "string scalar with 'char vec #s#' in it";
|
|||
chard = 'char vector with '' in it #v#';
|
||||
stringd = "string scalar with "" in it #s#";
|
||||
|
||||
chardi = 'incomplete char vector with '' in it #v#
|
||||
stringdi = "incomplete string scalar with "" in it #s#
|
||||
chardi = 'incomplete char vector with '' in it #V#
|
||||
stringdi = "incomplete string scalar with "" in it #S#
|
||||
|
||||
%% Strings with Comments
|
||||
|
||||
charvc = 'char vector with % comment char #v#';
|
||||
stringc = "string scalar with % comment char #s#";
|
||||
|
||||
charvci = 'incomplete char vector with % comment char #v#
|
||||
stringci = "incomplete string scalar with % comment char #s#
|
||||
charvci = 'incomplete char vector with % comment char #V#
|
||||
stringci = "incomplete string scalar with % comment char #S#
|
||||
|
||||
charvbc = 'char vector with %{ comment char #v# %} ';
|
||||
stringbc = "string scalar with %{ comment char #s# %} ";
|
||||
|
@ -69,8 +71,11 @@ icell_in_strs2_nested = { 'charv innercell " #v# }' "strinc innercel ' #s# }"
|
|||
%% Elipsis as comment
|
||||
|
||||
fun_call(); ... This is a comment after an elipsis #e#
|
||||
|
||||
fun_call(); ... 'charvec in elipsis comment #e#'
|
||||
|
||||
fun_call(); ... "string in elipsis comment #e#"
|
||||
|
||||
fun_call(); ... % comment after an elipsis is still elipsis #e#
|
||||
|
||||
%% Elipsis and strings and other comments
|
||||
|
@ -78,10 +83,12 @@ fun_call(); ... % comment after an elipsis is still elipsis #e#
|
|||
Ecv = 'string with ... in #v# it';
|
||||
Es = "string with ... in #s# it";
|
||||
% Comment with ... in it #c#
|
||||
eecv = '...'; % string with only ellipsis in it #c#
|
||||
ees = "..."; % string with only ellipsis in it #c#
|
||||
|
||||
x = [ 'foo bar',newline,...
|
||||
' ''-goo'', ... #v#',newline,...
|
||||
' ''-bar'', ... #v#',newline];
|
||||
x = [ 'foo bar', newline, ... #e#
|
||||
' ''-goo'', ... #v#', newline, ... #e#
|
||||
' ''-bar'', ... #v#', newline ];
|
||||
|
||||
func_call1('function with charvec', ... #e#
|
||||
'after ellipsis charvec with ellipsis ... #v#');
|
||||
|
@ -141,7 +148,7 @@ else
|
|||
Cs = "not unreachable #s#";
|
||||
end
|
||||
|
||||
%% Block Comments #c#
|
||||
%% Block Comments #C#
|
||||
|
||||
%{
|
||||
|
||||
|
@ -154,4 +161,34 @@ end
|
|||
|
||||
not_commented();
|
||||
|
||||
%{ just a regular comment #c# %} should_be_comment #c#
|
||||
|
||||
% Normal comment #c#
|
||||
|
||||
%% Ignored Comments #C#
|
||||
|
||||
% $$$ This comment is ignored by indentation engine. #i#
|
||||
|
||||
%^ This comment is igored too, used in tests for font lock. #i#
|
||||
|
||||
|
||||
%% Command line dual #C#
|
||||
% Note: stuff after a symbol<space> treated as string
|
||||
|
||||
disp _this is string input to function #d#_
|
||||
disp _this is also string input to a function #d#_
|
||||
|
||||
regularcode; #r#
|
||||
|
||||
% Note: Case sensitivity of cmd dual functions
|
||||
DISP _regular code even though ML would treat as cmd dual #r#_
|
||||
|
||||
%{
|
||||
% Local Variables:
|
||||
% matlab-syntax-support-command-dual: t
|
||||
% matlab-show-mlint-warnings: nil
|
||||
% End:
|
||||
%}
|
||||
|
||||
|
||||
%% END
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
function emacsrun(mfile, varargin)
|
||||
% Run code from MFILE.
|
||||
% Assumes MFILE was recently edited, and proactively clears that function.
|
||||
%
|
||||
% Command sent by Emacs for save-and-go functionality
|
||||
|
||||
% Now figure out if shortFileName is on the path.
|
||||
[ fullFilePath, shortFileName ] = fileparts(mfile);
|
||||
onpath = ~isempty(which(shortFileName));
|
||||
|
||||
if ~exist(fullFilePath,'file')
|
||||
error('You must save your file into a location accessible by MATLAB process.');
|
||||
end
|
||||
|
||||
|
||||
% If not on the path, temporarilly switch to that directory so it and an files it references are
|
||||
% accessible
|
||||
if ~onpath
|
||||
oldpath = pwd;
|
||||
cd(fullFilePath);
|
||||
cleanup = onCleanup(@()cd(oldpath));
|
||||
end
|
||||
clear(shortFileName);
|
||||
|
||||
cmd = [ shortFileName varargin{:} ];
|
||||
|
||||
evalin('base',cmd);
|
||||
end
|
Loading…
Reference in New Issue