MATLAB
I still use MATLAB a lot. It works quite well with emacs. A good introduction is here.
(use-package matlab :demand :ensure matlab-mode :if <<do.matlab/binary>> :bind <<do.matlab/keys>> :mode ("\\.m$" . matlab-mode) :init <<do.matlab/run-matlab>> <<do.matlab/settings>> <<do.matlab/alias>> <<do.matlab/shell-hooks>> <<do.matlab/hooks>> (require 'mlint) <<do.matlab/mlint-settings>> <<do.matlab/mlint-faces>> <<do.matlab/mlint-post-command>>)
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" (interactive) (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) (matlab-shell) ;; else set the correct $SHELL, launch matlab, and revert changes (setenv "SHELL" posix-shell-name) (matlab-shell) (setenv "SHELL" original-shell-env-var)))) (defun run-matlab-debug () (interactive) (let ((matlab-shell-command-switches '("-nodesktop" "-nosplash" "-nojvm" "-Dgdb"))) (run-matlab)))
Aliases
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)
Keybindings
(:map matlab-mode-map ("C-c C-c" . matlab-shell-run-region-or-line))
mlint
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)))))
Hooks
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) (highlight-symbol-mode) (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)