| ;;; gforth.el --- major mode for editing (G)Forth sources |
;;; gforth.el --- major mode for editing (G)Forth sources |
| |
|
| ;; Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc. |
;; Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc. |
| |
|
| ;; This file is part of Gforth. |
;; This file is part of Gforth. |
| |
|
| "create-interpret/compile") |
"create-interpret/compile") |
| non-immediate (font-lock-type-face . 2) |
non-immediate (font-lock-type-face . 2) |
| "[ \t\n]" t name (font-lock-variable-name-face . 3)) |
"[ \t\n]" t name (font-lock-variable-name-face . 3)) |
| |
("\\S-+%" non-immediate (font-lock-type-face . 2)) |
| (("defer" "alias" "create-interpret/compile:") |
(("defer" "alias" "create-interpret/compile:") |
| non-immediate (font-lock-type-face . 1) |
non-immediate (font-lock-type-face . 1) |
| "[ \t\n]" t name (font-lock-function-name-face . 3)) |
"[ \t\n]" t name (font-lock-function-name-face . 3)) |
| (defvar forth-indent-words nil |
(defvar forth-indent-words nil |
| "List of words that have indentation behaviour. |
"List of words that have indentation behaviour. |
| Each element of `forth-indent-words' should have the form |
Each element of `forth-indent-words' should have the form |
| (MATCHER INDENT1 INDENT2) |
(MATCHER INDENT1 INDENT2 &optional TYPE) |
| |
|
| MATCHER is either a list of strings to match, or a REGEXP. |
MATCHER is either a list of strings to match, or a REGEXP. |
| If it's a REGEXP, it should not be surrounded by `\\<` or `\\>`, since |
If it's a REGEXP, it should not be surrounded by `\\<` or `\\>`, since |
| that'll be done automatically by the search routines. |
that'll be done automatically by the search routines. |
| |
|
| |
TYPE might be omitted. If it's specified, the only allowed value is |
| |
currently the symbol `non-immediate', meaning that the word will not |
| |
have any effect on indentation inside definitions. (:NONAME is a good |
| |
example for this kind of word). |
| |
|
| INDENT1 specifies how to indent a word that's located at a line's begin, |
INDENT1 specifies how to indent a word that's located at a line's begin, |
| following any number of whitespaces. |
following any number of whitespaces. |
| |
|
| 1 * forth-indent-level + forth-minor-indent-level columns to the right.") |
1 * forth-indent-level + forth-minor-indent-level columns to the right.") |
| |
|
| (setq forth-indent-words |
(setq forth-indent-words |
| '(((":" ":noname" "code" "if" "begin" "do" "?do" "+do" "-do" "u+do" |
'((("if" "begin" "do" "?do" "+do" "-do" "u+do" |
| "u-do" "?dup-if" "?dup-0=-if" "case" "of" "try" "struct" |
"u-do" "?dup-if" "?dup-0=-if" "case" "of" "try" |
| "[if]" "[ifdef]" "[ifundef]" "[begin]" "[for]" "[do]" "[?do]" |
"[if]" "[ifdef]" "[ifundef]" "[begin]" "[for]" "[do]" "[?do]") |
| "class" "interface" "m:" ":m") |
|
| (0 . 2) (0 . 2)) |
(0 . 2) (0 . 2)) |
| |
((":" ":noname" "code" "struct" "m:" ":m" "class" "interface") |
| |
(0 . 2) (0 . 2) non-immediate) |
| |
("\\S-+%$" (0 . 2) (0 . 0) non-immediate) |
| ((";" ";m") (-2 . 0) (0 . -2)) |
((";" ";m") (-2 . 0) (0 . -2)) |
| (("end-code" "again" "repeat" "then" "endtry" "endcase" "endof" |
(("again" "repeat" "then" "endtry" "endcase" "endof" |
| "end-struct" "[then]" "[endif]" "[loop]" "[+loop]" "[next]" |
"[then]" "[endif]" "[loop]" "[+loop]" "[next]" |
| "[until]" "[repeat]" "[again]" "end-class" "end-interface" |
"[until]" "[repeat]" "[again]" "loop") |
| "end-class-noname" "end-interface-noname" "loop" |
|
| "class;") |
|
| (-2 . 0) (0 . -2)) |
(-2 . 0) (0 . -2)) |
| (("protected" "public" "how:") (-1 . 1) (0 . 0)) |
(("end-code" "end-class" "end-interface" "end-class-noname" |
| |
"end-interface-noname" "end-struct" "class;") |
| |
(-2 . 0) (0 . -2) non-immediate) |
| |
(("protected" "public" "how:") (-1 . 1) (0 . 0) non-immediate) |
| (("+loop" "-loop" "until") (-2 . 0) (-2 . 0)) |
(("+loop" "-loop" "until") (-2 . 0) (-2 . 0)) |
| (("else" "recover" "[else]") (-2 . 2) (0 . 0)) |
(("else" "recover" "[else]") (-2 . 2) (0 . 0)) |
| (("while" "does>" "[while]") (-1 . 1) (0 . 0)) |
(("while" "does>" "[while]") (-1 . 1) (0 . 0)) |
| (let* ((regexp (car forth-compiled-indent-words)) |
(let* ((regexp (car forth-compiled-indent-words)) |
| (pos (re-search-forward regexp to t))) |
(pos (re-search-forward regexp to t))) |
| (if pos |
(if pos |
| (if (text-property-not-all (match-beginning 0) (match-end 0) |
(let* ((start (match-beginning 0)) |
| 'forth-parsed nil) |
(end (match-end 0)) |
| (forth-next-known-indent-word to) |
(branch (forth-get-regexp-branch)) |
| (let* ((branch (forth-get-regexp-branch)) |
|
| (descr (cdr forth-compiled-indent-words)) |
(descr (cdr forth-compiled-indent-words)) |
| (indent (cdr (assoc branch descr)))) |
(indent (cdr (assoc branch descr))) |
| |
(type (nth 2 indent))) |
| |
;; skip words that are parsed (strings/comments) and |
| |
;; non-immediate words inside definitions |
| |
(if (or (text-property-not-all start end 'forth-parsed nil) |
| |
(and (eq type 'non-immediate) |
| |
(text-property-not-all start end |
| |
'forth-state nil))) |
| |
(forth-next-known-indent-word to) |
| (if (forth-first-word-on-line-p (match-beginning 0)) |
(if (forth-first-word-on-line-p (match-beginning 0)) |
| (nth 0 indent) (nth 1 indent)))) |
(nth 0 indent) (nth 1 indent)))) |
| nil))) |
nil))) |
| (defun forth-get-anchor-column () |
(defun forth-get-anchor-column () |
| (save-excursion |
(save-excursion |
| (if (/= 0 (forward-line -1)) 0 |
(if (/= 0 (forward-line -1)) 0 |
| (let ((next-indent) |
(let ((indent)) |
| (self-indent)) |
|
| (while (not (or (setq indent (forth-get-column-incr 1)) |
(while (not (or (setq indent (forth-get-column-incr 1)) |
| (<= (point) (point-min)))) |
(<= (point) (point-min)))) |
| (forward-line -1)) |
(forward-line -1)) |
| (save-restriction |
(save-restriction |
| (widen) |
(widen) |
| (save-excursion |
(save-excursion |
| (beginning-of-buffer) |
(goto-char (point-min)) |
| (end-of-line) |
(end-of-line) |
| (>= (current-column) 1024)))) |
(>= (current-column) 1024)))) |
| |
|