comments, modul operators, mark error messages

- add comments
- add keybord shortcuts
- add modul operators (from naturals, sequences)
- add functions to mark error messages in the SANY
  check buffer.
This commit is contained in:
Christian Barthel 2019-12-26 08:16:03 +01:00
parent 87707476af
commit c58bbb6671
1 changed files with 383 additions and 75 deletions

View File

@ -26,6 +26,10 @@
;;; Code:
;; -------------------------------------------------------------------
;; Customization variables:
(defcustom tla+-mode-hook '()
"Normal hook run when entering TLA+ mode."
:type 'hook
@ -55,21 +59,185 @@
:type 'file
:group 'tla+)
;; -------------------------------------------------------------------------------
(defvar tla+-mode-map
(let
((map (make-sparse-keymap))
(menu-map (make-sparse-keymap "TLA+"))
(operator-map (make-sparse-keymap))
(action-operator-map (make-sparse-keymap))
(temporal-operator-map (make-sparse-keymap))
(export-map (make-sparse-keymap)))
(export-map (make-sparse-keymap))
(modul-operators (make-sparse-keymap))
(modul-sequences-operators (make-sparse-keymap))
(modul-naturals-operators (make-sparse-keymap))
)
(set-keymap-parent map lisp-mode-shared-map)
(define-key map "\e\t" 'ispell-complete-word)
(define-key map (kbd "C-c C-t e") 'tla+-run-tlatex-dvi)
(define-key map (kbd "C-c C-t o") 'tla+-open-dvi)
(define-key map (kbd "C-c C-t c") 'tla+-run-sany)
;; Main TLA+ Menu:
(bindings--define-key map [menu-bar tla+]
(cons "TLA+" menu-map))
;; Modul Operators
(bindings--define-key menu-map [modul-operators]
(cons "Insert Modul Operator.." modul-operators))
;; Naturals Operators
(bindings--define-key modul-operators
[modul-naturals-operator]
(cons "Naturals" modul-naturals-operators))
(bindings--define-key
modul-naturals-operators [add-nat]
'(menu-item "+"
(lambda () (interactive)
(insert "+"))
:help "Addition"))
(bindings--define-key
modul-naturals-operators [sub-nat]
'(menu-item "-"
(lambda () (interactive)
(insert "-")
(backward-char 2))
:help "Subtraction"))
(bindings--define-key
modul-naturals-operators [mult-nat]
'(menu-item "*"
(lambda () (interactive)
(insert "*"))
:help "Multiplication"))
(bindings--define-key
modul-naturals-operators [div-nat]
'(menu-item "/"
(lambda () (interactive)
(insert "/"))
:help "Division"))
(bindings--define-key
modul-naturals-operators [exp-nat]
'(menu-item "^"
(lambda () (interactive)
(insert "^"))
:help "Exponentiation"))
(bindings--define-key
modul-naturals-operators [ft-nat]
'(menu-item ".."
(lambda () (interactive)
(insert ".."))
:help "From..To"))
(bindings--define-key
modul-naturals-operators [div2-nat]
'(menu-item "\\div"
(lambda () (interactive)
(insert "\div"))
:help "Integer Division"))
(bindings--define-key
modul-naturals-operators [mod-nat]
'(menu-item "%"
(lambda () (interactive)
(insert "%"))
:help "Modulo"))
(bindings--define-key
modul-naturals-operators [leq-nat]
'(menu-item "\\leq"
(lambda () (interactive)
(insert "\\leq"))
:help "Lower Equal"))
(bindings--define-key
modul-naturals-operators [geq-nat]
'(menu-item "\\geq"
(lambda () (interactive)
(insert "\\geq"))
:help "Greater Equal"))
(bindings--define-key
modul-naturals-operators [lt-nat]
'(menu-item "<"
(lambda () (interactive)
(insert "<"))
:help "Lower than"))
(bindings--define-key
modul-naturals-operators [gt-nat]
'(menu-item ">"
(lambda () (interactive)
(insert ">"))
:help "Greater than"))
;; Sequence Operators
(bindings--define-key modul-operators
[modul-sequences-operator]
(cons "Sequences" modul-sequences-operators))
(bindings--define-key
modul-sequences-operators [seq-s]
'(menu-item "Seq(S)"
(lambda () (interactive)
(insert "Seq(S)")
(backward-char 2))
:help
"Set of all Sequences of Elements of Set `S'"))
(bindings--define-key
modul-sequences-operators [head-s]
'(menu-item "Head(s)"
(lambda () (interactive)
(insert "Head(s)")
(backward-char 2))
:help "Head element of sequence `s'"))
(bindings--define-key
modul-sequences-operators [tail-s]
'(menu-item "Tail(s)"
(lambda () (interactive)
(insert "Tail(s)")
(backward-char 2))
:help "Tail sequence of sequence `s'"))
(bindings--define-key
modul-sequences-operators [append-s]
'(menu-item "Append(s,e)"
(lambda () (interactive)
(insert "Tail(S)")
(backward-char 2))
:help "Tail sequence of sequence `S'"))
(bindings--define-key
modul-sequences-operators [circ-s]
'(menu-item "s \\circ t"
(lambda () (interactive)
(insert "s \\circ t")
(backward-char 2))
:help "concatenation of sequence s and t"))
(bindings--define-key
modul-sequences-operators [len-s]
'(menu-item "Len(s)"
(lambda () (interactive)
(insert "Len(s)")
(backward-char 2))
:help "length of sequence s"))
;; Operators
(bindings--define-key menu-map [operator]
(cons "Insert Operator.." operator-map))
@ -91,7 +259,7 @@
(bindings--define-key
action-operator-map [nonstutter-operator]
'(menu-item "<<A>>_e" tla+-operator-nonstutter
:help "A /\ (e' \\= e)"))
:help "A /\\ (e' \\\\ = e)"))
(bindings--define-key
action-operator-map [enabled-operator]
@ -138,7 +306,8 @@
:help "F leads to G"))
;; Export Menu:
(bindings--define-key menu-map [export] (cons "Export.." export-map))
(bindings--define-key menu-map [export]
(cons "Export.." export-map))
(bindings--define-key export-map [export-pdf]
'(menu-item "Run TLatex and create PDF" tla+-run-tlatex-pdf
@ -163,7 +332,7 @@
'(menu-item "Run Syntax Checker" tla+-run-sany
:help
"Run SANY2 "
"(parser/syntax checker for TLA+ specifications.) "))
"(syntax checker for TLA+ specifications) "))
(bindings--define-key map [menu-bar tla+ tla+-create-module]
'(menu-item "Create new Module" tla+-create-module
@ -175,10 +344,10 @@
(defconst tla+-font-lock-keywords
(list
'("\\<\\(MODULE\\|CONSTANTS?\\|UNCHANGED\\|VARIABLES?\\|THEOREM\\|INSTANCE\\|LOCAL\\|ASUME\\|EXCEPT\\|EXTENDS?\\)\\>"
'("\\<\\(MODULE\\|CONSTANTS?\\|UNCHANGED\\|VARIABLES?\\|THEOREM\\|LOCAL\\|ASUME\\|EXTENDS?\\)\\>"
. font-lock-builtin-face)
'("\\<\\(TRUE\\|FALSE\\|OTHER\\|BOOLEAN\\)\\>" . font-lock-type-face)
'("\\<\\(CONSTANT\\|SUBSET\\|ENABLED\\|UNCHANGED\\|UNION\\|DOMAIN\\|EXCEPT\\|IF\\|THEN\\|ELSE\\|CHOOSE\\)\\>" . font-lock-keyword-face)
'("\\<\\(CONSTANT\\|SUBSET\\|ENABLED\\|UNCHANGED\\|INSTANCE\\|WITH\\|EXCEPT\\|UNION\\|DOMAIN\\|EXCEPT\\|IF\\|THEN\\|ELSE\\|CHOOSE\\)\\>" . font-lock-keyword-face)
'("\\\\\\*.*$" . font-lock-comment-face)
'("(\\*.*\\*)" . font-lock-comment-face)
'("\\('\\w*'\\)" . font-lock-variable-name-face)
@ -198,23 +367,41 @@ Turning on Text mode runs the normal hook `text-mode-hook'."
(setq-local text-mode-variant t)
(setq-local comment-start "\\* ")
(setq-local require-final-newline mode-require-final-newline))
(defun tla+-create-module ()
"Insert the base template for a new Module.
A new module will be created with the typical structure of a TLA+
specification file."
(interactive)
(let ((modulename
(concat (file-name-base (buffer-file-name)))))
(insert
(concat
"------------------- MODULE ......... -----------------------\n"
"------------------- MODULE "
modulename
" -----------------------\n"
"EXTENDS Naturals, ...\n"
"VARIABLE ..\n"
"------------------------------------------------------------\n"
"============================================================\n"
"\\* Modification History\n"
"\\* Created "
(current-time-string) " by " user-full-name "\n")))
(current-time-string) " by " user-full-name "\n"))))
(defun tla+-run-sany ()
"TODO: jump to line.."
"This function runs tla2sany.SANY (TLA syntax checker)
The function executes the TLA+ Syntax checker and reports errors
in a new frame. Errors are clickable buttons and the user can
directly go to the error line.
Operation:
1. execute the tla2sany.SANY program
2. the output of the shell-command is inserted into a newly
created buffer
3. errors are converted into clickable buttons by using the
`tla+/find-error-marks' function."
(interactive)
(let* ((filename (buffer-file-name))
(sanybuffer (get-buffer-create "*tla2sany.SANY*"))
@ -229,9 +416,15 @@ Turning on Text mode runs the normal hook `text-mode-hook'."
(other-window 1)
(switch-to-buffer sanybuffer)
(erase-buffer)
(insert output))))
(insert output)
(tla+/find-error-marks))))
(defun tla+-open-dvi (buffername)
"Function to open a DVI file.
This function starts the `xdvi' utility and opens the TLA+
specification file as DVI. It must be created beforehand
with the `tla+-run-tlatex-dvi'.
"
(interactive "b")
(save-excursion
(switch-to-buffer buffername)
@ -269,13 +462,22 @@ Turning on Text mode runs the normal hook `text-mode-hook'."
(interactive) (insert " ENABLED A"))
(defun tla+-operator-unchanged ()
"insert UNCHANGED operator.
Variables declared as unchanged will have the same value when a
step is taken to a new state, i.e. e' = e. "
(interactive) (insert " UNCHANGED e"))
(defun tla+-operator-unchanged ()
(defun tla+-operator-cdot ()
"insert operator A \\cdot B
A \\cdot B describes the composition of actions A, B."
(interactive) (insert " A \\cdot B"))
(defun tla+-run-tlatex (type)
"TODO: jump to line.."
"Run TLaTeX and generate DVI, PDF or PS file.
This function runs `pdflatex(1)' and geneartes a DVI file which can
be viewed with `xdvi'. If TYPE is 'pdf or 'ps, a PDF or PostScript
file will be generated as well.
The function executes one or two shell commands synchronously."
(interactive
(list
(completing-read
@ -308,10 +510,116 @@ Turning on Text mode runs the normal hook `text-mode-hook'."
;; (insert output))))
(defun tla+-run-tlatex-pdf ()
"Create PDF file from TLA+ Specification.
This function creates a PDF file of a TLA+ Specification by
`tla+-run-tlatex'"
(interactive) (tla+-run-tlatex 'pdf))
(defun tla+-run-tlatex-dvi ()
"Create DVI file from TLA+ Specification.
This function creates a DVI file of a TLA+ Specification by
`tla+-run-tlatex'"
(interactive) (tla+-run-tlatex 'dvi))
(defun tla+-run-tlatex-ps ()
"Create PS file from TLA+ Specification.
This function creates a PS file of a TLA+ Specification by
`tla+-run-tlatex'"
(interactive) (tla+-run-tlatex 'ps))
;; internal functions:
(define-button-type
'tla+/sany-button-pressed
'action 'tla+/sany-button-pressed
'follow-link t
'help-echo "Goto Source"
'help-args "test")
;; example: (make-button 1 12 :type 'custom-button)
(defun tla+/sany-button-pressed (button)
"Find the position and goto a sany error position.
This function will be executed when a user clicks on a button inside
the SANY error report buffer. This is done by selecting the other
window and going to the line mentioned in the error message.
The parameter BUTTON is currently unused.
Steps done by this function:
1. get the button at the current position of the `point'
2. get the text label of the button which is usually a line like
line XX, column YY
3. Get line number and column count of the error message
4. select the other-window (it is assumed that this is the *.tla
specification where SANY was executed.
5. goto line and column.
"
(let* ((pos (point))
(the-button (button-at pos))
(text (button-label the-button))
(s (string-match
(concat
"line \\([0-9][0-9]*\\)," ; line XYZ
"\\(column\\|col\\) " ; "column" or "col"
"\\([0-9][0-9]*\\)" ; XYZ
text))
(line (string-to-number (match-string 1 text)))
(col (string-to-number (match-string 3 text)))
)
;(message (format "Button pressed: %s" text))
(progn
;(switch-to-buffer (other-buffer))
(other-window 1)
;(switch-to-buffer (other-buffer))
;(switch-to-buffer-other-window (current-buffer))
(goto-char (point-min))
(goto-line line)
(forward-char col)
;(switch-to-buffer (other-buffer))
;(message "%s" (buffer-name))
)))
(defun tla+/make-link-button (begin end)
"Generate button from BEGIN until END
This function generates a new button starting at BEGIN until END.
The button will execute the `tla+/sany-button-pressed' when a user
clicks on it.
"
(make-button begin end :type 'tla+/sany-button-pressed))
(defun tla+/find-error-marks ()
"find error marks reported by SANY.
This function tries to find errors reported by SANY and converts them
into clickable buttons. By clicking on an error, the point will be
set to the other-buffer on that particular line and column. Currently
supported:
line XX, column YY
line XX, col YY
XX,YY are natural numbers.
The procedure works by:
1. finding a line that may look like an error message as described
above.
2. find the first offset and the last one
3. execute the `tla+/make-link-button' function to create a new button
"
(progn
(goto-char (point-min))
(while (re-search-forward
(concat
"line \\([0-9][0-9]*\\), "
"\\(column\\|col\\) "
"\\([0-9][0-9]*\\)")
(point-max) t)
(let* ((rstart (match-beginning 0))
(linenum (match-beginning 1))
(colnum (match-beginning 3))
(rend (+ colnum (- (length (int-to-string colnum)) 0)))
)
;(message "%s %s" linenum colnum)
(tla+/make-link-button rstart rend)
))))
(provide 'tla+-mode)