home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21eb.zip / octave / lisp / octave-mode.el < prev    next >
Lisp/Scheme  |  1999-05-13  |  16KB  |  410 lines

  1. ;; octave-mode.el - major mode for editing Octave source with GNU Emacs
  2. ;;
  3. ;; This major mode for GNU Emacs provides support for editing Octave
  4. ;; source files.  It automatically indents for block structures, line
  5. ;; continuations (e.g., ...), and comments.  The usual paren matching
  6. ;; support is included.  Indenting for continued matrix expressions is
  7. ;; currently not supported.  Perhaps it will be in the future.  Auto-fill
  8. ;; mode seems to actually work!  For convient use add something like the
  9. ;; following to your .emacs start-up file:
  10. ;;
  11. ;;   (autoload 'octave-mode "octave-mode" "Enter Octave-mode." t)
  12. ;;   (setq auto-mode-alist (cons '("\\.m$" . octave-mode) auto-mode-alist))
  13. ;;   (setq octave-mode-hook '(lambda () (setq fill-column 74)))
  14. ;;
  15. ;; Enjoy.
  16. ;;
  17. ;; Last modified Sun Mar  7 17:55:20 1993.
  18. ;;
  19. ;; This file was modified by John W. Eaton (jwe@che.utexas.edu) from
  20. ;; the file matlab-mode.el which is:
  21. ;;
  22. ;; Copyright (C) 1991 Matthew R. Wette.
  23. ;; Everyone is granted permission to copy, modify and redistribute this
  24. ;; file provided:
  25. ;;   1. All copies contain this copyright notice.
  26. ;;   2. All modified copies shall carry a prominant notice stating who
  27. ;;      made the last modification and the date of such modification.
  28. ;;   3. No charge is made for this software or works derived from it.
  29. ;;      This clause shall not be construed as constraining other software
  30. ;;      distributed on the same medium as this software, nor is a
  31. ;;      distribution fee considered a charge.
  32. ;;
  33. ;; Version 1.01, dated 25Jan91
  34. ;;
  35. ;; 25Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov
  36. ;;    Got indentation of matrix expression to work, I think.  Also,
  37. ;;    added tabs to comment start regular-expression.
  38. ;;
  39. ;; 14Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov
  40. ;;    Added functions (ml-unbal-matexp ml-matexp-indent) for matrix
  41. ;;    expressions.
  42. ;;
  43. ;; 07Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov
  44. ;;      Many changes.  Seems to work reasonably well.  Still would like
  45. ;;      to add some support for filling in comments and handle continued
  46. ;;      matrix expressions.  Released as Version 1.0.
  47. ;;
  48. ;; 04Jan91 by Matt Wette, mwette@csi.jpl.nasa.gov
  49. ;;      Created.  Used eiffel.el as a guide.
  50.  
  51. ;; Modified by Klaus Gebhardt, Apr 1996 - March 1997
  52.  
  53. (require 'server)
  54. (require 'octave)
  55.  
  56. (if window-system
  57.     (progn
  58.       (require 'hilit19)
  59.       (hilit-set-mode-patterns
  60.        '(octave-mode)
  61.        (append
  62.     '(("#.*$" nil comment))
  63.     '(("^%.*$" nil comment))
  64.     '((hilit-string-find ?' string))
  65.     '(("^[_A-Za-z0-9]+[ \t]*\+?=" nil define))
  66.     '(("[^_]\\<\\(for\\|function\\|if\\|try\\|unwind_protect\\|while\\|catch\\|else\\|elseif\\|unwind_protect_cleanup\\|end\\|endfor\\|endfunction\\|endif\\|end_try_catch\\|end_unwind_protect\\|endwhile\\|all_va_args\\|break\\|continue\\|global\\|gplot\\|gsplot\\|replot\\|return\\|casesen\\|cd\\|chdir\\|clear\\|diary\\|dir\\|document\\|echo\\|edit_history\\|format\\|help\\|history\\|hold\\|load\\|ls\\|more\\|run_history\\|save\\|gset\\|gshow\\|switch\\|case\\|otherwise\\|endswitch\\|type\\|which\\|who\\|whos\\)\\>[^_]" 1 keyword)
  67.       )))))
  68.  
  69. ;; Constants used in all Octave-mode buffers.
  70.  
  71. (defconst octave-indent-level 2
  72.   "*The indentation in Octave-mode.")
  73.  
  74. (defconst octave-comment-column 40
  75.   "*The goal comment column in Octave-mode buffers.")
  76.  
  77.  
  78. ;; Syntax Table
  79. (defvar octave-mode-syntax-table nil
  80.   "Syntax table used in Octave-mode buffers.")
  81.  
  82. (if octave-mode-syntax-table
  83.     ()
  84.   (setq octave-mode-syntax-table (make-syntax-table))
  85.   (modify-syntax-entry ?\\ "." octave-mode-syntax-table)
  86.   (modify-syntax-entry ?/ "." octave-mode-syntax-table)
  87.   (modify-syntax-entry ?* "." octave-mode-syntax-table)
  88.   (modify-syntax-entry ?+ "." octave-mode-syntax-table)
  89.   (modify-syntax-entry ?- "." octave-mode-syntax-table)
  90.   (modify-syntax-entry ?= "." octave-mode-syntax-table)
  91.   (modify-syntax-entry ?< "." octave-mode-syntax-table)
  92.   (modify-syntax-entry ?> "." octave-mode-syntax-table)
  93.   (modify-syntax-entry ?& "." octave-mode-syntax-table)
  94.   (modify-syntax-entry ?| "." octave-mode-syntax-table)
  95.   (modify-syntax-entry ?\' "\"" octave-mode-syntax-table)
  96.   (modify-syntax-entry ?# "<" octave-mode-syntax-table)
  97.   (modify-syntax-entry ?% "<" octave-mode-syntax-table)
  98.   (modify-syntax-entry ?\n ">" octave-mode-syntax-table)
  99.   (set-syntax-table octave-mode-syntax-table))
  100.  
  101.  
  102. ;; Abbrev Table
  103. (defvar octave-mode-abbrev-table nil
  104.   "Abbrev table used in Octave-mode buffers.")
  105.  
  106. (define-abbrev-table 'octave-mode-abbrev-table ())
  107.  
  108.  
  109. ;; Mode Map
  110. (defvar octave-mode-map ()
  111.   "Keymap used in octave-mode.")
  112.  
  113. (if octave-mode-map
  114.     ()
  115.   (setq octave-mode-map (make-sparse-keymap))
  116.   (define-key octave-mode-map "\r" 'octave-return)
  117.   (define-key octave-mode-map "\t" 'octave-indent-line)
  118.   (define-key octave-mode-map "\M-;" 'octave-comment)
  119.   (define-key octave-mode-map "\C-ct" 'octave-line-type)
  120.   (define-key octave-mode-map "\C-ci" 'octave-indent-type)
  121.   (define-key octave-mode-map "\M-\r" 'newline)
  122.   (define-key octave-mode-map "\C-x#" 'octave-mode-server-edit))
  123.  
  124.  
  125. ;; Octave Mode
  126. (defun octave-mode ()
  127.   "Major mode for editing Octave source files.  Version 1.0, 23 Feb 1993.
  128. Will run octave-mode-hook if it is non-nil.  Auto-fill-mode seems to work.
  129. Filling does not work (yet).
  130. Special Key Bindings:
  131. \\{octave-mode-map}
  132. Variables:
  133.   octave-indent-level                   Level to indent blocks.
  134.   octave-comment-column                 Goal column for on-line comments.
  135.   fill-column                           Column used in auto-fill (default=70).
  136. Commands:
  137.   octave-mode                           Enter Octave major mode.
  138.   octave-return                         Handle return with indenting.
  139.   octave-indent-line                    Indent line for structure.
  140.   octave-comment                        Add comment to current line.
  141.   octave-comment-indent                 Compute indent for comment.
  142.   octave-line-type                      Tell current line type (for debugging).
  143.   octave-indent-type                    Tell last indent type (for debugging).
  144. To add automatic support put something like the following in your .emacs file:
  145.   \(autoload 'octave-mode \"octave-mode\" \"Enter Octave-mode.\" t\)
  146.   \(setq auto-mode-alist \(cons '\(\"\\\\.m$\" . octave-mode\) \
  147. auto-mode-alist\)\)
  148.   \(setq octave-mode-hook '\(lambda \(\) \(setq fill-column 74\)\)\)"
  149.   (interactive)
  150.   (kill-all-local-variables)
  151.   (use-local-map octave-mode-map)
  152.   (setq major-mode 'octave-mode)
  153.   (setq mode-name "Octave")
  154.   (setq local-abbrev-table octave-mode-abbrev-table)
  155.   (set-syntax-table octave-mode-syntax-table)
  156.   (make-local-variable 'paragraph-start)
  157.   (setq paragraph-start (concat "^$\\|" page-delimiter))
  158.   (make-local-variable 'paragraph-separate)
  159.   (setq paragraph-separate paragraph-start)
  160.   (make-local-variable 'paragraph-ignore-fill-prefix)
  161.   (setq paragraph-ignore-fill-prefix t)
  162.   (make-local-variable 'indent-line-function)
  163.   (setq indent-line-function 'octave-indent-line)
  164.   (make-local-variable 'comment-start-skip)
  165.   (setq comment-start-skip "[%#][ \t]*")
  166.   (make-local-variable 'comment-column)
  167.   (setq comment-column 'octave-comment-column)
  168.   (make-local-variable 'comment-indent-function)
  169.   (setq comment-indent-function 'octave-comment-indent)
  170.   (make-local-variable 'fill-column)
  171.   (setq fill-column default-fill-column)
  172.   (run-hooks 'octave-mode-hook))
  173.  
  174. (defun octave-return ()
  175.   "Handle carriage return in Octave-mode."
  176.   (interactive)
  177.   (if (oct-block-end-line)
  178.       (octave-indent-line))
  179.   (newline)
  180.   (octave-indent-line))
  181.  
  182. (defun octave-comment ()
  183.   "Add a comment to the following line, or format if one already exists."
  184.   (interactive)
  185.   (cond
  186.    ((oct-empty-line)
  187.     (octave-indent-line)
  188.     (insert "# "))
  189.    ((oct-comment-line))
  190.    (t
  191.     (end-of-line)
  192.     (re-search-backward "[^ \t^]" 0 t)
  193.     (forward-char)
  194.     (delete-horizontal-space)
  195.     (if (< (current-column) octave-comment-column)
  196.         (indent-to octave-comment-column)
  197.       (insert " "))
  198.     (insert "# "))))
  199.  
  200. (defun octave-comment-indent ()
  201.   "Indent a comment line in Octave-mode."
  202.   (oct-calc-indent))
  203.  
  204. (defun octave-indent-line ()
  205.   "Indent a line in Octave-mode."
  206.   (interactive)
  207.   (save-excursion
  208.     (beginning-of-line)
  209.     (delete-horizontal-space)
  210.     (indent-to (oct-calc-indent)))
  211.   (skip-chars-forward " \t"))
  212.  
  213. (defun octave-line-type ()
  214.   "Display type of current line.  Used in debugging."
  215.   (interactive)
  216.   (cond
  217.    ((oct-empty-line)
  218.     (message "octave-line-type: empty-line"))
  219.    ((oct-comment-line)
  220.     (message "octave-line-type: comment-line"))
  221.    ((oct-continuation-line)
  222.     (message "octave-line-type: continuation-line"))
  223.    ((oct-block-beg-end-line)
  224.     (message "octave-line-type: block-beg-end-line"))
  225.    ((oct-block-beg-line)
  226.     (message "octave-line-type: block-beg-line"))
  227.    ((oct-block-end-line)
  228.     (message "octave-line-type: block-end-line"))
  229.    (t
  230.     (message "octave-line-type: other"))))
  231.  
  232. (defun octave-indent-type ()
  233.   "Display type of current or previous nonempty line.  Used in debugging."
  234.   (interactive)
  235.   (message (concat "octave-ident-type: " oct-last-indent-type)))
  236.  
  237. (defun octave-fill-region (from to &optional justify-flag)
  238.   "Fill the region of comments.
  239. Prefix arg (non-nil third arg, if called from program)
  240. means justify as well."
  241.   (interactive "r\nP")
  242.   (message "octave-fill-region not implemented yet."))
  243.  
  244. (defvar oct-last-indent-type "unknown"
  245.   "String to tell line type.")
  246.  
  247. (defun oct-calc-indent ()
  248.   "Return the appropriate indentation for this line as an int."
  249.   (let ((indent 0))
  250.     (save-excursion
  251.       (forward-line -1)                 ; compute indent based on previous
  252.       (if (oct-empty-line)               ;   non-empty line
  253.           (re-search-backward "[^ \t\n]" 0 t))
  254.       (cond
  255.        ((oct-empty-line) 
  256.         (setq oct-last-indent-type "empty"))
  257.        ((oct-comment-line) 
  258.         (setq oct-last-indent-type "comment"))
  259.        ((oct-continuation-line)
  260.         (setq oct-last-indent-type "continuation")
  261.         (setq indent (* 2 octave-indent-level)))
  262.        ((oct-block-beg-end-line)
  263.         (setq oct-last-indent-type "block begin-end"))
  264.        ((oct-block-beg-line)
  265.         (setq oct-last-indent-type "block begin")
  266.         (setq indent octave-indent-level))
  267.        ((oct-unbal-matexp-line)
  268.         (setq oct-last-indent-type "unbalanced-matrix-expression")
  269.         (setq indent (oct-calc-matexp-indent)))
  270.        (t
  271.         (setq oct-last-indent-type "other")))
  272.       (setq indent (+ indent (current-indentation)))
  273.       (if (= 0 (forward-line -1))
  274.           (if (oct-continuation-line)
  275.               (setq indent (- indent (* 2 octave-indent-level))))))
  276.     (if (oct-block-end-line) (setq indent (- indent octave-indent-level)))
  277.     (if (< indent 0) (setq indent 0))
  278.     indent))
  279.  
  280.  
  281. (defun oct-empty-line ()
  282.   "Returns t if current line is empty."
  283.   (save-excursion
  284.     (beginning-of-line)
  285.     (looking-at "^[ \t]*$")))
  286.  
  287. (defun oct-comment-line ()
  288.   "Returns t if current line is an Octave comment line."
  289.   (save-excursion
  290.     (beginning-of-line)
  291.     (skip-chars-forward " \t")
  292.     (looking-at "[%#]")))
  293.  
  294. (defun oct-continuation-line ()
  295.   "Returns t if current line ends in ... and optional comment."
  296.   (save-excursion
  297.     (beginning-of-line)
  298.     (re-search-forward "\\.\\.\\.+[ \t]*\\(%.*\\)?$" (oct-eoln-point) t)))
  299.  
  300. (defun oct-eoln-point ()
  301.   "Returns point for end-of-line in Octave-mode."
  302.   (save-excursion
  303.     (end-of-line)
  304.     (point)))
  305.  
  306. (defun oct-block-beg-line ()
  307.   "Returns t if line contains beginning of Octave block."
  308.   (save-excursion
  309.     (beginning-of-line)
  310.     (looking-at (concat "\\([^%#\n]*[ \t]\\)?" oct-block-beg-kw))))
  311.  
  312. (defconst oct-block-beg-kw "\\(for\\|while\\|if\\|else\\|elseif\\|function\\|switch\\|case\\|otherwise\\)"
  313.   "Regular expression for keywords which begin blocks in Octave-mode.")
  314.  
  315. (defun oct-block-end-line ()
  316.   "Returns t if line contains end of Octave block."
  317.   (save-excursion
  318.     (beginning-of-line)
  319.     (looking-at (concat "\\([^%#\n]*[ \t]\\)?" oct-block-end-kw))))
  320.  
  321. (defconst oct-block-end-kw "\\(end\\|endfor\\|endwhile\\|endif\\|endfunction\\|else\\|elseif\\|case\\|otherwise\\|endswitch\\)"
  322.   "Regular expression for keywords which end blocks.")
  323.  
  324. (defun oct-block-beg-end-line ()
  325.   "Returns t if line contains matching block begin-end in Octave-mode."
  326.   (save-excursion
  327.     (beginning-of-line)
  328.     (looking-at (concat
  329.                  "\\([^%#\n]*[ \t]\\)?" oct-block-beg-kw 
  330.                  "." "\\([^%#\n]*[ \t]\\)?" oct-block-end-kw))))
  331.  
  332. (defun oct-unbal-matexp-line ()
  333.   (if (= (oct-calc-matexp-indent) 0)
  334.     ()
  335.     t))
  336.  
  337. (defun oct-calc-matexp-indent ()
  338.   (let ((indent 0))
  339.     (save-excursion
  340.       (beginning-of-line)
  341.       (while (< (point) (oct-eoln-point))
  342.     (cond
  343.      ((looking-at "\\[")
  344.       (setq indent (+ indent octave-indent-level)))
  345.      ((looking-at "\\]")
  346.       (setq indent (- indent octave-indent-level))))
  347.     (forward-char)))
  348.     (* 2 indent)))
  349.  
  350. (defun oct-comment-on-line ()
  351.   "Returns t if current line contains a comment."
  352.   (save-excursion
  353.     (beginning-of-line)
  354.     (looking-at "[^\n]*[%#]")))
  355.  
  356. (defun oct-in-comment ()
  357.   "Returns t if point is in a comment."
  358.   (save-excursion
  359.     (and (/= (point) (point-max)) (forward-char))
  360.     (search-backward "[%#]" (save-excursion (beginning-of-line) (point)) t)))
  361.  
  362. (defun octave-mode-server-edit (&optional arg)
  363.   "Switch to next server editing buffer; say \"Done\" for current buffer.
  364. If a server buffer is current, it is marked \"done\" and optionally saved.
  365. When all of a client's buffers are marked as \"done\", the client is notified."
  366.   (interactive "P")
  367.   (if (or arg
  368.       (not server-process)
  369.       (memq (process-status server-process) '(signal exit)))
  370.       (server-start nil)
  371.     (apply 'octave-mode-server-switch-buffer (server-done))))
  372.  
  373. (defun octave-mode-server-switch-buffer (&optional next-buffer killed-one)
  374.   "Switch to another buffer, preferably one that has a client.
  375. Arg NEXT-BUFFER is a suggestion; if it is a live buffer, use it."
  376.   (cond ((and (windowp server-window)
  377.           (window-live-p server-window))
  378.      (select-window server-window))
  379.     ((framep server-window)
  380.      (if (not (frame-live-p server-window))
  381.          (setq server-window (make-frame)))
  382.      (select-window (frame-selected-window server-window))))
  383.   (if (window-minibuffer-p (selected-window))
  384.       (select-window (next-window nil 'nomini 0)))
  385.   (let ((last-window (previous-window nil 'nomini 0)))
  386.     (while (and (window-dedicated-p (selected-window))
  387.         (not (eq last-window (selected-window))))
  388.       (select-window (next-window nil 'nomini 0))))
  389.   (set-window-dedicated-p (selected-window) nil)
  390.   (if next-buffer
  391.       (if (and (bufferp next-buffer)
  392.            (buffer-name next-buffer))
  393.       (switch-to-buffer next-buffer)
  394.     (apply 'octave-mode-server-switch-buffer
  395.            (server-buffer-done next-buffer)))
  396.     (if server-clients
  397.     (octave-mode-server-switch-buffer
  398.      (nth 1 (car server-clients)) killed-one)
  399.       (if (not killed-one)
  400.       (progn
  401.         (if (and (get-buffer "*octave*") (get-buffer-process "*octave*"))
  402.         (let ((octave-mode-cb (current-buffer)))
  403.           (switch-to-buffer-other-window "*octave*")
  404.           (delete-window (get-buffer-window octave-mode-cb)))
  405.           (switch-to-buffer (other-buffer))))))))
  406.  
  407. (provide 'octave-mode)
  408.  
  409. ;; --- last line of octave-mode.el --- 
  410.