; cascade-mode.el
;
;Emacs major mode for editing Cascade input files


; $Id: cascade-mode.el,v 1.2 2001/09/05 17:52:46 dan Exp $
;
; Copyright (c) 2001 Dan McMahill
; All rights reserved.
;
; This code is derived from software written by Dan McMahill
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
; 1. Redistributions of source code must retain the above copyright
;    notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
;    notice, this list of conditions and the following disclaimer in the
;    documentation and/or other materials provided with the distribution.
; 3. All advertising materials mentioning features or use of this software
;    must display the following acknowledgement:
;        This product includes software developed by Dan McMahill
;  4. The name of the author may not be used to endorse or promote products
;     derived from this software without specific prior written permission.
; 
;  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
;  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
;  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
;  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
;  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
;  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
;  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
;  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
;  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
;  SUCH DAMAGE.
;


(defconst cascade-mode-version "0.9.1"
  "Current version of cascade mode.")

(defvar cascade-mode-syntax-table nil
  "Syntax table used in cascade-mode buffers.")

(defvar cascade-mode-abbrev-table nil
  "Abbrev table in use in cascade-mode buffers.")

(define-abbrev-table 'cascade-mode-abbrev-table ())

;    (princ (concat "\\<\\(\\$[a-zA-Z][a-zA-Z0-9_\\$]*\\|" 
;            (regexp-opt (list 
;                         "g" "nf" "iip3" "r"
;                         "cn0" "n0" "tn" "cn" "bw" ))
;            "\\)\\>" ))

(setq cascade-font-lock-keywords
  (list
   '("^[ \t]*[*#;@].*\$". font-lock-comment-face)
   '("^[ \t]*\\(source\\|defaults\\)" . font-lock-keyword-face)
   '("\\<\\(\\$[a-zA-Z][a-zA-Z0-9_\\$]*\\|g\\|gp\\|gv\\|rin\\|rout\\|rho\\|Rs\\|nf\\|iip3\\|r\\|cn0\\|n0\\|tn\\|c\\|cn\\|bw\\)\\>" . font-lock-variable-name-face)
   ))
;  "Expressions to hightlight in Cascade Mode.")


;; mode map
(defvar cascade-mode-map
  (let ((km (make-sparse-keymap)))
    (define-key km [return] 'cascade-return)
    km)
  "The keymap used in `cascade-mode'.")




(defun cascade-mode ()
  (interactive)
  (text-mode)
;;  (use-local-map cascade-mode-map)
  (setq mode-name "Cascade")
  (setq major-mode 'cascade-mode)
  (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter))
  (set (make-local-variable 'paragraph-separate) paragraph-start)
  (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
  (set (make-local-variable 'require-final-newline) t)
  (set (make-local-variable 'parse-sexp-ignore-comments) nil)
  (set (make-local-variable 'comment-start) "* ")
  (set (make-local-variable 'comment-end) "")
  (set (make-local-variable 'comment-column) 32)
  (make-local-variable 'font-lock-keywords)
  (setq font-lock-keywords cascade-font-lock-keywords)
  (if cascade-mode-syntax-table
      ()
    (setq cascade-mode-syntax-table (make-syntax-table))
    (modify-syntax-entry ?* "<" cascade-mode-syntax-table)
    (modify-syntax-entry ?$ "<" cascade-mode-syntax-table)
    (modify-syntax-entry ?\n ">" cascade-mode-syntax-table)
    (modify-syntax-entry ?\' "\"" cascade-mode-syntax-table)
    (set-syntax-table cascade-mode-syntax-table))
  (set (make-local-variable 'font-lock-defaults)
       '(cascade-font-lock-keywords
	 nil t cascade-mode-syntax-table beginning-of-line))
  (if window-system (cascade-frame-init))
  (run-hooks 'cascade-mode-hook)
  (if cascade-vers-on-startup (cascade-show-version))
)


(defun cascade-frame-init ()
  (interactive)
  ;;(modify-frame-parameters (selected-frame) '((menu-bar-lines . 2)))
  ;; make a menu keymap
  (easy-menu-define
   cascade-mode-menu
   cascade-mode-map
   "Cascade menu"
   '("Cascade"
     ["Save and go" cascade-not-impl t]
     "----"
     ["Version" cascade-show-version t]
     ))
  (easy-menu-add cascade-mode-menu cascade-mode-map))


;;; User-changeable variables =================================================

(defcustom cascade-vers-on-startup t
  "*If non-nil, show the version number on startup."
  :group 'cascade
  :type 'boolean)


;;; Utilities =================================================================

(defun cascade-show-version ()
  "Show the version number in the minibuffer."
  (interactive)
  (message "cascade-mode, version %s" cascade-mode-version))

(defun cascade-not-impl ()
  "Not implemented yet message."
  (interactive)
  (message "not implemented yet (sorry.)"))



(defvar cascade-shell-buffer-name "Cascade"
  "Name used to create `cascade-shell' mode buffers.
This name will have *'s surrounding it.")


(defun cascade-shell-save-and-go ()
  "Save this CAS file, and evaluate it in a Cascade shell."
  (interactive)
  (if (not (eq major-mode 'cascade-mode))
      (error "Save and go is only useful in a cascade buffer!"))
  (let ((fn-name (file-name-sans-extension
                  (file-name-nondirectory (buffer-file-name))))
        (msbn (concat "*" cascade-shell-buffer-name "*"))
        (param ""))
    (save-buffer)
    ;; Do we need parameters?
    (if (save-excursion
          (goto-char (point-min))
          (end-of-line)
          (forward-sexp -1)
          (looking-at "([a-zA-Z]"))
        (setq param (read-string "Parameters: "
                                 (car cascade-shell-save-and-go-history)
                                 'cascade-shell-save-and-go-history)))
    ;; No buffer?  Make it!
    (if (not (get-buffer msbn)) (cascade-shell))
    ;; Ok, now fun the function in the cascade shell
    (if (get-buffer-window msbn t)
        (select-window (get-buffer-window msbn t))
      (switch-to-buffer (concat "*" cascade-shell-buffer-name "*")))
    (comint-send-string (get-buffer-process (current-buffer))
                        (concat fn-name " " param "\n"))))


(provide 'cascade-mode)



