File: matlab-is-matlab-file.el

package info (click to toggle)
matlab-mode 7.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 12,132 kB
  • sloc: lisp: 167,753; sh: 5; makefile: 5
file content (122 lines) | stat: -rw-r--r-- 5,832 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
;;; matlab-is-matlab-file.el --- enter MATLAB mode? -*- lexical-binding: t -*-

;; Author: john.ciolfi.32@gmail.com
;; URL: https://github.com/mathworks/Emacs-MATLAB-Mode
;; SPDX-License-Identifier: GPL-3.0-or-later

;; Copyright (C) 1991-2025 Free Software Foundation, Inc.
;;
;; 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:
;;
;; When visiting a *.m file, enter matlab-ts-mode (or matlab-mode) if it contains MATLAB content.
;; The default Emacs setup assumes *.m files a Objective-C and therefore, we use magic-mode-alist to
;; enter matlab mode when needed.

;;; Code:


(defgroup matlab nil
  "MATLAB(R) mode."
  :prefix "matlab-"
  :group 'languages)

(defcustom matlab-mode-for-new-mfiles 'maybe
  "*Enter MATLAB mode for new *.m files.
Enter `matlab-ts-mode' or `matlab-mode' when the first part of a *.m
file is not 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 enter `objc-mode'."
  :group 'matlab
  :type '(choice (const :tag "Always" t)
                 (const :tag "Never" nil)
                 (const :tag "Maybe" maybe)))

;; 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
(defun matlab-is-matlab-file ()
  "Enter MATLAB mode when file content is likely a MATLAB *.m file.
The MATLAB mode will be `matlab-ts-mode' when the following is in effect:
  (add-to-list \\='major-mode-remap-alist \\='(matlab-mode . matlab-ts-mode))
Otherwise the MATLAB mode will be `matlab-mode'.

This will also enter MATLAB mode 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\\'"  ;; /path/to/file.m ?
        ;; buffer-file-name in archives look like:
        ;;   /path/to/archive.zip:archive/foo.m
        ;; and the ":" causes it too look like an invalid m-file path, so compare against the file
        ;; name from the archive.
        (file-name-sans-versions
         (if (and (boundp 'archive-subfile-mode) archive-subfile-mode)
             ;; When in an archive, the buffer-file-name will look like /path/to/archive.zip:foo.m,
             ;; which will not be a valid M-file name because of the ":". Therefore, match against
             ;; the file in the archive without the archive path.
             (if (fboundp 'archive--file-desc-ext-file-name) ;; Emacs 28+ uses a cl-defstruct.
                 (archive--file-desc-ext-file-name archive-subfile-mode)
               ;; Emacs 27 uses an array
               (aref archive-subfile-mode 0))
           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-ts-mode)
                                      (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))

(provide 'matlab-is-matlab-file)
;;; matlab-is-matlab-file.el ends here

;; LocalWords:  alist defcustom mfiles objc defun boundp aref setq cdr fboundp defstruct