--- gforth/gforth.el 2001/04/08 13:48:11 1.48 +++ gforth/gforth.el 2001/05/18 15:27:21 1.50 @@ -58,7 +58,8 @@ "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. +OOP package you're using. 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 ...) @@ -224,6 +225,11 @@ PARSED-TYPE specifies what kind of text (("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-hilight-level 3 "*Level of hilighting of Forth code.") (defvar forth-compiled-words nil "Compiled representation of `forth-words'.") @@ -231,21 +237,9 @@ PARSED-TYPE specifies what kind of text ; ; 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 +; 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 +; word-lists. Using local variable list? ; ; Konfiguration über customization groups ; @@ -258,13 +252,13 @@ PARSED-TYPE specifies what kind of text (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 +290,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 +307,26 @@ 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 contens of the current +forth-mode buffer. Prepend `forth-local-words' to `forth-words' and +`forth-local-indent-words' to `forth-local-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))) + ;; get location of first character of previous forth word that's got ;; properties (defun forth-previous-start (pos) @@ -525,7 +539,7 @@ INDENT1 and INDENT2 are indentation spec "[if]" "[ifdef]" "[ifundef]" "[begin]" "[for]" "[do]" "[?do]" "class" "interface" "m:" ":m") (0 . 2) (0 . 2)) - ((";" ";m") (0 . -2) (0 . -2)) + ((";" ";m") (-2 . 0) (0 . -2)) (("end-code" "again" "repeat" "then" "endtry" "endcase" "endof" "end-struct" "[then]" "[endif]" "[loop]" "[+loop]" "[next]" "[until]" "[repeat]" "[again]" "end-class" "end-interface" @@ -538,6 +552,12 @@ INDENT1 and INDENT2 are indentation spec (("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-indent-level 4 "Indentation of Forth statements.") (defvar forth-minor-indent-level 2 @@ -627,9 +647,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 +679,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 () @@ -807,9 +836,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) @@ -944,7 +973,6 @@ 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-words) (make-local-variable 'forth-compiled-words) @@ -954,22 +982,17 @@ exceeds 64 characters." (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) (setq forth-screen-marker (copy-marker 0)) -) + (add-hook 'after-change-functions 'forth-change-function)) -(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 @@ -1001,18 +1024,32 @@ Variables controlling syntax hilighting/ `forth-words' List of words that have a special parsing behaviour and/or should be hilighted. + 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-objects-words Hilighting information for the words of the \"Objects\" package for - object-oriented programming. Append it to `forth-words', if required. + object-oriented programming. Append it to `forth-words', if you need + it. forth-oof-words Hilighting information for the words of the \"OOF\" package. forth-hilight-level Controls how much syntax hilighting is done. Should be in the range - 0 (no hilighting) up to 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-indent-level Indentation increment/decrement of Forth statements. forth-minor-indent-level @@ -1021,9 +1058,9 @@ Variables controlling indentation style: Variables controlling block-file editing: `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'. + 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. @@ -1064,11 +1101,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 +1117,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 +1125,18 @@ 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-compile-words) + (forth-change-function (point-min) (point-max) nil))) (defun forth-fill-paragraph () "Fill comments (starting with '\'; do not fill code (block style