--- gforth/gforth.el 2001/04/08 13:48:11 1.48 +++ gforth/gforth.el 2001/12/15 22:44:52 1.55 @@ -1,6 +1,6 @@ ;;; 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. @@ -49,16 +49,40 @@ ;;; Code: - +;; Code ripped from `version.el' for compatability with Emacs versions +;; prior to 19.23. +(unless (boundp 'emacs-major-version) + (defconst emacs-major-version + (progn (string-match "^[0-9]+" emacs-version) + (string-to-int (match-string 0 emacs-version))))) + ;;; Hilighting and indentation engine (dk) ;;; +(defvar forth-disable-parser nil + "*Non-nil means to disable on-the-fly parsing of Forth-code. + +This will disable hilighting of forth-mode buffers and will decrease +the smartness of the indentation engine. Only set it to non-nil, if +your computer is very slow. To disable hilighting, set +`forth-hilight-level' to zero.") + +(defvar forth-jit-parser nil + "*Non-nil means to parse Forth-code just-in-time. + +This eliminates the need for initially parsing forth-mode buffers and +thus speeds up loading of Forth files. That feature is only available +in Emacs21 (and newer versions).") + (defvar forth-words nil "List of words for hilighting and recognition of parsed text areas. -You can enable hilighting of object-oriented Forth code, by appending either -`forth-objects-words' or `forth-oof-words' to the list, depending on which -OOP package you're using. + +Hilighting of object-oriented Forth code is achieved, by appending either +`forth-objects-words' or `forth-oof-words' to the list, depending on the values of `forth-use-objects' or `forth-use-oof'. + +After `forth-words' changed, `forth-compile-words' must be called to +make the changes take effect. Each item of `forth-words' has the form (MATCHER TYPE HILIGHT . &optional PARSED-TEXT ...) @@ -140,7 +164,9 @@ PARSED-TYPE specifies what kind of text (("true" "false" "c/l" "bl" "cell" "pi" "w/o" "r/o" "r/w") non-immediate (font-lock-constant-face . 2)) - (("~~") compile-only (font-lock-warning-face . 2)) + (("~~" "break:") compile-only (font-lock-warning-face . 2)) + (("break\"") compile-only (font-lock-warning-face . 1) + "[\"\n]" nil string (font-lock-string-face . 1)) (("postpone" "[is]" "defers" "[']" "[compile]") compile-only (font-lock-keyword-face . 2) "[ \t\n]" t name (font-lock-function-name-face . 3)) @@ -160,6 +186,7 @@ PARSED-TYPE specifies what kind of text "create-interpret/compile") non-immediate (font-lock-type-face . 2) "[ \t\n]" t name (font-lock-variable-name-face . 3)) + ("\\S-+%" non-immediate (font-lock-type-face . 2)) (("defer" "alias" "create-interpret/compile:") non-immediate (font-lock-type-face . 1) "[ \t\n]" t name (font-lock-function-name-face . 3)) @@ -170,8 +197,10 @@ PARSED-TYPE specifies what kind of text immediate (font-lock-constant-face . 3)) )) +(defvar forth-use-objects nil + "*Non-nil makes forth-mode also hilight words from the \"Objects\" package.") (defvar forth-objects-words nil - "Hilighting description for words of the \"Objects\" OOP package") + "Hilighting description for words of the \"Objects\" package") (setq forth-objects-words '(((":m") definition-starter (font-lock-keyword-face . 1) "[ \t\n]" t name (font-lock-function-name-face . 3)) @@ -201,16 +230,17 @@ PARSED-TYPE specifies what kind of text "methods" "end-methods" "this") non-immediate (font-lock-keyword-face . 2)) (("object") non-immediate (font-lock-type-face . 2)))) -; (nconc forth-words forth-objects-words) +(defvar forth-use-oof nil + "*Non-nil makes forth-mode also hilight words from the \"OOF\" package.") (defvar forth-oof-words nil - "Hilighting description for words of the \"OOF\" OOP package") + "Hilighting description for words of the \"OOF\" package") (setq forth-oof-words '((("class") non-immediate (font-lock-keyword-face . 2) "[ \t\n]" t name (font-lock-type-face . 3)) (("var") non-immediate (font-lock-type-face . 2) "[ \t\n]" t name (font-lock-variable-name-face . 3)) - (("method") non-immediate (font-lock-type-face . 2) + (("method" "early") non-immediate (font-lock-type-face . 2) "[ \t\n]" t name (font-lock-function-name-face . 3)) (("::" "super" "bind" "bound" "link") immediate (font-lock-keyword-face . 2) @@ -222,49 +252,56 @@ PARSED-TYPE specifies what kind of text "endwith") non-immediate (font-lock-keyword-face . 2)) (("object") non-immediate (font-lock-type-face . 2)))) -; (nconc forth-words forth-oof-words) + +(defvar forth-local-words nil + "List of Forth words to prepend to `forth-words'. Should be set by a + forth source, using a local variables list at the end of the file + (\"Local Variables: ... forth-local-words: ... End:\" construct).") + +(defvar forth-custom-words nil + "List of Forth words to prepend to `forth-words'. Should be set in your + .emacs.") (defvar forth-hilight-level 3 "*Level of hilighting of Forth code.") + (defvar forth-compiled-words nil "Compiled representation of `forth-words'.") + ; todo: ; -; Wörter ordentlich hilighten, die nicht auf whitespace beginning ( ..)IF -; -; Buffer-local variables can be set via "Local Variables:" or -*- -; Setting hilighting/indentation specifications requires multi-line variables, -; can only be done in 0 [IF] ... [ENDIF] blocks. -; Additional variable `forth-local-words'/`forth-local-indent-words' required. -; Should be appended to `forth-words'. Additional `forth-use-objects' or -; `forth-use-oof' could be set to non-nil for automatical adding of those -; word-lists. -; -; How to use block files with conversion? Use an additional mode? File-ending -; cannot be used for specifying encoding. -; -- Introduce a second mode `forth-blocked-mode', that decodes the buffer -; `decode-coding-region' ands set `buffer-coding-system'. *Warning* block -; conversion might not work well with regions, since it's a linewise -; conversion +; Wörter ordentlich hilighten, die nicht auf Whitespace beginnen ( ..)IF +; -- mit aktueller Konzeption nicht möglich?? ; ; Konfiguration über customization groups ; -; Bereich nur auf Wortanfang/ende ausweiten, wenn anfang bzw ende in einem +; Bereich nur auf Wortanfang/ende ausweiten, wenn Anfang bzw Ende in einem ; Wort liegen (?) -- speed! ; -; User interface -; ; 'forth-word' property muss eindeutig sein! +; +; Forth-Menu +; +; Interface zu GForth Prozessen (Patches von Michael Scholz) +; +; Byte-compile-Code rausschmeißen, Compilieren im Makefile über Emacs +; batch-Modus +; +; forth-help Kram rausschmeißen +; +; XEmacs Kompatibilität? imenu/speedbar -> fume? +; +; Folding neuschreiben (neue Parser-Informationen benutzen) -(setq debug-on-error t) +;(setq debug-on-error t) -;; Filter list by predicat. This is a somewhat standard function for +;; Filter list by predicate. This is a somewhat standard function for ;; functional programming languages. So why isn't it already implemented ;; in Lisp?? -(defun forth-filter (predicat list) +(defun forth-filter (predicate list) (let ((filtered nil)) (mapcar (lambda (item) - (when (funcall predicat item) + (when (funcall predicate item) (if filtered (nconc filtered (list item)) (setq filtered (cons item nil)))) @@ -296,7 +333,7 @@ PARSED-TYPE specifies what kind of text ;; parsing of the form ;; (regexp (subexp-count word-description) (subexp-count2 word-description2) ;; ...) -(defun forth-compile-words (words) +(defun forth-compile-wordlist (words) (let* ((mapped (mapcar 'forth-compile-words-mapper words)) (regexp (concat "\\<\\(" (mapconcat 'car mapped "\\|") @@ -313,6 +350,39 @@ PARSED-TYPE specifies what kind of text (byte-compile 'result) result))) +(defun forth-compile-words () + "Compile the the words from `forth-words' and `forth-indent-words' into + the format that's later used for doing the actual hilighting/indentation. + Store the resulting compiled wordlists in `forth-compiled-words' and +`forth-compiled-indent-words', respective" + (setq forth-compiled-words + (forth-compile-wordlist + (forth-filter 'forth-words-filter forth-words))) + (setq forth-compiled-indent-words + (forth-compile-wordlist forth-indent-words))) + +(defun forth-hack-local-variables () + "Parse and bind local variables, set in the contents of the current + forth-mode buffer. Prepend `forth-local-words' to `forth-words' and + `forth-local-indent-words' to `forth-indent-words'." + (hack-local-variables) + (setq forth-words (append forth-local-words forth-words)) + (setq forth-indent-words (append forth-local-indent-words + forth-indent-words))) + +(defun forth-customize-words () + "Add the words from `forth-custom-words' and `forth-custom-indent-words' + to `forth-words' and `forth-indent-words', respective. Add + `forth-objects-words' and/or `forth-oof-words' to `forth-words', if + `forth-use-objects' and/or `forth-use-oof', respective is set." + (setq forth-words (append forth-custom-words forth-words + (if forth-use-oof forth-oof-words nil) + (if forth-use-objects forth-objects-words nil))) + (setq forth-indent-words (append + forth-custom-indent-words forth-indent-words))) + + + ;; get location of first character of previous forth word that's got ;; properties (defun forth-previous-start (pos) @@ -353,7 +423,8 @@ PARSED-TYPE specifies what kind of text ;; Delete all properties, used by Forth mode, from `from' to `to'. (defun forth-delete-properties (from to) (remove-text-properties - from to '(face nil forth-parsed nil forth-word nil forth-state nil))) + from to '(face nil fontified nil + forth-parsed nil forth-word nil forth-state nil))) ;; Get the index of the branch of the most recently evaluated regular ;; expression that matched. (used for identifying branches "a\\|b\\|c...") @@ -421,11 +492,9 @@ PARSED-TYPE specifies what kind of text ;; Search for known Forth words in the range `from' to `to', using ;; `forth-next-known-forth-word' and set their properties via ;; `forth-set-word-properties'. -(defun forth-update-properties (from to) +(defun forth-update-properties (from to &optional loudly) (save-excursion - (let ((msg-flag nil) (state) (word-descr) (last-location)) - (when (> to (+ from 5000)) - (setq msg-flag t) (message "Parsing Forth code...")) + (let ((msg-count 0) (state) (word-descr) (last-location)) (goto-char (forth-previous-word (forth-previous-start (max (point-min) (1- from))))) (setq to (forth-next-end (min (point-max) (1+ to)))) @@ -434,8 +503,14 @@ PARSED-TYPE specifies what kind of text (setq state (get-text-property (point) 'forth-state)) (setq last-location (point)) (forth-delete-properties (point) to) + (put-text-property (point) to 'fontified t) ;; hilight loop... (while (setq word-descr (forth-next-known-forth-word to)) + (when loudly + (when (equal 0 (% msg-count 100)) + (message "Parsing Forth code...%s" + (make-string (/ msg-count 100) ?.))) + (setq msg-count (1+ msg-count))) (forth-set-word-properties state word-descr) (when state (put-text-property last-location (point) 'forth-state t)) (let ((type (car word-descr))) @@ -452,7 +527,6 @@ PARSED-TYPE specifies what kind of text to 'forth-state (current-buffer) (point-max)))) (forth-update-properties to extend-to)) )) - (when msg-flag (message "Parsing Forth code...done")) ))) ;; save-buffer-state borrowed from `font-lock.el' @@ -471,14 +545,21 @@ PARSED-TYPE specifies what kind of text ;; Function that is added to the `change-functions' hook. Calls ;; `forth-update-properties' and keeps care of disabling undo information ;; and stuff like that. -(defun forth-change-function (from to len) +(defun forth-change-function (from to len &optional loudly) + (save-match-data + (forth-save-buffer-state + () + (unless forth-disable-parser (forth-update-properties from to loudly)) + (forth-update-warn-long-lines)))) + +(defun forth-fontification-function (from) + "Function to be called from `fontification-functions' of Emacs 21." (save-match-data - (forth-save-buffer-state () - (unwind-protect - (progn - (forth-update-properties from to) - (forth-update-show-screen) - (forth-update-warn-long-lines)))))) + (forth-save-buffer-state + ((to (min (point-max) (+ from 100)))) + (unless (or forth-disable-parser (not forth-jit-parser) + (get-text-property from 'fontified)) + (forth-update-properties from to))))) (eval-when-compile (byte-compile 'forth-set-word-properties) @@ -487,6 +568,44 @@ PARSED-TYPE specifies what kind of text (byte-compile 'forth-delete-properties) (byte-compile 'forth-get-regexp-branch)) +;;; imenu support +;;; +(defvar forth-defining-words + '("VARIABLE" "CONSTANT" "2VARIABLE" "2CONSTANT" "FVARIABLE" "FCONSTANT" + "USER" "VALUE" "field" "end-struct" "VOCABULARY" "CREATE" ":" "CODE" + "DEFER" "ALIAS") + "List of words, that define the following word. +Used for imenu index generation.") + + +(defun forth-next-definition-starter () + (progn + (let* ((pos (re-search-forward forth-defining-words-regexp (point-max) t))) + (if pos + (if (or (text-property-not-all (match-beginning 0) (match-end 0) + 'forth-parsed nil) + (text-property-not-all (match-beginning 0) (match-end 0) + 'forth-state nil)) + (forth-next-definition-starter) + t) + nil)))) + +(defun forth-create-index () + (let* ((forth-defining-words-regexp + (concat "\\<\\(" (regexp-opt forth-defining-words) "\\)\\>")) + (index nil)) + (goto-char (point-min)) + (while (forth-next-definition-starter) + (if (looking-at "[ \t]*\\([^ \t\n]+\\)") + (setq index (cons (cons (match-string 1) (point)) index)))) + index)) + +(unwind-protect + (progn + (require 'speedbar) + (speedbar-add-supported-extension ".fs") + (speedbar-add-supported-extension ".fb"))) + ;; (require 'profile) ;; (setq profile-functions-list '(forth-set-word-properties forth-next-known-forth-word forth-update-properties forth-delete-properties forth-get-regexp-branch)) @@ -496,12 +615,17 @@ PARSED-TYPE specifies what kind of text (defvar forth-indent-words nil "List of words that have indentation behaviour. 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. If it's a REGEXP, it should not be surrounded by `\\<` or `\\>`, since 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, following any number of whitespaces. @@ -520,24 +644,37 @@ INDENT1 and INDENT2 are indentation spec 1 * forth-indent-level + forth-minor-indent-level columns to the right.") (setq forth-indent-words - '(((":" ":noname" "code" "if" "begin" "do" "?do" "+do" "-do" "u+do" - "u-do" "?dup-if" "?dup-0=-if" "case" "of" "try" "struct" - "[if]" "[ifdef]" "[ifundef]" "[begin]" "[for]" "[do]" "[?do]" - "class" "interface" "m:" ":m") + '((("if" "begin" "do" "?do" "+do" "-do" "u+do" + "u-do" "?dup-if" "?dup-0=-if" "case" "of" "try" + "[if]" "[ifdef]" "[ifundef]" "[begin]" "[for]" "[do]" "[?do]") (0 . 2) (0 . 2)) - ((";" ";m") (0 . -2) (0 . -2)) - (("end-code" "again" "repeat" "then" "endtry" "endcase" "endof" - "end-struct" "[then]" "[endif]" "[loop]" "[+loop]" "[next]" - "[until]" "[repeat]" "[again]" "end-class" "end-interface" - "end-class-noname" "end-interface-noname" "loop" - "class;") + ((":" ":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)) + (("again" "repeat" "then" "endtry" "endcase" "endof" + "[then]" "[endif]" "[loop]" "[+loop]" "[next]" + "[until]" "[repeat]" "[again]" "loop") (-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)) (("else" "recover" "[else]") (-2 . 2) (0 . 0)) (("while" "does>" "[while]") (-1 . 1) (0 . 0)) (("\\g") (-2 . 2) (0 . 0)))) +(defvar forth-local-indent-words nil + "List of Forth words to prepend to `forth-indent-words', when a forth-mode +buffer is created. Should be set by a Forth source, using a local variables +list at the end of the file (\"Local Variables: ... forth-local-words: ... +End:\" construct).") + +(defvar forth-custom-indent-words nil + "List of Forth words to prepend to `forth-indent-words'. Should be set in + your .emacs.") + (defvar forth-indent-level 4 "Indentation of Forth statements.") (defvar forth-minor-indent-level 2 @@ -561,12 +698,19 @@ INDENT1 and INDENT2 are indentation spec (let* ((regexp (car forth-compiled-indent-words)) (pos (re-search-forward regexp to t))) (if pos - (if (text-property-not-all (match-beginning 0) (match-end 0) - 'forth-parsed nil) - (forth-next-known-indent-word to) - (let* ((branch (forth-get-regexp-branch)) - (descr (cdr forth-compiled-indent-words)) - (indent (cdr (assoc branch descr)))) + (let* ((start (match-beginning 0)) + (end (match-end 0)) + (branch (forth-get-regexp-branch)) + (descr (cdr forth-compiled-indent-words)) + (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)) (nth 0 indent) (nth 1 indent)))) nil))) @@ -614,8 +758,7 @@ INDENT1 and INDENT2 are indentation spec (defun forth-get-anchor-column () (save-excursion (if (/= 0 (forward-line -1)) 0 - (let ((next-indent) - (self-indent)) + (let ((indent)) (while (not (or (setq indent (forth-get-column-incr 1)) (<= (point) (point-min)))) (forward-line -1)) @@ -627,9 +770,15 @@ INDENT1 and INDENT2 are indentation spec (column-incr (forth-get-column-incr 0))) (forth-indent-to (if column-incr (+ anchor column-incr) anchor)))) +(defun forth-current-column () + (- (point) (save-excursion (beginning-of-line) (point)))) +(defun forth-current-indentation () + (- (save-excursion (beginning-of-line) (forward-to-indentation 0) (point)) + (save-excursion (beginning-of-line) (point)))) + (defun forth-indent-to (x) (let ((p nil)) - (setq p (- (current-column) (current-indentation))) + (setq p (- (forth-current-column) (forth-current-indentation))) (forth-delete-indentation) (beginning-of-line) (indent-to x) @@ -653,10 +802,13 @@ INDENT1 and INDENT2 are indentation spec ;; insert newline, removing any trailing whitespaces in the current line (defun forth-newline-remove-trailing () - (newline) (save-excursion - (forward-line -1) - (forth-remove-trailing))) + (delete-region (point) (progn (skip-chars-backward " \t") (point)))) + (newline)) +; (let ((was-point (point-marker))) +; (unwind-protect +; (progn (forward-line -1) (forth-remove-trailing)) +; (goto-char (was-point))))) ;; workaround for bug in `reindent-then-newline-and-indent' (defun forth-reindent-then-newline-and-indent () @@ -769,7 +921,7 @@ done by checking whether the first line (save-restriction (widen) (save-excursion - (beginning-of-buffer) + (goto-char (point-min)) (end-of-line) (>= (current-column) 1024)))) @@ -807,9 +959,9 @@ screen number." (setq overlay-arrow-string forth-overlay-arrow-string) (goto-line first-line) (setq overlay-arrow-position forth-screen-marker) - (when (/= forth-screen-marker (point)) - (message "Entered screen #%i" scr) - (set-marker forth-screen-marker (point))))))) + (set-marker forth-screen-marker + (save-excursion (goto-line first-line) (point))) + (setq forth-screen-number-string (format "%d" scr)))))) (add-hook 'forth-motion-hooks 'forth-update-show-screen) @@ -822,6 +974,13 @@ exceeds 64 characters." forth-c/l)))) (add-hook 'forth-motion-hooks 'forth-update-warn-long-lines) + +(defvar forth-was-point nil) +(defun forth-check-motion () + "Run `forth-motion-hooks', if `point' changed since last call." + (when (or (eq forth-was-point nil) (/= forth-was-point (point))) + (setq forth-was-point (point)) + (run-hooks 'forth-motion-hooks))) ;;; End block file editing @@ -849,41 +1008,6 @@ exceeds 64 characters." (define-key forth-mode-map "\M-q" 'forth-fill-paragraph) (define-key forth-mode-map "\e." 'forth-find-tag) -;;; hook into motion events (realy ugly!) (dk) -(define-key forth-mode-map "\C-n" 'forth-next-line) -(define-key forth-mode-map "\C-p" 'forth-previous-line) -(define-key forth-mode-map [down] 'forth-next-line) -(define-key forth-mode-map [up] 'forth-previous-line) -(define-key forth-mode-map "\C-f" 'forth-forward-char) -(define-key forth-mode-map "\C-b" 'forth-backward-char) -(define-key forth-mode-map [right] 'forth-forward-char) -(define-key forth-mode-map [left] 'forth-backward-char) -(define-key forth-mode-map "\M-f" 'forth-forward-word) -(define-key forth-mode-map "\M-b" 'forth-backward-word) -(define-key forth-mode-map [C-right] 'forth-forward-word) -(define-key forth-mode-map [C-left] 'forth-backward-word) -(define-key forth-mode-map "\M-v" 'forth-scroll-down) -(define-key forth-mode-map "\C-v" 'forth-scroll-up) -(define-key forth-mode-map [prior] 'forth-scroll-down) -(define-key forth-mode-map [next] 'forth-scroll-up) - -(defun forth-next-line (arg) - (interactive "p") (next-line arg) (run-hooks 'forth-motion-hooks)) -(defun forth-previous-line (arg) - (interactive "p") (previous-line arg) (run-hooks 'forth-motion-hooks)) -(defun forth-backward-char (arg) - (interactive "p") (backward-char arg) (run-hooks 'forth-motion-hooks)) -(defun forth-forward-char (arg) - (interactive "p") (forward-char arg) (run-hooks 'forth-motion-hooks)) -(defun forth-forward-word (arg) - (interactive "p") (forward-word arg) (run-hooks 'forth-motion-hooks)) -(defun forth-backward-word (arg) - (interactive "p") (backward-word arg) (run-hooks 'forth-motion-hooks)) -(defun forth-scroll-down (arg) - (interactive "P") (scroll-down arg) (run-hooks 'forth-motion-hooks)) -(defun forth-scroll-up (arg) - (interactive "P") (scroll-up arg) (run-hooks 'forth-motion-hooks)) - ;setup for C-h C-i to work (if (fboundp 'info-lookup-add-help) (info-lookup-add-help @@ -898,8 +1022,11 @@ exceeds 64 characters." (defun forth-find-tag (tagname &optional next-p regexp-p) (interactive (find-tag-interactive "Find tag: ")) + (unless (or regexp-p next-p) + (setq tagname (concat "\\(^\\|\\s-\\)\\(" (regexp-quote tagname) + "\\)\\(\\s-\\|$\\)"))) (switch-to-buffer - (find-tag-noselect (concat " " tagname " ") next-p regexp-p))) + (find-tag-noselect tagname next-p t))) (defvar forth-mode-syntax-table nil "Syntax table in use in Forth-mode buffers.") @@ -944,32 +1071,35 @@ exceeds 64 characters." (setq comment-indent-hook 'forth-comment-indent) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments t) - (setq case-fold-search t) + (make-local-variable 'forth-was-point) + (setq forth-was-point -1) (make-local-variable 'forth-words) (make-local-variable 'forth-compiled-words) (make-local-variable 'forth-compiled-indent-words) (make-local-variable 'forth-hilight-level) (make-local-variable 'after-change-functions) + (make-local-variable 'post-command-hook) (make-local-variable 'forth-show-screen) (make-local-variable 'forth-screen-marker) (make-local-variable 'forth-warn-long-lines) + (make-local-variable 'forth-screen-number-string) + (make-local-variable 'forth-use-oof) + (make-local-variable 'forth-use-objects) (setq forth-screen-marker (copy-marker 0)) -) + (add-hook 'after-change-functions 'forth-change-function) + (add-hook 'post-command-hook 'forth-check-motion) + (if (>= emacs-major-version 21) + (add-hook 'fontification-functions 'forth-fontification-function)) + (setq imenu-create-index-function 'forth-create-index)) -(defun forth-mode-hook-dependent-variables () - (setq forth-compiled-words - (forth-compile-words (forth-filter 'forth-words-filter forth-words))) - (setq forth-compiled-indent-words - (forth-compile-words forth-indent-words))) - ;;;###autoload (defun forth-mode () " Major mode for editing Forth code. Tab indents for Forth code. Comments are delimited with \\ and newline. Paragraphs are separated by blank lines -only. Block files are autodetected, when read, and converted to normal stream -source format. See also `forth-block-mode'. +only. Block files are autodetected, when read, and converted to normal +stream source format. See also `forth-block-mode'. \\{forth-mode-map} Forth-split Positions the current buffer on top and a forth-interaction window @@ -1000,36 +1130,59 @@ Variables controlling interaction and st Variables controlling syntax hilighting/recognition of parsed text: `forth-words' List of words that have a special parsing behaviour and/or should be - hilighted. - forth-objects-words - Hilighting information for the words of the \"Objects\" package for - object-oriented programming. Append it to `forth-words', if required. - forth-oof-words - Hilighting information for the words of the \"OOF\" package. + hilighted. Add custom words by setting forth-custom-words in your + .emacs, or by setting forth-local-words, in source-files' local + variables lists. + forth-use-objects + Set this variable to non-nil in your .emacs, or in a local variables + list, to hilight and recognize the words from the \"Objects\" package + for object-oriented programming. + forth-use-oof + Same as above, just for the \"OOF\" package. + forth-custom-words + List of custom Forth words to prepend to `forth-words'. Should be set + in your .emacs. + forth-local-words + List of words to prepend to `forth-words', whenever a forth-mode + buffer is created. That variable should be set by Forth sources, using + a local variables list at the end of file, to get file-specific + hilighting. + 0 [IF] + Local Variables: ... + forth-local-words: ... + End: + [THEN] forth-hilight-level Controls how much syntax hilighting is done. Should be in the range - 0 (no hilighting) up to 3. + 0..3 Variables controlling indentation style: `forth-indent-words' List of words that influence indentation. + forth-local-indent-words + List of words to prepend to `forth-indent-words', similar to + forth-local-words. Should be used for specifying file-specific + indentation, using a local variables list. + forth-custom-indent-words + List of words to prepend to `forth-indent-words'. Should be set in your + .emacs. forth-indent-level Indentation increment/decrement of Forth statements. forth-minor-indent-level Minor indentation increment/decrement of Forth statemens. Variables controlling block-file editing: - `forth-show-screen' + forth-show-screen Non-nil means, that the start of the current screen is marked by an - overlay arrow, and motion over screen boundaries displays the number - of the screen entered. This variable is by default nil for `forth-mode' - and t for `forth-block-mode'. - `forth-overlay-arrow-string' + overlay arrow, and screen numbers are displayed in the mode line. + This variable is by default nil for `forth-mode' and t for + `forth-block-mode'. + forth-overlay-arrow-string String to display as the overlay arrow, when `forth-show-screen' is t. Setting this variable to nil disables the overlay arrow. - `forth-block-base' + forth-block-base Screen number of the first block in a block file. Defaults to 1. - `forth-warn-long-lines' + forth-warn-long-lines Non-nil means that a warning message is displayed whenever you edit or move over a line that is longer than 64 characters (the maximum line length that can be stored into a block file). This variable defaults to @@ -1064,11 +1217,9 @@ Variables controling documentation searc (forth-mode-variables) ; (if (not (forth-process-running-p)) ; (run-forth forth-program-name)) - (run-hooks 'forth-mode-hook) - (forth-mode-hook-dependent-variables) - (forth-change-function (point-min) (point-max) nil) - (add-hook 'after-change-functions 'forth-change-function)) + (run-hooks 'forth-mode-hook)) +;;;###autoload (define-derived-mode forth-block-mode forth-mode "Forth Block Source" "Major mode for editing Forth block source files, derived from `forth-mode'. Differences to `forth-mode' are: @@ -1082,7 +1233,7 @@ echo area and the line is truncated. Another problem is imposed by block files that contain newline or tab characters. When Emacs converts such files back to block file format, -it'll translate those characters to a number of spaces. However, whenever +it'll translate those characters to a number of spaces. However, when you read such a file, a warning message is displayed in the echo area, including a line number that may help you to locate and fix the problem. @@ -1090,12 +1241,20 @@ So have a look at the *Messages* buffer, bell during block file read/write operations." (setq buffer-file-format '(forth-blocks)) (setq forth-show-screen t) - (setq forth-warn-long-lines t)) + (setq forth-warn-long-lines t) + (setq forth-screen-number-string (format "%d" forth-block-base)) + (setq mode-line-format (append (reverse (cdr (reverse mode-line-format))) + '("--S" forth-screen-number-string "-%-")))) (add-hook 'forth-mode-hook '(lambda () (make-local-variable 'compile-command) - (setq compile-command "gforth "))) + (setq compile-command "gforth ") + (forth-hack-local-variables) + (forth-customize-words) + (forth-compile-words) + (unless (and forth-jit-parser (>= emacs-major-version 21)) + (forth-change-function (point-min) (point-max) nil t)))) (defun forth-fill-paragraph () "Fill comments (starting with '\'; do not fill code (block style @@ -1726,4 +1885,3 @@ The region is sent terminated by a newli )) ;;; gforth.el ends here -