;; -*- Mode: Emacs-Lisp -*- ;; $Id: matx-mode.el,v 2.18 2007/06/12 11:18:13 yasuaki Exp $ ;; File: matx-mode.el ;; Description: Mode for editing MaTX code ;; Author(s): 1995-1999 KIYOTA Hiromitsu ;; 1999-2007 TANIGUCHI Yasuaki ;; ;; Done by fairly faithful modification of: ;; CC-Mode version 5.25 ;; URL: http://www.python.org/emacs/cc-mode/ ;; gnuplot-mode version 0.5j ;; URL: http://feff.phys.washington.edu/~ravel/gnuplot/ ;; auctex version 9.8l ;; URL: http://sunsite.auc.dk/auctex/ ;; yatex version 1.67 ;; URL: http://www.yatex.org/ ;; ;; Copyright (c) Hiromitsu Kiyota, Yasuaki Taniguchi ;; Under GPL2.0 or later ;; ;; Special Thanks To: Masanobu Koga ;; ;; Last Modified: $Date: 2007/06/12 11:18:13 $ ;; Version: $Revision: 2.18 $ ;; Working Host(s): wind ;; Tested Platform(s): Emacs 22.1.1 ;; If you have problems or questions, you can contact me at the ;; following address: MaTX@MaTX.ORG (MaTX ML) ;; ;; To submit bug reports hit "C-c C-b" in a matx-mode buffer. This runs ;; the command matx-submit-bug-report and automatically sets up the ;; mail buffer with all the necessary information. ;; Archives on the Net: ;; In plain text: ;; ;; ;; matx-mode requires cc-mode and cc-langs version 5.25 or later since ;; it's hacked from CC Mode version 5.25. ;; Load matx-mode-19.el because Emacs 19 doesn't have some useful functions. (if (< emacs-major-version 20) (require 'matx-mode-19)) (defconst matx-version (cadr (split-string "$Revision: 2.18 $")) "MaTX Mode version number") (defun matx-version () "Echo the current version of MaTX Mode in the minibuffer." (interactive) (message "Using MaTX Mode version %s." matx-version) (c-keep-region-active)) ;; The cc-mode v5.25 or later is required to use this version of MaTX Mode. (eval-and-compile (require 'cc-mode) (require 'cc-langs) (require 'comint) (require 'custom)) (eval-when-compile (require 'reporter)) ;; checking CC-Mode version (let* ((c-version-list (split-string c-version "\\.")) (c-major-version (string-to-int (car c-version-list))) (c-minor-version (string-to-int (cadr c-version-list)))) (if (or (< c-major-version 5) (and (= c-major-version 5) (< c-minor-version 31))) (error "Your CC Mode is too old. You need to update CC Mode v5.31 or later. See http://www.python.org/emacs/cc-mode."))) ;; ;; font-lock part for matx-mode ;; (defconst matx-type-names nil) (defconst matx-font-lock-keywords-1 nil "Subdues level highlighting for MaTX Modes.") (defconst matx-font-lock-keywords-2 nil "Medium level highlighting for MaTX Modes.") (defconst matx-font-lock-keywords-3 nil "Gaudy level highlighting for MaTX Modes.") ;; This part is ported from font-lock.el of XEmacs-21.1.6. (let ((matx-keywords (concat "Func\\|break\\|c\\(lear\\|ontinue\\)\\|do\\|" "e\\(lse\\|xit\\)\\|" "for\\|if\\|p\\(ause\\|rint\\)\\|re\\(ad\\|turn\\)\\|" "switch\\|while")) (matx-type-types (concat "Complex\\|In\\(dex\\|teger\\)\\|List\\|Real\\|" "String\\|extern\\|static\\|void\\|" "\\(Co\\|Po\\|Ra\\)?\\(Array\\|Matrix\\)\\|" "\\(Co\\)?\\(Polynomial\\|Rational\\)")) (matxtoken "\\(\\sw\\|\\s_\\|[:~*&]\\)+")) (setq matx-type-names matx-type-types) (setq matx-font-lock-keywords-1 (list (list (concat "^\\(" "\\(" matxtoken "[ \t]+\\)" ; type specs; there can be no "\\(" "\\(" matxtoken "[ \t]+\\)" ; more than 3 tokens, right? "\\(" matxtoken "[ \t]+\\)" "?\\)?\\)?" ;;"\\([*&]+[ \t]*\\)?" ; pointer "\\(" matxtoken "\\)[ \t]*(") ; name 9 'font-lock-function-name-face) ;; As no typedef, struct, etc. exist... ;; (list (concat "^\\(typedef[ \t]+struct\\|struct\\|static[ \t]+struct\\)" ;; "[ \t]+\\(" ctoken "\\)[ \t]*\\(\{\\|$\\)") ;; 2 'font-lock-function-name-face) ;; Fontify case clauses. This is fast because its anchored on the left. '("case[ \t]+\\(\\(\\sw\\|\\s_\\)+\\)[ \t]+:". 1) '("\\<\\(default\\):". 1) ;; Fontify filenames in #include <...> preprocessor directives as strings. '("^#[ \t]*include[ \t]+\\(<[^>\"\n]+>\\)" 1 font-lock-string-face) ;; ;; Fontify function macro names. '("^#[ \t]*define[ \t]+\\(\\(\\sw+\\)(\\)" 2 font-lock-function-name-face) ;; ;; Fontify symbol names in #if ... defined preprocessor directives. ;; FSF Emacs doesn't have font-lock-preprocessor-face, so ;; use font-lock-function-name-face. '("^#[ \t]*if\\>" ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil (1 (if (featurep 'xemacs) font-lock-preprocessor-face;; for XEmacs font-lock-function-name-face));; for FSF Emacs (2 font-lock-variable-name-face nil t))) ;; ;; Fontify symbol names in #elif ... defined preprocessor directives. '("^#[ \t]*elif\\>" ("\\<\\(defined\\)\\>[ \t]*(?\\(\\sw+\\)?" nil nil (1 (if (featurep 'xemacs) font-lock-preprocessor-face;; for XEmacs font-lock-function-name-face));; for FSF Emacs (2 font-lock-variable-name-face nil t))) ;; ;; Fontify otherwise as symbol names, and the preprocessor directive names. '("^\\(#[ \t]*[a-z]+\\)\\>[ \t]*\\(\\sw+\\)?" (1 (if (featurep 'xemacs) font-lock-preprocessor-face;; for XEmacs font-lock-function-name-face));; for FSF Emacs (2 font-lock-variable-name-face nil t)))) (setq matx-font-lock-keywords-2 (append matx-font-lock-keywords-1 (list ;; ;; Simple regexps for speed. ;; ;; Fontify all type specifiers. (cons (concat "\\<\\(" matx-type-types "\\)\\>") 'font-lock-type-face) ;; Fontify Re(), Im() '("\\<\\(Re\\|Im\\)\\>[ \t\n]*(" 1 'font-lock-type-face) ;; ;; Fontify all builtin keywords (except case, default and goto; see below). (cons (concat "\\<\\(" matx-keywords "\\)\\>") 'font-lock-keyword-face) ;; ;; Fontify case/goto keywords and targets, and case default/goto tags. ;; MaTX doesn't have goto keyword. ;;'("\\<\\(case\\|goto\\)\\>[ \t]*\\([^ \t\n:;]+\\)?" '("\\<\\(case\\)\\>[ \t]*\\([^ \t\n:;]+\\)?" (1 font-lock-keyword-face) (2 font-lock-reference-face nil t)) '("^[ \t]*\\(\\sw+\\)[ \t]*:" 1 font-lock-reference-face) ))) (setq matx-font-lock-keywords-3 (append matx-font-lock-keywords-2 ;; ;; More complicated regexps for more complete highlighting for types. ;; We still have to fontify type specifiers individually, as C is so hairy. (list ;; ;; Fontify all storage classes and type specifiers, plus their items. (list (concat "\\<\\(" matx-type-types "\\)\\>" "\\([ \t*&]+\\sw+\\>\\)*") ;; Fontify each declaration item. '(font-lock-match-c++-style-declaration-item-and-skip-to-next ;; Start with point after all type specifiers. (goto-char (or (match-beginning 8) (match-end 1))) ;; Finish with point after first type specifier. (goto-char (match-end 1)) ;; Fontify as a variable or function name. (1 (if (match-beginning 4) font-lock-function-name-face font-lock-variable-name-face)))) ;; ;; Fontify structures, or typedef names, plus their items. '("\\(}\\)[ \t*]*\\sw" (font-lock-match-c++-style-declaration-item-and-skip-to-next (goto-char (match-end 1)) nil (1 (if (match-beginning 4) font-lock-function-name-face font-lock-variable-name-face)))) ;; ;; Fontify anything at beginning of line as a declaration or definition. '("^\\(\\sw+\\)\\>\\([ \t*]+\\sw+\\>\\)*" (1 font-lock-type-face) (font-lock-match-c++-style-declaration-item-and-skip-to-next (goto-char (or (match-beginning 2) (match-end 1))) nil (1 (if (match-beginning 4) font-lock-function-name-face font-lock-variable-name-face)))) (list (concat "\\<\\(bell\\|error\\|menu\\|system\\|warning\\|" "\\(f\\|s\\)?printf\\|f?scanf" "\\)\\>[ \t\n]*(") '(1 font-lock-keyword-face)))))) (defvar matx-font-lock-keywords matx-font-lock-keywords-1 "Default expressoins to highlight in MaTX Mode.") ;; compiler buffer font-lock keywords (defconst matx-compiler-font-lock-keywords-1 nil "Subdues level highlighting for MaTX compiler buffer.") (defconst matx-compiler-font-lock-keywords-2 nil "Medium level highlighting for MaTX compiler buffer.") (defconst matx-compiler-font-lock-keywords-3 nil "Gaudy level highlighting for MaTX compiler buffer.") (setq matx-compiler-font-lock-keywords-1 (list '("\\<\\(CAUTHT SIGNAL\\|EXITED ABNORMALLY\\)\\>" 1 'font-lock-keyword-face) ;; Fontify command string. '("^\\([ \t]*\\<\\(rt\\)?matc\\>[ \t]+.*\\)$" 1 'font-lock-string-face) )) (setq matx-compiler-font-lock-keywords-2 (append matx-compiler-font-lock-keywords-1 (list ;; Fontify MaTX compiler error messages. ;; error message format ;; "filename", line xx: in funcname(), error messages ;; "filename", line xx: error messages ;; "filename", in funcname(), error messages (list (concat "^\\(^\"[-_.A-Za-z0-9/\\]+\"\\)," ;; filename "\\( line [0-9]+: in \\(\\sw\\|\\s_\\)+()\\|" " line [0-9]+:\\|" " in \\(\\sw\\|\\s_\\)+()\\)" ",?" ;; place "\\(.+\\)$") ;; error message '(1 font-lock-string-face) '(2 (if (featurep 'xemacs) 'bold 'font-lock-variable-name-face)) '(5 font-lock-function-name-face)) '("\\(^Can't open mmifile\\):\\(.+\\)$" (1 'font-lock-function-name-face) (2 'font-lock-string-face)) ))) (defvar matx-compiler-font-lock-keywords matx-compiler-font-lock-keywords-1 "Default expressoins to highlight in MaTX compiler buffer.") ;; ;; ACTUAL INDENTATION CODE ;; ;; aliases and macros (defalias 'matx-end-of-defun 'c-end-of-defun) (defalias 'matx-indent-exp 'c-indent-exp) (defalias 'matx-indent-line-or-region 'c-indent-line-or-region) (defalias 'matx-indent-command 'c-indent-command) ;; from cc-mode-5.25 cc-langs.el ;; keywords introducing class definition. matx null string. (defconst matx-class-key "Func") (defconst matx-extra-toplevel-key "\\(extern\\)") ;; regexp describing access protection clauses. This variable is set nil ;; because matx doesn't have scope label (private, public.. etc) (defconst matx-access-key nil) ;; keywords introducing conditional blocks ;; this variable is removed in CC Mode 5.30 (defconst matx-conditional-key nil) ;; comment starter definitions for various languages. matx same as C++ (defconst matx-comment-start-regexp "/[/*]") ;; Regexp describing a switch's case or default label for all languages ;; from cc-langs.el (defvar matx-mode-syntax-table nil "Syntax table used in matx-mode buffers.") (if matx-mode-syntax-table () (setq matx-mode-syntax-table (make-syntax-table)) (c-populate-syntax-table matx-mode-syntax-table) (modify-syntax-entry ?' "'" matx-mode-syntax-table)) (defvar matx-mode-abbrev-table nil "Abbrev table used in matx-mode buffers.") (define-abbrev-table 'matx-mode-abbrev-table ()) (defvar matx-mode-map () "Keymap used in matx-mode.") (if matx-mode-map nil (setq matx-mode-map (c-make-inherited-keymap)) (define-key matx-mode-map "\M-\C-a" 'matx-beginning-of-defun) (define-key matx-mode-map "\M-\C-e" 'matx-end-of-defun) (define-key matx-mode-map "\C-c\C-q" 'matx-indent-defun) (define-key matx-mode-map "\C-c\C-b" 'matx-submit-bug-report) (define-key matx-mode-map "\C-cil" 'matx-send-line-to-matx) (define-key matx-mode-map "\C-cir" 'matx-send-region-to-matx) (define-key matx-mode-map "\C-cib" 'matx-send-buffer-file-to-matx) (define-key matx-mode-map "\C-cif" 'matx-send-file-to-matx) (define-key matx-mode-map "\C-cie" 'matx-send-exit-to-matx) (define-key matx-mode-map "\C-cco" 'matx-make-object-file) (define-key matx-mode-map "\C-ccc" 'matx-make-c-file) (define-key matx-mode-map "\C-ccs" 'matx-compiler-set-options) (define-key matx-mode-map "\C-ccm" 'compile)) (defvar matx-mode-menu nil "Menu for `matx-mode'.") (setq matx-mode-menu (append (c-mode-menu "MaTX") '("--:doubleLine" ("Interpreter" ("Interpreter name " ["matx" (setq matx-interpreter-program "matx") :style radio :selected (equal matx-interpreter-program "matx") ] ["rtmatx" (setq matx-interpreter-program "rtmatx") :style radio :selected (equal matx-interpreter-program "rtmatx") :active (memq system-type '(ms-dos windows-nt cygwin32)) ]) ["Send line " matx-send-line-to-matx t] ["Send region " matx-send-line-to-matx (c-region-is-active-p)] ["Send buffer file " matx-send-buffer-file-to-matx t] ["Send file " matx-send-file-to-matx t] ["Quit Interpreter " matx-send-exit-to-matx matx-interpreter-process]) ("Compiler" ("Compiler name " ["matc" (setq matx-compiler-program "matc") :style radio :selected (equal matx-compiler-program "matc") ] ["rtmatc" (setq matx-compiler-program "rtmatc") :style radio :selected (equal matx-compiler-program "rtmatc") :active (memq system-type '(ms-dos windows-nt cygwin32)) ]) ("Object file extension " [".o" (setq matx-compiler-object-extension "o") :style radio :selected (equal matx-compiler-object-extension "o")] [".obj (Visual C)" (setq matx-compiler-object-extension "obj") :style radio :selected (equal matx-compiler-object-extension "obj") :active (memq system-type '(ms-dos windows-nt cygwin32))]) ["Call make process " compile t] ["Make object file " matx-make-object-file t] ["Make C file " matx-make-c-file t] ["Set compiler options " matx-compiler-set-options t] ) "---" ["MaTX Mode bug report " matx-submit-bug-report t] ))) (easy-menu-define matx-menu matx-mode-map "MaTX Mode Commands" matx-mode-menu) ;; from cc-align.el ;; Indent close bracket line correctly. (defun matx-lineup-arglist (langelem) ;; lineup the current arglist line with the arglist appearing just ;; after the containing paren which starts the arglist. (save-excursion (let* ((containing-sexp (save-excursion ;; arglist-cont-nonempty gives relpos == ;; to boi of containing-sexp paren. This ;; is good when offset is +, but bad ;; when it is c-lineup-arglist, so we ;; have to special case a kludge here. (if (memq (car langelem) '(arglist-intro arglist-cont-nonempty)) (progn (beginning-of-line) (backward-up-list 1) (skip-chars-forward " \t" (c-point 'eol))) (goto-char (cdr langelem))) (point))) (langelem-col (c-langelem-col langelem t))) (if (save-excursion (beginning-of-line) (looking-at "[ \t]*[])]")) (progn (goto-char (match-end 0)) (c-forward-sexp -1) (forward-char 1) (c-forward-syntactic-ws) (- (current-column) langelem-col)) (goto-char containing-sexp) (or (eolp) (not (memq (char-after) '(?{ ?[ ?\( ))) (let ((eol (c-point 'eol)) (here (progn (forward-char 1) (skip-chars-forward " \t") (point)))) (c-forward-syntactic-ws) (if (< (point) eol) (goto-char here)))) (- (current-column) langelem-col) )))) ;; from cc-styles.el (defconst matx-knr-style '( ;; This offset is based on "KIYOTA-San" style. ;; Default style of matx-mode (c-basic-offset . 5) (c-comment-only-line-offset . 0) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . +) (substatement-open . 0) (label . 0) (statement-cont . +) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . matx-lineup-arglist) (arglist-cont-nonempty . matx-lineup-arglist) )) )) (defconst matx-gnu-style '((c-basic-offset . 2) (c-comment-only-line-offset . (0 . 0)) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . 5) (substatement-open . +) (label . 0) (statement-case-open . +) (statement-cont . +) (arglist-intro . c-lineup-arglist-intro-after-paren) (arglist-close . matx-lineup-arglist) (arglist-cont-nonempty . matx-lineup-arglist) (inline-open . 0) )) (c-special-indent-hook . c-gnu-impose-minimum) (c-block-comment-prefix . ""))) (defconst matx-bsd-style '((c-basic-offset . 4) (c-comment-only-line-offset . 0) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . +) (substatement-open . 0) (label . 0) (statement-cont . +) (inline-open . 0) (inexpr-class . 0) (arglist-close . matx-lineup-arglist) (arglist-cont-nonempty . matx-lineup-arglist) )))) (defconst matx-linux-style '((c-basic-offset . 8) (c-comment-only-line-offset . 0) (c-hanging-braces-alist . ((brace-list-open) (brace-entry-open) (substatement-open after) (block-close . c-snug-do-while))) (c-cleanup-list . (brace-else-brace)) (c-offsets-alist . ((statement-block-intro . +) (knr-argdecl-intro . 0) (substatement-open . 0) (label . 0) (statement-cont . +) (arglist-close . matx-lineup-arglist) (arglist-cont-nonempty . matx-lineup-arglist) )))) (c-add-style "matx-k&r" matx-knr-style) (c-add-style "matx-gnu" matx-gnu-style) (c-add-style "matx-bsd" matx-bsd-style) (c-add-style "matx-linux" matx-linux-style) (put 'matx-mode 'c-mode-prefix "matx-") (defun matx-mode () "Major mode for editing MaTX code. $Rivision$ This version of MaTX Mode depends on CC Mode version 5.25 or later. If you use older version of CC Mode, update it before installing MaTX Mode. Features: 1. Indent MaTX code by using CC Mode indent engine. 2. Execute MaTX interpreter on Emacs buffer (`comint' is used.) 3. Handle MaTX compiler on Emacs mini-buffer Key bindings: \\{matx-mode-map} Hook: `c-mode-common-hook' and `matx-mode-hook' are run when matx-mode is called. Custamizing indentation: MaTX Mode doesn't have its own indent engine. If you want to customize indentation, see CC Mode manuals. (Note `arglist-close' and `arglist-cont-noempty' have to be associated `matx-lineup-arglist' in order to indent close bracket properly.) Bug report, suggestions: Any comments about MaTX Mode are welcome. Type \\[matx-submit-bug-report] in matx-mode buffer. " (interactive) (kill-all-local-variables) (c-initialize-cc-mode t) (set-syntax-table matx-mode-syntax-table) (setq major-mode 'matx-mode mode-name "MaTX" local-abbrev-table matx-mode-abbrev-table) (use-local-map matx-mode-map) ;; easy-menu for XEmacs ;;(easy-menu-remove "MaTX") ; (c-init-language-vars-for 'matx-mode) (c-make-emacs-variables-local) (c-init-language-vars matx-mode) (c-common-init 'matx-mode) (easy-menu-add matx-mode-menu matx-mode-map) (setq comment-start "// " comment-end "" c-conditional-key matx-conditional-key c-comment-start-regexp matx-comment-start-regexp c-class-key matx-class-key c-extra-toplevel-key matx-extra-toplevel-key c-access-key matx-access-key c-recognize-knr-p t) (make-local-variable 'c-file-style) (setq c-file-style "matx-gnu") (run-hooks 'c-mode-common-hook) (run-hooks 'matx-mode-hook) (c-update-modeline)) ;; ;; Submit bug report parts. It requires "reporters". ;; (defconst matx-mode-help-address "MaTX@MaTX.ORG,yasuaki@MaTX.org" "Address accepting submission of bug reports.") (defun matx-submit-bug-report () "Submit via mail a bug report on MaTX Mode." (interactive) (require 'reporter) (require 'cc-vars) ;; load in reporter (let ((reporter-prompt-for-summary-p t) (reporter-dont-compact-list '(c-offsets-alist)) (style c-indentation-style) (hook c-special-indent-hook) (c-features c-emacs-features)) (and (if (y-or-n-p "Do you want to submit a report on MaTX Mode? ") t (message "") nil) (require 'reporter) (reporter-submit-bug-report matx-mode-help-address (concat "MaTX Mode " matx-version) (let ((vars (list ;; report only the vars that affect indentation 'c-basic-offset 'c-offsets-alist 'c-cleanup-list 'c-comment-only-line-offset 'c-backslash-column 'c-delete-function 'c-electric-pound-behavior 'c-hanging-braces-alist 'c-hanging-colons-alist 'c-hanging-comment-starter-p 'c-hanging-comment-ender-p 'c-indent-comments-syntactically-p 'c-tab-always-indent 'c-comment-continuation-stars 'c-label-minimum-indentation 'defun-prompt-regexp 'tab-width 'comment-column ;; A brain-damaged XEmacs only variable that, if ;; set to nil can cause all kinds of chaos. 'signal-error-on-buffer-boundary ))) (if (not (boundp 'defun-prompt-regexp)) (delq 'defun-prompt-regexp vars) vars)) (function (lambda () (insert "Buffer Style: " style "\n\n" (if (and hook (or (/= (length hook) 1) (not (eq (car hook) 'c-gnu-impose-minimum)) )) (concat "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n" "c-special-indent-hook is set to '" (format "%s" hook) ".\nPerhaps this is your problem?\n" "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n\n") "\n") (format "c-emacs-features: %s\n" c-features) ))) nil "Dear MaTX Mode maintainer," )))) ;;; Misc functions (defun matx-toggle-realtime-matx (&optional arg) " Set RtMaTX to matx-{interpreter,compiler}-program. This funtion works only on MS-DOS and Windows." (interactive) (if (not (memq system-type '(ms-dos windows-nt cygwin32))) (message "This platform is not supported by RtMaTX.") (if (or arg (not (and (equal matx-interpreter-program "rtmatx") (equal matx-compiler-program "rtmatc")))) (setq matx-interpreter-program "rtmatx" matx-compiler-program "rtmatc") (setq matx-interpreter-program "matx" matx-compiler-program "matc") ))) (defun matx-beginning-of-defun (&optional arg) "See comment of 'c-beginning-of-defun'." (interactive "p") (and (null arg) (setq arg 1)) (let ((pmin 1) (num 0)) (while (< num arg) (unless (re-search-backward (concat "\\ nil ;; XEmacs (split-string "") --> "" (if stmp (setq input stmp) (setq input "")))) (defun matx-comint-start-function () "Function run when comint/matx started. This sets font-lock and keyword completion in the comint/matx buffer. Further customization is possible via `matx-comint-setup-hook'." (if (featurep 'font-lock) (progn (make-variable-buffer-local 'font-lock-defaults) (setq font-lock-defaults '((matx-font-lock-keywords matx-font-lock-keywords-1 matx-font-lock-keywords-2) t t)) (if (featurep 'xemacs) (turn-on-font-lock)))) (run-hooks 'matx-comint-setup-hook)) (defun matx-make-matx-buffer () "Switch to the matx buffer or create one if none exists." (or (and matx-interpreter-process (get-process matx-interpreter-process) matx-interpreter-buffer (get-buffer matx-interpreter-buffer) (not (eq (process-status matx-interpreter-process) 'exit))) (progn (message "Starting MaTX Interpreter program...") (setq matx-interpreter-buffer (make-comint matx-interpreter-process-name matx-interpreter-program) matx-interpreter-process (get-process matx-interpreter-process-name)) (process-kill-without-query matx-interpreter-process t) (save-excursion (set-buffer matx-interpreter-buffer) (erase-buffer) ;; local-mode-map (use-local-map matx-comint-mode-map) ;; local-hook (make-local-hook 'kill-emacs-hook) (add-hook 'kill-emacs-hook 'matx-send-exit-to-matx) (make-local-hook 'kill-buffer-hook) (add-hook 'kill-buffer-hook 'matx-send-exit-to-matx nil t) (matx-comint-start-function) ;; local-variable (make-local-variable 'comint-process-echoes) (setq comint-process-echoes t) (make-local-variable 'comint-prompt-regexp) (setq comint-prompt-regexp matx-interpreter-prompt) (make-local-variable 'comint-input-filter-functions) (setq comint-input-filter-functions (append comint-input-filter-functions '(matx-comint-replace-ctrl-i-with-ws))) (make-local-variable 'comint-output-filter-functions) (setq comint-output-filter-functions (append comint-output-filter-functions '(comint-postoutput-scroll-to-bottom matx-protect-prompt-fn comint-strip-ctrl-m))) (message "Starting MaTX Interpreter program...Done"))))) (defun matx-split-string (string) "Break STRING at each carriage return, returning a list of lines." (let ((list ()) (line "") (index 0)) (while (< index (length string)) (if (char-equal (elt string index) ?\n) (setq list (append list (list line)) line "") (setq line (concat line (char-to-string (elt string index))))) (setq index (1+ index)) ) list)) (defun matx-send-string-to-matx (string text) "Sends STRING to the matx. If no matx process exists, a new one is created. TEXT indicates the type of text being sent to matx and is typically one of nil, 'line, 'region, 'buffer, or 'file." (matx-make-matx-buffer) ; make sure a matx buffer exists (setq matx-comint-recent-buffer (current-buffer)) ;; show frame if matx-display-process equals frame (if (equal matx-interpreter-display-process 'frame) (or (and matx-interpreter-process-frame (frame-live-p matx-interpreter-process-frame)) (let ((frame (selected-frame))) (setq matx-interpreter-process-frame (make-frame)) (select-frame matx-interpreter-process-frame) (switch-to-buffer matx-interpreter-buffer) (delete-other-windows) (select-frame frame)))) ;; exec MaTX interpreter (let ((buffer (current-buffer)) (gbuffer (get-buffer matx-interpreter-buffer)) (list (matx-split-string string))) (set-buffer gbuffer) (goto-char (point-max)) ;; bruce asks: what is this next line for? (set-marker (process-mark matx-interpreter-process) (point-marker)) (sleep-for (* 20 matx-interpreter-delay)) (while list (insert (car list)) (comint-send-input) (sleep-for matx-interpreter-delay) (setq list (cdr list)) (goto-char (point-max))) (set-buffer buffer) ;; show window if matx-display process equals window (cond ((equal matx-interpreter-display-process 'window) (select-window (display-buffer gbuffer)) (goto-char (point-max)) (or (pos-visible-in-window-p (point) (selected-window)) (recenter 5)) (other-window 1)) ((equal matx-interpreter-display-process 'frame) (select-frame matx-interpreter-process-frame) (display-buffer gbuffer) (goto-char (point-max)) (or (pos-visible-in-window-p (point) (selected-window)) (recenter 5)))) (setq matx-interpreter-recently-sent text) (run-hooks 'matx-interpreter-after-send-hook))) (defun matx-send-region-to-matx (&optional begin end text) "Sends a selected region to the matx. If BEGIN and END are not specified, point and mark are used. TEXT indicates the type of text being sent to matx. This will be 'region unless explicitly set by a function calling this one. Other typical values are of nil, 'line, 'buffer, or 'file. TEXT may be useful for function in `matx-after-send-hook'." (interactive "r") (let (string (txt (or text 'region))) (cond ((equal major-mode 'matx-mode) (setq string (buffer-substring-no-properties begin end)) (if (string= (substring string -1) "\n") () (setq string (concat string "\n"))) (matx-send-string-to-matx string txt)) (t (message (concat "You can only send regions from " "matx-mode buffers to matx.")))))) (defun matx-send-line-to-matx () "Sends the current line to the matx. This sets `matx-interpreter-recently-sent' to 'line." (interactive) (cond ((equal major-mode 'matx-mode) (let ((start (save-excursion (beginning-of-line) (point-marker))) (end (save-excursion (beginning-of-line 2) (point-marker)))) (if (not (string-match "\\`\\s-*\\'" (buffer-substring-no-properties start end))) (matx-send-region-to-matx start end 'line))) t) (t (message "You can only send lines in matx-mode buffers to matx.") nil))) (defun matx-send-buffer-to-matx () "Send the entire current buffer to matx." (interactive) (if (equal major-mode 'matx-mode) (matx-send-region-to-matx (point-min) (point-max) 'buffer) (message "You can only send matx-mode buffers to matx."))) (defun matx-send-buffer-file-to-matx () "Send the buffer file to matx." (interactive) (if (equal major-mode 'matx-mode) (progn (and (buffer-modified-p (current-buffer)) (or (not matx-save-query) (y-or-n-p (concat "Save file " (buffer-file-name (current-buffer)) "? "))) (save-buffer)) (matx-send-file-to-matx (buffer-file-name (current-buffer)))))) (defun matx-send-file-to-matx (filename) "Send a file to matx. This function use matx built-in function \"load\"." (interactive "fFilename to send to matx: ") (let ((expand (expand-file-name filename))) (matx-send-string-to-matx (concat "\nload \"" expand "\"\n") 'region))) ;; ;; Send SIGKILL to matx. never use this. ;; ;;(defun matx-kill-matx-program () ;; "Send SIGKILL to matx. When you want to quit matx, ;;use `matx-send-exit-to-matx'." ;; (if (eq (process-status matx-interpreter-process) 'run) ;; (kill-process matx-interpreter-process)) ;; (setq matx-interpreter-process nil ;; matx-interpreter-buffer nil)) (defun matx-send-exit-to-matx () "Send exit to matx to quit it." (interactive) (if (and matx-interpreter-process (eq (process-status matx-interpreter-process) 'run)) ;; Send q before exit for fear in mated. (progn (matx-send-string-to-matx "\nq\nexit\n" 'region) (while (eq (process-status matx-interpreter-process) 'run) (sleep-for 0.5)) ;; wait for quitting matx )) (setq matx-interpreter-process nil matx-interpreter-buffer nil)) ;; ;; MaTX Comipiler section ;; (defcustom matx-compiler-program "matc" "MaTX compiler program." :group 'MaTX-Compiler :type 'string) (defcustom matx-compiler-process-name "MaTX-Compiler" "MaTX compiler message output buffer." :group 'MaTX-Compiler :type 'string) (defvar matx-compiler-process nil "Variable holding the process handle.") (defvar matx-compiler-buffer nil "The name of the buffer displaying the MaTX compiler output.") (defcustom matx-compiler-object-extension "o" "Extension of object file." :group 'MaTX-Compiler :type 'string) (defvar matx-shell-command-option (or (and (boundp 'shell-command-option) shell-command-option) (and (boundp 'shell-command-switch) shell-command-switch) (if (memq system-type '(msdos windows-nt OS/2)) "/c" "-c" )) "Shell option for command execution.") (defvar matx-compiler-process-frame nil "The frame for dislpaying the MaTX compiler process.") (defcustom matx-compiler-display-process 'window "See `matx-display-process'. This controles that of matx-compiler-program." :group 'MaTX-Compiler :type '(radio (const :tag "Separate frame" frame) (const :tag "Separate window" window) (const :tag "Not displayed" nil))) (defcustom matx-compiler-options nil "Options for MaTX Compiler." :group 'MaTX-Compiler :type 'string) (defconst matx-compiler-remove-options '("-mm" "-c" "-help")) (defvar matx-default-extension "mm" "Default extension of MaTX source files.") (defvar matx-file-extensions '("mm") "MaTX file extensions.") (defvar matx-check-path '("./") "Directory path to search for dependencies.") (defcustom matx-save-query t "If non-nil, ask user for permisson to save files before starting compiler." :group 'MaTX-Compilier :type 'boolean) (defun matx-kill-matx-compiler-process (proc) "Kill process PROC after sending signal to PROC." (cond ((not (fboundp 'start-process)) (error "This system can't have concurrent process.")) ((or (null proc) (not (eq (process-status proc) 'run))) (message "MaTX compiler process is not running")) (t (eq (process-status proc) 'run) (progn (interrupt-process proc) (delete-process proc))))) (defun matx-make-matx-compiler-buffer () "Create MaTX compiler output buffer if none exists." (or (buffer-live-p matx-compiler-buffer) (progn (setq matx-compiler-buffer (get-buffer-create (concat "*" matx-compiler-process-name "*"))) (if (featurep 'font-lock) (save-excursion (set-buffer matx-compiler-buffer) (make-variable-buffer-local 'font-lock-defaults) (setq font-lock-defaults '((matx-compiler-font-lock-keywords matx-compiler-font-lock-keywords-1 matx-compiler-font-lock-keywords-2) t t)) (turn-on-font-lock)))))) (defun matx-exec-matx-compiler (command) "Execute MaTX compiler. COMMAND : shell command. BUFFER : a buffer which recieve compiler output." (matx-make-matx-compiler-buffer) ;; erace buffer before compile (set-buffer (concat "*" matx-compiler-process-name "*")) (erase-buffer) ;; show frame if matx-compiler-display-process equals frame (if (equal matx-compiler-display-process 'frame) (or (and matx-compiler-process-frame (frame-live-p matx-compiler-process-frame)) (let ((frame (selected-frame))) (setq matx-compiler-process-frame (make-frame)) (select-frame matx-compiler-process-frame) (switch-to-buffer matx-compiler-buffer) (delete-other-windows) (select-frame frame)))) ;; exec MaTX compiler (if (and matx-compiler-process (eq (process-status matx-compiler-process) 'run)) (matx-kill-matx-compiler-process matx-compiler-process)) ;;(set-buffer (get-buffer matx-compiler-buffer)) ;;(setq execdir default-directory) ;;(cd execdir) (insert "MaTX compiler started at " (substring (current-time-string) 0 -5) "\n") (insert command "\n\n") (message "Executing MaTX compiler...") (cond ((not (fboundp 'start-process)) ;; if MS-DOS (call-process shell-file-name nil matx-compiler-buffer nil matx-shell-command-option command) (setq mode-line-process (format ":%s" (process-status (process-buffer matx-compiler-process)))) (save-excursion (set-buffer matx-compiler-buffer) (goto-char (point-max)) (insert "\nMaTX compiler finished at " (substring (current-time-string) 0 -5) "\n")) (setq mode-line-process (concat ":" (symbol-name (process-status matx-compiler-process)) (if (zerop (process-exit-status matx-compiler-process)) " OK" (format " [exit-status %d]" (process-exit-status matx-compiler-process))))) (message "Executing MaTX compiler... Done")) (t ;; if UNIX or Windows NT system (Multi task system) (set-process-buffer (setq matx-compiler-process (start-process matx-compiler-process-name matx-compiler-buffer shell-file-name matx-shell-command-option command)) (get-buffer matx-compiler-buffer)) (set-process-sentinel matx-compiler-process 'matx-compiler-sentinel) (setq mode-line-process (format ":%s" (process-status (process-buffer matx-compiler-process)))))) ; (if (memq system-type '(msdos windows-nt OS/2)) ; (message "Executing MaTX compiler... Done.")) (cond ((equal matx-compiler-display-process 'window) (select-window (display-buffer (get-buffer matx-compiler-buffer))) (goto-char (point-max)) (or (pos-visible-in-window-p (point) (selected-window)) (recenter 5)) (other-window 1)) ((equal matx-compiler-display-process 'frame) (select-frame matx-compiler-process-frame) (display-buffer (get-buffer matx-compiler-buffer)) (goto-char (point-max)) (or (pos-visible-in-window-p (point) (selected-window)) (recenter 5)))) (run-hooks 'matx-compiler-hook)) (defun matx-compiler-sentinel (proc msg) "This function is run when `matx-compiler-program' process status changed." (let ((stat (process-status proc)) (estat (process-exit-status proc))) (cond ((null (buffer-name (process-buffer proc))) (set-process-buffer proc)) ((eq stat 'signal) (progn (message "Executing MaTX compiler... SIGNAL.") (setq matx-compiler-process nil) (save-excursion (set-buffer matx-compiler-buffer) (goto-char (point-max)) (insert "\nMaTX compiler CAUGHT" (format " SIGNAL with code %s " estat) "at " (substring (current-time-string) 0 -5))))) ((eq stat 'exit) (progn (message "Executing MaTX compiler... Done.") (save-excursion (set-buffer matx-compiler-buffer) (goto-char (point-max)) (if (zerop estat) (insert "\nMaTX compiler finished at " (substring (current-time-string) 0 -5)) (progn (insert "\nMaTX compiler EXITED " (format "ABNORMALLY with code %s at " estat) (substring (current-time-string) 0 -5)) (message "MaTX compiler EXITED ABNORMALLY with code %s." estat))))))) (set-buffer matx-compiler-buffer) (setq mode-line-process (concat ":" (symbol-name stat) (if (zerop estat) " OK" (format " [exit-status %d]" estat)))) (setq matx-compiler-process nil))) (defun matx-check-files (derived originals extensions) "Check that DERIVED is newer than any of the ORIGINALS. Try each original with each member of EXTENSIONS, in all directories in matx-check-path." (let ((found nil) (regexp (concat "\\`\\(" (mapconcat (function (lambda (dir) (regexp-quote (expand-file-name dir)))) matx-check-path "\\|") "\\).*\\(" (mapconcat 'regexp-quote originals "\\|") "\\)\\.\\(" (mapconcat 'regexp-quote extensions "\\|") "\\)\\'")) (buffers (buffer-list))) (while buffers (let* ((buffer (car buffers)) (name (buffer-file-name buffer))) (setq buffers (cdr buffers)) (if (and name (string-match regexp name)) (progn (and (buffer-modified-p buffer) (or (not matx-save-query) (y-or-n-p (concat "Save file " (buffer-file-name buffer) "? "))) (save-excursion (set-buffer buffer) (save-buffer))) (if (file-newer-than-file-p name derived) (setq found t)))))) found)) (defun matx-match-extension (file &optional extensions) "Return non-nil if FILE has an one of EXTENSIONS. If EXTENSIONS is not specified or nil, the value of matx-file-extensions is used instead." (if (null extensions) (setq extensions matx-file-extensions)) (let ((regexp (concat "\\.\\(" (mapconcat 'identity extensions "\\|") "\\)$"))) (string-match regexp file))) (defun matx-strip-extension (&optional string extensions nodir nostrip) "Return STRING without any trailing extension in EXTENSIONS. If NODIR is `t', also remove directory part of STRING. If NOSTRIP is set, do not remove extension after all. STRING defaults to the name of the current buffer. EXTENSIONS defaults to matx-file-extensions." (if (null string) (setq string (or (buffer-file-name) ""))) (if (null extensions) (setq extensions matx-file-extensions)) (let* ((strip (if (and (not nostrip) (matx-match-extension string extensions)) (substring string 0 (match-beginning 0)) string)) (dir (file-name-directory (expand-file-name strip)))) (if (or (eq nodir t) (string-equal dir (expand-file-name "./")) (string-equal dir (file-name-directory (buffer-file-name)))) (file-name-nondirectory strip) strip))) (defun matx-make-object-file (&optional fname opts dir) "Make object file from mm-source." (interactive) (if (null fname) (setq fname (matx-strip-extension))) (matx-make-target fname opts dir 'o)) (defun matx-make-c-file (&optional fname opts dir) "Make c file from mm-source." (interactive) (if (null fname) (setq fname (matx-strip-extension))) (matx-make-target fname opts dir 'c)) (defun matx-make-target (fname opts dir type) ;; check TYPE and set proper matx flags "Check target file and if the source is newer, start matx compiler with proper arguments. FNAME is base name of target file. TYPE is target type. ('c or 'o) OPTS and DIR is not used." (let ((cmpflag nil) (command nil) (extension nil)) (cond ((eq type 'o) (setq cmpflag " -c " extension (concat "." matx-compiler-object-extension))) ((eq type 'c) (setq cmpflag " -mm " extension ".c")) (t (error "Wrong TYPE argument"))) (if (not (stringp matx-compiler-options)) (matx-compiler-set-options)) (setq command (concat matx-compiler-program cmpflag matx-compiler-options fname "." matx-default-extension)) (cond ((matx-check-files (concat fname extension) (list fname) matx-file-extensions) (setq command (read-from-minibuffer "command: " command)) (matx-exec-matx-compiler command)) (t (message "The target is newer than the sources."))))) (defun matx-compiler-set-options (&optional arg) "Set matx-compiler-options." (interactive) (setq matx-compiler-options (read-from-minibuffer "Compiler options: " matx-compiler-options)) ;; remove `matx-compiler-remove-options' (let ((splitstrs (split-string matx-compiler-options)) (opts nil) (options nil)) (while (setq opts (car splitstrs)) (setq splitstrs (cdr splitstrs)) (if (not (member opts matx-compiler-remove-options)) (setq options (concat options opts " ")))) (setq matx-compiler-options options)) ; For FSF Emacs (difference of split-string) (if (null matx-compiler-options) (setq matx-compiler-options ""))) (defun matx-insert-exps (start end fexp sexp texp) (let ((curpos (make-marker))) (progn (goto-char (marker-position start)) (insert (concat "\n" fexp)) (setq curpos (point-marker)) (insert (concat sexp "\n")) (goto-char (marker-position end)) (insert (concat texp "\n")) (goto-char (marker-position curpos))))) (defun matx-insert-if () (interactive) (let ((start (make-marker)) (end (make-marker))) (set-marker start (point)) (set-marker end (1+ (point))) (progn (matx-insert-exps start end "if(" "){" "}")))) (provide 'matx-mode) ;; ;; MaTX Mode ends here. ;;