;;;;;;;;;;;;;;;;;;;;;;;;;;
;; $Haeder$
;; Copyright: (c) Heng Jiang, Uni Bremen 2007
;; License: LGPL, see LICENSE.txt or LIZENZ.txt
;; Contact: hets-users@informatik.uni-bremen.de
;;;;;;;;;;;;;;;;;;;;;;;;;;
;; casl-indent.el --- indentation module for CASL Mode
"casl indentation."
:prefix "casl-indent-")
"*Indentation of casl statements with respect to containing block."
"*Column on which to align right-hand sides (use 0 for ad-hoc alignment)."
(point)))
(point)))
"Returns the column number of APOINT."
(current-column)))
(concat "\\<\\("
"spec\\|then\\|view\\|units"
"\\)\\>")
"Regexp describing keywords to complete when standing at the first word
of a line.")
"\\(\\<library\\|\\<version\\|\\(%\\(authors\\|date\\|display\\):?\\)\\)"
"These keywords need not to be indented.")
"t when using XEmacs or Lucid.")
;;; customizations for different kinds of environments
;;; in which dealing with low-level events are different
(progn ;;; for XEmacs
(defun casl-indent-mark-active ()
(if zmacs-regions
t)))
;; in Gnu Emacs
(defun casl-indent-mark-active ()
)
;; for pushing indentation information
"Pushes indentation information for the column COL
followed by NAME (if present). Makes sure that the same indentation info
is not pushed twice in a row. Uses free var `indent-info'."
"Pushes indentation information for the column corresponding to POS
followed by NAME (if present). "
"Pushes indentation information for the column corresponding to POS
followed by an OFFSET (if present use its value otherwise use
`casl-indent-offset')."
(or offset casl-indent-offset))))
;;; redefinition of some Emacs function for dealing with
;;; Bird Style literate scripts
(defun casl-indent-bolp ()
"`bolp'"
(bolp)
)
(defun casl-indent-empty-line-p ()
"Checks if the current line is empty."
(looking-at "[ \t]*$"))
)
(defun casl-indent-back-to-indentation ()
"`back-to-indentation' function."
)
(defun casl-indent-current-indentation ()
"`current-indentation' function."
)
"`backward-to-indentation' function."
)
"`forward-line' function."
)
"`indent-line-to' function."
)
"Skips forward blanks, tabs and newlines until END."
)
"Skips backward blanks, tabs and newlines upto START."
)
;;; Start of indentation code
(defun casl-indent-start-of-def ()
"Returns the position of the start of a definition.
It is at the first character which is not in a comment after nearest
preceding non-empty line."
(let (start-code
(save-point (point)))
;; determine the starting point of the current piece of code
;; go backward until the first preceding empty line
(while (and (not (casl-indent-empty-line-p))
;; go forward after the empty line
(if (casl-indent-empty-line-p)
;; find the first line of code which is not a comment
(point)))
)
"If any structure (list or tuple) is not closed, between START and END,
returns the location of the opening symbol, nil otherwise."
)))
"Checks, starting from START, if END is within a comment, returns
the location of the start of the comment, nil otherwise."
( t
(cond
(point))
(re-search-backward "%%"
(casl-indent-get-beg-of-line) t))))
))))
)
;; Keine Ahnung
(defvar casl-indent-off-side-keywords-re
"\\<\\(with\\|to\\|and\\|hide\\)\\>[ \t]*")
(defun casl-indent-type-at-point ()
"Returns the type of the line (also puts information in `match-data')."
(cond
;; [_.] fuer __>__ Form und ., die Zeile die mit 'from', 'library',
;; 'logic' sowie '%xxxx' anfaengt, wird auch als ein indent angewendet.
"\\([a-zA-Z_.%]\\S-*\\)"
"[ \t\n]*\\)")) 'ident)
;; fuer type-definition
;; rhs ist in CASL nicht wichtig
; ((looking-at "\\(%\\sw+\\)") 'muell)
( t 'other))
)
"Global variable that keeps track of the first ident of the line to indent.")
"Generates contour information between START and END points."
(and (not (member (casl-indent-type-at-point)
)
contour))))
"Puts point to the next following symbol."
(forward-char 1))
))
"Returns a list of positions for important parts of a valdef."
type)
;; "parse" a valdef separating important parts
(if (null aft-valname)
(if (null aft-rhs-sign)
"Finds indentation information for a line starting with a guard."
;; push information indentation for the visible part
(if rhs-sign
(if valname
)))))
"Finds indentation information for a line starting with a rhs."
;; push information indentation for the visible part
(if valname
"Finds indentation information for a comment line.
If the previous line (between START and END) is also a comment line
-- comments are aligned on their start
{- comments are aligned on the first non-blank char following the open {
otherwise
indent at the same indentation as the previous line."
(if comment-start
;; %% style comment
;; %{ style comment
;; no previous comment indent with previous line
(let ((or "\\)\\|\\("))
(concat "\\("
"111111" or ;1 = vn avn rh arh gd agd
"1.0000" or ;2 = vn avn
"1.1000" or ;3 = vn (avn) rh
"111100" or ;4 = vn avn rh arh
"000011" or ;5 = gd agd
"001000" or ;6 = rh
"0011.." or ;7 = rh arh . .
"101..." or ;8 = vn rh (arh gd agd)
"000000" ;9 =
"\\)")))
"Find the index that matches in the decision table."
;; use the fact that the resulting match-data is a list of the form
;; (0 6 [2*(n-1) nil] 0 6) where n is the number of the matching regexp
;; so n= ((length match-date)/2)-1
(error "casl-indent-find-case: impossible case: %s" test)
))
"Finds indentation points for an empty line."
(let*
(if valname "1" "0")
)
(if (and valname-string ; special case for start keywords
)
(if (and valname-string
(case ; general case
;; "111111" 1 = all elements
;; "1.0000" 2= vn avn
(if aft-valname
;; "1.1000" 3= vn (avn) rh
(if aft-valname
)
;; "111100" 4= vn avn rh arh
;; "000011" 5= gd agd
;; "001000" 6= rh
;; "0011.." 7= rh arh (gd agd)
;; "101..." 8 = vn rh (arh gd agd)
;; "000000" 9=
(t (error "casl-indent-empty: %s impossible case" test )
))))))
"Finds indentation points for a line starting with an identifier."
(let*
(if valname "1" "0")
)
(if (and valname-string ; special case for start keywords
(if (not (string-match
)
(if (and valname-string
(case ; general case
;; "111111" 1 = all elements
;; "1.0000" 2= vn avn
(if aft-valname
;; "1.1000" 3= vn (avn) rh
;; "111100" 4= vn avn rh arh
;; "000011" 5= gd agd
(5 ;; (casl-indent-push-pos 0)
;; "001000" 6= rh
;; "0011.." 7= rh arh (gd agd)
(7
;; "101..." 8 = vn rh (arh)
;; "000000" 9=
(t (error "casl-indent-ident: %s impossible case" test )))))))
"Finds indentation points for a non-empty line starting with something other
than an identifier, a guard or rhs."
(let*
;(is-where
; (string-match "where[ \t]*" casl-indent-current-line-first-ident))
(if valname "1" "0")
)
(if (and valname-string ; special case for start keywords
(case ; general case
;; "111111" 1 = all elements
;; "1.0000" 2= vn avn
;; "1.1000" 3= vn (avn) rh
;; "111100" 4= vn avn rh arh
;; "000011" 5= gd agd
;; "001000" 6= rh
;; "0011.." 7= rh arh (gd agd)
(7 ())
;; "101.00" 8 = vn rh (arh)
;; "000000" 9=
(t (error "casl-indent-other: %s impossible case" test ))))))
"Finds indentation information for a value definition."
(case curr-line-type
('comment (error "Comment indent should never happen"))
"Separate a line of program into valdefs between offside keywords
and find indentation info for each part."
;; point is (already) at line-start
(if start-comment ; if comment at the end
;; loop on all parts separated by off-side-keywords
line-start ; end line before comment
;skip past end of comment
;; not in a comment
;; but keep the start of the line if keyword alone on the line
(goto-char line-start)))
(defun casl-indent-indentation-info ()
"Returns a list of possible indentations for the current line that
are then used by `casl-indent-cycle'."
(let ((start (casl-indent-start-of-def))
;; open structure? ie ( { [
;; there is an open structure to complete
(if (looking-at "\\s)\\|\\s.\\|$ ")
(point)))
;; in comment ?
(point) indent-info)))
;; full indentation
(if contour-line
(let* ((curr-line-type (casl-indent-type-at-point))
(progn ; guess the type of line
;; if the first ident is where or the start of a def
;; keep it in a global variable
(if contour-line ; next contour point
(point))
line-end))
indent-info)))
)))
;; simple contour just one indentation at start
)))
"Checks if EVENT is the TAB or RET key before returning the value
of `event-basic-type'. Needed for dealing with the case that Emacs
is not in a windowing environment."
(t (event-basic-type event)))
)
(defun casl-indent-cycle ()
"Indentation cycle.
We stay in the cycle as long as the TAB key is pressed.
Any other key or mouse click terminates the cycle and is interpreted
with the exception of the RET key which merely exits the cycle."
(interactive "*")
;;(message "Indent-list:%s" indent-list) (read-event) ; uncomment for debug!!
(message "Sole indentation")
; from the beginning
(message "Indenting..."))
(message "Done."))
(if marker
)
)
;;; alignment functions
;;;
"Shifts columns in region-stack to go to DEST-COLUMN.
Elements of the stack are pairs of points giving the start and end
of the regions to move."
(if (eobp) ; but it adds line at the end...
(throw 'end-of-buffer nil))
(move-to-column col)))
))
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; turn-on-casl-indent to be used in conjunction with
;;; the casl-mode of Graeme E Moss and Tommy Thorn
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun turn-on-casl-indent ()
"Turn on ``intelligent'' casl indentation mode."
(setq casl-indent-mode t)
)
(defun turn-off-casl-indent ()
"Turn off ``intelligent'' casl indentation mode that deals with
the layout rule of casl."
(local-unset-key "\t")
(setq casl-indent-mode nil)
)
(defvar casl-indent-mode nil
"Indicates if the semi-intelligent casl indentation mode is in effect
in the current buffer.")
;; Put this minor mode on the global minor-mode-alist.
'((casl-indent-mode " Ind")))))
"``intelligent'' casl indentation mode that deals with
the layout rule of casl.
Invokes `casl-indent-hook' if not nil."
(interactive "P")
(if casl-indent-mode
;; EOF