matlab.el:
(matlab-mode-for-new-mfiles): New setting. (matlab-is-matlab-file): New test for magic-mode-alist. (matlab-is-mcr-file): New test for MCR files. (auto-mode-alist -> magic-mode-alist): Use above to decide if a file is an objective C file. If not, do MATLAB. (matlab-mode-leave): When matlab-mode exists, disable mlint mode. (matlab-mode): Add change-major-mode-hook for `matlab-mode-leave' (matlab-frame-init, matlab-ltype-block-comm) (matlab-electric-block-comment, matlab-toggle-read-only) Spelling fixes.
This commit is contained in:
parent
6bcee3f537
commit
3402cdebf4
179
matlab.el
179
matlab.el
|
@ -64,6 +64,22 @@
|
|||
:prefix "matlab-"
|
||||
:group 'languages)
|
||||
|
||||
(defcustom matlab-mode-for-new-mfiles 'maybe
|
||||
"*Enter `matlab-mode' for new *.m files.
|
||||
The `matlab' package will automatically enter `matlab-mode' when
|
||||
the first part of a *.m file is doesn't contain Objective-C
|
||||
comments or '#' characters. If you want new (empty) files to
|
||||
automatically enter `matlab-mode', specify this item as
|
||||
t (always). If you specify 'maybe, new files will enter
|
||||
`matlab-mode' when you have an existing MATLAB buffer. Specifying
|
||||
nil (never) means that new *.m files will not enter
|
||||
`matlab-mode', and with default Emacs settings they will enter
|
||||
`objc-mode'"
|
||||
:group 'matlab
|
||||
:type '(choice (const :tag "Always" t)
|
||||
(const :tag "Never" nil)
|
||||
(const :tag "Maybe" maybe)))
|
||||
|
||||
(defcustom matlab-indent-level 4
|
||||
"*The basic indentation amount in `matlab-mode'."
|
||||
:group 'matlab
|
||||
|
@ -659,7 +675,7 @@ If font lock is not loaded, lay in wait."
|
|||
:help "When MATLAB debugger is active, set break point at current M-file point"]
|
||||
["Remove Breakpoint (ebclear in FILE at point)" gud-remove
|
||||
:active (matlab-shell-active-p)
|
||||
:help "Show all active breakpoints in a seperate buffer." ]
|
||||
:help "Show all active breakpoints in a separate buffer." ]
|
||||
["List Breakpoints (ebstatus)" gud-list-breakpoints
|
||||
:active (matlab-shell-active-p)
|
||||
:help "List active breakpoints."]
|
||||
|
@ -780,7 +796,7 @@ when attempting to understand the current context.")
|
|||
(goto-char (match-beginning 0))
|
||||
(call-interactively 'set-mark-command)
|
||||
(goto-char (match-end 0)))
|
||||
|
||||
|
||||
(defun matlab-font-lock-allstring-comment-match-normal (limit)
|
||||
"When font locking strings, call this function for normal character vectors.
|
||||
Argument LIMIT is the maximum distance to scan."
|
||||
|
@ -810,7 +826,7 @@ Argument LIMIT is the maximum distance to scan."
|
|||
)
|
||||
|
||||
;; Not a comment, must be a string or charvec
|
||||
|
||||
|
||||
;; Scan to end of string by looking at every matching
|
||||
;; string character and deciding what it means.
|
||||
(while (and (not done)
|
||||
|
@ -827,7 +843,7 @@ Argument LIMIT is the maximum distance to scan."
|
|||
done t))
|
||||
;; The other type of string - just keep going.
|
||||
nil))
|
||||
|
||||
|
||||
;; If not done, unterminated
|
||||
(if (not done)
|
||||
(setq bu b0
|
||||
|
@ -845,7 +861,7 @@ Argument LIMIT is the maximum distance to scan."
|
|||
|
||||
;; Move to the end
|
||||
(goto-char (or es eu ec))
|
||||
|
||||
|
||||
;; Successful string
|
||||
t)))
|
||||
|
||||
|
@ -1222,11 +1238,11 @@ Uses `regex-opt' if available. Otherwise creates a 'dumb' expression."
|
|||
(list (concat "^\\s-*\\(classdef\\)"
|
||||
matlab-class-attributes-list-re
|
||||
"\\s-+\\(\\sw+\\)")
|
||||
'("\\s-*[<&]\\s-*\\(\\(\\sw\\|\\.\\)+\\)" nil nil
|
||||
'("\\s-*[<&]\\s-*\\(\\(\\sw\\|\\.\\)+\\)" nil nil
|
||||
(1 font-lock-constant-face)))
|
||||
;; Property and Method blocks have attributes to highlight
|
||||
(list "^\\s-*\\(classdef\\|properties\\|methods\\|events\\|arguments\\)\\s-*("
|
||||
'("\\(\\sw+\\)\\s-*\\(=\\s-*[^,)]+\\)?" nil nil
|
||||
'("\\(\\sw+\\)\\s-*\\(=\\s-*[^,)]+\\)?" nil nil
|
||||
(1 font-lock-type-face)
|
||||
))
|
||||
;; Properties can have a type syntax after them
|
||||
|
@ -1289,14 +1305,68 @@ Uses `regex-opt' if available. Otherwise creates a 'dumb' expression."
|
|||
;; Imenu support.
|
||||
(defvar matlab-imenu-generic-expression
|
||||
'((nil "^\\s-*function\\>[ \t\n.]*\\(\\(\\[[^]]*\\]\\|\\sw+\\)[ \t\n.]*\
|
||||
< =\[ \t\n.]*\\)?\\([a-zA-Z0-9_]+\\)" 3))
|
||||
< =[ \t\n.]*\\)?\\([a-zA-Z0-9_]+\\)" 3))
|
||||
"Expressions which find function headings in MATLAB M files.")
|
||||
|
||||
|
||||
;;; MATLAB mode entry point ==================================================
|
||||
|
||||
;; Choose matlab-mode if when loading MATLAB *.m files
|
||||
;; See "How Emacs Chooses a Major Mode"
|
||||
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Auto-Major-Mode.html
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\.m$" . matlab-mode))
|
||||
(defun matlab-is-matlab-file ()
|
||||
"Enter `matlab-mode' when file content looks like a MATLAB *.m
|
||||
file or for empty files *.m files when `matlab-mode-for-new-mfiles'
|
||||
indicates as such."
|
||||
(and buffer-file-name ;; have a file?
|
||||
;; AND a valid MATLAB file name
|
||||
(string-match "^\\(.*/\\)?[a-zA-Z][a-zA-Z0-9_]*\\.m$" buffer-file-name)
|
||||
;; AND (have MATLAB code OR an empty file that should enter matlab-mode)
|
||||
(or
|
||||
;; Is content MATLAB code? We can definitely identify *some* MATLAB content using
|
||||
;; (looking-at "^[[:space:]\n]*\\(%\\|function\\|classdef\\)")
|
||||
;; i.e. '%', '%{' comments, or function/classdef start, but this fails to find MATLAB
|
||||
;; scripts. Thus, if buffer is NOT Objective-C and has something in it, we assume MATLAB.
|
||||
;; Objective-c is identified by
|
||||
;; - comment start chars: // or /*,
|
||||
;; - # char (as in #import)
|
||||
;; - @ char (as in @interface)
|
||||
;; MATLAB scripts are identified by the start of a valid identifier, i.e. a letter or
|
||||
;; some math operation, e.g. [1,2,3]*[1,2,3]', thus all we really need to look for
|
||||
;; is a non-whitespace character which could be a MATLAB comment, generic MATLAB commands,
|
||||
;; function/classdef, etc.
|
||||
(and (not (looking-at "^[[:space:]\n]*\\(//\\|/\\*\\|#\\|@\\)"))
|
||||
(looking-at "^[[:space:]\n]*[^[:space:]\n]"))
|
||||
;; Empty file - enter matlab-mode based on `matlab-mode-for-new-mfiles' setting
|
||||
(and (= (buffer-size) 0)
|
||||
(or (equal matlab-mode-for-new-mfiles t)
|
||||
(and (equal matlab-mode-for-new-mfiles 'maybe)
|
||||
;; Enter matlab-mode if we already have a buffer in matlab-mode
|
||||
(let ((buffers (buffer-list))
|
||||
enter-matlab-mode)
|
||||
(while buffers
|
||||
(with-current-buffer (car buffers)
|
||||
(when (or (eq major-mode 'matlab-mode)
|
||||
(eq major-mode 'matlab-shell-mode))
|
||||
(setq enter-matlab-mode t)
|
||||
(setq buffers nil)))
|
||||
(setq buffers (cdr buffers)))
|
||||
enter-matlab-mode)))))))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'magic-mode-alist '(matlab-is-matlab-file . matlab-mode))
|
||||
|
||||
;; MCR (MATLAB common run-time) *.m should enter fundamental-mode because they are binary.
|
||||
;;;###autoload
|
||||
(defun matlab-is-mcr-file ()
|
||||
(and buffer-file-name
|
||||
(string-match "^\\(.*/\\)?[a-zA-Z][a-zA-Z0-9_]*\\.m$" buffer-file-name)
|
||||
(looking-at "^[A-Z0-9]+MCR")))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'magic-mode-alist '(matlab-is-mcr-file . fundamental-mode))
|
||||
|
||||
(defvar mlint-minor-mode)
|
||||
(declare-function mlint-minor-mode "mlint.el")
|
||||
|
@ -1305,6 +1375,11 @@ Uses `regex-opt' if available. Otherwise creates a 'dumb' expression."
|
|||
(declare-function mlint-clear-cross-function-variable-highlighting "mlint.el")
|
||||
(defvar show-paren-data-function)
|
||||
|
||||
(defun matlab-mode-leave ()
|
||||
"When leaving `matlab-mode', turn off `mlint-minor-mode'"
|
||||
(when (eq major-mode 'matlab-mode)
|
||||
(mlint-minor-mode -1)))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode matlab-mode prog-mode "MATLAB"
|
||||
"MATLAB(R) mode is a major mode for editing MATLAB dot-m files.
|
||||
|
@ -1361,7 +1436,7 @@ Variables:
|
|||
All Key Bindings:
|
||||
\\{matlab-mode-map}"
|
||||
:after-hook (matlab-mode-init-mlint-if-needed)
|
||||
|
||||
|
||||
(kill-all-local-variables)
|
||||
(use-local-map matlab-mode-map)
|
||||
(setq major-mode 'matlab-mode)
|
||||
|
@ -1434,13 +1509,13 @@ All Key Bindings:
|
|||
)
|
||||
;; Enable our own block highlighting if paren mode not around.
|
||||
(matlab-enable-block-highlighting 1))
|
||||
|
||||
|
||||
(if window-system (matlab-frame-init))
|
||||
|
||||
;; built-in sexp navigation
|
||||
(make-local-variable 'forward-sexp-function)
|
||||
(setq forward-sexp-function #'matlab-move-simple-sexp-internal)
|
||||
|
||||
|
||||
;; If first function is terminated with an end statement, then functions have
|
||||
;; ends.
|
||||
(if (matlab-do-functions-have-end-p)
|
||||
|
@ -1491,6 +1566,9 @@ All Key Bindings:
|
|||
(t)
|
||||
)
|
||||
|
||||
;; When leaving matlab-mode, turn off mlint
|
||||
(add-hook 'change-major-mode-hook #'matlab-mode-leave)
|
||||
|
||||
(if matlab-vers-on-startup (matlab-show-version)))
|
||||
|
||||
(defun matlab-mode-init-mlint-if-needed ()
|
||||
|
@ -1511,7 +1589,7 @@ All Key Bindings:
|
|||
|
||||
;; If there is an error loading the stuff, don't
|
||||
;; continue.
|
||||
(error nil))))
|
||||
(error nil))))
|
||||
|
||||
|
||||
;;; Utilities =================================================================
|
||||
|
@ -1861,7 +1939,7 @@ If COUNT is negative, travel backward."
|
|||
(if (> 0 count)
|
||||
(skip-chars-backward " \t;.")
|
||||
(skip-chars-forward " \t;."))
|
||||
|
||||
|
||||
(let* ((bounds nil)
|
||||
(ctxt (matlab-cursor-comment-string-context 'bounds))
|
||||
(skipnav nil))
|
||||
|
@ -1885,7 +1963,7 @@ If COUNT is negative, travel backward."
|
|||
(forward-char (if (> 0 count) -1 1)))
|
||||
(setq skipnav t)
|
||||
)))
|
||||
|
||||
|
||||
(unless skipnav
|
||||
;; Outside of comments and strings, look at our local syntax and decide what to do.
|
||||
;; Skip over whitespace to see what the next interesting thing is.
|
||||
|
@ -1893,12 +1971,12 @@ If COUNT is negative, travel backward."
|
|||
(if (< 0 count)
|
||||
(progn ;; forward motion
|
||||
(skip-chars-forward " \t\n;.=")
|
||||
|
||||
|
||||
(cond ((or (looking-at "['\"]\\|%\\|\\.\\.\\."))
|
||||
;; In a comment or string.
|
||||
(forward-char 1)
|
||||
(matlab-up-string-or-comment))
|
||||
|
||||
|
||||
((looking-at "\\s(")
|
||||
;; At the beginning of a list, matrix, cell, whatever.
|
||||
(matlab-move-list-sexp-internal count))
|
||||
|
@ -1911,12 +1989,12 @@ If COUNT is negative, travel backward."
|
|||
;; backward motion
|
||||
(skip-chars-backward " \t\n;.=")
|
||||
(let ((ctxt2 (matlab-cursor-comment-string-context)))
|
||||
|
||||
|
||||
(cond ((or (looking-back "['\"]" (- (point) 2))
|
||||
(and (eolp) (or (eq ctxt2 'comment) (eq ctxt2 'elipsis))))
|
||||
(backward-char 2)
|
||||
(matlab-backward-up-string-or-comment))
|
||||
|
||||
|
||||
((looking-back "\\s)" (- (point) 1))
|
||||
;; At the end of a list, matrix, cell, etc
|
||||
(matlab-move-list-sexp-internal count))
|
||||
|
@ -1960,7 +2038,7 @@ This assumes that expressions do not cross \"function\" at the left margin."
|
|||
(matlab-cursor-in-string-or-comment))))
|
||||
;; Go backwards one simple expression
|
||||
(matlab-move-simple-sexp-internal -1))
|
||||
|
||||
|
||||
;; otherwise go backwards recursively across balanced expressions
|
||||
;; backup over our end
|
||||
(t
|
||||
|
@ -2243,7 +2321,7 @@ of character based."
|
|||
(lcbounds matlab-ltype-block-comm-lastcompute))
|
||||
|
||||
;;(if bounds (message "Recycle bounds") (message "no recycle bounds"))
|
||||
|
||||
|
||||
(cond ((and bounds (>= (point) (car bounds))
|
||||
(<= (point) (cdr bounds)))
|
||||
;; All set!
|
||||
|
@ -2253,7 +2331,7 @@ of character based."
|
|||
(<= (point) (cdr lcbounds)))
|
||||
;; Also all set
|
||||
nil)
|
||||
|
||||
|
||||
(t
|
||||
(setq bounds (matlab-ltype-block-comm-1)))
|
||||
)
|
||||
|
@ -2263,8 +2341,8 @@ of character based."
|
|||
;; cache point location
|
||||
(setq matlab-ltype-block-comm-lastcompute
|
||||
(cons (point-at-bol) (point-at-eol)))
|
||||
|
||||
;; Else clear lastcompute loation
|
||||
|
||||
;; Else clear lastcompute location
|
||||
(setq matlab-ltype-block-comm-lastcompute nil)
|
||||
;; Check if caller wants line bounds.
|
||||
(when (and linebounds bounds)
|
||||
|
@ -2286,11 +2364,11 @@ of character based."
|
|||
(if (and (matlab-ltype-block-comment-start)
|
||||
(not (matlab-cursor-in-string-or-comment)))
|
||||
(setq start (match-beginning 0)) ;; CHECK
|
||||
|
||||
|
||||
(while (and (setq good (re-search-backward "^\\s-*\\%\\([{}]\\)\\s-*$" nil t))
|
||||
(matlab-cursor-in-string-or-comment))
|
||||
nil)
|
||||
|
||||
|
||||
(when (and good (matlab-ltype-block-comment-start))
|
||||
(setq start (match-beginning 0))))
|
||||
|
||||
|
@ -2298,7 +2376,7 @@ of character based."
|
|||
(while (and (setq good (re-search-forward matlab-block-comment-end-re nil t))
|
||||
(matlab-cursor-in-string t))
|
||||
nil)
|
||||
|
||||
|
||||
(if (and good (goto-char (match-beginning 0)) (matlab-ltype-block-comment-end))
|
||||
(setq end (match-end 0))
|
||||
(setq end (point-max))))
|
||||
|
@ -2567,7 +2645,7 @@ line."
|
|||
(when (featurep 'pulse)
|
||||
(pulse-momentary-highlight-region (car bounds) (car (cdr bounds)))
|
||||
))))
|
||||
|
||||
|
||||
|
||||
(defun matlab-cursor-comment-string-context (&optional bounds-sym)
|
||||
"Return the comment/string context of cursor for the current line.
|
||||
|
@ -2631,7 +2709,7 @@ bounds of the string or comment the cursor is in"
|
|||
(if (or (eq returnme 'comment) (eq returnme 'elipsis))
|
||||
;; Comments and elipsis always end at end of line.
|
||||
(set bounds-sym (list laststart (point-at-eol)))
|
||||
|
||||
|
||||
;; Strings/charvec we need to keep searching forward.
|
||||
(save-excursion
|
||||
(let ((done nil)
|
||||
|
@ -2656,7 +2734,7 @@ bounds of the string or comment the cursor is in"
|
|||
(when (not done)
|
||||
(set bounds-sym (list laststart (point-at-eol))))
|
||||
))))
|
||||
|
||||
|
||||
;; Return the identified context.
|
||||
returnme))))
|
||||
|
||||
|
@ -2904,7 +2982,7 @@ Argument CURRENT-INDENTATION is what the previous line recommends for indentatio
|
|||
;; (beginning-of-line)
|
||||
;; (back-to-indentation)
|
||||
;; (= (point) (progn (matlab-beginning-of-command) (point))))
|
||||
|
||||
|
||||
;; This means we are at the beginning of a command structure.
|
||||
;; Always match up against the previous line.
|
||||
(list 'code ci))
|
||||
|
@ -3199,18 +3277,18 @@ Argument ARG specifies how many %s to insert."
|
|||
(interactive "P")
|
||||
(self-insert-command (or arg 1))
|
||||
(let ((bc (save-excursion (beginning-of-line) (matlab-ltype-block-comm))))
|
||||
|
||||
|
||||
(cond ((matlab-ltype-block-comment-start)
|
||||
|
||||
;; Starting block comment. Check if we are alreayd in a block
|
||||
|
||||
;; Starting block comment. Check if we are already in a block
|
||||
;; comment, and blink it if a problem.
|
||||
(let ((bcwrapped (save-excursion
|
||||
(beginning-of-line)
|
||||
(matlab-ltype-block-comm))))
|
||||
|
||||
;; Regardless, indent our linel
|
||||
|
||||
;; Regardless, indent our line
|
||||
(matlab-indent-line)
|
||||
|
||||
|
||||
(when bcwrapped
|
||||
(save-excursion
|
||||
(goto-char (car bcwrapped))
|
||||
|
@ -3651,6 +3729,7 @@ ARG is passed to `fill-paragraph' and will justify the text."
|
|||
(if (looking-at "%%")
|
||||
(progn (end-of-line)
|
||||
(forward-char 1)))
|
||||
(beginning-of-line)
|
||||
(point)))
|
||||
(end (save-excursion (matlab-end-of-command)
|
||||
(point)))
|
||||
|
@ -3726,7 +3805,7 @@ INTERACTIVE is ignored."
|
|||
gud-matlab-debug-active)
|
||||
;; The debugging is active, just re-enable debugging read-only-mode
|
||||
(matlab-shell-gud-minor-mode 1)
|
||||
;; Else - it is not - probably doing somethng else.
|
||||
;; Else - it is not - probably doing something else.
|
||||
(call-interactively 'read-only-mode)
|
||||
))
|
||||
|
||||
|
@ -3760,7 +3839,7 @@ Returns a list: \(HERE-BEG HERE-END THERE-BEG THERE-END MISMATCH)"
|
|||
;; where 4 == open paren and 5 == close paren
|
||||
;; and c is the char that closes the open or close paren
|
||||
;; These checks are much faster than regexp
|
||||
|
||||
|
||||
;; Step one - check for parens
|
||||
(cond ((and here-syntax (= (car here-syntax) 4)) ; open paren
|
||||
(setq here-beg (point)
|
||||
|
@ -3806,7 +3885,7 @@ Returns a list: \(HERE-BEG HERE-END THERE-BEG THERE-END MISMATCH)"
|
|||
(forward-symbol -1))
|
||||
|
||||
(matlab-navigation-syntax
|
||||
|
||||
|
||||
(condition-case err
|
||||
(cond
|
||||
((looking-at "function\\>")
|
||||
|
@ -3869,15 +3948,15 @@ Returns a list: \(HERE-BEG HERE-END THERE-BEG THERE-END MISMATCH)"
|
|||
there-end (match-end 0)
|
||||
mismatch nil)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
;; No block matches, just return nothing.
|
||||
(t (setq noreturn t))
|
||||
)
|
||||
;; An error occurred. Assume 'here-*' is set, and setup mismatch.
|
||||
(error (setq mismatch t)))
|
||||
|
||||
|
||||
|
||||
|
||||
)))
|
||||
|
||||
(if noreturn
|
||||
|
@ -4330,12 +4409,12 @@ desired. Optional argument FAST is not used."
|
|||
|
||||
;;; matlab.el ends here
|
||||
|
||||
;; LocalWords: el Wette mwette caltech edu Ludlam eludlam defconst online
|
||||
;; LocalWords: compat easymenu defcustom CASEINDENT COMMANDINDENT sexp defun
|
||||
;; LocalWords: mmode setq progn sg Fns Alist elipsis vf functionname vers
|
||||
;; LocalWords: minibuffer featurep fboundp facep zmacs defface cellbreak
|
||||
;; LocalWords: cellbreaks overline keymap torkel ispell gud allstring strchar
|
||||
;; LocalWords: bs eu bc ec searchlim eol charvec Matchers ltype cdr if'd
|
||||
;; LocalWords: el Wette mwette caltech edu Ludlam eludlam defconst online mfiles ebstop ebclear
|
||||
;; LocalWords: compat easymenu defcustom CASEINDENT COMMANDINDENT sexp defun ebstatus mlg gud's
|
||||
;; LocalWords: mmode setq progn sg Fns Alist elipsis vf functionname vers subjob flb fle elisp
|
||||
;; LocalWords: minibuffer featurep fboundp facep zmacs defface cellbreak bcend lastcompute noblock
|
||||
;; LocalWords: cellbreaks overline keymap torkel ispell gud allstring strchar decl lcbounds setcar
|
||||
;; LocalWords: bs eu bc ec searchlim eol charvec Matchers ltype cdr if'd setcdr bcwrapped
|
||||
;; LocalWords: uicontext setcolor mld keywordlist mapconcat pragmas Classdefs
|
||||
;; LocalWords: dem Za Imenu imenu alist prog reindent unindent boundp fn
|
||||
;; LocalWords: Parens symbolp prev lst nlst nreverse Aki Vehtari backquote
|
||||
|
|
Loading…
Reference in New Issue