home *** CD-ROM | disk | FTP | other *** search
- ;; octave-mode.el - major mode for Octave function files
- ;;
- ;; Copyright (C) 1994 John W. Eaton
- ;;
- ;; This file is part of Octave.
- ;;
- ;; Octave 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 2, or (at your option) any
- ;; later version.
- ;;
- ;; Octave 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 Octave; see the file COPYING. If not, write to the Free
- ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- ;;
- ;; This major mode for GNU emacs provides support for editing Octave
- ;; function files. It requires matlab-mode.el, which was written by
- ;; Matthew R. Wette <mwette@csi.jpl.nasa.gov>.
- ;;
- ;; It automatically indents block structures, line continuations
- ;; (e.g., ...), and comments. The usual paren matching support is
- ;; included. Filling and auto-fill works for comment lines. For
- ;; convenient use, put this file and matlab.el in your Emacs
- ;; load-path and add something like the following to your .emacs
- ;; start-up file:
- ;;
- ;; (autoload 'octave-mode "octave-mode" "Enter Octave mode." t)
- ;; (setq auto-mode-alist (cons '("\\.m$" . octave-mode) auto-mode-alist))
- ;; (defun my-octave-mode-hook ()
- ;; (setq fill-column 76)
- ;; (turn-on-auto-fill))
- ;; (setq octave-mode-hook 'my-octave-mode-hook)
- ;;
- ;; For Lucid Emacs, add ``(font-lock-mode 1)'' to your octave-bmode-hook.
-
- ;; Customize Matlab mode for Octave users.
-
- (setq matlab-comment-column 0)
- (setq matlab-comment-line-s "# ")
- (setq matlab-comment-on-line-s "# ")
- (setq matlab-comment-region-s "#$$$ ")
-
- (defconst matlab-show-vers t
- "*If non-nil, shows the version number on load.")
-
- ;; octave-mode
- (defun matlab-mode ()
- "Major mode for editing Octave function files. Version 1.0.
- Will run octave-mode-hook if it is non-nil. Filling works (comments justify).
-
- Special Key Bindings:
- \\{matlab-mode-map}
- Variables:
- matlab-indent-level Level to indent blocks.
- matlab-comment-column Goal column for on-line comments.
- fill-column Column used in auto-fill.
- matlab-comment-line-s String to start comment line.
- matlab-comment-region-s String to put comment lines in region.
- matlab-indent-before-return If t, matlab-indent-line before RET.
- matlab-indent-end-before-return If t, indent-line before RET on end.
- matlab-show-vers If t, show version on start-up.
-
- Commands:
- matlab-mode Enter MATLAB major mode.
- matlab-return RET with post indenting.
- matlab-linefeed RET with pre and post indent.
- matlab-comment-return RET for next-line comment.
- matlab-indent-line Indent line for structure.
- matlab-comment Add comment to current line.
- matlab-comment-indent Compute indent for comment.
- matlab-comment-region Comment (with arg, uncomment) region.
- matlab-fill-region Fill region (usually comments).
- matlab-justify-line Delete space on end and justify.
-
- To add automatic support put something like the following in your .emacs file:
- \(autoload 'matlab-mode \"matlab-mode\" \"Enter Matlab mode.\" t\)
- \(setq auto-mode-alist \(cons '\(\"\\\\.m$\" . matlab-mode\) \
- auto-mode-alist\)\)
- \(defun my-matlab-mode-hook \(\)
- \(setq fill-column 76\)
- \(turn-on-auto-fill\)\)
- \(setq matlab-mode-hook 'my-matlab-mode-hook\)"
- (interactive)
- (kill-all-local-variables)
- (use-local-map matlab-mode-map)
- (setq major-mode 'matlab-mode)
- (setq mode-name "Matlab")
- (setq local-abbrev-table matlab-mode-abbrev-table)
- (set-syntax-table matlab-mode-syntax-table)
- (make-local-variable 'paragraph-start)
- (setq paragraph-start (concat "^$\\|" page-delimiter))
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate paragraph-start)
- (make-local-variable 'paragraph-ignore-fill-prefix)
- (setq paragraph-ignore-fill-prefix t)
- (make-local-variable 'indent-line-function)
- (setq indent-line-function 'matlab-indent-line)
- (make-local-variable 'comment-start-skip)
- (setq comment-start-skip "%[ \t]*")
- (make-local-variable 'comment-column)
- (setq comment-column 'matlab-comment-column)
- (make-local-variable 'auto-fill-hook)
- (setq auto-fill-hook 'matlab-auto-fill)
- (make-local-variable 'comment-indent-hook)
- (setq comment-indent-hook 'matlab-comment-indent)
- (make-local-variable 'fill-column)
- (setq fill-column default-fill-column)
- (make-local-variable 'fill-prefix)
- (setq fill-prefix matlab-comment-line-s)
- ;;(setq font-lock-keywords matlab-font-lock-keywords) ;; Lucid emacs
- ;;(setq (make-local-variable 'font-lock-keywords) matlab-font-lock-keywords)
- (run-hooks 'matlab-mode-hook)
- (if matlab-show-vers
- (message "matlab-mode, Version 1.06.0 Dated 23Nov93")))
-
-
- (defconst mtlb-cline-start-skip "[ \t]*%[ \t]*"
- "*The regular expression for skipping comment start.")
-
- ;;
- (defun matlab-auto-fill ()
- "Do filling."
- (interactive)
- (cond
- ((mtlb-ltype-comment) do-auto-fill)
- ((mtlb-lattr-comment) do-auto-fill)
- (t ())))
-
-
- (defun matlab-return ()
- "Handle carriage return in matlab-mode."
- (interactive)
- (if matlab-indent-before-return
- (matlab-indent-line)
- (if matlab-indent-end-before-return
- (if (mtlb-ltype-block-end) (matlab-indent-line))))
- (newline)
- (matlab-indent-line))
-
- (defun matlab-linefeed ()
- "Handle linefeed in matlab-mode.
- Has effect of matlab-return with (not matlab-indent-before-return)."
- (interactive)
- (if (not matlab-indent-before-return) (matlab-indent-line))
- (newline)
- (matlab-indent-line))
-
- (defun matlab-comment-return ()
- "Handle carriage return for matlab comment line."
- (interactive)
- (cond
- ((mtlb-ltype-comment)
- (mtlb-set-comment-fill-prefix) (newline) (insert fill-prefix)
- (matlab-indent-line))
- ((mtlb-lattr-comment)
- (newline) (indent-to matlab-comment-column)
- (insert matlab-comment-on-line-s))
- (t
- (newline) (matlab-comment) (matlab-indent-line))))
-
- (defun matlab-indent-line ()
- "Indent a line in matlab-mode."
- (interactive)
- (save-excursion
- (beginning-of-line)
- (delete-horizontal-space)
- (indent-to (mtlb-calc-indent))
- ;; -- If line contains a comment, format it. --
- (if (or (mtlb-ltype-comment) (mtlb-lattr-comment))
- (matlab-comment)))
- (skip-chars-forward " \t%"))
-
-
- (defun matlab-comment ()
- "Add a comment to the current line. If one already exists, format it."
- (interactive)
- (cond
- ((mtlb-ltype-empty)
- (matlab-indent-line)
- (insert matlab-comment-line-s))
- ((mtlb-ltype-comment)
- (save-excursion
- (if (and (= 0 (forward-line -1)) (mtlb-ltype-comment))
- (progn
- (mtlb-set-comment-fill-prefix)
- (forward-line 1)
- (beginning-of-line)
- (delete-horizontal-space) (delete-char 1) (delete-horizontal-space)
- (insert fill-prefix)))))
- ((mtlb-lattr-comment)
- (beginning-of-line)
- (search-forward "%")
- (forward-char -1)
- (delete-horizontal-space)
- (insert " ")
- (if (< (current-column) matlab-comment-column)
- (indent-to matlab-comment-column))
- (skip-chars-forward "% "))
- (t
- (end-of-line)
- (re-search-backward "[^ \t\n^]" 0 t)
- (forward-char)
- (delete-horizontal-space)
- (if (< (current-column) matlab-comment-column)
- (indent-to matlab-comment-column)
- (insert " "))
- (insert matlab-comment-on-line-s))))
-
-
- (defun matlab-comment-indent ()
- "Indent a comment line in matlab-mode."
- (mtlb-calc-indent))
-
- (defun mtlb-calc-indent ()
- "Return the appropriate indentation for this line as an int."
- (let ((indent 0))
- (save-excursion
- (if (not (mtlb-prev-line))
- 0
- (setq indent (current-indentation))
- (setq indent
- (+ indent
- (cond
- ((mtlb-ltype-comment) (mtlb-set-comment-fill-prefix) 0)
- ((mtlb-ltype-block-beg) matlab-indent-level)
- ((mtlb-ltype-block-end) 0)
- (t (mtlb-calc-blok-indent)))))
- (if (mtlb-lattr-unbal-mexp)
- (setq indent (+ indent (mtlb-calc-mexp-indent))))
- (if (mtlb-lattr-cont)
- (setq indent (+ indent (* 2 matlab-indent-level)))))
- (if (mtlb-prev-line)
- (if (mtlb-lattr-cont)
- (setq indent (- indent (* 2 matlab-indent-level))))))
- (if (mtlb-ltype-block-end)
- (setq indent (- indent matlab-indent-level)))
- (if (< indent 0) (setq indent 0))
- indent))
-
- (defun mtlb-prev-line ()
- "Find the previous line. Return 0 if not found."
- (interactive)
- (if (/= 0 (forward-line -1))
- ()
- (if (mtlb-ltype-empty)
- (mtlb-prev-line)
- t)))
-
- (defun matlab-comment-region (beg-region end-region arg)
- "Comments every line in the region.
- Puts matlab-comment-region-s at the beginning of every line in the region.
- BEG-REGION and END-REGION are args which specify the region boundaries.
- With non-nil ARG, uncomments the region."
- (interactive "*r\nP")
- (let ((end-region-mark (make-marker)) (save-point (point-marker)))
- (set-marker end-region-mark end-region)
- (goto-char beg-region)
- (beginning-of-line)
- (if (not arg) ;comment the region
- (progn (insert matlab-comment-region-s)
- (while (and (= (forward-line 1) 0)
- (< (point) end-region-mark))
- (insert matlab-comment-region-s)))
- (let ((com (regexp-quote matlab-comment-region-s))) ;uncomment the region
- (if (looking-at com)
- (delete-region (point) (match-end 0)))
- (while (and (= (forward-line 1) 0)
- (< (point) end-region-mark))
- (if (looking-at com)
- (delete-region (point) (match-end 0))))))
- (goto-char save-point)
- (set-marker end-region-mark nil)
- (set-marker save-point nil)))
-
-
- (defun matlab-fill-region (beg-region end-region &optional justify-flag)
- "Fill the region. Non-nil arg means justify commment lines as well."
- (interactive "*r\nP")
- (let ((end-reg-mk (make-marker)))
- (set-marker end-reg-mk end-region)
- (goto-char beg-region)
- (beginning-of-line)
- (while (< (save-excursion (forward-line 1) (point)) end-reg-mk)
- (if (save-excursion (= (forward-line 1) 0))
- (progn
- (cond
- ((mtlb-ltype-comment)
- (while (matlab-fill-comment-line))
- (if justify-flag (justify-comment-line))))
- (forward-line 1))))))
-
- (defun matlab-fill-comment-line ()
- "Fill the current comment line."
- (interactive)
- (let ((prev-indent-col 0))
- (beginning-of-line)
- (re-search-forward mtlb-cline-start-skip)
- (setq prev-indent-col (current-column))
- (mtlb-set-comment-fill-prefix)
- (if (/= (forward-line 1) 0)
- ()
- (beginning-of-line)
- (re-search-forward mtlb-cline-start-skip)
- (if (/= prev-indent-col (current-column))
- (progn (forward-line -1) ())
- (mtlb-join-comment-lines)
- (if (mtlb-wrap-line)
- (save-excursion
- (forward-line 1)
- (beginning-of-line)
- (insert fill-prefix)
- t))))))
-
- (defun mtlb-join-comment-lines ()
- "Join current comment line to previous, deleting space and comment mark."
- (interactive)
- (beginning-of-line)
- (forward-char -1) (delete-char 1) ; delete newline
- (delete-horizontal-space)
- (delete-char 1) ; delete "%"
- (delete-horizontal-space)
- (insert " "))
-
- (defun mtlb-wrap-line ()
- "Wrap line so last token on line does not exceed fill-column."
- (interactive)
- (save-excursion
- (end-of-line)
- (delete-horizontal-space)
- (if (< (current-column) fill-column)
- ()
- (while (> (current-column) fill-column) (forward-char -1))
- (while (not (looking-at "[ \t]")) (forward-char -1))
- (delete-horizontal-space)
- (insert "\n")
- t)))
-
- (defun mtlb-set-comment-fill-prefix ()
- "Set the fill-prefix for the current comment line."
- (setq fill-prefix
- (save-excursion
- (beginning-of-line)
- (buffer-substring
- (point)
- (progn (re-search-forward mtlb-cline-start-skip) (point)))))
- (if (equal fill-prefix "")
- (setq fill-prefix nil)))
-
- (defun matlab-justify-line ()
- "Delete space on end of line and justify."
- (interactive)
- (save-excursion
- (end-of-line)
- (delete-horizontal-space)
- (justify-current-line)))
-
-
- ;;;
- ;;; line attributes ...
- (defun mtlb-lattr-comment ()
- "Returns t if current line contains a comment."
- (save-excursion
- (beginning-of-line)
- (looking-at ".*%")))
-
- (defun mtlb-lattr-cont ()
- "Returns t if current line ends in .. and optional comment."
- (save-excursion
- (beginning-of-line)
- (re-search-forward
- "[^; \t.][ \t]*\\.\\.\\.+[ \t]*\\(%.*\\)?$"
- (save-excursion (end-of-line) (point))
- t)))
-
- (defun mtlb-lattr-unbal-mexp ()
- (/= (mtlb-calc-mexp-indent) 0))
-
-
- ;;;
- ;;; line types ...
- (defun mtlb-ltype-empty ()
- "Returns t if current line is empty."
- (save-excursion
- (beginning-of-line)
- (looking-at "^[ \t]*$")))
-
- (defun mtlb-ltype-comment ()
- "Returns t if current line is a MATLAB comment line."
- (save-excursion
- (beginning-of-line)
- (looking-at "[ \t]*%")))
-
- (defun mtlb-ltype-block-beg ()
- "Returns t if line contains beginning of MATLAB block."
- (save-excursion
- (beginning-of-line)
- (and
- (looking-at (concat "[^%\n]*" mtlb-block-beg-kw))
- (not (mtlb-ltype-blk-beg-end)))))
-
- (defun mtlb-ltype-block-end ()
- "Returns t if line contains end of MATLAB block."
- (save-excursion
- (beginning-of-line)
- (and
- (looking-at (concat "\\([^%\n]*[ \t]\\)?" mtlb-block-end-kw))
- (not (mtlb-ltype-blk-beg-end)))))
-
- (defun mtlb-ltype-blk-beg-end ()
- "Returns t if line contains matching block begin-end in matlab-mode."
- (save-excursion
- (beginning-of-line)
- (looking-at (concat "[^%\n]*" mtlb-block-beg-kw
- "[^%\n]+" mtlb-block-end-kw))))
-
-
- ;;;
- ;;; utility functions ...
- (defconst mtlb-block-beg-kw "\\b\\(for\\|while\\|if\\|else\\|elseif\\)\\b"
- "Regular expression for keywords which begin blocks in matlab-mode.")
-
- (defconst mtlb-block-end-kw "\\b\\(end\\|else\\|elseif\\)\\b"
- "Regular expression for keywords which end blocks.")
-
- (defun mtlb-calc-blok-indent ()
- (let ((indent 0))
- (save-excursion
- (beginning-of-line)
- (while (< (point) (save-excursion (end-of-line) (point)))
- (cond
- ((looking-at mtlb-block-beg-kw)
- (setq indent (+ indent matlab-indent-level)))
- ((looking-at mtlb-block-end-kw)
- (setq indent (- indent matlab-indent-level))))
- (forward-char)))
- indent))
-
- (defun mtlb-calc-mexp-indent ()
- (let ((indent 0))
- (save-excursion
- (beginning-of-line)
- (while (< (point) (save-excursion (end-of-line) (point)))
- (cond
- ((looking-at "\\[")
- (setq indent (+ indent matlab-indent-level)))
- ((looking-at "\\]")
- (setq indent (- indent matlab-indent-level))))
- (forward-char)))
- (* 2 indent)))
-
- ;;;
- ;;; -- debugging --
- (defun matlab-show-line-attr ()
- "Display type and attributes of current line. Used in debugging."
- (interactive)
- (let ((msg "matlab-show-line-attr:"))
- (cond
- ((mtlb-ltype-empty)
- (setq msg (concat msg " empty")))
- ((mtlb-ltype-comment)
- (setq msg (concat msg " comment")))
- ((mtlb-ltype-block-beg)
- (setq msg (concat msg " block-begin")))
- ((mtlb-ltype-block-end)
- (setq msg (concat msg " block-end")))
- (t
- (setq msg (concat msg " other"))))
- (if (mtlb-lattr-cont)
- (setq msg (concat msg " w/cont")))
- (if (mtlb-lattr-comment)
- (setq msg (concat msg " w/comm")))
- (if (mtlb-lattr-unbal-mexp)
- (setq msg (concat msg " w/unbal-mexp")))
- (message msg)))
-
- (defun matlab-show-blok-indent ()
- "Display indentation for matrix expression. Used in debugging."
- (interactive)
- (let ((msg "matlab-show-blok-indent: "))
- (setq msg (concat msg (mtlb-calc-blok-indent)))
- (message msg)))
-
- (defun matlab-show-mexp-indent ()
- "Display indentation for matrix expression. Used in debugging."
- (interactive)
- (let ((msg "matlab-show-mexp-indent: "))
- (setq msg (concat msg (mtlb-calc-mexp-indent)))
- (message msg)))
-
-
- ;;; --- version 19 stuff ...
- (defvar matlab-font-lock-keywords
- (list
- '("\\b\\(break\\|else\\|elseif\\|end\\|for\\|if\\|return\\|while\\)\\b"
- . font-lock-keyword-face)
- '("\\bfunction[^=]+=[^)]+)" . font-lock-function-name-face)
- )
- "Expressions to hightlight in Matlab mode.")
-
- (if (featurep 'lhilit)
- (hilit-set-mode-patterns
- 'matlab-mode
- '(("%.*$" nil comment)
- ;;("'.*'" nil string)
- ("\\bfunction[^=]+=[^)]+)" nil defun)
- ;; key words
- ("\\<\\(load\\|save\\|clear\\)\\>" nil include)
- ("\\<\\(break\\|else\\|elseif\\|end\\|for\\|if\\|return\\)\\>"
- nil keyword)
- )))
-
-
- ;;; -- stuff which belongs elsewhere --
- (defun justify-comment-line ()
- "Add spaces to comment line point is in, so it ends at fill-column."
- (interactive)
- (save-excursion
- (save-restriction
- (let (ncols beg)
- (beginning-of-line)
- (forward-char (length fill-prefix))
- (skip-chars-forward " \t")
- (setq beg (point))
- (end-of-line)
- (narrow-to-region beg (point))
- (goto-char beg)
- (while (re-search-forward " *" nil t)
- (delete-region
- (+ (match-beginning 0)
- (if (save-excursion
- (skip-chars-backward " ])\"'")
- (memq (preceding-char) '(?. ?? ?!)))
- 2 1))
- (match-end 0)))
- (goto-char beg)
- (while (re-search-forward "[.?!][])""']*\n" nil t)
- (forward-char -1)
- (insert " "))
- (goto-char (point-max))
- (setq ncols (- fill-column (current-column)))
- (if (search-backward " " nil t)
- (while (> ncols 0)
- (let ((nmove (+ 3 (% (random) 3))))
- (while (> nmove 0)
- (or (search-backward " " nil t)
- (progn
- (goto-char (point-max))
- (search-backward " ")))
- (skip-chars-backward " ")
- (setq nmove (1- nmove))))
- (insert " ")
- (skip-chars-backward " ")
- (setq ncols (1- ncols))))))))
-
- (provide 'matlab-mode)
- ;; --- last line of matlab-mode.el ---
-