| ;; This file is part of GNU Emacs. |
;; Forth mode for Emacs |
| ;; Changes by anton |
|
| ;; This is a variant of forth.el that came with TILE. |
;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc. |
| ;; 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. |
|
| |
|
| ;; GNU Emacs is distributed in the hope that it will be useful, |
;; 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 |
;; but WITHOUT ANY WARRANTY. No author or distributor |
| ;; accepts responsibility to anyone for the consequences of using it |
;; accepts responsibility to anyone for the consequences of using it |
| ;; or for whether it serves any particular purpose or works at all, |
;; or for whether it serves any particular purpose or works at all, |
| ;; Everyone is granted permission to copy, modify and redistribute |
;; Everyone is granted permission to copy, modify and redistribute |
| ;; GNU Emacs, but only under the conditions described in the |
;; GNU Emacs, but only under the conditions described in the |
| ;; GNU Emacs General Public License. A copy of this license is |
;; GNU Emacs General Public License. A copy of this license is |
| ;; supposed to have been given to you along with GNU Emacs so you |
;; supposed to have been given to you along with Gforth so you |
| ;; can know your rights and responsibilities. It should be in a |
;; can know your rights and responsibilities. It should be in a |
| ;; file named COPYING. Among other things, the copyright notice |
;; file named COPYING. Among other things, the copyright notice |
| ;; and this notice must be preserved on all copies. |
;; and this notice must be preserved on all copies. |
| |
|
| ;;; $Header$ |
;; 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 |
;; A Forth indentation, documentation search and interaction library |
| |
|
| |
|
| (defvar forth-positives |
(defvar forth-positives |
| " : :noname begin do ?do while if ?dup-if ?dup-not-if else case create does> exception> struct [if] [else] " |
" : :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 |
"*Contains all words which will cause the indent-level to be incremented |
| on the next line. |
on the next line. |
| OBS! All words in forth-positives must be surrounded by spaces.") |
OBS! All words in forth-positives must be surrounded by spaces.") |
| |
|
| (defvar forth-negatives |
(defvar forth-negatives |
| " ; until repeat while +loop loop s+loop else then endif again endcase does> end-struct [then] [else] " |
" ; ;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 |
"*Contains all words which will cause the indent-level to be decremented |
| on the current line. |
on the current line. |
| OBS! All words in forth-negatives must be surrounded by spaces.") |
OBS! All words in forth-negatives must be surrounded by spaces.") |
| |
|
| (defvar forth-zeroes |
(defvar forth-zeroes |
| " : :noname " |
" : :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) |
| |
|
| |
(defvar forth-zup |
| |
" how: implements " |
| |
"Contains all words which causes zero indent level to change") |
| |
|
| |
(defvar forth-zdown |
| |
" class; how: class public: private: " |
| |
"Contains all words which causes zero indent level to change") |
| |
|
| (defvar forth-prefixes |
(defvar forth-prefixes |
| " postpone [compile] ['] [char] " |
" postpone [compile] ['] [char] " |
| (if (not forth-mode-map) |
(if (not forth-mode-map) |
| (setq forth-mode-map (make-sparse-keymap))) |
(setq forth-mode-map (make-sparse-keymap))) |
| |
|
| (global-set-key "\e\C-m" 'forth-send-paragraph) |
|
| (global-set-key "\C-x\C-m" 'forth-split) |
|
| (global-set-key "\e " 'forth-reload) |
|
| |
|
| ;(define-key forth-mode-map "\M-\C-x" 'compile) |
;(define-key forth-mode-map "\M-\C-x" 'compile) |
| (define-key forth-mode-map "\C-x\\" 'comment-region) |
(define-key forth-mode-map "\C-x\\" 'comment-region) |
| (define-key forth-mode-map "\C-x|" 'uncomment-region) |
|
| (define-key forth-mode-map "\C-x~" 'forth-remove-tracers) |
(define-key forth-mode-map "\C-x~" 'forth-remove-tracers) |
| (define-key forth-mode-map "\e\C-m" 'forth-send-paragraph) |
(define-key forth-mode-map "\e\C-m" 'forth-send-paragraph) |
| (define-key forth-mode-map "\eo" 'forth-send-buffer) |
(define-key forth-mode-map "\eo" 'forth-send-buffer) |
| (define-key forth-mode-map "\t" 'forth-indent-command) |
(define-key forth-mode-map "\t" 'forth-indent-command) |
| (define-key forth-mode-map "\C-m" 'reindent-then-newline-and-indent) |
(define-key forth-mode-map "\C-m" 'reindent-then-newline-and-indent) |
| (define-key forth-mode-map "\M-q" 'forth-fill-paragraph) |
(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) |
| |
(interactive (find-tag-interactive "Find tag: ")) |
| |
(switch-to-buffer |
| |
(find-tag-noselect (concat " " tagname " ") next-p regexp-p))) |
| |
|
| (defvar forth-mode-syntax-table nil |
(defvar forth-mode-syntax-table nil |
| "Syntax table in use in Forth-mode buffers.") |
"Syntax table in use in Forth-mode buffers.") |
| ;only supports one comment syntax (and a hack to accomodate C++); I |
;only supports one comment syntax (and a hack to accomodate C++); I |
| ;use '\' for natural language comments and '(' for formal comments |
;use '\' for natural language comments and '(' for formal comments |
| ;like stack comments, so for me it's better to have emacs treat '\' |
;like stack comments, so for me it's better to have emacs treat '\' |
| ;comments as comments. I you want it different, make the appropriate |
;comments as comments. If you want it different, make the appropriate |
| ;changes (best in your .emacs file). |
;changes (best in your .emacs file). |
| ; |
; |
| ;Hmm, the C++ hack could be used to support both comment syntaxes: we |
;Hmm, the C++ hack could be used to support both comment syntaxes: we |
| " |
" |
| Major mode for editing Forth code. Tab indents for Forth code. Comments |
Major mode for editing Forth code. Tab indents for Forth code. Comments |
| are delimited with \\ and newline. Paragraphs are separated by blank lines |
are delimited with \\ and newline. Paragraphs are separated by blank lines |
| only. Delete converts tabs to spaces as it moves back. |
only. |
| \\{forth-mode-map} |
\\{forth-mode-map} |
| Forth-split |
Forth-split |
| Positions the current buffer on top and a forth-interaction window |
Positions the current buffer on top and a forth-interaction window |
| (beginning-of-line) |
(beginning-of-line) |
| (while (and |
(while (and |
| (= (forward-line -1) 0) |
(= (forward-line -1) 0) |
| (looking-at "[ \t]*\\\\[ \t]+"))) |
(looking-at "[ \t]*\\\\g?[ \t]+"))) |
| (if (not (looking-at "[ \t]*\\\\[ \t]+")) |
(if (not (looking-at "[ \t]*\\\\g?[ \t]+")) |
| (forward-line 1)) |
(forward-line 1)) |
| (let ((from (point)) |
(let ((from (point)) |
| (to (save-excursion (forward-paragraph) (point)))) |
(to (save-excursion (forward-paragraph) (point)))) |
| (if (looking-at "[ \t]*\\\\[ \t]+") |
(if (looking-at "[ \t]*\\\\g?[ \t]+") |
| (progn (goto-char (match-end 0)) |
(progn (goto-char (match-end 0)) |
| (set-fill-prefix) |
(set-fill-prefix) |
| (fill-region from to nil)))))) |
(fill-region from to nil)))))) |
| (regexp-quote (concat " " w1 " ")) |
(regexp-quote (concat " " w1 " ")) |
| forth-negatives) |
forth-negatives) |
| forth-indent-level 0))) |
forth-indent-level 0))) |
| |
(if (string-match (regexp-quote (concat " " w1 " ")) forth-zdown) |
| |
(setq forth-zero 0)) |
| (if (string-match (regexp-quote (concat " " w1 " ")) forth-zeroes) |
(if (string-match (regexp-quote (concat " " w1 " ")) forth-zeroes) |
| (setq indent 0)) |
(setq indent forth-zero)) |
| |
(if (string-match (regexp-quote (concat " " w1 " ")) forth-zup) |
| |
(setq forth-zero 4)) |
| indent)) |
indent)) |
| |
|
| (defun forth-sum-line-indentation () |
(defun forth-sum-line-indentation () |
| (defun forth-remove-tracers () |
(defun forth-remove-tracers () |
| "Remove tracers of the form `~~ '. Queries the user for each occurrence." |
"Remove tracers of the form `~~ '. Queries the user for each occurrence." |
| (interactive) |
(interactive) |
| (query-replace "~~ " "")) |
(query-replace-regexp "\\(~~ \\| ~~$\\)" "" nil)) |
| |
|
| (defvar forth-program-name "gforth" |
(defvar forth-program-name "gforth" |
| "*Program invoked by the `run-forth' command.") |
"*Program invoked by the `run-forth' command.") |
| (forth-split) |
(forth-split) |
| (forth-set-runlight forth-runlight:input)) |
(forth-set-runlight forth-runlight:input)) |
| |
|
| |
(defun run-forth-if-not () |
| |
(if (not (forth-process-running-p)) |
| |
(run-forth forth-program-name))) |
| |
|
| (defun reset-forth () |
(defun reset-forth () |
| "Reset the Forth process." |
"Reset the Forth process." |
| (interactive) |
(interactive) |
| (message "Resetting Forth process...done"))))) |
(message "Resetting Forth process...done"))))) |
| |
|
| (defun forth-default-command-line () |
(defun forth-default-command-line () |
| (concat forth-program-name " -emacs" |
(concat forth-program-name |
| (if forth-program-arguments |
(if forth-program-arguments |
| (concat " " forth-program-arguments) |
(concat " " forth-program-arguments) |
| "") |
|
| (if forth-band-name |
|
| (concat " -band " forth-band-name) |
|
| ""))) |
""))) |
| |
|
| ;;;; Internal Variables |
;;;; Internal Variables |
| (interactive) |
(interactive) |
| (let ((process (get-process forth-program-name))) |
(let ((process (get-process forth-program-name))) |
| (if process (kill-process process t))) |
(if process (kill-process process t))) |
| (sleep-for-millisecs 100) |
(sleep-for 0 100) |
| (forth-mode)) |
(forth-mode)) |
| |
|
| |
|
| (compile1 ctools-compile-command "No more errors")) |
(compile1 ctools-compile-command "No more errors")) |
| |
|
| |
|
| |
;;; Forth menu |
| |
;;; Mikael Karlsson <qramika@eras70.ericsson.se> |
| |
|
| |
(cond ((string-match "XEmacs\\|Lucid" emacs-version) |
| |
(require 'func-menu) |
| |
|
| |
(defconst fume-function-name-regexp-forth |
| |
"^\\(:\\)[ \t]+\\([^ \t]*\\)" |
| |
"Expression to get word definitions in Forth.") |
| |
|
| |
(setq fume-function-name-regexp-alist |
| |
(append '((forth-mode . fume-function-name-regexp-forth) |
| |
) fume-function-name-regexp-alist)) |
| |
|
| |
;; Find next forth word in the buffer |
| |
(defun fume-find-next-forth-function-name (buffer) |
| |
"Searches for the next forth word in BUFFER." |
| |
(set-buffer buffer) |
| |
(if (re-search-forward fume-function-name-regexp nil t) |
| |
(let ((beg (match-beginning 2)) |
| |
(end (match-end 2))) |
| |
(cons (buffer-substring beg end) beg)))) |
| |
|
| |
(setq fume-find-function-name-method-alist |
| |
(append '((forth-mode . fume-find-next-forth-function-name)))) |
| |
|
| |
)) |
| |
;;; End Forth menu |
| |
|
| |
;;; File folding of forth-files |
| |
;;; uses outline |
| |
;;; Toggle activation with M-x fold-f (when editing a forth-file) |
| |
;;; Use f9 to expand, f10 to hide, Or the menubar in xemacs |
| |
;;; |
| |
;;; Works most of the times but loses sync with the cursor occasionally |
| |
;;; Could be improved by also folding on comments |
| |
|
| |
(require 'outline) |
| |
|
| |
(defun f-outline-level () |
| |
(cond ((looking-at "\\`\\\\") |
| |
0) |
| |
((looking-at "\\\\ SEC") |
| |
0) |
| |
((looking-at "\\\\ \\\\ .*") |
| |
0) |
| |
((looking-at "\\\\ DEFS") |
| |
1) |
| |
((looking-at "\\/\\* ") |
| |
1) |
| |
((looking-at ": .*") |
| |
1) |
| |
((looking-at "\\\\G") |
| |
2) |
| |
((looking-at "[ \t]+\\\\") |
| |
3)) |
| |
) |
| |
|
| |
(defun fold-f () |
| |
(interactive) |
| |
(add-hook 'outline-minor-mode-hook 'hide-body) |
| |
|
| |
; outline mode header start, i.e. find word definitions |
| |
;;; (setq outline-regexp "^\\(:\\)[ \t]+\\([^ \t]*\\)") |
| |
(setq outline-regexp "\\`\\\\\\|:\\|\\\\ SEC\\|\\\\G\\|[ \t]+\\\\\\|\\\\ DEFS\\|\\/\\*\\|\\\\ \\\\ .*") |
| |
(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 global-map '(shift up) 'fold-f) |
| |
|
| |
;;; end file folding |
| |
|
| |
;;; func-menu is a package that scans your source file for function definitions |
| |
;;; and makes a menubar entry that lets you jump to any particular function |
| |
;;; definition by selecting it from the menu. The following code turns this on |
| |
;;; for all of the recognized languages. Scanning the buffer takes some time, |
| |
;;; but not much. |
| |
;;; |
| |
(cond ((string-match "XEmacs\\|Lucid" emacs-version) |
| |
(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) |
| |
)) |
| |
|
| |
;;; Highlighting |
| |
|
| |
(if (not (file-exists-p "/usr/share/emacs/site-lisp/hl319.el")) |
| |
(require 'hilit19) |
| |
(require 'hl319)) |
| |
|
| |
(hilit-set-mode-patterns |
| |
'(forth-mode) |
| |
(append |
| |
'(("\\\\ \\(.*\\)$" nil comment)) ; comments |
| |
'(("\\\\[gG] \\(.*\\)$" nil comment)) ; comments |
| |
'(("(\\( [^)\n]* \\| \\)--\\( [^)\n]* \\| \\))" nil decl)) |
| |
'(("( " ")" comment)) |
| |
'(("\" [^\"\n]*\"" nil string)) |
| |
'(("\\(\\[IF]\\|\\[IFDEF]\\|\\[IFUNDEF]\\|\\[ELSE]\\|\\[THEN]\\|IF\\|ELSE\\|THEN\\|CASE\\|ENDCASE\\|OF\\|ENDOF\\|BEGIN\\|WHILE\\|REPEAT\\|UNTIL\\|AGAIN\\|DOES>\\|?DO\\|DO\\|\+LOOP\\|UNLOOP\\|LOOP\\|EXIT\\)" nil keyword)) |
| |
'(("\\(\\[if]\\|\\[ifdef]\\|\\[ifundef]\\|\\[else]\\|\\[then]\\|if\\|else\\|then\\|case\\|endcase\\|of\\|endof\\|begin\\|while\\|repeat\\|until\\|again\\|does>\\|?do\\|do\\|\+loop\\|unloop\\|loop\\|exit\\)" nil keyword)) |
| |
'((": *[^ \n]*" nil defun)) |
| |
'(("Defer *[^ \n]*" nil defun)) |
| |
'(("\\(Variable\\|Constant\\|Value\\|Create\\) *[^ \n]*" nil define)) |
| |
'(("\\(include\\|require\\) *[^ \n]*" nil include)) |
| |
'(("[\n ]\\(\\$[0-9A-Fa-f]+[\n ]\\|&[0-9]+[\n ]\\|[0-9]+[\n ]\\|%[01]+[\n ]\\|'[^ \n]+\\)+" nil formula)) |
| |
'((":noname" nil defun)))) |
| |
|
| |
;; end |
| |
|