;;; fpscalc-mode.el --- Major mode for fpscalc's .fps files -*- lexical-binding: t -*- ;; ;;; Commentary: ;; ;; Author: Emanuel Berg (incal) ;; Created: 2014-07-03 ;; Keywords: unix ;; License: GPL3+ ;; URL: https://dataswamp.org/~incal/fps/fpscalc.el ;; Version: 3.3.2 ;; ;; fpscalc.el is an Emacs major mode for the tool fpscalc [1] ;; to edit .fps files [2]. See [3] for screenshots. ;; ;; Features: ;; ;; - font-lock with configurable fonts ;; ;; - [un]comment with M-; ;; ;; - indentation ;; ;; - the mode is associated with the .fps extension ;; ;; In the package directory is also some LaTeX [4] how to ;; create diagrams using the pgfgantt package [5], diagrams ;; which can be used to illustrate fpscalc task flows. ;; ;; Use the fpscalc executable for example like this: ;; ;; data=$1 ;; ext=.fps ;; sys=$(basename $data $ext) ;; fpscalc < ${sys}${ext} > ${sys}-fallout.txt ;; ;; [1] http://www.idt.mdh.se/~ael01/fpscalc ;; ;; [2] https://dataswamp.org/~incal/fps/demo.fps ;; ;; [3] https://dataswamp.org/~incal/fps/fpscalc.png ;; https://dataswamp.org/~incal/fps/cis/cis.png ;; ;; [4] https://dataswamp.org/~incal/fps/cis/ ;; ;; [5] https://ctan.org/pkg/pgfgantt?lang=en ;; ;;; Code: (define-abbrev-table 'fpscalc-mode-abbrev-table '(("init" "initialise") ("prio" "priority") )) (defgroup fpscalc nil "`fpscalc' mode." :group 'local) (defgroup fpscalc-faces nil "`fpscalc' faces." :group 'fpscalc :group 'faces) (defface fpscalc-comment-delimiter '((t :inherit font-lock-comment-delimiter-face :background "black" :foreground "blue" :bold t) ) "`fpscalc' comment delimiter face.") (defface fpscalc-comment '((t :inherit font-lock-comment-face :background "black" :foreground "blue" :bold t) ) "`fpscalc' comment face.") (defface fpscalc-math-functions '((t :inherit font-lock-function-name-face :background "black" :foreground "red" :bold t) ) "`fpscalc' math functions: ceiling, floor, max, min, and sigma.") (defface fpscalc-program-parts '((t :inherit font-lock-keyword-face :background "black" :foreground "magenta" :bold t) ) "`fpscalc' program parts: formulas, declarations, initialise and semaphores.") (defface fpscalc-semaphore-keyword '((t :inherit font-lock-keyword-face :background "black" :foreground "blue" :bold nil) ) "`fpscalc' keyword \"semaphore\".") (defface fpscalc-semaphore-name '((t :inherit font-lock-variable-name-face :background "black" :foreground "yellow" :bold t) ) "`fpscalc' semaphore name.") (defface fpscalc-system-keyword '((t :inherit font-lock-keyword-face :background "black" :foreground "green" :bold t) ) "`fpscalc' keyword \"system\".") (defface fpscalc-system-name '((t :inherit font-lock-doc-face :background "black" :foreground "yellow" :bold nil) ) "`fpscalc' system name.") (defface fpscalc-task-i '((t :inherit font-lock-constant-face :background "black" :foreground "yellow" :bold t) ) "`fpscalc' task i.") (defface fpscalc-task-j '((t :inherit font-lock-constant-face :background "black" :foreground "blue" :bold t) ) "`fpscalc' task j.") (defface fpscalc-task-name-and-index '((t :inherit font-lock-variable-name-face :background "black" :foreground "cyan" :bold nil) ) "`fpscalc' task names and index.") (defface fpscalc-task-priority-sets '((t :inherit font-lock-builtin-face :background "black" :foreground "magenta" :bold nil) ) "`fpscalc' task priorities: all, ep, hp and lp.") (defface fpscalc-tasks-keyword '((t :inherit font-lock-keyword-face :background "black" :foreground "blue") ) "`fpscalc' keyword \"tasks\".") (defface fpscalc-variable-name '((t :inherit font-lock-variable-name-face :background "black" :foreground "green" :bold t) ) "`fpscalc' blocking indexed priority scalar name.") (defface fpscalc-variable-type '((t :inherit font-lock-type-face :background "black" :foreground "yellow" :bold t) ) "`fpscalc' variable types: blocking, indexed, priority and scalar.") (defvar fpscalc-keywords '(("\\(\\(!\\).*$\\)" (1 'fpscalc-comment-delimiter) (2 'fpscalc-comment) ) ("\\(semaphore\\)\\((\\)\\([[:word:]]+\\)\\(\\, \\)\\([[:word:]]+\\)" (1 'fpscalc-semaphore-keyword) (3 'fpscalc-semaphore-name) (5 'fpscalc-task-name-and-index) ) ("declarations\\|formulas\\|initialise\\|semaphores" . 'fpscalc-program-parts) ("ceiling\\|floor\\|min\\|max\\|sigma" . 'fpscalc-math-functions) ("all\\|ep\\|hp\\|lp" . 'fpscalc-task-priority-sets) ("\\([[:word:]]\\)\\(\\[\\)\\(i\\)\\(\\]\\)" (1 'fpscalc-variable-name) (3 'fpscalc-task-i) ) ("\\([[:word:]]\\)\\(\\[\\)\\(j\\)\\(\\]\\)" (1 'fpscalc-variable-name) (3 'fpscalc-task-j) ) ("\\([[:word:]]\\)\\(\\[\\)\\(.*\\)\\(\\]\\)" (1 'fpscalc-variable-name) (3 'fpscalc-task-name-and-index) ) ("\\(system \\)\\(.* \\)" (1 'fpscalc-system-keyword) (2 'fpscalc-system-name) ) ("\\(blocking\\|indexed\\|priority\\|scalar\\)\\( \\)+\\(\\(\\([[:word:]]\\( *\\, *\\)?\\)\\)*\\)" (1 'fpscalc-variable-type) (3 'fpscalc-variable-name) ) ("\\(tasks +\\)\\(\\(\\([[:word:]]\\( *\\, *\\)?\\)\\)*\\)" (1 'fpscalc-tasks-keyword) (2 'fpscalc-task-name-and-index) ))) (define-generic-mode fpscalc-mode '("!") nil fpscalc-keywords '("\\.fps\\'") '((lambda () (setq indent-line-function #'fpscalc-indent-line) )) "Major mode for .fps files used with the fpscalc tool.") (defvar fpscalc-mode-map (let ((kmap (make-keymap))) (define-key kmap "\t" #'newline-and-indent) kmap) "`fpscalc-mode' keymap.") (defvar fpscalc-mode-syntax-table (let ((syntax-table (make-syntax-table))) (modify-syntax-entry ?! "< b" syntax-table) (modify-syntax-entry ?\n "> b" syntax-table) syntax-table) "`fpscalc-mode' syntax table.") (defcustom fpscalc-command-name "fpscalc" "`fpscalc' executable." :type 'file) (defun fpscalc-indent-line () "`fpscalc' indentation function." (interactive) (beginning-of-line) (if (bobp) (indent-line-to 0) (let ((not-indented t) (cur-indent 0) (indent-unit 2)) (if (looking-at "^[ \t]*}") (progn (save-excursion (forward-line -1) (setq cur-indent (- (current-indentation) indent-unit) )) (when (< cur-indent 0) (setq cur-indent 0) )) (save-excursion (while not-indented (forward-line -1) (if (looking-at "^[ \t]*}") (progn (setq cur-indent (current-indentation)) (setq not-indented nil) ) (if (looking-at "^[ \t]*\\(system\\|declarations\\|semaphores\\|initialise\\|formulas\\)") (progn (setq cur-indent (+ (current-indentation) indent-unit)) (setq not-indented nil) ) (when (bobp) (setq not-indented nil) )))))) (indent-line-to cur-indent) ))) (provide 'fpscalc) ;;; fpscalc.el ends here