;; File : ZeBuLoN.el ;; This is emacs' config file for ZeBuLoN input files. ;; To install it, ;; - either add the command (load "path_to_this_file/ZeBuLoN") in your ~/.emacs file. ;; - or both commands : ;; (setq load-path (append (list "path_to_the_file") load-path)) ;; (load "ZeBuLoN") ;; - or use the 'autoload on demand' mechanism (not documented here) ;; ;; ;; JDG 12/06/2005 ;; Last modif 13 jan. 2006 ;; The main inspiration when writing this mode came from ;; http://www.emacswiki.org/ (esp. define-generic-mode and defface) ;; http://two-wugs.net/emacs/mode-tutorial.html ;; http://www.gnu.org/software/emacs/#Manuals (emacs manual and elisp reference) ;; http://www.cs.elte.hu/local/texinfo/emacs/emacs_16.html#SEC85 (regexp and syntax tables in emacs) ;; and of course from emacs' help (C-h) and (C-h f) ;;; Todo-list : ;; add M-n='goto-next-n-stars-block' and 'M-previous' ... ;; failproof the indent function ;; complete the list of keywords ;; rewrite this as a derived mode, and add a syntax list (is this really useful ?) ;; add an indent-region-function (see elisp-reference manual, sec 32.17.3) ;; see what can be done with "time" and "*time" and U1 R2 W3 ;; add dark-background colors, etc ... ;; teach it the default values of some instructions (?), so that it suggests newton after a ***resolution ;; C-c C-e : inserts a-la-LaTeX a bloc ****mesher with its default options !!! ;; M-o pour ouvrir le fichier materiau ou geof qui est sous le curseur ;; add RU1-3 as reactions, in a slightly different color from R1-3 (say font-lock-DOFs-face and font-lock-derived-variable-face) ;; 'help-on-keyword should open the manual at the right page ;; and not open an *Async shell output* (semi-fixed) ;; complete the 'local-set-key list ;; look up the load-on-demand ... ;; add a Z-menu ;; add a (M-x Zrun) command (detects whether its a -m , -o , -g .... ) ==> (partly) done, see bug list and merge it with the (M-x Zmaster) command ;; improve the 'open' command by something like (mouse-face highlight help-echo "M-o: visit this file in other window") (from dired.el:745) ;; see what can be done with completing-read (proposes a choice list ...) ;; make a "table of contents", à la reftex ;; lancer une regexp-optimize sur la liste de keywords ; mettre une couleur differente pour les keywords peu importants. ;;; Bug-list : ;; it looks like there's a problem with <TAB> chars : if a buffer is opened in Z-mode, other buffers (e.g. fundamental ones) also apply this "replace TAB by space" ... ;; regexp seem to work differently on SGI-Unix (has got emacs 20.4.2) ;; pretty-print function is not working ;; handle an error return from the function guess-option-for-Zrun (more precisely from the search for ****) ;; ;;;; code starts here (defalias 'zebulon-mode 'ZeBuLoN-mode) ;; .z7p files should be highlighted as c++ : (add-to-list 'auto-mode-alist '("\\.z7p\\'" . c++-mode)) (define-generic-mode 'ZeBuLoN-mode ;; see "M-x help f define-generic-mode" for help on this command '("%" "#") ;; comment characters ; according to zman user, "//" is not a comment '("ALL_ELEMENT" "ALL_NODE" "newton" "eeeeee" "p1p1p1" "p1p2p2" "p1p2p3" "TP" "PR" "EZ" "plane_stress" "plane_strain" "absolu" "classic_updated_lagrangian" "linear_elastic" "gen_evp" "lagrange_rotate_no_J" ) ;; list of keywords to highlight. '( ;; patterns to highlight ("\t" . 'highlight) ;; dangerous <TAB> characters are highlighted ("\\(func\\(tion\\)? \\)\\(.*;\\)" 3 'font-lock-ZeBuLoNfunc-face keep t) ;; see elisp-reference sec 23.5.2 (explains the '3' keep and t ) ("\\*\\{4\\} *[[:alnum:]_]+ *[[:alnum:]_]*" . 'font-lock-ZeBuLoN4star-face) ;;****keywords ("\\*\\{3\\} *[[:alnum:]_]+" . 'font-lock-ZeBuLoN3star-face) ;; highlighting ***keywords ("\\*\\{2\\} *[[:alnum:]_]+" . 'font-lock-ZeBuLoN2star-face) ;; highlighting **keywords ("\\*\\{1\\} *[[:alnum:]_]+" . 'font-lock-ZeBuLoN1star-face) ;; highlighting **keywords ; ("\\*\\{1\\} *\\w+" . 'font-lock-ZeBuLoN1star-face) ;; highlighting *keywords ... \\w+ means "a whole word" (this is based on the syntax-table) ;old version : ("^ *\\*\\{1\\} *[[:alnum:]_]+" . 'font-lock-ZeBuLoN1star-face) ;; highlighting *keywords ("\\<time\\>" . 'font-lock-keyword-face) ;; si je le mets dans la liste de keywords (cad en tete), *time est mal colore ; \\<...\\> signifie "mots complets" ("\\<constant\\>" . 'font-lock-keyword-face) ;; idem ("\\<[URW][1-3]\\>" . 'font-lock-keyword-face) ; DOF names (cf. zman user, p.326 DOFs). Dans la liste des keywords, une regexp ne passe pas ? ) '(".inp\\'" ".geof\\'" ".mat\\'" ".mast\\'") ;; file-names patterns (list ;; additional setup functions : (lambda () (set (make-local-variable 'indent-tabs-mode) nil) ) ;; replace <TAB> by spaces ;;; (lambda () (setq default-tab-width 1)) ;; size of indentation (lambda () (set (make-local-variable 'tab-width) 1)) (lambda () (set (make-local-variable 'indent-line-function) 'ZeBuLoN-indent-line)) (lambda () (local-set-key [f1] 'ZeBuLoN-help-on-keyword)) (lambda () (local-set-key "\M-o" 'ZeBuLoN-find-file-under-cursor)) (lambda () (setq mode-name "ZeBuLoN")) ; (lambda () (modify-syntax-entry ?_ "w")) ; on lui apprend que l'underscore est un caractere constituant les mots (lambda () (message "Welcome to ZeBuLoN mode. Type 'C-h m' to get some help.")) ) "Major mode for editing ZeBuLoN files (.inp .geof .mat). Version 1.0 (12 june 2005) Features : - highlights ***keywords - puts functions in italics (requires the terminating semicolon ;) - indentation - recognizes a few common keywords - etc ... (see features.inp) Please report bugs and suggest improvements to jean-didier[dot]garaud[at]onera[dot]fr " ) ;;; the next section is about indentation : (defun ZeBuLoN-line-is-blank () "Returns t if line is blank ... the function should already exist, but I couldn't find it !" (save-excursion (beginning-of-line) (looking-at "^[[:blank:]]*$") ) ) (defun ZeBuLoN-line-is-a-comment () "Returns t if line is a comment ... again, the function should already exist, but I couldn't find it !" (save-excursion (beginning-of-line) (looking-at "^[[:blank:]]*\\(%\\|#\\)") ; (looking-at "^[[:blank:]]*%") ;originally ) ) (defun ZeBuLoN-count-stars () "Returns the number of stars at the beginning of the current line." ; (interactive) (save-excursion (beginning-of-line) (cond ( (looking-at "^ *\\*\\{4\\}") 4 ) ( (looking-at "^ *\\*\\{3\\}") 3 ) ( (looking-at "^ *\\*\\{2\\}") 2 ) ( (looking-at "^ *\\*\\{1\\}") 1 ) ( t 0 ) ) ) ) (defun ZeBuLoN-indent-line-simple () "A simple 'indent current line' for ZeBuLoN files, according to the number of stars." (interactive) ;; means i can do M-x ZeBuLoN-indent-line-simple in emacs (save-excursion ;;keep cursor position while indenting (indent-line-to (- 4 (ZeBuLoN-count-stars))) ) ) (defun ZeBuLoN-indent-line () "Indent current line for ZeBuLoN files, aligning it with the previous same star-level entry." (interactive) (when (not (ZeBuLoN-line-is-a-comment)) ;; we do not want to indent comment lines ( (when ..) is an (if..) without the 'else' part) (if (ZeBuLoN-line-is-blank) (indent-line-to 0) ; <- if line is blank ; else : (let ((cur-indent 0) (not-indented t) (star-lvl (ZeBuLoN-count-stars)) ) (save-excursion (beginning-of-line) (while (and not-indented (not (bobp))) (forward-line -1) (when (and (not (ZeBuLoN-line-is-blank)) (not (ZeBuLoN-line-is-a-comment)) (<= star-lvl (ZeBuLoN-count-stars))) ; we ignore blank and comment lines (setq not-indented nil) (setq cur-indent (+ (current-indentation) (* tab-width (- (ZeBuLoN-count-stars) star-lvl)))) ;; (message "indenting to %d" cur-indent) ) ) ); end of save-excursion, so we return to the actual line (save-excursion (indent-line-to cur-indent) ) ; do the actual indenting ; the save-excursion keeps the cursor under the correct character ) ; end of let ) ) ) ;;; the next section is about help and Zman (defun ZeBuLoN-keyword-under-cursor () "Returns the word under the cursor, presuming it is a Z-keyword (i.e. only contains [*\-a-zA-Z0-9/_.] characters). The function certainly already exists somewhere ? (yes : it's called current-word ) " ; (interactive) (save-excursion (let ( (beg (+ (point) (skip-chars-backward "a-zA-Z0-9_."))) (end (+ (point) (skip-chars-forward "a-zA-Z0-9_."))) ) (buffer-substring-no-properties beg end) ) ) ) (defun ZeBuLoN-help-on-keyword () "Runs zman user, and (not yet) opens a 'find' window containing the current word ... pas encore au point ... " (interactive) (message "Looking for help on keyword : %s" (ZeBuLoN-keyword-under-cursor)) (shell-command "zman user &") ; todo : recherche le mot courant (delete-other-windows) ; pour ne pas que la fenetre Asynx shell output n'apparaisse ... pas encore au point, si 2fenetres etaient ouvertes ) ;;; the next section is about sub-files quick opening (defun ZeBuLoN-filename-under-cursor () "Returns the word under the cursor, presuming it is a filename." ; (interactive) (save-excursion (let ( (beg (+ (point) (skip-chars-backward "\-a-zA-Z0-9/~_."))) (end (+ (point) (skip-chars-forward "\-a-zA-Z0-9/~_."))) ) (buffer-substring-no-properties beg end) ) ) ) (defun ZeBuLoN-find-file-under-cursor () "Finds the file whose name is under the cursor (e.g. the geof or material file)." (interactive) (let ( (filename (ZeBuLoN-filename-under-cursor)) (buffername (file-name-nondirectory (ZeBuLoN-filename-under-cursor))) ; (file-name-nondirectory filename) ne passe pas : cf l'aide de (let ...) : les variables sont initialisees en qq sorte d'un bloc, et pas les unes apres les autres . ) (if (buffer-live-p (get-buffer buffername)) (progn (message "Displaying %s" buffername) (display-buffer buffername) ; better than pop-buffer, because focus remains on the first file ) (if (file-readable-p filename) (progn ; (find-file-other-window filename) (find-file-noselect filename) (display-buffer buffername) (message "Opening %s. Type C-x 1 to hide new window." (file-truename filename)) ) (message "File '%s' doesn't exist or is not readable (in directory %s)" filename (file-name-directory (file-truename filename))) ) ) ) ) ;;; the next section is about the Zrun command : (defun Zrun () "Zruns the current file, trying to guess the right options. " (interactive) ; todo : ajouter un prompt argument pour les command line options ; ; apparemment la doc de l'emacs refcard a un exemple qui utilise les prefix : (interactive "P") ... (prefix-numeric-value delargument) ; voir aussi l'aide de prefix-numeric-value (let ( (lacommande (concat "Zrun " (ZeBuLoN-select-right-option-for-Zrun) (buffer-name) " &" ) ) ) (when (buffer-modified-p) (when (y-or-n-p "Save current buffer? ") (save-buffer) ) ) (shell-command (read-from-minibuffer "Run command: " lacommande) (concat "*" lacommande " output*") ) ) ) (defun Zmaster () "Zmasters the current file, trying to guess the right options. " (interactive) ; todo : ajouter un prompt argument pour les command line options ; ; apparemment la doc de l'emacs refcard a un exemple qui utilise les prefix : (interactive "P") ... (prefix-numeric-value delargument) ; voir aussi l'aide de prefix-numeric-value (let ( (lacommande (concat "Zmaster " (buffer-name) " &" ) ) ) (when (buffer-modified-p) (when (y-or-n-p "Save current buffer? ") (save-buffer) ) ) (shell-command (read-from-minibuffer "Run command: " lacommande) (concat "*" lacommande " output*") ) ) ) (defun ZeBuLoN-type-of-inp-file () "Returns the first ****command it finds" ;; ici, en utilisant (file-name-extension (buffer-name) t), je pourrais verifier que j'ai bien un fichier .inp ... (save-excursion (goto-char (point-min)) ; goes to the beginning of file (search-forward "****") (ZeBuLoN-filename-under-cursor) ; happens to do exactly what i need ... current-word should also be ok ... ) ) (defun ZeBuLoN-select-right-option-for-Zrun () "This function knows the right option for each type of .inp file, in order too provide it to `Zrun'." (let ( (ftype (ZeBuLoN-type-of-inp-file)) ) (cond ;;;; i should make a list of correspondance btw types and options to be more emacs-like ((string-equal ftype "calcul") "" ) ((string-equal ftype "mesher") "-m ") ; l'espace est important ! ((string-equal ftype "optimize") "-o ") ((string-equal ftype "post_processing") "-pp ") (t (message "This type of .inp file is not recognized. Sorry, but I cannot suggest the right option for Zrun.") "" ) ;; should add a message to tech emacs ? ) ) ) ;;; the next sectio is about printing ... but is buggy right now ;; (defun ZeBuLoN-pretty-print () ;; "Prints to file, using font-faces" ;; (interactive) ;; (ps-print-buffer-with-faces "~/toto.ps") ;; ) ;;; the next section is about COLORS !! ; M-x list-colors-display to get a list of available colors... ; can also be customized from emacs : M-x customize-face (defface font-lock-ZeBuLoN4star-face '( ; ( ((background dark)) (:foreground "SeaGreen3" :bold t) ) ( ((background dark)) (:foreground "Gold" :bold t) ) ( t (:foreground "DarkBlue" :bold t )) ) "Font Lock mode face used to highlight ****keywords." :group 'font-lock-highlighting-faces) (defface font-lock-ZeBuLoN3star-face '( ( ((background dark)) (:foreground "chartreuse") ) (t (:foreground "Blue" )) ) "Font Lock mode face used to highlight ***keywords." :group 'font-lock-highlighting-faces) (defface font-lock-ZeBuLoN2star-face '( ( ((background dark)) (:foreground "aquamarine") ) ; "deep sky blue" (t (:foreground "DarkGreen")) ) "Font Lock mode face used to highlight **keywords." :group 'font-lock-highlighting-faces) (defface font-lock-ZeBuLoN1star-face '( ( ((background dark)) (:foreground "SkyBlue1") ) ; "LightSeaGreen" (t (:foreground "DarkCyan")) ) "Font Lock mode face used to highlight *keywords." :group 'font-lock-highlighting-faces) (defface font-lock-ZeBuLoNfunc-face '( (((class color) (background light)) (:foreground "DimGrey" :italic t)) (((class color) (background dark)) (:foreground "Light Grey" :italic t)) (t (:italic t)) ) "Font Lock mode face used to highlight functions." :group 'font-lock-highlighting-faces) ;;;; and code finishes here