I still use MATLAB a lot. It works quite well with emacs. A good introduction is here.

(use-package matlab
  :ensure matlab-mode
  :mode ("\\.m$" . matlab-mode)
  (require 'mlint)

Find the binary

(cond ((boundp 'matlab-shell-command) t)
      ((executable-find "matlab")
       (setq matlab-shell-command (executable-find "matlab")) t)
      (t nil))

General settings

(setq matlab-indent-function t)
(setq matlab-shell-enable-gud-flag t)
(setq matlab-shell-command-switches '("-nodesktop" "-nosplash"))
(setq-default matlab-function t)
(setq-default matlab-highlight-cross-function-variables t)
(setq-default matlab-functions-have-end t)
(setq-default matlab-fill-code nil)
(setq-default matlab-vers-on-startup nil)
(when (boundp 'company-dabbrev-code-modes)
  (add-to-list 'company-dabbrev-code-modes 'matlab-mode)
  (add-to-list 'company-dabbrev-code-modes 'matlab-shell-mode))

Running MATLAB

MATLAB does not play nice with my shell of choice, fish. It looks like MATLAB uses shell commands internally that assume a POSIX-compliant shell. This can be fixed by setting the environment variable $SHELL before launching MATLAB. $SHELL gets passed on to MATLAB from emacs. We need to therefore make sure that emacs passes /bin/bash as $SHELL to MATLAB.

(defun run-matlab ()
  "Execute MATLAB-SHELL with POSIX-compliant SHELL env variable"
  (let ((posix-shell-name "/bin/bash")
        (original-shell-env-var (getenv "SHELL")))
    ;; need to disable DRI3 according to red hat bug #1357571
    ;; (setenv "LIBGL_DRI3_DISABLE" "true") ;; -- seems to have been worked out now
    ;; if $SHELL is bash, just launch matlab
    (if (string= original-shell-env-var posix-shell-name)
      ;; else set the correct $SHELL, launch matlab, and revert changes
      (setenv "SHELL" posix-shell-name)
      (setenv "SHELL" original-shell-env-var))))

(defun run-matlab-debug ()
  (let ((matlab-shell-command-switches '("-nodesktop" "-nosplash" "-nojvm" "-Dgdb")))


We also want to have a legacy alias to launch matlab-shell and to run a line MATLAB code.

(defalias 'mshell 'run-matlab)
(defalias 'mrun 'matlab-shell-run-region-or-line)


(:map matlab-mode-map
      ("C-c C-c" .  matlab-shell-run-region-or-line))


This section configures mlint to check my MATLAB syntax after every save. We first need to point it at the right binary and set some general settings.

(if (boundp 'do.matlab/mlint-program)
    (setq mlint-program do.matlab/mlint-program)
  (setq mlint-program (executable-find "mlint")))
(setq-default matlab-show-mlint-warnings t)
(setq-default mlint-verbose nil)

Make the mlint warning faces a little more palatable.

(set-face-attribute 'linemark-stop-face nil
        :background 'unspecified
        :underline '(:color "red3" :style wave))
(set-face-attribute 'linemark-caution-face nil
        :background 'unspecified
        :underline '(:color "yellow4" :style wave))
(set-face-attribute 'linemark-go-face nil
        :background 'unspecified
        :underline '(:color "green4" :style wave))
(set-face-attribute 'linemark-funny-face nil
        :background 'unspecified
        :underline '(:color "blue3" :style wave))

In order to try to make mlint behave a little more like flycheck, I want to add a function similar to mlint-show-warning to my post-command-hook. It gets added to the hook in the "Hooks" section below.

(defun do.matlab/mlint-post-command ()
  "Show the warning for the current mark.
This is intended to be run after every command. It only prints a
message if there is a error at point."
  (let ((n (linemark-at-point (point) mlint-mark-group)))
    (when n
      (message (oref n warning)))))


First, the hook for the MATLAB shell.

(defun do.matlab/shell-hooks ()
  (setq global-hl-line-mode nil)
  (setq-local ml-interactive? t) ;; for mode line
  (setq show-trailing-whitespace nil))
(add-hook 'matlab-shell-mode-hook 'do.matlab/shell-hooks)

Now the hook for matlab-mode. Mostly setting up mlint.

(defun do.matlab/hooks ()
  (flycheck-mode -1)
  (mlint-minor-mode 1)
  (add-hook 'post-command-hook 'do.matlab/mlint-post-command)
  (setq-local company-backends (remove 'company-capf do.completion/backend-list)))
(add-hook 'matlab-mode-hook 'do.matlab/hooks)