;; MuPAD editing support package ;; ;; Major mode for MuPAD editing. It provides functions for editing ;; MuPAD code and interacting with MuPAD. See the documentation ;; of mupad-mode. ;; ;; LCD Archive Entry: ;; mupad-mode|Olivier Ramare|ramare@zeus.univ-lille1.fr| ;; MuPAD editing support| ;; 25-Mar-99|1.26|~/modes/mupad.el.Z| ;; ;; Maintainer: Olivier Ramare ;; ;; This code was initialy stolen by me from "maple.el" which is the work ;; of Bruno Salvy (Bruno.Salvy@inria.fr). Since then a huge part of ;; "pari.el" of Annette Hoffman/David Carlisle/Karim Belabas/Olivier Ramare ;; has been incorporated as well as most of "mupad-mode.el" of Juergen Billing. ;; Modified 15/09/1995: First release of mupad.el ;; Till 25-March-1999, combined efforts/comments of ;; Henning von Bargen (h.vonbargen@cityweb.de) ;; Juergen Billing (bij@mupad.de) ;; Michel Quercia (quercia@cal.enst.fr) ;; Nicolas Thiery (nthiery@jonas.univ-lyon1.fr) ;; Winfried Trümper (winni@xpilot.org) ;; Olivier Ramare (ramare@zeus.univ-lille1.fr) ;; Paul Zimmermann (Paul.Zimmermann@loria.fr) ;; have brought this version to life. ;; This file is split in different sections: ;; Here are the titles: ;; Part I : Variables and Constants, except Keymaps. ;; Part II : Keymaps and syntax tables. ;; Part III : Finders/Parsers. ;; Part IV : Highlighting stuff. ;; Part V : Window manager. ;; Part VI : mupad-mode/mupad-shell-mode ;; and some other main functions. ;; Part VII : Functions for writing programs. ;; Part VIII: Completion mecanism. ;; Part IX : Help and Examples. ;; Part X : Vcam and its followers. ;; Part XI : The Debugger. ;; Part XII : ReWriting. ;; Part XIII: Menu-bar builders. (provide 'mupad) ;;---------------------------------------------------- ;; Part I : Variables and Constants, except Keymaps. ;;---------------------------------------------------- (defconst mupad-mode-version "1.26" "Version of `mupad.el'.") (defvar isXEmacs (string-match "XEmacs" emacs-version)) ;;---------------------------------------------------- ;; USER DEPENDENT VARIABLES AND CONSTANTS: ;; The following variable decides where "help" is to be found. (defvar mupad-directory "/opt/math/MuPAD-1.4.0/share/") ;; The following variable decides where "vcam" is to be found. (defvar mupad-vcam-directory "/opt/math/MuPAD-1.4.0/bin/") ;; Regarding vcam, it turns out that the one of MuPAD-1.4.1 is suicidal. ;; In case of trouble, set this variable to t: (defvar mupad-mend-vcamp nil "Adds a nohup before starting vcam.") ;; The following variable decides where words for completion should be found. (defvar mupad-cpl-directory "~/lisp/first-look/") (defvar mupad-temp-directory "/tmp/" "*Directory in which to create temporary files.") (defconst mupad-max-nb-wind-conf 20 "Maximal number of saved window configurations") (defvar mupad-should-not-start-vcam nil "Set it to t if yoy do not want emacs to try vcam everytime it reads the output \"Error: Dumb terminal: Plotdata saved in file \" ") (defvar mupad-electric-allowedp t "*Non-nil means emacs will automatically indent properly each line ended by a carriage return, insert closing braces, and so on.") (defvar mupad-auto-indent t "*Non-nil means emacs will try to indent properly each line ended by a carriage return.") (defvar mupad-tab-always-indent t "*Non-nil means TAB in MuPAD-mode should always reindent the current line, regardless of where in the line point is when the TAB command is used.") ;; This variable is not used: (defvar mupad-auto-newline t "*Non-nil means automatically newline after semicolons and the punctation mark after an end.") (defvar mupad-no-closed-brace nil "Turn off self-closed braces.") (defvar mupad-colors "/home/ramare/lisp/first-look/mupad-colors.el" "Where the choice of colors is stored") ;; It should not be a constant if the file is installed ;; on a network. Each user will want a separate file. (defvar mupad-can-hilit t "Set it to nil if you do not want hilighting, to t otherwise") ;; Also modified internally and becomes nil if no colors are available, ;; or hilit19 is absent. (defvar mupad-lock-shell-modep t "t means you cannot write above the last prompt. If you try to modify an earlier input, emacs will automatically copy it at the bottom of your file.") (defconst mupad-forcefully-lock-shell-modep nil "'mupad-lock-shell-modep can be modified from the menu-bar. This variable cannot, its meaning is the same.") (defvar mupad-shell-historyp t "t means the arrow up and down will be used for a history mecanism in 'mupad-shell-mode and not for moving.") (defvar mupad-save-sessionp nil "t means emacs will ask you whether the MuPAD session should be saved before quitting. It will be saved in the file MuPAD-last-session.") (defvar mupad-javadoc-stylep nil "t to select a javadoc-style of insertion.") (defvar mupad-user-mail-address "ramare@gat.univ-lille1.fr") ;;---------------------------------------------------------------------- ;; Other variables and Constants. (defalias 'MuPAD-mode 'mupad-mode) ;; So that if the first line of a mupad program contains ;; "-*- MuPAD -*-", it triggers automatically mupad-mode. (defsubst mupad-print-if-compiling (messg) (if (get-buffer "*Compile-Log*") (save-excursion (set-buffer "*Compile-Log*") (insert messg "\n")))) (defsubst mupad-extend-hilit-mode-enable-list nil (if (symbol-plist 'hilit-mode-enable-list) (cond ((eq (car hilit-mode-enable-list) 'not) ; Do nothing ! ) (t (setq hilit-mode-enable-list (append hilit-mode-enable-list '(mupad-mode mupad-shell-mode))))) (defvar hilit-mode-enable-list '(mupad-mode mupad-shell-mode)))) (defsubst mupad-setup nil "Common packages required while compiling and running." (require 'facemenu) ;; For a fancy logo. (require 'disp-table) ;; Almost always required. (require 'backquote) ;; For macros. (require 'gud) ;; For the debugger. (require 'regexp-opt) (defconst mupad-places-alist (list ''mupad-comment ''mupad-string ''mupad-keyword ''mupad-options ''mupad-domain ''mupad-function-name ''mupad-variable-name ;; <-- Not used ''mupad-type ''mupad-info ''mupad-prompt ''mupad-primitive-name ''mupad-input) ;; To add something to this list, like ''mupad-warning, ;; set also the proper default in 'mupad-hilit-translate, ;; and define the corresponding pattern in ;; 'mupad-tell-hilit-about-patterns if it is for mupad-shell-mode, or ;; in 'mupad-hilit-init if it is for mupad-mode. "List of symbolic-names of faces which are linked with patterns to be hilighted via 'mupad-hilit-init and 'mupad-tell-hilit-about-patterns") ;; 'hilit19 needs this value: (fset 'x-display-color-p (lambda (&optional DISPLAY) t)) (mupad-extend-hilit-mode-enable-list) (or (featurep 'hilit19) (load "hilit19" t)) (or (featurep 'easymenu) (load "easymenu" t)) (or (featurep 'hilit19) (progn ;; Curiously enough, this part is essentially only crap for ;; the compiler. If hilit19 is loaded when this is used then ;; the proper definitions will be used ! (mupad-print-if-compiling "No highlighting: hilit19.el not found.") (defvar hilit-face-translation-table nil) (defvar hilit-background-mode 'dark) (mapcar (lambda (amupadplace) (eval (list 'defvar (eval amupadplace) nil))) mupad-places-alist) (fset 'hilit-translate nil) (fset 'hilit-set-mode-patterns nil) (fset 'hilit-string-find nil) (fset 'hilit-rehighlight-region nil) (fset 'hilit-unhighlight-region nil) (fset 'hilit-rehighlight-buffer nil) (fset 'hilit-recenter nil) (setq mupad-can-hilit t))) (or (featurep 'easymenu) (progn ;; This part is no crap ! 'easymenu has to be present ;; at compilation time. (mupad-print-if-compiling "No menu-bar: easymenu.el not found.") (fset 'easy-menu-define nil)))) (mupad-setup) (eval-when-compile (setq byte-compile-warnings '(free-vars unresolved redefine obsolete)) (setq byte-optimize t) (mupad-setup)) (defvar mupad-mode-hook nil) (defvar mupad-script-mode-hook nil) (defvar mupad-shell-mode-hook nil) (defvar mupad-mdx-mode-hook nil) (defvar mupad-input-filter-hook nil "Hook run in 'mupad-input-filter") (defvar MuPAD-menu-map nil "Keymap used for the menu-bar item MuPAD in mupad-mode") (defvar MuPAD-shell-menu-map nil "Keymap used for the menu-bar item MuPAD in mupad-shell-mode") (defvar mupad-registers-list nil "List of registers [0-mupad-max-nb-wind-conf] where window-configurations are stored. See 'mupad-store-wind-conf and 'mupad-restore-wind-conf.") (defvar mupad-command "mupad" "The command to run mupad on a file.") (defvar mupad-args "-P e" "Additional arguments passed to mupad. For old versions of MuPAD, -q could be useful") (defvar mupad-prompt-regexp "^[^-> \n]*>+ +" "*Regexp defining the prompt in MuPAD sessions.") (defvar zap-file (concat mupad-temp-directory (make-temp-name "mupad-")) "Temporary file name used for text being sent as input to MuPAD.") (defvar mupad-el-temp-file (concat mupad-temp-directory (make-temp-name "mupad-")) "Temporary file name used for text being sent as input to emacs.") (defvar mupad-cpl-file (concat mupad-cpl-directory "mupad-cpl-file.el")) (defvar mupad-process nil) (defvar mupad-tutorial-requiredp t) (defvar mupad-should-wait-for-outputp t) (defvar mupad-input-start 1 "Beginning of the expression to be send to MuPAD. See mupad-copy-input.") (defvar mupad-input-end nil "End of the expression to be send to MuPAD. See mupad-copy-input.") (defvar mupad-complete-expression nil "t if expression to be send to MuPAD is complete. See mupad-copy-input.") (defvar mupad-should-start-vcam nil "An internal variable not yet used !") (defvar mupad-lib-loadedp nil "t if completion list has been set.") (defvar mupad-prefix-alist '("NUMERIC" "CF" "ERROR" "RGB" "Axiom" "AxiomConstructor" "O" "Pref" "Series" "Sum" "adt" "domains" "faclib" "gcdlib" "intlib" "matchlib" "listtools" "module" "ode" "piecewise" "rec" "rectform" "solvelib" "stdlib") "List of the domains names.") (defvar mupad-prefix-regexp nil) (defvar mupad-prefix-loaded-alist '() "List of the packages names that have been exported for completion.") (defvar mupad-word-alist '() "Words used for completion, all imbedded in a list.") ;; MuPAD-1.4.0 contains 828 definitions. (defvar mupad-primitive-regexp nil "Regexp matching all the primitive names to be highlighted.") (defvar mupad-primitive-regexp-simple nil "Regexp matching all the primitive names that do not come from a library.") (defvar mupad-primitive-regexp-prefix-alist '() "List of elements of the form (prefix aregexp), where prefix is a library name and aregexp the regexp matching all the primitive names coming from this library.") (defconst mupad-keywords '("and " "axiom" "category" "begin" "break" "case " "div " "do " "downto " "E" "elif" "else" "end_case" "end_for" "end_if" "end_proc" "end_repeat" "end_while" "FAIL" "FALSE" "for " "from " "I" "if " "in " "intersect " "local " "minus " "mod " "name" "next" "NIL" "not " "of " "option " "or " "otherwise" "proc" "quit" "repeat " "step" "then" "to" "TRUE" "union " "until" "UNKNOWN" "while ") "MuPAD keywords to hilight while editing") ;;; ;;; Regular expressions used to calculate indent, etc. ;;; (defconst mupad-proc-def-start "\\(\\`\\|[^\\w]\\)\\([a-zA-Z_]\\w*\\)[ \t\n]*:=[ \t\n]*proc[ \t\n]*(" "regexp that matches the beginning of a function-definition") (defconst mupad-symbol-re "\\<[a-zA-Z_][a-zA-Z_0-9]*\\(::[a-zA-Z_]\\w*\\)?\\>") (defconst mupad-beg-block-re "\\<\\(proc\\|case\\|repeat\\|while\\|if\\|for\\|domain\\|category\\|axiom\\)\\>") (defconst mupad-end-block-re "\\<\\(end\\(_\\(proc\\|if\\|for\\|case\\|while\\|domain\\|category\\|axiom\\)\\)?\\|until\\)\\>") (defconst mupad-sub-block-re "\\<\\(el\\(se\\|if\\)\\|begin\\)\\>") (defconst mupad-noindent-re "\\<\\(el\\(se\\|if\\)\\|begin\\|end\\(_\\(proc\\|if\\|for\\|case\\|while\\|domain\\|category\\|axiom\\)\\)?\\|until\\)\\>") (defconst mupad-casesub-re "\\<\\(of\\|otherwise\\)\\>") (defconst mupad-autoindent-lines-re "\\<\\(end\\(_\\(proc\\|if\\|for\\|case\\|while\\|domain\\|category\\|axiom\\)\\)?\\|begin\\|of\\|do\\|otherwise\\|el\\(se\\|if\\)\\)\\>") ;;; Strings used to mark beginning and end of excluded text. The start ;; should start with /* and the end end with */. (defconst mupad-exclude-str-start "/*----\\/----- EXCLUDED -----\\/-----") (defconst mupad-exclude-str-end " -----/\\----- EXCLUDED -----/\\----*/") ;; Because of comments of type # # where it is impossible to guess whether # is ;; an opening or an ending, hilighting can be extremely slow. The following ;; string put at a beginning of a line indicates that we are ;; neither in a definition, neither in a commented area. (defvar mupad-safe-place-regexp "^\\(//--\\|####\\)$" "Marker used to tell emacs this point is outside a commented area or a sexp") (defvar mupad-indent-level 2 "*Indentation of Mupad statements with respect to containing block.") (defvar mupad-case-indent 2 "*Indentation for case statements.") (defvar mupad-auto-lineup '(all) ;; Not used "*List of contexts where auto lineup of :'s or ='s should be done. Elements can be of type: 'paramlist', 'declaration' or 'case', which will do auto lineup in parameterlist, declarations or case-statements respectively. The word 'all' will do all lineups. '(case paramlist) for instance will do lineup in case-statements and parameterlist, while '(all) will do all lineups.") (defvar mupad-type-keywords ;; Used for completion. '("DOM_INT" "DOM_RAT" "DOM_FLOAT" "DOM_COMPLEX" "DOM_STRING" "DOM_PROC" "DOM_EXEC" "DOM_EXPR") "*Keywords for types used when completing a word in a declaration or parmlist. \(eg. integer, real, char.) The types defined within the Mupad program will be completed runtime, and should not be added to this list.") (defvar mupad-start-keywords ;; Not used '("begin" "end_proc" "fun" "proc" "func" "until" "while" "repeat") "*Keywords to complete when standing at the first word of a statement. \(eg. begin, repeat, until, readln.) The procedures and variables defined within the Mupad program will be completed runtime and should not be added to this list.") (defvar mupad-separator-keywords ;; Not used '("from" "to" "else" "of" "otherwise" "do" "then") "*Keywords to complete when NOT standing at the first word of a statement. \(eg. downto, else, mod, then.) Variables and function names defined within the Mupad program are completed runtime and should not be added to this list.") ;;; bij - new (defvar mupad-end-keywords ;; Not used '("end_proc" "end_if" "end_case" "end_while" "end_for") "*Keywords to complete when standing at the first word of a statement. \(eg. begin, repeat, until, readln.) The procedures and variables defined within the Mupad program will be completed runtime and should not be added to this list.") (defvar mupad-string-opened 0) (defconst mupad-indent-alist '((block . (+ ind mupad-indent-level)) (caseblock . (+ ind mupad-indent-level mupad-indent-level)) (casesub . (+ ind mupad-indent-level)) (cpp . 0) ;; <-- What is a `cpp' ?? (declaration . (+ ind mupad-indent-level)) (comment . 0) (defun . ind) (contexp . ind) (unknown . 0) (string . 0))) ;;---------------------------------------------------------------------- (defconst mupad-separator (list "--------------")) ;; 100% internal. It is used for the menu-bar. (defvar mupad-colors-alist (list 'default 'red 'red3 'magenta3 'brown 'green3 'grey50 'grey40 'deepskyblue1 'hex-80a0ff 'blue3 'yellow 'hex-ffff60) "A list of symbolic-names of faces used + some default ones.") (defvar mupad-color-menu-list nil "List containing the color menu.") ;; An internal variable to speed things up. ;; Not too successful in that. (defvar mupad-colors-initp nil "t is colors have been initialized") ;; To avoid re-loading them if it has already been done. (defvar mupad-colors-modifiedp nil "t if some color has been modified") ;; To select whether the menu-item [MuPAD/Colors/Save] should be ;; active or not. (defvar mupad-vcam-process nil) ;; Not very rigorous since several vcam-process may be running. (defvar gud-mdx-history nil "History of argument lists passed to mdx.") ;; There's no guarantee that Emacs will hand the filter the entire ;; marker at once; it could be broken up across several strings. We ;; might even receive a big chunk with several markers in it. If we ;; receive a chunk of text which looks like it might contain the ;; beginning of a marker, we save it here between calls to the ;; filter. (defvar gud-mdx-marker-acc "") ;; Examples to be found in 'mupad-directory/examples: (defconst mupad-examples-alist1 (list "animation/catenoid/prg/cat-heli.mu" "animation/enneper/prg/enn.mu" "animation/enneper/prg/ennradial.mu" "animation/gauss/prg/gauss.mu" "animation/gauss/prg/gaussn.mu" "graphics/clipping/clip_3d.mu" "graphics/color/angle.mu" "graphics/color/attract.mu" "graphics/color/plane.mu" "graphics/color/sphere1.mu" "graphics/contour/contour.mu" "graphics/fractals/examples.mu" "graphics/fractals/fractals.mu" "graphics/list/hexagon.mu" "graphics/list/rectangl.mu" "graphics/list/sier.mu" "graphics/list/tetra.mu" "graphics/list/tree.mu" "graphics/minimal/catenoid.mu" "graphics/minimal/complex.mu" "graphics/minimal/enneper.mu" "graphics/minimal/enneperr.mu" "graphics/minimal/helicoid.mu" "graphics/minimal/henneber.mu" "graphics/minimal/planar.mu" "graphics/minimal/radial.mu" "graphics/minimal/riemann.mu")) ;; Examples to be found in 'mupad-directory/examples: (defconst mupad-examples-alist2 (list "graphics/misc/butfly.mu" "graphics/misc/klein.mu" "graphics/misc/pebbles.mu" "graphics/misc/rollkurve.mu" "graphics/misc/snake.mu" "graphics/misc/spiral.mu" "graphics/primitiv/col_cube.mu" "graphics/primitiv/cube.mu" "graphics/primitiv/hexagon.mu" "graphics/primitiv/rectangl.mu" "graphics/primitiv/sier.mu" "graphics/primitiv/tetra.mu" "graphics/primitiv/tree.mu" "graphics/solitons/burg_int.mu" "graphics/solitons/burg_one.mu" "graphics/solitons/burg_two.mu" "graphics/solitons/kdv_int.mu" "graphics/solitons/kdv_one.mu" "graphics/solitons/kdv_two.mu" "graphics/solitons/kdv_vir.mu" "graphics/solitons/sg_one.mu" "graphics/solitons/sg_two.mu" "groebner/trinks1.mu" "groebner/trinks2.mu" "lindenmayer/lsys.mu" "lindenmayer/plants.mu")) ;; To be found in mupad-directory demo/: (defconst mupad-examples-alist3 (list "domains/GaussNum.mu" "domains/IA.mu" "debugger/example1.mu" "debugger/example2.mu" "advanced/int.mu")) ;; Bad examples: animation-catenoid-prg-cat-heli.mu (asks for Raster) ;; graphics-color-angle.mu (phi is write-protected) ;; graphics-list-tree (length/lenght is write-protected) ;; graphics-minimal-enneper.mu (illegal color) ;; graphics-minimal-enneperr.mu (illegal color) ;; graphics-minimal-planar.mu (illegal color) ;; graphics-primitiv-tree.mu (length/lenght is write-protected) ;; graphics-solitons-kdv_int.mu (illegal color) ;; graphics-solitons-kdv_one.mu (illegal color) ;; graphics-solitons-kdv_two.mu (illegal color) ;; graphics-solitons-kdv_vir.mu (illegal color) ;; graphics-solitons-sg_one.mu (illegal color) ;; graphics-solitons-sg_two.mu (illegal color) ;; lindenmayer-plants.mu (illegal right hand side of rule [Lsys::new]) (defconst mupad-shell-letters-alist (string-to-list"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_=+-*/|^:!#()[]{}~%$,;.&?'`<> \"\\") "See 'mupad-define-locked-keys.") (defconst mupad-max-history-list 30 "Maximal number of commands send to MuPAD to be kept in the history list.") (defvar mupad-history-list nil "Record of the latest commands sent to MuPAD.") (defvar mupad-history-marker 0 "Location in the history list 'mupad-history-list.") (defvar mupad-history-point 0 "Location of last history recall in the buffer.") ;;-------------------------------------- ;; Part II : Keymaps and syntax tables. ;;-------------------------------------- (defvar mupad-mode-map nil "Keymap used in Mupad mode.") (if mupad-mode-map () (setq mupad-mode-map (make-sparse-keymap)) (define-key mupad-mode-map "\r" 'mupad-electric-auto-terminate-line) (define-key mupad-mode-map "\"" 'mupad-electric-open-quote) (define-key mupad-mode-map "(" 'mupad-electric-open-brace) (define-key mupad-mode-map "[" 'mupad-electric-open-brace) (define-key mupad-mode-map "{" 'mupad-electric-open-brace) (define-key mupad-mode-map "\M-\r" 'newline) (define-key mupad-mode-map "\M-i" 'mupad-complete) (define-key mupad-mode-map "\t" 'mupad-electric-tab) (define-key mupad-mode-map "\177" 'backward-delete-char-untabify) (define-key mupad-mode-map "\M-*" 'mupad-star-comment) (define-key mupad-mode-map "\C-c\C-c" 'comment-region) (define-key mupad-mode-map "\C-c\C-e" 'mupad-close-statement) (define-key mupad-mode-map [?\C->] 'mupad-indent-region) (define-key mupad-mode-map [?\C-<] 'mupad-unindent-region) (define-key mupad-mode-map "\M-p" 'mupad-backward-to-same-indent) (define-key mupad-mode-map "\M-n" 'mupad-forward-to-same-indent) (define-key mupad-mode-map "\C-cF" 'mupad-fun-to-proc) (define-key mupad-mode-map "\C-ch" 'mupad-help) (define-key mupad-mode-map "\C-cf" 'mupad-for) (define-key mupad-mode-map "\C-cw" 'mupad-while) (define-key mupad-mode-map "\C-ct" 'mupad-title) (define-key mupad-mode-map "\C-cm" 'mupad-modify) (define-key mupad-mode-map "\C-ce" 'mupad-else) (define-key mupad-mode-map "\C-cl" 'mupad-local) (define-key mupad-mode-map "\C-cp" 'mupad-proc) (define-key mupad-mode-map "\C-c\C-k" 'mupad-kill-job) (define-key mupad-mode-map "\M-l" 'mupad-force-update-hilit) (define-key mupad-mode-map "\M-\C-f" 'mupad-forward-sexp) (define-key mupad-mode-map "\M-\C-b" 'mupad-backward-sexp) ) (defvar mupad-shell-map nil "Keymap for the mupad shell. A shell-mode-map with a few additions") (defun mupad-define-locked-keys nil (mapcar (lambda (achar) (define-key mupad-shell-map (vector achar) (if (or mupad-lock-shell-modep mupad-forcefully-lock-shell-modep) 'mupad-shell-self-insert-command 'self-insert-command))) mupad-shell-letters-alist) (if (not (or mupad-lock-shell-modep mupad-forcefully-lock-shell-modep)) (progn (define-key mupad-shell-map [mouse-2] 'mouse-yank-at-click) (define-key mupad-shell-map "\C-?" 'backward-delete-char-untabify) (define-key mupad-shell-map "\C-y" 'yank)) (define-key mupad-shell-map [mouse-2] 'mupad-shell-mouse-2) (define-key mupad-shell-map "\C-?" 'mupad-shell-backward-delete-char-untabify) (define-key mupad-shell-map "\C-y" 'mupad-shell-yank))) (if mupad-shell-map nil (setq mupad-shell-map (make-sparse-keymap)) (mupad-define-locked-keys) (define-key mupad-shell-map "\M-p" 'previous-line) (define-key mupad-shell-map "\M-n" 'next-line) (define-key mupad-shell-map "\C-p" 'mupad-previous-command) (define-key mupad-shell-map "\C-n" 'mupad-next-command) (define-key mupad-shell-map "\C-cT" 'mupad-toggle-previous-next-behavior) (define-key mupad-shell-map "\C-m" 'mupad-send-input) (define-key mupad-shell-map "\C-j" 'mupad-C-j) (define-key mupad-shell-map "\M-\C-m" 'mupad-C-j) (define-key mupad-shell-map "\M-c" 'mupad-copy-input) (define-key mupad-shell-map "\C-c\C-c" 'mupad-interrupt) (define-key mupad-shell-map "\M-i" 'mupad-complete) (define-key mupad-shell-map "\C-i" 'mupad-complete) (define-key mupad-shell-map "\C-c\C-k" 'mupad-kill-job) (define-key mupad-shell-map "\C-c\C-l" 'mupad-recenter-output-buffer) (define-key mupad-shell-map "\M-l" 'mupad-force-update-hilit) (define-key mupad-shell-map "\C-ch" 'mupad-help) (if mupad-shell-historyp (progn (define-key mupad-shell-map [up] 'mupad-history-recall-previous) (define-key mupad-shell-map [down] 'mupad-history-recall-next)))) (defvar mupad-mode-syntax-table nil "Syntax table in use in mupad-mode buffers.") (if mupad-mode-syntax-table () (setq mupad-mode-syntax-table (make-syntax-table)) (modify-syntax-entry ?\\ "\\" mupad-mode-syntax-table) (modify-syntax-entry ?( "()" mupad-mode-syntax-table) (modify-syntax-entry ?) ")(" mupad-mode-syntax-table) (modify-syntax-entry ?[ "(]" mupad-mode-syntax-table) (modify-syntax-entry ?] ")[" mupad-mode-syntax-table) (modify-syntax-entry ?{ "(}" mupad-mode-syntax-table) (modify-syntax-entry ?} "){" mupad-mode-syntax-table) (modify-syntax-entry ?# "$#" mupad-mode-syntax-table) (modify-syntax-entry ?\~ "." mupad-mode-syntax-table) (modify-syntax-entry ?+ "." mupad-mode-syntax-table) (modify-syntax-entry ?- "." mupad-mode-syntax-table) ;(modify-syntax-entry ?/ ". 1456" mupad-mode-syntax-table) ; XEmacs? (modify-syntax-entry ?/ ". 124b" mupad-mode-syntax-table) (modify-syntax-entry ?* ". 23" mupad-mode-syntax-table) (if isXEmacs (progn (modify-syntax-entry ?\n ">b" mupad-mode-syntax-table) ;; Give CR the same syntax as newline, for selective-display (modify-syntax-entry ?\^m ">b" mupad-mode-syntax-table) ) (modify-syntax-entry ?\n "> b" mupad-mode-syntax-table) ;; Give CR the same syntax as newline, for selective-display (modify-syntax-entry ?\^m "> b" mupad-mode-syntax-table) ) (modify-syntax-entry ?= "." mupad-mode-syntax-table) (modify-syntax-entry ?% "_" mupad-mode-syntax-table) ; symbol (modify-syntax-entry ?! "_" mupad-mode-syntax-table) ; symbol (modify-syntax-entry ?~ "_" mupad-mode-syntax-table) ; symbol (modify-syntax-entry ?< "." mupad-mode-syntax-table) (modify-syntax-entry ?> "." mupad-mode-syntax-table) (modify-syntax-entry ?$ "." mupad-mode-syntax-table) (modify-syntax-entry ?| "." mupad-mode-syntax-table) (modify-syntax-entry ?_ "w" mupad-mode-syntax-table) (set-syntax-table mupad-mode-syntax-table) ) ;; Global keys. They *should* be global. (define-key esc-map "o" (function mupad-restore-wind-conf)) (define-key completion-list-mode-map [mouse-2] (function mupad-mouse-2)) (define-key minibuffer-local-completion-map " " 'self-insert-command) ;; It is usually 'minibuffer-complete-word, but C-i does that. ;; To remove temp-files even if we quit a bit violently: (add-hook 'kill-emacs-hook (function mupad-save-setting-kill-emacs)) (defsubst mupad-wait-for-output (&optional nomessg) "Hang around until the prompt appears. If NOMESSG is present, does not print any final message (aimed at short execution)." (let ((notdone t)) (while notdone (accept-process-output mupad-process 0 300) (let ((p (point))) (if (or (not (and (processp mupad-process) (eq 'run (process-status mupad-process)))) (save-excursion (if (re-search-backward mupad-prompt-regexp mupad-input-start t) (= (match-end 0) (point-max)) nil))) ;; If mupad is not running, or the prompt has appeared, stop. (progn (or nomessg (message "done")) (setq notdone nil)) ;; Else flush the buffer and wait a bit longer. (progn (message "Waiting for mupad output ...") (sit-for 0))) (goto-char p)))) (sit-for 0)) (defsubst safe-delete-file (afile) (if (file-exists-p afile) (delete-file afile))) ;;----------------------------- ;; Part III : Finders/Parsers. ;;----------------------------- (defun mupad-backward-sexp nil (interactive) (if (eq (following-char) ?#) (search-backward "#" nil t) (backward-sexp))) (defun mupad-forward-sexp nil (interactive) (if (eq (char-after (point)) ?#) (search-forward "#" nil t 2) (forward-sexp))) ;; Parsers related to 'mupad-shell-mode: (defun mupad-find-next-input (dummy) "A parser that answers a cons (beg.end) where beg is the beginning of the input and end is its end. DUMMY is not used and only introduced for compatibility with 'hilit-translate." (if (re-search-forward mupad-prompt-regexp nil t) (let ((beg (point)) (end (mupad-find-end-of-input (point-max) nil))) (if end (progn (goto-char end) (cons beg end)))))) (defsubst mupad-is-virtual (where) (get-text-property where 'mupad-virtual-newline)) (defsubst mupad-end-of-inputp (helpp) "Default behaviour is the following: t if point is on `:' or `;' or a virtual newline, and either at the end of the buffer either followed by a real newline. HELPP is a boolean variable. A nil value produce the default behaviour, while a t value answers t if point in at the end of the buffer, or on a virtual newline and either at the end of the buffer either followed by a real newline." (save-excursion (forward-char -1) (and (or (or helpp (looking-at "[;:]")) (and (looking-at "\n") (mupad-is-virtual (point)))) (or (= (point) (1- (point-max))) (and (progn (forward-char 1) (looking-at "\n")) (not (mupad-is-virtual (point)))))))) (defun mupad-find-end-of-input (end helpp) "Gives the position of next end-of-input before END and nil if none. Behaviour depends on boolean HELPP, see 'mupad-end-of-inputp." (save-excursion (while (and (re-search-forward "\n" end t) (not (save-excursion (forward-char -1) (mupad-end-of-inputp helpp))))) (if (and (char-equal (char-after (1- (point))) ?\n) (save-excursion (forward-char -1) (mupad-end-of-inputp helpp))) (point) ;; No more newlines in sight: (goto-char (point-max)) (if (mupad-end-of-inputp helpp) (point) nil)))) (defsubst mupad-relative-command (dir) "Steps to previous or next command line according to the first argument being 1 or -1." (while (and (zerop (forward-line dir)) (not (looking-at mupad-prompt-regexp)) (looking-at "^"))); forward-line at the end of a buffer (end-of-line)) (defun mupad-previous-command () "Recalls previous mupad command." (interactive) (mupad-relative-command -1)) (defun mupad-next-command () "Steps to mupad next command line." (interactive) (mupad-relative-command 1)) ;; Parsers related to 'mupad-mode: (defsubst mupad-get-beg-of-line (&optional arg) (save-excursion (beginning-of-line arg) (point))) (defsubst mupad-get-end-of-line (&optional arg) (save-excursion (end-of-line arg) (point))) (defsubst mupad-within-string () (nth 3 (parse-partial-sexp (mupad-get-beg-of-line) (point)))) ;; Comments : between # #, or /* */ or starting with // (defsubst mupad-get-safe-place nil (save-excursion (if (re-search-backward mupad-safe-place-regexp nil t) (match-end 0) (point-min)))) (defsubst mupad-within-emacs-comment (&optional starting-point) (save-excursion (let* ((aux (mupad-get-safe-place)) (st (if starting-point (max aux starting-point) aux))) (nth 4 (parse-partial-sexp st (point)))))) (defsubst mupad-within-sharp-comment (&optional starting-point) (save-excursion (let* ((howmany 0) (pt (point)) (aux (mupad-get-safe-place)) (st (if starting-point (max aux starting-point) aux))) (goto-char st) (while (search-forward "#" pt t) (setq howmany (1+ howmany))) (not (zerop (mod howmany 2)))))) (defun mupad-within-comment (&optional starting-point) " t if point is within a commented area, nil otherwise. The comment starts at the first character of the comment sequence." (save-match-data (or (mupad-within-emacs-comment starting-point) (mupad-within-sharp-comment starting-point)))) (defun mupad-skip-comments (&optional starting-point) "Skips comments, white spaces, tab and newline characters. Answers nil if no comment has been skipped." (interactive) (save-match-data (let ((has-been-used nil) (incomment nil)) ;; Looking for empty stuff or comment start: (while (and (not (eobp)) (or (looking-at "[ \t\n]+\\(#\\|/[/\\*]\\)?\\|#\\|/[/\\*]") (setq incomment (mupad-within-comment starting-point)))) (setq has-been-used t) (if incomment (re-search-forward "\n\\|\\'\\|\\*/\\|#" nil t) ;; We are outside comments: (skip-chars-forward " \t\n") ;; A comment may start next door: (if (looking-at "#") (re-search-forward "#" nil 1 2))) (forward-comment 100)) ;; 100 is as good a value as any, provided ;; it is large. has-been-used))) (defun mupad-next-balanced-brace () "Gibt die Position der nächsten geschlossenen Klamer zurück (innerhalb der Zeile)" (interactive) (save-excursion (nth 0 (parse-partial-sexp (point) (buffer-size) 0)) (point-marker) (sit-for 1))) (defsubst backward-mupadword nil "Seeks beginning of a mupadword.Returns point." (forward-word -1) (point)) (defsubst forward-mupadword nil "Seeks end of a mupadword. Returns point." (forward-word 1) (point)) (defsubst backward-extended-mupadword nil "Seeks the beginning of an extended mupadword. An extended mupadword is a continuous chain of \\([a-zA-Z_0-9]\\|::\\). Returns point." (if (re-search-backward "\\([^a-zA-Z0-9_:]\\|[^:]:\\|\\`\\)\\(\\(\\w\\|::\\)+\\)" nil t) (goto-char (match-beginning 2)))) (defsubst forward-extended-mupadword nil "Seeks the end of an extended mupadword. A mupadword is a continuous chain of \\([a-zA-Z_0-9]\\|::\\). Returns point." (re-search-forward "\\(\\(\\w\\|::\\)+\\)\\([^a-zA-Z0-9_:]\\|:[^:]\\|\\'\\)" nil t) (goto-char (match-end 1))) (defconst mupad-regexp-identifier "[a-zA-Z_][a-zA-Z_0-9]*" "Regexp to match identifiers in mupad.") (defun mupad-looking-at-identifierp nil "T if point is located at the beginning of a mupad-identifier." (if (looking-at mupad-regexp-identifier) (if (bobp) t (save-excursion (forward-char -1) (looking-at "[^a-zA-Z_0-9]"))) nil)) (defun mupad-end-of-identifier nil "Return end of identifier if mupad-looking-at-identifier is T, nil otherwise." (if (mupad-looking-at-identifierp) (save-excursion (skip-chars-forward "\w") (point)) nil)) (defun mupad-looking-at-fn-call nil "Return end of fn-call if point is located at the beginning of a fn-call, and nil otherwise." (if (mupad-looking-at-identifierp) (save-excursion (goto-char (mupad-end-of-identifier)) (if (not (looking-at "[ \t\n]*(")) nil (goto-char (- (match-end 0) 1)) (mupad-forward-sexp) ;; Error if expression is unbalanced. (point))) nil)) (defun mupad-find-proc-def-start nil "Returns beginning of next proc-name definition." (save-excursion (if (re-search-forward mupad-proc-def-start nil t) (match-beginning 2) nil))) (defun mupad-find-closing-one (regexp-beg expr-end) ;; Should be called from outside a commented area. ;; Answer nil if no proper end_proc is found. (save-excursion (let*((pt (point)) (regexp (concat "\\<" expr-end "\\>")) (pt-end (re-search-forward regexp nil t))) (while (mupad-within-comment) (setq pt-end (re-search-forward regexp nil t))) ;; pt-end is the candidate. Look whether there is another proc ;; before it: (if pt-end (progn (goto-char pt) (while (and pt-end (re-search-forward (concat "\\<" regexp-beg) pt-end t)) (if (not (mupad-within-comment)) (progn ;; We have found another BEG before the closing END ;; which should close before this one. Find a new candidate: (setq pt (mupad-find-closing-one regexp-beg expr-end)) (if pt (progn (goto-char pt) (setq pt-end (re-search-forward regexp nil t)) (goto-char pt)) ;; else trouble: (setq pt-end nil))) ;; a proc within comment counts for nothing. Continue. )) (if pt-end (goto-char pt-end)) (if (looking-at "[:;]") (forward-char 1)) (point)) nil)))) (defun mupad-find-closing-end_proc nil ;; Answers nil if no proper end_proc is found. ;; Should be called from outside a commented area. (mupad-find-closing-one "proc[ \n\t]*(" "end_proc")) (defun mupad-not-within-procp nil (save-excursion (let ((pt (point)) beg end) (goto-char (point-min)) (while (progn (setq beg (mupad-find-proc-def-start)) (and beg (< beg pt))) (setq end (mupad-find-closing-end_proc)) (goto-char (if end end (point-max)))) (< end pt)))) (defsubst mupad-find-regexp-parser (my-regexp) ;; We skip comments, and that saves some time since comments typically ;; contain lots of words. (let ((has-been-foundp nil) (st (point))) (while (if (setq has-been-foundp (re-search-forward my-regexp nil t)) (progn (goto-char (match-beginning 1)) (mupad-skip-comments st)))) (if has-been-foundp (cons (match-beginning 1) (goto-char (match-end 1))) ;; End of parsing. nil))) (defun mupad-find-simple-primitive-name (dummy) (mupad-find-regexp-parser mupad-primitive-regexp-simple)) (defun mupad-find-composed-primitive-name (dummy) ;; The time saving idea is that few contruct of the shape lib::fn ;; will be used. (let ((has-been-foundp nil) beg (st (point))) (while (if (setq has-been-foundp (if (re-search-forward (concat mupad-prefix-regexp "::") nil t) (progn (setq beg (match-end 0)) (goto-char (match-beginning 0)) (re-search-forward (nth 1 (assoc (buffer-substring (match-beginning 0) (- beg 2)) mupad-primitive-regexp-prefix-alist)) nil t)))) (progn (goto-char (match-beginning 1)) (mupad-skip-comments st)))) (if has-been-foundp (cons beg (goto-char (match-end 1))) ;; End of parsing. nil))) (defun mupad-find-prefix (dummy) (mupad-find-regexp-parser mupad-prefix-regexp)) ;;-------------------------------- ;; Part IV : Highlighting stuff. ;;-------------------------------- ;; A macro that behaves like a constant: (defmacro mupad-hilit-init nil "Enable highlighting for mupad-things" (` (if (and (setq mupad-can-hilit (and mupad-can-hilit (eq window-system 'x) (x-display-color-p))) (not mupad-colors-initp)) (progn (setq mupad-colors-initp t) ;; while running MuPAD (hilit-set-mode-patterns 'mupad-shell-mode (cons (cons mupad-prompt-regexp '(nil mupad-prompt)) '( (mupad-find-next-input 0 mupad-input)) )) ;; to edit MuPAD scripts. (hilit-set-mode-patterns 'mupad-mode ;; The patterns will be examined from bottom to top, and colouring ;; will be replaced by the new one. Thus everything inside a comment ;; will be in a same colour. If you want it the other way round, ;; you should displace the part related to comments. (cons (list (regexp-quote mupad-exclude-str-start) (regexp-quote mupad-exclude-str-end) 'mupad-comment) (cons (list mupad-proc-def-start 2 'mupad-function-name) '( ("#\\([^#]*\\)#" 0 mupad-comment) ("//.*$" 0 mupad-comment) ("/\\*" "\\*/" mupad-comment) ("\\<\\(axiom\\|begin\\|break\\|ca\\(\\(tegory\\)\\|\\(se\\)\\)\\|do\\(main\\|wnto\\)?\\|E\\|el\\(if\\|se\\)\\|end_\\(axiom\\|ca\\(tegory\\|se\\)\\|domain\\|for\\|if\\|proc\\|repeat\\|while\\)\\|for\\|from\\|I\\|if\\|in\\|intersect\\|local\\|name\\|next\\|of\\|option\\|otherwise\\|proc\\|quit\\|repeat\\|step\\|then\\|to\\|until\\|while\\)\\>" 1 mupad-keyword) ("[]-[\\.\\+\\*/,<>^;()=:\\$@]+" 0 mupad-keyword) ("&\\w*\\>" 0 mupad-keyword) ("\\<\\(and\\|or\\|union\\|minus\\|intersect\\|mod\\|div\\|not\\)\\>" 1 mupad-keyword) ("\\<\\(Adaptive\\|All\\(data\\)?\\|Always\\|Any\\|App\\(end\\|rox\\)\\|Attached\\|Axes\\(Scaling\\)?\\|BUTCHER6\\|BackSubstitution\\|Banded\\|Beam\\|Bin\\(ary\\)?\\|Bo\\(ttom\\|x\\)\\|CameraPoint\\|Capacity\\|Center\\|Co\\(effs\\|lor\\(Patches\\|s\\)?\\|lumn\\|mplete\\|ncave\\|ntours\\|nvex\\|rner\\)\\|Curves?\\|Cyclic\\|DebugOnTheFly\\)\\>" 1 mupad-options) ("\\<\\(DegInvLexOrder\\|Degree\\|DegreeOrder\\|Delete\\|Diagonal\\|Dimension\\|DomainsOnly\\|DualPrices\\|EULER1\\|Error\\|Eweight\\|Exact\\|Expr\\|Extended\\|Filled\\|FilledCircles\\|First\\|Flat\\|FloatFormat\\|FocalPoint\\|Format\\|Fr\\(ames\\|obenius\\)\\|GC\\|GL\\|GT\\|Gauss\\(Chebyshev\\|Legendre\\|Tschebyscheff\\)?\\|Gif\\|Grid\\|Height\\|HiddenLine\\|In\\(clude\\|dependent\\|dex\\(List\\)?\\|finity\\|tMod\\|teractive\\)\\|Label\\(ing\\|s\\)\\)\\>" 1 mupad-options) ("\\<\\(Laurent\\|Le\\(ft\\|ngth\\|xOrder\\)\\|Li\\(ne\\(Width\\)?\\|st\\)\\|Log\\|MaxDegree\\|Mesh\\|MinorExpansion\\|Mod\\(e\\|uleTrace\\)\\|Multiple\\|NC\\|Na\\(med?\\|ry\\|tural\\)\\|New\\(tonCotes\\)?\\|No\\(Check\\|Errors\\|\\(Left\\|Right\\)Vectors\\|nNe\\(gative\\|sted\\)\\|ne\\|tAKnot\\)\\|Only\\|Open\\|Origin\\|Path\\|Periodic\\|Piechart\\(3d\\)?\\|Plain\\|PlotDevice\\|Point\\(Style\\|Width\\)\\|PolyExpr\\|Post\\(Map\\|fix\\)\\|Pre\\(Map\\|fix\\|tty\\)\\|PrincipalValue\\|Proc\\)\\>" 1 mupad-options) ("\\<\\(Puiseux\\|Qu\\(iet\\|o\\)\\|Ra\\(ster\\|tExpr\\)\\|Re\\(cursive\\|m\\|order\\)\\|Right\\|Root\\|Sample\\|Scal\\(es\\|ing\\)\\|Smoothness\\|Special\\|Stepsize\\|Style\\|Surface\\|Symbolic\\(Analysis\\)?\\|System\\|Taylor\\|Te\\(rms?\\|st\\|xt\\)\\|Ti\\(cks\\|tle\\(Position\\|s\\)?\\)\\|To\\(\\(Minus\\)?Infinity\\|Nearest\\|Zero\\)\\|TrailingZeroes\\|Un\\(Constrained\\|ique\\|quoted\\|restricted\\|simplified\\)\\|Up\\|Use\\(PrimeTab\\|r\\)\\|Values\\|VectorOf\\|ViewingBox\\|Vweight\\|Warning\\|Write\\|X11\\|YRange\\|sin\\(cos\\|hcosh\\)\\)\\>" 1 mupad-options) (mupad-find-simple-primitive-name nil mupad-primitive-name) (mupad-find-composed-primitive-name nil mupad-primitive-name) (mupad-find-prefix nil mupad-domain) ; ( mupad-variable-name) ;; <-- Not used ("\\<\\(DOM_\\(ARRAY\\|BOOL\\|COMPLEX\\|DOMAIN\\|EX\\(EC\\|PR\\)\\|FAIL\\|FLOAT\\|FUNC_ENV\\|IDENT\\|\\(PO\\)?INT\\|LIST\\|NIL\\|NULL\\|POLY\\(GON\\)?\\|PROC\\(_ENV\\)?\\|RAT\\|SET\\|STRING\\|TABLE\\|VAR\\)\\)\\>" 2 mupad-type) ("\\<\\(TRUE\\|FALSE\\|UNKNOWN\\|FAIL\\|NIL\\|infinity\\)\\>" 1 mupad-type) ("\\<\\(userinfo([^;]+\\);" 1 mupad-info) (hilit-string-find ?\\ mupad-string))))) ;; Convert the symbols 'mupad-function-args and so on into ;; faces (well, not exactly : into other symbolic-names of faces ;; but which are associated to a face): (mupad-hilit-translate) ;; Work out the list of symbolic-names of faces used: (mupad-init-mupad-colors-alist) )))) (defun mupad-hilit-translate () "Translates symbolic highlight group names to actual colors. If you work with a dark background, set hilit-background-mode to 'dark before calling this function" ;; Extends the list `hilit-face-translation-table' by adding the ;; conses (symbolic-name-here . symbolic-name-face). We recover the ;; symbolic-name-face by ;; (cdr (assq 'symbolic-name hilit-face-translation-table)). (interactive) (if (file-exists-p mupad-colors) (load-file mupad-colors) (if (eq hilit-background-mode 'light) ;; light background (hilit-translate mupad-comment 'DimGray-italic mupad-string 'DimGray-italic ;'LimeGreen mupad-keyword 'LightGray-bold ;'MediumBlue mupad-options 'DimGray-bold-italic mupad-primitive-name 'red-inverse-video-bold mupad-function-name 'red-bold mupad-domain 'DimGray-bold-italic mupad-type 'Gray90 ;'MediumSeaGreen mupad-info 'GoldenRod mupad-prompt 'MediumSeaGreen mupad-input 'MediumBlue) ;; dark background (hilit-translate mupad-comment 'LightGray-italic mupad-string 'LightGray-italic mupad-keyword 'DimGray-bold mupad-options 'LightGray-bold-italic mupad-function-name 'red-bold mupad-primitive-name 'red-inverse-video-bold mupad-domain 'LightGray-bold-italic mupad-type 'DimGray mupad-info 'GoldenRod mupad-prompt 'MediumSeaGreen mupad-input 'MediumBlue )))) (defsubst mupad-put-color (acolor start end) "Paint text from START to END with ACOLOR. See mupad-fancy-logo for the type of ACOLOR." (facemenu-add-face (hilit-lookup-face-create acolor) start end)) (defun mupad-fancy-logo nil " To give colours to the logo." (save-excursion (goto-char (point-min)) (if (and mupad-can-hilit (featurep 'facemenu) (featurep 'hilit19) ;; A rough detector that the logo is present: (re-search-forward " \\*----\\* MuPAD " (point-max) t)) (progn (hilit-translate shade1 'yellow shade2 'red shade3 'blue shade4 'green shade5 'cyan) (goto-char (+ 3 (match-beginning 0))) (mupad-put-color 'shade1 (point) (+ 6 (point))) (forward-line 1) (mupad-put-color 'shade5 (+ 2 (point)) (+ 9 (point))) (forward-line 1) (mupad-put-color 'shade2 (1+ (point)) (+ 7 (point))) (mupad-put-color 'shade5 (+ 8 (point)) (+ 9 (point))) (forward-line 1) (mupad-put-color 'shade3 (+ 3 (point)) (+ 6 (point))) (mupad-put-color 'shade3 (+ 7 (point)) (+ 9 (point))) (mupad-put-color 'shade5 (1+ (point)) (+ 2 (point))) (mupad-put-color 'shade5 (+ 3 (point)) (+ 4 (point))) (forward-line 1) (mupad-put-color 'shade5 (1+ (point)) (+ 8 (point))) (forward-line 1) (mupad-put-color 'shade4 (1+ (point)) (+ 7 (point))) )))) (defsubst mupad-rehilight-region (st en) (if mupad-can-hilit (hilit-rehighlight-region st en t))) ;; We call all the symbols of the list mupad-places-alist: `mupad-places'. ;; They will be linked to a pattern to be hilighted and to a face. ;; Well, not exactly to a face but to another symbol which ;; `hilit19.el' will recognise as corresponding to a face. ;; We call them `symbolic-face-name(s)', `symbolic-name(s)' or `color(s)'. (defmacro mupad-place-to-name (amupad-place) (` (cdr (assq (, amupad-place) hilit-face-translation-table)))) (defsubst mupad-add-to-mupad-colors-alist (asymbolic-name) (if (memq asymbolic-name mupad-colors-alist) nil (setq mupad-colors-alist (cons asymbolic-name mupad-colors-alist)))) (defun mupad-init-mupad-colors-alist () (sort (mapcar (lambda (aquoted-mupad-place) (mupad-add-to-mupad-colors-alist (mupad-place-to-name (eval aquoted-mupad-place)))) mupad-places-alist) (function (lambda (p q) (string-lessp (symbol-name (mupad-place-to-name p)) (symbol-name (mupad-place-to-name q))))))) (defmacro mupad-save-acolor (amupad-place) (` (insert "(hilit-translate " (symbol-name (, amupad-place)) " '" ;; the nil face-name is replaced by default. (if (string= (symbol-name (mupad-place-to-name (, amupad-place))) "nil") "default" (symbol-name (mupad-place-to-name (, amupad-place)))) ")\n"))) (defun mupad-save-colors () " Stores the colors of the mupad-places in the file specified by mupad-colors" (interactive) (save-excursion (set-buffer (get-buffer-create "mupad-colors.el")) (set-visited-file-name mupad-colors) (mapcar (lambda (aquoted-mupad-place) (mupad-save-acolor (eval aquoted-mupad-place))) mupad-places-alist) ;; Now we make the changes but we do NOT keep the old version. ;; Will send a message when done. (if (file-exists-p mupad-colors) (save-buffer 0) (write-file mupad-colors)) (setq mupad-colors-modifiedp nil) (kill-buffer "mupad-colors.el"))) (defun mupad-force-update-hilit () "Update hilit" (interactive) (if mupad-can-hilit ;; Rehilit only the visible part: (hilit-rehighlight-region (window-start) (min (window-end) (point-max)))) (message "done.")) (defun mupad-wait-and-update-hilit () "Update hilit after a MUPAD-output" (mupad-wait-for-output) (if mupad-can-hilit ;; Rehilit only the visible part: (hilit-rehighlight-region (window-start) (min (window-end) (point-max))))) (defun mupad-update-hilit-buffers nil " Update hilighting/unhilighting on all the buffers that are in mupad-mode or in mupad-shell-mode." (interactive) (save-excursion (mapcar (lambda (abuffer) (set-buffer abuffer) (if (memq major-mode '(mupad-shell-mode mupad-mode)) (if mupad-can-hilit (hilit-rehighlight-buffer) (hilit-unhighlight-region (point-min) (point-max))))) (buffer-list)) (message ""))) (defmacro mupad-color-help () (` (if mupad-tutorial-requiredp (let ((wind (selected-window))) ;; We either create another window, either switch to another window ;; if there are already at least two of them. (mupad-window-manager "*MuPAD Help*" 'mupad-beginning-temp) (insert "Feeling adventurous ?\n\n" "A face name has the shape:\n" " FaceForForeground/FaceForBackground-[bold,italic]-[underline]\n" "or simply: FaceForForeground.\n\n" "And FaceFor[Foreground|Background] can be chosen in the\n" "following (non-exhaustive) list:\n" " black blue brown cyan DarkGoldenrod dimgrey firebrick\n" " ForestGreen Goldenrod green grey40 grey50 hex-80a0ff\n" " hex-ffff60 lightblue magenta\n" " mocassin OliveDrab orange pink Plum purple\n" " red RoyalBlue tan yellow white\n" "\n In addition, you can usually add an integer suffix between 1\n" "and 4, like in green3.\n" "\nFor instance, you can try the flashy firebrick/yellow-bold.\n" "Italic fonts don't show on the screen but are used whenever\n" "you get a print-out via the item `Postcript Print Buffer' of\n" " the menu-item `Tools'.\n" "Finally note here that nil is not the default face ... since.\n" "this default face is simply called `default' !\n") (select-window wind))))) (defun mupad-hilit-switch nil (interactive) (setq mupad-can-hilit (not mupad-can-hilit)) (mupad-update-hilit-buffers)) ;;---------------------------- ;; Part V : Window manager. ;;---------------------------- (defun mupad-mouse-2 (event) "A kind of hook for 'mouse-choose-completion." (interactive "e") (funcall 'mouse-choose-completion event) ;; 'mouse-choose-completion comes from the standard file "mouse.el". (mupad-restore-wind-conf) (forward-extended-mupadword)) (defsubst mupad-info-wind-conf nil (message "M-o or ESC-o will remove the help/completion window")) (defsubst mupad-depile-wind-conf nil (setq mupad-registers-list (cdr mupad-registers-list))) (defsubst mupad-backward-wind-conf nil "Restores previously stored window configuration." (if (not (equal mupad-registers-list nil)) (progn (jump-to-register (car mupad-registers-list)) (setq mupad-registers-list (cdr mupad-registers-list))))) (defsubst mupad-skim-list (alist abound) "If the length of ALIST is <= than ABOUND, does nothing, else replaces ALIST by the same list minus its last element." (or (<= (length (eval alist)) abound) (set alist (nreverse (cdr (nreverse (eval alist))))))) (defsubst mupad-store-wind-conf nil "Adds a the current window configuration to the pile. If the pile has more than mupad-max-nb-wind-conf items [numbered (0,1,...,(1- mupad-max-nb-wind-conf))] then the first item is lost." (mupad-skim-list 'mupad-registers-list mupad-max-nb-wind-conf) (let ((next (if (equal mupad-registers-list nil) 0 (if (= (car mupad-registers-list) (1- mupad-max-nb-wind-conf)) 0 (1+ (car mupad-registers-list)))))) (window-configuration-to-register next) (setq mupad-registers-list (cons next mupad-registers-list)))) (defun mupad-restore-wind-conf (&optional arg) "Restores the previous window-configuration, killing the *MuPAD Help* buffer if it was and is no more displayed. When called with prefix ^U, just now does nothing !" (interactive "P") (if (and arg (= (car arg) 4)) ;; Meaning that the call has been C-u-M-o nil (let ((had-help-windowp (and (get-buffer "*MuPAD Help*") (get-buffer-window "*MuPAD Help*")))) (mupad-backward-wind-conf) ;; Kill the buffer *MuPAD Help* if it is not displayed anymore: (if had-help-windowp (if (not (get-buffer-window "*MuPAD Help*")) (kill-buffer "*MuPAD Help*")))) ;; When called from menu-bar, write nothing in the minibuffer: (message ""))) (defsubst name-extension (filename) "Returns the extension suffix of filename, if any." (if (> (length filename) (length (file-name-sans-extension filename))) (substring filename (1+ (length (file-name-sans-extension filename)))) "")) (defmacro mupad-pgrmp (abuffer) "Returns t if buffer abuffer has a name with a .mupad extension suffix." (` (string= (name-extension (buffer-name (, abuffer))) "mu"))) (defmacro mupad-possible-file-name nil "Try to guess the name of a likely mupad-program" ;; First tries the existing windows, then the existing buffers. (` (let ((pgrm nil)) (walk-windows (lambda (wind) (if (mupad-pgrmp (window-buffer wind)) (setq pgrm (append (list (buffer-name (window-buffer wind))) pgrm))))) (if pgrm (car pgrm) ;; Return value if a window is displaying ;; a candidate mupad-program. (mapcar (lambda (abuffer) (if (mupad-pgrmp abuffer) (setq pgrm (append (list (buffer-name abuffer)) pgrm)))) (buffer-list)) (if pgrm (car pgrm) ;; Return value if a buffer is ;; candidate mupad-program. nil ;; Return value if fail. ))))) (defun mupad-window-manager (my-buffer-name option) "Takes care of the windows in mupad-mode and mupad-shell-mode. Displays the buffer MY-BUFFER-NAME in a proper window. The variable OPTION is -- mupad-beginning when we handle the beginning of a procedure. If a buffer already exists with this name, do nothing. -- mupad-beginning-temp when we handle the beginning of a procedure. If a buffer already exists with this name, store it. -- mupad-remove-help-now to remove help-window, -- mupad-remove-help-old-config to wait and remove help-window without touching to the other windows. -- mupad-remove-help-now-old-config to remove help-window without touching to the other windows. -- nil when it is the end of a call. The variable MY-BUFFER-NAME is one of \"*MuPAD*\" \"*MuPAD Help*\". " (cond ((and (string= my-buffer-name "*MuPAD*") (eq option 'mupad-beginning) (get-buffer-window "*MuPAD*")) ;; We go to *MuPAD* and a window already exists with this buffer. (select-window (get-buffer-window "*MuPAD*"))) ((and (string= my-buffer-name "*MuPAD*") (eq option 'mupad-beginning) (not (get-buffer-window "*MuPAD*"))) ;; We go to *MuPAD* and a window doesn't exist with this buffer. (if (= (count-windows) 1) ;; If there is only one window which contains a mupad-program, ;; split the window in 2, else use this window: (progn (if (mupad-pgrmp (window-buffer)) (select-window (split-window-vertically))) (switch-to-buffer "*MuPAD*")) ;; At least two windows exist. Do not create another one ;; and first try to use the help window, else the ;; starting window. (mupad-store-wind-conf) (cond ((get-buffer-window "*MuPAD Help*") (select-window (get-buffer-window "*MuPAD Help*")) (switch-to-buffer "*MuPAD*")) (t (switch-to-buffer-other-window "*MuPAD*"))))) ((and (string= my-buffer-name "*MuPAD*") (not option) (get-buffer "*MuPAD*")) ;; We want to exit from *MuPAD*. (if (> (count-windows) 1) (delete-windows-on "*MuPAD*") ;; Else only one window. (if (string= (buffer-name (window-buffer)) "*MuPAD*") ;; This only window displays "*MuPAD*" (let ((next-buffer (mupad-possible-file-name))) (if next-buffer (switch-to-buffer next-buffer) ;; Else, don't know what to do ! (mupad-restore-wind-conf) )))) (kill-buffer "*MuPAD*")) ((and (get-buffer my-buffer-name) (string= my-buffer-name "*MuPAD Help*") (eq option 'mupad-remove-help-now)) ;; A buffer displaying "*MuPAD Help*" exists. ;; We want to remove the message. (kill-buffer my-buffer-name) (let ((buffer-to-select "")) (save-excursion (let ((abufferlist (buffer-list))) (while (and (string= buffer-to-select "") abufferlist) (set-buffer (car abufferlist)) (if (memq major-mode '(mupad-shell-mode mupad-mode)) (setq buffer-to-select (buffer-name))) (setq abufferlist (cdr abufferlist))))) (if (string= buffer-to-select "") nil (switch-to-buffer buffer-to-select))) (mupad-restore-wind-conf)) ((and (get-buffer my-buffer-name) (string= my-buffer-name "*MuPAD Help*") (memq option '(mupad-remove-help-old-config mupad-remove-help-now-old-config))) ;; A buffer displaying "*MuPAD Help*" exists. ;; We want to remove the message without touching ;; to the window-configuration. (cond ((eq option 'mupad-remove-help-old-config) (message "PRESS ANY KEY TO CONTINUE.") (read-event))) (kill-buffer my-buffer-name)) ((and (string= my-buffer-name "*MuPAD Help*") (eq option 'mupad-beginning) (get-buffer-window "*MuPAD Help*")) ;; We go to *MuPAD Help* and a window already exists with this buffer. (select-window (get-buffer-window "*MuPAD Help*")) (erase-buffer)) ((and (string= my-buffer-name "*MuPAD Help*") (eq option 'mupad-beginning-temp) (get-buffer-window "*MuPAD Help*")) ;; We go temporarily to *MuPAD Help* and a window already exists with ;; this buffer. (mupad-store-wind-conf) (select-window (get-buffer-window "*MuPAD Help*")) (erase-buffer)) ((and (string= my-buffer-name "*MuPAD Help*") (memq option '(mupad-beginning mupad-beginning-temp)) (not (get-buffer-window "*MuPAD Help*"))) ;; We go to *MuPAD Help* and a window doesn't exist with this buffer. (mupad-store-wind-conf) (if (= (count-windows) 1) (progn (select-window (split-window-vertically)) (switch-to-buffer "*MuPAD Help*")) (cond ((and (get-buffer-window "*MuPAD*") (not (eq (get-buffer-window "*MuPAD*") (selected-window)))) (select-window (get-buffer-window "*MuPAD*")) (switch-to-buffer "*MuPAD Help*")) (t (switch-to-buffer-other-window "*MuPAD Help*")))) (erase-buffer)) )) ;; end of 'mupad-window-manager ;;------------------------------------------- ;; Part VI : mupad-mode/mupad-shell-mode ;; and some other main functions. ;;------------------------------------------- (defun mupad-displace-input nil (if (and (save-excursion (re-search-forward mupad-prompt-regexp nil t)) (save-excursion (re-search-backward mupad-prompt-regexp nil t))) (let ((where (point))) (re-search-backward mupad-prompt-regexp nil t) (goto-char (match-end 0)) (setq where (- where (point))) (mupad-copy-input) (re-search-backward mupad-prompt-regexp nil t) (goto-char (+ where (match-end 0)))))) (defun mupad-shell-self-insert-command nil (interactive) (mupad-displace-input) (insert-char last-command-char 1)) (defun mupad-shell-mouse-2 (anevent) (interactive "e") (mouse-set-point anevent) (mupad-displace-input) (yank)) (defun mupad-shell-yank nil (interactive) (mupad-displace-input) (yank)) (defun mupad-shell-backward-delete-char-untabify nil (interactive) (mupad-displace-input) (backward-delete-char-untabify 1)) (defun mupad-shell-mode nil "Major mode for MuPAD session. Available special keys are: \\{mupad-shell-map} You write expressions on several lines via M-RET." (interactive) (setq major-mode 'mupad-shell-mode mode-name "MuPAD") (set-syntax-table mupad-mode-syntax-table) (use-local-map mupad-shell-map) (run-hooks 'mupad-mode-hook) (run-hooks 'mupad-shell-mode-hook) (setq mupad-cpl-file (concat mupad-cpl-directory "mupad-cpl-file.el")) (mupad-hilit-init) (mupad-load-lib) (mupad-adapt-textwidth) (mupad-init-shell-menu-bar) (setq mode-line-process '(": %s"))) (defun mupad-save-setting-kill-emacs nil "Asks whether to save the choice of colors if need be and removes temporary files." (if (and mupad-colors-modifiedp (y-or-n-p " Save Colors ? ")) (mupad-save-colors)) (if (and mupad-save-sessionp (get-buffer "*MuPAD*") (y-or-n-p "Save MuPAD session ? ")) (progn (set-buffer "*MuPAD*") (set-visited-file-name "MuPAD-last-session") (save-buffer))) (mupad-clear-temp-files)) (defmacro mupad-background nil "Same as 'mupad except that it doesn't switch to the buffer `*MuPAD*'." (` (save-excursion (if (and (processp mupad-process) (eq (intern "run") (process-status mupad-process))) nil ;; If mupad is already running, do nothing. ;; Else start up mupad in the buffer. (save-excursion (set-buffer (get-buffer-create "*MuPAD*")) ;; Insert the command line string into the *PARI* buffer (for reference) (insert "Called with: " mupad-command " " mupad-args "\n\n") ;; Start mupad. (set-process-sentinel (setq mupad-process (start-process "mupad" "*MuPAD*" shell-file-name "-c" ;; .../[t]csh is the shell !! (has to be !) (concat "stty nl; env TERM=emacs PAGER=cat LINES=1000 COLUMNS=" (1- (window-width)) " " mupad-command (if (string= mupad-args "") "" (concat " " mupad-args))))) 'mupad-sentinel) (set-process-filter mupad-process 'mupad-output-filter) (run-hooks 'mupad-mode-hook) (setq mupad-cpl-file (concat mupad-cpl-directory "mupad-cpl-file.el")) (setq mupad-input-start (point-min)) (mupad-wait-for-output t) ;; Introduce 'mupad-mode: (if (equal major-mode 'mupad-shell-mode) nil (mupad-shell-mode)) (hilit-rehighlight-region (point-min) (point-max)) ;; Give some colors to the logo: (mupad-fancy-logo) ))))) (defun mupad-output-filter (process-name bit-of-output) (let ((continue (not (string= bit-of-output ""))) (beg "")) (while (and continue (not (string= bit-of-output ""))) (cond ((string= (substring bit-of-output 0 1) "\n") (setq beg (concat beg "\n")) (setq bit-of-output (substring bit-of-output 1))) ((and (> (length bit-of-output) 2) (string= (substring bit-of-output 0 3) "&> ")) (setq bit-of-output (substring bit-of-output 3))) (t (setq continue nil)))) (let ((my_buffer (buffer-name))) (set-buffer "*MuPAD*") (goto-char (point-max)) (insert beg bit-of-output) (set-buffer my_buffer)) (message ""))) (defun mupad nil " Open a buffer and a window for the execution of mupad. The following bindings are available: \\{mupad-map}" ;; flag is not used. (interactive) (mupad-window-manager "*MuPAD*" 'mupad-beginning) (or (processp mupad-process) (progn (mupad-background) (goto-char (point-max))))) (defun mupad-clear-temp-files nil (if zap-file (safe-delete-file zap-file)) (safe-delete-file mupad-el-temp-file)) (defun mupad-sentinel (proc msg) "Sentinel for the mupad-process in buffer *PARI*." (mupad-window-manager "*MuPAD Help*" 'mupad-remove-help-now) ;; We do not kill the buffer "*Completions*" as it may have ;; been triggered by something else. (mupad-window-manager "*MuPAD*" nil) (mupad-clear-temp-files) (setq mupad-process nil)) (defun mupad-lock-shell-modep-switch nil (interactive) (message (if (setq mupad-lock-shell-modep (not mupad-lock-shell-modep)) "Locked." "Unlocked.")) (mupad-define-locked-keys)) (defsubst mupad-store-in-history-list (beg end) (setq mupad-history-list (cons (buffer-substring beg end) mupad-history-list) mupad-history-marker 0) (mupad-skim-list 'mupad-history-list mupad-max-history-list)) (defsubst mupad-history-remove (who) (delete-region (point) (+ (point) (length (nth (1- who) mupad-history-list))))) (defsubst mupad-history-put (who) (let ((pt (point)) en) (insert (nth (1- who) mupad-history-list)) (setq en (point)) (goto-char pt) (while (and (re-search-forward "\n" nil t) (< (point) en)) (put-text-property (point) (1+ (point)) 'mupad-virtual-newline t)) (goto-char pt))) (defun mupad-history-recall-next nil (interactive) (if (or (not (or mupad-lock-shell-modep mupad-forcefully-lock-shell-modep)) (save-excursion (re-search-forward mupad-prompt-regexp nil t))) ; (mupad-displace-input)) (forward-line 1) (if (or (= mupad-history-marker 0) (not (= mupad-history-point (point)))) (progn (ding) (setq mupad-history-point (point))) (mupad-history-remove mupad-history-marker) (setq mupad-history-marker (1- mupad-history-marker)) (or (= mupad-history-marker 0) (mupad-history-put mupad-history-marker))))) (defun mupad-history-recall-previous nil (interactive) (if (or (not (or mupad-lock-shell-modep mupad-forcefully-lock-shell-modep)) ; (mupad-displace-input)) (save-excursion (re-search-forward mupad-prompt-regexp nil t))) (forward-line -1) (or (= mupad-history-point (point)) (setq mupad-history-marker 0 mupad-history-point (point))) (if (< mupad-history-marker (length mupad-history-list)) (progn (or (= mupad-history-marker 0) (mupad-history-remove mupad-history-marker)) (mupad-history-put (setq mupad-history-marker (1+ mupad-history-marker))))))) ;;;###autoload (defun mupad-mode () "Major mode for editing Mupad code. \\ !!! This version is still under development. !!! The main work is to indent code correctly while editing, to colour the code and to provide a menu-bar item. \\[comment-region] will place '//' at beginning of each line in region Other useful functions are: \\[mupad-star-comment]\t- insert /* */ \\[mupad-indent-region]\t- indent region without influence the indent structure \\[mupad-unindent-region]\t- the same reverse Variables controlling indentation/edit style: mupad-indent-level (default 2) Indentation of Mupad statements with respect to containing block. Turning on Mupad mode calls the value of the variable mupad-mode-hook with no args, if that value is non-nil." (interactive) (kill-all-local-variables) (use-local-map mupad-mode-map) (setq major-mode 'mupad-mode mode-name "MuPAD") (set-syntax-table mupad-mode-syntax-table) (make-local-variable 'indent-line-function) (setq indent-line-function 'mupad-indent-line) (setq comment-indent-function 'mupad-indent-comment) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments nil) (make-local-variable 'case-fold-search) (setq case-fold-search t) ;bij - comments (make-local-variable 'comment-start) (setq comment-start "//") (make-local-variable 'comment-start-skip) (setq comment-start-skip "^\\(\\(//\\)+ *\\)") (make-local-variable 'comment-end) (setq comment-end "") ;; Emacs - font-lock now takes care of this ;; except that I (OR) have removed font-lock !! (run-hooks 'mupad-mode-hook) (setq mupad-cpl-file (concat mupad-cpl-directory "mupad-cpl-file.el")) (run-hooks 'mupad-script-mode-hook) ;; OR: (mupad-load-lib) ;; Initializes completion list 'mupad-word-alist. (mupad-hilit-init) (mupad-init-menu-bar)) (defun mupad-C-j nil (interactive) (insert-char ?\n 1) (put-text-property (1- (point)) (point) 'mupad-virtual-newline t)) (defun mupad-copy-input() "Copy expression around point to the end of the buffer. (Unless this is already the last expression.)" (interactive) ;; Go back to the end of prompt, and record that point. (re-search-backward mupad-prompt-regexp) (goto-char (setq mupad-input-start (match-end 0))) ;; end of prompt (let ((helpp (looking-at "[ \t\n]*\\?"))) (setq mupad-input-end (mupad-find-end-of-input (point-max) helpp)) (if mupad-input-end (setq mupad-complete-expression t) (goto-char (point-max)) (setq mupad-input-end (point-max)) (setq mupad-complete-expression (mupad-end-of-inputp helpp))) (let ((lastp (equal mupad-input-end (point-max)))) (if (not lastp) ;; It is not the last expression: (setq mupad-input-end (1- mupad-input-end))) ;; Remove the trailing (virtual) \n : (if (char-equal (char-after (1- mupad-input-end)) ?\n) (progn (goto-char mupad-input-end) (re-search-backward "[^\n]\\(\n\\)" mupad-input-start t) (goto-char (match-beginning 1)) (put-text-property (point) (min (point-max) (1+ mupad-input-end)) 'mupad-virtual-newline nil) (setq mupad-input-end (point)) (setq mupad-complete-expression (mupad-end-of-inputp helpp)))) ;; We refine 'mupad-complete-expression: (let ((ans (parse-partial-sexp mupad-input-start mupad-input-end))) (setq mupad-complete-expression (and mupad-complete-expression (equal (nth 0 ans) 0) ;; Depth in parens is 0. ;; The following one does not work if * is used ;; but *not* as a binary operator: (if helpp t (equal (save-excursion (goto-char (nth 2 ans)) (mupad-forward-sexp) (re-search-forward "[ \t]*[:;]" nil t) (point)) mupad-input-end)) (not (nth 3 ans)) ;; Not inside a string. ;; This one does not work... Why ?? (not (nth 4 ans)) ;; Not inside a comment. ))) (goto-char (point-max)) (if (not lastp) ;; It is not the last expression: (progn (insert (buffer-substring mupad-input-start mupad-input-end)) (if mupad-complete-expression nil (ding) (message "Incomplete expression."))))))) (defun mupad-treat-special-inputp nil ;; There is no special cases that I know of. nil) (defun mupad-treat-special-output nil (save-excursion (mupad-relative-command -1) (setq mupad-should-start-vcam (looking-at "[ \n\t]*Error: Dumb terminal: Plotdata saved in binary file \\([^[]*\\) "))) ;; Ok I know you're wondering why I introduced this ;; variable... Well, maybe for the future. (if (and mupad-should-start-vcam (not mupad-should-not-start-vcam)) (progn (message "I'm trying to sort it out all the same...") (mupad-start-vcam (buffer-substring (match-beginning 1) (match-end 1)))))) (defun mupad-input-filter nil "Look at buffer between mupad-input-start and mupad-input-end. -- If a line `//@@' is found, set variable 'mupad-should-wait-for-ouputp to nil. -- If a comment `/* */' starts by a @@, the content is understood as a Lisp command and appended to the file mupad-el-temp-file. This file is empty at the beginning. This file is loaded before execution of the mupad program." ;; Follow 'mupad-copy-input so the input has been copied at the end ;; of the buffer. 'mupad-input-start and 'mupad-input-end are set. (interactive) (save-excursion ;; Takes care of `/*@@ foo */': (goto-char mupad-input-start) (let ((first-time t)) (while (re-search-forward "/\\*@@\\(\\([^\\*]\\|\\*[^/]\\)*\\)\\*/" mupad-input-end t) (if first-time (progn (setq first-time nil) ;; Remove any older version: (safe-delete-file mupad-el-temp-file))) ;; Append the Lisp part to the file "mupad-prgm": (write-region (match-beginning 1) (match-end 1) mupad-el-temp-file t) (write-region "\n" nil mupad-el-temp-file t) (goto-char (match-end 0))) (if first-time nil ;; Load the Lisp part: (load-file mupad-el-temp-file)))) ;; Run filter hooks if any. It should be here since the hook ;; may have been defined precisely in this file. ;; Should *not* be surrounded by a 'save-excursion ! (run-hooks 'mupad-input-filter-hook) (save-excursion (goto-char mupad-input-start) ;; Takes care of `export(...)': (while (re-search-forward "export(\\([^)]*\\))" mupad-input-end t) (mupad-extend-mupad-word-alist (buffer-substring (match-beginning 1) (match-end 1)))) ;; Takes care of `//@@': (goto-char mupad-input-start) (if (re-search-forward "^//@@$" mupad-input-end t) (setq mupad-should-wait-for-outputp nil)) )) (defun mupad-send-input () "Send input to mupad. Does not send incomplete expression i.e. those ending with \ or a \n which has the text-property 'mupad-virtual-newline. Use a temporary file (and read ) for large expressions" (interactive) (if (mupad-treat-special-inputp) nil ;; already treated. (mupad-copy-input)) ;; does all the work! (if mupad-complete-expression ;; If it is a complete expression do this: (progn (mupad-store-in-history-list mupad-input-start mupad-input-end) (insert "\n") (mupad-input-filter) (if (> (- mupad-input-end mupad-input-start) 1023) ;; If large expression, use a temporary file. (progn (write-region mupad-input-start mupad-input-end zap-file nil) (process-send-string mupad-process (concat "read(\""zap-file"\"):\n"))) ;; Else use process-send-region. (process-send-region mupad-process mupad-input-start mupad-input-end) (process-send-string mupad-process "\n")) (set-marker (process-mark mupad-process) (point)) (if mupad-should-wait-for-outputp (progn (mupad-wait-and-update-hilit) (mupad-treat-special-output)) (setq mupad-should-wait-for-outputp t)) ) ;; Else do this: (message "Incomplete expression: Not sent to MuPAD."))) (defun mupad-interrupt () "Interrupt mupad. This is identical to interrupt-shell-subjob in shell-mode." (interactive) (interrupt-process nil t)) ;;--------------------------------------------------------- ;; Sending/Extracting informations from the mupad-process. ;;--------------------------------------------------------- (defun mupad-quiet-command (acommand) "Execute the command ACOMMAND in an invisible fashion." (save-excursion (set-buffer "*MuPAD*") (setq mupad-input-start (goto-char (point-max))) ;; We need a newline to recognize the prompt properly: (insert "\n") (process-send-string mupad-process (concat acommand "\n")) (mupad-wait-for-output t) ;; Clear what has appeared: (delete-region mupad-input-start (point-max)))) (defun mupad-visible-command (acommand) (mupad-window-manager "*MuPAD*" 'mupad-beginning) (let ((pt (point))) (goto-char (point-max)) (re-search-backward mupad-prompt-regexp (point-min) t) (let ((old (buffer-substring (goto-char (match-end 0)) (point-max)))) (if (<= (point) pt) (setq pt (- pt (+ (point) (length old))))) ;; Removes what was there: (delete-region (point) (point-max)) (insert acommand) (mupad-send-input) ;; Restores what was there: (insert old) (if (> pt 0) (goto-char pt) (forward-char pt))))) (defun mupad-extract-command (acommand window-option) "Same as 'mupad-quiet-command except that the command is being displayed in the buffer \"*MuPAD Help*\". Displays the help window if window-option is 'mupad-beginning. Have it surrounded by a 'save-excursion if you want to call it with a window-option equal to nil." (set-buffer "*MuPAD*") (setq mupad-input-start (goto-char (point-max))) (let (acopy isFAIL) (process-send-string mupad-process (concat acommand "\n")) (mupad-wait-for-output) (goto-char mupad-input-start) (setq isFAIL (looking-at "[ \n\t]*FAIL[ \n\t]+")) (setq acopy (buffer-substring mupad-input-start (point-max))) (delete-region mupad-input-start (point-max)) (if (and (eq window-option 'mupad-beginning) isFAIL) (message "FAIL") (if (eq window-option 'mupad-beginning) ;;Switch to buffer "*MuPAD Help*": (mupad-window-manager "*MuPAD Help*" 'mupad-beginning) (set-buffer (get-buffer-create "*MuPAD Help*")) (erase-buffer)) (insert acopy) (beginning-of-line) ;; We remove the last prompt line. (delete-region (point) (point-max)) (goto-char (point-min))))) ;;------------------------------------------------------------------ ;; Parameters that should be within control: ;; TEXTWIDTH (integer), DIGITS (integer), PRETTY_PRINT (TRUE/FALSE) ;;------------------------------------------------------------------ (defun mupad-set-digits nil (interactive) (mupad-visible-command (concat "DIGITS:=" (read-string "New Value: ") ":"))) (defun mupad-get-prettyprint-value nil "t if PRETTY_PRINT is TRUE, nil otherwise" (save-excursion (set-buffer "*MuPAD*") (setq mupad-input-start (goto-char (point-max))) (let (prettyprint) (process-send-string mupad-process"PRETTY_PRINT;\n") (mupad-wait-for-output) (re-search-backward "TRUE\\|FALSE" nil t) (setq prettyprint (looking-at "TRUE")) (delete-region mupad-input-start (point-max)) prettyprint))) (defun mupad-set-prettyprint-switch nil (interactive) (let ((prettyprint (not (mupad-get-prettyprint-value)))) (mupad-quiet-command (concat "PRETTY_PRINT:=" (if prettyprint "TRUE" "FALSE") ":")) (message (concat "PRETTY_PRINT:=" (if prettyprint "TRUE" "FALSE"))))) (defun mupad-set-prettyprint-invisible nil (interactive) (mupad-quiet-command (concat "PRETTY_PRINT:=" (if (mupad-get-prettyprint-value) "FALSE" "TRUE") ":"))) (defun mupad-adapt-textwidth nil ;; A mupad-process is running. ;; It is most probably not a very good idea to let ;; MuPAD handle the line truncation... Thus TEXTWIDTH:=1023 ;; seems to be best except when the prettyprinter is on. (interactive) (mupad-quiet-command (concat "TEXTWIDTH:=" (number-to-string (1- (window-width))) ":"))) (defun mupad-start nil (interactive) (if (processp mupad-process) (mupad-window-manager "*MuPAD*" 'mupad-beginning) (mupad)) (message "")) (defun mupad-region (beg end) "Run MuPAD on the current region. A temporary file (zap-file) is written in directory mupad-temp-directory, but MuPAD is run in the current directory." (interactive "r") (setq mupad-input-start beg mupad-input-end end) (mupad-input-filter) (save-excursion (save-restriction (widen) (write-region beg end zap-file nil nil))) (mupad) (mupad-visible-command (concat "read(\"" zap-file "\"):"))) (defun mupad-read-input (prompt default sep flag) " If flag is non-nil, reads string (if string is \"\" uses default). Else, if flag is nil, set string to default. If resulting string is not \"\" prepends sep. As a special case, if string is \" \", return \"\"." (let ((string (if flag ;; If flag is non-nil prompt for input from mini-buffer. (read-input (concat prompt " (Default "default") ")) ;; Else use the default string. default))) (if (equal string "") (if (equal default "") "" ;; If string and default both "": (concat sep default)) ;; If string "" and default is non empty: (if (equal string " ") "" ;; If string is a space: (concat sep string))))) ;; If string is non empty: (defun mupad-send-file (closing-statement) "Run MuPAD on a file. If CLOSING-STATEMENT is \":\" then `read' will be used with a final `:' which means errors won't be displayed. Alternatively, CLOSING-STATEMENT can be \";\". See \\[mupad-region] for more information." (let ((mupad-pgrm (mupad-read-input "Name of the MUPAD programm : " (mupad-possible-file-name) "" t))) (mupad) ;; Should be read before the input-filter is applied. (if (get-buffer mupad-pgrm) (save-excursion (set-buffer mupad-pgrm) (if (buffer-modified-p) (save-buffer)) (setq mupad-input-start (point-min) mupad-input-end (point-max)) (mupad-input-filter) ;; In case 'mupad-input-filter modified the buffer: (setq mupad-pgrm (buffer-file-name)) (if (buffer-modified-p) (save-buffer 0)))) (mupad-visible-command (concat "read\(\"" mupad-pgrm "\"\)" closing-statement)))) (defun mupad-file nil (interactive) (mupad-send-file ":")) (defun mupad-execute-file nil (interactive) (mupad-send-file ";")) (defun mupad-kill-job () "Kill the currently running MuPAD job." (interactive) (process-send-string mupad-process "quit\n")) (defun mupad-recenter-output-buffer (linenum) "Redisplay buffer of MuPAD job output so that most recent output can be seen. The last line of the buffer is displayed on line LINE of the window, or centered if LINE is nil." (interactive "P") (let ((old-buffer (current-buffer)) (mupad-shell (if (get-buffer-process (current-buffer)) (current-buffer) (get-buffer "*MuPAD*")))) (if (null mupad-shell) (message "No MuPAD output buffer") (pop-to-buffer mupad-shell) (goto-char (point-max)) (recenter (if linenum (prefix-numeric-value linenum) (/ (window-height) 2))) (pop-to-buffer old-buffer)))) (defun mupad-toggle-previous-next-behavior () "Change C-p/M-p C-n/M-n from previous-line and next-line to mupad-previous-command and mupad-next-command and reciprocally" (interactive) (if (equal (key-binding "\C-p") 'previous-line) (progn (define-key mupad-shell-map "\M-p" 'previous-line) (define-key mupad-shell-map "\M-n" 'next-line) (define-key mupad-shell-map "\C-p" 'mupad-previous-command) (define-key mupad-shell-map "\C-n" 'mupad-next-command)) (define-key mupad-shell-map "\C-p" 'previous-line) (define-key mupad-shell-map "\C-n" 'next-line) (define-key mupad-shell-map "\M-p" 'mupad-previous-command) (define-key mupad-shell-map "\M-n" 'mupad-next-command))) (defun mupad-toggle-electric-behavior () "Change RET/M-RET from mupad-electric-auto-terminate-line to newline and reciprocally" (interactive) (if (equal (key-binding "\r") 'newline) (progn (define-key mupad-mode-map "\r" 'mupad-electric-auto-terminate-line) (define-key mupad-mode-map "\M-\r" 'newline)) (define-key mupad-mode-map "\M-\r" 'mupad-electric-auto-terminate-line) (define-key mupad-mode-map "\r" 'newline))) (defun mupad-toggle nil "Change some keys. See mupad-toggle-previous-next-behavior" (interactive) (if (equal major-mode 'mupad-shell-mode) (progn (mupad-toggle-previous-next-behavior) (message "Exchanged the bindings of the keys C-p/M-p and C-n/M-n.")) (mupad-toggle-electric-behavior) (message "Exchanged the bindings of the keys RET/M-RET."))) ;;---------------------------------------------- ;; Part VII : Functions for writing programs. ;;---------------------------------------------- (defun mupad-go-to-this-indent (step indent-level) "Move point repeatedly by lines till the current line has given indent-level or less, or the start/end of the buffer is hit. Ignore blank lines and comments." (while (and (zerop (forward-line step)) (or (looking-at "[ \t]*$") (looking-at "[ \t]*#") (> (current-indentation) indent-level))) nil)) (defun mupad-backward-to-same-indent () "Move point backwards to nearest line with same indentation or less. If not found, point is left at top of buffer." (interactive) (mupad-go-to-this-indent -1 (current-indentation)) (back-to-indentation)) (defun mupad-forward-to-same-indent () "Move point forwards to nearest line with same indentation or less. If not found, point is left at start of last line in buffer." (interactive) (mupad-go-to-this-indent 1 (current-indentation)) (back-to-indentation)) (defun mupad-for () "Build skeleton for-loop statment, prompting for the loop parameters." (interactive) (let ((for (read-string "var: ")) (st (point))) (if (string-equal for "") (let ((to (read-string "to: "))) (if (not (string-equal to "")) (insert " to " to))) (insert "for " for) (let ((in (read-string "in: "))) (if (not (string-equal in "")) (insert " in " in) (let ((from (read-string "from: "))) (if (not (string-equal from "")) (insert " from " from))) (let ((to (read-string "to: "))) (if (not (string-equal to "")) (insert " to " to)))))) (insert " do") (mupad-electric-terminate-line) (insert "end_for;") (mupad-electric-terminate-line) (mupad-rehilight-region st (point)) (forward-line -2) (mupad-indent-line))) (defun mupad-while () "Build skeleton while-loop statment, prompting for the loop parameters." (interactive) (let ((st (point))) (insert "while " (read-string "conditional: ")) (insert " do") (mupad-electric-terminate-line) (mupad-electric-terminate-line) (insert "end_while;") (mupad-rehilight-region st (point)) (mupad-electric-terminate-line) (forward-line -2) (mupad-indent-line))) (defun mupad-title () "Insert a comment block containing the module title, author, etc." (interactive) (let ((st (point)) (the-title (read-string "Title: " (buffer-name)))) (goto-char (point-min)) (insert "\n\n") (forward-char -2) (insert "/* -*-MuPAD-*-\n\n Title: \t" the-title "\n Created:\t" (current-time-string) "\n Author: \t" (user-full-name) "\n \t\t<" (user-login-name) "@" (system-name) ">\n" "\n Description: \n\n*/\n") (mupad-rehilight-region (point-min) (point)) (goto-char st))) (defun mupad-modify () "Insert a comment block containing the modification, author, etc." (interactive) (let ((st (point)) beg (modif (read-string "Modification: "))) (goto-char (point-min)) (if (not (looking-at "[ \\w]")) (mupad-skip-comments)) (while (char-equal (preceding-char) ?\n) (forward-char -1)) (forward-char 1) (setq beg (point)) (insert "\n/* Modified: " (current-time-string) "\n Author: " (user-full-name) "\n Modification: " modif "\n*/\n") (mupad-rehilight-region beg (point)) (goto-char st))) (defun mupad-else () "Add an elif clause to an if statement, prompting for the condition. When no condition is given, put an else." (interactive) (let ((condition (read-string "else/elif: ")) (st (point))) (if (string-equal condition "") (insert "else ") (insert "elif " condition) (mupad-electric-terminate-line) (insert "then ")) (mupad-rehilight-region st (point)))) (defun mupad-local () "Add a new local variable, inserting the word local if necessary." (interactive) (save-excursion (let ((newvar (read-string "New variable: "))) (beginning-of-line) (while (and (not (looking-at mupad-proc-def-start)) (not (looking-at "[ \t]*proc[ \t]*(")) (not (looking-at "[ \t]*local "))) (forward-line -1)) (let ((first-time (not (looking-at "[ \t]*local "))) (st (point))) (if first-time (progn (end-of-line) (mupad-electric-terminate-line) (insert "local ;") (setq first-time t)) (search-forward ";")) (forward-char -1) (if first-time (insert newvar) (insert ", " newvar)) (mupad-rehilight-region st (point)))))) (defun mupad-proc () (interactive) ;; In this function, we let 'mupad-electric-terminate-line do ;; the indentation job. (let ((name (read-string "Name: " )) args (st (point))) (insert name ":=\nproc (" (read-string "Arguments: ") ")") (let ((options (read-string "Options: "))) (if (not (string-equal options "")) (progn (mupad-electric-terminate-line) (insert "options " options ";")))) (mupad-electric-terminate-line) (insert "begin") (mupad-electric-terminate-line) (mupad-electric-terminate-line) (insert "end_proc: /* End of " name " */") (mupad-rehilight-region st (point)) (mupad-electric-terminate-line) (forward-line -2) (mupad-indent-line))) (defun mupad-display-comment () "Inserts 3 comment lines, making a display comment." (interactive) (save-excursion (let ((st (point))) (insert "/*\n\n*/") (end-of-line) (mupad-rehilight-region st (point)))) (forward-char 3)) (defun mupad-star-comment () "Insert Mupad star comment at point." (interactive) (if (not (mupad-within-comment)) (progn (if (or (bolp) (string= (char-to-string (char-syntax (preceding-char))) " ")) (insert "/* ") (insert " /* ")) (insert " */")) (message "Stay always in commented-area or parenthesis mismatch.") )) (defun mupad-exclude-area (beg end) "Exclude an area of text." (interactive "r") (save-excursion (goto-char beg) (while (re-search-forward mupad-safe-place-regexp end t) (beginning-of-line) (insert " ") (end-of-line) (setq end (1+ end))) (goto-char end) (insert "\n" mupad-exclude-str-end "\n") (goto-char beg) (insert "\n" mupad-exclude-str-start "\n") (mupad-force-update-hilit))) ;;; ;;; Electric functions ;;; (defun mupad-electric-terminate-line () "Terminate line and indent next line." (interactive) ;; First, check if current line should be indented (delete-horizontal-space) (save-excursion (beginning-of-line) (skip-chars-forward " \t") (if (looking-at mupad-autoindent-lines-re) (mupad-indent-line))) (delete-horizontal-space) ; Removes trailing whitespaces (if (mupad-within-string) (insert "\\")) (newline) ;; Indent next line (mupad-indent-line) ) (defun mupad-electric-auto-terminate-line () (interactive) (cond ((and mupad-auto-indent mupad-electric-allowedp) (mupad-electric-terminate-line)) (t (newline)))) ;; This function is not used: (defun mupad-electric-semi-or-dot () "Insert `;' character and reindent the line." (interactive) (insert last-command-char) (save-excursion (beginning-of-line) (mupad-indent-line)) (if mupad-auto-newline ;; (and mupad-electric-allowedp) included in the ;; next function. (mupad-electric-terminate-line))) (defun mupad-electric-open-brace () "Insert closed brace." (interactive) (if (or mupad-no-closed-brace (not mupad-electric-allowedp)) (insert last-command-char) (let ((br (char-to-string last-command-char))) (insert br) (save-excursion (if (not (or (mupad-within-string) (mupad-within-comment) (string= (char-to-string (char-syntax (following-char))) "w"))) (insert (cond ((string= br "(") ")") ((string= br "[") "]") ((string= br "{") "}")))) )))) (defun mupad-open-brace-switch nil (interactive) (setq mupad-no-closed-brace (not mupad-no-closed-brace)) (message (concat "Automatic Braces " (if mupad-no-closed-brace "Off." "On.")))) (defun mupad-electric-switch nil (interactive) (setq mupad-electric-allowedp (not mupad-electric-allowedp)) (message (concat "Electric semi-mode " (if mupad-electric-allowedp "On." "Off.")))) (defun mupad-electric-open-quote () "Insert closed quote." (interactive) (if mupad-electric-allowedp (if (mupad-within-string) (if (= mupad-string-opened 0) (insert "\\\"") (insert "\"") (setq mupad-string-opened 0)) (insert "\"") (if (not (string= (char-to-string (char-syntax (following-char))) "w")) (save-excursion (insert "\"")) (setq mupad-string-opened 1))) (insert "\"")) ) (defun mupad-electric-tab () "Function called when TAB is pressed in MuPAD mode." (interactive) (cond ;; Do nothing if within a string or in a comment: ((mupad-within-comment) (message "no indent while in comment")) ;; If mupad-tab-always-indent, indent the beginning of the line. (t ; else (if mupad-tab-always-indent (let ((beg (point)) be move-p) (end-of-line) (delete-horizontal-space) (beginning-of-line) (setq move-p (if (re-search-forward "[^ \t]" beg t) nil t)) (save-excursion (beginning-of-line) (skip-chars-forward " \t") (setq be (point)) (mupad-indent-line) (setq be (- (point) be))) (if move-p (progn (beginning-of-line) (skip-chars-forward " \t")) (goto-char beg) (forward-char be))) (insert "\t"))) )) ;;; ;;; Indentation ;;; (defun mupad-indent-line () "Indent current line as a Mupad statement." (let* ((indent-str (mupad-calculate-indent)) (type (car indent-str)) (ind (car (cdr indent-str)))) (delete-horizontal-space) ;; Some things should not be indented (if (eq type 'cpp) () ;; Other things should have no extra indent (cond ((looking-at mupad-noindent-re) (indent-to ind)) ((looking-at mupad-casesub-re) (indent-to (+ ind mupad-indent-level))) ;; But most lines are treated this way: (t (indent-to (eval (cdr (assoc type mupad-indent-alist))))) ))) ) (defun mupad-calculate-indent () "Calculates the indent of the current Mupad line. Returns a list of two elements: (INDENT-TYPE INDENT-LEVEL)." (save-excursion (let* ((oldpos (point)) (safe-place (mupad-get-safe-place)) (state (save-excursion (parse-partial-sexp safe-place (point)))) (nest 0) (par 0) (curcol (current-column)) (exs 0) (exsx 0) (exsb 0) (exse 0) (complete (looking-at (concat "[ \t]*" mupad-end-block-re))) ; endblock ;(ass nil) (ass (looking-at (concat mupad-symbol-re "[ \t]*:="))) (assex nil) ; assign (lastmatch "") (lastmatchp 0) (elsed (looking-at (concat "[ \t]*" mupad-sub-block-re))) ; subblock (type (catch 'nesting ;; Check if inside a string, comment or parenthesis (cond ((nth 3 state) (throw 'nesting 'string)) ((nth 4 state) (throw 'nesting 'comment)) ((mupad-within-sharp-comment safe-place) (throw 'nesting 'comment)) ((> (car state) 0) ;; depth in paren is > 0. (save-excursion (goto-char (scan-lists (point) -1 1)) (setq par (1+ (current-column)) exsx (point))) (setq exs (scan-lists (point) -1 (car state))) ; exit subsexpression (save-excursion (search-backward-regexp mupad-beg-block-re exsx t) (setq exsb (point))) (save-excursion (search-backward-regexp mupad-end-block-re exsx t) (setq exse (point))) (if (or (= (point) exsb) (and (not (= (point) exse)) (> exse exsb))) (goto-char exs)) ) ((save-excursion (beginning-of-line) (or (eq (following-char) ?#) (and (eq (following-char) ?/) (or (eq (save-excursion (forward-char) (following-char)) ?/) (eq (save-excursion (forward-char) (following-char)) ?*)) ;; <<-- Modif OR. Was ?/. ))) (throw 'nesting 'cpp) ) ) ;; Loop until correct indent is found (while t (mupad-backward-sexp) (cond (;--ignore comments (mupad-within-emacs-comment safe-place) ;(mupad-within-comment) (forward-comment -10) ) (;--Nest block outwards (looking-at mupad-beg-block-re) (setq lastmatch (buffer-substring (match-beginning 0) (match-end 0)) lastmatchp (match-beginning 0)) (if (= nest 0) (progn (setq curcol (current-column)) (cond ((looking-at "\\") (throw 'nesting 'caseblock)) ( t (throw 'nesting 'block)))) (setq nest (1- nest) ;assex t) ) )) (;--Nest block inwards (looking-at mupad-end-block-re) (setq lastmatch (buffer-substring (match-beginning 0) (match-end 0)) lastmatchp (match-beginning 0)) (setq complete t ;assex t nest (1+ nest)) ; if block end found ) (;--else, elif, of, otherwise (and (not complete) (looking-at mupad-sub-block-re)) (setq lastmatch (buffer-substring (match-beginning 0) (match-end 0)) lastmatchp (match-beginning 0)) (setq curcol (current-column)) (if (or (looking-at "\\") (looking-at "\\")) (throw 'nesting 'casesub) (throw 'nesting 'block))) (;--Found assignment (and (not assex) (looking-at (concat mupad-symbol-re "[ \t]*:="))) (setq lastmatch (buffer-substring (match-beginning 0) (match-end 0)) lastmatchp (match-beginning 0)) (if (bolp) ; assign at left margin (progn (setq lastmatch "bobp" lastmatchp (match-beginning 0)) (throw 'nesting 'cpp)) ; nothing sub possible (if (or complete elsed) () ; nothing (setq ass nil) (save-excursion ; normal indentation (setq curcol (mupad-indent-level)) (search-forward ":=" nil t) (if (not (looking-at "[ \t]*\\($\\|\\(/\\(/\\|\*\\)\\)\\|#\\)")) (setq curcol (1+ (current-column)) ;assex t )) ; search for completion of assignment (if (save-excursion (while (not ass) (mupad-forward-sexp) (setq ass (or (= (following-char) ?\;) (= (following-char) ?\:) (looking-at mupad-end-block-re) (eobp)))) (> (point) oldpos)) (throw 'nesting 'defun) )) )) ) (;--No known statements (bobp) (setq lastmatch "bobp" lastmatchp 0) (throw 'nesting 'unknown)) )) ))) ;; Return type of block and indent level. (cond ((and (> par 0) (> par curcol)) ; Unclosed Parenthesis (list 'contexp par lastmatch lastmatchp)) (t (list type curcol lastmatch lastmatchp)))))) (defun mupad-indent-level () "Return the indent-level the current statement has. Do not count labels, case-statements or records." (save-excursion (beginning-of-line) (skip-chars-forward " \t") (current-column))) (defun mupad-indent-comment (&optional arg) "Indent current line as comment. If optional arg is non-nil, just return the column number the line should be indented to." (let* ((stcol (save-excursion (re-search-backward "\\(#(\\)\\|# +\\|\\(//\\)\\|\\(/\*\\)" nil t) (1+ (current-column))))) (if arg stcol (delete-horizontal-space) (indent-to stcol)))) (defun mupad-close-statement () "Close the last unclosed statement." (interactive) (let ((ind (mupad-calculate-indent)) pat) (save-excursion ; subblock (while ;(or (string-match mupad-sub-block-re (nth 2 ind)) ; (string-match ":=" (nth 2 ind)) ; (not (string= "bobp" (nth 2 ind)))) (and (> (nth 3 ind) 0) (not (string-match mupad-beg-block-re (nth 2 ind)))) (goto-char (nth 3 ind)) (setq ind (mupad-calculate-indent))) (if (string-match mupad-beg-block-re (nth 2 ind)) (setq pat (concat "end_" (nth 2 ind))) (setq pat ""))) (if (not (string= pat "")) (progn (delete-horizontal-space) (cond ((not (> (mupad-get-beg-of-line) (nth 3 ind))) (insert (concat " " pat))) ((bolp) (if (looking-at "[ \t]*$") (insert pat) (save-excursion (mupad-electric-terminate-line)) (insert pat) (mupad-electric-tab))) (t (mupad-electric-terminate-line) (insert pat))) (mupad-electric-tab)) (message "No unclosed statement found.")) )) ;;; bij - neue Funktionen (defun mupad-fun-to-proc (&optional sende) "Schneidet 'fun(...)' aus und gibt '(()->(...))' zurück" (interactive) (let ((now (point)) ende anf reg) (if 'sende () (setq sende (mupad-get-end-of-search))) ;; Unkown function ?? (re-search-forward "\\\" sende t) (re-search-backward "\\\" 1 t) (if (string= (char-to-string (char-syntax (preceding-char))) "\"") (progn (message "fun als Zeichenkette") (sit-for 1) (if (< (point) now) (message "Keine 'fun' mehr in dieser Datei.")) (goto-char (1+ (point)))) (save-excursion (setq ende (mupad-next-balanced-brace))) (setq anf (point-marker)) (replace-match "" t t) (kill-region anf ende) (setq reg (substring (current-kill 0) 1 -1)) (goto-char ende) (insert (concat "(()->(" (concat reg) "))")) ) ;(message "Region %s" reg)) )) (defun mupad-indent-region (start end) "Ein Zeichen nach rechts einrücken. Adds one identation to the whole region." (interactive "r") (save-excursion (goto-char end) (setq end (point-marker)) (goto-char start) (save-excursion (while (< (point) end) (progn (beginning-of-line) (skip-chars-forward " \t") (insert " ") (next-line 1) ))) )) (defun mupad-unindent-region (start end) "Ein Zeichen nach rechts einrücken. Removes one indentation to the right for the whole region." (interactive "r") (save-excursion (goto-char end) (setq end (point-marker)) (goto-char start) (save-excursion (while (< (point) end) (progn (beginning-of-line) (skip-chars-forward " \t") (if (not (bolp)) (backward-delete-char-untabify 1)) (next-line 1) ))) )) ;;; bij - aus tex-mode.el (defun mupad-validate-buffer () "Check current buffer for paragraphs containing mismatched $'s. As each such paragraph is found, a mark is pushed at its beginning, and the location is displayed for a few seconds." (interactive) (let ((opoint (point))) (goto-char (point-max)) ;; Does not use save-excursion ;; because we do not want to save the mark. (unwind-protect (while (and (not (input-pending-p)) (not (bobp))) (let ((end (point))) (search-backward "\n\n" nil 'move) (or (mupad-validate-region (point) end) (progn (push-mark (point)) (message "Mismatch found in pararaph starting here") (sit-for 4))))) (goto-char opoint)))) ;;; bij - aus tex-mode.el (defun mupad-validate-region (start end) "Check for mismatched braces or $'s in region. Returns t if no mismatches. Returns nil and moves point to suspect area if a mismatch is found." (interactive "r") (let ((failure-point nil) (max-possible-sexps (- end start))) (save-excursion (condition-case () (save-restriction (narrow-to-region start end) (goto-char start) (while (< 0 (setq max-possible-sexps (1- max-possible-sexps))) (mupad-forward-sexp))) (error (setq failure-point (point))))) (if failure-point (progn (goto-char failure-point) nil) t))) ;;--------------------------------- ;; Part VIII: Completion mecanism. ;;--------------------------------- (defun mupad-complete () " Attempts to complete a partially typed command. Displays possible completions in the completion buffer if no unique completion can be done." ;; We use a buffer named "*Completions*" which is the buffer usually ;; used, like when reading a file name from the minibuffer. (interactive) (backward-extended-mupadword) (let* ((c-begin (point)) (word (buffer-substring c-begin (forward-extended-mupadword))) (comp (try-completion word mupad-word-alist))) ;; The 3 possible outcomes of completion: (cond ;; (1) Already complete. ((eq comp t) (if (and (get-buffer "*Completions*") (get-buffer-window "*Completions*")) ;; Occurs whenever an earlier completion has ;; been asked for. (mupad-restore-wind-conf)) (message "%s is complete" word)) ;; (2) Not found. (It may be a valid mupad function, unknown to the ;; completion system) ((eq comp nil) (message "No Match found")) ;; (3) Some extension to the word possible. (t (if (not (string= comp word)) ;; Add any unique extension. (progn (insert comp) (delete-region (+ c-begin (length word)) (+ c-begin (* 2 (length word)))))) (if (eq t (try-completion comp mupad-word-alist)) ;; If the extended word is definitely complete, remove the help window (progn (if (and (get-buffer "*Completions*") (get-buffer-window "*Completions*")) ;; Occurs whenever an earlier completion has ;; been asked for. (mupad-restore-wind-conf)) (message "%s is complete" comp)) ;; else display all possible completions... ;; ONLY if no extension has been found. (if (not (string= comp word)) nil (mupad-store-wind-conf) (mupad-info-wind-conf) (with-output-to-temp-buffer "*Completions*" (buffer-disable-undo "*Completions*") (display-completion-list (all-completions word mupad-word-alist)))) ))))) ;; end of mupad-complete. ;;------------------------------- ;; Part IX : Help and Examples. ;;------------------------------- (defun mupad-build-cpl-list nil "This function creates the file 'mupad-cpl-file and initializes 'mupad-word-alist. The buffer is assumed to be *MuPAD* where a mupad-process is running." ;; All identifiers: (mupad-extract-command "anames(3);" nil) (set-buffer "*MuPAD Help*") (goto-char (point-min)) (delete-region (point-min) (re-search-forward "{" nil t)) (while (and (not (looking-at "[ \n]*}")) (re-search-forward "\\(^\\| \\)[a-zA-Z_0-9]" nil t)) (goto-char (match-end 1)) (add-to-list 'mupad-word-alist (buffer-substring (point) (progn (re-search-forward "[,}\n]" nil t) (goto-char (match-beginning 0)))))) ;; Command names: (mupad-extract-command "?*" nil) (set-buffer "*MuPAD Help*") (goto-char (point-min)) (delete-region (point-min) (re-search-forward "Try: " nil t)) (while (not (eobp)) (let ((first-prefix-end (or (save-excursion (re-search-forward "::" nil t)) (point-max))) (first-word-end (save-excursion (if (re-search-forward "[ \n]" nil t) (progn (forward-char -1) (point)) (point-max)))) prefix) (add-to-list 'mupad-word-alist (buffer-substring (point) first-word-end)) (if (< first-prefix-end first-word-end) (add-to-list 'mupad-prefix-alist (buffer-substring (point) (- first-prefix-end 2)))) (if (re-search-forward "[ \n]+[^ \n]" nil t) (goto-char (1- (point))) (goto-char (point-max))))) (setq mupad-word-alist (mapcar 'list mupad-word-alist)) (kill-buffer "*MuPAD Help*") (mupad-save-mupad-word-alist)) (defun mupad-regexp-opt (alist) (if (fboundp 'regexp-opt) (regexp-opt alist) (mapconcat 'regexp-quote alist "\\|"))) (defun mupad-save-mupad-word-alist nil "Saves also 'mupad-prefix-alist." (interactive) ;; Write a full cpl file: (get-buffer-create (file-name-nondirectory mupad-cpl-file)) (erase-buffer) (insert ";; File " (file-truename mupad-cpl-file) ".\n" ";; Created " (current-time-string) "\n" ";; It contains the words used for completion while using mupad.el.\n" ";; If removed, this file will automatically be created when using\n" ";; 'mupad-mode or 'mupad-shell-mode.\n\n" "(setq mupad-word-alist\n'(\n") (let ((who 0)) (while (< who (length mupad-word-alist)) (insert "(\"" (car (nth who mupad-word-alist)) "\")\n") (setq who (1+ who)))) (insert "))\n(setq mupad-prefix-alist\n'(\n") (let ((who 0)) (while (< who (length mupad-prefix-alist)) (insert "\""(nth who mupad-prefix-alist) "\"\n") (setq who (1+ who)))) (insert "))\n;; end of " mupad-cpl-file ". " (number-to-string (+ 13 (length mupad-word-alist) (length mupad-prefix-alist))) " lines.\n") (set-visited-file-name mupad-cpl-file) (save-buffer) (kill-buffer (file-name-nondirectory mupad-cpl-file))) (defun mupad-remove-prefix (astring) (if (string-match "::" astring) (substring astring (match-end 0)) astring)) (defun mupad-from-loaded-libraryp (astring) (member astring (mapcar (lambda (prefix) (concat prefix "::" (mupad-remove-prefix astring))) mupad-prefix-loaded-alist))) (defun mupad-capitalizedp (astring) "t if ASTRING is all in capitals, nil otherwise." (let ((case-fold-search nil)) (if (string-match "[a-z]" astring) nil t))) (defun mupad-remove-empty-strings (alist) (let ((new-list '())) (while alist (or (and (stringp (car alist)) (string-equal (car alist) "")) (setq new-list (cons (car alist) new-list))) (setq alist (cdr alist))) new-list)) (defun mupad-make-primitive-regexp nil (let ((alist-end '()) (beg-list (mapcar 'char-to-string (string-to-list "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"))) (simple-words-list '()) (toexclude (append mupad-prefix-alist mupad-keywords mupad-type-keywords))) (mapcar (lambda (astring) (or (member astring toexclude) (mupad-capitalizedp astring) (add-to-list 'alist-end astring))) (mapcar (lambda (aa) (if (mupad-from-loaded-libraryp aa) (mupad-remove-prefix aa) aa)) (mapcar 'car mupad-word-alist))) ;; Now 'alist-end contains all the names of primitives. ;; We split this list, separating first the primitives ;; that do not come from a library (or from a loaded one): (setq simple-words-list (mupad-remove-empty-strings (mapcar (lambda (astring) (if (string-match "::" astring) "" astring)) alist-end))) (setq simple-words-list (mapcar 'list simple-words-list)) (setq alist-end (mapcar 'list (mupad-remove-empty-strings (mapcar (lambda (astring) (if (member astring simple-words-list) "" astring)) alist-end)))) ;; We now build the three lists: (setq mupad-primitive-regexp-simple (concat "\\<\\(" (mapconcat (lambda (a) a) (mupad-remove-empty-strings (mapcar (lambda (achar) (let ((aa (all-completions achar simple-words-list))) (if aa (mupad-regexp-opt aa) ""))) beg-list)) "\\|") "\\)\\>")) (setq mupad-primitive-regexp-prefix-alist (mupad-remove-empty-strings (mapcar (lambda (aprefix) (let ((aa (all-completions (concat aprefix "::") alist-end))) (if aa (list aprefix (mupad-regexp-opt aa)) ""))) mupad-prefix-alist))) (setq mupad-primitive-regexp (concat "\\<\\(" mupad-primitive-regexp-simple "\\|" (mapconcat (lambda (a) (nth 1 a)) mupad-primitive-regexp-prefix-alist "\\|") "\\)\\>")))) (defun mupad-load-lib nil (cond (mupad-lib-loadedp ;; already done. nil) ((file-exists-p mupad-cpl-file) (setq mupad-lib-loadedp t) (load-file mupad-cpl-file)) (t (save-excursion (setq mupad-lib-loadedp t) ;; 'mupad-background will *not* try to load the library ! (mupad-background) (mupad-build-cpl-list)))) (setq mupad-prefix-regexp (concat "\\<\\(" (mupad-regexp-opt mupad-prefix-alist) "\\)\\>")) (mupad-make-primitive-regexp)) (defun mupad-extend-mupad-word-alist (prefix) "Adds the function names of the library PREFIX to the completion list." (if (not (member prefix mupad-prefix-loaded-alist)) (let ((comp (all-completions prefix mupad-word-alist))) ;; comp is a list of the possible completions; (mapcar (lambda (aword) (if (not (string= aword prefix)) (add-to-list 'mupad-word-alist (list (substring aword (+ 2 (length prefix))))))) (all-completions prefix mupad-word-alist)) ;; add prefix from mupad-prefix-loaded-alist: (add-to-list 'mupad-prefix-loaded-alist prefix)))) (defun mupad-ask-fn-name (question) (save-excursion (let ((orig (point)) bow) (backward-extended-mupadword) (if (= orig (point)) (progn (forward-extended-mupadword) (setq bow (match-beginning 1))) (setq bow (point)) (forward-extended-mupadword)) (let* ((posfuncname (buffer-substring bow (point))) (funcname (completing-read (if (string-equal posfuncname "") (concat question ": ") (concat question " [" posfuncname "]: ")) mupad-word-alist))) (and (string-equal funcname "") (setq funcname posfuncname)) funcname)))) (defun mupad-help () "Like describe-function in lisp-mode, tries to guess which function is interesting for the user and prompts for confirmation, then displays help. This help goes through a MuPAD process... It has to be available !" (interactive) (let ((wind (selected-window)) (funcname (mupad-ask-fn-name "Help about")) (proposal "")) ;; Start a mupad-process if need be: (or (processp mupad-process) (mupad-background)) (mupad-extract-command (concat "?" funcname ";") 'mupad-beginning) ;; We are in the buffer "*MuPAD Help*": (if (not (looking-at "[ \t\n]*Sorry, no help page available for")) (progn (select-window wind) (mupad-info-wind-conf)) (if (search-forward "\nTry: " (point-max) t) (progn (goto-char (match-end 0)) (setq proposal (buffer-substring (point) (progn (end-of-line) (point)))))) (mupad-window-manager "*MuPAD Help*" 'mupad-remove-help-now) ;; It may be a user defined thing: (if (member funcname mupad-keywords) (message (concat funcname " is a keyword." (if (not (string= proposal "")) (concat " You can try: " proposal ".")))) (mupad-extract-command (concat funcname ";") 'mupad-beginning) ;; We are in the buffer "*MuPAD Help*": (if (not (looking-at (concat "[ \t\n]*" funcname))) (progn (select-window wind) (mupad-info-wind-conf)) (mupad-window-manager "*MuPAD Help*" 'mupad-remove-help-now) (message (concat "Sorry ! " funcname " is unknown to me." (if (not (string= proposal "")) (concat " You can try: " proposal "."))))))))) (defun mupad-start-hytex-manual nil (interactive) (shell-command (concat mupad-directory "../bin/hypage" " " mupad-directory "doc/hytex/man_eng"))) ;;------------------ ;; Getting examples ;;------------------ (defun mupad-get-example (this-one subdir) (let (my-buffer) ;; We first work out an admissible name for the file: (save-excursion (set-buffer "*Messages*") (goto-char (point-max)) (insert "\n" this-one) (beginning-of-line) (while (search-forward "/" nil t) (replace-match "-" nil t)) (beginning-of-line) (setq my-buffer (buffer-substring (point) (point-max)))) (find-file my-buffer) (erase-buffer) (insert-file-contents (concat mupad-directory subdir this-one)) (setq major-mode 'mupad-mode) (hilit-rehighlight-buffer) ;; Modify the path of the read command: (goto-char (point-min)) (while (re-search-forward "\\]*>\\) at line <\\([0-9]*\\)>\\s +in file <\\([^\"]*\\)>." string) (setq gud-last-frame (cons (substring string (match-beginning 3) (match-end 3)) (string-to-int (substring string (match-beginning 2) (match-end 2)))))) string) (defun gud-mdx-find-file (f) (find-file-noselect f)) ;;;###autoload (defun mdx (command-line) "Run mdx on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for your debugger." (interactive (list (read-from-minibuffer "Run mdx (like this): " (if (consp gud-mdx-history) (car gud-mdx-history) (concat mupad-command " " ; mupad-args " " should be added. (mupad-possible-file-name))) nil nil '(gud-mdx-history . 1)))) (if (fboundp 'gud-overload-functions) (gud-overload-functions '((gud-massage-args . gud-mdx-massage-args) (gud-marker-filter . gud-mdx-marker-filter) (gud-find-file . gud-mdx-find-file) ))) (gud-common-init command-line 'gud-mdx-massage-args 'gud-mdx-marker-filter 'gud-mdx-find-file) (gud-def gud-break "S %f %l" "\C-b" "Set breakpoint at current line.") (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line") (gud-def gud-step "s" "\C-s" "Step one source line with display.") (gud-def gud-next "n" "\C-n" "Step one line (skip functions).") (gud-def gud-cont "c" "\C-r" "Continue with display.") (gud-def gud-finish "f" "\C-f" "Finish executing current function.") (gud-def gud-up "u %p" "<" "Up N stack frames (numeric arg).") (gud-def gud-down "d %p" ">" "Down N stack frames (numeric arg).") (gud-def gud-print "p %e" "\C-p" "Evaluate perl expression at point.") (setq comint-prompt-regexp "^\\(mdx>\\|>> \\)") (or (member "^/tmp/debug" revert-without-query) (setq revert-without-query (cons "^/tmp/debug" revert-without-query))) (run-hooks 'mupad-mdx-mode-hook) ) (defmacro mdx-help () (` (if mupad-tutorial-requiredp (let ((wind (selected-window))) ;; We either create another window, either switch to another window ;; if there are already at least two of them. (mupad-window-manager "*MuPAD Help*" 'mupad-beginning-temp) (insert " To start mdx: M-x mdx\n" " To get internal help of the debugger: 'h ENTER' in the buffer\n" " To get help on gud: M-h m\n") (select-window wind))))) (defun mupad-mdx nil (interactive) (mdx-help) (mdx (read-from-minibuffer "Run mdx (like this): " (if (consp gud-mdx-history) (car gud-mdx-history) (concat mupad-command " " ;; mupad-args " " should be added. (mupad-possible-file-name))) nil nil '(gud-mdx-history . 1)))) ;;----------------------- ;; Part XII : ReWriting. ;;----------------------- (defun mupad-rewrite-proc (beg end) "The region delimited by BEG and END is a procedure definition. We send it to be evaluated by MuPAD and rewrite it following according to the MuPAD function expose, except that we add a : at the end. The problem is that comments are deleted..." (interactive "r") (save-excursion (goto-char beg) (let (procname) (or (looking-at "\\<\\w+") (forward-word -1)) (setq beg (point)) (forward-word 1) (setq procname (buffer-substring beg (point))) (if (not (looking-at "[ \t\n]*:=[ \t\n]*proc[ \t]*(")) (message "A procedure definition does not start here") ;; Else we try to rewrite this part: ;; Start a mupad-process if required: (or (processp mupad-process) (mupad-background)) (save-excursion (save-restriction (widen) (write-region beg end zap-file nil nil)) (mupad-quiet-command (concat "read(\"" zap-file "\"):")) (mupad-extract-command (concat "expose(" procname ");") nil)) ;; Now, if all went well, the procedure has been rewritten in ;; "*MuPAD Help*". Work a bit on it and transfer it to this file: (let (indent-used newdef) (delete-region beg end) (save-excursion (set-buffer "*MuPAD Help*") ;; Removes empty lines at the beginning: (goto-char (point-min)) (while (looking-at "\n") (delete-char 1)) ;; Computes the indent used: (search-forward "proc" (point-max) t) (setq indent-used (- (point) 5)) ;; Removes empty lines at the end: (goto-char (point-max)) (forward-char -1) (while (looking-at "\n") (delete-char 1) (forward-char -1)) ;; Adds a ":" at the end: (forward-char 1) (insert-char ?: 1) ;; Restores the text that has been cut: (goto-char (point-min)) (while (re-search-forward "\\\\\n" (point-max) t) (replace-match "")) ;; Replaces the indent by the one decided: (goto-char (point-min)) (delete-char indent-used) (insert-char ? mupad-indent-level) (while (and (= (forward-line 1) 0) (not (eobp))) (insert-char ? mupad-indent-level) (delete-char indent-used)) ;; Extracts the proc name: (goto-char (point-min)) (re-search-forward "^[ ]*name \\([^;]*\\);\n" (point-max) t) ;; We should have procname = ;; (buffer-substring (match-beginning 1) (match-end 1)). (delete-region (match-beginning 0) (match-end 0)) (goto-char (point-min)) (insert procname ":=\n") (setq newdef (buffer-substring (point-min) (point-max))) (kill-buffer "*MuPAD Help*")) (insert newdef) (mupad-rehilight-region beg (point))))))) (defun mupad-rewrite-region (st en) "Rewrite all the proc via 'mupad-rewrite-proc." (interactive "r") (save-excursion (goto-char st) ;; Start a mupad-process if required: (or (processp mupad-process) (mupad-background)) (let (prettyprint beg end) (setq prettyprint (mupad-get-prettyprint-value)) (if prettyprint (mupad-set-prettyprint-invisible)) (while (re-search-forward "[ \t\n]*:=[ \t\n]*proc[ \t]*(" en t) (setq beg (match-beginning 0)) (if (not (mupad-within-comment)) (progn (setq end (mupad-find-closing-end_proc)) (if end (progn (mupad-rewrite-proc beg end) ;; We do not rewrite inner proc-definitions: (goto-char end)) (goto-char en))))) (if prettyprint (mupad-set-prettyprint-invisible))))) (defun mupad-rewrite-all nil (interactive) (mupad-rewrite-region (point-min) (point-max))) (defun mupad-expose (afunction) (or (processp mupad-process) (mupad-background)) (mupad-extract-command (concat "expose(" afunction ");") 'mupad-beginning)) (defun mupad-expose-who (afunction) (interactive (list (mupad-ask-fn-name "Function Name"))) (mupad-expose afunction)) (defun mupad-comment-proc (name arguments options) "Inserts javadoc-style comments." (let ((startpos 0)) (insert "/**\n") (insert "* Procedure " name " is not yet documented.\n") (insert "* Insert description for procedure here.\n") (insert "* @AUTHOR " "href=\"mailto:" mupad-user-mail-address "\">" (user-full-name) "\n") (while (string-match " *\\([A-Za-z_]\\w*\\) *" arguments startpos) (insert "* @PARAM " (substring arguments (match-beginning 1) (match-end 1)) " not documented.\n") (setq startpos (match-end 0)) (setq startpos (if (string-match "," arguments startpos) (match-end 0) (length arguments)))) (insert "* @RETURN " "return value not documented.\n") (insert "*/") (mupad-electric-terminate-line) (mupad-force-update-hilit))) (defun mupad-describe-this-proc () "Generate JavaDoc-style comment-header for procedure at cursor." (interactive) (save-excursion (beginning-of-line) (if (looking-at " *\\([A-Za-z_]\\w*\\) *:= *proc*(\\(.*\\))") (let ((name (buffer-substring (match-beginning 1) (match-end 1))) (arguments (buffer-substring (match-beginning 2) (match-end 2))) (options nil) ) (beginning-of-line) (mupad-comment-proc name arguments options)) (message "Cursor is not on a function definition line.")))) ;;-------------------------------- ;; Part XIII : Menu-bar builders. ;;-------------------------------- (defmacro mupad-cmd-to-show-example (anexample subdir) "Build the command to edit anexample." ;; A weird way of programming ... We build a Lisp expression ;; which is a function definition. A kind of automatic programming. (` (list (list 'lambda nil '(interactive) (list (function mupad-get-example) (, anexample) (, subdir)))))) (defmacro mupad-build-example-menu nil "Build the examaples submenu." (` (list (cons "Examples" (cons (cons "First Group" (mapcar (lambda (anexample) (vector anexample (mupad-cmd-to-show-example anexample "examples/") t)) mupad-examples-alist1)) (cons (cons "Second Group" (mapcar (lambda (anexample) (vector anexample (mupad-cmd-to-show-example anexample "examples/") t)) mupad-examples-alist2)) (list (cons "Third Group" (mapcar (lambda (anexample) (vector anexample (mupad-cmd-to-show-example anexample "demo/") t)) mupad-examples-alist3))))))))) (defmacro mupad-build-main-syn-menu nil (` (list (append (list "Shapes" ["Procedure" mupad-proc t]) (if mupad-javadoc-stylep (list ["Describe" mupad-describe-this-proc t]) nil) (list ["Local" mupad-local t] ["Else/Elif" mupad-else t] ["While" mupad-while t] ["For" mupad-for t] "----------------------" ["Title" mupad-title t] ["Modify" mupad-modify t] "----------------------" ["Exclude Area" mupad-exclude-area mark-active] ["Display Comments" mupad-display-comment t] ["/*...*/" mupad-star-comment t] "----------------------" ["Expose" mupad-expose-who t])) (list "ReWrite" ["All" mupad-rewrite-all t] ["Region" mupad-rewrite-region mark-active]) (list "Shortcuts" ["Close Statements" mupad-close-statement t] ["Fun to Proc" mupad-fun-to-proc t]) (list "Indentation" ["Indent Region" mupad-indent-region mark-active] ["Unindent Region" mupad-unindent-region mark-active] ["Forward to same indent" mupad-forward-to-same-indent t] ["Backward to same indent" mupad-backward-to-same-indent t])))) (defmacro mupad-cmd2-to-paint (amupad-place) "Build the command to paint amupad-place according to a read face-name." ;; See the comment attached to 'mupad-cmd-to-paint. (` (list (list 'lambda nil '(interactive) (list (function mupad-store-wind-conf)) (list (function mupad-color-help)) (list 'let (list (list 'temp-name ;; We don't use 'read-face-name because this function ;; forces the user to enter a valid face-name. Here, ;; if the face-name chosen doesn't exist, ;; the default face-name will be used. (list (function read-from-minibuffer) "Use face: ")) (list 'a-face-name nil)) (list 'setq 'a-face-name (list 'intern (list 'if (list 'string= 'temp-name "") '"default" 'temp-name))) (list 'if (list 'string= 'a-face-name "default") (list (function hilit-translate) (, amupad-place) nil) (list (function hilit-translate) (, amupad-place) 'a-face-name)) (list (function setq) 'mupad-colors-modifiedp t) (list (function mupad-update-hilit-buffers)) (list (function mupad-add-to-mupad-colors-alist) 'a-face-name) ;; In fact, one should add a command here to modify the ;; menu-items that presents the colors... ;; It is a good deal of code for an almost empty use. ;; From this point of view, it was also useless to ;; modify 'mupad-colors-alist above... ;; We remove the help. (list 'if 'mupad-tutorial-requiredp (list 'progn (list (function mupad-window-manager) "*MuPAD Help*" ''mupad-remove-help-now-old-config) (list (function mupad-restore-wind-conf)) ))))))) (defmacro mupad-cmd-to-paint (acolor amupad-place) "Build the command to paint amupad-place to acolor." ;; A weird way of programming ... We build a Lisp expression ;; which is a function definition. A kind of automatic programming. (` (list (list 'lambda nil '(interactive) (list (function hilit-translate) (, amupad-place) (list 'quote (, acolor))) (list (function setq) 'mupad-colors-modifiedp t) (list (function mupad-update-hilit-buffers)) (list (function message) "") ;; Clear the minibuffer )))) (defmacro mupad-cmd-to-enable (acolor amupad-place) " Build the command that enable acolor to be chosen in the menu item [MUPAD amupad-place]. A color is enabled if it is not already the one that is being used for this item." ;; See the comment attached to 'mupad-cmd-to-paint. (` (list 'and 'mupad-can-hilit (list 'not (list 'eq (list 'quote (, acolor)) (list (function mupad-place-to-name) (list 'quote (, amupad-place)))))))) (defmacro mupad-build-color-submenu (amupad-place) "Build the Colors submenu. The colors proposed are the one of the list 'mupad-colors-alist" (` (append (mapcar (lambda (acolor) (vector (if acolor (symbol-name acolor) 'default) (mupad-cmd-to-paint acolor (, amupad-place)) (mupad-cmd-to-enable acolor (, amupad-place)))) mupad-colors-alist) (list "----------------") (list (vector "Other..." (mupad-cmd2-to-paint (, amupad-place)) 'mupad-can-hilit))))) (defmacro mupad-build-color-menu nil "Build the Colors menu" (` (if (not (eq mupad-color-menu-list nil)) mupad-color-menu-list (setq mupad-color-menu-list (list (if (and (eq window-system 'x) (x-display-color-p)) (append (list "Colors") ;; There is an entry for each pattern to be colored. ;; A list of these items can be found in mupad-places-alist. ;; The colors proposed are the ones of 'mupad-colors-alist. ;; The only color that is not choose-able (in grey) ;; is the one already used. (list ["Update locally" mupad-force-update-hilit mupad-can-hilit] ["Update" hilit-recenter mupad-can-hilit]) mupad-separator (mapcar (lambda (aquoted-mupad-place) (cons (substring (upcase-initials (symbol-name (eval aquoted-mupad-place))) 6) (mupad-build-color-submenu (eval aquoted-mupad-place)))) mupad-places-alist) (list "------------------------------------------" ;; In order to save the changes made in the file mupad-colors. ["Save" mupad-save-colors mupad-colors-modifiedp] ["Hilit Switch" mupad-hilit-switch t] ["Rehilit All" mupad-update-hilit-buffers mupad-can-hilit])))))))) ;;---------------------------- ;; Add a menu to the menu-bar. ;;---------------------------- (defmacro mupad-menu-bar () "Menu-bar item MuPAD" (` (append (list "MuPAD") (if (equal major-mode 'mupad-mode) (list ["Start MuPAD" mupad-start t]) nil) (list (list "Run MuPAD on file..." ["Silently" mupad-file t] ["Openly" mupad-execute-file t])) (if (equal major-mode 'mupad-mode) (list ["Run MuPAD in region" mupad-region mark-active]) nil) (if (equal major-mode 'mupad-shell-mode) (list ["Interrupt" mupad-interrupt (processp mupad-process)]) nil) (list ["Kill MuPAD session" mupad-kill-job (processp mupad-process)] "---------------------") (if (equal major-mode 'mupad-mode) (append (mupad-build-main-syn-menu) mupad-separator) nil) (list ["Help on ..." mupad-help t] ["HyTeX Manual" mupad-start-hytex-manual t]) (if mupad-tutorial-requiredp (mupad-build-example-menu) nil) mupad-separator (list (list "Graph" ["VCam On..." mupad-start-vcam t])) (list ["Debug..." mupad-mdx t]) (mupad-build-color-menu) (list (append (list "Environment" ["Set DIGITS..." mupad-set-digits (processp mupad-process)] ["PRETTY_PRINT switch" mupad-set-prettyprint-switch (processp mupad-process)] ["Adapt TEXTWIDTH" mupad-adapt-textwidth (processp mupad-process)] "--------------------" ["Exchange Keys" mupad-toggle t]) (if (equal major-mode 'mupad-mode) (list ["Electric-semi-mode Switch" mupad-electric-switch t] ["Automatic Braces Switch" mupad-open-brace-switch t]) nil) (if (and (equal major-mode 'mupad-shell-mode) (not mupad-forcefully-lock-shell-modep)) (list ["Locked Mode Switch" mupad-lock-shell-modep-switch t]) nil))) ) )) (defun mupad-init-menu-bar () "Add menu-bar item MuPAD in mupad-mode" (if (and (featurep 'easymenu) (eq MuPAD-menu-map nil)) (easy-menu-define MuPAD-menu-map mupad-mode-map "Menu-bar item used under mupad-mode" (mupad-menu-bar)))) (defun mupad-init-shell-menu-bar () "Add menu-bar item MuPAD in mupad-shell-mode" (if (and (featurep 'easymenu) (eq MuPAD-shell-menu-map nil)) (easy-menu-define MuPAD-shell-menu-map mupad-shell-map "Menu-bar item used under mupad-mode" (mupad-menu-bar)))) ;; mupad.el ends here. 3600 lines