summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiotr Szarmanski2023-05-02 10:31:10 +0200
committerPiotr Szarmanski2023-05-02 10:31:10 +0200
commitfc2409a3d82c0b8c983735ecbf584d811497180c (patch)
tree1f9a9c50190aef207edd690d0684111bc109770b
parent7fc3f3f78cb6c7615b6f8f678d05ae065e38618f (diff)
add downloaded pkgs into repo
-rw-r--r--pkgs/gforth.el1683
-rw-r--r--pkgs/webjump-ido.el143
2 files changed, 1826 insertions, 0 deletions
diff --git a/pkgs/gforth.el b/pkgs/gforth.el
new file mode 100644
index 0000000..d9c6fbb
--- /dev/null
+++ b/pkgs/gforth.el
@@ -0,0 +1,1683 @@
+;;; gforth.el --- major mode for editing (G)Forth sources
+
+;; Authors: Bernd Paysan, Anton Ertl, David Kühling
+;; Copyright (C) 1995,1996,1997,1998,2000,2001,2003,2004,2007,2008,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 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
+;; accepts responsibility to anyone for the consequences of using it
+;; or for whether it serves any particular purpose or works at all,
+;; unless he says so in writing. Refer to the GNU Emacs General Public
+;; License for full details.
+
+;; Everyone is granted permission to copy, modify and redistribute
+;; GNU Emacs, but only under the conditions described in the
+;; GNU Emacs General Public License. A copy of this license is
+;; supposed to have been given to you along with Gforth so you
+;; can know your rights and responsibilities. It should be in a
+;; file named COPYING. Among other things, the copyright notice
+;; and this notice must be preserved on all copies.
+
+;; Author: Goran Rydqvist <gorry@ida.liu.se>
+;; Maintainer: David Kühling <dvdkhlng@gmx.de>
+;; Created: 16 July 88 by Goran Rydqvist
+;; Keywords: forth, 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.
+
+;; Changes by David
+;; Added a syntax-hilighting engine, rewrote auto-indentation engine.
+;; Added support for block files.
+;; Replaced forth-process code with comint-based implementation.
+
+;; Tested with Emacs 25, 26
+;; The last version with support for Emacs <21 is in commit
+;; 8ebfcc8f5efcbdf2aaef807b7968f4ca8efa6516
+
+;;-------------------------------------------------------------------
+;; A Forth indentation, documentation search and interaction library
+;;-------------------------------------------------------------------
+;;
+;; Written by Goran Rydqvist, gorry@ida.liu.se, Summer 1988
+;; Started: 16 July 88
+;; Version: 2.10
+;; Last update: 5 December 1989 by Mikael Patel, mip@ida.liu.se
+;; Last update: 25 June 1990 by Goran Rydqvist, gorry@ida.liu.se
+;;
+;; Documentation: See forth-mode (^HF forth-mode)
+;;-------------------------------------------------------------------
+
+;;; Code:
+
+(require 'font-lock)
+(require 'ansi-color)
+
+; todo:
+;
+
+; 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
+; Wort liegen (?) -- speed!
+;
+; '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
+;
+; Folding neuschreiben (neue Parser-Informationen benutzen)
+
+;;; Motion-hooking (dk)
+;;;
+(defun forth-idle-function ()
+ "Function that is called when Emacs is idle to detect cursor motion
+in forth-block-mode buffers (which is mainly used for screen number
+display in). Currently ignores forth-mode buffers but that may change
+in the future."
+ (if (eq major-mode 'forth-block-mode)
+ (forth-check-motion)))
+
+(defvar forth-idle-function-timer nil
+ "Timer that runs `forth-idle-function' or nil if no timer installed.")
+
+(defun forth-install-motion-hook ()
+ "Install the motion-hooking mechanism. Currently uses idle timers
+but might be transparently changed in the future."
+ (unless forth-idle-function-timer
+ ;; install idle function only once (first time forth-mode is used)
+ (setq forth-idle-function-timer
+ (run-with-idle-timer .05 t 'forth-idle-function))))
+
+(defvar forth-was-point nil)
+
+(defun forth-check-motion ()
+ "Run `forth-motion-hooks', if `point' changed since last call. This
+used to be called via `post-command-hook' but uses idle timers now as
+users complaint about lagging performance."
+ (when (or (eq forth-was-point nil) (/= forth-was-point (point)))
+ (setq forth-was-point (point))
+ (run-hooks 'forth-motion-hooks)))
+
+
+;;; 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.
+
+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 ...)
+
+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 should be one of 'definiton-starter', 'definition-ender',
+ 'compile-only', 'immediate' or 'non-immediate'. Those
+ information are required to determine whether a word actually
+ parses (and whether that parsed text needs to be hilighted).
+
+HILIGHT is a cons cell of the form (FACE . MINIMUM-LEVEL) Where
+ MINIMUM-LEVEL specifies the minimum value of
+ `forth-hilight-level', that's required for matching text to be
+ hilighted.
+
+PARSED-TEXT specifies whether and how a word parses following
+ text. You can specify as many subsequent PARSED-TEXT as you
+ wish, but that shouldn't be necessary very often. It has the
+ following form:
+ (DELIM-REGEXP SKIP-LEADING-FLAG PARSED-TYPE HILIGHT)
+
+DELIM-REGEXP is a regular expression that should match strings of
+ length 1, which are delimiters for the parsed text.
+
+A non-nil value for PARSE-LEADING-FLAG means, that leading
+ delimiter strings before parsed text should be skipped. This
+ is the parsing behaviour of the Forth word WORD. Set it to t
+ for name-parsing words, nil for comments and strings.
+
+PARSED-TYPE specifies what kind of text is parsed. It should be
+ on of 'name', 'string' or 'comment'.")
+(setq forth-words
+ '(
+ (("[") definition-ender (font-lock-keyword-face . 1))
+ (("]" "]l") definition-starter (font-lock-keyword-face . 1))
+ ((":") definition-starter (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("to:") definition-starter (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("defer@:") definition-starter (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("event:") definition-starter (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("immediate" "compile-only" "restrict")
+ immediate (font-lock-keyword-face . 1))
+ (("does>") definition-starter (font-lock-keyword-face . 1))
+ ((":noname" "comp:" "compsem:" "opt:" "defer:" "defer@-opt:" "to-opt:") definition-starter (font-lock-keyword-face . 1))
+ ((";" ";code" ";abi-code") definition-ender (font-lock-keyword-face . 1))
+ (("include" "require" "needs" "use")
+ non-immediate (font-lock-keyword-face . 1)
+ "[\n\t ]" t string (font-lock-string-face . 1))
+ (("included" "required" "thru" "load")
+ non-immediate (font-lock-keyword-face . 1))
+ (("code" "abi-code")
+ non-immediate (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("end-code")
+ non-immediate (font-lock-keyword-face . 1))
+ (("[char]") compile-only (font-lock-keyword-face . 1)
+ "[ \t\n]" t string (font-lock-string-face . 1))
+ (("char") non-immediate (font-lock-keyword-face . 1)
+ "[ \t\n]" t string (font-lock-string-face . 1))
+ ("'.'?" non-immediate (font-lock-string-face . 1))
+ (("s\"" "c\"" "l\"" "x\"" "s\\\"") immediate (font-lock-string-face . 1)
+ "[\"\n]" nil string (font-lock-string-face . 1))
+ ((".\"" ".\\\"") compile-only (font-lock-string-face . 1)
+ "[\"\n]" nil string (font-lock-string-face . 1))
+ (("abort\"") compile-only (font-lock-keyword-face . 1)
+ "[\"\n]" nil string (font-lock-string-face . 1))
+ (("warning\"") compile-only (font-lock-keyword-face . 1)
+ "[\"\n]" nil string (font-lock-string-face . 1))
+ (("{" "{:" "[{:") compile-only (font-lock-variable-name-face . 1)
+ "[\n}]" nil name (font-lock-variable-name-face . 1))
+ ((".(" "(") immediate (font-lock-comment-face . 1)
+ ")" nil comment (font-lock-comment-face . 1))
+ (("\\" "\\G") immediate (font-lock-comment-face . 1)
+ "[\n]" nil comment (font-lock-comment-face . 1))
+ (("\\\\\\") immediate (font-lock-comment-face . 1)
+ "[\0]" nil comment (font-lock-comment-face . 1))
+
+ (("[if]" "[?do]" "[do]" "[for]" "[begin]"
+ "[endif]" "[then]" "[loop]" "[+loop]" "[next]" "[until]" "[repeat]"
+ "[again]" "[while]" "[else]" "[:"
+ "[n:l" "[n:h" "[n:d" "[d:l" "[d:h" "[d:d" "[f:l" "[f:h" "[f:d"
+ "[{:" ";]" "nope")
+ immediate (font-lock-keyword-face . 2))
+ (("[ifdef]" "[ifundef]" "[defined]" "[undefined]") immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("if" "begin" "ahead" "do" "?do" "+do" "u+do" "-do" "u-do" "for"
+ "case" "of" "?of" "?dup-if" "?dup-0=-if" "then" "endif" "until"
+ "repeat" "again" "leave" "?leave"
+ "loop" "+loop" "-loop" "next" "endcase" "next-case" "endof" "contof"
+ "else" "while" "try"
+ "recover" "endtry" "iferror" "restore" "endtry-iferror"
+ "assert(" "assert0(" "assert1(" "assert2("
+ "assert3(" ")" "<interpretation" "<compilation" "interpretation>"
+ "compilation>")
+ compile-only (font-lock-keyword-face . 2))
+
+ (("true" "false" "c/l" "bl" "cell" "pi" "w/o" "r/o" "r/w")
+ non-immediate (font-lock-constant-face . 2))
+ (("~~" "break:" "dbg" "???" "wtf??" "!!fixme!!" "~~bt" "~~1bt" "bt") 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))
+ (("is" "what's") immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("<is>" "'" "see") non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("[to]" "[+to]" "[addr]") compile-only (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("to" "+to" "addr") immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("<to>" "<+to>" "<addr>") non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+
+ (("create" "variable" "constant" "2variable" "2constant" "fvariable"
+ "$variable" "$[]variable" "fconstant" "value" "2value" "fvalue"
+ "field" "user" "vocabulary" "cs-vocabulary" "create-interpret/compile"
+ "interpret/compile:" "debug:" "field:" "2field:" "ffield:"
+ "sffield:" "dffield:" "uvar" "uvalue" "cfield:" "wfield:" "lfield:"
+ "+field" "value:" "cvalue:" "scvalue:" "wvalue:" "swvalue:"
+ "lvalue:" "slvalue:" "2value:" "fvalue:" "sfvalue:" "dfvalue:"
+ "$value:" "defer:" "value[]:" "$value[]:"
+ "wrap+value:")
+ non-immediate (font-lock-type-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("method" "umethod")
+ non-immediate (font-lock-type-face . 2)
+ "[ \t\n]" t name (font-lock-function-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))
+ (("synonym")
+ 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 . 2))
+ (("end-struct") non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-type-face . 3))
+ (("struct" "end-c-library" "c-library-name" "end-structure")
+ non-immediate (font-lock-keyword-face . 2))
+ (("c-library" "begin-structure" "extend-structure") non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("c-variable") 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))
+ (("c-function" "c-value") 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)
+ "[\n]" nil comment (font-lock-variable-name-face . 3))
+ (("c-callback") non-immediate (font-lock-type-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3)
+ "[\n]" nil comment (font-lock-variable-name-face . 3))
+ (("c-funptr") non-immediate (font-lock-type-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3)
+ "[}]" t name (font-lock-function-name-face . 3)
+ "[\n]" nil comment (font-lock-variable-name-face . 3))
+ (("\\c") non-immediate (font-lock-keyword-face . 1)
+ "[\n]" nil string (font-lock-string-face . 1))
+ ("-?[0-9a-f]+\\(\\.[0-9]*e\\(-?[0-9]+\\)?\\|\\.?[0-9a-f]*\\)"
+ immediate (font-lock-constant-face . 3))
+ ("-?\\([&#][0-9a-f.]+\\|\\(0x\\|\\$\\)[0-9a-f.]+\\|%[01]+\\)"
+ immediate (font-lock-constant-face . 3))
+ ("\\([&#]-?[0-9a-f.]+\\|\\(0x-?\\|\\$-?\\)[0-9a-f.]+\\|%-?[01]+\\)"
+ immediate (font-lock-constant-face . 3))
+ ("\"[^\"]**" immediate (font-lock-string-face . 1)
+ "[\"\n]" nil string (font-lock-string-face . 1))
+ ("\".*\""
+ immediate (font-lock-string-face . 3))
+ ("[a-z\-0-9]+(" immediate (font-lock-comment-face . 1)
+ ")" nil comment (font-lock-comment-face . 1))
+ ))
+
+(defvar forth-use-objects nil
+ "*Non-nil makes forth-mode also hilight words from the \"Objects\" package.")
+(defvar forth-objects-words
+ '(((":m") definition-starter (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("m:") definition-starter (font-lock-keyword-face . 1))
+ ((";m") definition-ender (font-lock-keyword-face . 1))
+ (("[current]" "[parent]") compile-only (font-lock-keyword-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("current" "overrides") non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("[to-inst]") compile-only (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("[bind]") compile-only (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-type-face . 3)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("bind") non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-type-face . 3)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("inst-var" "inst-value") non-immediate (font-lock-type-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("method" "selector" "umethod")
+ non-immediate (font-lock-type-face . 1)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("end-class" "end-interface")
+ non-immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-type-face . 3))
+ (("public" "protected" "class" "exitm" "implementation" "interface"
+ "methods" "end-methods" "this")
+ non-immediate (font-lock-keyword-face . 2))
+ (("object") non-immediate (font-lock-type-face . 2)))
+ "Hilighting description for words of the \"Objects\" package")
+
+
+(defvar forth-use-oof nil
+ "*Non-nil makes forth-mode also hilight words from the \"OOF\" package.")
+(defvar 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" "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)
+ "[ \t\n]" t name (font-lock-function-name-face . 3))
+ (("ptr" "asptr" "[]")
+ immediate (font-lock-keyword-face . 2)
+ "[ \t\n]" t name (font-lock-variable-name-face . 3))
+ (("class;" "how:" "self" "new" "new[]" "definitions" "class?" "with"
+ "endwith")
+ non-immediate (font-lock-keyword-face . 2))
+ (("object") non-immediate (font-lock-type-face . 2)))
+ "Hilighting description for words of the \"OOF\" package")
+
+(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'.")
+
+(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 &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 the beginning
+ of a line, following any number of whitespaces.
+
+INDENT2 specifies how to indent words that are not located at the
+ beginning of a line.
+
+INDENT1 and INDENT2 are indentation specifications of the form
+ (SELF-INDENT . NEXT-INDENT), where SELF-INDENT is a numerical value,
+ specifying how the matching line and all following lines are to be
+ indented, relative to previous lines. NEXT-INDENT specifies how to indent
+ following lines, relative to the matching line.
+
+ Even values of SELF-INDENT and NEXT-INDENT correspond to multiples of
+ `forth-indent-level'. Odd values get an additional
+ `forth-minor-indent-level' added/substracted. Eg a value of -2 indents
+ 1 * forth-indent-level to the left, whereas 3 indents
+ 1 * forth-indent-level + forth-minor-indent-level columns to the right.")
+
+(setq forth-indent-words
+ '((("if" "begin" "do" "?do" "+do" "-do" "u+do"
+ "u-do" "?dup-if" "?dup-0=-if" "case" "of" "?of" "try" "iferror"
+ "[if]" "[ifdef]" "[ifundef]" "[begin]" "[for]" "[do]" "[?do]" "[:"
+ "[n:l" "[n:h" "[n:d" "[d:l" "[d:h" "[d:d" "[f:l" "[f:h" "[f:d" "[{:")
+ (0 . 2) (0 . 2))
+ ((":" ":noname" "code" "abi-code" "struct" "m:" ":m" "class" "uclass"
+ "interface" "c-library" "c-library-name" "comp:" "opt:" "post:"
+ "begin-structure" "extend-structure" "event:" "to-opt:" "defer@-opt:" "to:" "defer@:")
+ (0 . 2) (0 . 2) non-immediate)
+ ("\\S-+%$" (0 . 2) (0 . 0) non-immediate)
+ ((";" ";m") (-2 . 0) (0 . -2))
+ (("again" "then" "endif" "endtry" "endcase" "next-case" "endof" "contof"
+ "[then]" "[endif]" "[loop]" "[+loop]" "[next]"
+ "[until]" "[again]" "loop" ";]" "nope")
+ (-2 . 0) (0 . -2))
+ (("end-code" "end-class" "end-interface" "end-class-noname"
+ "end-interface-noname" "end-struct" "class;" "end-c-library" "end-structure")
+ (-2 . 0) (0 . -2) non-immediate)
+ (("protected" "public" "how:") (-1 . 1) (0 . 0) non-immediate)
+ (("+loop" "-loop" "until") (-2 . 0) (-2 . 0))
+ (("else" "recover" "restore" "endtry-iferror" "[else]")
+ (-2 . 2) (0 . 0))
+ (("does>" "compile>" "int>" ";code" ";abi-code") (-1 . 1) (0 . 0))
+ (("while" "[while]") (-2 . 4) (0 . 2))
+ (("repeat" "[repeat]") (-4 . 0) (0 . -4))))
+
+(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
+ "*Minor indentation of Forth statements.")
+(defvar forth-compiled-indent-words nil)
+
+;(setq debug-on-error t)
+
+;; 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 (predicate list)
+ (let ((filtered nil))
+ (dolist (item list)
+ (when (funcall predicate item)
+ (if filtered
+ (nconc filtered (list item))
+ (setq filtered (cons item nil)))))
+ filtered))
+
+;; Helper function for `forth-compile-word': return whether word has to be
+;; added to the compiled word list, for syntactic parsing and hilighting.
+(defun forth-words-filter (word)
+ (let* ((hilight (nth 2 word))
+ (level (cdr hilight))
+ (parsing-flag (nth 3 word)))
+ (or parsing-flag
+ (<= level forth-hilight-level))))
+
+;; Helper function for `forth-compile-word': translate one entry from
+;; `forth-words' into the form (regexp regexp-depth word-description)
+(defun forth-compile-words-mapper (word)
+ ;; warning: we cannot rely on regexp-opt's PAREN argument, since
+ ;; XEmacs will use shy parens by default :-(
+ (let* ((matcher (car word))
+ (regexp
+ (concat "\\(" (cond ((stringp matcher) matcher)
+ ((listp matcher) (regexp-opt matcher))
+ (t (error "Invalid matcher")))
+ "\\)"))
+ (depth (regexp-opt-depth regexp))
+ (description (cdr word)))
+ (list regexp depth description)))
+
+;; Read `words' and create a compiled representation suitable for efficient
+;; parsing of the form
+;; (regexp (subexp-count word-description) (subexp-count2 word-description2)
+;; ...)
+(defun forth-compile-wordlist (words)
+ (let* ((mapped (mapcar 'forth-compile-words-mapper words))
+ (regexp (concat "\\<\\("
+ (mapconcat 'car mapped "\\|")
+ "\\)\\>"))
+ (sub-count 2)
+ (sub-list (mapcar
+ (lambda (i)
+ (let ((sub (cons sub-count (nth 2 i))))
+ (setq sub-count (+ sub-count (nth 1 i)))
+ sub
+ ))
+ mapped)))
+ (cons regexp sub-list)))
+
+(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'."
+ (put 'forth-local-indent-words 'safe-local-variable 'listp)
+ (put 'forth-local-words 'safe-local-variable 'listp)
+ (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)
+ (let* ((word (get-text-property pos 'forth-word))
+ (prev (previous-single-property-change
+ (min (point-max) (1+ pos)) 'forth-word
+ (current-buffer) (point-min))))
+ (if (or (= (point-min) prev) word) prev
+ (if (get-text-property (1- prev) 'forth-word)
+ (previous-single-property-change
+ prev 'forth-word (current-buffer) (point-min))
+ (point-min)))))
+
+;; Get location of the last character of the current/next forth word that's
+;; got properties, text that's parsed by the word is considered as parts of
+;; the word.
+(defun forth-next-end (pos)
+ (let* ((word (get-text-property pos 'forth-word))
+ (next (next-single-property-change pos 'forth-word
+ (current-buffer) (point-max))))
+ (if word next
+ (if (get-text-property next 'forth-word)
+ (next-single-property-change
+ next 'forth-word (current-buffer) (point-max))
+ (point-max)))))
+
+(defun forth-next-whitespace (pos)
+ (save-excursion
+ (goto-char pos)
+ (skip-syntax-forward "-" (point-max))
+ (point)))
+(defun forth-previous-word (pos)
+ (save-excursion
+ (goto-char pos)
+ (re-search-backward "\\<" pos (point-min) 1)
+ (point)))
+
+;; Delete all properties, used by Forth mode, from `from' to `to'.
+(defun forth-delete-properties (from to)
+ (remove-text-properties
+ 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...")
+(defun forth-get-regexp-branch ()
+ (let ((count 2))
+ (while (not (condition-case err (match-beginning count)
+ (args-out-of-range t))) ; XEmacs requires error handling
+ (setq count (1+ count)))
+ count))
+
+;; seek to next forth-word and return its "word-description"
+(defun forth-next-known-forth-word (to)
+ (if (<= (point) to)
+ (progn
+ (let* ((regexp (car forth-compiled-words))
+ (pos (re-search-forward regexp to t)))
+ (if pos (let ((branch (forth-get-regexp-branch))
+ (descr (cdr forth-compiled-words)))
+ (goto-char (match-beginning 0))
+ (cdr (assoc branch descr)))
+ 'nil)))
+ nil))
+
+;; Set properties of forth word at `point', eventually parsing subsequent
+;; words, and parsing all whitespaces. Set point to delimiter after word.
+;; The word, including it's parsed text gets the `forth-word' property, whose
+;; value is unique, and may be used for getting the word's start/end
+;; positions.
+(defun forth-set-word-properties (state data)
+ (let* ((start (point))
+ (end (progn (re-search-forward "[ \t]\\|$" (point-max) 1)
+ (point)))
+ (type (car data))
+ (hilight (nth 1 data))
+ (bad-word (and (not state) (eq type 'compile-only)))
+ (hlface (if bad-word font-lock-warning-face
+ (if (<= (cdr hilight) forth-hilight-level)
+ (car hilight) nil))))
+ (when hlface (put-text-property start end 'face hlface))
+ ;; if word parses in current state, process parsed range of text
+ (when (or (not state) (eq type 'compile-only) (eq type 'immediate))
+ (let ((parse-data (nthcdr 2 data)))
+ (while parse-data
+ (let ((delim (nth 0 parse-data))
+ (skip-leading (nth 1 parse-data))
+ (parse-type (nth 2 parse-data))
+ (parsed-hilight (nth 3 parse-data))
+ (parse-start (point))
+ (parse-end))
+ (when skip-leading
+ (while (and (looking-at delim) (> (match-end 0) (point))
+ (not (looking-at "\n")))
+ (forward-char)))
+ (re-search-forward delim (point-max) 1)
+ (setq parse-end (point))
+ (forth-delete-properties end parse-end)
+ (when (<= (cdr parsed-hilight) forth-hilight-level)
+ (put-text-property
+ parse-start parse-end 'face (car parsed-hilight)))
+ (put-text-property
+ parse-start parse-end 'forth-parsed parse-type)
+ (setq end parse-end)
+ (setq parse-data (nthcdr 4 parse-data))))))
+ (put-text-property start end 'forth-word start)))
+
+;; 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 &optional loudly)
+ (save-excursion
+ (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))))
+ ;; `to' must be on a space delimiter, if a parsing word was changed
+ (setq to (forth-next-whitespace to))
+ (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)))
+ (if (eq type 'definition-starter) (setq state t))
+ (if (eq type 'definition-ender) (setq state nil))
+ (setq last-location (point))))
+ ;; update state property up to `to'
+ (if (and state (< (point) to))
+ (put-text-property last-location to 'forth-state t))
+ ;; extend search if following state properties differ from current state
+ (if (< to (point-max))
+ (if (not (equal state (get-text-property (1+ to) 'forth-state)))
+ (let ((extend-to (next-single-property-change
+ to 'forth-state (current-buffer) (point-max))))
+ (forth-update-properties to extend-to))
+ ))
+ )))
+
+;; save-buffer-state borrowed from `font-lock.el'
+(eval-when-compile
+ (defmacro forth-save-buffer-state (varlist &rest body)
+ "Bind variables according to VARLIST and eval BODY restoring buffer state."
+ `(let* (,@(append varlist
+ '((modified (buffer-modified-p)) (buffer-undo-list t)
+ (inhibit-read-only t) (inhibit-point-motion-hooks t)
+ before-change-functions after-change-functions
+ deactivate-mark buffer-file-name buffer-file-truename)))
+ ,@body
+ (when (and (not modified) (buffer-modified-p))
+ (set-buffer-modified-p nil)))))
+
+;; 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 &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
+ ((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)))))
+
+(byte-compile 'forth-set-word-properties)
+(byte-compile 'forth-next-known-forth-word)
+(byte-compile 'forth-update-properties)
+(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" "2Value" "field" "end-struct" "VOCABULARY" "CREATE" ":" "CODE"
+ "DEFER" "ALIAS" "interpret/compile:" "debug:" "field:" "2field:" "ffield:"
+ "sffield:" "dffield:" "uvar" "uvalue" "voctable" "method" "umethod")
+ "List of words, that define the following word.
+Used for imenu index generation.")
+
+(defvar forth-defining-words-regexp nil
+ "Regexp that's generated for matching `forth-defining-words'")
+
+(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))
+
+;; top-level require is executed at byte-compile and load time
+(eval-and-compile (require 'speedbar))
+
+;; this code is executed at load-time only
+(when (memq 'speedbar features)
+ (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))
+
+;;; Indentation
+;;;
+
+;; Return, whether `pos' is the first forth word on its line
+(defun forth-first-word-on-line-p (pos)
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (= pos (point))))
+
+;; Return indentation data (SELF-INDENT . NEXT-INDENT) of next known
+;; indentation word, or nil if there is no word up to `to'.
+;; Position `point' at location just after found word, or at `to'. Parsed
+;; ranges of text will not be taken into consideration!
+(defun forth-next-known-indent-word (to)
+ (if (<= (point) to)
+ (progn
+ (let* ((regexp (car forth-compiled-indent-words))
+ (pos (re-search-forward regexp to t)))
+ (if pos
+ (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)))
+ nil))
+
+;; Translate indentation value `indent' to indentation column. Multiples of
+;; 2 correspond to multiples of `forth-indent-level'. Odd numbers get an
+;; additional `forth-minor-indent-level' added (or substracted).
+(defun forth-convert-to-column (indent)
+ (let* ((sign (if (< indent 0) -1 1))
+ (value (abs indent))
+ (major (* (/ value 2) forth-indent-level))
+ (minor (* (% value 2) forth-minor-indent-level)))
+ (* sign (+ major minor))))
+
+;; Return the column increment, that the current line of forth code does to
+;; the current or following lines. `which' specifies which indentation values
+;; to use. 1 means the indentation of following lines relative to current
+;; line, 0 means the indentation of the current line relative to the previous
+;; line. Return `nil', if there are no indentation words on the current line.
+(defun forth-get-column-incr (which)
+ (save-excursion
+ (let ((regexp (car forth-compiled-indent-words))
+ (word-indent)
+ (self-indent nil)
+ (next-indent nil)
+ (to (save-excursion (end-of-line) (point))))
+ (beginning-of-line)
+ (while (setq word-indent (forth-next-known-indent-word to))
+ (let* ((self-incr (car word-indent))
+ (next-incr (cdr word-indent))
+ (self-column-incr (forth-convert-to-column self-incr))
+ (next-column-incr (forth-convert-to-column next-incr)))
+ (setq next-indent (if next-indent next-indent 0))
+ (setq self-indent (if self-indent self-indent 0))
+ (if (or (and (> next-indent 0) (< self-column-incr 0))
+ (and (< next-indent 0) (> self-column-incr 0)))
+ (setq next-indent (+ next-indent self-column-incr))
+ (setq self-indent (+ self-indent self-column-incr)))
+ (setq next-indent (+ next-indent next-column-incr))))
+ (nth which (list self-indent next-indent)))))
+
+;; Find previous line that contains indentation words, return the column,
+;; to which following text should be indented to.
+(defun forth-get-anchor-column ()
+ (save-excursion
+ (if (/= 0 (forward-line -1)) 0
+ (let ((indent))
+ (while (not (or (setq indent (forth-get-column-incr 1))
+ (<= (point) (point-min))))
+ (forward-line -1))
+ (+ (current-indentation) (if indent indent 0))))))
+
+(defun forth-indent-line (&optional flag)
+ "Correct indentation of the current Forth line."
+ (let* ((anchor (forth-get-anchor-column))
+ (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 (- (forth-current-column) (forth-current-indentation)))
+ (forth-delete-indentation)
+ (beginning-of-line)
+ (indent-to x)
+ (if (> p 0) (forward-char p))))
+
+(defun forth-delete-indentation ()
+ (save-excursion
+ (delete-region
+ (progn (beginning-of-line) (point))
+ (progn (back-to-indentation) (point)))))
+
+(defun forth-indent-command ()
+ (interactive)
+ (forth-indent-line t))
+
+;; remove trailing whitespaces in current line
+(defun forth-remove-trailing ()
+ (save-excursion
+ (end-of-line)
+ (delete-region (point) (progn (skip-chars-backward " \t") (point)))))
+
+;; insert newline, removing any trailing whitespaces in the current line
+(defun forth-newline-remove-trailing ()
+ (save-excursion
+ (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 ()
+ (interactive "*")
+ (indent-according-to-mode)
+ (forth-newline-remove-trailing)
+ (indent-according-to-mode))
+
+
+;;; Block file encoding/decoding (dk)
+;;;
+
+(defconst forth-c/l 64 "Number of characters per block line")
+(defconst forth-l/b 16 "Number of lines per block")
+
+;; Check whether the unconverted block file line, point is in, does not
+;; contain `\n' and `\t' characters.
+(defun forth-check-block-line (line)
+ (let ((end (save-excursion (beginning-of-line) (forward-char forth-c/l)
+ (point))))
+ (save-excursion
+ (beginning-of-line)
+ (when (search-forward "\n" end t)
+ (message "Warning: line %i contains newline character #10" line)
+ (ding t))
+ (beginning-of-line)
+ (when (search-forward "\t" end t)
+ (message "Warning: line %i contains tab character #8" line)
+ (ding t)))))
+
+(defun forth-convert-from-block (from to)
+ "Convert block file format to stream source in current buffer."
+ (let ((line (count-lines (point-min) from)))
+ (save-excursion
+ (goto-char from)
+ (set-mark to)
+ (while (< (+ (point) forth-c/l) (mark t))
+ (setq line (1+ line))
+ (forth-check-block-line line)
+ (forward-char forth-c/l)
+ (forth-newline-remove-trailing))
+ (when (= (+ (point) forth-c/l) (mark t))
+ (forth-remove-trailing))
+ (mark t)))
+ (set-buffer-modified-p 'nil))
+
+;; Pad a line of a block file up to `forth-c/l' characters, positioning `point'
+;; at the end of line.
+(defun forth-pad-block-line ()
+ (save-excursion
+ (end-of-line)
+ (if (<= (current-column) forth-c/l)
+ (move-to-column forth-c/l t)
+ (message "Line %i longer than %i characters, truncated"
+ (count-lines (point-min) (point)) forth-c/l)
+ (ding t)
+ (move-to-column forth-c/l t)
+ (delete-region (point) (progn (end-of-line) (point))))))
+
+;; Replace tab characters in current line by spaces.
+(defun forth-convert-tabs-in-line ()
+ (save-excursion
+ (beginning-of-line)
+ (while (search-forward "\t" (save-excursion (end-of-line) (point)) t)
+ (backward-char)
+ (delete-region (point) (1+ (point)))
+ (insert-char ?\ (- tab-width (% (current-column) tab-width))))))
+
+;; Delete newline at end of current line, concatenating it with the following
+;; line. Place `point' at end of newly formed line.
+(defun forth-delete-newline ()
+ (end-of-line)
+ (delete-region (point) (progn (beginning-of-line 2) (point))))
+
+(defun forth-convert-to-block (from to &optional original-buffer)
+ "Convert range of text to block file format in current buffer."
+ (let* ((lines 0)) ; I have to count lines myself, since `count-lines' has
+ ; problems with trailing newlines...
+ (save-excursion
+ (goto-char from)
+ (set-mark to)
+ ;; pad lines to full length (`forth-c/l' characters per line)
+ (while (< (save-excursion (end-of-line) (point)) (mark t))
+ (setq lines (1+ lines))
+ (forth-pad-block-line)
+ (forth-convert-tabs-in-line)
+ (forward-line))
+ ;; also make sure the last line is padded, if `to' is at its end
+ (end-of-line)
+ (when (= (point) (mark t))
+ (setq lines (1+ lines))
+ (forth-pad-block-line)
+ (forth-convert-tabs-in-line))
+ ;; remove newlines between lines
+ (goto-char from)
+ (while (< (save-excursion (end-of-line) (point)) (mark t))
+ (forth-delete-newline))
+ ;; append empty lines, until last block is complete
+ (goto-char (mark t))
+ (let* ((required (* (/ (+ lines (1- forth-l/b)) forth-l/b) forth-l/b))
+ (pad-lines (- required lines)))
+ (while (> pad-lines 0)
+ (insert-char ?\ forth-c/l)
+ (setq pad-lines (1- pad-lines))))
+ (point))))
+
+(defun forth-detect-block-file-p ()
+ "Return non-nil if the current buffer is in block file format. Detection is
+done by checking whether the first line has 1024 characters or more."
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char (point-min))
+ (end-of-line)
+ (>= (current-column) 1024))))
+
+;; add block file conversion routines to `format-alist'
+(defconst forth-block-format-description
+ '(forth-blocks "Forth block source file" nil
+ forth-convert-from-block forth-convert-to-block
+ t normal-mode))
+(unless (memq forth-block-format-description format-alist)
+ (setq format-alist (cons forth-block-format-description format-alist)))
+
+;;; End block file encoding/decoding
+
+;;; Block file editing
+;;;
+(defvar forth-overlay-arrow-string ">>")
+(defvar forth-block-base 1 "Number of first block in block file")
+(defvar forth-show-screen nil
+ "Non-nil means to show screen starts and numbers (for block files)")
+(defvar forth-warn-long-lines nil
+ "Non-nil means to warn about lines that are longer than 64 characters")
+
+(defvar forth-screen-marker nil)
+(defvar forth-screen-number-string nil)
+
+(defun forth-update-show-screen ()
+ "If `forth-show-screen' is non-nil, put overlay arrow to start of screen,
+`point' is in. If arrow now points to different screen than before, display
+screen number."
+ (if (not forth-show-screen)
+ (setq overlay-arrow-string nil)
+ (save-excursion
+ (let* ((line (count-lines (point-min) (min (point-max) (1+ (point)))))
+ (first-line (1+ (* (/ (1- line) forth-l/b) forth-l/b)))
+ (scr (+ forth-block-base (/ first-line forth-l/b))))
+ (setq overlay-arrow-string forth-overlay-arrow-string)
+ (forward-line (- first-line (line-number-at-pos)))
+ (setq overlay-arrow-position forth-screen-marker)
+ (set-marker forth-screen-marker
+ (save-excursion (forward-line (- first-line (line-number-at-pos))) (point)))
+ (setq forth-screen-number-string (format "%d" scr))))))
+
+(add-hook 'forth-motion-hooks 'forth-update-show-screen)
+
+(defun forth-update-warn-long-lines ()
+ "If `forth-warn-long-lines' is non-nil, display a warning whenever a line
+exceeds 64 characters."
+ (when forth-warn-long-lines
+ (when (> (save-excursion (end-of-line) (current-column)) forth-c/l)
+ (message "Warning: current line exceeds %i characters"
+ forth-c/l))))
+
+(add-hook 'forth-motion-hooks 'forth-update-warn-long-lines)
+
+;;; End block file editing
+
+
+(defvar forth-mode-abbrev-table nil
+ "Abbrev table in use in Forth-mode buffers.")
+
+(define-abbrev-table 'forth-mode-abbrev-table ())
+
+(defvar forth-mode-map nil
+ "Keymap used in Forth mode.")
+
+(if (not forth-mode-map)
+ (setq forth-mode-map (make-sparse-keymap)))
+
+;(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~" 'forth-remove-tracers)
+(define-key forth-mode-map "\C-x\C-m" 'forth-split)
+(define-key forth-mode-map "\t" 'forth-indent-command)
+(define-key forth-mode-map "\C-m" 'forth-reindent-then-newline-and-indent)
+(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
+(eval-and-compile (require 'info-look))
+(when (memq 'info-look features)
+ (defvar forth-info-lookup '(symbol (forth-mode "\\S-+" t
+ (("(gforth)Word Index"))
+ "\\S-+")))
+ (unless (memq forth-info-lookup info-lookup-alist)
+ (setq info-lookup-alist (cons forth-info-lookup info-lookup-alist)))
+ ;; in X-Emacs C-h C-i is by default bound to Info-query
+ (define-key forth-mode-map [?\C-h ?\C-i] 'info-lookup-symbol))
+
+;; (info-lookup-add-help
+;; :topic 'symbol
+;; :mode 'forth-mode
+;; :regexp "[^
+;; ]+"
+;; :ignore-case t
+;; :doc-spec '(("(gforth)Name Index" nil "`" "' "))))
+
+(require 'etags)
+
+(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-*\x7f")))
+ (switch-to-buffer
+ (find-tag-noselect tagname next-p t)))
+
+(defvar forth-mode-syntax-table nil
+ "Syntax table in use in Forth-mode buffers.")
+
+;; Important: hilighting/indentation now depends on a correct syntax table.
+;; All characters, except whitespace *must* belong to the "word constituent"
+;; syntax class. If different behaviour is required, use of Categories might
+;; help.
+(if (not forth-mode-syntax-table)
+ (progn
+ (setq forth-mode-syntax-table (make-syntax-table))
+ (let ((char 0))
+ (while (< char ?!)
+ (modify-syntax-entry char " " forth-mode-syntax-table)
+ (setq char (1+ char)))
+ (while (< char 256)
+ (modify-syntax-entry char "w" forth-mode-syntax-table)
+ (setq char (1+ char))))
+ ))
+
+(defun forth-mode-variables ()
+ (set-syntax-table forth-mode-syntax-table)
+ (setq local-abbrev-table forth-mode-abbrev-table)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "^$\\|" page-delimiter))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'forth-indent-line)
+; (make-local-variable 'require-final-newline)
+; (setq require-final-newline t)
+ (make-local-variable 'comment-start)
+ (setq comment-start "\\ ")
+ ;(make-local-variable 'comment-end)
+ ;(setq comment-end " )")
+ (make-local-variable 'comment-column)
+ (setq comment-column 40)
+ (setq compilation-error-screen-columns nil) ;; for WHEREG
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "\\\\ ")
+ (make-local-variable 'comment-indent-function)
+ (setq comment-indent-function '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 '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)
+ (if forth-jit-parser
+ (add-hook 'fontification-functions 'forth-fontification-function))
+ (setq imenu-create-index-function 'forth-create-index))
+
+;;;###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'.
+\\{forth-mode-map}
+
+Variables controlling syntax hilighting/recognition of parsed text:
+ `forth-words'
+ List of words that have a special parsing behaviour and/or should be
+ 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..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 statements.
+
+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 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
+ Screen number of the first block in a block file. Defaults to 1.
+ 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
+ t for `forth-block-mode' and to nil for `forth-mode'.
+
+Variables controlling interaction with the Forth-process (also see
+`run-forth'):
+ forth-program-name
+ Program invoked by the `run-forth' command (including arguments).
+ inferior-forth-mode-hook
+ Hook for customising inferior-forth-mode.
+ forth-compile-command
+ Default command to execute on `compile'.
+"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map forth-mode-map)
+ (setq mode-name "Forth")
+ (setq major-mode 'forth-mode)
+ (setq bidi-display-reordering nil)
+ (forth-install-motion-hook)
+ ;; convert buffer contents from block file format, if necessary
+ (when (forth-detect-block-file-p)
+ (widen)
+ (message "Converting from Forth block source...")
+ (forth-convert-from-block (point-min) (point-max))
+ (message "Converting from Forth block source...done"))
+ ;; if user switched from forth-block-mode to forth-mode, make sure the file
+ ;; is now stored as normal strem source
+ (when (equal buffer-file-format '(forth-blocks))
+ (setq buffer-file-format nil))
+ (forth-mode-variables)
+; (if (not (forth-process-running-p))
+; (run-forth forth-program-name))
+ (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:
+ * files are converted to block format, when written (`buffer-file-format'
+ is set to `(forth-blocks)')
+ * `forth-show-screen' and `forth-warn-long-lines' are t by default
+
+Note that the length of lines in block files is limited to 64 characters.
+When writing longer lines to a block file, a warning is displayed in the
+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, 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.
+
+So have a look at the *Messages* buffer, whenever you hear (or see) Emacs'
+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-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 ")
+ (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 '\\' which start a line; do not fill code."
+ ;; Something like lisp-fill-paragraph may be better. We cannot use
+ ;; fill-paragraph, because it removes the \ from the first comment
+ ;; line. Therefore we have to look for the first line of the comment
+ ;; and use fill-region.
+ (interactive)
+ (save-excursion
+ (beginning-of-line)
+ (while (and
+ (= (forward-line -1) 0)
+ (looking-at "[ \t]*\\\\g?[ \t]+")))
+ (if (not (looking-at "[ \t]*\\\\g?[ \t]+"))
+ (forward-line 1))
+ (let ((from (point))
+ (to (save-excursion (forward-paragraph) (point))))
+ (if (looking-at "[ \t]*\\\\g?[ \t]+")
+ (progn (goto-char (match-end 0))
+ (let ((fill-prefix-save fill-prefix))
+ (set-fill-prefix)
+ (fill-region from to nil)
+ (setq fill-prefix fill-prefix-save)))))))
+
+(defun forth-comment-indent ()
+ (save-excursion
+ (beginning-of-line)
+ (if (looking-at ":[ \t]*")
+ (progn
+ (end-of-line)
+ (skip-chars-backward " \t\n")
+ (1+ (current-column)))
+ comment-column)))
+
+
+;; Forth commands
+
+(defun forth-remove-tracers ()
+ "Remove tracers of the form `~~ '. Queries the user for each occurrence."
+ (interactive)
+ (query-replace-regexp "\\(~~[ \t]\\|[ \t]~~$\\)" "" nil))
+
+(define-key forth-mode-map "\C-x\C-e" 'compile)
+(define-key forth-mode-map "\C-x\C-n" 'next-error)
+(require 'compile)
+
+(defvar forth-compile-command "gforth ")
+;(defvar forth-compilation-window-percent-height 30)
+
+(defun forth-split ()
+ (interactive)
+ (forth-split-1 "*forth*"))
+
+(defun forth-split-1 (buffer)
+ (if (not (eq (window-buffer) (get-buffer buffer)))
+ (progn
+ (delete-other-windows)
+ (split-window-vertically
+ (/ (frame-height) 2))
+ (other-window 1)
+ (switch-to-buffer buffer)
+ (goto-char (point-max))
+ (other-window 1))))
+
+;;; 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
+
+;; (dk) This code needs a rewrite; just too ugly and doesn't use the
+;; newer and smarter scanning rules of `imenu'. Who needs it anyway??
+
+;; (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
+
+;;;
+;;; Inferior Forth interpreter
+;;; -- mostly copied from `cmuscheme.el' of Emacs 21.2
+;;;
+
+(eval-and-compile (require 'comint))
+
+(when (memq 'comint features)
+
+ (defvar forth-program-name "gforth"
+ "*Program invoked by the `run-forth' command, including program arguments")
+
+ (defcustom inferior-forth-mode-hook nil
+ "*Hook for customising inferior-forth-mode."
+ :type 'hook
+ :group 'forth)
+
+ (defvar inferior-forth-mode-map
+ (let ((m (make-sparse-keymap)))
+ (define-key m "\r" 'comint-send-input)
+ (define-key m "\M-\C-x" 'forth-send-paragraph-and-go)
+ (define-key m "\C-c\C-l" 'forth-load-file)
+ m))
+ ;; Install the process communication commands in the forth-mode keymap.
+ (define-key forth-mode-map "\e\C-m" 'forth-send-paragraph-and-go)
+ (define-key forth-mode-map "\eo" 'forth-send-buffer-and-go)
+
+ (define-key forth-mode-map "\M-\C-x" 'forth-send-paragraph-and-go)
+ (define-key forth-mode-map "\C-c\C-r" 'forth-send-region)
+ (define-key forth-mode-map "\C-c\M-r" 'forth-send-region-and-go)
+ (define-key forth-mode-map "\C-c\C-z" 'forth-switch-to-interactive)
+ (define-key forth-mode-map "\C-c\C-l" 'forth-load-file)
+
+ (defvar forth-process-buffer)
+
+ (define-derived-mode inferior-forth-mode comint-mode "Inferior Forth"
+ "Major mode for interacting with an inferior Forth process.
+
+The following commands are available:
+\\{inferior-forth-mode-map}
+
+A Forth process can be fired up with M-x run-forth.
+
+Customisation: Entry to this mode runs the hooks on comint-mode-hook and
+inferior-forth-mode-hook (in that order).
+
+You can send text to the inferior Forth process from other buffers containing
+Forth source.
+ forth-switch-to-interactive switches the current buffer to the Forth
+ process buffer.
+ forth-send-paragraph sends the current paragraph to the Forth process.
+ forth-send-region sends the current region to the Forth process.
+ forth-send-buffer sends the current buffer to the Forth process.
+
+ forth-send-paragraph-and-go, forth-send-region-and-go,
+ forth-send-buffer-and-go switch to the Forth process buffer after
+ sending their text.
+For information on running multiple processes in multiple buffers, see
+documentation for variable `forth-process-buffer'.
+
+Commands:
+Return after the end of the process' output sends the text from the
+end of process to point. If you accidentally suspend your process, use
+\\[comint-continue-subjob] to continue it. "
+ ;; Customise in inferior-forth-mode-hook
+ (setq comint-prompt-regexp "^")
+ (setq mode-line-process '(":%s")))
+
+ (defun forth-args-to-list (string)
+ (let ((where (string-match "[ \t]" string)))
+ (cond ((null where) (list string))
+ ((not (= where 0))
+ (cons (substring string 0 where)
+ (forth-args-to-list (substring string (+ 1 where)
+ (length string)))))
+ (t (let ((pos (string-match "[^ \t]" string)))
+ (if (null pos)
+ nil
+ (forth-args-to-list (substring string pos
+ (length string)))))))))
+
+;;;###autoload
+ (defun run-forth (cmd)
+ "Run an inferior Forth process, input and output via buffer *forth*.
+If there is a process already running in `*forth*', switch to that buffer.
+With argument, allows you to edit the command line (default is value
+of `forth-program-name'). Runs the hooks `inferior-forth-mode-hook'
+\(after the `comint-mode-hook' is run).
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
+
+ (interactive (list (if current-prefix-arg
+ (read-string "Run Forth: " forth-program-name)
+ forth-program-name)))
+ (if (not (comint-check-proc "*forth*"))
+ (let ((cmdlist (forth-args-to-list cmd)))
+ (set-buffer (apply 'make-comint "forth" (car cmdlist)
+ nil (cdr cmdlist)))
+ (inferior-forth-mode)))
+ (setq forth-program-name cmd)
+ (setq forth-process-buffer "*forth*")
+ (pop-to-buffer "*forth*"))
+
+ (defun forth-send-region (start end)
+ "Send the current region to the inferior Forth process."
+ (interactive "r")
+ (comint-send-region (forth-proc) start end)
+ (comint-send-string (forth-proc) "\n"))
+
+ (defun forth-end-of-paragraph ()
+ (if (looking-at "[\t\n ]+") (skip-chars-backward "\t\n "))
+ (if (not (re-search-forward "\n[ \t]*\n" nil t))
+ (goto-char (point-max))))
+
+ (defun forth-send-paragraph ()
+ "Send the current or the previous paragraph to the Forth process"
+ (interactive)
+ (let (end)
+ (save-excursion
+ (forth-end-of-paragraph)
+ (skip-chars-backward "\t\n ")
+ (setq end (point))
+ (if (null (re-search-backward "\n[ \t]*\n" nil t))
+ (goto-char (point-min)))
+ (skip-chars-forward "\t\n ")
+ (forth-send-region (point) end))))
+
+ (defun forth-send-paragraph-and-go ()
+ "Send the current or the previous paragraph to the Forth process.
+Then switch to the process buffer."
+ (interactive)
+ (forth-send-paragraph)
+ (forth-switch-to-interactive t))
+
+ (defun forth-send-buffer ()
+ "Send the current buffer to the Forth process."
+ (interactive)
+ (if (eq (current-buffer) forth-process-buffer)
+ (error "Not allowed to send this buffer's contents to Forth"))
+ (forth-send-region (point-min) (point-max)))
+
+ (defun forth-send-buffer-and-go ()
+ "Send the current buffer to the Forth process.
+Then switch to the process buffer."
+ (interactive)
+ (forth-send-buffer)
+ (forth-switch-to-interactive t))
+
+
+ (defun forth-switch-to-interactive (eob-p)
+ "Switch to the Forth process buffer.
+With argument, position cursor at end of buffer."
+ (interactive "P")
+ (if (get-buffer forth-process-buffer)
+ (pop-to-buffer forth-process-buffer)
+ (error "No current process buffer. See variable `forth-process-buffer'"))
+ (cond (eob-p
+ (push-mark)
+ (goto-char (point-max)))))
+
+ (defun forth-send-region-and-go (my-start end)
+ "Send the current region to the inferior Forth process.
+Then switch to the process buffer."
+ (interactive "r")
+ (forth-send-region my-start end)
+ (forth-switch-to-interactive t))
+
+ (defcustom forth-source-modes '(forth-mode forth-block-mode)
+ "*Used to determine if a buffer contains Forth source code.
+If it's loaded into a buffer that is in one of these major modes, it's
+considered a Forth source file by `forth-load-file' and `forth-compile-file'.
+Used by these commands to determine defaults."
+ :type '(repeat function)
+ :group 'forth)
+
+ (defvar forth-prev-l/c-dir/file nil
+ "Caches the last (directory . file) pair.
+Caches the last pair used in the last `forth-load-file' or
+`forth-compile-file' command. Used for determining the default in the
+next one.")
+
+ (defun forth-load-file (file-name)
+ "Load a Forth file FILE-NAME into the inferior Forth process."
+ (interactive (comint-get-source "Load Forth file: " forth-prev-l/c-dir/file
+ forth-source-modes t)) ; T because LOAD
+ ; needs an exact name
+ (comint-check-source file-name) ; Check to see if buffer needs saved.
+ (setq forth-prev-l/c-dir/file (cons (file-name-directory file-name)
+ (file-name-nondirectory file-name)))
+ (comint-send-string (forth-proc)
+ (concat "s\" " file-name "\" included\n")))
+
+
+ (defvar forth-process-buffer nil "*The current Forth process buffer.
+
+See `scheme-buffer' for an explanation on how to run multiple Forth
+processes.")
+
+ (defun forth-proc ()
+ "Return the current Forth process. See variable `forth-process-buffer'."
+ (let ((proc (get-buffer-process (if (eq major-mode 'inferior-forth-mode)
+ (current-buffer)
+ forth-process-buffer))))
+ (or proc
+ (error "No current process. See variable `forth-process-buffer'"))))
+ )
+
+(provide 'forth-mode)
+
+;; coverage mode
+
+(defun display-ansi-colors ()
+ (interactive)
+ (ansi-color-apply-on-region (point-min) (point-max))
+ (set-buffer-modified-p 'nil))
+
+(define-derived-mode forth-coverage-mode fundamental-mode "Forth Coverage Mode"
+ "Major mode for viewing coverage files"
+ )
+;(add-to-list 'auto-mode-alist '("\\.fs.cov\\'" . forth-coverage-mode))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.fth\\'" . forth-mode))
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.4th\\'" . forth-mode))
+
+;;; gforth.el ends here
diff --git a/pkgs/webjump-ido.el b/pkgs/webjump-ido.el
new file mode 100644
index 0000000..7b6b2bd
--- /dev/null
+++ b/pkgs/webjump-ido.el
@@ -0,0 +1,143 @@
+;;; webjump-ido.el --- Use ido for selecting URLs for webjump
+
+;; Filename: webjump-ido.el
+;; Description: Use ido for selecting URLs for webjump
+;; Author: Joe Bloggs <vapniks@yahoo.com>
+;; Maintainer: Joe Bloggs <vapniks@yahoo.com>
+;; Copyleft (Ↄ) 2015, Joe Bloggs, all rites reversed.
+;; Created: 2015-09-01 23:59:48
+;; Version: 0.1
+;; Last-Updated: 2015-09-01 23:59:48
+;; By: Joe Bloggs
+;; URL: https://github.com/vapniks/webjump-ido
+;; Keywords: convenience
+;; Compatibility: GNU Emacs 24.5.1
+;; Package-Requires:
+;;
+;; Features that might be required by this library:
+;;
+;; webjump
+;;
+
+;;; This file is NOT part of GNU Emacs
+
+;;; License
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.
+;; If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Bitcoin donations gratefully accepted: 12k9zUo9Dgqk8Rary2cuzyvAQWD5EAuZ4q
+;;
+;; This package provides an ido version of the `webjump' command, with customizable
+;; URL's
+;;
+;;;;
+
+;;; Commands:
+;;
+;; Below are complete command list:
+;;
+;; `webjump-ido' : Jumps to a Web site from a programmable hotlist.
+;;
+;;; Customizable Options:
+;;
+;; Below are customizable option list:
+;;
+;; `webjump-ido-sites' :
+;; *Hotlist for WebJump.
+;; default = (if (featurep (quote webjump-plus)) (append webjump-plus-sites webjump-sample-sites) webjump-sample-sites)
+
+
+;;; Installation:
+;;
+;; Put webjump-ido.el in a directory in your load-path, e.g. ~/.emacs.d/
+;; You can add a directory to your load-path with the following line in ~/.emacs
+;; (add-to-list 'load-path (expand-file-name "~/elisp"))
+;; where ~/elisp is the directory you want to add
+;; (you don't need to do this for ~/.emacs.d - it's added by default).
+;;
+;; Add the following to your ~/.emacs startup file.
+;;
+;; (require 'webjump-ido)
+
+;;; Customize:
+;;
+;; To automatically insert descriptions of customizable variables defined in this buffer
+;; place point at the beginning of the next line and do: M-x auto-document
+
+;;
+;; All of the above can customized by:
+;; M-x customize-group RET webjump-ido RET
+;;
+
+;;; Require
+(require 'webjump)
+(require 'webjump-plus nil t)
+
+;;; Code:
+
+(defcustom webjump-ido-sites (if (featurep 'webjump-plus)
+ (append webjump-plus-sites webjump-sample-sites)
+ webjump-sample-sites)
+ "Hotlist for `webjump-ido'. This variable takes the same for as `webjump-sites' (which see),
+but is specific to `webjump-ido', and is customizable. By default it should contains the same
+URL's as `webjump-sample-sites' and `webjump-plus-sites' (if available)."
+ :type '(alist :key-type (string :tag "Name")
+ :value-type (choice (string :tag "URL")
+ (choice :tag "Vector"
+ (vector :tag "Name"
+ (const name))
+ (vector :tag "Simple-query"
+ (const simple-query)
+ (string :tag "Static URL")
+ (string :tag "Prefix")
+ (string :tag "Suffix"))
+ (sexp :tag "Mirrors"
+ :help-echo "This should be a vector whos first element is the symbol 'mirrors and subsequent elements are strings containing URLs of mirror sites."))
+ (function :tag "Function")
+ (sexp :tag "Sexp to eval"))))
+
+;;;###autoload
+(defun webjump-ido nil
+ "Jumps to a Web site from a programmable hotlist, using ido to select the website.
+See the documentation for the `webjump-ido-sites' variable for how to customize the hotlist."
+ (interactive)
+ (let* ((completion-ignore-case t)
+ (item (assoc-string
+ (ido-completing-read "WebJump to site: "
+ (mapcar 'car webjump-ido-sites) nil t)
+ webjump-ido-sites t))
+ (name (car item))
+ (expr (cdr item)))
+ (browse-url (webjump-url-fix
+ (cond ((not expr) "")
+ ((stringp expr) expr)
+ ((vectorp expr) (webjump-builtin expr name))
+ ((listp expr) (eval expr))
+ ((symbolp expr)
+ (if (fboundp expr)
+ (funcall expr name)
+ (error "WebJump URL function \"%s\" undefined"
+ expr)))
+ (t (error "WebJump URL expression for \"%s\" invalid"
+ name)))))))
+
+(provide 'webjump-ido)
+
+;; (magit-push)
+;; (yaoddmuse-post "EmacsWiki" "webjump-ido.el" (buffer-name) (buffer-string) "update")
+
+;;; webjump-ido.el ends here