;;;; A syntax highlighting and indentation mode for the altarica language (defvar altarica-mode-hook nil) (add-to-list 'auto-mode-alist '("\\.alt\\'" . altarica-mode)) ;; define keyword classes (setq altarica-struct-regexp (regexp-opt '("node" "edon" "domain" "const" "in" "out" "flow" "state" "assert" "event" "trans" "extern" "init" "param" "param_set" "sort" "sub" "struct" "tcurts" "sync") 'words)) (setq altarica-builtin-regexp (regexp-opt '("and" "or" "not" "imply" "max" "min" "mod" "sig" "if" "then" "else" "case" "esac" "law" "constant" "exponential" "dirac") 'words)) (setq altarica-type-regexp (regexp-opt '("int" "integer" "bool") 'words)) (setq altarica-bconstants-regexp (regexp-opt '("true" "false") 'words)) (setq altarica-nconstants-regexp "[[:digit:]]+\\(.[[:digit:]]+\\)?") (setq altarica-font-lock-keywords `((,altarica-struct-regexp . font-lock-keyword-face) (,altarica-builtin-regexp . font-lock-builtin-face) (,altarica-type-regexp . font-lock-type-face) (,altarica-bconstants-regexp . font-lock-constant-face) (,altarica-nconstants-regexp . font-lock-constant-face) ;; highlight transition symbols (,"\\(|-[^-]*->\\)" . font-lock-function-name-face) ;; bold assignments and question marks (,"\\(\\?\\|:=\\)" (1 '(:weight bold))) ;; highlight types in domain declaration (,"domain[ \t]+\\([[:alnum:]_]+\\)" (1 font-lock-type-face)) ;; highlight types in node declaration (,"node[ \t]+\\([[:alnum:]_]+\\)" (1 font-lock-type-face)) ;; highlight types in state/sub declaration (,(concat "^[ \t]*\\(sub\\|state\\)?" "[ \t]*[[:alnum:]_]+[ \t]*:" "[ \t]*\\([[:alnum:]_]+\\)[ \t]*;") (2 font-lock-type-face)) ;; highlight types in flow declaration (,(concat "[ \t]*\\(flow\\)?" "[ \t]*[[:alnum:]_]+[ \t]*:" "[ \t]*\\([[:alnum:]_]+\\)[ \t]*:" "[ \t]*\\(in\\|out\\)[ \t]*;") (2 font-lock-type-face)))) (defvar altarica-basic-offset 2) (defun altarica-indent-line () "Indent current line as altarica code" (interactive) ;; without this indent-line-to moves the point to beginning of line (let ((altarica-kw-main "^[ \t]*\\(node\\|domain\\|const\\|edon\\)\\([^a-zA-Z_0-9].*\\)?$") (altarica-kw-secondary (concat "^[ \t]*\\(flow\\|state\\|assert\\|" "event\\|trans\\|init\\|extern\\|sub\\|sync\\)")) (indent-unit altarica-basic-offset) next-indent) (save-excursion (beginning-of-line) (setq next-indent (cond ((bobp) 0) ((looking-at altarica-kw-main) 0) ((looking-at altarica-kw-secondary) indent-unit) ((looking-at "^[ \t]*|-") (* 3 indent-unit)) (t nil))) (if (not next-indent) (progn (while (not next-indent) (forward-line -1) (setq next-indent (cond ((bobp) 0) ;; previous line is primary keyword ((looking-at altarica-kw-main) indent-unit) ;; previous line is secondary keyword ((looking-at altarica-kw-secondary) (* 2 indent-unit)) ;; previous line ends with semicolon ((looking-at ".*;[ \t]*$") (* 2 indent-unit)) ;; previous line ends with "->" ((looking-at ".*->[ \t]*$") (* 4 indent-unit)) ;; previous line contains "->" ((re-search-forward "->[ \t]*" (line-end-position) t) (current-column)) ;; previous line contains "|-" ((looking-at "^[ \t]*|-") (* 4 indent-unit)) ;; previous line ends with "case { " ((re-search-forward "case[ \t]*{[ \t]*$" (line-end-position) t) (+ 2 (- (match-beginning 0) (line-beginning-position)))) ;; previous line contains "case { " ((re-search-forward "case[ \t]*{[ \t]*" (line-end-position) t) (current-column)) ;; else look at previous previous line (t nil))))))) (setq offset (max 0 (- (current-column) (current-indentation)))) (indent-line-to next-indent) (move-to-column (+ (current-indentation) offset)))) ;; command to comment/uncomment text (defun altarica-comment-dwim (arg) "Comment or uncomment current line or region in a smart way. For detail, see `comment-dwim'." (interactive "*P") (require 'newcomment) (let ((comment-start "//") (comment-end "")) (comment-dwim arg))) ;; Syntax table magic ... yadda yadda abracadabra ... COMMENTS !! (defvar altarica-syntax-table nil "Syntax table for `altarica-mode'.") (setq altarica-syntax-table (let ((table (make-syntax-table))) ;; make underscore a word char (modify-syntax-entry ?_ "w" table) ;; detect c++ comments (modify-syntax-entry ?/ ". 124" table) (modify-syntax-entry ?* ". 23b" table) (modify-syntax-entry ?\n ">" table) table)) ;; define the mode (define-derived-mode altarica-mode fundamental-mode "Major mode for editing altarica" (set-syntax-table altarica-syntax-table) (setq font-lock-defaults '(altarica-font-lock-keywords)) (setq indent-line-function 'altarica-indent-line) (setq mode-name "altarica mode") ;; modify the keymap (define-key altarica-mode-map [remap comment-dwim] 'altarica-comment-dwim) ;; clear memory (setq altarica-struct-regexp nil) (setq altarica-func-regexp nil) (setq altarica-builtin-regexp nil) (setq altarica-type-regexp nil) (setq altarica-constants-regexp nil) (setq altarica-symbols-regexp nil) )