--- gforth/gforth.el 1998/05/09 21:27:16 1.29 +++ gforth/gforth.el 2001/03/11 22:50:49 1.47 @@ -1,10 +1,8 @@ ;; Forth mode for Emacs -;; This file is part of GForth. -;; Changes by anton -;; This is a variant of forth.el that came with TILE. -;; I left most of this stuff untouched and made just a few changes for -;; the things I use (mainly indentation and syntax tables). -;; So there is still a lot of work to do to adapt this to gforth. + +;; Copyright (C) 1995,1996,1997,1998,2000 Free Software Foundation, Inc. + +;; This file is part of Gforth. ;; GForth is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY. No author or distributor @@ -21,6 +19,12 @@ ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies. +;; Changes by anton +;; This is a variant of forth.el that came with TILE. +;; I left most of this stuff untouched and made just a few changes for +;; the things I use (mainly indentation and syntax tables). +;; So there is still a lot of work to do to adapt this to gforth. + ;;------------------------------------------------------------------- ;; A Forth indentation, documentation search and interaction library ;;------------------------------------------------------------------- @@ -36,20 +40,20 @@ (defvar forth-positives - " : :noname code interpretation: ;code does> begin do ?do +do -do u+do u-do while if ?dup-if ?dup-0=-if else case of struct [if] [ifdef] [ifundef] [else] with public: private: class " - "Contains all words which will cause the indent-level to be incremented + " : :noname m: :m code interpretation: ;code does> begin do ?do +do -do u+do u-do while if ?dup-if ?dup-0=-if else case of struct [if] [ifdef] [ifundef] [else] with public: private: class try recover " + "*Contains all words which will cause the indent-level to be incremented on the next line. OBS! All words in forth-positives must be surrounded by spaces.") (defvar forth-negatives - " ; end-code ;code does> until repeat while +loop loop -loop s+loop else then endif again endcase endof end-struct [then] [else] [endif] endwith class; how: " - "Contains all words which will cause the indent-level to be decremented + " ; ;m end-code ;code does> until repeat while +loop loop -loop s+loop else then endif again endcase endof end-struct [then] [else] [endif] endwith end-class class; how: recover endtry " + "*Contains all words which will cause the indent-level to be decremented on the current line. OBS! All words in forth-negatives must be surrounded by spaces.") (defvar forth-zeroes " : :noname code interpretation: public: private: how: implements class class; " - "Contains all words which causes the indent to go to zero") + "*Contains all words which causes the indent to go to zero") (setq forth-zero 0) @@ -88,6 +92,16 @@ OBS! All words in forth-negatives must b (define-key forth-mode-map "\M-q" 'forth-fill-paragraph) (define-key forth-mode-map "\e." 'forth-find-tag) +;setup for C-h C-i to work +(if (fboundp 'info-lookup-add-help) + (info-lookup-add-help + :topic 'symbol + :mode 'forth-mode + :regexp "[^ +]+" + :ignore-case t + :doc-spec '(("(gforth)Name Index" nil "`" "' ")))) + (load "etags") (defun forth-find-tag (tagname &optional next-p regexp-p) @@ -98,7 +112,7 @@ OBS! All words in forth-negatives must b (defvar forth-mode-syntax-table nil "Syntax table in use in Forth-mode buffers.") -(if (not forth-mode-syntax-table) +(if t;; (not forth-mode-syntax-table) (progn (setq forth-mode-syntax-table (make-syntax-table)) (let ((char 0)) @@ -109,8 +123,6 @@ OBS! All words in forth-negatives must b (modify-syntax-entry char "w" forth-mode-syntax-table) (setq char (1+ char)))) (modify-syntax-entry ?\" "\"" forth-mode-syntax-table) - (modify-syntax-entry ?\\ "<" forth-mode-syntax-table) - (modify-syntax-entry ?\n ">" forth-mode-syntax-table) )) ;I do not define '(' and ')' as comment delimiters, because emacs ;only supports one comment syntax (and a hack to accomodate C++); I @@ -124,6 +136,8 @@ OBS! All words in forth-negatives must b ;same character. we could use ' ' as first and '(' and '\' as second ;character. However this would fail for G\ comments. +;comment handling has been moved to syntactic font lock (david) + (defconst forth-indent-level 4 "Indentation of Forth statements.") @@ -149,7 +163,14 @@ OBS! All words in forth-negatives must b (make-local-variable 'comment-indent-hook) (setq comment-indent-hook 'forth-comment-indent) (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments t)) + (setq parse-sexp-ignore-comments t) + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults '(forth-font-lock-keywords nil t nil nil + (font-lock-syntactic-keywords . forth-font-lock-syntactic-keywords))) +; (make-local-variable 'font-lock-syntactic-keywords) +; (setq font-lock-syntactic-keywords 'forth-font-lock-syntactic-keywords) +) + ;;;###autoload (defun forth-mode () @@ -227,7 +248,7 @@ Variables controling documentation searc ; (run-forth forth-program-name)) (run-hooks 'forth-mode-hook)) -(setq forth-mode-hook +(add-hook 'forth-mode-hook '(lambda () (make-local-variable 'compile-command) (setq compile-command "gforth "))) @@ -951,10 +972,10 @@ The region is sent terminated by a newli (setq outline-level 'f-outline-level) (outline-minor-mode) -(define-key outline-minor-mode-map '(shift up) 'hide-sublevels) -(define-key outline-minor-mode-map '(shift right) 'show-children) -(define-key outline-minor-mode-map '(shift left) 'hide-subtree) -(define-key outline-minor-mode-map '(shift down) 'show-subtree) + (define-key outline-minor-mode-map '(shift up) 'hide-sublevels) + (define-key outline-minor-mode-map '(shift right) 'show-children) + (define-key outline-minor-mode-map '(shift left) 'hide-subtree) + (define-key outline-minor-mode-map '(shift down) 'show-subtree) ) @@ -972,9 +993,100 @@ The region is sent terminated by a newli (require 'func-menu) ;; (define-key global-map 'f8 'function-menu) (add-hook 'find-fible-hooks 'fume-add-menubar-entry) - (define-key global-map "\C-cg" 'fume-prompt-function-goto) - (define-key global-map '(shift button3) 'mouse-function-menu) +; (define-key global-map "\C-cg" 'fume-prompt-function-goto) +; (define-key global-map '(shift button3) 'mouse-function-menu) )) -;; end +;;; Font lock code (david ) +;;; +;;; note that words which contain a closing paren, which have the comment-ender +;;; syntactic class, won't be matched by `\w+' and `\<' and `\>' won't work +;;; either; solution: use of `\S-' and `\s-' where necessary +;;; +(defvar forth-bracket-keyword nil) +(defvar forth-syntactic-keywords nil) +(defvar forth-variable-defining-words nil) +(defvar forth-function-defining-words nil) +(defvar forth-function-parsing-words nil) +(defvar forth-variable-parsing-words nil) +(defvar forth-word-string-parsing-words nil) +(defvar forth-type-defining-words nil) +(defvar forth-font-lock-keywords nil) + +(setq forth-bracket-keywords + '("[if]" "[ifdef]" "[ifundef]" "[else]" "[then]" "[?do]" "[do]" "[for]" + "[loop]" "[+loop]" "[next]" "[begin]" "[until]" "[again]" "[while]" + "[repeat]")) +(setq forth-syntactic-keywords + '("if" "else" "then" "case" "endcase" "of" "endof" "begin" "while" + "repeat" "until" "again" "does>" "?do" "do" "+loop" "unloop" "loop" + "exit" "u+do" "-do" "u-do" "-loop" "u+do" "for" "next" "cs-roll" + "cs-pick" "recurse" "?dup-if" "?dup-0=-if" "leave" "?leave" "done" + ";" ":noname" "immediate" "restrict" "compile-only" "interpretation>" + "" "")) +(setq forth-variable-parsing-words + '("[TO]" "TO" "")) +(setq forth-word-string-parsing-words + '("[CHAR]" "CHAR" "include" "require" "needs")) +(setq forth-type-defining-words + '("end-struct")) + +(defun forth-make-words-regexp (word-list) + (concat "\\<" (regexp-opt word-list t) "\\>")) +(defun forth-make-parsing-words-regexp (word-list) + (concat "\\<" (regexp-opt word-list t) "\\s-+\\(\\S-+\\)")) +(defun forth-make-parsing-words-matcher (word-list word-face parsed-face) + (let ((regexp (forth-make-parsing-words-regexp word-list))) + (list regexp (list 1 word-face) + (list (regexp-opt-depth regexp) parsed-face)) + )) + +(setq forth-font-lock-keywords + (list + (forth-make-parsing-words-matcher forth-function-defining-words + font-lock-keyword-face font-lock-function-name-face) + (forth-make-parsing-words-matcher forth-variable-defining-words + font-lock-type-face font-lock-variable-name-face) + (forth-make-parsing-words-matcher forth-type-defining-words + font-lock-keyword-face font-lock-type-face) + (forth-make-parsing-words-matcher forth-function-parsing-words + font-lock-keyword-face font-lock-function-name-face) + (forth-make-parsing-words-matcher forth-variable-parsing-words + font-lock-keyword-face font-lock-variable-name-face) + (forth-make-parsing-words-matcher forth-word-string-parsing-words + font-lock-keyword-face font-lock-string-face) + (list (forth-make-words-regexp forth-bracket-keywords) + 0 font-lock-keyword-face) + (list (forth-make-words-regexp forth-syntactic-keywords) + 0 font-lock-keyword-face) +; '("\\<\\({\\)\\(\\([ \t]+-?[^- \t}\n]*\\>\\)*\\)\\([^}\n]*\\)\\(}\\)?" +; (1 font-lock-keyword-face) (2 font-lock-variable-name-face) +; (4 font-lock-comment-face) (5 font-lock-keyword-face nil t)) + '("\\<-?[0-9][0-9a-f]*\\>" . font-lock-constant-face) + '("\\<[^ \t\n%]+%" . font-lock-type-face) + )) + +;; Syntactic highlighting is used for getting Forth comments highlighted +;; properly: `\' and `\g' comments are handled with a single regular +;; expression that parses from `\' to end of line and assigns the +;; "comment-fence" generic comment delimiter to the backslash and end-of-line +;; characters. +;; `( ... )' comments are handled by the usual comment-starter/comment-ender +;; syntax classes, with the extension that `(' must be a single word. +;; +(defvar forth-font-lock-syntactic-keywords nil) +(setq forth-font-lock-syntactic-keywords + '(("\\<\\(\\(\\\\\\)g?\\)\\>.*\\(\n\\)" (2 (14 . nil)) (3 (14 . nil))) + ("\\<(\\>" 0 (11 . nil)) + (")" 0 (12 . nil)))) + +;;; End font lock code