emacs-matlab/matlab-compat.el

262 lines
9.9 KiB
EmacsLisp

;;; matlab-compat.el --- Compatibility Code
;;
;; Copyright (C) 2019 Eric Ludlam
;;
;; Author: Eric Ludlam <eludlam@osboxes>
;;
;; 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:
;;
;; To support a wide range of different Emacs versions, these compat
;; functions will hide away the shims needed to work cross platform.
;;; Code:
(eval-and-compile
(if (string-match "X[Ee]macs" emacs-version)
(progn
(defalias 'matlab-make-overlay 'make-extent)
(defalias 'matlab-overlay-put 'set-extent-property)
(defalias 'matlab-overlay-get 'extent-property)
(defalias 'matlab-delete-overlay 'delete-extent)
(defalias 'matlab-overlay-start 'extent-start-position)
(defalias 'matlab-overlay-end 'extent-end-position)
(defalias 'matlab-previous-overlay-change 'previous-extent-change)
(defalias 'matlab-next-overlay-change 'next-extent-change)
(defalias 'matlab-overlays-at
(lambda (pos) (when (fboundp 'extent-list) (extent-list nil pos pos))))
(defalias 'matlab-cancel-timer 'delete-itimer)
(defun matlab-run-with-idle-timer (secs repeat function &rest args)
(condition-case nil
(apply 'start-itimer
"matlab" function secs
(if repeat secs nil) t
t (car args)))
(error
;; If the above doesn't work, then try this old version of
;; start itimer.
(when (fboundp 'start-itimer)
(start-itimer "matlab" function secs (if repeat secs nil)))))
)
;; Else GNU Emacs
(defalias 'matlab-make-overlay 'make-overlay)
(defalias 'matlab-overlay-put 'overlay-put)
(defalias 'matlab-overlay-get 'overlay-get)
(defalias 'matlab-delete-overlay 'delete-overlay)
(defalias 'matlab-overlay-start 'overlay-start)
(defalias 'matlab-overlay-end 'overlay-end)
(defalias 'matlab-previous-overlay-change 'previous-overlay-change)
(defalias 'matlab-next-overlay-change 'next-overlay-change)
(defalias 'matlab-overlays-at 'overlays-at)
(defalias 'matlab-cancel-timer 'cancel-timer)
(defalias 'matlab-run-with-idle-timer 'run-with-idle-timer)
))
;;; Helper aliases to suppress compiler warnings ===============================
(eval-and-compile
;; `set-face-underline-p' is an obsolete function (as of 24.3); use `set-face-underline' instead.
(cond ((fboundp 'set-face-underlined)
(defalias 'matlab-set-face-underline 'set-face-underlined))
(t
(defalias 'matlab-set-face-underline 'set-face-underline-p)))
;; `set-face-bold-p' is an obsolete function (as of 24.4); use `set-face-bold' instead.
(cond ((fboundp 'set-face-bold)
(defalias 'matlab-set-face-bold 'set-face-bold))
(t
(defalias 'matlab-set-face-bold 'set-face-bold-p)))
;; `default-fill-column' is an obsolete variable (as of 23.2); use `fill-column' instead.
(cond ((boundp 'fill-column)
(defvaralias 'matlab-fill-column 'fill-column))
(t
(defvaralias 'matlab-fill-column 'default-fill-column)))
;; `interactive-p' is an obsolete function (as of 23.2); use `called-interactively-p' instead.
(defun matlab-called-interactively-p-helper ()
(called-interactively-p 'interactive))
(cond ((fboundp 'called-interactively-p)
(defalias 'matlab-called-interactively-p 'matlab-called-interactively-p-helper))
(t
(defalias 'matlab-called-interactively-p 'interactive-p)))
;; `toggle-read-only' is an obsolete function (as of 24.3); use `read-only-mode' instead.
;; (matlab-read-only-mode -1) ==> make writable
;; (matlab-read-only-mode 1) ==> make read-only
(cond ((fboundp 'read-only-mode)
(defalias 'matlab-read-only-mode 'read-only-mode))
(t
(defalias 'matlab-read-only-mode 'toggle-read-only)))
(cond ((fboundp 'point-at-bol)
(defalias 'matlab-point-at-bol 'point-at-bol)
(defalias 'matlab-point-at-eol 'point-at-eol))
;; Emacs 20.4
((fboundp 'line-beginning-position)
(defalias 'matlab-point-at-bol 'line-beginning-position)
(defalias 'matlab-point-at-eol 'line-end-position))
(t
(defmacro matlab-point-at-bol ()
(save-excursion (beginning-of-line) (point)))
(defmacro matlab-point-at-eol ()
(save-excursion (end-of-line) (point)))))
)
;; Keymaps
(if (fboundp 'set-keymap-parent)
(defalias 'matlab-set-keymap-parent 'set-keymap-parent)
;; 19.31 doesn't have set-keymap-parent
(eval-when-compile
(require 'comint))
(defun matlab-set-keymap-parent (keymap parent)
"Set KEYMAP's parent to be PARENT."
(nconc keymap comint-mode-map)))
;; String trim
(if (locate-library "subr-x")
(progn
(require 'subr-x)
(defalias 'matlab-string-trim 'string-trim)
)
(defsubst matlab-string-trim (string &optional regexp)
"Trim STRING of leading string matching REGEXP.
REGEXP defaults to \"[ \\t\\n\\r]+\"."
(let ((out string)
(regexp_ (or regexp "[ \t\n\r]+")))
(when (string-match (concat "\\`\\(?:" regexp_ "\\)") out)
(setq out (substring out (match-end 0))))
(when (string-match (concat "\\(?:" regexp_ "\\)\\'") out)
(setq out (substring out 0 (match-beginning 0))))
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.
Return the base directory it is in."
(let ((dir nil))
(dolist (P exec-path)
(let ((nm (expand-file-name program P)))
(when (and (file-exists-p nm) (file-executable-p nm))
(let* ((fa (file-attributes nm))
(lnk (car fa)))
;; The car is t for a directory, a string for a link, nil otherwise
(if (stringp lnk)
;; We have a link - use that as our directory.
(setq dir (file-name-directory lnk))
;; No link - just use this path.
(setq dir P)))
)))
dir))
;; Completion Tools
(defun matlab-display-completion-list (completions common-substring)
"Method for displaying COMPLETIONS with a COMMON-SUBSTRING."
;; In emacs 24.4 the common-substring is no longer needed.
(let ((args (if (or (< emacs-major-version 24)
(and (= emacs-major-version 24) (< emacs-minor-version 4)))
(list completions common-substring)
(list completions))))
(apply 'display-completion-list args)))
;; Font lock
(require 'font-lock)
(unless (fboundp 'font-lock-ensure)
(defalias 'font-lock-ensure 'font-lock-fontify-buffer))
;; CEDET compat if CEDET isn't around
(condition-case nil
(progn
(require 'pulse)
)
(error
(defun pulse-momentary-highlight-region (start end &optional face)
"Compat impl of pulse command." nil)))
;; EIEIO compatibility
(condition-case nil
(progn
(require 'eieio)
(unless (fboundp 'cl-defgeneric)
;; We are in an antique Emacs that uses the old eieio.
(defalias 'cl-defmethod 'defmethod)
)
(unless (fboundp 'cl-call-next-method)
;; We are in an antique Emacs that uses the old eieio.
(defalias 'cl-call-next-method 'call-next-method)
)
)
(error (message "EIEIO not available. Only MATLAB editing enabled.")))
;;; Finding EmacsClient
(defun matlab-find-emacsclient ()
"Locate the emacsclient correspoinding to the current emacs
binary defined by `invocation-name' in `invocation-directory'"
(let ((ec "emacsclient"))
(cond
;; Mac
((equal system-type 'darwin)
(if (file-exists-p (concat invocation-directory "emacsclient")) ;; running the default emacs?
(setq ec (concat invocation-directory "emacsclient"))
;; On Mac, one can install into
;; /Applications/Emacs.app/Contents/MacOS/Emacs
;; /Applications/Emacs.app/Contents/MacOS/bin/emacsclient
(if (file-exists-p (concat invocation-directory "bin/emacsclient"))
(setq ec (concat invocation-directory "bin/emacsclient")))))
;; Windows
((equal system-type 'windows-nt)
(if (file-exists-p (concat invocation-directory "emacsclientw.exe"))
(setq ec (concat invocation-directory "emacsclientw.exe"))
(error "unable to locate emacsclientw.exe. It should be in %s" invocation-directory)))
;; Linux or other UNIX system
(t
;; Debian 9 can be setup to have:
;; /usr/bin/emacs
;; /usr/bin/emacsclient
;; /usr/bin/emacs24
;; /usr/bin/emacsclient.emacs24
;; /usr/bin/emacs25
;; /usr/bin/emacsclient.emacs25
(if (and (equal invocation-name "emacs")
(file-exists-p (concat invocation-directory "emacsclient")))
(setq ec (concat invocation-directory "emacsclient"))
(if (file-exists-p (concat invocation-directory "emacsclient." invocation-name))
(setq ec (concat invocation-directory "emacsclient." invocation-name))))))
;; Return, ec, the emacsclient to use
ec
))
(provide 'matlab-compat)
;;; matlab-compat.el ends here
;; LocalWords: el Ludlam eludlam osboxes Ee progn defalias fboundp itimer
;; LocalWords: defun boundp defvaralias bol eol defmacro Keymaps keymap comint
;; LocalWords: KEYMAP's nconc dolist nm lnk setq