Commits

Anonymous committed 2d1f2e6

added erlang.el

Comments (0)

Files changed (1)

+;; erlang.el --- Major modes for editing and running Erlang
+;; %CopyrightBegin%
+;;
+;; Copyright Ericsson AB 1996-2010. All Rights Reserved.
+;;
+;; The contents of this file are subject to the Erlang Public License,
+;; Version 1.1, (the "License"); you may not use this file except in
+;; compliance with the License. You should have received a copy of the
+;; Erlang Public License along with this software. If not, it can be
+;; retrieved online at http://www.erlang.org/.
+;;
+;; Software distributed under the License is distributed on an "AS IS"
+;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+;; the License for the specific language governing rights and limitations
+;; under the License.
+;;
+;; %CopyrightEnd%
+;; 
+;; Copyright (C) 2004  Free Software Foundation, Inc.
+;; Author:   Anders Lindgren
+;; Keywords: erlang, languages, processes
+
+;; Lars Thors�n's modifications of 2000-06-07 included.
+;; The original version of this package was written by Robert Virding.
+;;
+;;; Commentary:
+
+;; Introduction:
+;; ------------
+;;
+;; This package provides support for the programming language Erlang.
+;; The package provides an editing mode with lots of bells and
+;; whistles, compilation support, and it makes it possible for the
+;; user to start Erlang shells that run inside Emacs.
+;;
+;; See the Erlang distribution for full documentation of this package.
+
+;; Installation:
+;; ------------
+;;
+;; Place this file in Emacs load path, byte-compile it, and add the
+;; following line to the appropriate init file:
+;;
+;;    (require 'erlang-start)
+;;
+;; The full documentation contains much more extensive description of
+;; the installation procedure.
+
+;; Reporting Bugs:
+;; --------------
+;;
+;; Please send bug reports to the following email address:
+;;      erlang-bugs@erlang.org
+;; or if you have a patch suggestion to:
+;;      erlang-patches@erlang.org
+;; Please state as exactly as possible:
+;;    - Version number of Erlang Mode (see the menu), Emacs, Erlang,
+;;	and of any other relevant software.
+;;    - What the expected result was.
+;;    - What you did, preferably in a repeatable step-by-step form.
+;;    - A description of the unexpected result.
+;;    - Relevant pieces of Erlang code causing the problem.
+;;    - Personal Emacs customisations, if any.
+;;
+;; Should the Emacs generate an error, please set the Emacs variable
+;; `debug-on-error' to `t'.  Repeat the error and enclose the debug
+;; information in your bug-report.
+;;
+;; To set the variable you can use the following command:
+;;     M-x set-variable RET debug-on-error RET t RET
+;;; Code:
+
+;; Variables:
+
+(defconst erlang-version "2.7"
+  "The version number of Erlang mode.")
+
+(defvar erlang-root-dir nil
+  "The directory where the Erlang system is installed.
+The name should not contain the trailing slash.
+
+Should this variable be nil, no manual pages will show up in the
+Erlang mode menu.")
+
+(eval-and-compile
+  (defconst erlang-emacs-major-version
+    (if (boundp 'emacs-major-version)
+	emacs-major-version
+      (string-match "\\([0-9]+\\)\\.\\([0-9]+\\)" emacs-version)
+      (erlang-string-to-int (substring emacs-version
+				       (match-beginning 1) (match-end 1))))
+    "Major version number of Emacs."))
+
+(eval-and-compile
+  (defconst erlang-emacs-minor-version
+  (if (boundp 'emacs-minor-version)
+      emacs-minor-version
+    (string-match "\\([0-9]+\\)\\.\\([0-9]+\\)" emacs-version)
+    (erlang-string-to-int (substring emacs-version
+			      (match-beginning 2) (match-end 2))))
+  "Minor version number of Emacs."))
+
+(defconst erlang-xemacs-p (string-match "Lucid\\|XEmacs" emacs-version)
+  "Non-nil when running under XEmacs or Lucid Emacs.")
+
+(defvar erlang-xemacs-popup-menu '("Erlang Mode Commands" . nil)
+  "Common popup menu for all buffers in Erlang mode.
+
+This variable is destructively modified every time the Erlang menu
+is modified.  The effect is that all changes take effect in all
+buffers in Erlang mode, just like under GNU Emacs.
+
+Never EVER set this variable!")
+
+(defvar erlang-menu-items '(erlang-menu-base-items
+			    erlang-menu-skel-items
+			    erlang-menu-shell-items
+			    erlang-menu-compile-items
+			    erlang-menu-man-items
+			    erlang-menu-personal-items
+			    erlang-menu-version-items)
+  "*List of menu item list to combine to create Erlang mode menu.
+
+External programs which temporarily add menu items to the Erlang mode
+menu may use this variable.  Please use the function `add-hook' to add
+items.
+
+Please call the function `erlang-menu-init' after every change to this
+variable.")
+
+(defvar erlang-menu-base-items
+  '(("Indent"
+     (("Indent Line" erlang-indent-command)
+      ("Indent Region " erlang-indent-region
+       (if erlang-xemacs-p (mark) mark-active))
+      ("Indent Clause" erlang-indent-clause)
+      ("Indent Function" erlang-indent-function)
+      ("Indent Buffer" erlang-indent-current-buffer)))
+    ("Edit"
+     (("Fill Comment" erlang-fill-paragraph)
+      ("Comment Region" comment-region
+       (if erlang-xemacs-p (mark) mark-active))
+      ("Uncomment Region" erlang-uncomment-region
+       (if erlang-xemacs-p (mark) mark-active))
+      nil
+      ("Beginning of Function" erlang-beginning-of-function)
+      ("End of Function" erlang-end-of-function)
+      ("Mark Function" erlang-mark-function)
+      nil
+      ("Beginning of Clause" erlang-beginning-of-clause)
+      ("End of Clause" erlang-end-of-clause)
+      ("Mark Clause" erlang-mark-clause)
+      nil
+      ("New Clause" erlang-generate-new-clause)
+      ("Clone Arguments" erlang-clone-arguments)
+      nil
+      ("Align Arrows" erlang-align-arrows)))
+    ("Syntax Highlighting"
+     (("Level 4" erlang-font-lock-level-4)
+      ("Level 3" erlang-font-lock-level-3)
+      ("Level 2" erlang-font-lock-level-2)
+      ("Level 1" erlang-font-lock-level-1)
+      ("Off" erlang-font-lock-level-0)))
+    ("TAGS"
+     (("Find Tag" find-tag)
+      ("Find Next Tag" erlang-find-next-tag)
+					;("Find Regexp" find-tag-regexp)
+      ("Complete Word" erlang-complete-tag)
+      ("Tags Apropos" tags-apropos)
+      ("Search Files" tags-search))))
+  "Description of menu used in Erlang mode.
+
+This variable must be a list.  The elements are either nil representing
+a horizontal line or a list with two or three elements.  The first is
+the name of the menu item, the second is the function to call, or a
+submenu, on the same same form as ITEMS.  The third optional argument
+is an expression which is evaluated every time the menu is displayed.
+Should the expression evaluate to nil the menu item is ghosted.
+
+Example:
+    '((\"Func1\" function-one)
+      (\"SubItem\"
+       ((\"Yellow\" function-yellow)
+        (\"Blue\" function-blue)))
+      nil
+      (\"Region Function\" spook-function midnight-variable))
+
+Call the function `erlang-menu-init' after modifying this variable.")
+
+(defvar erlang-menu-shell-items
+  '(nil
+    ("Shell"
+     (("Start New Shell" erlang-shell)
+      ("Display Shell"   erlang-shell-display))))
+  "Description of the Shell menu used by Erlang mode.
+
+Please see the documentation of `erlang-menu-base-items'.")
+
+(defvar erlang-menu-compile-items
+  '(("Compile"
+     (("Compile Buffer" erlang-compile)
+      ("Display Result" erlang-compile-display)
+      ("Next Error"     erlang-next-error))))
+  "Description of the Compile menu used by Erlang mode.
+
+Please see the documentation of `erlang-menu-base-items'.")
+
+(defvar erlang-menu-version-items
+  '(nil
+    ("Version" erlang-version))
+  "Description of the version menu used in Erlang mode.")
+
+(defvar erlang-menu-personal-items nil
+  "Description of personal menu items used in Erlang mode.
+
+Please see the variable `erlang-menu-base-items' for a description
+of the format.")
+
+(defvar erlang-menu-man-items nil
+  "The menu containing man pages.
+
+The format of the menu should be compatible with `erlang-menu-base-items'.
+This variable is added to the list of Erlang menus stored in
+`erlang-menu-items'.")
+
+(defvar erlang-menu-skel-items '()
+  "Description of the menu containing the skeleton entries.
+The menu is in the form described by the variable `erlang-menu-base-items'.")
+
+(defvar erlang-mode-hook nil
+  "*Functions to run when Erlang mode is activated.
+
+This hook is used to change the behaviour of Erlang mode.  It is
+normally used by the user to personalise the programming environment.
+When used in a site init file, it could be used to customise Erlang
+mode for all users on the system.
+
+The functions added to this hook are run every time Erlang mode is
+started.  See also `erlang-load-hook', a hook which is run once,
+when Erlang mode is loaded into Emacs, and `erlang-shell-mode-hook'
+which is run every time a new inferior Erlang shell is started.
+
+To use a hook, create an Emacs lisp function to perform your actions
+and add the function to the hook by calling `add-hook'.
+
+The following example binds the key sequence C-c C-c to the command
+`erlang-compile' (normally bound to C-c C-k).  The example also
+activates Font Lock mode to fontify the buffer and adds a menu
+containing all functions defined in the current buffer.
+
+To use the example, copy the following lines to your `~/.emacs' file:
+
+    (add-hook 'erlang-mode-hook 'my-erlang-mode-hook)
+
+    (defun my-erlang-mode-hook ()
+      (local-set-key \"\\C-c\\C-c\" 'erlang-compile)
+      (if window-system
+          (progn
+            (setq font-lock-maximum-decoration t)
+            (font-lock-mode 1)))
+      (if (and window-system (fboundp 'imenu-add-to-menubar))
+          (imenu-add-to-menubar \"Imenu\")))")
+
+(defvar erlang-load-hook nil
+  "*Functions to run when Erlang mode is loaded.
+
+This hook is used to change the behaviour of Erlang mode.  It is
+normally used by the user to personalise the programming environment.
+When used in a site init file, it could be used to customize Erlang
+mode for all users on the system.
+
+The difference between this hook and `erlang-mode-hook' and
+`erlang-shell-mode-hook' is that the functions in this hook
+is only called once, when the Erlang mode is loaded into Emacs
+the first time.
+
+Natural actions for the functions added to this hook are actions which
+only should be performed once, and actions which should be performed
+before starting Erlang mode.  For example, a number of variables are
+used by Erlang mode before `erlang-mode-hook' is run.
+
+The following example sets the variable `erlang-root-dir' so that the
+manual pages can be retrieved (note that you must set the value of
+`erlang-root-dir' to match the location of Erlang on your system):
+
+    (add-hook 'erlang-load-hook 'my-erlang-load-hook)
+
+    (defun my-erlang-load-hook ()
+       (setq erlang-root-dir \"/usr/local/erlang\"))")
+
+(defvar erlang-new-file-hook nil
+  "Functions to run when a new Erlang source file is being edited.
+
+A useful function is `tempo-template-erlang-normal-header'.
+\(This function only exists when the `tempo' package is available.)")
+
+(defvar erlang-check-module-name 'ask
+  "*Non-nil means check that module name and file name agrees when saving.
+
+If the value of this variable is the atom `ask', the user is
+prompted.  If the value is t the source is silently changed.")
+
+(defvar erlang-electric-commands
+  '(erlang-electric-comma
+    erlang-electric-semicolon
+    erlang-electric-gt)
+  "*List of activated electric commands.
+
+The list should contain the electric commands which should be active.
+Currently, the available electric commands are:
+    `erlang-electric-comma'
+    `erlang-electric-semicolon'
+    `erlang-electric-gt'
+    `erlang-electric-newline'
+
+Should the variable be bound to t, all electric commands
+are activated.
+
+To deactivate all electric commands, set this variable to nil.")
+
+(defvar erlang-electric-newline-inhibit t
+  "*Set to non-nil to inhibit newline after electric command.
+
+This is useful since a lot of people press return after executing an
+electric command.
+
+In order to work, the command must also be in the
+list `erlang-electric-newline-inhibit-list'.
+
+Note that commands in this list are required to set the variable
+`erlang-electric-newline-inhibit' to nil when the newline shouldn't be
+inhibited.")
+
+(defvar erlang-electric-newline-inhibit-list
+  '(erlang-electric-semicolon
+    erlang-electric-comma
+    erlang-electric-gt)
+  "*Commands which can inhibit the next newline.")
+
+(defvar erlang-electric-semicolon-insert-blank-lines nil
+  "*Number of blank lines inserted before header, or nil.
+
+This variable controls the behaviour of `erlang-electric-semicolon'
+when a new function header is generated.  When nil, no blank line is
+inserted between the current line and the new header.  When bound to a
+number it represents the number of blank lines which should be
+inserted.")
+
+(defvar erlang-electric-semicolon-criteria
+  '(erlang-next-lines-empty-p
+    erlang-at-keyword-end-p
+    erlang-at-end-of-function-p)
+  "*List of functions controlling `erlang-electric-semicolon'.
+The functions in this list are called, in order, whenever a semicolon
+is typed.  Each function in the list is called with no arguments,
+and should return one of the following values:
+
+  nil             -- no determination made, continue checking
+  'stop           -- do not create prototype for next line
+  (anything else) -- insert prototype, and stop checking
+
+If every function in the list is called with no determination made,
+then no prototype is inserted.
+
+The test is performed by the function `erlang-test-criteria-list'.")
+
+(defvar erlang-electric-comma-criteria
+  '(erlang-stop-when-inside-argument-list
+    erlang-stop-when-at-guard
+    erlang-next-lines-empty-p
+    erlang-at-keyword-end-p
+    erlang-at-end-of-clause-p
+    erlang-at-end-of-function-p)
+  "*List of functions controlling `erlang-electric-comma'.
+The functions in this list are called, in order, whenever a comma
+is typed.  Each function in the list is called with no arguments,
+and should return one of the following values:
+
+  nil             -- no determination made, continue checking
+  'stop           -- do not create prototype for next line
+  (anything else) -- insert prototype, and stop checking
+
+If every function in the list is called with no determination made,
+then no prototype is inserted.
+
+The test is performed by the function `erlang-test-criteria-list'.")
+
+(defvar erlang-electric-arrow-criteria
+  '(erlang-next-lines-empty-p
+    erlang-at-end-of-function-p)
+  "*List of functions controlling the arrow aspect of `erlang-electric-gt'.
+The functions in this list are called, in order, whenever a `>'
+is typed.  Each function in the list is called with no arguments,
+and should return one of the following values:
+
+  nil             -- no determination made, continue checking
+  'stop           -- do not create prototype for next line
+  (anything else) -- insert prototype, and stop checking
+
+If every function in the list is called with no determination made,
+then no prototype is inserted.
+
+The test is performed by the function `erlang-test-criteria-list'.")
+
+(defvar erlang-electric-newline-criteria
+  '(t)
+  "*List of functions controlling `erlang-electric-newline'.
+
+The electric newline commands indents the next line.  Should the
+current line begin with a comment the comment start is copied to
+the newly created line.
+
+The functions in this list are called, in order, whenever a comma
+is typed.  Each function in the list is called with no arguments,
+and should return one of the following values:
+
+  nil             -- no determination made, continue checking
+  'stop           -- do not create prototype for next line
+  (anything else) -- trigger the electric command.
+
+If every function in the list is called with no determination made,
+then no prototype is inserted.  Should the atom t be a member of the
+list, it is treated as a function triggering the electric command.
+
+The test is performed by the function `erlang-test-criteria-list'.")
+
+(defvar erlang-next-lines-empty-threshold 2
+  "*Number of blank lines required to activate an electric command.
+
+Actually, this value controls the behaviour of the function
+`erlang-next-lines-empty-p' which normally is a member of the
+criteria lists controlling the electric commands.  (Please see
+the variables `erlang-electric-semicolon-criteria' and
+`erlang-electric-comma-criteria'.)
+
+The variable is bound to a threshold value, a number, representing the
+number of lines which must be empty.
+
+Setting this variable to zero, electric commands will always be
+triggered by `erlang-next-lines-empty-p', unless inhibited by other
+rules.
+
+Should this variable be nil, `erlang-next-lines-empty-p' will never
+trigger an electric command.  The same effect would be reached if the
+function `erlang-next-lines-empty-p' would be removed from the criteria
+lists.
+
+Note that even if `erlang-next-lines-empty-p' should not trigger an
+electric command, other functions in the criteria list could.")
+
+(defvar erlang-new-clause-with-arguments nil
+  "*Non-nil means that the arguments are cloned when a clause is generated.
+
+A new function header can be generated by calls to the function
+`erlang-generate-new-clause' and by use of the electric semicolon.")
+
+(defvar erlang-compile-use-outdir t
+  "*When nil, go to the directory containing source file when compiling.
+
+This is a workaround for a bug in the `outdir' option of compile.  If the
+outdir is not in the current load path, Erlang doesn't load the object
+module after it has been compiled.
+
+To activate the workaround, place the following in your `~/.emacs' file:
+    (setq erlang-compile-use-outdir nil)")
+
+(defvar erlang-indent-level 4
+  "*Indentation of Erlang calls/clauses within blocks.")
+
+(defvar erlang-indent-guard 2
+  "*Indentation of Erlang guards.")
+
+(defvar erlang-argument-indent 2
+  "*Indentation of the first argument in a function call.
+When nil, indent to the column after the `(' of the
+function.")
+
+(defvar erlang-tab-always-indent t
+  "*Non-nil means TAB in Erlang mode should always re-indent the current line,
+regardless of where in the line point is when the TAB command is used.")
+
+(defvar erlang-error-regexp-alist
+  '(("^\\([^:( \t\n]+\\)[:(][ \t]*\\([0-9]+\\)[:) \t]" . (1 2)))
+  "*Patterns for matching Erlang errors.")
+
+(defvar erlang-man-inhibit (eq system-type 'windows-nt)
+  "Inhibit the creation of the Erlang Manual Pages menu.
+
+The Windows distribution of Erlang does not include man pages, hence
+there is no attempt to create the menu.")
+
+(defvar erlang-man-dirs
+  '(("Man - Commands" "/man/man1" t)
+    ("Man - Modules" "/man/man3" t)
+    ("Man - Files" "/man/man4" t)
+    ("Man - Applications" "/man/man6" t))
+  "*The man directories displayed in the Erlang menu.
+
+Each item in the list should be a list with three elements, the first
+the name of the menu, the second the directory, and the last a flag.
+Should the flag the nil, the directory is absolute, should it be non-nil
+the directory is relative to the variable `erlang-root-dir'.")
+
+(defvar erlang-man-max-menu-size 35
+  "*The maximum number of menu items in one menu allowed.")
+
+(defvar erlang-man-display-function 'erlang-man-display
+  "*Function used to display man page.
+
+The function is called with one argument, the name of the file
+containing the man page.  Use this variable when the default
+function, `erlang-man-display', does not work on your system.")
+
+(defvar erlang-compile-extra-opts '()
+  "*Additional options to the compilation command.
+This is an elisp list of options. Each option can be either:
+- an atom
+- a dotted pair
+- a string
+Example: '(bin_opt_info (i . \"/path1/include\") (i . \"/path2/include\"))")
+
+(eval-and-compile
+  (defvar erlang-regexp-modern-p
+    (if (> erlang-emacs-major-version 21) t nil)
+    "Non-nil when this version of Emacs uses a modern version of regexp.
+Supporting \_< and \_> This is determined by checking the version of Emacs used."))
+
+(eval-and-compile
+  (defconst erlang-atom-quoted-regexp 
+    "'\\(?:[^\\']\\|\\(?:\\\\.\\)\\)*'"
+    "Regexp describing a single-quoted atom"))
+
+(eval-and-compile
+  (defconst erlang-atom-regular-regexp
+    (if erlang-regexp-modern-p
+	"\\_<[[:lower:]]\\(?:\\sw\\|\\s_\\)*\\_>"
+      "\\<[[:lower:]]\\(?:\\sw\\|\\s_\\)*\\>")
+    "Regexp describing a regular (non-quoted) atom"))
+
+(eval-and-compile
+  (defconst erlang-atom-regexp 
+    (concat "\\(" erlang-atom-quoted-regexp "\\|" 
+	    erlang-atom-regular-regexp "\\)")
+    "Regexp describing an Erlang atom."))
+
+(eval-and-compile
+  (defconst erlang-atom-regexp-matches 1
+    "Number of regexp parenthesis pairs in `erlang-atom-regexp'.
+  
+This is used to determine parenthesis matches in complex regexps which
+contains `erlang-atom-regexp'."))
+
+
+(eval-and-compile
+  (defconst erlang-variable-regexp 
+    (if erlang-regexp-modern-p 
+	"\\_<\\([[:upper:]_]\\(?:\\sw\\|\\s_\\)*\\)\\_>"
+      "\\<\\([[:upper:]_]\\(?:\\sw\\|\\s_\\)*\\)\\>")
+    "Regexp which should match an Erlang variable.
+
+The regexp must be surrounded with a pair of regexp parentheses."))
+
+(eval-and-compile
+  (defconst erlang-variable-regexp-matches 1
+    "Number of regexp parenthesis pairs in `erlang-variable-regexp'.
+
+This is used to determine matches in complex regexps which contains
+`erlang-variable-regexp'."))
+
+
+(eval-and-compile
+  (defun erlang-regexp-opt (strings &optional paren)
+    "Like `regexp-opt', except if PAREN is `symbols', then the
+resulting regexp is surrounded by \\_< and \\_>."
+    (if (eq paren 'symbols)
+	(if erlang-regexp-modern-p
+	    (concat "\\_<" (regexp-opt strings t) "\\_>")
+	  (concat "\\<" (regexp-opt strings t) "\\>"))
+      (regexp-opt strings paren))))
+
+
+(eval-and-compile 
+  (defvar erlang-keywords
+    '("after"
+      "begin"
+      "catch"
+      "case"
+      "cond"
+      "end"
+      "fun"
+      "if"
+      "let"
+      "of"
+      "query"
+      "receive"
+      "try"
+      "when")
+    "Erlang reserved keywords"))
+
+(eval-and-compile
+  (defconst erlang-keywords-regexp (erlang-regexp-opt erlang-keywords 'symbols)))
+  
+(eval-and-compile
+  (defvar erlang-operators
+    '("and"
+      "andalso"
+      "band"
+      "bnot"
+      "bor"
+      "bsl"
+      "bsr"
+      "bxor"
+      "div"
+      "not"
+      "or"
+      "orelse"
+      "rem"
+      "xor")
+    "Erlang operators"))
+;; What about these?
+;; '+' '-' '*' '/' '>', '>=', '<', '=<', '=:=', '==', '=/=', '/='
+
+(eval-and-compile
+  (defconst erlang-operators-regexp (erlang-regexp-opt erlang-operators 'symbols)))
+  
+
+(eval-and-compile
+  (defvar erlang-guards
+    '("is_atom"
+      "is_binary"
+      "is_bitstring"
+      "is_boolean"
+      "is_float"
+      "is_function"
+      "is_integer"
+      "is_list"
+      "is_number"
+      "is_pid"
+      "is_port"
+      "is_record"
+      "is_reference"
+      "is_tuple"
+      "atom"
+      "binary"
+      "bitstring"
+      "boolean"
+      ;;"float"	; Not included to avoid clashes with the bif float/1
+      "function"
+      "integer"
+      "list"
+      "number"
+      "pid"
+      "port"
+      "record"
+      "reference"
+      "tuple")
+    "Erlang guards"))
+
+(eval-and-compile
+  (defconst erlang-guards-regexp (erlang-regexp-opt erlang-guards 'symbols)))
+
+(eval-and-compile
+  (defvar erlang-predefined-types
+    '("any"
+      "arity"
+      "boolean"
+      "byte"
+      "char"
+      "cons"
+      "deep_string"
+      "iolist"
+      "maybe_improper_list"
+      "module"
+      "mfa"
+      "nil"
+      "neg_integer"
+      "none"
+      "non_neg_integer"
+      "nonempty_list"
+      "nonempty_improper_list"
+      "nonempty_maybe_improper_list"
+      "no_return"
+      "pos_integer"
+      "string"
+      "term"
+      "timeout")
+    "Erlang type specs types"))
+
+(eval-and-compile
+  (defconst erlang-predefined-types-regexp 
+    (erlang-regexp-opt erlang-predefined-types 'symbols)))
+
+
+(eval-and-compile
+  (defvar erlang-int-bifs
+    '("abs"
+      "adler32"
+      "adler32_combine"
+      "alive"
+      "apply"
+      "atom_to_binary"
+      "atom_to_list"
+      "binary_to_atom"
+      "binary_to_existing_atom"
+      "binary_to_list"
+      "binary_to_term"
+      "bit_size"
+      "bitstring_to_list"
+      "byte_size"
+      "check_process_code"
+      "contact_binary"
+      "crc32"
+      "crc32_combine"
+      "date"
+      "decode_packet"
+      "delete_module"
+      "disconnect_node"
+      "element"
+      "erase"
+      "exit"
+      "float"
+      "float_to_list"
+      "garbage_collect"
+      "get"
+      "get_keys"
+      "group_leader"
+      "halt"
+      "hd"
+      "integer_to_list"
+      "internal_bif"
+      "iolist_size"
+      "iolist_to_binary"
+      "is_alive"
+      "is_atom"
+      "is_binary"
+      "is_bitstring"
+      "is_boolean"
+      "is_float"
+      "is_function"
+      "is_integer"
+      "is_list"
+      "is_number"
+      "is_pid"
+      "is_port"
+      "is_process_alive"
+      "is_record"
+      "is_reference"
+      "is_tuple"
+      "length"
+      "link"
+      "list_to_atom"
+      "list_to_binary"
+      "list_to_bitstring"
+      "list_to_existing_atom"
+      "list_to_float"
+      "list_to_integer"
+      "list_to_pid"
+      "list_to_tuple"
+      "load_module"
+      "make_ref"
+      "module_loaded"
+      "monitor_node"
+      "node"
+      "node_link"
+      "node_unlink"
+      "nodes"
+      "notalive"
+      "now"
+      "open_port"
+      "pid_to_list"
+      "port_close"
+      "port_command"
+      "port_connect"
+      "port_control"
+      "pre_loaded"
+      "process_flag"
+      "process_info"
+      "processes"
+      "purge_module"
+      "put"
+      "register"
+      "registered"
+      "round"
+      "self"
+      "setelement"
+      "size"
+      "spawn"
+      "spawn_link"
+      "spawn_monitor"
+      "spawn_opt"
+      "split_binary"
+      "statistics"
+      "term_to_binary"
+      "time"
+      "throw"
+      "tl"
+      "trunc"
+      "tuple_size"
+      "tuple_to_list"
+      "unlink"
+      "unregister"
+      "whereis")
+    "Erlang built-in functions (BIFs)"))
+
+(eval-and-compile
+  (defconst erlang-int-bif-regexp (erlang-regexp-opt erlang-int-bifs 'symbols)))
+  
+
+(eval-and-compile
+  (defvar erlang-ext-bifs
+    '("append_element"
+      "bump_reductions"
+      "cancel_timer"
+      "demonitor"
+      "display"
+      "fun_info"
+      "fun_to_list"
+      "function_exported"
+      "get_cookie"
+      "get_stacktrace"
+      "hash"
+      "integer_to_list"
+      "is_builtin"
+      "list_to_integer"
+      "loaded"
+      "localtime"
+      "localtime_to_universaltime"
+      "make_tuple"
+      "max"
+      "md5"
+      "md5_final"
+      "md5_init"
+      "md5_update"
+      "memory"
+      "min"
+      "monitor"
+      "monitor_node"
+      "phash"
+      "phash2"
+      "port_call"
+      "port_info"
+      "port_to_list"
+      "ports"
+      "process_display"
+      "read_timer"
+      "ref_to_list"
+      "resume_process"
+      "send"
+      "send_after"
+      "send_nosuspend"
+      "set_cookie"
+      "start_timer"
+      "suspend_process"
+      "system_flag"
+      "system_info"
+      "system_monitor"
+      "system_profile"
+      "trace"
+      "trace_delivered"
+      "trace_info"
+      "trace_pattern"
+      "universaltime"
+      "universaltime_to_localtime"
+      "yield")
+    "Erlang built-in functions (BIFs) that needs erlang: prefix"))
+
+(eval-and-compile
+  (defconst erlang-ext-bif-regexp
+    (erlang-regexp-opt (append erlang-int-bifs erlang-ext-bifs) 'symbols)))
+
+
+(defvar erlang-defun-prompt-regexp (concat "^" erlang-atom-regexp "\\s *(")
+  "Regexp which should match beginning of a clause.")
+
+(defvar erlang-file-name-extension-regexp "\\.[eh]rl$"
+  "*Regexp which should match an Erlang file name.
+
+This regexp is used when an Erlang module name is extracted from the
+name of an Erlang source file.
+
+The regexp should only match the section of the file name which should
+be excluded from the module name.
+
+To match all files set this variable to \"\\\\(\\\\..*\\\\|\\\\)$\".
+The matches all except the extension.  This is useful if the Erlang
+tags system should interpret tags on the form `module:tag' for
+files written in other languages than Erlang.")
+
+(defvar erlang-inferior-shell-split-window t
+  "*If non-nil, when starting an inferior shell, split windows.
+If nil, the inferior shell replaces the window. This is the traditional
+behaviour.")
+
+(defconst inferior-erlang-use-cmm (boundp 'minor-mode-overriding-map-alist)
+  "Non-nil means use `compilation-minor-mode' in Erlang shell.")
+
+(defvar erlang-mode-map
+  (let ((map (make-sparse-keymap)))
+    (unless (boundp 'indent-line-function)
+      (define-key map "\t"        'erlang-indent-command))
+    (define-key map ";"	      'erlang-electric-semicolon)
+    (define-key map ","	      'erlang-electric-comma)
+    (define-key map "<"         'erlang-electric-lt)
+    (define-key map ">"         'erlang-electric-gt)
+    (define-key map "\C-m"      'erlang-electric-newline)
+    (if (not (boundp 'delete-key-deletes-forward))
+        (define-key map "\177" 'backward-delete-char-untabify)
+      (define-key map [(backspace)] 'backward-delete-char-untabify))
+    ;;(unless (boundp 'fill-paragraph-function)
+    (define-key map "\M-q"      'erlang-fill-paragraph)
+    (unless (boundp 'beginning-of-defun-function)
+      (define-key map "\M-\C-a"   'erlang-beginning-of-function)
+      (define-key map "\M-\C-e"   'erlang-end-of-function)
+      (define-key map '(meta control h)   'erlang-mark-function))	; Xemacs
+    (define-key map "\M-\t"     'erlang-complete-tag)
+    (define-key map "\C-c\M-\t" 'tempo-complete-tag)
+    (define-key map "\M-+"      'erlang-find-next-tag)
+    (define-key map "\C-c\M-a"  'erlang-beginning-of-clause)
+    (define-key map "\C-c\M-b"  'tempo-backward-mark)
+    (define-key map "\C-c\M-e"  'erlang-end-of-clause)
+    (define-key map "\C-c\M-f"  'tempo-forward-mark)
+    (define-key map "\C-c\M-h"  'erlang-mark-clause)
+    (define-key map "\C-c\C-c"  'comment-region)
+    (define-key map "\C-c\C-j"  'erlang-generate-new-clause)
+    (define-key map "\C-c\C-k"  'erlang-compile)
+    (define-key map "\C-c\C-l"  'erlang-compile-display)
+    (define-key map "\C-c\C-s"  'erlang-show-syntactic-information)
+    (define-key map "\C-c\C-q"  'erlang-indent-function)
+    (define-key map "\C-c\C-u"  'erlang-uncomment-region)
+    (define-key map "\C-c\C-y"  'erlang-clone-arguments)
+    (define-key map "\C-c\C-a"  'erlang-align-arrows)
+    (define-key map "\C-c\C-z"  'erlang-shell-display)
+    (unless inferior-erlang-use-cmm
+      (define-key map "\C-x`"    'erlang-next-error))
+    map)
+  "*Keymap used in Erlang mode.")
+(defvar erlang-mode-abbrev-table nil
+  "Abbrev table in use in Erlang-mode buffers.")
+(defvar erlang-mode-syntax-table nil
+  "Syntax table in use in Erlang-mode buffers.")
+
+
+
+(defvar erlang-skel-file "erlang-skels"
+  "The type of erlang-skeletons that should be used, default
+   uses edoc type, for the old type, standard comments,
+   set \"erlang-skels-old\" in your .emacs and restart.
+
+   Or define your own and set the variable to that file.")
+
+;; Tempo skeleton templates:
+(load erlang-skel-file)
+
+;; Font-lock variables
+
+;; The next few variables define different Erlang font-lock patterns.
+;; They could be appended to form a custom font-lock appearance.
+;;
+;; The function `erlang-font-lock-set-face' could be used to change
+;; the face of a pattern.
+;;
+;; Note that Erlang strings and atoms are highlighted with using
+;; syntactic analysis.
+
+(defvar erlang-font-lock-keywords-function-header
+  (list
+   (list (concat "^" erlang-atom-regexp "\\s-*(")
+	 1 'font-lock-function-name-face t))
+  "Font lock keyword highlighting a function header.")
+
+(defvar erlang-font-lock-keywords-int-bifs
+  (list
+   (list (concat erlang-int-bif-regexp "\\s-*(")
+         1 'font-lock-builtin-face))
+  "Font lock keyword highlighting built in functions.")
+
+(defvar erlang-font-lock-keywords-ext-bifs
+  (list
+   (list (concat "\\<\\(erlang\\)\\s-*:\\s-*" erlang-ext-bif-regexp "\\s-*(")
+	 '(1 'font-lock-builtin-face)
+	 '(2 'font-lock-builtin-face)))
+  "Font lock keyword highlighting built in functions.")
+
+(defvar erlang-font-lock-keywords-int-function-calls
+  (list
+   (list (concat erlang-atom-regexp "\\s-*(")
+         1 'font-lock-type-face))
+  "Font lock keyword highlighting an internal function call.")
+
+(defvar erlang-font-lock-keywords-ext-function-calls
+  (list
+   (list (concat erlang-atom-regexp "\\s-*:\\s-*"
+                 erlang-atom-regexp "\\s-*(")
+         '(1 'font-lock-type-face)
+	 '(2 'font-lock-type-face)))
+  "Font lock keyword highlighting an external function call.")
+
+(defvar erlang-font-lock-keywords-fun-n
+  (list
+   (list (concat "\\(" erlang-atom-regexp "/[0-9]+\\)")
+         1 'font-lock-type-face))
+  "Font lock keyword highlighting a fun descriptor in F/N format.")
+
+(defvar erlang-font-lock-keywords-operators
+  (list
+   (list erlang-operators-regexp
+         1 'font-lock-builtin-face))
+  "Font lock keyword highlighting Erlang operators.")
+
+(defvar erlang-font-lock-keywords-dollar
+  (list
+   (list "\\(\\$\\([^\\]\\|\\\\\\([^0-7^\n]\\|[0-7]+\\|\\^[a-zA-Z]\\)\\)\\)"
+	 1 'font-lock-constant-face))
+  "Font lock keyword highlighting numbers in ASCII form (e.g. $A).")
+
+(defvar erlang-font-lock-keywords-arrow
+  (list
+   (list "->\\(\\s \\|$\\)" 1 'font-lock-function-name-face))
+  "Font lock keyword highlighting clause arrow.")
+
+(defvar erlang-font-lock-keywords-lc
+  (list
+   (list "\\(<-\\|<=\\|||\\)\\(\\s \\|$\\)" 1 'font-lock-keyword-face))
+  "Font lock keyword highlighting list comprehension operators.")
+
+(defvar erlang-font-lock-keywords-keywords
+  (list
+   (list erlang-keywords-regexp 1 'font-lock-keyword-face))
+  "Font lock keyword highlighting Erlang keywords.")
+
+(defvar erlang-font-lock-keywords-attr
+  (list
+   (list (concat "^\\(-" erlang-atom-regexp "\\)\\(\\s-\\|\\.\\|(\\)")	 
+	 1 (if (boundp 'font-lock-preprocessor-face)
+	       'font-lock-preprocessor-face
+	     'font-lock-constant-face)))
+  "Font lock keyword highlighting attributes.")
+
+(defvar erlang-font-lock-keywords-quotes
+  (list
+   (list "`\\([-+a-zA-Z0-9_:*][-+a-zA-Z0-9_:*]+\\)'"
+	 1
+	 'font-lock-keyword-face
+	 t))
+  "Font lock keyword highlighting words in single quotes in comments.
+
+This is not the highlighting of Erlang strings and atoms, which
+are highlighted by syntactic analysis.")
+
+(defvar erlang-font-lock-keywords-guards
+  (list
+   (list (concat "[^:]" erlang-guards-regexp "\\s-*(")
+	 1 'font-lock-builtin-face))
+  "Font lock keyword highlighting guards.")
+
+(defvar erlang-font-lock-keywords-predefined-types
+  (list
+   (list (concat "[^:]" erlang-predefined-types-regexp "\\s-*(")
+	 1 'font-lock-builtin-face))
+  "Font lock keyword highlighting predefined types.")
+
+
+(defvar erlang-font-lock-keywords-macros
+  (list
+   (list (concat "?\\s-*\\(" erlang-atom-regexp
+		 "\\|" erlang-variable-regexp "\\)")
+	 1 'font-lock-constant-face)
+   (list (concat "^\\(-\\(?:define\\|ifn?def\\)\\)\\s-*(\\s-*\\(" erlang-atom-regexp
+		 "\\|" erlang-variable-regexp "\\)")
+	 (if (boundp 'font-lock-preprocessor-face)
+	     (list 1 'font-lock-preprocessor-face t)
+	   (list 1 'font-lock-constant-face t))
+	 (list 3 'font-lock-type-face t t))
+   (list "^-e\\(lse\\|ndif\\)\\>" 0 'font-lock-preprocessor-face t))
+  "Font lock keyword highlighting macros.
+This must be placed in front of `erlang-font-lock-keywords-vars'.")
+
+(defvar erlang-font-lock-keywords-records
+  (list
+   (list (concat "#\\s *" erlang-atom-regexp)
+         1 'font-lock-type-face)
+   ;; Don't highlight numerical constants.
+   (list (if erlang-regexp-modern-p
+	     "\\_<[0-9]+#\\([0-9a-zA-Z]+\\)"
+	   "\\<[0-9]+#\\([0-9a-zA-Z]+\\)")
+         1 nil t)
+   (list (concat "^-record\\s-*(\\s-*" erlang-atom-regexp)
+         1 'font-lock-type-face))
+  "Font lock keyword highlighting Erlang records.
+This must be placed in front of `erlang-font-lock-keywords-vars'.")
+
+(defvar erlang-font-lock-keywords-vars
+  (list
+   (list (concat "[^#]" erlang-variable-regexp)	; no numerical constants
+	 1 'font-lock-variable-name-face))
+  "Font lock keyword highlighting Erlang variables.
+Must be preceded by `erlang-font-lock-keywords-macros' to work properly.")
+
+(defvar erlang-font-lock-descr-string
+  "Font-lock keywords used by Erlang Mode.
+
+There exists three levels of Font Lock keywords for Erlang:
+  `erlang-font-lock-keywords-1' - Function headers and reserved keywords.
+  `erlang-font-lock-keywords-2' - Bifs, guards and `single quotes'.
+  `erlang-font-lock-keywords-3' - Variables, macros and records.
+  `erlang-font-lock-keywords-4' - Function names, Funs, LCs (not Atoms)
+
+To use a specific level, please set the variable
+`font-lock-maximum-decoration' to the appropriate level.  Note that the
+variable must be set before Erlang mode is activated.
+
+Example:
+    (setq font-lock-maximum-decoration 2)")
+
+(defvar erlang-font-lock-keywords-1
+  (append erlang-font-lock-keywords-function-header
+	  erlang-font-lock-keywords-dollar
+	  erlang-font-lock-keywords-arrow
+	  erlang-font-lock-keywords-keywords
+	  )
+  ;; DocStringOrig: erlang-font-lock-keywords
+  erlang-font-lock-descr-string)
+
+(defvar erlang-font-lock-keywords-2
+  (append erlang-font-lock-keywords-1
+	  erlang-font-lock-keywords-int-bifs
+	  erlang-font-lock-keywords-ext-bifs
+	  erlang-font-lock-keywords-attr
+	  erlang-font-lock-keywords-quotes
+	  erlang-font-lock-keywords-guards
+	  )
+  ;; DocStringCopy: erlang-font-lock-keywords
+  erlang-font-lock-descr-string)
+
+(defvar erlang-font-lock-keywords-3
+  (append erlang-font-lock-keywords-2
+	  erlang-font-lock-keywords-operators
+	  erlang-font-lock-keywords-macros
+	  erlang-font-lock-keywords-records
+	  erlang-font-lock-keywords-vars
+	  erlang-font-lock-keywords-predefined-types
+	  )
+  ;; DocStringCopy: erlang-font-lock-keywords
+  erlang-font-lock-descr-string)
+
+(defvar erlang-font-lock-keywords-4
+  (append erlang-font-lock-keywords-3
+          erlang-font-lock-keywords-int-function-calls
+	  erlang-font-lock-keywords-ext-function-calls
+	  erlang-font-lock-keywords-fun-n
+          erlang-font-lock-keywords-lc
+	  )
+  ;; DocStringCopy: erlang-font-lock-keywords
+  erlang-font-lock-descr-string)
+
+(defvar erlang-font-lock-keywords erlang-font-lock-keywords-4
+  ;; DocStringCopy: erlang-font-lock-keywords
+  erlang-font-lock-descr-string)
+
+(defvar erlang-font-lock-syntax-table nil
+  "Syntax table used by Font Lock mode.
+
+The difference between this and the standard Erlang Mode
+syntax table is that `_' is treated as part of words by
+this syntax table.
+
+Unfortunately, XEmacs hasn't got support for a special Font
+Lock syntax table.  The effect is that `apply' in the atom
+`foo_apply' will be highlighted as a bif.")
+
+
+;;; Avoid errors while compiling this file.
+
+;; `eval-when-compile' is not defined in Emacs 18.  We define it as a
+;; no-op.
+(or (fboundp 'eval-when-compile)
+    (defmacro eval-when-compile (&rest rest) nil))
+
+;; These umm...functions are new in Emacs 20. And, yes, until version
+;; 19.27 Emacs backquotes were this ugly.
+
+(or (fboundp 'unless)
+    (defmacro unless (condition &rest body)
+      "(unless CONDITION BODY...): If CONDITION is false, do BODY, else return nil."
+      `((if (, condition) nil ,@body))))
+
+(or (fboundp 'when)
+    (defmacro when (condition &rest body)
+      "(when CONDITION BODY...): If CONDITION is true, do BODY, else return nil."
+      `((if (, condition) (progn ,@body) nil))))
+
+(or (fboundp 'char-before)
+    (defmacro char-before (&optional pos)
+      "Return the character in the current buffer just before POS."
+      `( (char-after (1- (or ,pos (point)))))))
+
+;; defvar some obsolete variables, which we still support for
+;; backwardscompatibility reasons.
+(eval-when-compile
+  (defvar comment-indent-hook)
+  (defvar dabbrev-case-fold-search)
+  (defvar tempo-match-finder)
+  (defvar compilation-menu-map)
+  (defvar next-error-last-buffer))
+
+(eval-when-compile
+  (if (or (featurep 'bytecomp)
+	  (featurep 'byte-compile))
+      (progn
+	(cond ((string-match "Lucid\\|XEmacs" emacs-version)
+	       (put 'comment-indent-hook 'byte-obsolete-variable nil)
+	       ;; Do not warn for unused variables
+	       ;; when compiling under XEmacs.
+	       (setq byte-compile-warnings
+		     '(free-vars unresolved callargs redefine))))
+	(require 'comint)
+	(require 'tempo)
+	(require 'compile))))
+
+
+(defun erlang-version ()
+  "Return the current version of Erlang mode."
+  (interactive)
+  (if (interactive-p)
+      (message "Erlang mode version %s, written by Anders Lindgren"
+	       erlang-version))
+  erlang-version)
+
+
+;;;###autoload
+(defun erlang-mode ()
+  "Major mode for editing Erlang source files in Emacs.
+It knows about syntax and comment, it can indent code, it is capable
+of fontifying the source file, the TAGS commands are aware of Erlang
+modules, and the Erlang man pages can be accessed.
+
+Should this module, \"erlang.el\", be installed properly, Erlang mode
+is activated whenever an Erlang source or header file is loaded into
+Emacs.  To indicate this, the mode line should contain the word
+\"Erlang\".
+
+The main feature of Erlang mode is indentation, press TAB and the
+current line will be indented correctly.
+
+Comments starting with only one `%' are indented to the column stored
+in the variable `comment-column'.  Comments starting with two `%':s
+are indented with the same indentation as code.  Comments starting
+with at least three `%':s are indented to the first column.
+
+However, Erlang mode contains much more, this is a list of the most
+useful commands:
+     TAB     - Indent the line.
+     C-c C-q - Indent current function.
+     M-;     - Create a comment at the end of the line.
+     M-q     - Fill a comment, i.e. wrap lines so that they (hopefully)
+		 will look better.
+     M-a     - Goto the beginning of an Erlang clause.
+     M-C-a   - Ditto for function.
+     M-e     - Goto the end of an Erlang clause.
+     M-C-e   - Ditto for function.
+     M-h     - Mark current Erlang clause.
+     M-C-h   - Ditto for function.
+     C-c C-z - Start, or switch to, an inferior Erlang shell.
+     C-c C-k - Compile current file.
+     C-x `   - Next error.
+     ,       - Electric comma.
+     ;       - Electric semicolon.
+
+Erlang mode check the name of the file against the module name when
+saving, whenever a mismatch occurs Erlang mode offers to modify the
+source.
+
+The variable `erlang-electric-commands' controls the electric
+commands.  To deactivate all of them, set it to nil.
+
+There exists a large number of commands and variables in the Erlang
+module.  Please press `M-x apropos RET erlang RET' to see a complete
+list.  Press `C-h f name-of-function RET' and `C-h v name-of-variable
+RET'to see the full description of functions and variables,
+respectively.
+
+On entry to this mode the contents of the hook `erlang-mode-hook' is
+executed.
+
+Please see the beginning of the file `erlang.el' for more information
+and examples of hooks.
+
+Other commands:
+\\{erlang-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (setq major-mode 'erlang-mode)
+  (setq mode-name "Erlang")
+  (erlang-syntax-table-init)
+  (use-local-map erlang-mode-map)
+  (erlang-electric-init)
+  (erlang-menu-init)
+  (erlang-mode-variables)
+  (erlang-check-module-name-init)
+  (erlang-add-compilation-alist erlang-error-regexp-alist)
+  (erlang-man-init)
+  (erlang-tags-init)
+  (erlang-font-lock-init)
+  (erlang-skel-init)
+  (tempo-use-tag-list 'erlang-tempo-tags)
+  (run-hooks 'erlang-mode-hook)
+  (if (zerop (buffer-size))
+      (run-hooks 'erlang-new-file-hook))
+  ;; Doesn't exist in Emacs v21.4; required by Emacs v23.
+  (if (boundp 'after-change-major-mode-hook)
+      (run-hooks 'after-change-major-mode-hook)))
+
+
+(defun erlang-syntax-table-init ()
+  (if (null erlang-mode-syntax-table)
+      (let ((table (make-syntax-table)))
+	(modify-syntax-entry ?\n ">" table)
+	(modify-syntax-entry ?\" "\"" table)
+	(modify-syntax-entry ?# "." table)
+;;	(modify-syntax-entry ?$ "\\" table)   ;; Creates problems with indention afterwards
+;;	(modify-syntax-entry ?$ "'" table)    ;; Creates syntax highlighting and indention problems
+	(modify-syntax-entry ?$ "/" table)    ;; Misses the corner case "string that ends with $" 
+	                                      ;; we have to live with that for now..it is the best alternative
+	                                      ;; that can be worked around with "string hat ends with \$" 
+	(modify-syntax-entry ?% "<" table)
+	(modify-syntax-entry ?& "." table)
+	(modify-syntax-entry ?\' "\"" table)
+	(modify-syntax-entry ?* "." table)
+	(modify-syntax-entry ?+ "." table)
+	(modify-syntax-entry ?- "." table)
+	(modify-syntax-entry ?/ "." table)
+	(modify-syntax-entry ?: "." table)
+	(modify-syntax-entry ?< "." table)
+	(modify-syntax-entry ?= "." table)
+	(modify-syntax-entry ?> "." table)
+	(modify-syntax-entry ?\\ "\\" table)
+	(modify-syntax-entry ?_ "_" table)
+	(modify-syntax-entry ?| "." table)
+	(modify-syntax-entry ?^ "'" table)
+	
+	;; Pseudo bit-syntax: Latin1 double angle quotes as parens.
+	;;(modify-syntax-entry ?\253 "(?\273" table)
+	;;(modify-syntax-entry ?\273 ")?\253" table)
+
+	(setq erlang-mode-syntax-table table)))
+
+  (set-syntax-table erlang-mode-syntax-table))
+
+
+(defun erlang-electric-init ()
+  ;; Set up electric character functions to work with
+  ;; delsel/pending-del mode. Also, set up text properties for bit
+  ;; syntax handling.
+  (mapc #'(lambda (cmd)
+	    (put cmd 'delete-selection t) ;for delsel (Emacs)
+	    (put cmd 'pending-delete t)) ;for pending-del (XEmacs)
+	'(erlang-electric-semicolon
+	  erlang-electric-comma
+	  erlang-electric-gt))
+  
+  (put 'bitsyntax-open-outer 'syntax-table '(4 . ?>))
+  (put 'bitsyntax-open-outer 'rear-nonsticky '(category))
+  (put 'bitsyntax-open-inner 'rear-nonsticky '(category))
+  (put 'bitsyntax-close-inner 'rear-nonsticky '(category))
+  (put 'bitsyntax-close-outer 'syntax-table '(5 . ?<))
+  (put 'bitsyntax-close-outer 'rear-nonsticky '(category))
+  (make-local-variable 'parse-sexp-lookup-properties)
+  (setq parse-sexp-lookup-properties 't))
+
+
+(defun erlang-mode-variables ()
+  (or erlang-mode-abbrev-table
+      (define-abbrev-table 'erlang-mode-abbrev-table ()))
+  (setq local-abbrev-table erlang-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 'paragraph-ignore-fill-prefix)
+  (setq paragraph-ignore-fill-prefix t)
+  (make-local-variable 'require-final-newline)
+  (setq require-final-newline t)
+  (make-local-variable 'defun-prompt-regexp)
+  (setq defun-prompt-regexp erlang-defun-prompt-regexp)
+  (make-local-variable 'comment-start)
+  (setq comment-start "%")
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip "%+\\s *")
+  (make-local-variable 'comment-column)
+  (setq comment-column 48)
+  (make-local-variable 'indent-line-function)
+  (setq indent-line-function 'erlang-indent-command)
+  (make-local-variable 'indent-region-function)
+  (setq indent-region-function 'erlang-indent-region)
+  (set (make-local-variable 'comment-indent-function) 'erlang-comment-indent)
+  (if (<= erlang-emacs-major-version 18)
+      (set (make-local-variable 'comment-indent-hook) 'erlang-comment-indent))
+  (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  (set (make-local-variable 'dabbrev-case-fold-search) nil)
+  (set (make-local-variable 'imenu-prev-index-position-function)
+       'erlang-beginning-of-function)
+  (set (make-local-variable 'imenu-extract-index-name-function)
+       'erlang-get-function-name-and-arity)
+  (set (make-local-variable 'tempo-match-finder)
+       "[^-a-zA-Z0-9_]\\([-a-zA-Z0-9_]*\\)\\=")
+  (set (make-local-variable 'beginning-of-defun-function)
+       'erlang-beginning-of-function)
+  (set (make-local-variable 'end-of-defun-function) 'erlang-end-of-function)
+  (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)
+  (set (make-local-variable 'fill-paragraph-function) 'erlang-fill-paragraph)
+  (set (make-local-variable 'comment-add) 1)
+  (set (make-local-variable 'outline-regexp) "[[:lower:]0-9_]+ *(.*) *-> *$")
+  (set (make-local-variable 'outline-level) (lambda () 1))
+  (set (make-local-variable 'add-log-current-defun-function)
+       'erlang-current-defun))
+
+
+;; Compilation.
+;;
+;; The following code is compatible with the standard package `compilation',
+;; making it possible to go to errors using `erlang-next-error' (or just
+;; `next-error' in Emacs 21).
+;;
+;; The normal `compile' command works of course.  For best result, please
+;; execute `make' with the `-w' flag.
+;;
+;; Please see the variables named `compiling-..' above.
+
+(defun erlang-add-compilation-alist (alist)
+  (require 'compile)
+  (cond ((boundp 'compilation-error-regexp-alist) ; Emacs 19
+	 (while alist
+	   (or (assoc (car (car alist)) compilation-error-regexp-alist)
+	       (setq compilation-error-regexp-alist
+		     (cons (car alist) compilation-error-regexp-alist)))
+	   (setq alist (cdr alist))))
+	((boundp 'compilation-error-regexp)
+	 ;; Emacs 18,  Only one regexp is allowed.
+	 (funcall (symbol-function 'set)
+		  'compilation-error-regexp (car (car alist))))))
+
+(defun erlang-font-lock-init ()
+  "Initialize Font Lock for Erlang mode."
+  (or erlang-font-lock-syntax-table
+      (setq erlang-font-lock-syntax-table
+	    (let ((table (copy-syntax-table erlang-mode-syntax-table)))
+	      (modify-syntax-entry ?_ "w" table)
+	      table)))
+  (set (make-local-variable 'font-lock-syntax-table)
+       erlang-font-lock-syntax-table)
+  (set (make-local-variable 'font-lock-beginning-of-syntax-function)
+       'erlang-beginning-of-clause)
+  (make-local-variable 'font-lock-keywords)
+  (let ((level (cond ((boundp 'font-lock-maximum-decoration)
+		      (symbol-value 'font-lock-maximum-decoration))
+		     ((boundp 'font-lock-use-maximal-decoration)
+		      (symbol-value 'font-lock-use-maximal-decoration))
+		     (t nil))))
+    (if (consp level)
+	(setq level (cdr-safe (or (assq 'erlang-mode level)
+				  (assq t level)))))
+    ;; `level' can here be:
+    ;;      A number - The fontification level
+    ;;      nil      - Use the default
+    ;;      t        - Use maximum
+    (cond ((eq level nil)
+	   (set 'font-lock-keywords erlang-font-lock-keywords))
+	  ((eq level 1)
+	   (set 'font-lock-keywords erlang-font-lock-keywords-1))
+	  ((eq level 2)
+	   (set 'font-lock-keywords erlang-font-lock-keywords-2))
+          ((eq level 3)
+           (set 'font-lock-keywords erlang-font-lock-keywords-3))
+          (t
+           (set 'font-lock-keywords erlang-font-lock-keywords-4))))
+
+  ;; Modern font-locks can handle the above much more elegantly:
+  (set (make-local-variable 'font-lock-defaults)
+       '((erlang-font-lock-keywords erlang-font-lock-keywords-1
+				    erlang-font-lock-keywords-2 
+				    erlang-font-lock-keywords-3 
+				    erlang-font-lock-keywords-4)
+	 nil nil ((?_ . "w")) erlang-beginning-of-clause
+	 (font-lock-mark-block-function . erlang-mark-clause))))
+
+
+
+;; Useful when defining your own keywords.
+(defun erlang-font-lock-set-face (ks &rest faces)
+  "Replace the face components in a list of keywords.
+
+The first argument, KS, is a list of keywords.  The rest of the
+arguments are expressions to replace the face information with.  The
+first expression replaces the face of the first keyword, the second
+expression the second keyword etc.
+
+Should an expression be nil, the face of the corresponding keyword is
+not changed.
+
+Should fewer expressions than keywords be given, the last expression
+is used for all remaining keywords.
+
+Normally, the expressions are just atoms representing the new face.
+They could however be more complex, returning different faces in
+different situations.
+
+This function only handles keywords with elements on the forms:
+  (REGEXP NUMBER FACE)
+  (REGEXP NUMBER FACE OVERWRITE)
+
+This could be used when defining your own special font-lock setup, e.g:
+
+\(setq my-font-lock-keywords
+      (append erlang-font-lock-keywords-function-header
+              erlang-font-lock-keywords-dollar
+              (erlang-font-lock-set-face
+               erlang-font-lock-keywords-macros 'my-neon-green-face)
+              (erlang-font-lock-set-face
+               erlang-font-lock-keywords-lc 'my-deep-red 'my-light-red)
+              erlang-font-lock-keywords-attr))
+
+For a more elaborate example, please see the beginning of the file
+`erlang.el'."
+  (let ((res '()))
+    (while ks
+      (let* ((regexp (car (car ks)))
+	     (number (car (cdr (car ks))))
+	     (new-face (if (and faces (car faces))
+			   (car faces)
+			 (car (cdr (cdr (car ks))))))
+	     (overwrite (car (cdr (cdr (cdr (car ks))))))
+	     (new-keyword (list regexp number new-face)))
+	(if overwrite (nconc new-keyword (list overwrite)))
+	(setq res (cons new-keyword res))
+	(setq ks (cdr ks))
+	(if (and faces (cdr faces))
+	    (setq faces (cdr faces)))))
+    (nreverse res)))
+
+
+(defun erlang-font-lock-level-0 ()
+  ;; DocStringOrig: font-cmd
+  "Unfontify current buffer."
+  (interactive)
+  (font-lock-mode 0))
+
+
+(defun erlang-font-lock-level-1 ()
+  ;; DocStringCopy: font-cmd
+  "Fontify current buffer at level 1.
+This highlights function headers, reserved keywords, strings and comments."
+  (interactive)
+  (require 'font-lock)
+  (set 'font-lock-keywords erlang-font-lock-keywords-1)
+  (font-lock-mode 1)
+  (funcall (symbol-function 'font-lock-fontify-buffer)))
+
+
+(defun erlang-font-lock-level-2 ()
+  ;; DocStringCopy: font-cmd
+  "Fontify current buffer at level 2.
+This highlights level 1 features (see `erlang-font-lock-level-1')
+plus bifs, guards and `single quotes'."
+  (interactive)
+  (require 'font-lock)
+  (set 'font-lock-keywords erlang-font-lock-keywords-2)
+  (font-lock-mode 1)
+  (funcall (symbol-function 'font-lock-fontify-buffer)))
+
+
+(defun erlang-font-lock-level-3 ()
+  ;; DocStringCopy: font-cmd
+  "Fontify current buffer at level 3.
+This highlights level 2 features (see `erlang-font-lock-level-2')
+plus variables, macros and records."
+  (interactive)
+  (require 'font-lock)
+  (set 'font-lock-keywords erlang-font-lock-keywords-3)
+  (font-lock-mode 1)
+  (funcall (symbol-function 'font-lock-fontify-buffer)))
+
+(defun erlang-font-lock-level-4 ()
+  ;; DocStringCopy: font-cmd
+  "Fontify current buffer at level 4.
+This highlights level 3 features (see `erlang-font-lock-level-2')
+plus variables, macros and records."
+  (interactive)
+  (require 'font-lock)
+  (set 'font-lock-keywords erlang-font-lock-keywords-4)
+  (font-lock-mode 1)
+  (funcall (symbol-function 'font-lock-fontify-buffer)))
+
+
+(defun erlang-menu-init ()
+  "Init menus for Erlang mode.
+
+The variable `erlang-menu-items' contain a description of the Erlang
+mode menu.  Normally, the list contains atoms, representing variables
+bound to pieces of the menu.
+
+Personal extensions could be added to `erlang-menu-personal-items'.
+
+This function should be called if any variable describing the
+menu configuration is changed."
+  (erlang-menu-install "Erlang" erlang-menu-items erlang-mode-map t))
+
+
+(defun erlang-menu-install (name items keymap &optional popup)
+  "Install a menu in Emacs or XEmacs based on an abstract description.
+
+NAME is the name of the menu.
+
+ITEMS is a list.  The elements are either nil representing a horizontal
+line or a list with two or three elements.  The first is the name of
+the menu item, the second the function to call, or a submenu, on the
+same same form as ITEMS.  The third optional element is an expression
+which is evaluated every time the menu is displayed.  Should the
+expression evaluate to nil the menu item is ghosted.
+
+KEYMAP is the keymap to add to menu to.  (When using XEmacs, the menu
+will only be visible when this menu is the global, the local, or an
+activate minor mode keymap.)
+
+If POPUP is non-nil, the menu is bound to the XEmacs `mode-popup-menu'
+variable, i.e. it will popup when pressing the right mouse button.
+
+Please see the variable `erlang-menu-base-items'."
+  (cond (erlang-xemacs-p
+	 (let ((menu (erlang-menu-xemacs name items keymap)))
+	   ;; We add the menu to the global menubar.
+	   ;;(funcall (symbol-function 'set-buffer-menubar)
+	   ;;         (symbol-value 'current-menubar))
+	   (funcall (symbol-function 'add-submenu) nil menu)
+	   (setcdr erlang-xemacs-popup-menu (cdr menu))
+	   (if (and popup (boundp 'mode-popup-menu))
+	       (funcall (symbol-function 'set)
+			'mode-popup-menu erlang-xemacs-popup-menu))))
+	((>= erlang-emacs-major-version 19)
+	 (define-key keymap (vector 'menu-bar (intern name))
+	   (erlang-menu-make-keymap name items)))
+	(t nil)))
+
+
+(defun erlang-menu-make-keymap (name items)
+  "Build a menu for Emacs 19."
+  (let ((menumap (funcall (symbol-function 'make-sparse-keymap)
+			  name))
+	(count 0)
+	id def first second third)
+    (setq items (reverse items))
+    (while items
+      ;; Replace any occurrence of atoms by their value.
+      (while (and items (atom (car items)) (not (null (car items))))
+	(if (and (boundp (car items))
+		 (listp (symbol-value (car items))))
+	    (setq items (append (reverse (symbol-value (car items)))
+				(cdr items)))
+	  (setq items (cdr items))))
+      (setq first (car-safe (car items)))
+      (setq second (car-safe (cdr-safe (car items))))
+      (setq third (car-safe (cdr-safe (cdr-safe (car items)))))
+      (cond ((null first)
+	     (setq count (+ count 1))
+	     (setq id (intern (format "separator-%d" count)))
+	     (setq def '("--" . nil)))
+	    ((and (consp second) (eq (car second) 'lambda))
+	     (setq count (+ count 1))
+	     (setq id (intern (format "lambda-%d" count)))
+	     (setq def (cons first second)))
+	    ((symbolp second)
+	     (setq id second)
+	     (setq def (cons first second)))
+	    (t
+	     (setq count (+ count 1))
+	     (setq id (intern (format "submenu-%d" count)))
+	     (setq def (erlang-menu-make-keymap first second))))
+      (define-key menumap (vector id) def)
+      (if third
+	  (put id 'menu-enable third))
+      (setq items (cdr items)))
+    (cons name menumap)))
+
+
+(defun erlang-menu-xemacs (name items &optional keymap)
+  "Build a menu for XEmacs."
+  (let ((res '())
+	first second third entry)
+    (while items
+      ;; Replace any occurrence of atoms by their value.
+      (while (and items (atom (car items)) (not (null (car items))))
+	(if (and (boundp (car items))
+		 (listp (symbol-value (car items))))
+	    (setq items (append (reverse (symbol-value (car items)))
+				(cdr items)))
+	  (setq items (cdr items))))
+      (setq first (car-safe (car items)))
+      (setq second (car-safe (cdr-safe (car items))))
+      (setq third (car-safe (cdr-safe (cdr-safe (car items)))))
+      (cond ((null first)
+	     (setq res (cons "------" res)))
+	    ((symbolp second)
+	     (setq res (cons (vector first second (or third t)) res)))
+	    ((and (consp second) (eq (car second) 'lambda))
+	     (setq res (cons (vector first (list 'call-interactively second)
+				     (or third t)) res)))
+	    (t
+	     (setq res (cons (cons first
+				   (cdr (erlang-menu-xemacs
+					 first second)))
+			     res))))
+      (setq items (cdr items)))
+    (setq res (reverse res))
+    ;; When adding a menu to a minor-mode keymap under Emacs,
+    ;; it disappears when the mode is disabled.  The expression
+    ;; generated below imitates this behaviour.
+    ;; (This could be expressed much clearer using backquotes,
+    ;; but I don't want to pull in every package.)
+    (if keymap
+	(let ((expr (list 'or
+			  (list 'eq keymap 'global-map)
+			  (list 'eq keymap (list 'current-local-map))
+			  (list 'symbol-value
+				(list 'car-safe
+				      (list 'rassq
+					    keymap
+					    'minor-mode-map-alist))))))
+	  (setq res (cons ':included (cons expr res)))))
+    (cons name res)))
+
+
+(defun erlang-menu-substitute (items alist)
+  "Substitute functions in menu described by ITEMS.
+
+The menu ITEMS is updated destructively.
+
+ALIST is list of pairs where the car is the old function and cdr the new."
+  (let (first second pair)
+    (while items
+      (setq first (car-safe (car items)))
+      (setq second (car-safe (cdr-safe (car items))))
+      (cond ((null first))
+	    ((symbolp second)
+	     (setq pair (and second (assq second alist)))
+	     (if pair
+		 (setcar (cdr (car items)) (cdr pair))))
+	    ((and (consp second) (eq (car second) 'lambda)))
+	    (t
+	     (erlang-menu-substitute second alist)))
+      (setq items (cdr items)))))
+
+
+(defun erlang-menu-add-above (entry above items)
+  "Add menu ENTRY above menu entry ABOVE in menu ITEMS.
+Do nothing if the items already should be in the menu.
+Should ABOVE not be in the list, the entry is added at
+the bottom of the menu.
+
+The new menu is returned.  No guarantee is given that the original
+menu is left unchanged.
+
+The equality test is performed by `eq'.
+
+Example:  (erlang-menu-add-above 'my-erlang-menu-items
+                                 'erlang-menu-man-items)"
+  (erlang-menu-add-below entry above items t))
+
+
+(defun erlang-menu-add-below (entry below items &optional above-p)
+  "Add menu ENTRY below menu items BELOW in the Erlang menu.
+Do nothing if the items already should be in the menu.
+Should BELOW not be in the list, items is added at the bottom
+of the menu.
+
+The new menu is returned.  No guarantee is given that the original
+menu is left unchanged.
+
+The equality test is performed by `eq'.
+
+Example:
+
+\(setq erlang-menu-items
+      (erlang-menu-add-below 'my-erlang-menu-items
+	 	             'erlang-menu-base-items
+                             erlang-menu-items))"
+  (if (memq entry items)
+      items				; Return the original menu.
+    (let ((head '())
+	  (done nil)
+	  res)
+      (while (not done)
+	(cond ((null items)
+	       (setq res (append head (list entry)))
+	       (setq done t))
+	      ((eq below (car items))
+	       (setq res
+		     (if above-p
+			 (append head (cons entry items))
+		       (append head (cons (car items)
+					  (cons entry (cdr items))))))
+	       (setq done t))
+	      (t
+	       (setq head (append head (list (car items))))
+	       (setq items (cdr items)))))
+      res)))
+
+(defun erlang-menu-delete (entry items)
+  "Delete ENTRY from menu ITEMS.
+
+The new menu is returned.  No guarantee is given that the original
+menu is left unchanged."
+  (delq entry items))
+
+;; Man code:
+
+(defun erlang-man-init ()
+  "Add menus containing the manual pages of the Erlang.
+
+The variable `erlang-man-dirs' contains entries describing
+the location of the manual pages."
+  (interactive)
+  (if erlang-man-inhibit
+      ()
+    (setq erlang-menu-man-items
+	  '(nil
+	    ("Man - Function" erlang-man-function)))
+    (if erlang-man-dirs
+	(setq erlang-menu-man-items
+	      (append erlang-menu-man-items
+		      (erlang-man-make-top-menu erlang-man-dirs))))
+    (setq erlang-menu-items
+	  (erlang-menu-add-above 'erlang-menu-man-items
+				 'erlang-menu-version-items
+				 erlang-menu-items))
+    (erlang-menu-init)))
+
+
+(defun erlang-man-uninstall ()
+  "Remove the man pages from the Erlang mode."
+  (interactive)
+  (setq erlang-menu-items
+	(erlang-menu-delete 'erlang-menu-man-items erlang-menu-items))
+  (erlang-menu-init))
+
+
+;; The man menu is a hierarchal structure, with the manual sections
+;; at the top, described by `erlang-man-dirs'.  The next level could
+;; either be the manual pages if not to many, otherwise it is an index
+;; menu whose submenus will contain up to `erlang-man-max-menu-size'
+;; manual pages.
+
+(defun erlang-man-make-top-menu (dir-list)
+  "Create one menu entry per element of DIR-LIST.
+The format is described in the documentation of `erlang-man-dirs'."
+  (let ((menu '())
+	dir)
+    (while dir-list
+      (setq dir (cond ((nth 2 (car dir-list))
+		       ;; Relative to `erlang-root-dir'.
+		       (and (stringp erlang-root-dir)
+			    (concat erlang-root-dir (nth 1 (car dir-list)))))
+		      (t
+		       ;; Absolute
+		       (nth 1 (car dir-list)))))
+      (if (and dir
+	       (file-readable-p dir))
+	  (setq menu (cons (list (car (car dir-list))
+				 (erlang-man-make-middle-menu
+				  (erlang-man-get-files dir)))
+			   menu)))
+      (setq dir-list (cdr dir-list)))
+    ;; Should no menus be found, generate a menu item which
+    ;; will display a help text, when selected.
+    (if menu
+	(nreverse menu)
+      '(("Man Pages"
+	 (("Error! Why?" erlang-man-describe-error)))))))
+
+
+;; Should the menu be to long, let's split it into a number of
+;; smaller menus.  Warning, this code contains beautiful
+;; destructive operations!
+(defun erlang-man-make-middle-menu (filelist)
+  "Create the second level menu from FILELIST.
+
+Should the list be longer than `erlang-man-max-menu-size', a tree of
+menus is created."
+  (if (<= (length filelist) erlang-man-max-menu-size)
+      (erlang-man-make-menu filelist)
+    (let ((menu '())
+	  (filelist (copy-sequence filelist))
+	  segment submenu pair)
+      (while filelist
+	(setq pair (nthcdr (- erlang-man-max-menu-size 1) filelist))
+	(setq segment filelist)
+	(if (null pair)
+	    (setq filelist nil)
+	  (setq filelist (cdr pair))
+	  (setcdr pair nil))
+	(setq submenu (erlang-man-make-menu segment))
+	(setq menu (cons (list (concat (car (car submenu))
+				       " -- "
+				       (car (car (reverse submenu))))
+			       submenu)
+			 menu)))
+      (nreverse menu))))
+
+
+(defun erlang-man-make-menu (filelist)
+  "Make a leaf menu based on FILELIST."
+  (let ((menu '())
+	item)
+    (while filelist
+      (setq item (erlang-man-make-menu-item (car filelist)))
+      (if item
+	  (setq menu (cons item menu)))
+      (setq filelist (cdr filelist)))
+    (nreverse menu)))
+
+
+(defun erlang-man-make-menu-item (file)
+  "Create a menu item containing the name of the man page."
+  (and (string-match ".+/\\([^/]+\\)\\.\\([124-9]\\|3\\(erl\\)?\\)\\(\\.gz\\)?$" file)
+       (let ((page (substring file (match-beginning 1) (match-end 1))))
+	 (list (capitalize page)
+	       (list 'lambda '()
+		     '(interactive)
+		     (list 'funcall 'erlang-man-display-function
+			   file))))))
+
+
+(defun erlang-man-get-files (dir)
+  "Return files in directory DIR."
+  (directory-files dir t ".+\\.\\([124-9]\\|3\\(erl\\)?\\)\\(\\.gz\\)?\\'"))
+
+
+(defun erlang-man-module (&optional module)
+  "Find manual page for MODULE, defaults to module of function under point.
+This function is aware of imported functions."
+  (interactive
+   (list (let* ((mod (car-safe (erlang-get-function-under-point)))
+		(input (read-string
+			(format "Manual entry for module%s: "
+				(if (or (null mod) (string= mod ""))
+				    ""
+				  (format " (default %s)" mod))))))
+	   (if (string= input "")
+	       mod
+	     input))))
+  (or module (setq module (car (erlang-get-function-under-point))))
+  (if (or (null module) (string= module ""))
+      (error "No Erlang module name given"))
+  (let ((dir-list erlang-man-dirs)
+	(pat (concat "/" (regexp-quote module) "\\.\\([124-9]\\|3\\(erl\\)?\\)\\(\\.gz\\)?$"))
+	(file nil)
+	file-list)
+    (while (and dir-list (null file))
+      (setq file-list (erlang-man-get-files
+		       (if (nth 2 (car dir-list))
+			   (concat erlang-root-dir (nth 1 (car dir-list)))
+			 (nth 1 (car dir-list)))))
+      (while (and file-list (null file))
+	(if (string-match pat (car file-list))
+	    (setq file (car file-list)))
+	(setq file-list (cdr file-list)))
+      (setq dir-list (cdr dir-list)))
+    (if file
+	(funcall erlang-man-display-function file)
+      (error "No manual page for module %s found" module))))
+
+
+;; Warning, the function `erlang-man-function' is a hack!
+;; It links itself into the man code in a non-clean way.  I have
+;; chosen to keep it since it provides a very useful functionality
+;; which is not possible to achieve using a clean approach.
+;;   / AndersL
+
+(defvar erlang-man-function-name nil
+  "Name of function for last `erlang-man-function' call.
+Used for communication between `erlang-man-function' and the
+patch to `Man-notify-when-ready'.")
+
+(defun erlang-man-function (&optional name)
+  "Find manual page for NAME, where NAME is module:function.
+The entry for `function' is displayed.
+
+This function is aware of imported functions."
+  (interactive
+   (list (let* ((mod-func (erlang-get-function-under-point))
+		(mod (car-safe mod-func))
+		(func (nth 1 mod-func))
+		(input (read-string
+			(format
+			 "Manual entry for `module:func' or `module'%s: "
+			 (if (or (null mod) (string= mod ""))
+			     ""
+			   (format " (default %s:%s)" mod func))))))
+	   (if (string= input "")
+	       (if (and mod func)
+		   (concat mod ":" func)
+		 mod)
+	     input))))
+  ;; Emacs 18 doesn't provide `man'...
+  (condition-case nil
+      (require 'man)
+    (error nil))
+  (let ((modname nil)
+	(funcname nil))
+    (cond ((null name)
+	   (let ((mod-func (erlang-get-function-under-point)))
+	     (setq modname (car-safe mod-func))
+	     (setq funcname (nth 1 mod-func))))
+	  ((string-match ":" name)
+	   (setq modname (substring name 0 (match-beginning 0)))
+	   (setq funcname (substring name (match-end 0) nil)))
+	  ((stringp name)
+	   (setq modname name)))
+    (if (or (null modname) (string= modname ""))
+	(error "No Erlang module name given"))
+    (cond ((fboundp 'Man-notify-when-ready)
+	   ;; Emacs 19:  The man command could possibly start an
+	   ;; asynchronous process, i.e. we must hook ourselves into
+	   ;; the system to be activated when the man-process
+	   ;; terminates.
+	   (if (null funcname)
+	       ()
+	     (erlang-man-patch-notify)
+	     (setq erlang-man-function-name funcname))
+	   (condition-case nil
+	       (erlang-man-module modname)
+	     (error (setq erlang-man-function-name nil))))
+	  (t
+	   (erlang-man-module modname)
+	   (if funcname
+	       (erlang-man-find-function
+		(or (get-buffer "*Manual Entry*") ; Emacs 18
+		    (current-buffer))	; XEmacs
+		funcname))))))
+
+
+;; Should the defadvice be at the top level, the package `advice' would
+;; be required.  Now it is only required when this functionality
+;; is used.  (Emacs 19 specific.)
+(defun erlang-man-patch-notify ()
+  "Patch the function `Man-notify-when-ready' to search for function.
+The variable `erlang-man-function-name' is assumed to be bound to
+the function name, or to nil.
+
+The reason for patching a function is that under Emacs 19, the man
+command is executed asynchronously."
+  (condition-case nil
+      (require 'advice)
+    ;; This should never happened since this is only called when
+    ;; running under Emacs 19.
+    (error (error (concat "This command needs the package `advice', "
+			  "please upgrade your Emacs."))))
+  (require 'man)
+  (defadvice Man-notify-when-ready
+    (after erlang-Man-notify-when-ready activate)
+    "Set point at the documentation of the function name in
+`erlang-man-function-name' when the man page is displayed."
+    (if erlang-man-function-name
+	(erlang-man-find-function (ad-get-arg 0) erlang-man-function-name))
+    (setq erlang-man-function-name nil)))
+
+
+(defun erlang-man-find-function (buf func)
+  "Find manual page for function in `erlang-man-function-name' in buffer BUF."
+  (if func
+      (let ((win (get-buffer-window buf)))
+	(if win
+	    (progn
+	      (set-buffer buf)
+	      (goto-char (point-min))
+	      (if (re-search-forward
+		   (concat "^[ \t]+" func " ?(")
+		   (point-max) t)
+		  (progn
+		    (forward-word -1)
+		    (set-window-point win (point)))
+		(message "Could not find function `%s'" func)))))))
+
+
+(defun erlang-man-display (file)
+  "Display FILE as a `man' file.
+This is the default manual page display function.
+The variables `erlang-man-display-function' contains the function
+to be used."
+  ;; Emacs 18 doesn't `provide' man.
+  (condition-case nil
+      (require 'man)
+    (error nil))
+  (if file
+      (let ((process-environment (copy-sequence process-environment)))
+	(if (string-match "\\(.*\\)/man[^/]*/\\([^.]+\\)\\.\\([124-9]\\|3\\(erl\\)?\\)\\(\\.gz\\)?$" file)
+	    (let ((dir (substring file (match-beginning 1) (match-end 1)))
+		  (page (substring file (match-beginning 2) (match-end 2))))
+	      (if (fboundp 'setenv)
+		  (setenv "MANPATH" dir)
+		;; Emacs 18
+		(setq process-environment (cons (concat "MANPATH=" dir)
+						process-environment)))
+	      (cond ((not (and (not erlang-xemacs-p)
+			       (= erlang-emacs-major-version 19)
+			       (< erlang-emacs-minor-version 29)))
+		     (manual-entry page))
+		    (t
+		     ;; Emacs 19.28 and earlier versions of 19:
+		     ;; The manual-entry command unconditionally prompts
+		     ;; the user :-(
+		     (funcall (symbol-function 'Man-getpage-in-background)
+			      page))))
+	  (error "Can't find man page for %s\n" file)))))
+
+
+(defun erlang-man-describe-error ()
+  "Describe why the manual pages weren't found."
+  (interactive)
+  (with-output-to-temp-buffer "*Erlang Man Error*"
+    (princ "Normally, this menu should contain Erlang manual pages.
+
+In order to find the manual pages, the variable `erlang-root-dir'
+should be bound to the name of the directory containing the Erlang
+installation.  The name should not include the final slash.
+
+Practically, you should add a line on the following form to
+your ~/.emacs, or ask your system administrator to add it to
+the site init file:
+    (setq erlang-root-dir \"/the/erlang/root/dir/goes/here\")
+
+For example:
+    (setq erlang-root-dir \"/usr/local/erlang\")
+
+After installing the line, kill and restart Emacs, or restart Erlang
+mode with the command `M-x erlang-mode RET'.")))
+
+;; Skeleton code:
+
+;; This code is based on the package `tempo' which is part of modern
+;; Emacsen.  (GNU Emacs 19.25 (?) and XEmacs 19.14.)
+
+(defun erlang-skel-init ()
+  "Generate the skeleton functions and menu items.
+The variable `erlang-skel' contains the name and descriptions of
+all skeletons.
+
+The skeleton routines are based on the `tempo' package.  Should this
+package not be present, this function does nothing."
+  (interactive)
+  (condition-case nil
+      (require 'tempo)
+    (error t))
+  (if (featurep 'tempo)
+      (let ((skel erlang-skel)
+	    (menu '()))
+	(while skel
+	  (cond ((null (car skel))
+		 (setq menu (cons nil menu)))
+		(t
+		 (funcall (symbol-function 'tempo-define-template)
+			  (concat "erlang-" (nth 1 (car skel)))
+			  ;; The tempo template used contains an `include'
+			  ;; function call only, hence changes to the
+			  ;; variables describing the templates take effect
+			  ;; immdiately.
+			  (list (list 'erlang-skel-include (nth 2 (car skel))))
+			  (nth 1 (car skel))
+			  (car (car skel))
+			  'erlang-tempo-tags)
+		 (setq menu (cons (erlang-skel-make-menu-item
+				   (car skel)) menu))))
+	  (setq skel (cdr skel)))
+	(setq erlang-menu-skel-items
+	      (list nil (list "Skeletons" (nreverse menu))))
+	(setq erlang-menu-items
+	      (erlang-menu-add-above 'erlang-menu-skel-items
+				     'erlang-menu-version-items
+				     erlang-menu-items))
+	(erlang-menu-init))))
+
+(defun erlang-skel-make-menu-item (skel)
+  (let ((func (intern (concat "tempo-template-erlang-" (nth 1 skel)))))
+    (cond ((null (nth 3 skel))
+	   (list (car skel) func))
+	  (t
+	   (list (car skel)
+		 (list 'lambda '()
+		       '(interactive)
+		       (list 'funcall
+			     (list 'quote (nth 3 skel))
+			     (list 'quote func))))))))
+
+;; Functions designed to be added to the skeleton menu.
+;; (Not normally used)
+(defun erlang-skel-insert (func)
+  "Insert skeleton generated by FUNC and goto first tempo mark."
+  (save-excursion (funcall func))
+  (funcall (symbol-function 'tempo-forward-mark)))
+
+(defun erlang-skel-header (func)
+  "Insert the header generated by FUNC at the beginning of the buffer."
+  (goto-char (point-min))
+  (save-excursion (funcall func))
+  (funcall (symbol-function 'tempo-forward-mark)))
+
+
+;; Functions used inside the skeleton descriptions.
+(defun erlang-skel-skip-blank ()
+  (skip-chars-backward " \t")
+  nil)
+
+(defun erlang-skel-include (&rest args)
+  "Include a template inside another template.
+
+Example of use, assuming that `erlang-skel-func' is defined:
+
+ (defvar foo-skeleton '(\"%%% New function:\"
+                        (erlang-skel-include erlang-skel-func)))
+
+Technically, this function returns the `tempo' attribute`(l ...)' which
+can contain other `tempo' attributes.  Please see the function
+`tempo-define-template' for a description of the `(l ...)' attribute."
+  (let ((res '())
+	entry)
+    (while args
+      (setq entry (car args))
+      (while entry
+	(setq res (cons (car entry) res))
+	(setq entry (cdr entry)))
+      (setq args (cdr args)))
+    (cons 'l (nreverse res))))
+
+(defvar erlang-skel-separator-length 70)
+
+(defun erlang-skel-separator (&optional percent)
+  "Return a comment separator."
+  (let ((percent (or percent 3)))
+    (concat (make-string percent ?%) 
+	    (make-string (- erlang-skel-separator-length percent) ?-) 
+	    "\n")))
+
+(defun erlang-skel-double-separator (&optional percent)
+  "Return a comment separator."
+  (let ((percent (or percent 3)))
+    (concat (make-string percent ?%) 
+	    (make-string (- erlang-skel-separator-length percent) ?=) 
+	    "\n")))
+
+(defun erlang-skel-dd-mmm-yyyy ()
+  "Return the current date as a string in \"DD Mon YYYY\" form.
+The first character of DD is space if the value is less than 10."
+  (let ((date (current-time-string)))
+    (format "%2d %s %s"
+	    (erlang-string-to-int (substring date 8 10))
+	    (substring date 4 7)
+	    (substring date -4))))
+
+;; Indentation code:
+
+(defun erlang-indent-command (&optional whole-exp)
+  "Indent current line as Erlang code.
+With argument, indent any additional lines of the same clause
+rigidly along with this one."
+  (interactive "P")
+  (if whole-exp
+      ;; If arg, always indent this line as Erlang
+      ;; and shift remaining lines of clause the same amount.
+      (let ((shift-amt (erlang-indent-line))
+	    beg end)
+	(save-excursion
+	  (if erlang-tab-always-indent
+	      (beginning-of-line))
+	  (setq beg (point))
+	  (erlang-end-of-clause 1)
+	  (setq end (point))
+	  (goto-char beg)
+	  (forward-line 1)
+	  (setq beg (point)))
+	(if (> end beg)
+	    (indent-code-rigidly beg end shift-amt "\n")))
+    (if (and (not erlang-tab-always-indent)
+	     (save-excursion
+	       (skip-chars-backward " \t")
+	       (not (bolp))))
+	(insert-tab)
+      (erlang-indent-line))))
+