summaryrefslogtreecommitdiffstats
path: root/emacs.d/nxhtml/related
diff options
context:
space:
mode:
authorGravatar Tom Willemsen2011-03-07 09:04:49 +0100
committerGravatar Tom Willemsen2011-03-07 09:04:49 +0100
commit94d2fc1815a919734353c942f224db1de4b4fcb8 (patch)
tree4168e816ead132bfa3510e272427837c3895f5e2 /emacs.d/nxhtml/related
parentd0e7674fdb1de12c8de202d4028a5d7ed3669a6e (diff)
downloaddotfiles-94d2fc1815a919734353c942f224db1de4b4fcb8.tar.gz
dotfiles-94d2fc1815a919734353c942f224db1de4b4fcb8.zip
Django, org
* Added nxhtml, mostly for django support. * Changed some org settings.
Diffstat (limited to 'emacs.d/nxhtml/related')
-rw-r--r--emacs.d/nxhtml/related/blank.html6
-rw-r--r--emacs.d/nxhtml/related/csharp-mode.el1977
-rw-r--r--emacs.d/nxhtml/related/django.el203
-rw-r--r--emacs.d/nxhtml/related/env.js695
-rw-r--r--emacs.d/nxhtml/related/flymake-css.el161
-rw-r--r--emacs.d/nxhtml/related/flymake-helpers.el78
-rw-r--r--emacs.d/nxhtml/related/flymake-java-1.el109
-rw-r--r--emacs.d/nxhtml/related/flymake-js.el234
-rw-r--r--emacs.d/nxhtml/related/flymakemsg.el144
-rw-r--r--emacs.d/nxhtml/related/flymu.el157
-rw-r--r--emacs.d/nxhtml/related/iss-mode.el205
-rw-r--r--emacs.d/nxhtml/related/iss-mumamo.el70
-rw-r--r--emacs.d/nxhtml/related/js_temp.js4
-rw-r--r--emacs.d/nxhtml/related/jslint.js523
-rw-r--r--emacs.d/nxhtml/related/moz.el289
-rw-r--r--emacs.d/nxhtml/related/mozadd.el369
-rw-r--r--emacs.d/nxhtml/related/php-imenu.el174
-rw-r--r--emacs.d/nxhtml/related/php-mode.el1231
-rw-r--r--emacs.d/nxhtml/related/readme.txt7
-rw-r--r--emacs.d/nxhtml/related/rhino.js14
-rw-r--r--emacs.d/nxhtml/related/smarty-mode.el2753
-rw-r--r--emacs.d/nxhtml/related/tt-mode.el124
-rw-r--r--emacs.d/nxhtml/related/visual-basic-mode.el1263
-rw-r--r--emacs.d/nxhtml/related/wikipedia-mode.el2296
24 files changed, 13086 insertions, 0 deletions
diff --git a/emacs.d/nxhtml/related/blank.html b/emacs.d/nxhtml/related/blank.html
new file mode 100644
index 0000000..f8b6c17
--- /dev/null
+++ b/emacs.d/nxhtml/related/blank.html
@@ -0,0 +1,6 @@
+<html>
+ <head>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/emacs.d/nxhtml/related/csharp-mode.el b/emacs.d/nxhtml/related/csharp-mode.el
new file mode 100644
index 0000000..9cd7914
--- /dev/null
+++ b/emacs.d/nxhtml/related/csharp-mode.el
@@ -0,0 +1,1977 @@
+;;; csharp-mode.el --- C# mode derived mode
+
+;; Author: Dylan R. E. Moonfire
+;; Maintainer: Dylan R. E. Moonfire <contact@mfgames.com>
+;; Created: Feburary 2005
+;; Modified: February 2010
+;; Version: 0.7.4 - Dino Chiesa <dpchiesa@hotmail.com>
+;; Keywords: c# languages oop mode
+
+;; 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 2 of the License, 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, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; This is a separate mode to implement the C# constructs and
+;; font-locking. It is based on the java-mode example from cc-mode.
+;;
+;; csharp-mode requires CC Mode 5.30 or later. It works with
+;; cc-mode 5.31.3, which is current at this time.
+;;
+;; Features:
+;;
+;; - font-lock and indent of C# syntax including:
+;; all c# keywords and major syntax
+;; attributes that decorate methods, classes, fields, properties
+;; enum types
+;; #if/#endif #region/#endregion
+;; instance initializers
+;; anonymous functions and methods
+;; verbatim literal strings (those that begin with @)
+;; generics
+;;
+;; - automagic code-doc generation when you type three slashes.
+;;
+;; - intelligent inserttion of matched pairs of curly braces.
+;;
+;; - sets the compiler regex for next-error, for csc.exe output.
+;;
+;;
+
+
+;;; To use:
+;;
+;; put this in your .emacs:
+;;
+;; (autoload 'csharp-mode "csharp-mode" "Major mode for editing C# code." t)
+;;
+;; or:
+;;
+;; (require 'csharp-mode)
+;;
+;;
+;; AND:
+;;
+;; (setq auto-mode-alist
+;; (append '(("\\.cs$" . csharp-mode)) auto-mode-alist))
+;; (defun my-csharp-mode-fn ()
+;; "function that runs when csharp-mode is initialized for a buffer."
+;; ...insert your code here...
+;; ...most commonly, your custom key bindings ...
+;; )
+;; (add-hook 'csharp-mode-hook 'my-csharp-mode-fn t)
+;;
+;;
+
+
+;;; Bugs:
+;;
+;; Namespaces in the using statements are not fontified. Should do in
+;; c-basic-matchers-before or c-basic-matchers-after.
+;;
+;; Method names with a preceding attribute are not fontified.
+;;
+;; Field/Prop names inside object initializers are fontified only
+;; if the null constructor is used, with no parens.
+;;
+;; This code doesn't seem to work when you compile it, then
+;; load/require in the emacs file. You will get an error (error
+;; "`c-lang-defconst' must be used in a file") which happens because
+;; cc-mode doesn't think it is in a buffer while loading directly
+;; from the init. However, if you call it based on a file extension,
+;; it works properly. Interestingly enough, this doesn't happen if
+;; you don't byte-compile cc-mode.
+;;
+;;
+;;
+;; Todo:
+;;
+;; Get csharp-mode.el accepted as part of the emacs standard distribution.
+;; Must contact monnier at iro.umontreal.ca to make this happen.
+;;
+;;
+;;
+;; Acknowledgements:
+;;
+;; Thanks to Alan Mackenzie and Stefan Monnier for answering questions
+;; and making suggestions.
+;;
+;;
+
+;;; Versions:
+;;
+;; 0.1.0 - Initial release.
+;; 0.2.0 - Fixed the identification on the "enum" keyword.
+;; - Fixed the font-lock on the "base" keyword
+;; 0.3.0 - Added a regex to fontify attributes. It isn't the
+;; the best method, but it handles single-like attributes
+;; well.
+;; - Got "super" not to fontify as a keyword.
+;; - Got extending classes and interfaces to fontify as something.
+;; 0.4.0 - Removed the attribute matching because it broke more than
+;; it fixed.
+;; - Corrected a bug with namespace not being properly identified
+;; and treating the class level as an inner object, which screwed
+;; up formatting.
+;; - Added "partial" to the keywords.
+;; 0.5.0 - Found bugs with compiled cc-mode and loading from init files.
+;; - Updated the eval-when-compile to code to let the mode be
+;; compiled.
+;; 0.6.0 - Added the c-filter-ops patch for 5.31.1 which made that
+;; function in cc-langs.el unavailable.
+;; - Added a csharp-lineup-region for indention #region and
+;; #endregion block differently.
+;; 0.7.0 - Added autoload so update-directory-autoloads works
+;; (Thank you, Nikolaj Schumacher)
+;; - Fontified the entire #region and #endregion lines.
+;; - Initial work to get get, set, add, remove font-locked.
+;; 0.7.1 - Added option to indent #if/endif with code
+;; - Fixed c-opt-cpp-prefix defn (it must not include the BOL
+;; char (^).
+;; - proper fontification and indent of classes that inherit
+;; (previously the colon was confusing the parser)
+;; - reclassified namespace as a block beginner
+;; - removed $ as a legal symbol char - not legal in C#.
+;; - added struct to c-class-decl-kwds so indent is correct
+;; within a struct.
+;; 0.7.2 - Added automatic codedoc insertion.
+;; 0.7.3 - Instance initializers (new Type { ... } ) and
+;; (new Type() { ...} ) are now indented properly.
+;; - proper fontification and indent of enums as brace-list-*,
+;; including special treatment for enums that explicitly
+;; inherit from an int type. Previously the colon was
+;; confusing the parser.
+;; - proper fontification of verbatim literal strings,
+;; including those that end in slash. This edge case was not
+;; handled at all before; it is now handled correctly.
+;; - code cleanup and organization; removed the linefeed.
+;; - intelligent curly-brace insertion
+;; 0.7.4 - added a C# style
+;; - using is now a keyword and gets fontified
+;; - fixed a bug that had crept into the codedoc insertion
+;;
+
+
+(require 'cc-mode)
+
+(message (concat "Loading " load-file-name))
+
+
+;; ==================================================================
+;; c# upfront stuff
+;; ==================================================================
+
+;; This is a copy of the function in cc-mode which is used to handle
+;; the eval-when-compile which is needed during other times.
+(defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
+ ;; See cc-langs.el, a direct copy.
+ (unless (listp (car-safe ops))
+ (setq ops (list ops)))
+ (cond ((eq opgroup-filter t)
+ (setq opgroup-filter (lambda (opgroup) t)))
+ ((not (functionp opgroup-filter))
+ (setq opgroup-filter `(lambda (opgroup)
+ (memq opgroup ',opgroup-filter)))))
+ (cond ((eq op-filter t)
+ (setq op-filter (lambda (op) t)))
+ ((stringp op-filter)
+ (setq op-filter `(lambda (op)
+ (string-match ,op-filter op)))))
+ (unless xlate
+ (setq xlate 'identity))
+ (c-with-syntax-table (c-lang-const c-mode-syntax-table)
+ (delete-duplicates
+ (mapcan (lambda (opgroup)
+ (when (if (symbolp (car opgroup))
+ (when (funcall opgroup-filter (car opgroup))
+ (setq opgroup (cdr opgroup))
+ t)
+ t)
+ (mapcan (lambda (op)
+ (when (funcall op-filter op)
+ (let ((res (funcall xlate op)))
+ (if (listp res) res (list res)))))
+ opgroup)))
+ ops)
+ :test 'equal)))
+
+
+
+;; These are only required at compile time to get the sources for the
+;; language constants. (The cc-fonts require and the font-lock
+;; related constants could additionally be put inside an
+;; (eval-after-load "font-lock" ...) but then some trickery is
+;; necessary to get them compiled.)
+(eval-when-compile
+ (let ((load-path
+ (if (and (boundp 'byte-compile-dest-file)
+ (stringp byte-compile-dest-file))
+ (cons (file-name-directory byte-compile-dest-file) load-path)
+ load-path)))
+ (load "cc-mode" nil t)
+ (load "cc-fonts" nil t)
+ (load "cc-langs" nil t)))
+
+(eval-and-compile
+ ;; Make our mode known to the language constant system. Use Java
+ ;; mode as the fallback for the constants we don't change here.
+ ;; This needs to be done also at compile time since the language
+ ;; constants are evaluated then.
+ (c-add-language 'csharp-mode 'java-mode))
+
+;; ==================================================================
+;; end of c# upfront stuff
+;; ==================================================================
+
+
+
+
+
+;; ==================================================================
+;; csharp-mode utility and feature defuns
+;; ==================================================================
+
+;; Indention: csharp-mode follows normal indention rules except for
+;; when indenting the #region and #endregion blocks. This function
+;; defines a custom indention to indent the #region blocks properly
+;;
+
+(defun csharp-lineup-region (langelem)
+ "Indent all #region and #endregion blocks inline with code while
+retaining normal column-zero indention for #if and the other
+processing blocks.
+
+To use this indenting just put the following in your emacs file:
+ (c-set-offset 'cpp-macro 'csharp-lineup-region)
+
+An alternative is to use `csharp-lineup-if-and-region'.
+"
+
+ (save-excursion
+ (back-to-indentation)
+ (if (re-search-forward "#\\(end\\)?region" (c-point 'eol) [0]) 0 [0])))
+
+
+
+(defun csharp-lineup-if-and-region (langelem)
+
+"Indent all #region/endregion blocks and #if/endif blocks inline
+with code while retaining normal column-zero indention for any
+other processing blocks.
+
+To use this indenting just put the following in your emacs file:
+ (c-set-offset 'cpp-macro 'csharp-lineup-if-and-region)
+
+Another option is to use `csharp-lineup-region'.
+
+"
+ (save-excursion
+ (back-to-indentation)
+ (if (re-search-forward "#\\(\\(end\\)?\\(if\\|region\\)\\|else\\)" (c-point 'eol) [0]) 0 [0])))
+
+
+
+
+
+(defun csharp-insert-open-brace ()
+ "Intelligently insert a pair of curly braces. This fn is most
+often bound to the open-curly brace, with
+
+ (local-set-key (kbd \"{\") 'csharp-insert-open-brace)
+
+The default binding for an open curly brace in cc-modes is often
+`c-electric-brace' or `skeleton-pair-insert-maybe'. The former
+can be configured to insert newlines around braces in various
+syntactic positions. The latter inserts a pair of braces and
+then does not insert a newline, and does not indent.
+
+This fn provides another option, with some additional
+intelligence for csharp-mode. When you type an open curly, the
+appropriate pair of braces appears, with spacing and indent set
+in a context-sensitive manner.
+
+Within a string literal, you just get a pair of braces, and point
+is set between them. Following an equals sign, you get a pair of
+braces, with a semincolon appended. Otherwise, you
+get the open brace on a new line, with the closing brace on the
+line following.
+
+There may be another way to get this to happen appropriately just within emacs,
+but I could not figure out how to do it. So I wrote this alternative.
+"
+ (interactive)
+ (let
+ (tpoint
+ (in-string (string= (csharp-in-literal) "string"))
+ (preceding3
+ (save-excursion
+ (and
+ (skip-chars-backward " ")
+ (> (- (point) 2) (point-min))
+ (buffer-substring-no-properties (point) (- (point) 3)))))
+ (one-word-back
+ (save-excursion
+ (backward-word 2)
+ (thing-at-point 'word))))
+
+ (cond
+
+ ;; Case 1: inside a string literal?
+ ;; --------------------------------------------
+ ;; If so, then just insert a pair of braces and put the point
+ ;; between them. The most common case is a format string for
+ ;; String.Format() or Console.WriteLine().
+ (in-string
+ (self-insert-command 1)
+ (insert "}")
+ (backward-char))
+
+ ;; Case 2: the open brace starts an array initializer.
+ ;; --------------------------------------------
+ ;; When the last non-space was an equals sign or square brackets,
+ ;; then it's an initializer.
+ ((save-excursion
+ (backward-sexp)
+ (looking-at "\\(\\w+\\b *=\\|[[]]+\\)"))
+ (self-insert-command 1)
+ (insert " };")
+ (backward-char 3))
+
+ ;; Case 3: the open brace starts an instance initializer
+ ;; --------------------------------------------
+ ;; If one-word-back was "new", then it's an object initializer.
+ ((string= one-word-back "new")
+ (save-excursion
+ (message "object initializer")
+ (setq tpoint (point)) ;; prepare to indent-region later
+ (newline)
+ (self-insert-command 1)
+ (newline-and-indent)
+ (newline)
+ (insert "};")
+ (c-indent-region tpoint (point))
+ (previous-line)
+ (indent-according-to-mode)
+ (end-of-line)
+ (setq tpoint (point)))
+ (goto-char tpoint))
+
+ ;; Case 4: a lambda initialier.
+ ;; --------------------------------------------
+ ;; If the open curly follows =>, then it's a lambda initializer.
+ ((string= (substring preceding3 -2) "=>")
+ (message "lambda init")
+ (self-insert-command 1)
+ (insert " }")
+ (backward-char 2))
+
+ ;; else, it's a new scope. (if, while, class, etc)
+ (t
+ (save-excursion
+ (message "new scope")
+ (set-mark (point)) ;; prepare to indent-region later
+ ;; check if the prior sexp is on the same line
+ (if (save-excursion
+ (let ((curline (line-number-at-pos))
+ (aftline (progn
+ (backward-sexp)
+ (line-number-at-pos))))
+ (= curline aftline)))
+ (newline-and-indent))
+ (self-insert-command 1)
+ (c-indent-line-or-region)
+ (end-of-line)
+ (newline)
+ (insert "}")
+ ;;(c-indent-command) ;; not sure of the difference here
+ (c-indent-line-or-region)
+ (previous-line)
+ (end-of-line)
+ (newline-and-indent)
+ ;; point ends up on an empty line, within the braces, properly indented
+ (setq tpoint (point)))
+
+ (goto-char tpoint)))))
+
+
+
+
+;; ==================================================================
+;; end of csharp-mode utility and feature defuns
+;; ==================================================================
+
+
+
+
+
+
+;; ==================================================================
+;; c# values for "language constants" defined in cc-langs.el
+;; ==================================================================
+
+
+;; Java uses a series of regexes to change the font-lock for class
+;; references. The problem comes in because Java uses Pascal (leading
+;; space in names, SomeClass) for class and package names, but
+;; Camel-casing (initial lowercase, upper case in words,
+;; i.e. someVariable) for variables. The notation suggested by EMCA for C# is
+;; to use Pascal notation for everything, except inner variables. So,
+;; the Java regex and formatting produces very wrong results in C#.
+;;(error (byte-compile-dest-file))
+;;(error (c-get-current-file))
+(c-lang-defconst c-opt-after-id-concat-key
+ csharp (if (c-lang-const c-opt-identifier-concat-key)
+ (c-lang-const c-symbol-start)))
+
+(c-lang-defconst c-basic-matchers-before
+ csharp `(
+ ;;;; Font-lock the attributes by searching for the
+ ;;;; appropriate regex and marking it as TODO.
+ ;;,`(,(concat "\\(" csharp-attribute-regex "\\)")
+ ;; 0 font-lock-function-name-face)
+
+ ;; Put a warning face on the opener of unclosed strings that
+ ;; can't span lines. Later font
+ ;; lock packages have a `font-lock-syntactic-face-function' for
+ ;; this, but it doesn't give the control we want since any
+ ;; fontification done inside the function will be
+ ;; unconditionally overridden.
+ ,(c-make-font-lock-search-function
+ ;; Match a char before the string starter to make
+ ;; `c-skip-comments-and-strings' work correctly.
+ (concat ".\\(" c-string-limit-regexp "\\)")
+ '((c-font-lock-invalid-string)))
+
+ ;; Fontify keyword constants.
+ ,@(when (c-lang-const c-constant-kwds)
+ (let ((re (c-make-keywords-re nil
+ (c-lang-const c-constant-kwds))))
+ `((eval . (list ,(concat "\\<\\(" re "\\)\\>")
+ 1 c-constant-face-name)))))
+
+ ;; Fontify all keywords except the primitive types.
+ ,`(,(concat "\\<" (c-lang-const c-regular-keywords-regexp))
+ 1 font-lock-keyword-face)
+
+ ;; Fontify leading identifiers in fully qualified names like
+ ;; "Foo.Bar".
+ ,@(when (c-lang-const c-opt-identifier-concat-key)
+ `((,(byte-compile
+ `(lambda (limit)
+ (while (re-search-forward
+ ,(concat "\\(\\<" ; 1
+ "\\(" (c-lang-const c-symbol-key)
+ "\\)" ; 2
+ "[ \t\n\r\f\v]*"
+ (c-lang-const
+ c-opt-identifier-concat-key)
+ "[ \t\n\r\f\v]*"
+ "\\)"
+ "\\("
+ (c-lang-const
+ c-opt-after-id-concat-key)
+ "\\)")
+ limit t)
+ (unless (progn
+ (goto-char (match-beginning 0))
+ (c-skip-comments-and-strings limit))
+ (or (get-text-property (match-beginning 2) 'face)
+ (c-put-font-lock-face (match-beginning 2)
+ (match-end 2)
+ c-reference-face-name))
+ (goto-char (match-end 1)))))))))
+ ))
+
+
+
+;; C# does not allow a leading qualifier operator. It also doesn't
+;; allow the ".*" construct of Java. So, we redo this regex without
+;; the "\\|\\*" regex.
+(c-lang-defconst c-identifier-key
+ csharp (concat "\\(" (c-lang-const c-symbol-key) "\\)" ; 1
+ (concat "\\("
+ "[ \t\n\r\f\v]*"
+ (c-lang-const c-opt-identifier-concat-key)
+ "[ \t\n\r\f\v]*"
+ (concat "\\("
+ "\\(" (c-lang-const c-symbol-key) "\\)"
+ "\\)")
+ "\\)*")))
+
+;; C# has a few rules that are slightly different than Java for
+;; operators. This also removed the Java's "super" and replaces it
+;; with the C#'s "base".
+(c-lang-defconst c-operators
+ csharp `((prefix "base")))
+
+
+;; C# uses CPP-like prefixes to mark #define, #region/endregion,
+;; #if/else/endif, and #pragma. This regexp matches the prefix,
+;; not including the beginning-of-line (BOL), and not including
+;; the term after the prefix (define, pragma, etc). This regexp says
+;; whitespace, followed by the prefix, followed by maybe more whitespace.
+
+(c-lang-defconst c-opt-cpp-prefix
+ csharp "\\s *#\\s *")
+
+
+;; there are no message directives in C#
+(c-lang-defconst c-cpp-message-directives
+ csharp nil)
+
+(c-lang-defconst c-cpp-expr-directives
+ csharp '("if"))
+
+(c-lang-defconst c-opt-cpp-macro-define
+ csharp "define")
+
+;; $ is not a legal char in an identifier in C#. So we need to
+;; create a csharp-specific definition of this constant.
+(c-lang-defconst c-symbol-chars
+ csharp (concat c-alnum "_"))
+
+
+(c-lang-defconst c-colon-type-list-kwds
+ csharp '("class"))
+
+(c-lang-defconst c-block-prefix-disallowed-chars
+
+ ;; Allow ':' for inherit list starters.
+ csharp (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+ '(?: ?,)))
+
+
+(c-lang-defconst c-assignment-operators
+ csharp '("=" "*=" "/=" "%=" "+=" "-=" ">>=" "<<=" "&=" "^=" "|="))
+
+(c-lang-defconst c-primitive-type-kwds
+ ;; ECMA-344, S8
+ csharp '("object" "string" "sbyte" "short" "int" "long" "byte"
+ "ushort" "uint" "ulong" "float" "double" "bool" "char"
+ "decimal" "void"))
+
+;; The keywords that define that the following is a type, such as a
+;; class definition.
+(c-lang-defconst c-type-prefix-kwds
+ ;; ECMA-344, S?
+ csharp '("class" "interface" "struct")) ;; no enum here.
+ ;; we want enum to be a brace list.
+
+
+;; Type modifier keywords. They appear anywhere in types, but modify
+;; instead of create one.
+(c-lang-defconst c-type-modifier-kwds
+ ;; EMCA-344, S?
+ csharp '("readonly" "const"))
+
+
+;; Tue, 20 Apr 2010 16:02
+;; need to vverify that this works for lambdas...
+(c-lang-defconst c-special-brace-lists
+ csharp '((?{ . ?}) ))
+
+
+
+;; dinoch
+;; Thu, 22 Apr 2010 18:54
+;;
+;; No idea why this isn't getting set properly in the first place.
+;; In cc-langs.el, it is set to the union of a bunch of things, none
+;; of which include "new", or "enum".
+;;
+;; But somehow both of those show up in the resulting derived regexp.
+;; This breaks indentation of instance initializers, such as
+;;
+;; var x = new Foo { ... };
+;;
+;; Based on my inspection, the existing c-lang-defconst should work!
+;; I don't know how to fix this c-lang-defconst, so I am re-setting this
+;; variable here, to provide the regex explicitly.
+;;
+(c-lang-defconst c-decl-block-key
+
+ csharp '"\\(namespace\\)\\([^[:alnum:]_]\\|$\\)\\|\\(class\\|interface\\|struct\\)\\([^[:alnum:]_]\\|$\\)"
+ )
+
+
+
+;; Thu, 22 Apr 2010 14:29
+;; I want this to handle var x = new Foo[] { ... };
+;; not sure if necessary.
+(c-lang-defconst c-inexpr-brace-list-kwds
+ csharp '("new"))
+
+
+;; ;;(c-lang-defconst c-inexpr-class-kwds
+;; ;; csharp '("new"))
+
+
+
+(c-lang-defconst c-class-decl-kwds
+ ;; EMCA-344, S?
+ csharp '("class" "interface" "struct" )) ;; no "enum"!!
+
+
+;; The various modifiers used for class and method descriptions.
+(c-lang-defconst c-modifier-kwds
+ csharp '("public" "partial" "private" "const" "abstract"
+ "protected" "ref" "out" "static" "virtual"
+ "override" "params" "internal"))
+
+
+;; Thu, 22 Apr 2010 23:02
+;; Based on inspection of the cc-mode code, the c-protection-kwds
+;; c-lang-const is used only for objective-c. So the value is
+;; irrelevant for csharp.
+(c-lang-defconst c-protection-kwds
+ csharp nil
+ ;; csharp '("private" "protected" "public" "internal")
+)
+
+
+;; Define the keywords that can have something following after them.
+(c-lang-defconst c-type-list-kwds
+ csharp '("struct" "class" "interface" "is" "as"
+ "delegate" "event" "set" "get" "add" "remove"))
+
+
+;; This allows the classes after the : in the class declartion to be
+;; fontified.
+(c-lang-defconst c-typeless-decl-kwds
+ csharp '(":"))
+
+;; Sets up the enum to handle the list properly, and also the new
+;; keyword to handle object initializers. This requires a modified
+;; c-basic-matchers-after (see above) in order to correctly fontify C#
+;; 3.0 object initializers.
+(c-lang-defconst c-brace-list-decl-kwds
+ csharp '("enum" "new"))
+
+
+;; Statement keywords followed directly by a substatement.
+;; catch is not one of them.
+(c-lang-defconst c-block-stmt-1-kwds
+ csharp '("do" "try" "finally"))
+
+
+;; Statement keywords followed by a paren sexp and then by a substatement.
+(c-lang-defconst c-block-stmt-2-kwds
+ csharp '("for" "if" "switch" "while" "catch" "foreach" "using"
+ "checked" "unchecked" "lock"))
+
+
+;; Statements that break out of braces
+(c-lang-defconst c-simple-stmt-kwds
+ csharp '("return" "continue" "break" "throw" "goto" ))
+
+;; Statements that allow a label
+;; TODO?
+(c-lang-defconst c-before-label-kwds
+ csharp nil)
+
+;; Constant keywords
+(c-lang-defconst c-constant-kwds
+ csharp '("true" "false" "null"))
+
+;; Keywords that start "primary expressions."
+(c-lang-defconst c-primary-expr-kwds
+ csharp '("this" "base"))
+
+;; Treat namespace as an outer block so class indenting
+;; works properly.
+(c-lang-defconst c-other-block-decl-kwds
+ csharp '("namespace"))
+
+(c-lang-defconst c-other-kwds
+ csharp '("in" "sizeof" "typeof" "is" "as" "yield"
+ "where" "select" "from"))
+
+(c-lang-defconst c-overloadable-operators
+ ;; EMCA-344, S14.2.1
+ csharp '("+" "-" "*" "/" "%" "&" "|" "^"
+ "<<" ">>" "==" "!=" ">" "<" ">=" "<="))
+
+
+;; This c-cpp-matchers stuff is used for fontification.
+;; see cc-font.el
+;;
+
+;; There's no preprocessor in C#, but there are still compiler
+;; directives to fontify: "#pragma", #region/endregion, #define, #undef,
+;; #if/else/endif. (The definitions for the extra keywords above are
+;; enough to incorporate them into the fontification regexps for types
+;; and keywords, so no additional font-lock patterns are required for
+;; keywords.)
+
+(c-lang-defconst c-cpp-matchers
+ csharp (cons
+ ;; Use the eval form for `font-lock-keywords' to be able to use
+ ;; the `c-preprocessor-face-name' variable that maps to a
+ ;; suitable face depending on the (X)Emacs version.
+ '(eval . (list "^\\s *\\(#pragma\\|undef\\|define\\)\\>\\(.*\\)"
+ (list 1 c-preprocessor-face-name)
+ '(2 font-lock-string-face)))
+ ;; There are some other things in `c-cpp-matchers' besides the
+ ;; preprocessor support, so include it.
+ (c-lang-const c-cpp-matchers)))
+
+(defcustom csharp-font-lock-extra-types nil
+ "*List of extra types (aside from the type keywords) to recognize in C# mode.
+Each list item should be a regexp matching a single identifier."
+ :type 'list :group 'csharp)
+
+(defconst csharp-font-lock-keywords-1 (c-lang-const c-matchers-1 csharp)
+ "Minimal highlighting for C# mode.")
+
+(defconst csharp-font-lock-keywords-2 (c-lang-const c-matchers-2 csharp)
+ "Fast normal highlighting for C# mode.")
+
+(defconst csharp-font-lock-keywords-3 (c-lang-const c-matchers-3 csharp)
+ "Accurate normal highlighting for C# mode.")
+
+(defvar csharp-font-lock-keywords csharp-font-lock-keywords-3
+ "Default expressions to highlight in C# mode.")
+
+(defvar csharp-mode-syntax-table nil
+ "Syntax table used in csharp-mode buffers.")
+(or csharp-mode-syntax-table
+ (setq csharp-mode-syntax-table
+ (funcall (c-lang-const c-make-mode-syntax-table csharp))))
+
+(defvar csharp-mode-abbrev-table nil
+ "Abbreviation table used in csharp-mode buffers.")
+(c-define-abbrev-table 'csharp-mode-abbrev-table
+ ;; Keywords that if they occur first on a line might alter the
+ ;; syntactic context, and which therefore should trig reindentation
+ ;; when they are completed.
+ '(("else" "else" c-electric-continued-statement 0)
+ ("while" "while" c-electric-continued-statement 0)
+ ("catch" "catch" c-electric-continued-statement 0)
+ ("finally" "finally" c-electric-continued-statement 0)))
+
+(defvar csharp-mode-map (let ((map (c-make-inherited-keymap)))
+ ;; Add bindings which are only useful for C#
+ map)
+ "Keymap used in csharp-mode buffers.")
+
+
+;; TODO
+;; Defines our constant for finding attributes.
+;;(defconst csharp-attribute-regex "\\[\\([XmlType]+\\)(")
+;;(defconst csharp-attribute-regex "\\[\\(.\\)")
+;; This doesn't work because the string regex happens before this point
+;; and getting the font-locking to work before and after is fairly difficult
+;;(defconst csharp-attribute-regex
+;; (concat
+;; "\\[[a-zA-Z][ \ta-zA-Z0-9.]+"
+;; "\\((.*\\)?"
+;;))
+
+
+;; ==================================================================
+;; end of c# values for "language constants" defined in cc-langs.el
+;; ==================================================================
+
+
+
+
+;; ==================================================================
+;; C# code-doc insertion magic
+;; ==================================================================
+;;
+;; In Visual Studio, if you type three slashes, it immediately expands into
+;; an inline code-documentation fragment. The following method does the
+;; same thing.
+;;
+;; This is the kind of thing that could be handled by YASnippet or
+;; another similarly flexible snippet framework. But I don't want to
+;; introduce a dependency on yasnippet to csharp-mode. So the capability
+;; must live within csharp-mode itself.
+
+(defun csharp-maybe-insert-codedoc (arg)
+
+ "Insert an xml code documentation template as appropriate, when
+typing slashes. This fn gets bound to / (the slash key), in
+csharp-mode. If the slash being inserted is not the third
+consecutive slash, the slash is inserted as normal. If it is the
+third consecutive slash, then a xml code documentation template
+may be inserted in some cases. For example,
+
+ a <summary> template is inserted if the prior line is empty,
+ or contains only an open curly brace;
+ a <remarks> template is inserted if the prior word
+ closes the <summary> element;
+ a <returns> template is inserted if the prior word
+ closes the <remarks> element;
+ an <example> template is inserted if the prior word closes
+ the <returns> element;
+ a <para> template is inserted if the prior word closes
+ a <para> element.
+
+In all other cases the slash is inserted as normal.
+
+If you want the default cc-mode behavior, which implies no automatic
+insertion of xml code documentation templates, then use this in
+your `csharp-mode-hook' function:
+
+ (local-set-key (kbd \"/\") 'c-electric-slash)
+
+ "
+ (interactive "*p")
+ ;;(message "csharp-maybe-insert-codedoc")
+ (let (
+ (cur-point (point))
+ (char last-command-char)
+ (cb0 (char-before (- (point) 0)))
+ (cb1 (char-before (- (point) 1)))
+ is-first-non-whitespace
+ did-auto-insert
+ )
+
+ ;; check if two prior chars were slash
+ (if (and
+ (= char ?/)
+ cb0 (= ?/ cb0)
+ cb1 (= ?/ cb1)
+ )
+
+ (progn
+ ;;(message "yes - this is the third consecutive slash")
+ (setq is-first-non-whitespace
+ (save-excursion
+ (back-to-indentation)
+ (= cur-point (+ (point) 2))))
+
+ (if is-first-non-whitespace
+ ;; This is a 3-slash sequence. It is the first non-whitespace text
+ ;; on the line. Now we need to examine the surrounding context
+ ;; in order to determine which xml cod doc template to insert.
+ (let (word-back char0 char1
+ word-fore char-0 char-1
+ text-to-insert ;; text to insert in lieu of slash
+ fn-to-call ;; func to call after inserting text
+ (preceding-line-is-empty (or
+ (= (line-number-at-pos) 1)
+ (save-excursion
+ (previous-line)
+ (beginning-of-line)
+ (looking-at "[ \t]*$\\|[ \t]*{[ \t]*$"))))
+ (flavor 0) ;; used only for diagnostic purposes
+ )
+
+ ;;(message "starting a 3-slash comment")
+ ;; get the prior word, and the 2 chars preceding it.
+ (backward-word)
+
+ (setq word-back (thing-at-point 'word)
+ char0 (char-before (- (point) 0))
+ char1 (char-before (- (point) 1)))
+
+ ;; restore prior position
+ (goto-char cur-point)
+
+ ;; get the following word, and the 2 chars preceding it.
+ (forward-word)
+ (backward-word)
+ (setq word-fore (thing-at-point 'word)
+ char-0 (char-before (- (point) 0))
+ char-1 (char-before (- (point) 1)))
+
+ ;; restore prior position again
+ (goto-char cur-point)
+
+ (cond
+ ;; The preceding line is empty, or all whitespace, or
+ ;; contains only an open-curly. In this case, insert a
+ ;; summary element pair.
+ (preceding-line-is-empty
+ (setq text-to-insert "/ <summary>\n/// \n/// </summary>"
+ flavor 1) )
+
+ ;; The preceding word closed a summary element. In this case,
+ ;; if the forward word does not open a remarks element, then
+ ;; insert a remarks element.
+ ((and (string-equal word-back "summary") (eq char0 ?/) (eq char1 ?<))
+ (if (not (and (string-equal word-fore "remarks") (eq char-0 ?<)))
+ (setq text-to-insert "/ <remarks>\n/// <para>\n/// \n/// </para>\n/// </remarks>"
+ flavor 2)))
+
+ ;; The preceding word closed the remarks section. In this case,
+ ;; insert an example element.
+ ((and (string-equal word-back "remarks") (eq char0 ?/) (eq char1 ?<))
+ (setq text-to-insert "/ <example>\n/// \n/// </example>"
+ flavor 3))
+
+ ;; The preceding word closed the example section. In this
+ ;; case, insert an returns element. This isn't always
+ ;; correct, because sometimes the xml code doc is attached to
+ ;; a class or a property, neither of which has a return
+ ;; value. A more intelligent implementation would inspect the
+ ;; syntax state and only inject a returns element if
+ ;; appropriate.
+ ((and (string-equal word-back "example") (eq char0 ?/) (eq char1 ?<))
+ (setq text-to-insert "/ <returns></returns>"
+ fn-to-call (lambda ()
+ (backward-word)
+ (backward-char)
+ (backward-char)
+ (c-indent-line-or-region)
+ )
+ flavor 4))
+
+ ;; The preceding word opened the remarks section, or it
+ ;; closed a para section. In this case, insert a para
+ ;; element, using appropriate indentation with respect to the
+ ;; prior tag.
+ ((or
+ (and (string-equal word-back "remarks") (eq char0 ?<) (or (eq char1 32) (eq char1 9)))
+ (and (string-equal word-back "para") (eq char0 ?/) (eq char1 ?<)))
+
+ (let (prior-point spacer)
+ (save-excursion
+ (backward-word)
+ (backward-char)
+ (backward-char)
+ (setq prior-point (point))
+ (skip-chars-backward "\t ")
+ (setq spacer (buffer-substring (point) prior-point))
+ ;;(message (format "pt(%d) prior(%d) spacer(%s)" (point) prior-point spacer))
+ )
+
+ (if (string-equal word-back "remarks")
+ (setq spacer (concat spacer " ")))
+
+ (setq text-to-insert (format "/%s<para>\n///%s \n///%s</para>"
+ spacer spacer spacer)
+ flavor 6)))
+
+ ;; The preceding word opened a para element. In this case, if
+ ;; the forward word does not close the para element, then
+ ;; close the para element.
+ ;; --
+ ;; This is a nice idea but flawed. Suppose I have a para element with some
+ ;; text in it. If I position the cursor at the first line, then type 3 slashes,
+ ;; I get a close-element, and that would be inappropriate. Not sure I can
+ ;; easily solve that problem, so the best thing might be to simply punt, and
+ ;; require people to close their own elements.
+ ;;
+ ;; ( (and (string-equal word-back "para") (eq char0 60) (or (eq char1 32) (eq char1 9)))
+ ;; (if (not (and (string-equal word-fore "para") (eq char-0 47) (eq char-1 60) ))
+ ;; (setq text-to-insert "/ \n/// </para>\n///"
+ ;; fn-to-call (lambda ()
+ ;; (previous-line)
+ ;; (end-of-line)
+ ;; )
+ ;; flavor 7) )
+ ;; )
+
+ ;; the default case - do nothing
+ (t nil))
+
+ (if text-to-insert
+ (progn
+ ;;(message (format "inserting special text (f(%d))" flavor))
+
+ ;; set the flag, that we actually inserted text
+ (setq did-auto-insert t)
+
+ ;; save point of beginning of insertion
+ (setq cur-point (point))
+
+ ;; actually insert the text
+ (insert text-to-insert)
+
+ ;; indent the inserted string, and re-position point, either through
+ ;; the case-specific fn, or via the default progn.
+ (if fn-to-call
+ (funcall fn-to-call)
+
+ (let ((newline-count 0) (pos 0) ix)
+
+ ;; count the number of newlines in the inserted string
+ (while (string-match "\n" text-to-insert pos)
+ (setq pos (match-end 0)
+ newline-count (+ newline-count 1) )
+ )
+
+ ;; indent what we just inserted
+ (c-indent-region cur-point (point) t)
+
+ ;; move up n/2 lines. This assumes that the
+ ;; inserted text is ~symmetric about the halfway point.
+ ;; The assumption holds if the xml code doc uses a
+ ;; begin-elt and end-elt on a new line all by themselves,
+ ;; and a blank line in between them where the point should be.
+ ;; A more intelligent implementation would use a specific
+ ;; marker string, like @@DOT, to note the desired point.
+ (previous-line (/ newline-count 2))
+ (end-of-line)))))))))
+
+ (if (not did-auto-insert)
+ (self-insert-command (prefix-numeric-value arg)))))
+
+;; ==================================================================
+;; end of c# code-doc insertion magic
+;; ==================================================================
+
+
+
+
+;; ==================================================================
+;; c# fontification extensions
+;; ==================================================================
+;; Commentary:
+;;
+;; The purpose of the following code is to fix font-lock for C#,
+;; specifically for the verbatim-literal strings. C# is a cc-mode
+;; language and strings are handled mostly like other c-based
+;; languages. The one exception is the verbatim-literal string, which
+;; uses the syntax @"...".
+;;
+;; `parse-partial-sexp' treats those strings as just regular strings,
+;; with the @ a non-string character. This is fine, except when the
+;; verblit string ends in a slash, in which case, font-lock breaks from
+;; that point onward in the buffer.
+;;
+;; This is an attempt to fix that.
+;;
+;; The idea is to scan the buffer in full for verblit strings, and apply the
+;; appropriate syntax-table text properties for verblit strings. Also setting
+;; `parse-sexp-lookup-properties' to t tells `parse-partial-sexp'
+;; to use the syntax-table text properties set up by the scan as it does
+;; its parse.
+;;
+;; Also need to re-scan after any changes in the buffer, but on a more
+;; limited region.
+;;
+
+
+;; ;; I don't remember what this is supposed to do,
+;; ;; or how I figured out the value.
+;; ;;
+;; (defconst csharp-font-lock-syntactic-keywords
+;; '(("\\(@\\)\\(\"\\)[^\"]*\\(\"\\)\\(\"\\)[^\"]*\\(\"\\)[^\"]"
+;; (1 '(6)) (2 '(7)) (3 '(1)) (4 '(1)) (5 '(7))
+;; ))
+;; "Highlighting of verbatim literal strings. See also the variable
+;; `font-lock-keywords'.")
+
+
+
+;; Allow this:
+;; (csharp-log 3 "csharp: scan...'%s'" state)
+
+(defvar csharp-log-level 0
+ "The current log level for CSharp-specific operations.
+This is used in particular by the verbatim-literal
+string scanning.
+
+Most other csharp functions are not instrumented.
+0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG, 4 = SHUTUP ALREADY. ")
+
+(defun csharp-log (level text &rest args)
+ "Log a message at level LEVEL.
+If LEVEL is higher than `csharp-log-level', the message is
+ignored. Otherwise, it is printed using `message'.
+TEXT is a format control string, and the remaining arguments ARGS
+are the string substitutions (see `format')."
+ (if (<= level csharp-log-level)
+ (let* ((msg (apply 'format text args)))
+ (message "%s" msg)
+ )))
+
+
+
+(defun csharp-max-beginning-of-stmt ()
+ "Return the greater of `c-beginning-of-statement-1' and
+`c-beginning-of-statement' . I don't understand why both of
+these methods are necessary or why they differ. But they do."
+
+ (let (dash
+ nodash
+ (curpos (point)))
+
+ ;; I think this may need a save-excursion...
+ ;; Calling c-beginning-of-statement-1 resets the point!
+
+ (setq dash (progn (c-beginning-of-statement-1) (point)))
+ (csharp-log 3 "C#: max-bostmt dash(%d)" dash)
+ (goto-char curpos)
+
+ (setq nodash (progn (c-beginning-of-statement 1) (point)))
+ (csharp-log 3 "C#: max-bostmt nodash(%d)" nodash)
+ (goto-char curpos)
+
+ (max dash nodash)))
+
+
+(defun csharp-in-literal (&optional lim detect-cpp)
+ "Return the type of literal point is in, if any.
+Basically this works like `c-in-literal' except it doesn't
+use or fill the cache (`c-in-literal-cache').
+
+The return value is `c' if in a C-style comment, `c++' if in a C++
+style comment, `string' if in a string literal, `pound' if DETECT-CPP
+is non-nil and in a preprocessor line, or nil if somewhere else.
+Optional LIM is used as the backward limit of the search. If omitted,
+or nil, `c-beginning-of-syntax' is used.
+
+Note that this function might do hidden buffer changes. See the
+comment at the start of cc-engine.el for more info."
+
+ (let ((rtn
+ (save-excursion
+ (let* ((pos (point))
+ (lim (or lim (progn
+ (c-beginning-of-syntax)
+ (point))))
+ (state (parse-partial-sexp lim pos)))
+ (csharp-log 4 "C#: parse lim(%d) state: %s" lim (prin1-to-string state))
+ (cond
+ ((elt state 3)
+ (csharp-log 4 "C#: in literal string (%d)" pos)
+ 'string)
+ ((elt state 4)
+ (csharp-log 4 "C#: in literal comment (%d)" pos)
+ (if (elt state 7) 'c++ 'c))
+ ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
+ (t nil))))))
+ rtn))
+
+
+(defun csharp-set-vliteral-syntax-table-properties (beg end)
+ "Scan the buffer text between BEG and END, a verbatim literal
+string, setting and clearing syntax-table text properties where
+necessary.
+
+We need to modify the default syntax-table text property in these cases:
+ (backslash) - is not an escape inside a verbatim literal string.
+ (double-quote) - can be a literal quote, when doubled.
+
+BEG is the @ delimiter. END is the 'old' position of the ending quote.
+
+see http://www.sunsite.ualberta.ca/Documentation/Gnu/emacs-lisp-ref-21-2.7/html_node/elisp_592.html
+for the list of syntax table numeric codes.
+
+"
+
+ (csharp-log 3 "C#: set-vlit-syntax-table: beg(%d) end(%d)" beg end)
+
+ (if (and (> beg 0) (> end 0))
+
+ (let ((curpos beg)
+ (state 0))
+
+ (c-clear-char-properties beg end 'syntax-table)
+
+ (while (<= curpos end)
+
+ (cond
+ ((= state 0)
+ (if (= (char-after curpos) ?@)
+ (progn
+ (c-put-char-property curpos 'syntax-table '(3)) ; (6) = expression prefix, (3) = symbol
+ ;;(message (format "C#: set-s-t: prefix pos(%d) chr(%c)" beg (char-after beg)))
+ )
+ )
+ (setq state (+ 1 state)))
+
+ ((= state 1)
+ (if (= (char-after curpos) ?\")
+ (progn
+ (c-put-char-property curpos 'syntax-table '(7)) ; (7) = string quote
+ ;;(message (format "C#: set-s-t: open quote pos(%d) chr(%c)"
+ ;; curpos (char-after curpos)))
+ ))
+ (setq state (+ 1 state)))
+
+ ((= state 2)
+ (cond
+ ;; handle backslash
+ ((= (char-after curpos) ?\\)
+ (c-put-char-property curpos 'syntax-table '(2)) ; (1) = punctuation, (2) = word
+ ;;(message (format "C#: set-s-t: backslash word pos(%d) chr(%c)" curpos (char-after curpos)))
+ )
+
+ ;; doubled double-quote
+ ((and
+ (= (char-after curpos) ?\")
+ (= (char-after (+ 1 curpos)) ?\"))
+ (c-put-char-property curpos 'syntax-table '(2)) ; (1) = punctuation, (2) = word
+ (c-put-char-property (+ 1 curpos) 'syntax-table '(2)) ; (1) = punctuation
+ ;;(message (format "C#: set-s-t: double doublequote pos(%d) chr(%c)" curpos (char-after curpos)))
+ (setq curpos (+ curpos 1))
+ )
+
+ ;; a single double-quote, which should be a string terminator
+ ((= (char-after curpos) ?\")
+ (c-put-char-property curpos 'syntax-table '(7)) ; (7) = string quote
+ ;;(message (format "C#: set-s-t: close quote pos(%d) chr(%c)" curpos (char-after curpos)))
+ ;;go no further
+ (setq state (+ 1 state)))
+
+ ;; everything else
+ (t
+ ;;(message (format "C#: set-s-t: none pos(%d) chr(%c)" curpos (char-after curpos)))
+ nil))))
+ ;; next char
+ (setq curpos (+ curpos 1))))))
+
+
+
+(defun csharp-end-of-verbatim-literal-string (&optional lim)
+ "Moves to and returns the position of the end quote of the verbatim literal
+string. When calling, point should be on the @ of the verblit string.
+If it is not, then no movement is performed and `point' is returned.
+
+This function ignores text properties. In fact it is the
+underlying scanner used to set the text properties in a C# buffer.
+"
+
+ (csharp-log 3 "C#: end-of-vlit-string: point(%d) c(%c)" (point) (char-after))
+
+ (let (curpos
+ (max (or lim (point-max))))
+
+ (if (not (looking-at "@\""))
+ (point)
+ (forward-char 2) ;; pass up the @ sign and first quote
+ (setq curpos (point))
+
+ ;; Within a verbatim literal string, a doubled double-quote
+ ;; escapes the double-quote."
+ (while (and ;; process characters...
+ (or ;; while...
+ (not (eq (char-after curpos) ?\")) ;; it's not a quote
+ (eq (char-after (+ curpos 1)) ?\")) ;; or, its a double (double) quote
+ (< curpos max)) ;; and we're not done yet
+
+ (cond
+ ((and (eq (char-after curpos) ?\") ;; it's a double-quote.
+ (eq (char-after (+ curpos 1)) ?\"))
+ (setq curpos (+ 2 curpos))) ;; Skip 2
+ (t ;; anything else
+ (setq curpos (+ 1 curpos))))) ;; skip fwd 1
+ curpos)))
+
+
+
+
+(defun csharp-scan-for-verbatim-literals-and-set-props (&optional beg end)
+
+"Scans the buffer, between BEG and END, for verbatim literal
+strings, and sets override text properties on each string to
+allow proper syntax highlighting, indenting, and cursor movement.
+
+BEG and END define the limits of the scan. When nil, they
+default to `point-min' and `point-max' respectively.
+
+Setting text properties generally causes the buffer to be marked
+as modified, but this fn suppresses that via the
+`c-buffer-save-state' macro, for any changes in text properties
+that it makes. This fn also ignores the read-only setting on a
+buffer, using the same macro.
+
+This fn is called when a csharp-mode buffer is loaded, with BEG
+and END set to nil, to do a full scan. It is also called on
+every buffer change, with the BEG and END set to the values for
+the change.
+
+The return value is nil if the buffer was not a csharp-mode
+buffer. Otherwise it is the last cursor position examined by the
+scan.
+"
+
+ (if (not (c-major-mode-is 'csharp-mode)) ;; don't scan if not csharp mode
+ nil
+ (save-excursion
+ (c-save-buffer-state
+ ((curpos (or beg (point-min)))
+ (lastpos (or end (point-max)))
+ (state 0) (start 0) (cycle 0)
+ literal eos limits)
+
+ (csharp-log 3 "C#: scan")
+ (goto-char curpos)
+
+ (while (and (< curpos lastpos) (< cycle 10000))
+ (cond
+
+ ;; Case 1: current char is a @ sign
+ ;; --------------------------------------------
+ ;; Check to see if it demarks the beginning of a verblit
+ ;; string.
+ ((= ?@ (char-after curpos))
+
+ ;; are we in a comment? a string? Maybe the @ is a prefix
+ ;; to allow the use of a reserved word as a symbol. Let's find out.
+
+ ;; not sure why I need both of the following.
+ (syntax-ppss-flush-cache 1)
+ (parse-partial-sexp 1 curpos)
+ (goto-char curpos)
+ (setq literal (csharp-in-literal))
+ (cond
+
+ ;; Case 1.A: it's a @ within a string.
+ ;; --------------------------------------------
+ ;; This should never happen, because this scanner hops over strings.
+ ;; But it might happen if the scan starts at an odd place.
+ ((eq literal 'string) nil)
+
+ ;; Case 1.B: The @ is within a comment. Hop over it.
+ ((and (memq literal '(c c++))
+ ;; This is a kludge for XEmacs where we use
+ ;; `buffer-syntactic-context', which doesn't correctly
+ ;; recognize "\*/" to end a block comment.
+ ;; `parse-partial-sexp' which is used by
+ ;; `c-literal-limits' will however do that in most
+ ;; versions, which results in that we get nil from
+ ;; `c-literal-limits' even when `c-in-literal' claims
+ ;; we're inside a comment.
+ ;;(setq limits (c-literal-limits start)))
+ (setq limits (c-literal-limits)))
+
+ ;; advance to the end of the comment
+ (if limits
+ (progn
+ (csharp-log 4 "C#: scan: jump end comment A (%d)" (cdr limits))
+ (setq curpos (cdr limits)))))
+
+
+ ;; Case 1.B: curpos is at least 2 chars before the last
+ ;; position to examine, and, the following char is a
+ ;; double-quote (ASCII 34).
+ ;; --------------------------------------------
+ ;; This looks like the beginning of a verbatim string
+ ;; literal.
+ ((and (< (+ 2 curpos) lastpos)
+ (= ?\" (char-after (+ 1 curpos))))
+
+ (setq eos (csharp-end-of-verbatim-literal-string))
+ ;; set override syntax properties on the verblit string
+ (csharp-set-vliteral-syntax-table-properties curpos eos)
+
+ (csharp-log 4 "C#: scan: jump end verblit string (%d)" eos)
+ (setq curpos eos))))
+
+
+ ;; Case 2: current char is a double-quote.
+ ;; --------------------------------------------
+ ;; If this is a string, we hop over it, on the assumption that
+ ;; this scanner need not bother with regular literal strings, which
+ ;; get the proper syntax with the generic approach.
+ ;; If in a comment, hop over the comment.
+ ((= ?\" (char-after curpos))
+ (goto-char curpos)
+ (setq literal (c-in-literal))
+ (cond
+
+ ;; Case 2.A: a quote within a string
+ ;; --------------------------------------------
+ ;; This shouldn't happen, because we hop over strings.
+ ;; But it might.
+ ((eq literal 'string) nil)
+
+ ;; Case 2.B: a quote within a comment
+ ;; --------------------------------------------
+ ((and (memq literal '(c c++))
+ ;; This is a kludge for XEmacs where we use
+ ;; `buffer-syntactic-context', which doesn't correctly
+ ;; recognize "\*/" to end a block comment.
+ ;; `parse-partial-sexp' which is used by
+ ;; `c-literal-limits' will however do that in most
+ ;; versions, which results in that we get nil from
+ ;; `c-literal-limits' even when `c-in-literal' claims
+ ;; we're inside a comment.
+ ;;(setq limits (c-literal-limits start)))
+ (setq limits (c-literal-limits)))
+
+ ;; advance to the end of the comment
+ (if limits
+ (progn
+ (setq curpos (cdr limits))
+ (csharp-log 3 "C#: scan: jump end comment B (%s)" curpos))))
+
+
+ ;; Case 2.C: Not in a comment, and not in a string.
+ ;; --------------------------------------------
+ ;; This is the beginning of a literal (but not verbatim) string.
+ (t
+ (forward-char 1) ;; pass up the quote
+ (if (consp (setq limits (c-literal-limits)))
+ (progn
+ (csharp-log 4 "C#: scan: jump end literal (%d)" (cdr limits))
+ (setq curpos (cdr limits))))))))
+
+ (setq cycle (+ 1 cycle))
+ (setq curpos (+ 1 curpos))
+ (c-safe (goto-char curpos)))))))
+
+
+(defun csharp-before-font-lock (beg end old-len)
+ "Adjust`syntax-table' properties on the region affected by the change
+in a csharp-mode buffer.
+
+This function is the C# value for `c-before-font-lock-function'.
+It intended to be called only by the cc-mode runtime.
+
+It prepares the buffer for font locking, hence must get called
+before `font-lock-after-change-function'.
+
+It does hidden buffer changes.
+
+BEG, END and OLD-LEN have the same meaning here as for any
+after-change function.
+
+Point is undefined both before and after this function call.
+The return value is meaningless, and is ignored by cc-mode.
+"
+ (let ((start-scan (progn
+ (c-beginning-of-statement 1)
+ (point))))
+ (csharp-scan-for-verbatim-literals-and-set-props start-scan end)))
+
+
+
+(c-lang-defconst c-before-font-lock-function
+ csharp 'csharp-before-font-lock)
+
+;; ==================================================================
+;; end of c# fontification extensions
+;; ==================================================================
+
+
+
+
+
+;; ==================================================================
+;; C#-specific optimizations of cc-mode funcs
+;; ==================================================================
+
+
+;; There's never a need to check for C-style macro definitions in
+;; a C# buffer.
+(defadvice c-beginning-of-macro (around
+ csharp-mode-advice-1
+ compile activate)
+ (if (c-major-mode-is 'csharp-mode)
+ nil
+ ad-do-it)
+ )
+
+
+;; There's never a need to move over an Obj-C directive in csharp mode
+(defadvice c-forward-objc-directive (around
+ csharp-mode-advice-2
+ compile activate)
+ (if (c-major-mode-is 'csharp-mode)
+ nil
+ ad-do-it)
+ )
+
+;; ==================================================================
+;; end of C#-specific optimizations of cc-mode funcs
+;; ==================================================================
+
+
+
+
+
+
+
+
+;; ==================================================================
+;; c# - monkey-patching of basic parsing logic
+;; ==================================================================
+;;
+;; Here, the model redefines two defuns to add special cases for csharp
+;; mode. These primarily deal with indentation of instance
+;; initializers, which are somewhat unique to C#. I couldn't figure out
+;; how to get cc-mode to do what C# needs, without modifying these
+;; defuns.
+;;
+
+(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end)
+ ;; Return non-nil if we're looking at the beginning of a block
+ ;; inside an expression. The value returned is actually a cons of
+ ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the
+ ;; position of the beginning of the construct.
+ ;;
+ ;; LIM limits the backward search. CONTAINING-SEXP is the start
+ ;; position of the closest containing list. If it's nil, the
+ ;; containing paren isn't used to decide whether we're inside an
+ ;; expression or not. If both LIM and CONTAINING-SEXP are used, LIM
+ ;; needs to be farther back.
+ ;;
+ ;; If CHECK-AT-END is non-nil then extra checks at the end of the
+ ;; brace block might be done. It should only be used when the
+ ;; construct can be assumed to be complete, i.e. when the original
+ ;; starting position was further down than that.
+ ;;
+ ;; This function might do hidden buffer changes.
+
+ (save-excursion
+ (let ((res 'maybe) passed-paren
+ (closest-lim (or containing-sexp lim (point-min)))
+ ;; Look at the character after point only as a last resort
+ ;; when we can't disambiguate.
+ (block-follows (and (eq (char-after) ?{) (point))))
+
+ (while (and (eq res 'maybe)
+ (progn (c-backward-syntactic-ws)
+ (> (point) closest-lim))
+ (not (bobp))
+ (progn (backward-char)
+ (looking-at "[\]\).]\\|\\w\\|\\s_"))
+ (c-safe (forward-char)
+ (goto-char (scan-sexps (point) -1))))
+
+ (setq res
+ (if (looking-at c-keywords-regexp)
+ (let ((kw-sym (c-keyword-sym (match-string 1))))
+ (cond
+ ((and block-follows
+ (c-keyword-member kw-sym 'c-inexpr-class-kwds))
+ (and (not (eq passed-paren ?\[))
+
+ ;; dinoch Thu, 22 Apr 2010 18:20
+ ;; ============================================
+ ;; looking at new MyType() { ... }
+ ;; means this is a brace list, so, return nil,
+ ;; implying NOT looking-at-inexpr-block
+ (not
+ (and (c-major-mode-is 'csharp-mode)
+ (looking-at "new\s+\\([[:alnum:]_]+\\)\\b")))
+
+ (or (not (looking-at c-class-key))
+ ;; If the class instantiation is at the start of
+ ;; a statement, we don't consider it an
+ ;; in-expression class.
+ (let ((prev (point)))
+ (while (and
+ (= (c-backward-token-2 1 nil closest-lim) 0)
+ (eq (char-syntax (char-after)) ?w))
+ (setq prev (point)))
+ (goto-char prev)
+ (not (c-at-statement-start-p)))
+ ;; Also, in Pike we treat it as an
+ ;; in-expression class if it's used in an
+ ;; object clone expression.
+ (save-excursion
+ (and check-at-end
+ (c-major-mode-is 'pike-mode)
+ (progn (goto-char block-follows)
+ (zerop (c-forward-token-2 1 t)))
+ (eq (char-after) ?\())))
+ (cons 'inexpr-class (point))))
+ ((c-keyword-member kw-sym 'c-inexpr-block-kwds)
+ (when (not passed-paren)
+ (cons 'inexpr-statement (point))))
+ ((c-keyword-member kw-sym 'c-lambda-kwds)
+ (when (or (not passed-paren)
+ (eq passed-paren ?\())
+ (cons 'inlambda (point))))
+ ((c-keyword-member kw-sym 'c-block-stmt-kwds)
+ nil)
+ (t
+ 'maybe)))
+
+ (if (looking-at "\\s(")
+ (if passed-paren
+ (if (and (eq passed-paren ?\[)
+ (eq (char-after) ?\[))
+ ;; Accept several square bracket sexps for
+ ;; Java array initializations.
+ 'maybe)
+ (setq passed-paren (char-after))
+ 'maybe)
+ 'maybe))))
+
+ (if (eq res 'maybe)
+ (when (and c-recognize-paren-inexpr-blocks
+ block-follows
+ containing-sexp
+ (eq (char-after containing-sexp) ?\())
+ (goto-char containing-sexp)
+ (if (or (save-excursion
+ (c-backward-syntactic-ws lim)
+ (and (> (point) (or lim (point-min)))
+ (c-on-identifier)))
+ (and c-special-brace-lists
+ (c-looking-at-special-brace-list)))
+ nil
+ (cons 'inexpr-statement (point))))
+
+ res))))
+
+
+
+
+(defconst csharp-enum-decl-re
+ (concat
+ "\\<enum\\>\s+\\([[:alnum:]_]+\\)\s*:\s*"
+ "\\("
+ (c-make-keywords-re nil
+ (list "sbyte" "byte" "short" "ushort" "int" "uint" "long" "ulong"))
+ "\\)")
+ "Regex that captures an enum declaration in C#"
+ )
+
+
+
+(defun c-inside-bracelist-p (containing-sexp paren-state)
+ ;; return the buffer position of the beginning of the brace list
+ ;; statement if we're inside a brace list, otherwise return nil.
+ ;; CONTAINING-SEXP is the buffer pos of the innermost containing
+ ;; paren. PAREN-STATE is the remainder of the state of enclosing
+ ;; braces
+ ;;
+ ;; N.B.: This algorithm can potentially get confused by cpp macros
+ ;; placed in inconvenient locations. It's a trade-off we make for
+ ;; speed.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (or
+ ;; This will pick up brace list declarations.
+ (c-safe
+ (save-excursion
+ (goto-char containing-sexp)
+ (c-forward-sexp -1)
+ (let (bracepos)
+ (if (and (or (looking-at c-brace-list-key)
+
+ (progn (c-forward-sexp -1)
+ (looking-at c-brace-list-key))
+
+ ;; dinoch Thu, 22 Apr 2010 18:20
+ ;; ============================================
+ ;; looking enum Foo : int
+ ;; means this is a brace list, so, return nil,
+ ;; implying NOT looking-at-inexpr-block
+
+ (and (c-major-mode-is 'csharp-mode)
+ (progn
+ (c-forward-sexp -1)
+ (looking-at csharp-enum-decl-re))))
+
+ (setq bracepos (c-down-list-forward (point)))
+ (not (c-crosses-statement-barrier-p (point)
+ (- bracepos 2))))
+ (point)))))
+ ;; this will pick up array/aggregate init lists, even if they are nested.
+ (save-excursion
+ (let ((class-key
+ ;; Pike can have class definitions anywhere, so we must
+ ;; check for the class key here.
+ (and (c-major-mode-is 'pike-mode)
+ c-decl-block-key))
+ bufpos braceassignp lim next-containing)
+ (while (and (not bufpos)
+ containing-sexp)
+ (when paren-state
+ (if (consp (car paren-state))
+ (setq lim (cdr (car paren-state))
+ paren-state (cdr paren-state))
+ (setq lim (car paren-state)))
+ (when paren-state
+ (setq next-containing (car paren-state)
+ paren-state (cdr paren-state))))
+ (goto-char containing-sexp)
+ (if (c-looking-at-inexpr-block next-containing next-containing)
+ ;; We're in an in-expression block of some kind. Do not
+ ;; check nesting. We deliberately set the limit to the
+ ;; containing sexp, so that c-looking-at-inexpr-block
+ ;; doesn't check for an identifier before it.
+ (setq containing-sexp nil)
+ ;; see if the open brace is preceded by = or [...] in
+ ;; this statement, but watch out for operator=
+ (setq braceassignp 'dontknow)
+ (c-backward-token-2 1 t lim)
+ ;; Checks to do only on the first sexp before the brace.
+ (when (and c-opt-inexpr-brace-list-key
+ (eq (char-after) ?\[))
+ ;; In Java, an initialization brace list may follow
+ ;; directly after "new Foo[]", so check for a "new"
+ ;; earlier.
+ (while (eq braceassignp 'dontknow)
+ (setq braceassignp
+ (cond ((/= (c-backward-token-2 1 t lim) 0) nil)
+ ((looking-at c-opt-inexpr-brace-list-key) t)
+ ((looking-at "\\sw\\|\\s_\\|[.[]")
+ ;; Carry on looking if this is an
+ ;; identifier (may contain "." in Java)
+ ;; or another "[]" sexp.
+ 'dontknow)
+ (t nil)))))
+ ;; Checks to do on all sexps before the brace, up to the
+ ;; beginning of the statement.
+ (while (eq braceassignp 'dontknow)
+ (cond ((eq (char-after) ?\;)
+ (setq braceassignp nil))
+ ((and class-key
+ (looking-at class-key))
+ (setq braceassignp nil))
+ ((eq (char-after) ?=)
+ ;; We've seen a =, but must check earlier tokens so
+ ;; that it isn't something that should be ignored.
+ (setq braceassignp 'maybe)
+ (while (and (eq braceassignp 'maybe)
+ (zerop (c-backward-token-2 1 t lim)))
+ (setq braceassignp
+ (cond
+ ;; Check for operator =
+ ((and c-opt-op-identifier-prefix
+ (looking-at c-opt-op-identifier-prefix))
+ nil)
+ ;; Check for `<opchar>= in Pike.
+ ((and (c-major-mode-is 'pike-mode)
+ (or (eq (char-after) ?`)
+ ;; Special case for Pikes
+ ;; `[]=, since '[' is not in
+ ;; the punctuation class.
+ (and (eq (char-after) ?\[)
+ (eq (char-before) ?`))))
+ nil)
+ ((looking-at "\\s.") 'maybe)
+ ;; make sure we're not in a C++ template
+ ;; argument assignment
+ ((and
+ (c-major-mode-is 'c++-mode)
+ (save-excursion
+ (let ((here (point))
+ (pos< (progn
+ (skip-chars-backward "^<>")
+ (point))))
+ (and (eq (char-before) ?<)
+ (not (c-crosses-statement-barrier-p
+ pos< here))
+ (not (c-in-literal))
+ ))))
+ nil)
+ (t t))))))
+ (if (and (eq braceassignp 'dontknow)
+ (/= (c-backward-token-2 1 t lim) 0))
+ (setq braceassignp nil)))
+ (if (not braceassignp)
+ (if (eq (char-after) ?\;)
+ ;; Brace lists can't contain a semicolon, so we're done.
+ (setq containing-sexp nil)
+ ;; Go up one level.
+ (setq containing-sexp next-containing
+ lim nil
+ next-containing nil))
+ ;; we've hit the beginning of the aggregate list
+ (c-beginning-of-statement-1
+ (c-most-enclosing-brace paren-state))
+ (setq bufpos (point))))
+ )
+ bufpos))
+ ))
+
+;; ==================================================================
+;; end of monkey-patching of basic parsing logic
+;; ==================================================================
+
+
+
+
+;;(easy-menu-define csharp-menu csharp-mode-map "C# Mode Commands"
+;; ;; Can use `csharp' as the language for `c-mode-menu'
+;; ;; since its definition covers any language. In
+;; ;; this case the language is used to adapt to the
+;; ;; nonexistence of a cpp pass and thus removing some
+;; ;; irrelevant menu alternatives.
+;; (cons "C#" (c-lang-const c-mode-menu csharp)))
+
+;;; Autoload mode trigger
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.cs$" . csharp-mode))
+
+
+
+(c-add-style "C#"
+ '("Java"
+ (c-basic-offset . 4)
+ (c-comment-only-line-offset . (0 . 0))
+ (c-offsets-alist . (
+ (access-label . -)
+ (arglist-close . c-lineup-arglist)
+ (arglist-cont . 0)
+ (arglist-cont-nonempty . c-lineup-arglist)
+ (arglist-intro . c-lineup-arglist-intro-after-paren)
+ (block-close . 0)
+ (block-open . 0)
+ (brace-entry-open . 0)
+ (brace-list-close . 0)
+ (brace-list-entry . 0)
+ (brace-list-intro . +)
+ (brace-list-open . +)
+ (c . c-lineup-C-comments)
+ (case-label . +)
+ (catch-clause . 0)
+ (class-close . 0)
+ (class-open . 0)
+ (comment-intro . c-lineup-comment)
+ (cpp-macro . 0)
+ (cpp-macro-cont . c-lineup-dont-change)
+ (defun-block-intro . +)
+ (defun-close . 0)
+ (defun-open . 0)
+ (do-while-closure . 0)
+ (else-clause . 0)
+ (extern-lang-close . 0)
+ (extern-lang-open . 0)
+ (friend . 0)
+ (func-decl-cont . +)
+ (inclass . +)
+ (inexpr-class . +)
+ (inexpr-statement . 0)
+ (inextern-lang . +)
+ (inher-cont . c-lineup-multi-inher)
+ (inher-intro . +)
+ (inlambda . c-lineup-inexpr-block)
+ (inline-close . 0)
+ (inline-open . 0)
+ (innamespace . +)
+ (knr-argdecl . 0)
+ (knr-argdecl-intro . 5)
+ (label . 0)
+ (lambda-intro-cont . +)
+ (member-init-cont . c-lineup-multi-inher)
+ (member-init-intro . +)
+ (namespace-close . 0)
+ (namespace-open . 0)
+ (statement . 0)
+ (statement-block-intro . +)
+ (statement-case-intro . +)
+ (statement-case-open . +)
+ (statement-cont . +)
+ (stream-op . c-lineup-streamop)
+ (string . c-lineup-dont-change)
+ (substatement . +)
+ (substatement-open . 0)
+ (template-args-cont c-lineup-template-args +)
+ (topmost-intro . 0)
+ (topmost-intro-cont . 0)
+ ))
+ ))
+
+
+
+
+;; Custom variables
+;;;###autoload
+(defcustom csharp-mode-hook nil
+ "*Hook called by `csharp-mode'."
+ :type 'hook
+ :group 'c)
+
+
+
+;;; The entry point into the mode
+;;;###autoload
+(defun csharp-mode ()
+ "Major mode for editing C# code. This mode is derived from CC Mode to
+support C#.
+
+The hook `c-mode-common-hook' is run with no args at mode
+initialization, then `csharp-mode-hook'.
+
+This mode will automatically add a regexp for Csc.exe error and warning
+messages to the `compilation-error-regexp-alist'.
+
+Key bindings:
+\\{csharp-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (make-local-variable 'beginning-of-defun-function)
+ (make-local-variable 'end-of-defun-function)
+ (c-initialize-cc-mode t)
+ (set-syntax-table csharp-mode-syntax-table)
+
+ ;; define underscore as part of a word in the Csharp syntax table
+ (modify-syntax-entry ?_ "w" csharp-mode-syntax-table)
+
+ ;; define @ as an expression prefix in Csharp syntax table
+ (modify-syntax-entry ?@ "'" csharp-mode-syntax-table)
+
+ (setq major-mode 'csharp-mode
+ mode-name "C#"
+ local-abbrev-table csharp-mode-abbrev-table
+ abbrev-mode t)
+ (use-local-map csharp-mode-map)
+
+ ;; `c-init-language-vars' is a macro that is expanded at compile
+ ;; time to a large `setq' with all the language variables and their
+ ;; customized values for our language.
+ (c-init-language-vars csharp-mode)
+
+
+ ;; `c-common-init' initializes most of the components of a CC Mode
+ ;; buffer, including setup of the mode menu, font-lock, etc.
+ ;; There's also a lower level routine `c-basic-common-init' that
+ ;; only makes the necessary initialization to get the syntactic
+ ;; analysis and similar things working.
+ (c-common-init 'csharp-mode)
+
+
+ ;; csc.exe, the C# Compiler, produces errors like this:
+ ;; file.cs(6,18): error SC1006: Name of constructor must match name of class
+
+ (add-hook 'compilation-mode-hook
+ (lambda ()
+ (setq compilation-error-regexp-alist
+ (cons ' ("^[ \t]*\\([A-Za-z0-9][^(]+\\.cs\\)(\\([0-9]+\\)[,]\\([0-9]+\\)) ?: \\(error\\|warning\\) CS[0-9]+:" 1 2 3)
+ compilation-error-regexp-alist))))
+
+ ;; to allow next-error to work with csc.exe:
+ (setq compilation-scroll-output t)
+
+ ;; allow fill-paragraph to work on xml code doc
+ (set (make-local-variable 'paragraph-separate)
+ "[ \t]*\\(//+\\|\\**\\)\\([ \t]+\\|[ \t]+<.+?>\\)$\\|^\f")
+
+
+ (c-run-mode-hooks 'c-mode-common-hook 'csharp-mode-hook)
+
+
+ ;; Need the following for parse-partial-sexp to work properly with
+ ;; verbatim literal strings Setting this var to non-nil tells
+ ;; `parse-partial-sexp' to pay attention to the syntax text
+ ;; properties on the text in the buffer. If csharp-mode attaches
+ ;; text syntax to @"..." then, `parse-partial-sexp' will treat those
+ ;; strings accordingly.
+ (set (make-local-variable 'parse-sexp-lookup-properties)
+ t)
+
+ ;; scan the entire buffer for verblit strings
+ (csharp-scan-for-verbatim-literals-and-set-props nil nil)
+
+
+ (local-set-key (kbd "/") 'csharp-maybe-insert-codedoc)
+ (local-set-key (kbd "{") 'csharp-insert-open-brace)
+
+ (c-update-modeline))
+
+
+
+(message (concat "Done loading " load-file-name))
+
+
+(provide 'csharp-mode)
+
+;;; csharp-mode.el ends here
+;;MD5: 4EDCB2ECE38841F407C7ED3DA8354E15
diff --git a/emacs.d/nxhtml/related/django.el b/emacs.d/nxhtml/related/django.el
new file mode 100644
index 0000000..f592550
--- /dev/null
+++ b/emacs.d/nxhtml/related/django.el
@@ -0,0 +1,203 @@
+;;; django.el ---
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: Sun Nov 18 18:29:41 2007
+;; Version: 0.3
+;; Last-Updated: 2008-08-08T13:22:19+0200 Fri
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Simple highlighting for Django for use with mumamo.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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 2, 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;; Maybe there are something to get here?
+;; http://github.com/cosmin/emacs-utils/tree/85cc1d2bd447cb9b2fc98e27b5f8780453e5b978/django-html-mode.el
+
+(defconst django-indenting-keywords
+ '("block" "comment" "else"
+ "filter" "for" "if" "ifchanged" "ifequal"
+ "ifnotequal" "spaceless" "with"))
+
+;; (append '(or) django-indenting-keywords)
+(defconst django-font-lock-keywords
+ (list
+ (cons (rx-to-string
+ `(and
+ word-start
+ (or "as" "autoescape" "csrf_token" "cycle" "debug" "extends"
+ "firstof" "in" "include" "load" "now" "regroup" "ssi"
+ "templatetag" "url" "widthratio"
+ (seq
+ (opt "end")
+ ;; (or "autoescape" "block" "comment" "cycle" "debug" "else"
+ ;; "extends" "filter" "firstof" "for" "if" "ifchanged" "ifequal"
+ ;; "ifnotequal" "include" "load" "now" "regroup"
+ ;; "spaceless" "ssi" "templatetag" "url" "widthratio"
+ ;; "with")
+ ,(append '(or) django-indenting-keywords)
+ ))
+ word-end))
+ font-lock-keyword-face)
+ )
+ "Minimal highlighting expressions for Django mode")
+
+(defcustom django-indent-width 2
+ "Indentation width for Django."
+ :type 'integer
+ :group 'django)
+
+(defun django-indent-line ()
+ "Indent current line as Django code.
+Indent like the examples on URL
+`http://docs.djangoproject.com/en/1.1/ref/templates/builtins/'."
+ (save-match-data
+ (let* ((indent-re (rx-to-string `(and word-start
+ ,(append '(or "else") django-indenting-keywords))))
+ (deindent-re (rx-to-string `(and word-start
+ (or "else"
+ (seq
+ "end"
+ ,(append '(or) django-indenting-keywords))))))
+ (here (point-marker))
+ (this-indentation (current-indentation))
+ (this-line-start (progn (beginning-of-line) (point)))
+ (prev-line-start (progn (skip-chars-backward " \t\n\r\f")
+ (beginning-of-line)
+ (when (< (point) this-line-start)
+ (point))))
+ (prev-indentation (if prev-line-start (current-indentation) 0))
+ (shift-in (if (and prev-line-start
+ (re-search-forward indent-re (point-at-eol) t))
+ django-indent-width 0))
+ (shift-out (progn
+ (goto-char this-line-start)
+ (if (re-search-forward deindent-re (point-at-eol) t)
+ (- django-indent-width) 0)))
+ (new-indentation (max 0 (+ prev-indentation shift-in shift-out)))
+ )
+ (goto-char this-line-start)
+ (cond
+ ((> new-indentation this-indentation)
+ (skip-chars-forward " \t")
+ (indent-to new-indentation))
+ ((< new-indentation this-indentation)
+ (back-to-indentation)
+ (delete-region this-line-start (point))
+ (indent-to new-indentation)))
+ (goto-char here))))
+
+;;;###autoload
+(define-derived-mode django-mode nil "Django"
+ "Simple Django mode for use with mumamo.
+This mode only provides syntax highlighting."
+ (set (make-local-variable 'indent-line-function) 'django-indent-line)
+ (setq font-lock-defaults '(django-font-lock-keywords)))
+
+;;; Comments mode
+;; (defconst django-comment-font-lock-keywords
+;; (list
+;; (cons "\\(.*\\)" (list 1 font-lock-comment-face))
+;; ))
+
+;; (defvar django-comment-font-lock-defaults
+;; '(django-comment-font-lock-keywords t t))
+
+;; (define-derived-mode django-comment-mode nil "Django comment"
+;; "For django comment blocks."
+;; (set (make-local-variable 'font-lock-defaults) django-comment-font-lock-defaults))
+
+;;; Variables mode
+
+(defconst django-variable-font-lock-keywords
+ (list
+ ;; Built in filters:
+ (cons (rx
+ "|"
+ (submatch
+ (or "add" "addslashes" "capfirst" "center" "cut"
+ "date" "default" "default_if_none"
+ "dictsort" "dictsortreversed"
+ "divisibleby"
+ "escape"
+ "filesizeformat"
+ "first"
+ "fixampersands"
+ "floatformat"
+ "force_escape"
+ "iriencode"
+ "join"
+ "length" "length_is"
+ "linebreaks" "linebreaksbr" "linenumbers"
+ "ljust"
+ "lower"
+ "make_list"
+ "phone2numeric"
+ "pluralize"
+ "pprint"
+ "random"
+ "removetags"
+ "rjust"
+ "safe" "slice" "slugify" "stringformat" "striptags"
+ "time" "timesince" "timeuntil"
+ "title" "truncatewords" "truncatewords_html"
+ "unordered_list"
+ "upper" "urlencode" "urlize" "urlizetrunc"
+ "wordcount" "wordwrap" "yesno")))
+ (list 1 font-lock-builtin-face))
+ (cons (rx
+ "|"
+ (submatch
+ (0+ (any "a-z"))))
+ (list 1 font-lock-function-name-face))
+ (cons "\\([^|]*\\)" (list 1 font-lock-variable-name-face))
+ ))
+
+(defvar django-variable-font-lock-defaults
+ '(django-variable-font-lock-keywords
+ t t
+ ;; This still gives teh syntax symbol to |, why?
+ ((?| . ". "))
+ ))
+
+(define-derived-mode django-variable-mode nil "Django variable"
+ "For django comment blocks."
+ ;;(modify-syntax-entry ?| ?.)
+ (set (make-local-variable 'font-lock-defaults) django-variable-font-lock-defaults))
+
+(provide 'django)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; django.el ends here
diff --git a/emacs.d/nxhtml/related/env.js b/emacs.d/nxhtml/related/env.js
new file mode 100644
index 0000000..53551e7
--- /dev/null
+++ b/emacs.d/nxhtml/related/env.js
@@ -0,0 +1,695 @@
+/*
+ * Simulated browser environment for Rhino
+ * By John Resig <http://ejohn.org/>
+ * Copyright 2007 John Resig, under the MIT License
+ */
+
+// The window Object
+var window = this;
+
+(function(){
+
+ // Browser Navigator
+
+ window.navigator = {
+ get userAgent(){
+ return "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";
+ }
+ };
+
+ var curLocation = (new java.io.File("./")).toURL();
+
+ window.__defineSetter__("location", function(url){
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+ xhr.onreadystatechange = function(){
+ curLocation = new java.net.URL( curLocation, url );
+ window.document = xhr.responseXML;
+
+ var event = document.createEvent();
+ event.initEvent("load");
+ window.dispatchEvent( event );
+ };
+ xhr.send();
+ });
+
+ window.__defineGetter__("location", function(url){
+ return {
+ get protocol(){
+ return curLocation.getProtocol() + ":";
+ },
+ get href(){
+ return curLocation.toString();
+ },
+ toString: function(){
+ return this.href;
+ }
+ };
+ });
+
+ // Timers
+
+ var timers = [];
+
+ window.setTimeout = function(fn, time){
+ var num;
+ return num = setInterval(function(){
+ fn();
+ clearInterval(num);
+ }, time);
+ };
+
+ window.setInterval = function(fn, time){
+ var num = timers.length;
+
+ timers[num] = new java.lang.Thread(new java.lang.Runnable({
+ run: function(){
+ while (true){
+ java.lang.Thread.currentThread().sleep(time);
+ fn();
+ }
+ }
+ }));
+
+ timers[num].start();
+
+ return num;
+ };
+
+ window.clearInterval = function(num){
+ if ( timers[num] ) {
+ timers[num].stop();
+ delete timers[num];
+ }
+ };
+
+ // Window Events
+
+ var events = [{}];
+
+ window.addEventListener = function(type, fn){
+ if ( !this.uuid || this == window ) {
+ this.uuid = events.length;
+ events[this.uuid] = {};
+ }
+
+ if ( !events[this.uuid][type] )
+ events[this.uuid][type] = [];
+
+ if ( events[this.uuid][type].indexOf( fn ) < 0 )
+ events[this.uuid][type].push( fn );
+ };
+
+ window.removeEventListener = function(type, fn){
+ if ( !this.uuid || this == window ) {
+ this.uuid = events.length;
+ events[this.uuid] = {};
+ }
+
+ if ( !events[this.uuid][type] )
+ events[this.uuid][type] = [];
+
+ events[this.uuid][type] =
+ events[this.uuid][type].filter(function(f){
+ return f != fn;
+ });
+ };
+
+ window.dispatchEvent = function(event){
+ if ( event.type ) {
+ if ( this.uuid && events[this.uuid][event.type] ) {
+ var self = this;
+
+ events[this.uuid][event.type].forEach(function(fn){
+ fn.call( self, event );
+ });
+ }
+
+ if ( this["on" + event.type] )
+ this["on" + event.type].call( self, event );
+ }
+ };
+
+ // DOM Document
+
+ window.DOMDocument = function(file){
+ this._file = file;
+ this._dom = Packages.javax.xml.parsers.
+ DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder().parse(file);
+
+ if ( !obj_nodes.containsKey( this._dom ) )
+ obj_nodes.put( this._dom, this );
+ };
+
+ DOMDocument.prototype = {
+ createTextNode: function(text){
+ return makeNode( this._dom.createTextNode(
+ text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")) );
+ },
+ createElement: function(name){
+ return makeNode( this._dom.createElement(name.toLowerCase()) );
+ },
+ getElementsByTagName: function(name){
+ return new DOMNodeList( this._dom.getElementsByTagName(
+ name.toLowerCase()) );
+ },
+ getElementById: function(id){
+ var elems = this._dom.getElementsByTagName("*");
+
+ for ( var i = 0; i < elems.length; i++ ) {
+ var elem = elems.item(i);
+ if ( elem.getAttribute("id") == id )
+ return makeNode(elem);
+ }
+
+ return null;
+ },
+ get body(){
+ return this.getElementsByTagName("body")[0];
+ },
+ get documentElement(){
+ return makeNode( this._dom.getDocumentElement() );
+ },
+ get ownerDocument(){
+ return null;
+ },
+ addEventListener: window.addEventListener,
+ removeEventListener: window.removeEventListener,
+ dispatchEvent: window.dispatchEvent,
+ get nodeName() {
+ return "#document";
+ },
+ importNode: function(node, deep){
+ return makeNode( this._dom.importNode(node._dom, deep) );
+ },
+ toString: function(){
+ return "Document" + (typeof this._file == "string" ?
+ ": " + this._file : "");
+ },
+ get innerHTML(){
+ return this.documentElement.outerHTML;
+ },
+
+ get defaultView(){
+ return {
+ getComputedStyle: function(elem){
+ return {
+ getPropertyValue: function(prop){
+ prop = prop.replace(/\-(\w)/g,function(m,c){
+ return c.toUpperCase();
+ });
+ var val = elem.style[prop];
+
+ if ( prop == "opacity" && val == "" )
+ val = "1";
+
+ return val;
+ }
+ };
+ }
+ };
+ },
+
+ createEvent: function(){
+ return {
+ type: "",
+ initEvent: function(type){
+ this.type = type;
+ }
+ };
+ }
+ };
+
+ function getDocument(node){
+ return obj_nodes.get(node);
+ }
+
+ // DOM NodeList
+
+ window.DOMNodeList = function(list){
+ this._dom = list;
+ this.length = list.getLength();
+
+ for ( var i = 0; i < this.length; i++ ) {
+ var node = list.item(i);
+ this[i] = makeNode( node );
+ }
+ };
+
+ DOMNodeList.prototype = {
+ toString: function(){
+ return "[ " +
+ Array.prototype.join.call( this, ", " ) + " ]";
+ },
+ get outerHTML(){
+ return Array.prototype.map.call(
+ this, function(node){return node.outerHTML;}).join('');
+ }
+ };
+
+ // DOM Node
+
+ window.DOMNode = function(node){
+ this._dom = node;
+ };
+
+ DOMNode.prototype = {
+ get nodeType(){
+ return this._dom.getNodeType();
+ },
+ get nodeValue(){
+ return this._dom.getNodeValue();
+ },
+ get nodeName() {
+ return this._dom.getNodeName();
+ },
+ cloneNode: function(deep){
+ return makeNode( this._dom.cloneNode(deep) );
+ },
+ get ownerDocument(){
+ return getDocument( this._dom.ownerDocument );
+ },
+ get documentElement(){
+ return makeNode( this._dom.documentElement );
+ },
+ get parentNode() {
+ return makeNode( this._dom.getParentNode() );
+ },
+ get nextSibling() {
+ return makeNode( this._dom.getNextSibling() );
+ },
+ get previousSibling() {
+ return makeNode( this._dom.getPreviousSibling() );
+ },
+ toString: function(){
+ return '"' + this.nodeValue + '"';
+ },
+ get outerHTML(){
+ return this.nodeValue;
+ }
+ };
+
+ // DOM Element
+
+ window.DOMElement = function(elem){
+ this._dom = elem;
+ this.style = {
+ get opacity(){ return this._opacity; },
+ set opacity(val){ this._opacity = val + ""; }
+ };
+
+ // Load CSS info
+ var styles = (this.getAttribute("style") || "").split(/\s*;\s*/);
+
+ for ( var i = 0; i < styles.length; i++ ) {
+ var style = styles[i].split(/\s*:\s*/);
+ if ( style.length == 2 )
+ this.style[ style[0] ] = style[1];
+ }
+ };
+
+ DOMElement.prototype = extend( new DOMNode(), {
+ get nodeName(){
+ return this.tagName.toUpperCase();
+ },
+ get tagName(){
+ return this._dom.getTagName();
+ },
+ toString: function(){
+ return "<" + this.tagName + (this.id ? "#" + this.id : "" ) + ">";
+ },
+ get outerHTML(){
+ var ret = "<" + this.tagName, attr = this.attributes;
+
+ for ( var i in attr )
+ ret += " " + i + "='" + attr[i] + "'";
+
+ if ( this.childNodes.length || this.nodeName == "SCRIPT" )
+ ret += ">" + this.childNodes.outerHTML +
+ "</" + this.tagName + ">";
+ else
+ ret += "/>";
+
+ return ret;
+ },
+
+ get attributes(){
+ var attr = {}, attrs = this._dom.getAttributes();
+
+ for ( var i = 0; i < attrs.getLength(); i++ )
+ attr[ attrs.item(i).nodeName ] = attrs.item(i).nodeValue;
+
+ return attr;
+ },
+
+ get innerHTML(){
+ return this.childNodes.outerHTML;
+ },
+ set innerHTML(html){
+ html = html.replace(/<\/?([A-Z]+)/g, function(m){
+ return m.toLowerCase();
+ });
+
+ var nodes = this.ownerDocument.importNode(
+ new DOMDocument( new java.io.ByteArrayInputStream(
+ (new java.lang.String("<wrap>" + html + "</wrap>"))
+ .getBytes("UTF8"))).documentElement, true).childNodes;
+
+ while (this.firstChild)
+ this.removeChild( this.firstChild );
+
+ for ( var i = 0; i < nodes.length; i++ )
+ this.appendChild( nodes[i] );
+ },
+
+ get textContent(){
+ return nav(this.childNodes);
+
+ function nav(nodes){
+ var str = "";
+ for ( var i = 0; i < nodes.length; i++ )
+ if ( nodes[i].nodeType == 3 )
+ str += nodes[i].nodeValue;
+ else if ( nodes[i].nodeType == 1 )
+ str += nav(nodes[i].childNodes);
+ return str;
+ }
+ },
+ set textContent(text){
+ while (this.firstChild)
+ this.removeChild( this.firstChild );
+ this.appendChild( this.ownerDocument.createTextNode(text));
+ },
+
+ style: {},
+ clientHeight: 0,
+ clientWidth: 0,
+ offsetHeight: 0,
+ offsetWidth: 0,
+
+ get disabled() {
+ var val = this.getAttribute("disabled");
+ return val != "false" && !!val;
+ },
+ set disabled(val) { return this.setAttribute("disabled",val); },
+
+ get checked() {
+ var val = this.getAttribute("checked");
+ return val != "false" && !!val;
+ },
+ set checked(val) { return this.setAttribute("checked",val); },
+
+ get selected() {
+ if ( !this._selectDone ) {
+ this._selectDone = true;
+
+ if ( this.nodeName == "OPTION" && !this.parentNode.getAttribute("multiple") ) {
+ var opt = this.parentNode.getElementsByTagName("option");
+
+ if ( this == opt[0] ) {
+ var select = true;
+
+ for ( var i = 1; i < opt.length; i++ )
+ if ( opt[i].selected ) {
+ select = false;
+ break;
+ }
+
+ if ( select )
+ this.selected = true;
+ }
+ }
+ }
+
+ var val = this.getAttribute("selected");
+ return val != "false" && !!val;
+ },
+ set selected(val) { return this.setAttribute("selected",val); },
+
+ get className() { return this.getAttribute("class") || ""; },
+ set className(val) {
+ return this.setAttribute("class",
+ val.replace(/(^\s*|\s*$)/g,""));
+ },
+
+ get type() { return this.getAttribute("type") || ""; },
+ set type(val) { return this.setAttribute("type",val); },
+
+ get value() { return this.getAttribute("value") || ""; },
+ set value(val) { return this.setAttribute("value",val); },
+
+ get src() { return this.getAttribute("src") || ""; },
+ set src(val) { return this.setAttribute("src",val); },
+
+ get id() { return this.getAttribute("id") || ""; },
+ set id(val) { return this.setAttribute("id",val); },
+
+ getAttribute: function(name){
+ return this._dom.hasAttribute(name) ?
+ new String( this._dom.getAttribute(name) ) :
+ null;
+ },
+ setAttribute: function(name,value){
+ this._dom.setAttribute(name,value);
+ },
+ removeAttribute: function(name){
+ this._dom.removeAttribute(name);
+ },
+
+ get childNodes(){
+ return new DOMNodeList( this._dom.getChildNodes() );
+ },
+ get firstChild(){
+ return makeNode( this._dom.getFirstChild() );
+ },
+ get lastChild(){
+ return makeNode( this._dom.getLastChild() );
+ },
+ appendChild: function(node){
+ this._dom.appendChild( node._dom );
+ },
+ insertBefore: function(node,before){
+ this._dom.insertBefore( node._dom, before ? before._dom : before );
+ },
+ removeChild: function(node){
+ this._dom.removeChild( node._dom );
+ },
+
+ getElementsByTagName: DOMDocument.prototype.getElementsByTagName,
+
+ addEventListener: window.addEventListener,
+ removeEventListener: window.removeEventListener,
+ dispatchEvent: window.dispatchEvent,
+
+ click: function(){
+ var event = document.createEvent();
+ event.initEvent("click");
+ this.dispatchEvent(event);
+ },
+ submit: function(){
+ var event = document.createEvent();
+ event.initEvent("submit");
+ this.dispatchEvent(event);
+ },
+ focus: function(){
+ var event = document.createEvent();
+ event.initEvent("focus");
+ this.dispatchEvent(event);
+ },
+ blur: function(){
+ var event = document.createEvent();
+ event.initEvent("blur");
+ this.dispatchEvent(event);
+ },
+ get elements(){
+ return this.getElementsByTagName("*");
+ },
+ get contentWindow(){
+ return this.nodeName == "IFRAME" ? {
+ document: this.contentDocument
+ } : null;
+ },
+ get contentDocument(){
+ if ( this.nodeName == "IFRAME" ) {
+ if ( !this._doc )
+ this._doc = new DOMDocument(
+ new java.io.ByteArrayInputStream((new java.lang.String(
+ "<html><head><title></title></head><body></body></html>"))
+ .getBytes("UTF8")));
+ return this._doc;
+ } else
+ return null;
+ }
+ });
+
+ // Helper method for extending one object with another
+
+ function extend(a,b) {
+ for ( var i in b ) {
+ var g = b.__lookupGetter__(i), s = b.__lookupSetter__(i);
+
+ if ( g || s ) {
+ if ( g )
+ a.__defineGetter__(i, g);
+ if ( s )
+ a.__defineSetter__(i, s);
+ } else
+ a[i] = b[i];
+ }
+ return a;
+ }
+
+ // Helper method for generating the right
+ // DOM objects based upon the type
+
+ var obj_nodes = new java.util.HashMap();
+
+ function makeNode(node){
+ if ( node ) {
+ if ( !obj_nodes.containsKey( node ) )
+ obj_nodes.put( node, node.getNodeType() ==
+ Packages.org.w3c.dom.Node.ELEMENT_NODE ?
+ new DOMElement( node ) : new DOMNode( node ) );
+
+ return obj_nodes.get(node);
+ } else
+ return null;
+ }
+
+ // XMLHttpRequest
+ // Originally implemented by Yehuda Katz
+
+ window.XMLHttpRequest = function(){
+ this.headers = {};
+ this.responseHeaders = {};
+ };
+
+ XMLHttpRequest.prototype = {
+ open: function(method, url, async, user, password){
+ this.readyState = 1;
+ if (async)
+ this.async = true;
+ this.method = method || "GET";
+ this.url = url;
+ this.onreadystatechange();
+ },
+ setRequestHeader: function(header, value){
+ this.headers[header] = value;
+ },
+ getResponseHeader: function(header){ },
+ send: function(data){
+ var self = this;
+
+ function makeRequest(){
+ var url = new java.net.URL(curLocation, self.url);
+
+ if ( url.getProtocol() == "file" ) {
+ if ( self.method == "PUT" ) {
+ var out = new java.io.FileWriter(
+ new java.io.File( new java.net.URI( url.toString() ) ) ),
+ text = new java.lang.String( data || "" );
+
+ out.write( text, 0, text.length() );
+ out.flush();
+ out.close();
+ } else if ( self.method == "DELETE" ) {
+ var file = new java.io.File( new java.net.URI( url.toString() ) );
+ file["delete"]();
+ } else {
+ var connection = url.openConnection();
+ connection.connect();
+ handleResponse();
+ }
+ } else {
+ var connection = url.openConnection();
+
+ connection.setRequestMethod( self.method );
+
+ // Add headers to Java connection
+ for (var header in self.headers)
+ connection.addRequestProperty(header, self.headers[header]);
+
+ connection.connect();
+
+ // Stick the response headers into responseHeaders
+ for (var i = 0; ; i++) {
+ var headerName = connection.getHeaderFieldKey(i);
+ var headerValue = connection.getHeaderField(i);
+ if (!headerName && !headerValue) break;
+ if (headerName)
+ self.responseHeaders[headerName] = headerValue;
+ }
+
+ handleResponse();
+ }
+
+ function handleResponse(){
+ self.readyState = 4;
+ self.status = parseInt(connection.responseCode) || undefined;
+ self.statusText = connection.responseMessage || "";
+
+ var stream = new java.io.InputStreamReader(connection.getInputStream()),
+ buffer = new java.io.BufferedReader(stream), line;
+
+ while ((line = buffer.readLine()) != null)
+ self.responseText += line;
+
+ self.responseXML = null;
+
+ if ( self.responseText.match(/^\s*</) ) {
+ try {
+ self.responseXML = new DOMDocument(
+ new java.io.ByteArrayInputStream(
+ (new java.lang.String(
+ self.responseText)).getBytes("UTF8")));
+ } catch(e) {}
+ }
+ }
+
+ self.onreadystatechange();
+ }
+
+ if (this.async)
+ (new java.lang.Thread(new java.lang.Runnable({
+ run: makeRequest
+ }))).start();
+ else
+ makeRequest();
+ },
+ abort: function(){},
+ onreadystatechange: function(){},
+ getResponseHeader: function(header){
+ if (this.readyState < 3)
+ throw new Error("INVALID_STATE_ERR");
+ else {
+ var returnedHeaders = [];
+ for (var rHeader in this.responseHeaders) {
+ if (rHeader.match(new Regexp(header, "i")))
+ returnedHeaders.push(this.responseHeaders[rHeader]);
+ }
+
+ if (returnedHeaders.length)
+ return returnedHeaders.join(", ");
+ }
+
+ return null;
+ },
+ getAllResponseHeaders: function(header){
+ if (this.readyState < 3)
+ throw new Error("INVALID_STATE_ERR");
+ else {
+ var returnedHeaders = [];
+
+ for (var header in this.responseHeaders)
+ returnedHeaders.push( header + ": " + this.responseHeaders[header] );
+
+ return returnedHeaders.join("\r\n");
+ }
+ },
+ async: true,
+ readyState: 0,
+ responseText: "",
+ status: 0
+ };
+})();
diff --git a/emacs.d/nxhtml/related/flymake-css.el b/emacs.d/nxhtml/related/flymake-css.el
new file mode 100644
index 0000000..d80abe3
--- /dev/null
+++ b/emacs.d/nxhtml/related/flymake-css.el
@@ -0,0 +1,161 @@
+;;; flymake-css.el --- Flymake setup for css files
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2009-11-21 Sat
+;; Version:
+;; Last-Updated:
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; See variable `flymake-css-validator-jar' for instructions for how
+;; to set this up.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+
+(require 'flymake)
+(require 'xml)
+
+
+(defcustom flymake-allowed-css-file-name-masks '(("\\.css\\'" flymake-css-init))
+ "Filename extensions that switch on js syntax checks."
+ :type '(repeat (list (regexp :tag "File name regexp")
+ (function :tag "Init function")
+ (choice (const :tag "No cleanup function" nil)
+ (function :tag "Cleanup function"))))
+ :group 'flymake)
+
+
+(defvar flymake-css-err-line-pattern-re '(("^file:\\([^:]+\\):\\([^:]+\\):\\(.*\\)" 1 2 nil 3))
+ "Regexp matching CSS error messages")
+
+(defcustom flymake-css-validator-jar "~/bin/css-validator.jar"
+ "Full path to css-validor.jar file.
+You need the css-validator.jar and some other files for flymake
+for CSS to work. The instructions below tell you how to get and
+install it. The instructions are copied from
+
+ http://www.emacswiki.org/emacs/FlymakeCSS
+
+Get http://www.w3.org/QA/Tools/css-validator/css-validator.jar
+create a directory named ‘lib’ in the same directory. Copy to the
+‘lib’ dir the following jars:
+
+ * commons-collections-3.2.1.jar
+ * jigsaw.jar
+ * velocity-1.6.1.jar
+ * xml-apis.jar
+ * commons-lang-2.4.jar
+ * tagsoup-1.2.jar
+ * xercesImpl.jar
+
+From:
+
+ URL `http://jigsaw.w3.org/Distrib/jigsaw_2.2.6.tar.gz'
+ URL `http://www.apache.org/dist/commons/collections/binaries/commons-collections-3.2.1-bin.tar.gz'
+ URL `http://www.apache.org/dist/commons/lang/binaries/commons-lang-2.4-bin.tar.gz'
+ URL `http://www.apache.org/dist/velocity/engine/1.6.1/velocity-1.6.1.tar.gz'
+ URL `http://www.apache.org/dist/xerces/j/Xerces-J-bin.2.9.1.tar.gz'
+ URL `http://home.ccil.org/~cowan/XML/tagsoup/tagsoup-1.2.jar'
+
+Test validating some CSS file by running:
+
+ java -jar css-validator.jar file:somecssfile.css"
+ :type 'file
+ :group 'flymake)
+;;(setq flymake-css-validator-jar "c:/dl/programs/css-valid/css-validator.jar")
+
+(defun flymake-css-init ()
+ (let* ((temp-file (flymake-init-create-temp-buffer-copy
+ 'flymake-create-temp-inplace))
+ (local-file (file-relative-name
+ temp-file
+ (file-name-directory buffer-file-name))))
+ (unless (file-exists-p flymake-css-validator-jar)
+ (error "Can't find css-validator.jar: %s\n\nPlease customize option flymake-css-validator-jar\n"
+ flymake-css-validator-jar))
+ (list "java"
+ (list "-jar" flymake-css-validator-jar
+ "-output" "gnu"
+ (concat "file:" local-file)))))
+
+;;;###autoload
+(defun flymake-css-load ()
+ (dolist (rec flymake-allowed-css-file-name-masks)
+ (add-to-list 'flymake-allowed-file-name-masks rec))
+ (dolist (rec flymake-css-err-line-pattern-re)
+ (add-to-list 'flymake-err-line-patterns rec)))
+
+
+;;(defun flymake-make-overlay (beg end tooltip-text face mouse-face)
+(defadvice flymake-make-overlay (before
+ flymake-css-ad-flymake-make-overlay
+ activate
+ compile)
+ (ad-set-arg 2 (xml-substitute-numeric-entities (ad-get-arg 2))))
+
+;; Fix-me: remove when this has been giving its proper place in Emacs.
+(eval-when-compile
+ (unless (fboundp 'xml-substitute-numeric-entities)
+ (message "Use Emacs 22 workaround for newsticker--decode-numeric-entities")
+ (defun xml-substitute-numeric-entities (string)
+ "Decode SGML numeric entities by their respective utf characters.
+This is just a copy of the function in newst-backen.el for Emacs
+22 users.
+
+This function replaces numeric entities in the input STRING and
+returns the modified string. For example \"&#42;\" gets replaced
+by \"*\"."
+ (if (and string (stringp string))
+ (let ((start 0))
+ (while (string-match "&#\\([0-9]+\\);" string start)
+ (condition-case nil
+ (setq string (replace-match
+ (string (read (substring string
+ (match-beginning 1)
+ (match-end 1))))
+ nil nil string))
+ (error nil))
+ (setq start (1+ (match-beginning 0))))
+ string)
+ nil))
+ ))
+
+;;(eval-after-load 'css-mode (flymake-css-load))
+
+(provide 'flymake-css)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; flymake-css.el ends here
diff --git a/emacs.d/nxhtml/related/flymake-helpers.el b/emacs.d/nxhtml/related/flymake-helpers.el
new file mode 100644
index 0000000..34468d5
--- /dev/null
+++ b/emacs.d/nxhtml/related/flymake-helpers.el
@@ -0,0 +1,78 @@
+;;; flymake-helpers.el --- Helper functions for flymake
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2008-07-21T14:30:20+0200 Mon
+;; Version:
+;; Last-Updated:
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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 2, 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(eval-when-compile (require 'flymake))
+
+;; (flymake-create-temp-intemp buffer-file-name nil)
+(defun flymake-create-temp-intemp (file-name prefix)
+ "Return file name in temporary directory for checking FILE-NAME.
+This is a replacement for `flymake-create-temp-inplace'. The
+only difference is that it gives a file name in
+`temporary-file-directory' instead of the same directory as
+FILE-NAME.
+
+For the use of PREFIX see that function.
+
+Note that not making the temporary file in another directory
+\(like here) will not work if the file you are checking depends
+on relative paths to other files \(for the type of checks flymake
+makes)."
+ (unless (stringp file-name)
+ (error "Invalid file-name"))
+ (or prefix
+ (setq prefix "flymake"))
+ (let* ((prefix (concat
+ (file-name-nondirectory (file-name-sans-extension file-name))
+ "_" prefix))
+ (suffix (concat "." (file-name-extension file-name)))
+ (temp-name (make-temp-file prefix nil suffix)))
+ (flymake-log 3 "create-temp-intemp: file=%s temp=%s" file-name temp-name)
+ temp-name))
+
+
+(provide 'flymake-helpers)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; flymake-helpers.el ends here
diff --git a/emacs.d/nxhtml/related/flymake-java-1.el b/emacs.d/nxhtml/related/flymake-java-1.el
new file mode 100644
index 0000000..deb1e86
--- /dev/null
+++ b/emacs.d/nxhtml/related/flymake-java-1.el
@@ -0,0 +1,109 @@
+;;; flymake-java-1.el --- Flymake for single java files
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2009-12-02 Wed
+;; Version:
+;; Last-Updated:
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(eval-and-compile (require 'flymake))
+
+(defun flymake-init-maybe-find-buildfile-dir (source-file-name buildfile-name)
+ "Find buildfile, store its dir in buffer data and return its dir, if found."
+ (let* ((buildfile-dir
+ (flymake-find-buildfile buildfile-name
+ (file-name-directory source-file-name))))
+ (if buildfile-dir
+ (setq flymake-base-dir buildfile-dir)
+ (flymake-log 1 "no buildfile (%s) for %s" buildfile-name source-file-name)
+ nil)))
+
+(defun flymake-complex-make-init-impl-1 (create-temp-f use-relative-base-dir use-relative-source build-file-name get-cmdline-f)
+ "Create syntax check command line for a directly checked source file.
+Use CREATE-TEMP-F for creating temp copy."
+ (let* ((args nil)
+ (source-file-name buffer-file-name)
+ (buildfile-dir (flymake-init-maybe-find-buildfile-dir source-file-name build-file-name)))
+ (if buildfile-dir
+ (let* ((temp-source-file-name (flymake-init-create-temp-buffer-copy create-temp-f)))
+ (setq args (flymake-get-syntax-check-program-args temp-source-file-name buildfile-dir
+ use-relative-base-dir use-relative-source
+ get-cmdline-f))))
+ args))
+
+(defun flymake-complex-java-init ()
+ (or (flymake-complex-make-init-impl-1 'flymake-create-temp-with-folder-structure nil nil "Makefile" 'flymake-get-make-cmdline)
+ (flymake-complex-make-init-impl-1 'flymake-create-temp-with-folder-structure nil nil "build.xml" 'flymake-get-make-cmdline)
+ (flymake-java-1-init)))
+
+(defcustom flymake-java-1-javac "c:/Sun/SDK/jdk/bin/javac.exe"
+ "Path to javac."
+ :group 'flymake)
+
+(defun flymake-java-1-init ()
+ (if (not (executable-find flymake-java-1-javac))
+ (message "Can't find javac. Please customize flymake-java-1-javac")
+ (list flymake-java-1-javac
+ (list (flymake-init-create-temp-buffer-copy
+ 'flymake-create-temp-with-folder-structure)))))
+
+;; (defun flymake-java-1-turn-on ()
+;; (interactive)
+;; (if (not (executable-find flymake-java-1-javac))
+;; (message "Can't find javac. Please customize flymake-java-1-javac")
+;; (let ((flymake-allowed-file-name-masks
+;; '(("\\.java\\'" flymake-java-1-init flymake-simple-cleanup))))
+;; (when flymake-mode (flymake-mode -1))
+;; (flymake-mode 1))))
+
+;;;###autoload
+(defun flymake-java-1-load ()
+ (let ((jrec (assoc "\\.java\\'" flymake-allowed-file-name-masks)))
+ (setq flymake-allowed-file-name-masks
+ (delete jrec flymake-allowed-file-name-masks))
+ (setq flymake-allowed-file-name-masks
+ (cons
+ '("\\.java\\'" flymake-complex-java-init flymake-simple-java-cleanup)
+ flymake-allowed-file-name-masks))))
+
+(provide 'flymake-java-1)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; flymake-java-1.el ends here
diff --git a/emacs.d/nxhtml/related/flymake-js.el b/emacs.d/nxhtml/related/flymake-js.el
new file mode 100644
index 0000000..256eee5
--- /dev/null
+++ b/emacs.d/nxhtml/related/flymake-js.el
@@ -0,0 +1,234 @@
+;;; flymake-js.el --- Flymake setup for javascript files
+;;
+;; Author: Lennart Borgman
+;; Created: Sun Dec 02 07:52:52 2007
+;; Version:
+;; Last-Updated:
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; This library provides basic setup for using `flymake-mode' with
+;; javascript files. To use this you must have a javascript
+;; installed. There are (at least) two free javascript engines (both
+;; from Mozill) you can use, Rhino (implemented in Java) or
+;; SpiderMonkey (implemented in C). Both are supported in this
+;; library.
+;;
+;; I have not been able to find binaries for SpiderMonkeys to
+;; download. However the Rhino engine seems fast enough and is easy to
+;; install. You find them at
+;;
+;; http://www.mozilla.org/rhino/
+;; http://www.mozilla.org/js/spidermonkey/
+;;
+;; Put this file in your Emacs `load-path' and then in .emacs
+;;
+;; (require 'flymake-js)
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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 2, 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+;; Flymake JS mode
+
+(require 'flymake)
+
+(defconst flymake-js-dir
+ (file-name-directory (or load-file-name
+ (when (boundp 'bytecomp-filename) bytecomp-filename)
+ buffer-file-name))
+ "Installation directory for flymake-js.")
+
+;;;###autoload
+(defgroup flymake-js nil
+ "Customization group for flymake for javascript."
+ :group 'flymake)
+
+(defcustom flymake-allowed-js-file-name-masks '(("\\.json\\'" flymake-js-init)
+ ("\\.js\\'" flymake-js-init))
+ "Filename extensions that switch on js syntax checks."
+ :type '(repeat (list (regexp :tag "File name regexp")
+ (function :tag "Init function")
+ (choice (const :tag "No cleanup function" nil)
+ (function :tag "Cleanup function"))))
+ :group 'flymake-js)
+
+
+(defvar flymake-js-err-line-pattern-re
+ '(;; These pattern are probably for Rhino:
+ ("^js: \"\\(.+\\)\", line \\([0-9]+\\): \\(.+\\)$" 1 2 nil 3)
+ ("^js: uncaught JavaScript \\(.+\\)$" nil nil nil 1)
+ ;; For Rhino with jslint.js
+ ("^Lint at line \\([[:digit:]]+\\) character \\([[:digit:]]+\\): \\(.+\\)$" nil 1 2 3)
+ ;; These pattern are probably for SpiderMonkey:
+ ("^\\(.+\\)\:\\([0-9]+\\)\: \\(SyntaxError\:.+\\)\:$" 1 2 nil 3)
+ ("^\\(.+\\)\:\\([0-9]+\\)\: \\(strict warning: trailing comma.+\\)\:$" 1 2 nil 3))
+ "Regexp matching JavaScript error messages")
+
+(defcustom flymake-js-rhino-jar "/path/to/js.jar"
+ "Path to Rihno jar file.
+Download and install Rhino JavaScript engine from
+
+ URL `http://www.mozilla.org/rhino/'
+
+This variable should point to the file js.jar that is in the top
+directory of the Rhino dir tree. \(It was differently named
+earlier and might perhaps be renamed again.)"
+ :type '(file :must-match t)
+ :group 'flymake-js)
+
+;;(setq flymake-log-level 3)
+;;(setq flymake-js-rhino-use-jslint nil)
+(defcustom flymake-js-rhino-use-jslint nil
+ "Use jslint.js if this is non-nil.
+jslint.js will give you warnings about style things like indentation too."
+ :type 'boolean
+ :group 'flymake-js)
+
+(defcustom flymake-js-rhino-js (expand-file-name "rhino.js" flymake-js-dir)
+ "Path to rhino.js.
+Only used if `flymake-js-rhino-use-jslint' is nil.
+
+This file and env.js must be placed in the same directory. Default
+is this directory.
+
+Those files comes with Rhino, see `flymake-js-rhino-jar'."
+ :type '(file :must-match t)
+ :group 'flymake-js)
+
+(defcustom flymake-js-rhino-jslint (expand-file-name "jslint.js" flymake-js-dir)
+ "Path to jslint.js.
+Only used if `flymake-js-rhino-use-jslint' is t.
+
+If you do not have this file you can download it from URL
+`http://www.jslint.com/rhino/jslint.js'. I had to change quit(2)
+to quit(0) in it \(which seems like a bug in `flymake-mode' to
+me)."
+ :type '(file :must-match t)
+ :group 'flymake-js)
+
+;;(flymake-js-check-rhino-js)
+(defun flymake-js-check-rhino-js ()
+ "Checks that the path to env.js is ok."
+ (with-current-buffer (find-file-noselect flymake-js-rhino-js)
+ (let* ((proj-folder (file-name-as-directory (file-name-directory (buffer-file-name))))
+ (proj-line (concat "var project_folder = 'file:///" proj-folder "';"))
+ (proj-line-re "^\\W*var\\W+project_folder\\W*=\\W*"))
+ (save-restriction
+ (widen)
+ (goto-char (point-max))
+ (if (re-search-backward proj-line-re nil t)
+ (let ((beg (line-beginning-position))
+ (end (line-end-position)))
+ (unless (string= (buffer-substring-no-properties beg end)
+ proj-line)
+ (delete-region beg end)
+ (insert proj-line)
+ (basic-save-buffer)))
+ (goto-char (point-min))
+ (insert proj-line "\n")
+ (basic-save-buffer))))))
+
+(defcustom flymake-js-engine 'rhino
+ "Javascript engine to use.
+You may have to restart Emacs after changing this - if you can
+not figure out what buffers and processes to kill.
+
+I have only been able to test Rhino since I do not have
+SpiderMonkey."
+ :type '(choice (const :tag "Rhino" rhino)
+ (const :tag "SpiderMonkey" spidermonkey))
+ :group 'flymake-js)
+
+(defun flymake-js-init ()
+ (message "running flymake-js-init")
+ (let* ((temp-file (flymake-init-create-temp-buffer-copy
+ 'flymake-create-temp-inplace))
+ (local-file (file-relative-name
+ temp-file
+ (file-name-directory buffer-file-name))))
+ (flymake-js-check-has-engine)
+ (cond
+ ((eq flymake-js-engine 'rhino)
+ (list "java" (list "-jar" flymake-js-rhino-jar
+ (if flymake-js-rhino-use-jslint
+ flymake-js-rhino-jslint
+ flymake-js-rhino-js)
+ local-file)))
+ ((eq flymake-js-engine 'spidermonkey)
+ (list "js" (list "-s" local-file)))
+ (t
+ (error "Bad value: %s" flymake-js-engine)))))
+
+(defvar flymake-js-has-engine nil)
+
+(defun flymake-js-check-has-engine ()
+ "Check for the needed files."
+ (if flymake-js-has-engine
+ t
+ (cond
+ ;; Rhino
+ ((eq flymake-js-engine 'rhino)
+ (unless (executable-find "java")
+ (error "Could not find java executable"))
+ (unless (file-exists-p flymake-js-rhino-jar)
+ (error "Could not find file %s\n\nPlease customize flymake-js-rhino-jar\n"
+ flymake-js-rhino-jar))
+ (if flymake-js-rhino-use-jslint
+ (unless (file-exists-p flymake-js-rhino-jslint)
+ (error "Could not find file %s" flymake-js-rhino-jslint))
+ (unless (file-exists-p flymake-js-rhino-js)
+ (error "Could not find file %s" flymake-js-rhino-js))
+ (flymake-js-check-rhino-js)))
+ ;; SpiderMonkey
+ ((eq flymake-js-engine 'spidermonkey)
+ (unless (executable-find "js")
+ (error "Could not find js program")))
+ (t
+ (error "Bad value: %s" flymake-js-engine)))
+ (setq flymake-js-has-engine t)))
+
+;;;###autoload
+(defun flymake-js-load ()
+ (dolist (rec flymake-allowed-js-file-name-masks)
+ (add-to-list 'flymake-allowed-file-name-masks rec))
+ (dolist (rec flymake-js-err-line-pattern-re)
+ (add-to-list 'flymake-err-line-patterns rec)))
+
+;;(eval-after-load 'javascript (flymake-js-load))
+
+(provide 'flymake-js)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; flymake-js.el<2> ends here
diff --git a/emacs.d/nxhtml/related/flymakemsg.el b/emacs.d/nxhtml/related/flymakemsg.el
new file mode 100644
index 0000000..b704ba7
--- /dev/null
+++ b/emacs.d/nxhtml/related/flymakemsg.el
@@ -0,0 +1,144 @@
+;;; flymakemsg.el --- Show flymake compile errors in echo area
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2009-11-21 Sat
+;; Version: 0.1
+;; Last-Updated: 2009-11-21 Sat
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+ ;; `backquote', `bytecomp'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Show flymake error messages in minibuffer when point is on a
+;; flymake error overlay.
+;;
+;; To use it just load this file. Put this in .emacs:
+;;
+;; (require 'flymakemsg)
+;;
+;; This file run `defadvice' on some functions in `flymake-mode'.
+;; This code started from an idea in a paste.
+;;
+;; Note: This code breaks Emacs conventions since it does the
+;; defadvising when you just loads this file.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(eval-when-compile (require 'flymake))
+
+(defun flymakemsg-show-err-at-point ()
+ "If point is on a flymake error, show it in echo area.
+Protected to run in timers and hooks."
+ (condition-case err
+ (flymakemsg-show-err-at-point-1)
+ (error (message "%s" err))))
+
+(defvar flymakemsg-last-errovl nil)
+
+(defun flymakemsg-show-err-at-point-1 ()
+ "If point is on a flymake error, show it in echo area."
+ (interactive)
+ (when flymake-mode
+ (let ((flyovl (flymakemsg-get-errovl (point))))
+ (unless (eq flyovl flymakemsg-last-errovl)
+ (setq flymakemsg-last-errovl flyovl)
+ (when flyovl
+ (message "%s" (propertize
+ (overlay-get flyovl 'help-echo)
+ 'face 'flymake-errline)))))))
+
+(defun flymakemsg-get-errovl (POS)
+ "Get flymake error overlay at POS."
+ (catch 'errovl
+ (dolist (ovl (overlays-at POS))
+ (when (eq 'flymake-errline (overlay-get ovl 'face))
+ (throw 'errovl ovl)))))
+
+(defadvice flymake-mode (after
+ flymakemsg-ad-flymake-mode
+ activate compile)
+ "Turn on showing of flymake errors then point is on them.
+This shows the error in the echo area."
+ (if flymake-mode
+ nil ;;(add-hook 'post-command-hook 'flymakemsg-post-command t t)
+ (remove-hook 'post-command-hook 'flymakemsg-post-command t)))
+
+(defadvice flymake-log (after
+ flymakemsg-ad-flymake-log
+ activate compile)
+ "Display error on current line if any."
+ ;;(message "flymake-log defadvice called")
+ (if (not flymake-err-info)
+ (remove-hook 'post-command-hook 'flymakemsg-post-command t)
+ (add-hook 'post-command-hook 'flymakemsg-post-command t t)
+ ;; Wait, because there is another message first.
+ (flymakemsg-start-msg-timer 3.0)))
+
+(defun flymakemsg-post-command ()
+ ;; Wait to not disturb to much.
+ (flymakemsg-start-msg-timer 0.2))
+
+(defvar flymakemsg-msg-timer nil)
+
+(defun flymakemsg-cancel-msg-timer ()
+ (when (timerp flymakemsg-msg-timer)
+ (cancel-timer flymakemsg-msg-timer)))
+
+(defun flymakemsg-start-msg-timer (delay)
+ (flymakemsg-cancel-msg-timer)
+ (run-with-idle-timer delay nil 'flymakemsg-show-err-at-point))
+
+;;; I have no idea why it was done the way below. It was in the paste.
+;;; It seems very unnecessary but I keep it for now.
+;;
+;; (defun fly-pyflake-determine-message (err)
+;; "pyflake is flakey if it has compile problems, this adjusts the
+;; message to display, so there is one ;)"
+;; (cond ((not (or (eq major-mode 'Python) (eq major-mode 'python-mode) t)))
+;; ((null (flymake-ler-file err))
+;; ;; normal message do your thing
+;; (flymake-ler-text err))
+;; (t ;; could not compile err
+;; (format "compile error, problem on line %s" (flymake-ler-line err)))))
+
+;; (let ((line-no (line-number-at-pos)))
+;; (dolist (elem flymake-err-info)
+;; (if (eq (car elem) line-no)
+;; (let ((err (car (second elem))))
+;; (message "%s" (fly-pyflake-determine-message err))))))
+
+
+(provide 'flymakemsg)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; flymakemsg.el ends here
diff --git a/emacs.d/nxhtml/related/flymu.el b/emacs.d/nxhtml/related/flymu.el
new file mode 100644
index 0000000..6b3a552
--- /dev/null
+++ b/emacs.d/nxhtml/related/flymu.el
@@ -0,0 +1,157 @@
+;;; flymu.el --- Flymake for mumamo-mode
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: Sun Dec 02 14:52:32 2007
+;; Version: 0.1
+;; Last-Updated:
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+;; None
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Flymake syntax checks for mumamo chunks.
+;;
+;; Not ready yet!!!
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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 2, 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(require 'flymake)
+
+;;(flymu-make-major-mode-alist)
+(defun flymu-make-major-mode-alist ()
+ "Grab values from `flymake-allowed-file-name-masks'.
+We need a list of major modes and the corresponding init and
+cleanup functions for flymake. This functions creates such a list
+from flymakes dito list for file names."
+ (let ((allowed nil))
+ (save-match-data
+ (dolist (regexp-init flymake-allowed-file-name-masks)
+ (let* ((regexp (car regexp-init))
+ (init (cdr regexp-init))
+ ;; Make it as simple as possible. First see if the same
+ ;; regexp is used:
+ (mode (let ((m (cdr (assoc regexp auto-mode-alist))))
+ ;; Don't use this if it is complicated:
+ (when (commandp m) m)))
+ (ext regexp))
+ (unless mode
+ ;; Try to make a simple file name, this could be made
+ ;; better but I do not know if that would be meaningful:
+ (setq ext (replace-regexp-in-string "\\\\\\." "." ext))
+ (setq ext (replace-regexp-in-string "\\\\'" "" ext))
+ (setq ext (replace-regexp-in-string "[\\$?+*]" "" ext))
+ ;; Next compare the filename against the entries in
+ ;; auto-mode-alist. The code is from `set-auto-mode'.
+ (let ((name ext)
+ (done nil))
+ (while name
+ ;; Find first matching alist entry.
+ (setq mode
+ (if (memq system-type '(vax-vms windows-nt cygwin))
+ ;; System is case-insensitive.
+ (let ((case-fold-search t))
+ (assoc-default name auto-mode-alist
+ 'string-match))
+ ;; System is case-sensitive.
+ (or
+ ;; First match case-sensitively.
+ (let ((case-fold-search nil))
+ (assoc-default name auto-mode-alist
+ 'string-match))
+ ;; Fallback to case-insensitive match.
+ (and auto-mode-case-fold
+ (let ((case-fold-search t))
+ (assoc-default name auto-mode-alist
+ 'string-match))))))
+ (if (and mode
+ (consp mode)
+ (cadr mode))
+ (setq name (substring name 0 (match-beginning 0)))
+ (setq name)))))
+ (when (and mode
+ ;; nxml-mode's do not need flymake:
+ (let ((major-mode mode))
+ (not (derived-mode-p 'nxml-mode))))
+ (let ((rec (append (list mode) init)))
+ (when (= (length rec) 2)
+ (setq rec (append rec (list nil))))
+ (add-to-list 'allowed rec))))))
+ allowed))
+
+(defcustom flymu-allowed-major-modes (flymu-make-major-mode-alist)
+ "Major modes syntax checking is allowed for."
+ :type '(repeat (list (function :tag "Major mode")
+ (function :tag "Init function")
+ (choice (const :tag "No cleanup function" nil)
+ (function :tag "Cleanup function"))))
+ :set-after '(flymake-allowed-file-name-masks)
+ :group 'flymu)
+
+(defvar flymu-mumamo-chunk nil)
+(make-variable-buffer-local 'flymu-mumamo-chunk)
+
+
+;; Fix-me: What to check? When? Make flymu-mumamo-chunk a function
+;; instead? Mark chunks for checking - let mumamo do that? Flymake
+;; should be able to mark a chunk to, even if it is not a whole
+;; line. What about line numbers?
+
+;; Advice these functions:
+(defadvice flymake-get-file-name-mode-and-masks (around
+ flymu-ad-flymake-get-file-name-mode-and-masks
+ (file-name))
+ "Make flymake init file selection according to mode."
+ (if flymu-mumamo-chunk
+ (let ((major (overlay-get ovl 'mumamo-major-mode))
+ (rec (assq major flymu-allowed-major-modes)))
+ (when rec
+ (setq ad-return-value (cdr rec))))
+ ad-do-it))
+(ad-activate 'flymake-get-file-name-mode-and-masks)
+
+;;(defun flymake-save-buffer-in-file (file-name)
+(defadvice flymake-save-buffer-in-file (around
+ flymu-ad-flymake-save-buffer-in-file
+ (file-name))
+ (if flymu-mumamo-chunk
+ (let ((min (overlay-start flymu-mumamo-chunk))
+ (max (overlay-end flymu-mumamo-chunk)))
+ (make-directory (file-name-directory file-name) 1)
+ (write-region min max file-name nil 566)
+ (flymake-log 3 "saved chunk %s:%s-%s in file %s" (buffer-name) min ma file-name))
+ ad-do-it))
+
+(provide 'flymu)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; flymu.el ends here
diff --git a/emacs.d/nxhtml/related/iss-mode.el b/emacs.d/nxhtml/related/iss-mode.el
new file mode 100644
index 0000000..7e498c0
--- /dev/null
+++ b/emacs.d/nxhtml/related/iss-mode.el
@@ -0,0 +1,205 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; iss-mode.el --- Mode for InnoSetup install scripts
+
+;; Copyright (C) 2000-2007 by Stefan Reichoer
+
+;; Emacs Lisp Archive Entry
+;; Filename: iss-mode.el
+;; Author: Stefan Reichoer, <stefan@xsteve.at>
+;; Version: 1.1d
+
+;; iss-mode.el 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 2, or (at your option)
+;; any later version.
+
+;; iss-mode.el 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary
+
+;; InnoSetup is an Application Installer for Windows
+;; See: http://www.jrsoftware.org/isinfo.php
+;; This version of iss-mode.el is tested with InnoSetup v5.0
+
+;; iss-mode provides the following features:
+;; * Syntax coloring for InnoSetup scripts
+;; * Integration of the InnoSetup commandline compiler iscc.exe
+;; - Compilation via M-x iss-compile
+;; - Jump to compilation error via M-x next-error
+;; * Start Innosetup help via M-x iss-compiler-help
+;; * Test the installation via M-x iss-run-installer
+
+;; Of course you can bind this commands to keys (e.g. in the iss-mode-hook)
+
+;; My initialization for InnoSetup looks like this:
+;; (autoload 'iss-mode "iss-mode" "Innosetup Script Mode" t)
+;; (setq auto-mode-alist (append '(("\\.iss$" . iss-mode)) auto-mode-alist))
+;; (setq iss-compiler-path "c:/Programme/Inno Setup 5/")
+;; (add-hook 'iss-mode-hook 'xsteve-iss-mode-init)
+;; (defun xsteve-iss-mode-init ()
+;; (interactive)
+;; (define-key iss-mode-map [f6] 'iss-compile)
+;; (define-key iss-mode-map [(meta f6)] 'iss-run-installer)))
+
+;; The latest version of iss-mode.el can be found at:
+;; http://www.xsteve.at/prg/emacs/iss-mode.el
+
+;; Comments / suggestions welcome!
+
+;;; Change log:
+;;
+;; Version 1.1e:
+;;
+;; - Add some new flags to keywords
+
+;;; Code:
+
+(eval-and-compile (require 'compile))
+
+(defvar iss-compiler-path nil "Path to the iss compiler")
+
+;;; End of user settings
+
+(defvar iss-mode-syntax-table
+ (let ((table (make-syntax-table)))
+ ;; ";" starts a comment
+ ;;(modify-syntax-entry ?\; "<" iss-mode-syntax-table)
+ (modify-syntax-entry ?\; ". 12" table)
+ ;; and \n and \^M end a comment
+ (modify-syntax-entry ?\n ">" table)
+ (modify-syntax-entry ?\^M ">" table)
+
+ (modify-syntax-entry ?\" "." table)
+
+ (modify-syntax-entry ?_ "w" table)
+ table)
+ "Syntax table in use in iss-mode buffers.")
+
+
+(defvar iss-font-lock-keywords
+ (list
+ (cons (concat "^;\.*")
+ 'font-lock-comment-face)
+ (cons (concat "\\sw+: ")
+ 'font-lock-keyword-face)
+ (cons "^[ \t]*\\[\.+\\]" 'font-lock-function-name-face) ;font-lock-constant-face)
+ (cons "^[ \t]*#include[ \t]*\".+\"" 'font-lock-preprocessor-face)
+ (cons (concat "^[ \t]*\\<\\(appname\\|appvername\\|appversion\\|appcopyright\\|appid\\|"
+ "appmutex\\|beveledlabel\\|defaultdirname\\|versioninfoversion"
+ "\\|defaultgroupname\\|minversion\\|outputdir\\|outputbasefilename\\|"
+ "allownoicons\\|uninstallfilesdir\\|"
+ "sourcedir\\|disableprogramgrouppage\\|alwayscreateuninstallicon\\)\\>")
+ 'font-lock-type-face)
+ (cons (concat "\\<\\(alwaysskipifsameorolder\\|uninsneveruninstall\\|"
+ "comparetimestampalso\\|restartreplace\\|isreadme\\|"
+ "unchecked\\|nowait\\|postinstall\\|skipifsilent\\|ignoreversion\\|"
+ "uninsdeletekeyifempty\\|uninsdeletekey\\|"
+ "runasoriginaluser\\|runascurrentuser"
+ "\\)\\>")
+ 'font-lock-variable-name-face)
+ (cons (concat "\\<\\(HKCU\\|HKLM\\|dirifempty\\|files\\|filesandordirs\\)\\>")
+ 'font-lock-constant-face)
+ (list 'iss-fontify-options '(1 'font-lock-variable-name-face) '(2 'font-lock-keyword-face))
+ )
+ "Expressions to highlight in iss mode.")
+
+(defun iss-fontify-options (bound)
+ (message "iss-fontify-options %s" bound)
+ (when (re-search-forward "^[ \t]*\\([^=]+\\)[ \t]*\\(=\\)" bound t)
+ (match-data)))
+
+(defvar iss-mode-map (make-sparse-keymap)
+ "Keymap used in iss-mode buffers.")
+
+(easy-menu-define
+ iss-menu
+ iss-mode-map
+ "InnoSetup script menu"
+ (list
+ "ISS"
+ ["Compile" (iss-compile) t]
+ ["Run Installer" (iss-run-installer) t]
+ ["InnoSetup Help" (iss-compiler-help) t]
+ ))
+(easy-menu-add iss-menu)
+
+(defvar compilation-file-regexp-alist) ;; silence compiler, don't know the var.
+
+;;;###autoload
+(defun iss-mode ()
+ "Major mode for editing InnoSetup script files. Upon startup iss-mode-hook is run."
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map iss-mode-map)
+ (setq major-mode 'iss-mode)
+ (setq mode-name "iss")
+ (set-syntax-table iss-mode-syntax-table)
+ (set (make-local-variable 'comment-start) ";")
+ (set (make-local-variable 'comment-end) "")
+ (set (make-local-variable 'comment-multi-line) nil)
+
+ (set (make-local-variable 'compilation-error-regexp-alist)
+ '(("\\(Error on line\\) \\([0-9]+\\):" nil 2)))
+ (set (make-local-variable 'compilation-file-regexp-alist)
+ '(("iscc \\(.*\\)$" 1)))
+
+ ;; Font lock support
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '(iss-font-lock-keywords nil t))
+ (run-hooks 'iss-mode-hook))
+
+(defun iss-compiler-help ()
+ "Start the online documentation for the InnoSetup compiler"
+ (interactive)
+ (let ((default-directory (or iss-compiler-path default-directory)))
+ (w32-shell-execute 1 "ISetup.chm")))
+
+(defun iss-compile ()
+ "Compile the actual file with the InnoSetup compiler"
+ (interactive)
+ (let ((default-directory (or iss-compiler-path default-directory))
+ (compilation-process-setup-function 'iss-process-setup))
+ (compile (concat "iscc " (buffer-file-name)))))
+
+(defun iss-process-setup ()
+ "Set up `compilation-exit-message-function' for `iss-compile'."
+ (set (make-local-variable 'compilation-exit-message-function)
+ 'iss-compilation-exit-message-function))
+
+(defun iss-compilation-exit-message-function (process-status exit-status msg)
+ (interactive)
+ (save-excursion
+ (let ((buffer-read-only nil))
+ (goto-char (point-min))
+ ;;scroll down one line, so that the compile command is parsed to:
+ ;; -> get the filename of the compiled file
+ (insert "\n")))
+ (cons msg exit-status))
+
+(defun iss-find-option (option)
+ (let ((search-regexp
+ (concat option "[ \t]*=[ \t]*\\(.*\\)$")))
+ (save-excursion
+ (goto-char (point-min))
+ (when (search-forward-regexp search-regexp nil t)
+ (buffer-substring-no-properties (match-beginning 1) (match-end 1))))))
+
+(defun iss-run-installer ()
+ (interactive)
+ (let ((executable
+ (concat (or (iss-find-option "outputdir") "Output\\")
+ (or (iss-find-option "outputbasefilename") "setup")
+ ".exe")))
+ (w32-shell-execute 1 executable)))
+
+(provide 'iss-mode)
+
+;; arch-tag: b07b7119-d591-465e-927f-d0be0bcf7cab
diff --git a/emacs.d/nxhtml/related/iss-mumamo.el b/emacs.d/nxhtml/related/iss-mumamo.el
new file mode 100644
index 0000000..85e067c
--- /dev/null
+++ b/emacs.d/nxhtml/related/iss-mumamo.el
@@ -0,0 +1,70 @@
+;;; iss-mumamo.el --- Defines multi major mode for Inno Setup files
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2008-08-09
+;; Version: 0.3
+;; Last-Updated: 2009-12-12 Sat
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+ ;; `comint', `compile', `iss-mode', `ring', `tool-bar'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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 2, 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(require 'iss-mode)
+(require 'mumamo)
+
+(defun mumamo-chunk-iss-code (pos min max)
+ "Find [code]..., return range and `pascal-mode'.
+See `mumamo-find-possible-chunk' for POS, MIN and MAX.
+
+Note that if this section is not the last"
+ (mumamo-quick-static-chunk pos min max "[code]" "{*** End of CODE **}" t 'pascal-mode t))
+
+;;;###autoload
+(define-mumamo-multi-major-mode iss-mumamo-mode
+ "Turn on multiple major modes Inno Setup .iss files.
+The main major mode will be `iss-mode'.
+The [code] section, if any, will be in `pascal-mode'."
+ ("Inno ISS Family" iss-mode
+ (mumamo-chunk-iss-code
+ )))
+
+(add-to-list 'auto-mode-alist '("\\.iss\\'" . iss-mumamo-mode))
+
+(provide 'iss-mumamo)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; iss-mumamo.el ends here
diff --git a/emacs.d/nxhtml/related/js_temp.js b/emacs.d/nxhtml/related/js_temp.js
new file mode 100644
index 0000000..a2c6748
--- /dev/null
+++ b/emacs.d/nxhtml/related/js_temp.js
@@ -0,0 +1,4 @@
+
+ // I am testing
+
+ var x == 10;
diff --git a/emacs.d/nxhtml/related/jslint.js b/emacs.d/nxhtml/related/jslint.js
new file mode 100644
index 0000000..fb89c06
--- /dev/null
+++ b/emacs.d/nxhtml/related/jslint.js
@@ -0,0 +1,523 @@
+// (C)2002 Douglas Crockford
+// www.JSLint.com
+// Rhino Edition
+"use strict";var JSLINT=(function(){var adsafe_id,adsafe_may,adsafe_went,anonname,approved,atrule={media:true,'font-face':true,page:true},bang={'<':true,'<=':true,'==':true,'===':true,'!==':true,'!=':true,'>':true,'>=':true,'+':true,'-':true,'*':true,'/':true,'%':true},banned={'arguments':true,callee:true,caller:true,constructor:true,'eval':true,prototype:true,unwatch:true,valueOf:true,watch:true},boolOptions={adsafe:true,bitwise:true,browser:true,cap:true,css:true,debug:true,eqeqeq:true,evil:true,forin:true,fragment:true,immed:true,laxbreak:true,newcap:true,nomen:true,on:true,onevar:true,passfail:true,plusplus:true,regexp:true,rhino:true,undef:true,safe:true,sidebar:true,strict:true,sub:true,white:true,widget:true},browser={addEventListener:false,alert:false,blur:false,clearInterval:false,clearTimeout:false,close:false,closed:false,confirm:false,console:false,Debug:false,defaultStatus:false,document:false,event:false,focus:false,frames:false,getComputedStyle:false,history:false,Image:false,length:false,location:false,moveBy:false,moveTo:false,name:false,navigator:false,onbeforeunload:true,onblur:true,onerror:true,onfocus:true,onload:true,onresize:true,onunload:true,open:false,opener:false,opera:false,Option:false,parent:false,print:false,prompt:false,removeEventListener:false,resizeBy:false,resizeTo:false,screen:false,scroll:false,scrollBy:false,scrollTo:false,setInterval:false,setTimeout:false,status:false,top:false,XMLHttpRequest:false},cssAttributeData,cssAny,cssColorData={"aliceblue":true,"antiquewhite":true,"aqua":true,"aquamarine":true,"azure":true,"beige":true,"bisque":true,"black":true,"blanchedalmond":true,"blue":true,"blueviolet":true,"brown":true,"burlywood":true,"cadetblue":true,"chartreuse":true,"chocolate":true,"coral":true,"cornflowerblue":true,"cornsilk":true,"crimson":true,"cyan":true,"darkblue":true,"darkcyan":true,"darkgoldenrod":true,"darkgray":true,"darkgreen":true,"darkkhaki":true,"darkmagenta":true,"darkolivegreen":true,"darkorange":true,"darkorchid":true,"darkred":true,"darksalmon":true,"darkseagreen":true,"darkslateblue":true,"darkslategray":true,"darkturquoise":true,"darkviolet":true,"deeppink":true,"deepskyblue":true,"dimgray":true,"dodgerblue":true,"firebrick":true,"floralwhite":true,"forestgreen":true,"fuchsia":true,"gainsboro":true,"ghostwhite":true,"gold":true,"goldenrod":true,"gray":true,"green":true,"greenyellow":true,"honeydew":true,"hotpink":true,"indianred":true,"indigo":true,"ivory":true,"khaki":true,"lavender":true,"lavenderblush":true,"lawngreen":true,"lemonchiffon":true,"lightblue":true,"lightcoral":true,"lightcyan":true,"lightgoldenrodyellow":true,"lightgreen":true,"lightpink":true,"lightsalmon":true,"lightseagreen":true,"lightskyblue":true,"lightslategray":true,"lightsteelblue":true,"lightyellow":true,"lime":true,"limegreen":true,"linen":true,"magenta":true,"maroon":true,"mediumaquamarine":true,"mediumblue":true,"mediumorchid":true,"mediumpurple":true,"mediumseagreen":true,"mediumslateblue":true,"mediumspringgreen":true,"mediumturquoise":true,"mediumvioletred":true,"midnightblue":true,"mintcream":true,"mistyrose":true,"moccasin":true,"navajowhite":true,"navy":true,"oldlace":true,"olive":true,"olivedrab":true,"orange":true,"orangered":true,"orchid":true,"palegoldenrod":true,"palegreen":true,"paleturquoise":true,"palevioletred":true,"papayawhip":true,"peachpuff":true,"peru":true,"pink":true,"plum":true,"powderblue":true,"purple":true,"red":true,"rosybrown":true,"royalblue":true,"saddlebrown":true,"salmon":true,"sandybrown":true,"seagreen":true,"seashell":true,"sienna":true,"silver":true,"skyblue":true,"slateblue":true,"slategray":true,"snow":true,"springgreen":true,"steelblue":true,"tan":true,"teal":true,"thistle":true,"tomato":true,"turquoise":true,"violet":true,"wheat":true,"white":true,"whitesmoke":true,"yellow":true,"yellowgreen":true},cssBorderStyle,cssBreak,cssLengthData={'%':true,'cm':true,'em':true,'ex':true,'in':true,'mm':true,'pc':true,'pt':true,'px':true},cssOverflow,escapes={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','/':'\\/','\\':'\\\\'},funct,functionicity=['closure','exception','global','label','outer','unused','var'],functions,global,htmltag={a:{},abbr:{},acronym:{},address:{},applet:{},area:{empty:true,parent:' map '},b:{},base:{empty:true,parent:' head '},bdo:{},big:{},blockquote:{},body:{parent:' html noframes '},br:{empty:true},button:{},canvas:{parent:' body p div th td '},caption:{parent:' table '},center:{},cite:{},code:{},col:{empty:true,parent:' table colgroup '},colgroup:{parent:' table '},dd:{parent:' dl '},del:{},dfn:{},dir:{},div:{},dl:{},dt:{parent:' dl '},em:{},embed:{},fieldset:{},font:{},form:{},frame:{empty:true,parent:' frameset '},frameset:{parent:' html frameset '},h1:{},h2:{},h3:{},h4:{},h5:{},h6:{},head:{parent:' html '},html:{parent:'*'},hr:{empty:true},i:{},iframe:{},img:{empty:true},input:{empty:true},ins:{},kbd:{},label:{},legend:{parent:' fieldset '},li:{parent:' dir menu ol ul '},link:{empty:true,parent:' head '},map:{},menu:{},meta:{empty:true,parent:' head noframes noscript '},noframes:{parent:' html body '},noscript:{parent:' body head noframes '},object:{},ol:{},optgroup:{parent:' select '},option:{parent:' optgroup select '},p:{},param:{empty:true,parent:' applet object '},pre:{},q:{},samp:{},script:{empty:true,parent:' body div frame head iframe p pre span '},select:{},small:{},span:{},strong:{},style:{parent:' head ',empty:true},sub:{},sup:{},table:{},tbody:{parent:' table '},td:{parent:' tr '},textarea:{},tfoot:{parent:' table '},th:{parent:' tr '},thead:{parent:' table '},title:{parent:' head '},tr:{parent:' table tbody thead tfoot '},tt:{},u:{},ul:{},'var':{}},ids,implied,inblock,indent,jsonmode,lines,lookahead,member,membersOnly,nexttoken,noreach,option,predefined,prereg,prevtoken,rhino={defineClass:false,deserialize:false,gc:false,help:false,load:false,loadClass:false,print:false,quit:false,readFile:false,readUrl:false,runCommand:false,seal:false,serialize:false,spawn:false,sync:false,toint32:false,version:false},scope,sidebar={System:false},src,stack,standard={Array:false,Boolean:false,Date:false,decodeURI:false,decodeURIComponent:false,encodeURI:false,encodeURIComponent:false,Error:false,'eval':false,EvalError:false,Function:false,hasOwnProperty:false,isFinite:false,isNaN:false,JSON:false,Math:false,Number:false,Object:false,parseInt:false,parseFloat:false,RangeError:false,ReferenceError:false,RegExp:false,String:false,SyntaxError:false,TypeError:false,URIError:false},standard_member={E:true,LN2:true,LN10:true,LOG2E:true,LOG10E:true,PI:true,SQRT1_2:true,SQRT2:true,MAX_VALUE:true,MIN_VALUE:true,NEGATIVE_INFINITY:true,POSITIVE_INFINITY:true},strict_mode,syntax={},tab,token,urls,warnings,widget={alert:true,animator:true,appleScript:true,beep:true,bytesToUIString:true,Canvas:true,chooseColor:true,chooseFile:true,chooseFolder:true,closeWidget:true,COM:true,convertPathToHFS:true,convertPathToPlatform:true,CustomAnimation:true,escape:true,FadeAnimation:true,filesystem:true,Flash:true,focusWidget:true,form:true,FormField:true,Frame:true,HotKey:true,Image:true,include:true,isApplicationRunning:true,iTunes:true,konfabulatorVersion:true,log:true,md5:true,MenuItem:true,MoveAnimation:true,openURL:true,play:true,Point:true,popupMenu:true,preferenceGroups:true,preferences:true,print:true,prompt:true,random:true,Rectangle:true,reloadWidget:true,ResizeAnimation:true,resolvePath:true,resumeUpdates:true,RotateAnimation:true,runCommand:true,runCommandInBg:true,saveAs:true,savePreferences:true,screen:true,ScrollBar:true,showWidgetPreferences:true,sleep:true,speak:true,Style:true,suppressUpdates:true,system:true,tellWidget:true,Text:true,TextArea:true,Timer:true,unescape:true,updateNow:true,URL:true,Web:true,widget:true,Window:true,XMLDOM:true,XMLHttpRequest:true,yahooCheckLogin:true,yahooLogin:true,yahooLogout:true},xmode,xquote,ax=/@cc|<\/?|script|\]*s\]|<\s*!|&lt/i,cx=/[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,tx=/^\s*([(){}\[.,:;'"~\?\]#@]|==?=?|\/(\*(jslint|members?|global)?|=|\/)?|\*[\/=]?|\+[+=]?|-[\-=]?|%=?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=!]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/,hx=/^\s*(['"=>\/&#]|<(?:\/|\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\-]*|[0-9]+|--|.)/,nx=/[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,nxg=/[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,ox=/[>&]|<[\/!]?|--/,lx=/\*\/|\/\*/,ix=/^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,jx=/^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i,ux=/&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto/i,sx=/^\s*([{:#%.=,>+\[\]@()"';]|\*=?|\$=|\|=|\^=|~=|[a-zA-Z_][a-zA-Z0-9_\-]*|[0-9]+|<\/|\/\*)/,ssx=/^\s*([@#!"'};:\-%.=,+\[\]()*_]|[a-zA-Z][a-zA-Z0-9._\-]*|\/\*?|\d+(?:\.\d+)?|<\/)/,qx=/[^a-zA-Z0-9-_\/ ]/,dx=/[\[\]\/\\"'*<>.&:(){}+=#]/,rx={outer:hx,html:hx,style:sx,styleproperty:ssx};function F(){}
+if(typeof Object.create!=='function'){Object.create=function(o){F.prototype=o;return new F();};}
+function is_own(object,name){return Object.prototype.hasOwnProperty.call(object,name);}
+function combine(t,o){var n;for(n in o){if(is_own(o,n)){t[n]=o[n];}}}
+String.prototype.entityify=function(){return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');};String.prototype.isAlpha=function(){return(this>='a'&&this<='z\uffff')||(this>='A'&&this<='Z\uffff');};String.prototype.isDigit=function(){return(this>='0'&&this<='9');};String.prototype.supplant=function(o){return this.replace(/\{([^{}]*)\}/g,function(a,b){var r=o[b];return typeof r==='string'||typeof r==='number'?r:a;});};String.prototype.name=function(){if(ix.test(this)){return this;}
+if(nx.test(this)){return'"'+this.replace(nxg,function(a){var c=escapes[a];if(c){return c;}
+return'\\u'+('0000'+a.charCodeAt().toString(16)).slice(-4);})+'"';}
+return'"'+this+'"';};function assume(){if(!option.safe){if(option.rhino){combine(predefined,rhino);}
+if(option.browser||option.sidebar){combine(predefined,browser);}
+if(option.sidebar){combine(predefined,sidebar);}
+if(option.widget){combine(predefined,widget);}}}
+function quit(m,l,ch){throw{name:'JSLintError',line:l,character:ch,message:m+" ("+Math.floor((l/lines.length)*100)+"% scanned)."};}
+function warning(m,t,a,b,c,d){var ch,l,w;t=t||nexttoken;if(t.id==='(end)'){t=token;}
+l=t.line||0;ch=t.from||0;w={id:'(error)',raw:m,evidence:lines[l-1]||'',line:l,character:ch,a:a,b:b,c:c,d:d};w.reason=m.supplant(w);JSLINT.errors.push(w);if(option.passfail){quit('Stopping. ',l,ch);}
+warnings+=1;if(warnings>=option.maxerr){quit("Too many errors.",l,ch);}
+return w;}
+function warningAt(m,l,ch,a,b,c,d){return warning(m,{line:l,from:ch},a,b,c,d);}
+function error(m,t,a,b,c,d){var w=warning(m,t,a,b,c,d);quit("Stopping, unable to continue.",w.line,w.character);}
+function errorAt(m,l,ch,a,b,c,d){return error(m,{line:l,from:ch},a,b,c,d);}
+var lex=(function lex(){var character,from,line,s;function nextLine(){var at;if(line>=lines.length){return false;}
+character=1;s=lines[line];line+=1;at=s.search(/ \t/);if(at>=0){warningAt("Mixed spaces and tabs.",line,at+1);}
+s=s.replace(/\t/g,tab);at=s.search(cx);if(at>=0){warningAt("Unsafe character.",line,at);}
+if(option.maxlen&&option.maxlen<s.length){warningAt("Line too long.",line,s.length);}
+return true;}
+function it(type,value){var i,t;if(type==='(color)'){t={type:type};}else if(type==='(punctuator)'||(type==='(identifier)'&&is_own(syntax,value))){t=syntax[value]||syntax['(error)'];}else{t=syntax[type];}
+t=Object.create(t);if(type==='(string)'||type==='(range)'){if(jx.test(value)){warningAt("Script URL.",line,from);}}
+if(type==='(identifier)'){t.identifier=true;if(value==='__iterator__'||value==='__proto__'){errorAt("Reserved name '{a}'.",line,from,value);}else if(option.nomen&&(value.charAt(0)==='_'||value.charAt(value.length-1)==='_')){warningAt("Unexpected {a} in '{b}'.",line,from,"dangling '_'",value);}}
+t.value=value;t.line=line;t.character=character;t.from=from;i=t.id;if(i!=='(endline)'){prereg=i&&(('(,=:[!&|?{};'.indexOf(i.charAt(i.length-1))>=0)||i==='return');}
+return t;}
+return{init:function(source){if(typeof source==='string'){lines=source.replace(/\r\n/g,'\n').replace(/\r/g,'\n').split('\n');}else{lines=source;}
+line=0;nextLine();from=1;},range:function(begin,end){var c,value='';from=character;if(s.charAt(0)!==begin){errorAt("Expected '{a}' and instead saw '{b}'.",line,character,begin,s.charAt(0));}
+for(;;){s=s.slice(1);character+=1;c=s.charAt(0);switch(c){case'':errorAt("Missing '{a}'.",line,character,c);break;case end:s=s.slice(1);character+=1;return it('(range)',value);case xquote:case'\\':warningAt("Unexpected '{a}'.",line,character,c);}
+value+=c;}},token:function(){var b,c,captures,d,depth,high,i,l,low,q,t;function match(x){var r=x.exec(s),r1;if(r){l=r[0].length;r1=r[1];c=r1.charAt(0);s=s.substr(l);from=character+l-r1.length;character+=l;return r1;}}
+function string(x){var c,j,r='';if(jsonmode&&x!=='"'){warningAt("Strings must use doublequote.",line,character);}
+if(xquote===x||(xmode==='scriptstring'&&!xquote)){return it('(punctuator)',x);}
+function esc(n){var i=parseInt(s.substr(j+1,n),16);j+=n;if(i>=32&&i<=126&&i!==34&&i!==92&&i!==39){warningAt("Unnecessary escapement.",line,character);}
+character+=n;c=String.fromCharCode(i);}
+j=0;for(;;){while(j>=s.length){j=0;if(xmode!=='html'||!nextLine()){errorAt("Unclosed string.",line,from);}}
+c=s.charAt(j);if(c===x){character+=1;s=s.substr(j+1);return it('(string)',r,x);}
+if(c<' '){if(c==='\n'||c==='\r'){break;}
+warningAt("Control character in string: {a}.",line,character+j,s.slice(0,j));}else if(c===xquote){warningAt("Bad HTML string",line,character+j);}else if(c==='<'){if(option.safe&&xmode==='html'){warningAt("ADsafe string violation.",line,character+j);}else if(s.charAt(j+1)==='/'&&(xmode||option.safe)){warningAt("Expected '<\\/' and instead saw '</'.",line,character);}else if(s.charAt(j+1)==='!'&&(xmode||option.safe)){warningAt("Unexpected '<!' in a string.",line,character);}}else if(c==='\\'){if(xmode==='html'){if(option.safe){warningAt("ADsafe string violation.",line,character+j);}}else if(xmode==='styleproperty'){j+=1;character+=1;c=s.charAt(j);if(c!==x){warningAt("Escapement in style string.",line,character+j);}}else{j+=1;character+=1;c=s.charAt(j);switch(c){case xquote:warningAt("Bad HTML string",line,character+j);break;case'\\':case'\'':case'"':case'/':break;case'b':c='\b';break;case'f':c='\f';break;case'n':c='\n';break;case'r':c='\r';break;case't':c='\t';break;case'u':esc(4);break;case'v':c='\v';break;case'x':if(jsonmode){warningAt("Avoid \\x-.",line,character);}
+esc(2);break;default:warningAt("Bad escapement.",line,character);}}}
+r+=c;character+=1;j+=1;}}
+for(;;){if(!s){return it(nextLine()?'(endline)':'(end)','');}
+while(xmode==='outer'){i=s.search(ox);if(i===0){break;}else if(i>0){character+=1;s=s.slice(i);break;}else{if(!nextLine()){return it('(end)','');}}}
+t=match(rx[xmode]||tx);if(!t){if(xmode==='html'){return it('(error)',s.charAt(0));}else{t='';c='';while(s&&s<'!'){s=s.substr(1);}
+if(s){errorAt("Unexpected '{a}'.",line,character,s.substr(0,1));}}}else{if(c.isAlpha()||c==='_'||c==='$'){return it('(identifier)',t);}
+if(c.isDigit()){if(xmode!=='style'&&!isFinite(Number(t))){warningAt("Bad number '{a}'.",line,character,t);}
+if(xmode!=='style'&&xmode!=='styleproperty'&&s.substr(0,1).isAlpha()){warningAt("Missing space after '{a}'.",line,character,t);}
+if(c==='0'){d=t.substr(1,1);if(d.isDigit()){if(token.id!=='.'&&xmode!=='styleproperty'){warningAt("Don't use extra leading zeros '{a}'.",line,character,t);}}else if(jsonmode&&(d==='x'||d==='X')){warningAt("Avoid 0x-. '{a}'.",line,character,t);}}
+if(t.substr(t.length-1)==='.'){warningAt("A trailing decimal point can be confused with a dot '{a}'.",line,character,t);}
+return it('(number)',t);}
+switch(t){case'"':case"'":return string(t);case'//':if(src||(xmode&&xmode!=='script')){warningAt("Unexpected comment.",line,character);}else if(xmode==='script'&&/<\s*\//i.test(s)){warningAt("Unexpected <\/ in comment.",line,character);}else if((option.safe||xmode==='script')&&ax.test(s)){warningAt("Dangerous comment.",line,character);}
+s='';token.comment=true;break;case'/*':if(src||(xmode&&xmode!=='script'&&xmode!=='style'&&xmode!=='styleproperty')){warningAt("Unexpected comment.",line,character);}
+if(option.safe&&ax.test(s)){warningAt("ADsafe comment violation.",line,character);}
+for(;;){i=s.search(lx);if(i>=0){break;}
+if(!nextLine()){errorAt("Unclosed comment.",line,character);}else{if(option.safe&&ax.test(s)){warningAt("ADsafe comment violation.",line,character);}}}
+character+=i+2;if(s.substr(i,1)==='/'){errorAt("Nested comment.",line,character);}
+s=s.substr(i+2);token.comment=true;break;case'/*members':case'/*member':case'/*jslint':case'/*global':case'*/':return{value:t,type:'special',line:line,character:character,from:from};case'':break;case'/':if(prereg){depth=0;captures=0;l=0;for(;;){b=true;c=s.charAt(l);l+=1;switch(c){case'':errorAt("Unclosed regular expression.",line,from);return;case'/':if(depth>0){warningAt("Unescaped '{a}'.",line,from+l,'/');}
+c=s.substr(0,l-1);q={g:true,i:true,m:true};while(q[s.charAt(l)]===true){q[s.charAt(l)]=false;l+=1;}
+character+=l;s=s.substr(l);return it('(regexp)',c);case'\\':c=s.charAt(l);if(c<' '){warningAt("Unexpected control character in regular expression.",line,from+l);}else if(c==='<'){warningAt("Unexpected escaped character '{a}' in regular expression.",line,from+l,c);}
+l+=1;break;case'(':depth+=1;b=false;if(s.charAt(l)==='?'){l+=1;switch(s.charAt(l)){case':':case'=':case'!':l+=1;break;default:warningAt("Expected '{a}' and instead saw '{b}'.",line,from+l,':',s.charAt(l));}}else{captures+=1;}
+break;case'|':b=false;break;case')':if(depth===0){warningAt("Unescaped '{a}'.",line,from+l,')');}else{depth-=1;}
+break;case' ':q=1;while(s.charAt(l)===' '){l+=1;q+=1;}
+if(q>1){warningAt("Spaces are hard to count. Use {{a}}.",line,from+l,q);}
+break;case'[':c=s.charAt(l);if(c==='^'){l+=1;if(option.regexp){warningAt("Insecure '{a}'.",line,from+l,c);}}
+q=false;if(c===']'){warningAt("Empty class.",line,from+l-1);q=true;}
+klass:do{c=s.charAt(l);l+=1;switch(c){case'[':case'^':warningAt("Unescaped '{a}'.",line,from+l,c);q=true;break;case'-':if(q){q=false;}else{warningAt("Unescaped '{a}'.",line,from+l,'-');q=true;}
+break;case']':if(!q){warningAt("Unescaped '{a}'.",line,from+l-1,'-');}
+break klass;case'\\':c=s.charAt(l);if(c<' '){warningAt("Unexpected control character in regular expression.",line,from+l);}else if(c==='<'){warningAt("Unexpected escaped character '{a}' in regular expression.",line,from+l,c);}
+l+=1;q=true;break;case'/':warningAt("Unescaped '{a}'.",line,from+l-1,'/');q=true;break;case'<':if(xmode==='script'){c=s.charAt(l);if(c==='!'||c==='/'){warningAt("HTML confusion in regular expression '<{a}'.",line,from+l,c);}}
+q=true;break;default:q=true;}}while(c);break;case'.':if(option.regexp){warningAt("Insecure '{a}'.",line,from+l,c);}
+break;case']':case'?':case'{':case'}':case'+':case'*':warningAt("Unescaped '{a}'.",line,from+l,c);break;case'<':if(xmode==='script'){c=s.charAt(l);if(c==='!'||c==='/'){warningAt("HTML confusion in regular expression '<{a}'.",line,from+l,c);}}}
+if(b){switch(s.charAt(l)){case'?':case'+':case'*':l+=1;if(s.charAt(l)==='?'){l+=1;}
+break;case'{':l+=1;c=s.charAt(l);if(c<'0'||c>'9'){warningAt("Expected a number and instead saw '{a}'.",line,from+l,c);}
+l+=1;low=+c;for(;;){c=s.charAt(l);if(c<'0'||c>'9'){break;}
+l+=1;low=+c+(low*10);}
+high=low;if(c===','){l+=1;high=Infinity;c=s.charAt(l);if(c>='0'&&c<='9'){l+=1;high=+c;for(;;){c=s.charAt(l);if(c<'0'||c>'9'){break;}
+l+=1;high=+c+(high*10);}}}
+if(s.charAt(l)!=='}'){warningAt("Expected '{a}' and instead saw '{b}'.",line,from+l,'}',c);}else{l+=1;}
+if(s.charAt(l)==='?'){l+=1;}
+if(low>high){warningAt("'{a}' should not be greater than '{b}'.",line,from+l,low,high);}}}}
+c=s.substr(0,l-1);character+=l;s=s.substr(l);return it('(regexp)',c);}
+return it('(punctuator)',t);case'<!--':l=line;c=character;for(;;){i=s.indexOf('--');if(i>=0){break;}
+i=s.indexOf('<!');if(i>=0){errorAt("Nested HTML comment.",line,character+i);}
+if(!nextLine()){errorAt("Unclosed HTML comment.",l,c);}}
+l=s.indexOf('<!');if(l>=0&&l<i){errorAt("Nested HTML comment.",line,character+l);}
+character+=i;if(s[i+2]!=='>'){errorAt("Expected -->.",line,character);}
+character+=3;s=s.slice(i+3);break;case'#':if(xmode==='html'||xmode==='styleproperty'){for(;;){c=s.charAt(0);if((c<'0'||c>'9')&&(c<'a'||c>'f')&&(c<'A'||c>'F')){break;}
+character+=1;s=s.substr(1);t+=c;}
+if(t.length!==4&&t.length!==7){warningAt("Bad hex color '{a}'.",line,from+l,t);}
+return it('(color)',t);}
+return it('(punctuator)',t);default:if(xmode==='outer'&&c==='&'){character+=1;s=s.substr(1);for(;;){c=s.charAt(0);character+=1;s=s.substr(1);if(c===';'){break;}
+if(!((c>='0'&&c<='9')||(c>='a'&&c<='z')||c==='#')){errorAt("Bad entity",line,from+l,character);}}
+break;}
+return it('(punctuator)',t);}}}}};}());function addlabel(t,type){if(option.safe&&funct['(global)']&&typeof predefined[t]!=='boolean'){warning('ADsafe global: '+t+'.',token);}else if(t==='hasOwnProperty'){warning("'hasOwnProperty' is a really bad name.");}
+if(is_own(funct,t)&&!funct['(global)']){warning(funct[t]===true?"'{a}' was used before it was defined.":"'{a}' is already defined.",nexttoken,t);}
+funct[t]=type;if(funct['(global)']){global[t]=funct;if(is_own(implied,t)){warning("'{a}' was used before it was defined.",nexttoken,t);delete implied[t];}}else{scope[t]=funct;}}
+function doOption(){var b,obj,filter,o=nexttoken.value,t,v;switch(o){case'*/':error("Unbegun comment.");break;case'/*members':case'/*member':o='/*members';if(!membersOnly){membersOnly={};}
+obj=membersOnly;break;case'/*jslint':if(option.safe){warning("ADsafe restriction.");}
+obj=option;filter=boolOptions;break;case'/*global':if(option.safe){warning("ADsafe restriction.");}
+obj=predefined;break;default:}
+t=lex.token();loop:for(;;){for(;;){if(t.type==='special'&&t.value==='*/'){break loop;}
+if(t.id!=='(endline)'&&t.id!==','){break;}
+t=lex.token();}
+if(t.type!=='(string)'&&t.type!=='(identifier)'&&o!=='/*members'){error("Bad option.",t);}
+v=lex.token();if(v.id===':'){v=lex.token();if(obj===membersOnly){error("Expected '{a}' and instead saw '{b}'.",t,'*/',':');}
+if(t.value==='indent'&&o==='/*jslint'){b=+v.value;if(typeof b!=='number'||!isFinite(b)||b<=0||Math.floor(b)!==b){error("Expected a small integer and instead saw '{a}'.",v,v.value);}
+obj.white=true;obj.indent=b;}else if(t.value==='maxerr'&&o==='/*jslint'){b=+v.value;if(typeof b!=='number'||!isFinite(b)||b<=0||Math.floor(b)!==b){error("Expected a small integer and instead saw '{a}'.",v,v.value);}
+obj.maxerr=b;}else if(v.value==='true'){obj[t.value]=true;}else if(v.value==='false'){obj[t.value]=false;}else{error("Bad option value.",v);}
+t=lex.token();}else{if(o==='/*jslint'){error("Missing option value.",t);}
+obj[t.value]=false;t=v;}}
+if(filter){assume();}}
+function peek(p){var i=p||0,j=0,t;while(j<=i){t=lookahead[j];if(!t){t=lookahead[j]=lex.token();}
+j+=1;}
+return t;}
+function advance(id,t){switch(token.id){case'(number)':if(nexttoken.id==='.'){warning("A dot following a number can be confused with a decimal point.",token);}
+break;case'-':if(nexttoken.id==='-'||nexttoken.id==='--'){warning("Confusing minusses.");}
+break;case'+':if(nexttoken.id==='+'||nexttoken.id==='++'){warning("Confusing plusses.");}
+break;}
+if(token.type==='(string)'||token.identifier){anonname=token.value;}
+if(id&&nexttoken.id!==id){if(t){if(nexttoken.id==='(end)'){warning("Unmatched '{a}'.",t,t.id);}else{warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",nexttoken,id,t.id,t.line,nexttoken.value);}}else if(nexttoken.type!=='(identifier)'||nexttoken.value!==id){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,id,nexttoken.value);}}
+prevtoken=token;token=nexttoken;for(;;){nexttoken=lookahead.shift()||lex.token();if(nexttoken.id==='(end)'||nexttoken.id==='(error)'){return;}
+if(nexttoken.type==='special'){doOption();}else{if(nexttoken.id!=='(endline)'){break;}}}}
+function parse(rbp,initial){var left;if(nexttoken.id==='(end)'){error("Unexpected early end of program.",token);}
+advance();if(option.safe&&typeof predefined[token.value]==='boolean'&&(nexttoken.id!=='('&&nexttoken.id!=='.')){warning('ADsafe violation.',token);}
+if(initial){anonname='anonymous';funct['(verb)']=token.value;}
+if(initial===true&&token.fud){left=token.fud();}else{if(token.nud){left=token.nud();}else{if(nexttoken.type==='(number)'&&token.id==='.'){warning("A leading decimal point can be confused with a dot: '.{a}'.",token,nexttoken.value);advance();return token;}else{error("Expected an identifier and instead saw '{a}'.",token,token.id);}}
+while(rbp<nexttoken.lbp){advance();if(token.led){left=token.led(left);}else{error("Expected an operator and instead saw '{a}'.",token,token.id);}}}
+return left;}
+function adjacent(left,right){left=left||token;right=right||nexttoken;if(option.white||xmode==='styleproperty'||xmode==='style'){if(left.character!==right.from&&left.line===right.line){warning("Unexpected space after '{a}'.",right,left.value);}}}
+function nospace(left,right){left=left||token;right=right||nexttoken;if(option.white&&!left.comment){if(left.line===right.line){adjacent(left,right);}}}
+function nonadjacent(left,right){if(option.white){left=left||token;right=right||nexttoken;if(left.line===right.line&&left.character===right.from){warning("Missing space after '{a}'.",nexttoken,left.value);}}}
+function nobreaknonadjacent(left,right){left=left||token;right=right||nexttoken;if(!option.laxbreak&&left.line!==right.line){warning("Bad line breaking before '{a}'.",right,right.id);}else if(option.white){left=left||token;right=right||nexttoken;if(left.character===right.from){warning("Missing space after '{a}'.",nexttoken,left.value);}}}
+function indentation(bias){var i;if(option.white&&nexttoken.id!=='(end)'){i=indent+(bias||0);if(nexttoken.from!==i){warning("Expected '{a}' to have an indentation at {b} instead at {c}.",nexttoken,nexttoken.value,i,nexttoken.from);}}}
+function nolinebreak(t){t=t||token;if(t.line!==nexttoken.line){warning("Line breaking error '{a}'.",t,t.value);}}
+function comma(){if(token.line!==nexttoken.line){if(!option.laxbreak){warning("Bad line breaking before '{a}'.",token,nexttoken.id);}}else if(token.character!==nexttoken.from&&option.white){warning("Unexpected space after '{a}'.",nexttoken,token.value);}
+advance(',');nonadjacent(token,nexttoken);}
+function symbol(s,p){var x=syntax[s];if(!x||typeof x!=='object'){syntax[s]=x={id:s,lbp:p,value:s};}
+return x;}
+function delim(s){return symbol(s,0);}
+function stmt(s,f){var x=delim(s);x.identifier=x.reserved=true;x.fud=f;return x;}
+function blockstmt(s,f){var x=stmt(s,f);x.block=true;return x;}
+function reserveName(x){var c=x.id.charAt(0);if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){x.identifier=x.reserved=true;}
+return x;}
+function prefix(s,f){var x=symbol(s,150);reserveName(x);x.nud=(typeof f==='function')?f:function(){this.right=parse(150);this.arity='unary';if(this.id==='++'||this.id==='--'){if(option.plusplus){warning("Unexpected use of '{a}'.",this,this.id);}else if((!this.right.identifier||this.right.reserved)&&this.right.id!=='.'&&this.right.id!=='['){warning("Bad operand.",this);}}
+return this;};return x;}
+function type(s,f){var x=delim(s);x.type=s;x.nud=f;return x;}
+function reserve(s,f){var x=type(s,f);x.identifier=x.reserved=true;return x;}
+function reservevar(s,v){return reserve(s,function(){if(this.id==='this'||this.id==='arguments'){if(strict_mode&&funct['(global)']){warning("Strict violation.",this);}else if(option.safe){warning("ADsafe violation.",this);}}
+return this;});}
+function infix(s,f,p,w){var x=symbol(s,p);reserveName(x);x.led=function(left){if(!w){nobreaknonadjacent(prevtoken,token);nonadjacent(token,nexttoken);}
+if(typeof f==='function'){return f(left,this);}else{this.left=left;this.right=parse(p);return this;}};return x;}
+function relation(s,f){var x=symbol(s,100);x.led=function(left){nobreaknonadjacent(prevtoken,token);nonadjacent(token,nexttoken);var right=parse(100);if((left&&left.id==='NaN')||(right&&right.id==='NaN')){warning("Use the isNaN function to compare with NaN.",this);}else if(f){f.apply(this,[left,right]);}
+if(left.id==='!'){warning("Confusing use of '{a}'.",left,'!');}
+if(right.id==='!'){warning("Confusing use of '{a}'.",left,'!');}
+this.left=left;this.right=right;return this;};return x;}
+function isPoorRelation(node){return node&&((node.type==='(number)'&&+node.value===0)||(node.type==='(string)'&&node.value===' ')||node.type==='true'||node.type==='false'||node.type==='undefined'||node.type==='null');}
+function assignop(s,f){symbol(s,20).exps=true;return infix(s,function(left,that){var l;that.left=left;if(predefined[left.value]===false&&scope[left.value]['(global)']===true){warning('Read only.',left);}
+if(option.safe){l=left;do{if(typeof predefined[l.value]==='boolean'){warning('ADsafe violation.',l);}
+l=l.left;}while(l);}
+if(left){if(left.id==='.'||left.id==='['){if(!left.left||left.left.value==='arguments'){warning('Bad assignment.',that);}
+that.right=parse(19);return that;}else if(left.identifier&&!left.reserved){if(funct[left.value]==='exception'){warning("Do not assign to the exception parameter.",left);}
+that.right=parse(19);return that;}
+if(left===syntax['function']){warning("Expected an identifier in an assignment and instead saw a function invocation.",token);}}
+error("Bad assignment.",that);},20);}
+function bitwise(s,f,p){var x=symbol(s,p);reserveName(x);x.led=(typeof f==='function')?f:function(left){if(option.bitwise){warning("Unexpected use of '{a}'.",this,this.id);}
+this.left=left;this.right=parse(p);return this;};return x;}
+function bitwiseassignop(s){symbol(s,20).exps=true;return infix(s,function(left,that){if(option.bitwise){warning("Unexpected use of '{a}'.",that,that.id);}
+nonadjacent(prevtoken,token);nonadjacent(token,nexttoken);if(left){if(left.id==='.'||left.id==='['||(left.identifier&&!left.reserved)){parse(19);return that;}
+if(left===syntax['function']){warning("Expected an identifier in an assignment, and instead saw a function invocation.",token);}
+return that;}
+error("Bad assignment.",that);},20);}
+function suffix(s,f){var x=symbol(s,150);x.led=function(left){if(option.plusplus){warning("Unexpected use of '{a}'.",this,this.id);}else if((!left.identifier||left.reserved)&&left.id!=='.'&&left.id!=='['){warning("Bad operand.",this);}
+this.left=left;return this;};return x;}
+function optionalidentifier(){if(nexttoken.reserved){warning("Expected an identifier and instead saw '{a}' (a reserved word).",nexttoken,nexttoken.id);}
+if(nexttoken.identifier){advance();return token.value;}}
+function identifier(){var i=optionalidentifier();if(i){return i;}
+if(token.id==='function'&&nexttoken.id==='('){warning("Missing name in function statement.");}else{error("Expected an identifier and instead saw '{a}'.",nexttoken,nexttoken.value);}}
+function reachable(s){var i=0,t;if(nexttoken.id!==';'||noreach){return;}
+for(;;){t=peek(i);if(t.reach){return;}
+if(t.id!=='(endline)'){if(t.id==='function'){warning("Inner functions should be listed at the top of the outer function.",t);break;}
+warning("Unreachable '{a}' after '{b}'.",t,t.value,s);break;}
+i+=1;}}
+function statement(noindent){var i=indent,r,s=scope,t=nexttoken;if(t.id===';'){warning("Unnecessary semicolon.",t);advance(';');return;}
+if(t.identifier&&!t.reserved&&peek().id===':'){advance();advance(':');scope=Object.create(s);addlabel(t.value,'label');if(!nexttoken.labelled){warning("Label '{a}' on {b} statement.",nexttoken,t.value,nexttoken.value);}
+if(jx.test(t.value+':')){warning("Label '{a}' looks like a javascript url.",t,t.value);}
+nexttoken.label=t.value;t=nexttoken;}
+if(!noindent){indentation();}
+if(nexttoken.id==='new'){warning("'new' should not be used as a statement.");}
+r=parse(0,true);if(!t.block){if(!r||!r.exps){warning("Expected an assignment or function call and instead saw an expression.",token);}
+if(nexttoken.id!==';'){warningAt("Missing semicolon.",token.line,token.from+token.value.length);}else{adjacent(token,nexttoken);advance(';');nonadjacent(token,nexttoken);}}
+indent=i;scope=s;return r;}
+function use_strict(){if(nexttoken.value==='use strict'){advance();advance(';');strict_mode=true;return true;}else{return false;}}
+function statements(begin){var a=[],f,p;if(begin&&!use_strict()&&option.strict){warning('Missing "use strict" statement.',nexttoken);}
+if(option.adsafe){switch(begin){case'script':if(!adsafe_may){if(nexttoken.value!=='ADSAFE'||peek(0).id!=='.'||(peek(1).value!=='id'&&peek(1).value!=='go')){error('ADsafe violation: Missing ADSAFE.id or ADSAFE.go.',nexttoken);}}
+if(nexttoken.value==='ADSAFE'&&peek(0).id==='.'&&peek(1).value==='id'){if(adsafe_may){error('ADsafe violation.',nexttoken);}
+advance('ADSAFE');advance('.');advance('id');advance('(');if(nexttoken.value!==adsafe_id){error('ADsafe violation: id does not match.',nexttoken);}
+advance('(string)');advance(')');advance(';');adsafe_may=true;}
+break;case'lib':if(nexttoken.value==='ADSAFE'){advance('ADSAFE');advance('.');advance('lib');advance('(');advance('(string)');comma();f=parse(0);if(f.id!=='function'){error('The second argument to lib must be a function.',f);}
+p=f.funct['(params)'];p=p&&p.join(', ');if(p&&p!=='lib'){error("Expected '{a}' and instead saw '{b}'.",f,'(lib)','('+p+')');}
+advance(')');advance(';');return a;}else{error("ADsafe lib violation.");}}}
+while(!nexttoken.reach&&nexttoken.id!=='(end)'){if(nexttoken.id===';'){warning("Unnecessary semicolon.");advance(';');}else{a.push(statement());}}
+return a;}
+function block(f){var a,b=inblock,old_indent=indent,s=scope,t;inblock=f;scope=Object.create(scope);nonadjacent(token,nexttoken);t=nexttoken;if(nexttoken.id==='{'){advance('{');if(nexttoken.id!=='}'||token.line!==nexttoken.line){indent+=option.indent;while(!f&&nexttoken.from>indent){indent+=option.indent;}
+if(!f){use_strict();}
+a=statements();indent-=option.indent;indentation();}
+advance('}',t);indent=old_indent;}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'{',nexttoken.value);noreach=true;a=[statement()];noreach=false;}
+funct['(verb)']=null;scope=s;inblock=b;return a;}
+function idValue(){return this;}
+function countMember(m){if(membersOnly&&typeof membersOnly[m]!=='boolean'){warning("Unexpected /*member '{a}'.",token,m);}
+if(typeof member[m]==='number'){member[m]+=1;}else{member[m]=1;}}
+function note_implied(token){var name=token.value,line=token.line,a=implied[name];if(typeof a==='function'){a=false;}
+if(!a){a=[line];implied[name]=a;}else if(a[a.length-1]!==line){a.push(line);}}
+function cssName(){if(nexttoken.identifier){advance();return true;}}
+function cssNumber(){if(nexttoken.id==='-'){advance('-');adjacent();nolinebreak();}
+if(nexttoken.type==='(number)'){advance('(number)');return true;}}
+function cssString(){if(nexttoken.type==='(string)'){advance();return true;}}
+function cssColor(){var i,number;if(nexttoken.identifier){if(nexttoken.value==='rgb'){advance();advance('(');for(i=0;i<3;i+=1){if(i){advance(',');}
+number=nexttoken.value;if(nexttoken.type!=='(number)'||number<0){warning("Expected a positive number and instead saw '{a}'",nexttoken,number);advance();}else{advance();if(nexttoken.id==='%'){advance('%');if(number>100){warning("Expected a percentage and instead saw '{a}'",token,number);}}else{if(number>255){warning("Expected a small number and instead saw '{a}'",token,number);}}}}
+advance(')');return true;}else if(cssColorData[nexttoken.value]===true){advance();return true;}}else if(nexttoken.type==='(color)'){advance();return true;}
+return false;}
+function cssLength(){if(nexttoken.id==='-'){advance('-');adjacent();nolinebreak();}
+if(nexttoken.type==='(number)'){advance();if(nexttoken.type!=='(string)'&&cssLengthData[nexttoken.value]===true){adjacent();advance();}else if(+token.value!==0){warning("Expected a linear unit and instead saw '{a}'.",nexttoken,nexttoken.value);}
+return true;}
+return false;}
+function cssLineHeight(){if(nexttoken.id==='-'){advance('-');adjacent();}
+if(nexttoken.type==='(number)'){advance();if(nexttoken.type!=='(string)'&&cssLengthData[nexttoken.value]===true){adjacent();advance();}
+return true;}
+return false;}
+function cssWidth(){if(nexttoken.identifier){switch(nexttoken.value){case'thin':case'medium':case'thick':advance();return true;}}else{return cssLength();}}
+function cssMargin(){if(nexttoken.identifier){if(nexttoken.value==='auto'){advance();return true;}}else{return cssLength();}}
+function cssAttr(){if(nexttoken.identifier&&nexttoken.value==='attr'){advance();advance('(');if(!nexttoken.identifier){warning("Expected a name and instead saw '{a}'.",nexttoken,nexttoken.value);}
+advance();advance(')');return true;}
+return false;}
+function cssCommaList(){while(nexttoken.id!==';'){if(!cssName()&&!cssString()){warning("Expected a name and instead saw '{a}'.",nexttoken,nexttoken.value);}
+if(nexttoken.id!==','){return true;}
+comma();}}
+function cssCounter(){if(nexttoken.identifier&&nexttoken.value==='counter'){advance();advance('(');if(!nexttoken.identifier){}
+advance();if(nexttoken.id===','){comma();if(nexttoken.type!=='(string)'){warning("Expected a string and instead saw '{a}'.",nexttoken,nexttoken.value);}
+advance();}
+advance(')');return true;}
+if(nexttoken.identifier&&nexttoken.value==='counters'){advance();advance('(');if(!nexttoken.identifier){warning("Expected a name and instead saw '{a}'.",nexttoken,nexttoken.value);}
+advance();if(nexttoken.id===','){comma();if(nexttoken.type!=='(string)'){warning("Expected a string and instead saw '{a}'.",nexttoken,nexttoken.value);}
+advance();}
+if(nexttoken.id===','){comma();if(nexttoken.type!=='(string)'){warning("Expected a string and instead saw '{a}'.",nexttoken,nexttoken.value);}
+advance();}
+advance(')');return true;}
+return false;}
+function cssShape(){var i;if(nexttoken.identifier&&nexttoken.value==='rect'){advance();advance('(');for(i=0;i<4;i+=1){if(!cssLength()){warning("Expected a number and instead saw '{a}'.",nexttoken,nexttoken.value);break;}}
+advance(')');return true;}
+return false;}
+function cssUrl(){var c,url;if(nexttoken.identifier&&nexttoken.value==='url'){nexttoken=lex.range('(',')');url=nexttoken.value;c=url.charAt(0);if(c==='"'||c==='\''){if(url.slice(-1)!==c){warning("Bad url string.");}else{url=url.slice(1,-1);if(url.indexOf(c)>=0){warning("Bad url string.");}}}
+if(!url){warning("Missing url.");}
+advance();if(option.safe&&ux.test(url)){error("ADsafe URL violation.");}
+urls.push(url);return true;}
+return false;}
+cssAny=[cssUrl,function(){for(;;){if(nexttoken.identifier){switch(nexttoken.value.toLowerCase()){case'url':cssUrl();break;case'expression':warning("Unexpected expression '{a}'.",nexttoken,nexttoken.value);advance();break;default:advance();}}else{if(nexttoken.id===';'||nexttoken.id==='!'||nexttoken.id==='(end)'||nexttoken.id==='}'){return true;}
+advance();}}}];cssBorderStyle=['none','hidden','dotted','dashed','solid','double','ridge','inset','outset'];cssBreak=['auto','always','avoid','left','right'];cssOverflow=['auto','hidden','scroll','visible'];cssAttributeData={background:[true,'background-attachment','background-color','background-image','background-position','background-repeat'],'background-attachment':['scroll','fixed'],'background-color':['transparent',cssColor],'background-image':['none',cssUrl],'background-position':[2,[cssLength,'top','bottom','left','right','center']],'background-repeat':['repeat','repeat-x','repeat-y','no-repeat'],'border':[true,'border-color','border-style','border-width'],'border-bottom':[true,'border-bottom-color','border-bottom-style','border-bottom-width'],'border-bottom-color':cssColor,'border-bottom-style':cssBorderStyle,'border-bottom-width':cssWidth,'border-collapse':['collapse','separate'],'border-color':['transparent',4,cssColor],'border-left':[true,'border-left-color','border-left-style','border-left-width'],'border-left-color':cssColor,'border-left-style':cssBorderStyle,'border-left-width':cssWidth,'border-right':[true,'border-right-color','border-right-style','border-right-width'],'border-right-color':cssColor,'border-right-style':cssBorderStyle,'border-right-width':cssWidth,'border-spacing':[2,cssLength],'border-style':[4,cssBorderStyle],'border-top':[true,'border-top-color','border-top-style','border-top-width'],'border-top-color':cssColor,'border-top-style':cssBorderStyle,'border-top-width':cssWidth,'border-width':[4,cssWidth],bottom:[cssLength,'auto'],'caption-side':['bottom','left','right','top'],clear:['both','left','none','right'],clip:[cssShape,'auto'],color:cssColor,content:['open-quote','close-quote','no-open-quote','no-close-quote',cssString,cssUrl,cssCounter,cssAttr],'counter-increment':[cssName,'none'],'counter-reset':[cssName,'none'],cursor:[cssUrl,'auto','crosshair','default','e-resize','help','move','n-resize','ne-resize','nw-resize','pointer','s-resize','se-resize','sw-resize','w-resize','text','wait'],direction:['ltr','rtl'],display:['block','compact','inline','inline-block','inline-table','list-item','marker','none','run-in','table','table-caption','table-cell','table-column','table-column-group','table-footer-group','table-header-group','table-row','table-row-group'],'empty-cells':['show','hide'],'float':['left','none','right'],font:['caption','icon','menu','message-box','small-caption','status-bar',true,'font-size','font-style','font-weight','font-family'],'font-family':cssCommaList,'font-size':['xx-small','x-small','small','medium','large','x-large','xx-large','larger','smaller',cssLength],'font-size-adjust':['none',cssNumber],'font-stretch':['normal','wider','narrower','ultra-condensed','extra-condensed','condensed','semi-condensed','semi-expanded','expanded','extra-expanded'],'font-style':['normal','italic','oblique'],'font-variant':['normal','small-caps'],'font-weight':['normal','bold','bolder','lighter',cssNumber],height:[cssLength,'auto'],left:[cssLength,'auto'],'letter-spacing':['normal',cssLength],'line-height':['normal',cssLineHeight],'list-style':[true,'list-style-image','list-style-position','list-style-type'],'list-style-image':['none',cssUrl],'list-style-position':['inside','outside'],'list-style-type':['circle','disc','square','decimal','decimal-leading-zero','lower-roman','upper-roman','lower-greek','lower-alpha','lower-latin','upper-alpha','upper-latin','hebrew','katakana','hiragana-iroha','katakana-oroha','none'],margin:[4,cssMargin],'margin-bottom':cssMargin,'margin-left':cssMargin,'margin-right':cssMargin,'margin-top':cssMargin,'marker-offset':[cssLength,'auto'],'max-height':[cssLength,'none'],'max-width':[cssLength,'none'],'min-height':cssLength,'min-width':cssLength,opacity:cssNumber,outline:[true,'outline-color','outline-style','outline-width'],'outline-color':['invert',cssColor],'outline-style':['dashed','dotted','double','groove','inset','none','outset','ridge','solid'],'outline-width':cssWidth,overflow:cssOverflow,'overflow-x':cssOverflow,'overflow-y':cssOverflow,padding:[4,cssLength],'padding-bottom':cssLength,'padding-left':cssLength,'padding-right':cssLength,'padding-top':cssLength,'page-break-after':cssBreak,'page-break-before':cssBreak,position:['absolute','fixed','relative','static'],quotes:[8,cssString],right:[cssLength,'auto'],'table-layout':['auto','fixed'],'text-align':['center','justify','left','right'],'text-decoration':['none','underline','overline','line-through','blink'],'text-indent':cssLength,'text-shadow':['none',4,[cssColor,cssLength]],'text-transform':['capitalize','uppercase','lowercase','none'],top:[cssLength,'auto'],'unicode-bidi':['normal','embed','bidi-override'],'vertical-align':['baseline','bottom','sub','super','top','text-top','middle','text-bottom',cssLength],visibility:['visible','hidden','collapse'],'white-space':['normal','nowrap','pre','pre-line','pre-wrap','inherit'],width:[cssLength,'auto'],'word-spacing':['normal',cssLength],'word-wrap':['break-word','normal'],'z-index':['auto',cssNumber]};function styleAttribute(){var v;while(nexttoken.id==='*'||nexttoken.id==='#'||nexttoken.value==='_'){if(!option.css){warning("Unexpected '{a}'.",nexttoken,nexttoken.value);}
+advance();}
+if(nexttoken.id==='-'){if(!option.css){warning("Unexpected '{a}'.",nexttoken,nexttoken.value);}
+advance('-');if(!nexttoken.identifier){warning("Expected a non-standard style attribute and instead saw '{a}'.",nexttoken,nexttoken.value);}
+advance();return cssAny;}else{if(!nexttoken.identifier){warning("Excepted a style attribute, and instead saw '{a}'.",nexttoken,nexttoken.value);}else{if(is_own(cssAttributeData,nexttoken.value)){v=cssAttributeData[nexttoken.value];}else{v=cssAny;if(!option.css){warning("Unrecognized style attribute '{a}'.",nexttoken,nexttoken.value);}}}
+advance();return v;}}
+function styleValue(v){var i=0,n,once,match,round,start=0,vi;switch(typeof v){case'function':return v();case'string':if(nexttoken.identifier&&nexttoken.value===v){advance();return true;}
+return false;}
+for(;;){if(i>=v.length){return false;}
+vi=v[i];i+=1;if(vi===true){break;}else if(typeof vi==='number'){n=vi;vi=v[i];i+=1;}else{n=1;}
+match=false;while(n>0){if(styleValue(vi)){match=true;n-=1;}else{break;}}
+if(match){return true;}}
+start=i;once=[];for(;;){round=false;for(i=start;i<v.length;i+=1){if(!once[i]){if(styleValue(cssAttributeData[v[i]])){match=true;round=true;once[i]=true;break;}}}
+if(!round){return match;}}}
+function styleChild(){if(nexttoken.id==='(number)'){advance();if(nexttoken.value==='n'&&nexttoken.identifier){adjacent();advance();if(nexttoken.id==='+'){adjacent();advance('+');adjacent();advance('(number)');}}
+return;}else{switch(nexttoken.value){case'odd':case'even':if(nexttoken.identifier){advance();return;}}}
+warning("Unexpected token '{a}'.",nexttoken,nexttoken.value);}
+function substyle(){var v;for(;;){if(nexttoken.id==='}'||nexttoken.id==='(end)'||xquote&&nexttoken.id===xquote){return;}
+while(nexttoken.id===';'){warning("Misplaced ';'.");advance(';');}
+v=styleAttribute();advance(':');if(nexttoken.identifier&&nexttoken.value==='inherit'){advance();}else{if(!styleValue(v)){warning("Unexpected token '{a}'.",nexttoken,nexttoken.value);advance();}}
+if(nexttoken.id==='!'){advance('!');adjacent();if(nexttoken.identifier&&nexttoken.value==='important'){advance();}else{warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'important',nexttoken.value);}}
+if(nexttoken.id==='}'||nexttoken.id===xquote){warning("Missing '{a}'.",nexttoken,';');}else{advance(';');}}}
+function styleSelector(){if(nexttoken.identifier){if(!is_own(htmltag,nexttoken.value)){warning("Expected a tagName, and instead saw {a}.",nexttoken,nexttoken.value);}
+advance();}else{switch(nexttoken.id){case'>':case'+':advance();styleSelector();break;case':':advance(':');switch(nexttoken.value){case'active':case'after':case'before':case'checked':case'disabled':case'empty':case'enabled':case'first-child':case'first-letter':case'first-line':case'first-of-type':case'focus':case'hover':case'last-of-type':case'link':case'only-of-type':case'root':case'target':case'visited':advance();break;case'lang':advance();advance('(');if(!nexttoken.identifier){warning("Expected a lang code, and instead saw :{a}.",nexttoken,nexttoken.value);}
+advance(')');break;case'nth-child':case'nth-last-child':case'nth-last-of-type':case'nth-of-type':advance();advance('(');styleChild();advance(')');break;case'not':advance();advance('(');if(nexttoken.id===':'&&peek(0).value==='not'){warning("Nested not.");}
+styleSelector();advance(')');break;default:warning("Expected a pseudo, and instead saw :{a}.",nexttoken,nexttoken.value);}
+break;case'#':advance('#');if(!nexttoken.identifier){warning("Expected an id, and instead saw #{a}.",nexttoken,nexttoken.value);}
+advance();break;case'*':advance('*');break;case'.':advance('.');if(!nexttoken.identifier){warning("Expected a class, and instead saw #.{a}.",nexttoken,nexttoken.value);}
+advance();break;case'[':advance('[');if(!nexttoken.identifier){warning("Expected an attribute, and instead saw [{a}].",nexttoken,nexttoken.value);}
+advance();if(nexttoken.id==='='||nexttoken.value==='~='||nexttoken.value==='$='||nexttoken.value==='|='||nexttoken.id==='*='||nexttoken.id==='^='){advance();if(nexttoken.type!=='(string)'){warning("Expected a string, and instead saw {a}.",nexttoken,nexttoken.value);}
+advance();}
+advance(']');break;default:error("Expected a CSS selector, and instead saw {a}.",nexttoken,nexttoken.value);}}}
+function stylePattern(){var name;if(nexttoken.id==='{'){warning("Expected a style pattern, and instead saw '{a}'.",nexttoken,nexttoken.id);}else if(nexttoken.id==='@'){advance('@');name=nexttoken.value;if(nexttoken.identifier&&atrule[name]===true){advance();return name;}
+warning("Expected an at-rule, and instead saw @{a}.",nexttoken,name);}
+for(;;){styleSelector();if(nexttoken.id==='</'||nexttoken.id==='{'||nexttoken.id==='(end)'){return'';}
+if(nexttoken.id===','){comma();}}}
+function styles(){var i;while(nexttoken.id==='@'){i=peek();if(i.identifier&&i.value==='import'){advance('@');advance();if(!cssUrl()){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'url',nexttoken.value);advance();}
+advance(';');}else{break;}}
+while(nexttoken.id!=='</'&&nexttoken.id!=='(end)'){stylePattern();xmode='styleproperty';if(nexttoken.id===';'){advance(';');}else{advance('{');substyle();xmode='style';advance('}');}}}
+function doBegin(n){if(n!=='html'&&!option.fragment){if(n==='div'&&option.adsafe){error("ADSAFE: Use the fragment option.");}else{error("Expected '{a}' and instead saw '{b}'.",token,'html',n);}}
+if(option.adsafe){if(n==='html'){error("Currently, ADsafe does not operate on whole HTML documents. It operates on <div> fragments and .js files.",token);}
+if(option.fragment){if(n!=='div'){error("ADsafe violation: Wrap the widget in a div.",token);}}else{error("Use the fragment option.",token);}}
+option.browser=true;assume();}
+function doAttribute(n,a,v){var u,x;if(a==='id'){u=typeof v==='string'?v.toUpperCase():'';if(ids[u]===true){warning("Duplicate id='{a}'.",nexttoken,v);}
+if(option.adsafe){if(adsafe_id){if(v.slice(0,adsafe_id.length)!==adsafe_id){warning("ADsafe violation: An id must have a '{a}' prefix",nexttoken,adsafe_id);}else if(!/^[A-Z]+_[A-Z]+$/.test(v)){warning("ADSAFE violation: bad id.");}}else{adsafe_id=v;if(!/^[A-Z]+_$/.test(v)){warning("ADSAFE violation: bad id.");}}}
+x=v.search(dx);if(x>=0){warning("Unexpected character '{a}' in {b}.",token,v.charAt(x),a);}
+ids[u]=true;}else if(a==='class'||a==='type'||a==='name'){x=v.search(qx);if(x>=0){warning("Unexpected character '{a}' in {b}.",token,v.charAt(x),a);}
+ids[u]=true;}else if(a==='href'||a==='background'||a==='content'||a==='data'||a.indexOf('src')>=0||a.indexOf('url')>=0){if(option.safe&&ux.test(v)){error("ADsafe URL violation.");}
+urls.push(v);}else if(a==='for'){if(option.adsafe){if(adsafe_id){if(v.slice(0,adsafe_id.length)!==adsafe_id){warning("ADsafe violation: An id must have a '{a}' prefix",nexttoken,adsafe_id);}else if(!/^[A-Z]+_[A-Z]+$/.test(v)){warning("ADSAFE violation: bad id.");}}else{warning("ADSAFE violation: bad id.");}}}else if(a==='name'){if(option.adsafe&&v.indexOf('_')>=0){warning("ADsafe name violation.");}}}
+function doTag(n,a){var i,t=htmltag[n],x;src=false;if(!t){error("Unrecognized tag '<{a}>'.",nexttoken,n===n.toLowerCase()?n:n+' (capitalization error)');}
+if(stack.length>0){if(n==='html'){error("Too many <html> tags.",token);}
+x=t.parent;if(x){if(x.indexOf(' '+stack[stack.length-1].name+' ')<0){error("A '<{a}>' must be within '<{b}>'.",token,n,x);}}else if(!option.adsafe&&!option.fragment){i=stack.length;do{if(i<=0){error("A '<{a}>' must be within '<{b}>'.",token,n,'body');}
+i-=1;}while(stack[i].name!=='body');}}
+switch(n){case'div':if(option.adsafe&&stack.length===1&&!adsafe_id){warning("ADSAFE violation: missing ID_.");}
+break;case'script':xmode='script';advance('>');indent=nexttoken.from;if(a.lang){warning("lang is deprecated.",token);}
+if(option.adsafe&&stack.length!==1){warning("ADsafe script placement violation.",token);}
+if(a.src){if(option.adsafe&&(!adsafe_may||!approved[a.src])){warning("ADsafe unapproved script source.",token);}
+if(a.type){warning("type is unnecessary.",token);}}else{if(adsafe_went){error("ADsafe script violation.",token);}
+statements('script');}
+xmode='html';advance('</');if(!nexttoken.identifier&&nexttoken.value!=='script'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'script',nexttoken.value);}
+advance();xmode='outer';break;case'style':xmode='style';advance('>');styles();xmode='html';advance('</');if(!nexttoken.identifier&&nexttoken.value!=='style'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'style',nexttoken.value);}
+advance();xmode='outer';break;case'input':switch(a.type){case'radio':case'checkbox':case'button':case'reset':case'submit':break;case'text':case'file':case'password':case'file':case'hidden':case'image':if(option.adsafe&&a.autocomplete!=='off'){warning("ADsafe autocomplete violation.");}
+break;default:warning("Bad input type.");}
+break;case'applet':case'body':case'embed':case'frame':case'frameset':case'head':case'iframe':case'noembed':case'noframes':case'object':case'param':if(option.adsafe){warning("ADsafe violation: Disallowed tag: "+n);}
+break;}}
+function closetag(n){return'</'+n+'>';}
+function html(){var a,attributes,e,n,q,t,v,w=option.white,wmode;xmode='html';xquote='';stack=null;for(;;){switch(nexttoken.value){case'<':xmode='html';advance('<');attributes={};t=nexttoken;if(!t.identifier){warning("Bad identifier {a}.",t,t.value);}
+n=t.value;if(option.cap){n=n.toLowerCase();}
+t.name=n;advance();if(!stack){stack=[];doBegin(n);}
+v=htmltag[n];if(typeof v!=='object'){error("Unrecognized tag '<{a}>'.",t,n);}
+e=v.empty;t.type=n;for(;;){if(nexttoken.id==='/'){advance('/');if(nexttoken.id!=='>'){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'>',nexttoken.value);}
+break;}
+if(nexttoken.id&&nexttoken.id.substr(0,1)==='>'){break;}
+if(!nexttoken.identifier){if(nexttoken.id==='(end)'||nexttoken.id==='(error)'){error("Missing '>'.",nexttoken);}
+warning("Bad identifier.");}
+option.white=true;nonadjacent(token,nexttoken);a=nexttoken.value;option.white=w;advance();if(!option.cap&&a!==a.toLowerCase()){warning("Attribute '{a}' not all lower case.",nexttoken,a);}
+a=a.toLowerCase();xquote='';if(is_own(attributes,a)){warning("Attribute '{a}' repeated.",nexttoken,a);}
+if(a.slice(0,2)==='on'){if(!option.on){warning("Avoid HTML event handlers.");}
+xmode='scriptstring';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
+xquote=q;wmode=option.white;option.white=false;advance(q);statements('on');option.white=wmode;if(nexttoken.id!==q){error("Missing close quote on script attribute.");}
+xmode='html';xquote='';advance(q);v=false;}else if(a==='style'){xmode='scriptstring';advance('=');q=nexttoken.id;if(q!=='"'&&q!=="'"){error("Missing quote.");}
+xmode='styleproperty';xquote=q;advance(q);substyle();xmode='html';xquote='';advance(q);v=false;}else{if(nexttoken.id==='='){advance('=');v=nexttoken.value;if(!nexttoken.identifier&&nexttoken.id!=='"'&&nexttoken.id!=='\''&&nexttoken.type!=='(string)'&&nexttoken.type!=='(number)'&&nexttoken.type!=='(color)'){warning("Expected an attribute value and instead saw '{a}'.",token,a);}
+advance();}else{v=true;}}
+attributes[a]=v;doAttribute(n,a,v);}
+doTag(n,attributes);if(!e){stack.push(t);}
+xmode='outer';advance('>');break;case'</':xmode='html';advance('</');if(!nexttoken.identifier){warning("Bad identifier.");}
+n=nexttoken.value;if(option.cap){n=n.toLowerCase();}
+advance();if(!stack){error("Unexpected '{a}'.",nexttoken,closetag(n));}
+t=stack.pop();if(!t){error("Unexpected '{a}'.",nexttoken,closetag(n));}
+if(t.name!==n){error("Expected '{a}' and instead saw '{b}'.",nexttoken,closetag(t.name),closetag(n));}
+if(nexttoken.id!=='>'){error("Missing '{a}'.",nexttoken,'>');}
+xmode='outer';advance('>');break;case'<!':if(option.safe){warning("ADsafe HTML violation.");}
+xmode='html';for(;;){advance();if(nexttoken.id==='>'||nexttoken.id==='(end)'){break;}
+if(nexttoken.value.indexOf('--')>=0){warning("Unexpected --.");}
+if(nexttoken.value.indexOf('<')>=0){warning("Unexpected <.");}
+if(nexttoken.value.indexOf('>')>=0){warning("Unexpected >.");}}
+xmode='outer';advance('>');break;case'(end)':return;default:if(nexttoken.id==='(end)'){error("Missing '{a}'.",nexttoken,'</'+stack[stack.length-1].value+'>');}else{advance();}}
+if(stack&&stack.length===0&&(option.adsafe||!option.fragment||nexttoken.id==='(end)')){break;}}
+if(nexttoken.id!=='(end)'){error("Unexpected material after the end.");}}
+type('(number)',idValue);type('(string)',idValue);syntax['(identifier)']={type:'(identifier)',lbp:0,identifier:true,nud:function(){var v=this.value,s=scope[v],f;if(typeof s==='function'){s=undefined;}else if(typeof s==='boolean'){f=funct;funct=functions[0];addlabel(v,'var');s=funct;funct=f;}
+if(funct===s){switch(funct[v]){case'unused':funct[v]='var';break;case'label':warning("'{a}' is a statement label.",token,v);break;}}else if(funct['(global)']){if(option.undef&&predefined[v]!=='boolean'){warning("'{a}' is not defined.",token,v);}
+note_implied(token);}else{switch(funct[v]){case'closure':case'function':case'var':case'unused':warning("'{a}' used out of scope.",token,v);break;case'label':warning("'{a}' is a statement label.",token,v);break;case'outer':case'global':break;default:if(s===true){funct[v]=true;}else if(s===null){warning("'{a}' is not allowed.",token,v);note_implied(token);}else if(typeof s!=='object'){if(option.undef){warning("'{a}' is not defined.",token,v);}else{funct[v]=true;}
+note_implied(token);}else{switch(s[v]){case'function':case'var':case'unused':s[v]='closure';funct[v]=s['(global)']?'global':'outer';break;case'closure':case'parameter':funct[v]=s['(global)']?'global':'outer';break;case'label':warning("'{a}' is a statement label.",token,v);}}}}
+return this;},led:function(){error("Expected an operator and instead saw '{a}'.",nexttoken,nexttoken.value);}};type('(regexp)',function(){return this;});delim('(endline)');delim('(begin)');delim('(end)').reach=true;delim('</').reach=true;delim('<!');delim('<!--');delim('-->');delim('(error)').reach=true;delim('}').reach=true;delim(')');delim(']');delim('"').reach=true;delim("'").reach=true;delim(';');delim(':').reach=true;delim(',');delim('#');delim('@');reserve('else');reserve('case').reach=true;reserve('catch');reserve('default').reach=true;reserve('finally');reservevar('arguments');reservevar('eval');reservevar('false');reservevar('Infinity');reservevar('NaN');reservevar('null');reservevar('this');reservevar('true');reservevar('undefined');assignop('=','assign',20);assignop('+=','assignadd',20);assignop('-=','assignsub',20);assignop('*=','assignmult',20);assignop('/=','assigndiv',20).nud=function(){error("A regular expression literal can be confused with '/='.");};assignop('%=','assignmod',20);bitwiseassignop('&=','assignbitand',20);bitwiseassignop('|=','assignbitor',20);bitwiseassignop('^=','assignbitxor',20);bitwiseassignop('<<=','assignshiftleft',20);bitwiseassignop('>>=','assignshiftright',20);bitwiseassignop('>>>=','assignshiftrightunsigned',20);infix('?',function(left,that){that.left=left;that.right=parse(10);advance(':');that['else']=parse(10);return that;},30);infix('||','or',40);infix('&&','and',50);bitwise('|','bitor',70);bitwise('^','bitxor',80);bitwise('&','bitand',90);relation('==',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'===','==');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'===',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'===',right.value);}
+return this;});relation('===');relation('!=',function(left,right){if(option.eqeqeq){warning("Expected '{a}' and instead saw '{b}'.",this,'!==','!=');}else if(isPoorRelation(left)){warning("Use '{a}' to compare with '{b}'.",this,'!==',left.value);}else if(isPoorRelation(right)){warning("Use '{a}' to compare with '{b}'.",this,'!==',right.value);}
+return this;});relation('!==');relation('<');relation('>');relation('<=');relation('>=');bitwise('<<','shiftleft',120);bitwise('>>','shiftright',120);bitwise('>>>','shiftrightunsigned',120);infix('in','in',120);infix('instanceof','instanceof',120);infix('+',function(left,that){var right=parse(130);if(left&&right&&left.id==='(string)'&&right.id==='(string)'){left.value+=right.value;left.character=right.character;if(jx.test(left.value)){warning("JavaScript URL.",left);}
+return left;}
+that.left=left;that.right=right;return that;},130);prefix('+','num');infix('-','sub',130);prefix('-','neg');infix('*','mult',140);infix('/','div',140);infix('%','mod',140);suffix('++','postinc');prefix('++','preinc');syntax['++'].exps=true;suffix('--','postdec');prefix('--','predec');syntax['--'].exps=true;prefix('delete',function(){var p=parse(0);if(!p||(p.id!=='.'&&p.id!=='[')){warning("Expected '{a}' and instead saw '{b}'.",nexttoken,'.',nexttoken.value);}
+this.first=p;return this;}).exps=true;prefix('~',function(){if(option.bitwise){warning("Unexpected '{a}'.",this,'~');}
+parse(150);return this;});prefix('!',function(){this.right=parse(150);this.arity='unary';if(bang[this.right.id]===true){warning("Confusing use of '{a}'.",this,'!');}
+return this;});prefix('typeof','typeof');prefix('new',function(){var c=parse(155),i;if(c&&c.id!=='function'){if(c.identifier){c['new']=true;switch(c.value){case'Object':warning("Use the object literal notation {}.",token);break;case'Array':if(nexttoken.id!=='('){warning("Use the array literal notation [].",token);}else{advance('(');if(nexttoken.id===')'){warning("Use the array literal notation [].",token);}else{i=parse(0);c.dimension=i;if((i.id==='(number)'&&/[.+\-Ee]/.test(i.value))||(i.id==='-'&&!i.right)||i.id==='(string)'||i.id==='['||i.id==='{'||i.id==='true'||i.id==='false'||i.id==='null'||i.id==='undefined'||i.id==='Infinity'){warning("Use the array literal notation [].",token);}
+if(nexttoken.id!==')'){error("Use the array literal notation [].",token);}}
+advance(')');}
+this.first=c;return this;case'Number':case'String':case'Boolean':case'Math':case'JSON':warning("Do not use {a} as a constructor.",token,c.value);break;case'Function':if(!option.evil){warning("The Function constructor is eval.");}
+break;case'Date':case'RegExp':break;default:if(c.id!=='function'){i=c.value.substr(0,1);if(option.newcap&&(i<'A'||i>'Z')){warning("A constructor name should start with an uppercase letter.",token);}}}}else{if(c.id!=='.'&&c.id!=='['&&c.id!=='('){warning("Bad constructor.",token);}}}else{warning("Weird construction. Delete 'new'.",this);}
+adjacent(token,nexttoken);if(nexttoken.id!=='('){warning("Missing '()' invoking a constructor.");}
+this.first=c;return this;});syntax['new'].exps=true;infix('.',function(left,that){adjacent(prevtoken,token);var m=identifier();if(typeof m==='string'){countMember(m);}
+that.left=left;that.right=m;if(!option.evil&&left&&left.value==='document'&&(m==='write'||m==='writeln')){warning("document.write can be a form of eval.",left);}else if(option.adsafe){if(left&&left.value==='ADSAFE'){if(m==='id'||m==='lib'){warning("ADsafe violation.",that);}else if(m==='go'){if(xmode!=='script'){warning("ADsafe violation.",that);}else if(adsafe_went||nexttoken.id!=='('||peek(0).id!=='(string)'||peek(0).value!==adsafe_id||peek(1).id!==','){error("ADsafe violation: go.",that);}
+adsafe_went=true;adsafe_may=false;}}}
+if(!option.evil&&(m==='eval'||m==='execScript')){warning('eval is evil.');}else if(option.safe){for(;;){if(banned[m]===true){warning("ADsafe restricted word '{a}'.",token,m);}
+if(typeof predefined[left.value]!=='boolean'||nexttoken.id==='('){break;}
+if(standard_member[m]===true){if(nexttoken.id==='.'){warning("ADsafe violation.",that);}
+break;}
+if(nexttoken.id!=='.'){warning("ADsafe violation.",that);break;}
+advance('.');token.left=that;token.right=m;that=token;m=identifier();if(typeof m==='string'){countMember(m);}}}
+return that;},160,true);infix('(',function(left,that){adjacent(prevtoken,token);nospace();var n=0,p=[];if(left){if(left.type==='(identifier)'){if(left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)){if(left.value!=='Number'&&left.value!=='String'&&left.value!=='Boolean'&&left.value!=='Date'){if(left.value==='Math'){warning("Math is not a function.",left);}else if(option.newcap){warning("Missing 'new' prefix when invoking a constructor.",left);}}}}else if(left.id==='.'){if(option.safe&&left.left.value==='Math'&&left.right==='random'){warning("ADsafe violation.",left);}}}
+if(nexttoken.id!==')'){for(;;){p[p.length]=parse(10);n+=1;if(nexttoken.id!==','){break;}
+comma();}}
+advance(')');if(option.immed&&left.id==='function'&&nexttoken.id!==')'){warning("Wrap the entire immediate function invocation in parens.",that);}
+nospace(prevtoken,token);if(typeof left==='object'){if(left.value==='parseInt'&&n===1){warning("Missing radix parameter.",left);}
+if(!option.evil){if(left.value==='eval'||left.value==='Function'||left.value==='execScript'){warning("eval is evil.",left);}else if(p[0]&&p[0].id==='(string)'&&(left.value==='setTimeout'||left.value==='setInterval')){warning("Implied eval is evil. Pass a function instead of a string.",left);}}
+if(!left.identifier&&left.id!=='.'&&left.id!=='['&&left.id!=='('&&left.id!=='&&'&&left.id!=='||'&&left.id!=='?'){warning("Bad invocation.",left);}}
+that.left=left;return that;},155,true).exps=true;prefix('(',function(){nospace();var v=parse(0);advance(')',this);nospace(prevtoken,token);if(option.immed&&v.id==='function'){if(nexttoken.id==='('){warning("Move the invocation into the parens that contain the function.",nexttoken);}else{warning("Do not wrap function literals in parens unless they are to be immediately invoked.",this);}}
+return v;});infix('[',function(left,that){nospace();var e=parse(0),s;if(e&&e.type==='(string)'){if(option.safe&&banned[e.value]===true){warning("ADsafe restricted word '{a}'.",that,e.value);}else if(!option.evil&&(e.value==='eval'||e.value==='execScript')){warning("eval is evil.",that);}else if(option.safe&&(e.value.charAt(0)==='_'||e.value.charAt(0)==='-')){warning("ADsafe restricted subscript '{a}'.",that,e.value);}
+countMember(e.value);if(!option.sub&&ix.test(e.value)){s=syntax[e.value];if(!s||!s.reserved){warning("['{a}'] is better written in dot notation.",e,e.value);}}}else if(!e||e.type!=='(number)'||e.value<0){if(option.safe){warning('ADsafe subscripting.');}}
+advance(']',that);nospace(prevtoken,token);that.left=left;that.right=e;return that;},160,true);prefix('[',function(){var b=token.line!==nexttoken.line;this.first=[];if(b){indent+=option.indent;if(nexttoken.from===indent+option.indent){indent+=option.indent;}}
+while(nexttoken.id!=='(end)'){while(nexttoken.id===','){warning("Extra comma.");advance(',');}
+if(nexttoken.id===']'){break;}
+if(b&&token.line!==nexttoken.line){indentation();}
+this.first.push(parse(10));if(nexttoken.id===','){comma();if(nexttoken.id===']'){warning("Extra comma.",token);break;}}else{break;}}
+if(b){indent-=option.indent;indentation();}
+advance(']',this);return this;},160);(function(x){x.nud=function(){var b,i,s,seen={};b=token.line!==nexttoken.line;if(b){indent+=option.indent;if(nexttoken.from===indent+option.indent){indent+=option.indent;}}
+for(;;){if(nexttoken.id==='}'){break;}
+if(b){indentation();}
+i=optionalidentifier(true);if(!i){if(nexttoken.id==='(string)'){i=nexttoken.value;if(ix.test(i)){s=syntax[i];}
+advance();}else if(nexttoken.id==='(number)'){i=nexttoken.value.toString();advance();}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'}',nexttoken.value);}}
+if(seen[i]===true){warning("Duplicate member '{a}'.",nexttoken,i);}
+seen[i]=true;countMember(i);advance(':');nonadjacent(token,nexttoken);parse(10);if(nexttoken.id===','){comma();if(nexttoken.id===','||nexttoken.id==='}'){warning("Extra comma.",token);}}else{break;}}
+if(b){indent-=option.indent;indentation();}
+advance('}',this);return this;};x.fud=function(){error("Expected to see a statement and instead saw a block.",token);};}(delim('{')));function varstatement(prefix){var id,name,value;if(funct['(onevar)']&&option.onevar){warning("Too many var statements.");}else if(!funct['(global)']){funct['(onevar)']=true;}
+this.first=[];for(;;){nonadjacent(token,nexttoken);id=identifier();if(funct['(global)']&&predefined[id]===false){warning("Redefinition of '{a}'.",token,id);}
+addlabel(id,'unused');if(prefix){break;}
+name=token;this.first.push(token);if(nexttoken.id==='='){nonadjacent(token,nexttoken);advance('=');nonadjacent(token,nexttoken);if(peek(0).id==='='&&nexttoken.identifier){error("Variable {a} was not declared correctly.",nexttoken,nexttoken.value);}
+value=parse(0);name.first=value;}
+if(nexttoken.id!==','){break;}
+comma();}
+return this;}
+stmt('var',varstatement).exps=true;function functionparams(){var i,t=nexttoken,p=[];advance('(');nospace();if(nexttoken.id===')'){advance(')');nospace(prevtoken,token);return;}
+for(;;){i=identifier();p.push(i);addlabel(i,'parameter');if(nexttoken.id===','){comma();}else{advance(')',t);nospace(prevtoken,token);return p;}}}
+function doFunction(i){var s=scope;scope=Object.create(s);funct={'(name)':i||'"'+anonname+'"','(line)':nexttoken.line,'(context)':funct,'(breakage)':0,'(loopage)':0,'(scope)':scope};token.funct=funct;functions.push(funct);if(i){addlabel(i,'function');}
+funct['(params)']=functionparams();block(false);scope=s;funct['(last)']=token.line;funct=funct['(context)'];}
+blockstmt('function',function(){if(inblock){warning("Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.",token);}
+var i=identifier();adjacent(token,nexttoken);addlabel(i,'unused');doFunction(i);if(nexttoken.id==='('&&nexttoken.line===token.line){error("Function statements are not invocable. Wrap the whole function invocation in parens.");}
+return this;});prefix('function',function(){var i=optionalidentifier();if(i){adjacent(token,nexttoken);}else{nonadjacent(token,nexttoken);}
+doFunction(i);if(funct['(loopage)']&&nexttoken.id!=='('){warning("Be careful when making functions within a loop. Consider putting the function in a closure.");}
+return this;});blockstmt('if',function(){var t=nexttoken;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);if(nexttoken.id==='else'){nonadjacent(token,nexttoken);advance('else');if(nexttoken.id==='if'||nexttoken.id==='switch'){statement(true);}else{block(true);}}
+return this;});blockstmt('try',function(){var b,e,s;if(option.adsafe){warning("ADsafe try violation.",this);}
+block(false);if(nexttoken.id==='catch'){advance('catch');nonadjacent(token,nexttoken);advance('(');s=scope;scope=Object.create(s);e=nexttoken.value;if(nexttoken.type!=='(identifier)'){warning("Expected an identifier and instead saw '{a}'.",nexttoken,e);}else{addlabel(e,'exception');}
+advance();advance(')');block(false);b=true;scope=s;}
+if(nexttoken.id==='finally'){advance('finally');block(false);return;}else if(!b){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'catch',nexttoken.value);}
+return this;});blockstmt('while',function(){var t=nexttoken;funct['(breakage)']+=1;funct['(loopage)']+=1;advance('(');nonadjacent(this,t);nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);block(true);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}).labelled=true;reserve('with');blockstmt('switch',function(){var t=nexttoken,g=false;funct['(breakage)']+=1;advance('(');nonadjacent(this,t);nospace();this.condition=parse(20);advance(')',t);nospace(prevtoken,token);nonadjacent(token,nexttoken);t=nexttoken;advance('{');nonadjacent(token,nexttoken);indent+=option.indent;this.cases=[];for(;;){switch(nexttoken.id){case'case':switch(funct['(verb)']){case'break':case'case':case'continue':case'return':case'switch':case'throw':break;default:warning("Expected a 'break' statement before 'case'.",token);}
+indentation(-option.indent);advance('case');this.cases.push(parse(20));g=true;advance(':');funct['(verb)']='case';break;case'default':switch(funct['(verb)']){case'break':case'continue':case'return':case'throw':break;default:warning("Expected a 'break' statement before 'default'.",token);}
+indentation(-option.indent);advance('default');g=true;advance(':');break;case'}':indent-=option.indent;indentation();advance('}',t);if(this.cases.length===1||this.condition.id==='true'||this.condition.id==='false'){warning("This 'switch' should be an 'if'.",this);}
+funct['(breakage)']-=1;funct['(verb)']=undefined;return;case'(end)':error("Missing '{a}'.",nexttoken,'}');return;default:if(g){switch(token.id){case',':error("Each value should have its own case label.");return;case':':statements();break;default:error("Missing ':' on a case clause.",token);}}else{error("Expected '{a}' and instead saw '{b}'.",nexttoken,'case',nexttoken.value);}}}}).labelled=true;stmt('debugger',function(){if(!option.debug){warning("All 'debugger' statements should be removed.");}
+return this;}).exps=true;(function(){var x=stmt('do',function(){funct['(breakage)']+=1;funct['(loopage)']+=1;this.first=block(true);advance('while');var t=nexttoken;nonadjacent(token,t);advance('(');nospace();parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}
+advance(')',t);nospace(prevtoken,token);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;});x.labelled=true;x.exps=true;}());blockstmt('for',function(){var f=option.forin,s,t=nexttoken;funct['(breakage)']+=1;funct['(loopage)']+=1;advance('(');nonadjacent(this,t);nospace();if(peek(nexttoken.id==='var'?1:0).id==='in'){if(nexttoken.id==='var'){advance('var');varstatement(true);}else{switch(funct[nexttoken.value]){case'unused':funct[nexttoken.value]='var';break;case'var':break;default:warning("Bad for in variable '{a}'.",nexttoken,nexttoken.value);}
+advance();}
+advance('in');parse(20);advance(')',t);s=block(true);if(!f&&(s.length>1||typeof s[0]!=='object'||s[0].value!=='if')){warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.",this);}
+funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}else{if(nexttoken.id!==';'){if(nexttoken.id==='var'){advance('var');varstatement();}else{for(;;){parse(0,'for');if(nexttoken.id!==','){break;}
+comma();}}}
+nolinebreak(token);advance(';');if(nexttoken.id!==';'){parse(20);if(nexttoken.id==='='){warning("Expected a conditional expression and instead saw an assignment.");advance('=');parse(20);}}
+nolinebreak(token);advance(';');if(nexttoken.id===';'){error("Expected '{a}' and instead saw '{b}'.",nexttoken,')',';');}
+if(nexttoken.id!==')'){for(;;){parse(0,'for');if(nexttoken.id!==','){break;}
+comma();}}
+advance(')',t);nospace(prevtoken,token);block(true);funct['(breakage)']-=1;funct['(loopage)']-=1;return this;}}).labelled=true;stmt('break',function(){var v=nexttoken.value;if(funct['(breakage)']===0){warning("Unexpected '{a}'.",nexttoken,this.value);}
+nolinebreak(this);if(nexttoken.id!==';'){if(token.line===nexttoken.line){if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+this.first=nexttoken;advance();}}
+reachable('break');return this;}).exps=true;stmt('continue',function(){var v=nexttoken.value;if(funct['(breakage)']===0){warning("Unexpected '{a}'.",nexttoken,this.value);}
+nolinebreak(this);if(nexttoken.id!==';'){if(token.line===nexttoken.line){if(funct[v]!=='label'){warning("'{a}' is not a statement label.",nexttoken,v);}else if(scope[v]!==funct){warning("'{a}' is out of scope.",nexttoken,v);}
+this.first=nexttoken;advance();}}
+reachable('continue');return this;}).exps=true;stmt('return',function(){nolinebreak(this);if(nexttoken.id==='(regexp)'){warning("Wrap the /regexp/ literal in parens to disambiguate the slash operator.");}
+if(nexttoken.id!==';'&&!nexttoken.reach){nonadjacent(token,nexttoken);this.first=parse(20);}
+reachable('return');return this;}).exps=true;stmt('throw',function(){nolinebreak(this);nonadjacent(token,nexttoken);this.first=parse(20);reachable('throw');return this;}).exps=true;reserve('void');reserve('class');reserve('const');reserve('enum');reserve('export');reserve('extends');reserve('import');reserve('super');reserve('let');reserve('yield');reserve('implements');reserve('interface');reserve('package');reserve('private');reserve('protected');reserve('public');reserve('static');function jsonValue(){function jsonObject(){var o={},t=nexttoken;advance('{');if(nexttoken.id!=='}'){for(;;){if(nexttoken.id==='(end)'){error("Missing '}' to match '{' from line {a}.",nexttoken,t.line);}else if(nexttoken.id==='}'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}else if(nexttoken.id!=='(string)'){warning("Expected a string and instead saw {a}.",nexttoken,nexttoken.value);}
+if(o[nexttoken.value]===true){warning("Duplicate key '{a}'.",nexttoken,nexttoken.value);}else if(nexttoken.value==='__proto__'){warning("Stupid key '{a}'.",nexttoken,nexttoken.value);}else{o[nexttoken.value]=true;}
+advance();advance(':');jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance('}');}
+function jsonArray(){var t=nexttoken;advance('[');if(nexttoken.id!==']'){for(;;){if(nexttoken.id==='(end)'){error("Missing ']' to match '[' from line {a}.",nexttoken,t.line);}else if(nexttoken.id===']'){warning("Unexpected comma.",token);break;}else if(nexttoken.id===','){error("Unexpected comma.",nexttoken);}
+jsonValue();if(nexttoken.id!==','){break;}
+advance(',');}}
+advance(']');}
+switch(nexttoken.id){case'{':jsonObject();break;case'[':jsonArray();break;case'true':case'false':case'null':case'(number)':case'(string)':advance();break;case'-':advance('-');if(token.character!==nexttoken.from){warning("Unexpected space after '-'.",token);}
+adjacent(token,nexttoken);advance('(number)');break;default:error("Expected a JSON value.",nexttoken);}}
+var itself=function(s,o){var a,i;JSLINT.errors=[];predefined=Object.create(standard);if(o){a=o.predef;if(a instanceof Array){for(i=0;i<a.length;i+=1){predefined[a[i]]=true;}}
+if(o.adsafe){o.safe=true;}
+if(o.safe){o.browser=false;o.css=false;o.debug=false;o.eqeqeq=true;o.evil=false;o.forin=false;o.nomen=true;o.on=false;o.rhino=false;o.safe=true;o.sidebar=false;o.strict=true;o.sub=false;o.undef=true;o.widget=false;predefined.Date=null;predefined['eval']=null;predefined.Function=null;predefined.Object=null;predefined.ADSAFE=false;predefined.lib=false;}
+option=o;}else{option={};}
+option.indent=option.indent||4;option.maxerr=option.maxerr||50;adsafe_id='';adsafe_may=false;adsafe_went=false;approved={};if(option.approved){for(i=0;i<option.approved.length;i+=1){approved[option.approved[i]]=option.approved[i];}}else{approved.test='test';}
+tab='';for(i=0;i<option.indent;i+=1){tab+=' ';}
+indent=1;global=Object.create(predefined);scope=global;funct={'(global)':true,'(name)':'(global)','(scope)':scope,'(breakage)':0,'(loopage)':0};functions=[funct];ids={};urls=[];src=false;xmode=false;stack=null;member={};membersOnly=null;implied={};inblock=false;lookahead=[];jsonmode=false;warnings=0;lex.init(s);prereg=true;strict_mode=false;prevtoken=token=nexttoken=syntax['(begin)'];assume();try{advance();if(nexttoken.value.charAt(0)==='<'){html();if(option.adsafe&&!adsafe_went){warning("ADsafe violation: Missing ADSAFE.go.",this);}}else{switch(nexttoken.id){case'{':case'[':option.laxbreak=true;jsonmode=true;jsonValue();break;case'@':case'*':case'#':case'.':case':':xmode='style';advance();if(token.id!=='@'||!nexttoken.identifier||nexttoken.value!=='charset'||token.line!==1||token.from!==1){error('A css file should begin with @charset "UTF-8";');}
+advance();if(nexttoken.type!=='(string)'&&nexttoken.value!=='UTF-8'){error('A css file should begin with @charset "UTF-8";');}
+advance();advance(';');styles();break;default:if(option.adsafe&&option.fragment){error("Expected '{a}' and instead saw '{b}'.",nexttoken,'<div>',nexttoken.value);}
+statements('lib');}}
+advance('(end)');}catch(e){if(e){JSLINT.errors.push({reason:e.message,line:e.line||nexttoken.line,character:e.character||nexttoken.from},null);}}
+return JSLINT.errors.length===0;};function is_array(o){return Object.prototype.toString.apply(o)==='[object Array]';}
+function to_array(o){var a=[],k;for(k in o){if(is_own(o,k)){a.push(k);}}
+return a;}
+itself.data=function(){var data={functions:[]},fu,globals,implieds=[],f,i,j,members=[],n,unused=[],v;if(itself.errors.length){data.errors=itself.errors;}
+if(jsonmode){data.json=true;}
+for(n in implied){if(is_own(implied,n)){implieds.push({name:n,line:implied[n]});}}
+if(implieds.length>0){data.implieds=implieds;}
+if(urls.length>0){data.urls=urls;}
+globals=to_array(scope);if(globals.length>0){data.globals=globals;}
+for(i=1;i<functions.length;i+=1){f=functions[i];fu={};for(j=0;j<functionicity.length;j+=1){fu[functionicity[j]]=[];}
+for(n in f){if(is_own(f,n)&&n.charAt(0)!=='('){v=f[n];if(is_array(fu[v])){fu[v].push(n);if(v==='unused'){unused.push({name:n,line:f['(line)'],'function':f['(name)']});}}}}
+for(j=0;j<functionicity.length;j+=1){if(fu[functionicity[j]].length===0){delete fu[functionicity[j]];}}
+fu.name=f['(name)'];fu.param=f['(params)'];fu.line=f['(line)'];fu.last=f['(last)'];data.functions.push(fu);}
+if(unused.length>0){data.unused=unused;}
+members=[];for(n in member){if(typeof member[n]==='number'){data.member=member;break;}}
+return data;};itself.report=function(option){var data=itself.data();var a=[],c,e,err,f,i,k,l,m='',n,o=[],s;function detail(h,s){if(s){o.push('<div><i>'+h+'</i> '+
+s.sort().join(', ')+'</div>');}}
+if(data.errors||data.implieds||data.unused){err=true;o.push('<div id=errors><i>Error:</i>');if(data.errors){for(i=0;i<data.errors.length;i+=1){c=data.errors[i];if(c){e=c.evidence||'';o.push('<p>Problem'+(isFinite(c.line)?' at line '+
+c.line+' character '+c.character:'')+': '+c.reason.entityify()+'</p><p class=evidence>'+
+(e&&(e.length>80?e.slice(0,77)+'...':e).entityify())+'</p>');}}}
+if(data.implieds){s=[];for(i=0;i<data.implieds.length;i+=1){s[i]='<code>'+data.implieds[i].name+'</code>&nbsp;<i>'+
+data.implieds[i].line+'</i>';}
+o.push('<p><i>Implied global:</i> '+s.join(', ')+'</p>');}
+if(data.unused){s=[];for(i=0;i<data.unused.length;i+=1){s[i]='<code><u>'+data.unused[i].name+'</u></code>&nbsp;<i>'+
+data.unused[i].line+'</i> <code>'+
+data.unused[i]['function']+'</code>';}
+o.push('<p><i>Unused variable:</i> '+s.join(', ')+'</p>');}
+if(data.json){o.push('<p>JSON: bad.</p>');}
+o.push('</div>');}
+if(!option){o.push('<br><div id=functions>');if(data.urls){detail("URLs<br>",data.urls,'<br>');}
+if(data.json&&!err){o.push('<p>JSON: good.</p>');}else if(data.globals){o.push('<div><i>Global</i> '+
+data.globals.sort().join(', ')+'</div>');}else{o.push('<div><i>No new global variables introduced.</i></div>');}
+for(i=0;i<data.functions.length;i+=1){f=data.functions[i];o.push('<br><div class=function><i>'+f.line+'-'+
+f.last+'</i> '+(f.name||'')+'('+
+(f.param?f.param.join(', '):'')+')</div>');detail('<big><b>Unused</b></big>',f.unused);detail('Closure',f.closure);detail('Variable',f['var']);detail('Exception',f.exception);detail('Outer',f.outer);detail('Global',f.global);detail('Label',f.label);}
+if(data.member){a=to_array(data.member);if(a.length){a=a.sort();m='<br><pre id=members>/*members ';l=10;for(i=0;i<a.length;i+=1){k=a[i];n=k.name();if(l+n.length>72){o.push(m+'<br>');m=' ';l=1;}
+l+=n.length+2;if(data.member[k]===1){n='<i>'+n+'</i>';}
+if(i<a.length-1){n+=', ';}
+m+=n;}
+o.push(m+'<br>*/</pre>');}
+o.push('</div>');}}
+return o.join('');};itself.jslint=itself;itself.edition='2009-10-04';return itself;}());(function(a){var e,i,input;if(!a[0]){print("Usage: jslint.js file.js");quit(1);}
+input=readFile(a[0]);if(!input){print("jslint: Couldn't open file '"+a[0]+"'.");quit(1);}
+if(!JSLINT(input,{bitwise:true,eqeqeq:true,immed:true,newcap:true,nomen:true,onevar:true,plusplus:true,regexp:true,rhino:true,undef:true,white:true})){for(i=0;i<JSLINT.errors.length;i+=1){e=JSLINT.errors[i];if(e){print('Lint at line '+e.line+' character '+
+e.character+': '+e.reason);print((e.evidence||'').replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"));print('');}}
+quit(0);}else{print("jslint: No problems found in "+a[0]);quit();}}(arguments));
diff --git a/emacs.d/nxhtml/related/moz.el b/emacs.d/nxhtml/related/moz.el
new file mode 100644
index 0000000..e910286
--- /dev/null
+++ b/emacs.d/nxhtml/related/moz.el
@@ -0,0 +1,289 @@
+;;; moz.el --- Lets current buffer interact with inferior mozilla.
+
+;; URL: http://github.com/bard/mozrepl/raw/master/chrome/content/moz.el
+
+;; Copyright (C) 2006 by Massimiliano Mirra
+;;
+;; 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 2 of the License, 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; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+;;
+;; Author: Massimiliano Mirra, <bard [at] hyperstruct [dot] net>
+;; Contributors:
+;; - Lennart Borgman
+
+;;; Commentary:
+;;
+;; This file implements communication with Firefox via MozRepl
+;; (http://hyperstruct.net/projects/mozrepl). It is a slightly
+;; modified version of the file moz.el that comes with MozLab. To use
+;; it you have to install the MozRepl addon in Firefox.
+;;
+;; This file contains
+;;
+;; * a major mode for direct interaction in a buffer (as with
+;; telnet) with MozRepl, `inferior-moz-mode'.
+;; * a minor mode for sending code portions or whole files from
+;; other buffers to MozRepl, `moz-minor-mode'.
+;;
+;; Assuming you want to use javascript-mode to edit Javascript files,
+;; enter the following in your .emacs initialization file (from Emacs
+;; integration in the help text):
+;;
+;; (add-to-list 'auto-mode-alist '("\\.js$" . javascript-mode))
+;; (autoload 'inferior-moz-mode "moz" "MozRepl Inferior Mode" t)
+;; (autoload 'moz-minor-mode "moz" "MozRepl Minor Mode" t)
+;; (add-hook 'javascript-mode-hook 'javascript-moz-setup)
+;; (defun javascript-moz-setup () (moz-minor-mode 1))
+;;
+;; Replace javascript-mode above with the name of your favorite
+;; javascript mode.
+;;
+;; If you got this with nXhtml the setup above is already done for
+;; you.
+;;
+;; *Note 1* You have to start the MozRepl server in Firefox (or
+;; whatever Mozilla browser you use). From the menus do
+;;
+;; Tools - MozRepl - Start
+;;
+;; *Note 2* For clearness and brevity the documentation says Firefox
+;; where the correct term should rather be "your Mozilla web
+;; browser".
+
+;;; Change log:
+;;
+;; 2008-07-20: Lennart Borgman
+;; - Add `moz-minor-mode-map'.
+;; - Add `inferior-moz-insert-moz-repl'.
+;; - Add `inferior-moz-mode-map'.
+;; - Add doc strings to interactive functions.
+;; - Make minor enhancements to documentation etc.
+;; - Change Mozilla to Firefox/MozRepl for clarity and brevity.
+;; - Add error handling when starting MozRepl.
+
+;;; Code:
+
+(require 'comint)
+(require 'cc-cmds)
+
+;; Maybe fix-me: C-c control-char are reserved for major modes. But
+;; this minor mode is used in only one major mode (or one family of
+;; major modes) so it complies I think ...
+(defvar moz-minor-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-c\C-s" 'run-mozilla)
+ (define-key map "\C-\M-x" 'moz-send-defun)
+ (define-key map "\C-c\C-c" 'moz-send-defun-and-go)
+ (define-key map "\C-c\C-r" 'moz-send-region)
+ (define-key map "\C-c\C-l" 'moz-save-buffer-and-send)
+ map))
+
+;;;###autoload
+(define-minor-mode moz-minor-mode
+ "MozRepl minor mode for interaction with Firefox.
+With no argument, this command toggles the mode.
+Non-null prefix argument turns on the mode.
+Null prefix argument turns off the mode.
+
+When this minor mode is enabled, some commands become available
+to send current code area \(as understood by c-mark-function) or
+region or buffer to an inferior MozRepl process (which will be
+started as needed).
+
+The following keys are bound in this minor mode:
+
+\\{moz-minor-mode-map}"
+ nil
+ " Moz"
+ :keymap moz-minor-mode-map
+ :group 'moz)
+
+(defalias 'run-mozilla 'inferior-moz-switch-to-mozilla)
+
+(defvar moz-repl-name "repl"
+ "The current name of the repl.")
+
+(defvar moz-input-separator "\n--end-remote-input\n")
+
+(defvar moz-repl-host "localhost")
+
+(defvar moz-repl-port 4242)
+
+(defvar moz-temporary-file nil)
+
+(defun moz-temporary-file ()
+ (if (and moz-temporary-file
+ (file-readable-p moz-temporary-file))
+ moz-temporary-file
+ (setq moz-temporary-file (make-temp-file "emacs-mozrepl"))))
+
+(defun moz-send-region (start end)
+ "Send the region to Firefox via MozRepl."
+ (interactive "r")
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); "
+ moz-repl-name ".setenv('printPrompt', false); "
+ moz-repl-name ".setenv('inputMode', 'multiline'); "
+ "undefined; \n"))
+ ;; Give the previous line a chance to be evaluated on its own. If
+ ;; it gets concatenated to the following ones, we are doomed.
+ (sleep-for 0 1)
+ (comint-send-region (inferior-moz-process)
+ start end)
+ (comint-send-string (inferior-moz-process)
+ "\n--end-remote-input\n")
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".popenv('inputMode', 'printPrompt'); "
+ "undefined; \n"))
+ (comint-send-string (inferior-moz-process)
+ "\n--end-remote-input\n")
+ (display-buffer (process-buffer (inferior-moz-process))))
+
+(defun moz-send-defun ()
+ "Send the current function to Firefox via MozRepl.
+Curent function is the one recognized by c-mark-function."
+ (interactive)
+ (save-excursion
+ (c-mark-function)
+ (moz-send-region (point) (mark))))
+
+(defun moz-send-defun-and-go ()
+ "Send the current function to Firefox via MozRepl.
+Also switch to the interaction buffer."
+ (interactive)
+ (moz-send-defun)
+ (inferior-moz-switch-to-mozilla nil))
+
+(defun moz-save-buffer-and-send ()
+ "Save the current buffer and load it in Firefox via MozRepl."
+ (interactive)
+ (save-buffer)
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".pushenv('printPrompt', 'inputMode'); "
+ moz-repl-name ".setenv('inputMode', 'line'); "
+ moz-repl-name ".setenv('printPrompt', false); undefined; "))
+ (comint-send-string (inferior-moz-process)
+ (concat moz-repl-name ".load('file://localhost/" (buffer-file-name) "');\n"
+ moz-repl-name ".popenv('inputMode', 'printPrompt'); undefined;\n"))
+ (display-buffer (process-buffer (inferior-moz-process))))
+
+;;; Inferior Mode
+
+(defvar inferior-moz-buffer nil
+ "The buffer in which the inferior process is running.")
+
+(defun inferior-moz-insert-moz-repl ()
+ "Insert value of `moz-repl-name' and a dot (.)."
+ (interactive) (insert moz-repl-name "."))
+
+(defvar inferior-moz-mode-map
+ (let ((map (make-sparse-keymap)))
+ ;; Note: changed from C-c c which is reserved for users.
+ (define-key map "\C-c\C-c" 'inferior-moz-insert-moz-repl)
+ map))
+
+;;;###autoload
+(define-derived-mode inferior-moz-mode comint-mode "Inf-MozRepl"
+ "Major mode for interacting with Firefox via MozRepl."
+ (setq comint-input-sender 'inferior-moz-input-sender)
+ (add-hook 'comint-output-filter-functions 'inferior-moz-track-repl-name nil t))
+
+(defun inferior-moz-track-repl-name (comint-output)
+ (save-match-data
+ (when (string-match "\\(\\w+\\)> $" comint-output)
+ (setq moz-repl-name (match-string 1 comint-output)))))
+
+(defun inferior-moz-self-insert-or-repl-name ()
+ (interactive)
+ (if (looking-back "\\(\\w+\\)> $")
+ (insert moz-repl-name ".")
+ (insert last-command-event)))
+
+(defun inferior-moz-input-sender (proc string)
+ "Custom function to send input with comint-send-input.
+Instead of sending input and newline separately like in
+comint-simple-send, here we *first* concatenate input and
+newline, then send it all together. This prevents newline to be
+interpreted on its own."
+ (comint-send-string proc (concat string "\n")))
+
+(defun inferior-moz-switch-to-mozilla (arg)
+ "Switch to the inferior MozRepl buffer.
+Create the buffer and start the MozRepl process and connect to
+Firefox if needed.
+
+See also `inferior-moz-start-process'."
+ (interactive "P")
+ (when arg
+ (setq moz-repl-host (read-string "Host: " "localhost"))
+ (setq moz-repl-port (read-number "Port: " 4242)))
+ (pop-to-buffer (process-buffer (inferior-moz-process)))
+ (goto-char (process-mark (inferior-moz-process))))
+
+(defun inferior-moz-process ()
+ "Return inferior MozRepl process. Start it if necessary.
+See also `inferior-moz-start-process'."
+ (or (if (buffer-live-p inferior-moz-buffer)
+ (get-buffer-process inferior-moz-buffer))
+ (progn
+ (inferior-moz-start-process)
+ (inferior-moz-process))))
+
+(defvar mozrepl-home-page "http://hyperstruct.net/projects/mozrepl")
+
+(defun inferior-moz-start-process ()
+ "Start an inferior Mozrepl process and connect to Firefox.
+It runs the hook `inferior-moz-hook' after starting the process
+and setting up the inferior Firefox buffer.
+
+Note that you have to start the MozRepl server from Firefox."
+ (interactive)
+ (condition-case err
+ (progn
+ (setq inferior-moz-buffer
+ (apply 'make-comint "MozRepl" (cons moz-repl-host moz-repl-port) nil nil))
+ (sleep-for 0 100)
+ (with-current-buffer inferior-moz-buffer
+ (inferior-moz-mode)
+ (run-hooks 'inferior-moz-hook)))
+ (file-error
+ (with-output-to-temp-buffer (help-buffer)
+ (help-setup-xref (list #'describe-function 'inferior-moz-start-process) (interactive-p))
+ (with-current-buffer (help-buffer)
+ (insert "Can't start MozRepl, the error message was:\n\n "
+ (error-message-string err)
+ "\n"
+ "\nA possible reason is that you have not installed"
+ "\nthe MozRepl add-on to Firefox or that you have not"
+ "\nstarted it. You start it from the menus in Firefox:"
+ "\n\n Tools / MozRepl / Start"
+ "\n"
+ "\nSee ")
+ (insert-text-button
+ "MozRepl home page"
+ 'action (lambda (button)
+ (browse-url mozrepl-home-page))
+ 'help-echo mozrepl-home-page
+ 'face 'button)
+ (insert
+ " for more information."
+ "\n"
+ "\nMozRepl is also available directly from Firefox add-on"
+ "\npages, but is updated less frequently there.")
+ ))
+ (error "Can't start MozRepl"))))
+
+(provide 'moz)
+
+;;; moz.el ends here
diff --git a/emacs.d/nxhtml/related/mozadd.el b/emacs.d/nxhtml/related/mozadd.el
new file mode 100644
index 0000000..a303fe4
--- /dev/null
+++ b/emacs.d/nxhtml/related/mozadd.el
@@ -0,0 +1,369 @@
+;;; mozadd.el --- Additional functionality for MozRepl
+;;
+;; Author: Lennart Borgman (lennart O borgman A gmail O com)
+;; Created: 2009-07-22 Wed
+(defconst mozadd:version "0.2") ;; Version:
+;; Last-Updated: 2009-08-04 Tue
+;; URL:
+;; Keywords:
+;; Compatibility:
+;;
+;; Features that might be required by this library:
+;;
+ ;; `cc-cmds', `cc-defs', `cc-engine', `cc-vars', `comint', `json',
+ ;; `moz', `regexp-opt', `ring'.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Live tracking of editing changes, see
+;; `mozadd-mirror-mode'
+;; `mozadd-refresh-edited-on-save-mode'
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Change log:
+;;
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; 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, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(require 'moz)
+(require 'json)
+
+(defun mozadd-warning (format-string &rest args)
+ (let ((str (apply 'format format-string args)))
+ (message "%s" (propertize str 'face 'secondary-selection))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Refresh Firefox after save etc
+
+;; Partly after an idea on EmacsWiki
+
+(defvar mozadd-edited-buffer nil)
+(setq mozadd-edited-buffer nil)
+
+;;;###autoload
+(define-minor-mode mozadd-refresh-edited-on-save-mode
+ "Refresh mozadd edited file in Firefox when saving file.
+The mozadd edited file is the file in the last buffer visited in
+`mozadd-mirror-mode'.
+
+You can use this for example when you edit CSS files.
+
+The mozadd edited file must be shown in Firefox and visible."
+ :lighter "MozRefresh"
+ (if mozadd-refresh-edited-on-save-mode
+ (add-hook 'after-save-hook 'mozadd-queue-reload-mozilla-edited-file nil t)
+ (remove-hook 'after-save-hook 'mozadd-queue-reload-mozilla-edited-file t)))
+(put 'mozadd-refresh-edited-on-save-mode 'permanent-local t)
+
+;;;###autoload
+(define-globalized-minor-mode global-mozadd-refresh-edited-on-save-mode
+ mozadd-refresh-edited-on-save-mode
+ (lambda ()
+ (when (or (derived-mode-p 'css-mode)
+ (mozadd-html-buffer-file-p))
+ (mozadd-refresh-edited-on-save-mode 1))))
+
+(defun mozadd-queue-reload-mozilla-edited-file ()
+ "Reload edited file."
+ (when (buffer-live-p mozadd-edited-buffer)
+ (if (buffer-modified-p mozadd-edited-buffer)
+ (mozadd-warning "Mozadd: Edited buffer %s is not saved, can't reload browser."
+ (buffer-name mozadd-edited-buffer))
+ (mozadd-add-queue-get-mirror-location)
+ (mozadd-add-task-1 'mozadd-send-refresh-edited-to-mozilla))))
+
+(defun mozadd-send-refresh-edited-to-mozilla ()
+ "Update the remote mozrepl instance"
+ (with-current-buffer mozadd-edited-buffer
+ (if (not (mozadd-edited-file-is-shown))
+ (mozadd-warning "Mozadd: Edited buffer %s is not shown, can't reload browser."
+ (buffer-name mozadd-edited-buffer))
+ (comint-send-string (inferior-moz-process)
+ "setTimeout(BrowserReload(), \"1000\");")))
+ (mozadd-exec-next))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mirror html buffer in Firefox
+
+;; Partly after an idea on
+;; http://people.internetconnection.net/2009/02/interactive-html-development-in-emacs/
+
+;; Fun, it kind of works, but is perhaps totally useless .... - slow
+;; and maybe scrolling... - but the file I am testing with have 3000
+;; lines...
+
+;; Fix-me: How do you get the currently shown page in Firefox?
+
+(defun mozadd-perhaps-start ()
+ "Start if MozRepl if not running. Return message if not ok."
+ (unless (buffer-live-p inferior-moz-buffer)
+ (condition-case err
+ (progn
+ (inferior-moz-start-process)
+ nil)
+ (error (error-message-string err)))))
+
+(defvar mozadd-mirror-location nil)
+(make-variable-buffer-local 'mozadd-mirror-location)
+(put 'mozadd-mirror-location 'permanent-local t)
+
+(defvar mozadd-initial-mirror-location nil)
+(make-variable-buffer-local 'mozadd-initial-mirror-location)
+(put 'mozadd-initial-mirror-location 'permanent-local t)
+
+;;(mozadd-get-comint-string-part "\"hi\" there")
+(defun mozadd-get-comint-string-part (comint-output)
+ (save-match-data
+ (if (string-match "^\".*?\"" comint-output)
+ (match-string 0 comint-output)
+ comint-output)))
+
+(defun mozadd-get-initial-mirror-location (comint-output)
+ ;;(message "mozadd-get-initial-mirror-location %S" comint-output)
+ (with-current-buffer mozadd-edited-buffer
+ (setq mozadd-initial-mirror-location (mozadd-get-comint-string-part comint-output)))
+ (mozadd-exec-next)
+ comint-output)
+
+(defun mozadd-get-mirror-location (comint-output)
+ ;;(message "mozadd-get-mirror-location %S" comint-output)
+ (with-current-buffer mozadd-edited-buffer
+ (setq mozadd-mirror-location (mozadd-get-comint-string-part comint-output)))
+ (mozadd-exec-next)
+ comint-output)
+
+(defun mozadd-add-queue-get-mirror-location ()
+ (mozadd-add-task "content.location.href" 'mozadd-get-mirror-location))
+
+(defun mozadd-skip-output-until-prompt (comint-output)
+ ;;(message "mozadd-skip-output-until-prompt %S" comint-output)
+ (if (not (string-match-p "\\(\\w+\\)> $" comint-output))
+ ""
+ ;;(message "done recieve %s" (current-time-string))
+ (mozadd-exec-next)
+ comint-output
+ ""
+ ))
+
+(defun mozadd-queue-send-buffer-content-to-mozilla (buffer)
+ (mozadd-add-queue-get-mirror-location)
+ (setq mozadd-edited-buffer buffer)
+ (mozadd-add-task-1 'mozadd-send-buffer-content-to-mozilla))
+
+(defun mozadd-edited-file-is-shown ()
+ (with-current-buffer mozadd-edited-buffer
+ (string= mozadd-mirror-location mozadd-initial-mirror-location)))
+
+(defvar mozadd-xml-path-outline-style "2px solid red")
+(defun mozadd-send-buffer-content-to-mozilla ()
+ "Update the remote mozrepl instance"
+ (with-current-buffer mozadd-edited-buffer
+ (if (mozadd-edited-file-is-shown)
+ (mozadd-requeue-me-as-task
+ (concat "content.document.body.innerHTML="
+ (json-encode
+ (save-restriction
+ (widen)
+ (let ((where-points nil)
+ (str "")
+ (p1 (point-min))
+ p2)
+ ;; If nxml-where-mode is on add corresponding outline style.
+ (when (and (boundp 'nxml-where-mode) nxml-where-mode)
+ (mapc (lambda (ovl)
+ (when (overlay-get ovl 'nxml-where)
+ (when (/= ?/ (1+ (char-after (overlay-start ovl))))
+ (push (1- (overlay-end ovl)) where-points))))
+ (overlays-in (point-min) (point-max)))
+ (setq where-points (sort where-points '<)))
+ (dolist (p2 where-points)
+ (setq str (concat str
+ (buffer-substring-no-properties p1
+ p2)))
+ (setq str (concat str
+ " style=\"outline: "
+ mozadd-xml-path-outline-style
+ "\""))
+ (setq p1 p2)
+ )
+ (setq str (concat str
+ (buffer-substring-no-properties p1
+ (point-max))))
+ str))
+ )
+ ";")
+ 'mozadd-skip-output-until-prompt)
+ (mozadd-skip-current-task))
+ ;; Timer to avoid looping
+ (run-with-idle-timer 0 nil 'mozadd-maybe-exec-next)
+ ))
+
+(defvar mozadd-current-task nil)
+(setq mozadd-current-task nil)
+
+(defvar mozadd-task-queue nil)
+(setq mozadd-task-queue nil)
+;;(mozadd-add-task "content.location.href" 'mozadd-get-initial-mirror-location)
+;;(mozadd-add-task "hi" 1)
+;;(mozadd-add-task "hm" 2)
+
+(defun mozadd-clear-exec-queue ()
+ (setq mozadd-current-task nil)
+ (setq mozadd-task-queue nil)
+ (when (buffer-live-p inferior-moz-buffer)
+ (with-current-buffer inferior-moz-buffer
+ (dolist (fun (buffer-local-value 'comint-preoutput-filter-functions (current-buffer)))
+ (remove-hook 'comint-preoutput-filter-functions fun t)))))
+
+(defun mozadd-add-task (input task)
+ (mozadd-add-task-1 (list input task)))
+
+(defun mozadd-add-task-1 (task)
+ (setq mozadd-task-queue (cons task mozadd-task-queue))
+ (setq mozadd-task-queue (reverse mozadd-task-queue))
+ ;;(message "add-task: mozadd-task-queue=%S, current=%s" mozadd-task-queue mozadd-current-task)
+ (mozadd-maybe-exec-next))
+
+(defun mozadd-maybe-exec-next ()
+ ;;(message "mozadd-maybe-exec-next, current=%s" mozadd-current-task)
+ (unless mozadd-current-task
+ (mozadd-exec-next)))
+
+(defun mozadd-exec-next ()
+ (when mozadd-current-task
+ (let* ((old-task mozadd-current-task) ;;(pop mozadd-task-queue))
+ (old-filter (when (listp old-task) (nth 1 old-task))))
+ (when (and old-filter (buffer-live-p inferior-moz-buffer))
+ (with-current-buffer inferior-moz-buffer
+ (remove-hook 'comint-preoutput-filter-functions old-filter t)))))
+ (setq mozadd-current-task nil)
+ (when mozadd-task-queue
+ (let* ((this (pop mozadd-task-queue))
+ (input (when (listp this) (nth 0 this)))
+ (task (when (listp this) (nth 1 this)))
+ )
+ (setq mozadd-current-task this)
+ ;;(message "EXEC: %s" this)
+ (if (not (listp this))
+ (funcall this)
+ (when (buffer-live-p inferior-moz-buffer)
+ (with-current-buffer inferior-moz-buffer
+ (add-hook 'comint-preoutput-filter-functions task nil t)))
+ (comint-send-string (inferior-moz-process) input)))))
+
+(defun mozadd-skip-current-task ()
+ ;;(message "mozadd-skip-current-task")
+ ;;(pop mozadd-task-queue)
+ (setq mozadd-current-task nil))
+
+(defun mozadd-requeue-me-as-task (input task)
+ (mozadd-skip-current-task)
+ ;;(message "mozadd-requeue-me-as-task %S %S" input task)
+ (setq mozadd-task-queue (cons (list input task) mozadd-task-queue)))
+
+(defcustom mozadd-browseable-file-extensions
+ '("html" "htm" "xhtml")
+ "File extensions possibly viewable in a web browser."
+ :type '(repeat (string :tag "File extension (without leading dot)"))
+ :group 'mozadd)
+
+(defun mozadd-html-buffer-file-p ()
+ "Return non-nil if buffer file is viewable in a web browser."
+ (when (buffer-file-name)
+ (member (file-name-extension (buffer-file-name))
+ mozadd-browseable-file-extensions)))
+
+;;;###autoload
+(define-minor-mode mozadd-mirror-mode
+ "Mirror content of current file buffer immediately in Firefox.
+When you turn on this mode the file will be opened in Firefox.
+Every change you make in the buffer will trigger a redraw in
+Firefox - regardless of if you save the file or not.
+
+For the mirroring to work the edited file must be shown in
+Firefox and visible.
+
+If `nxml-where-mode' is on the marks will also be shown in
+Firefox as CSS outline style. You can customize the style
+through the option `mozadd-xml-path-outline-style'.
+
+See also `mozadd-refresh-edited-on-save-mode'."
+ nil
+ :lighter " MozMirror"
+ :group 'mozadd
+ (if mozadd-mirror-mode
+ (unless (catch 'ok
+ (unless (mozadd-html-buffer-file-p)
+ (mozadd-warning "You can only mirror html file buffers")
+ (throw 'ok nil))
+ (when (buffer-modified-p)
+ (mozadd-warning "Please save buffer first")
+ (throw 'ok nil))
+ (let ((msg (mozadd-perhaps-start)))
+ (when msg
+ (mozadd-warning msg)
+ (throw 'ok nil)))
+ (mozadd-clear-exec-queue)
+ (setq mozadd-edited-buffer (current-buffer))
+ (mozadd-add-task (concat "content.location.href = "
+ "\"file:///" (buffer-file-name) "\";")
+ 'mozadd-get-initial-mirror-location)
+ (add-hook 'after-change-functions 'mozadd-update-mozilla t t)
+ (add-hook 'nxhtml-where-hook 'mozadd-update-mozilla t t)
+ (add-hook 'post-command-hook 'mozadd-edited-buffer-post-command)
+ t)
+ (setq mozadd-mirror-mode nil))
+ (setq mozadd-edited-buffer nil)
+ (remove-hook 'post-command-hook 'mozadd-edited-buffer-post-command)
+ (remove-hook 'nxhtml-where-hook 'mozadd-update-mozilla t)
+ (remove-hook 'after-change-functions 'mozadd-update-mozilla t)))
+(put 'mozadd-mirror-mode 'permanent-local t)
+
+;;;###autoload
+(define-globalized-minor-mode global-mozadd-mirror-mode mozadd-mirror-mode
+ (lambda ()
+ (when (mozadd-html-buffer-file-p)
+ (mozadd-mirror-mode 1))))
+
+(defun mozadd-edited-buffer-post-command ()
+ "Check if we are in a new edited buffer."
+ (when mozadd-mirror-mode
+ (setq mozadd-edited-buffer (current-buffer))))
+
+
+(defvar mozadd-buffer-content-to-mozilla-timer nil)
+
+(defun mozadd-update-mozilla (&rest ignored)
+ (when (timerp mozadd-buffer-content-to-mozilla-timer)
+ (cancel-timer mozadd-buffer-content-to-mozilla-timer))
+ (setq mozadd-buffer-content-to-mozilla-timer
+ (run-with-idle-timer 1 nil 'mozadd-queue-send-buffer-content-to-mozilla (current-buffer))))
+(put 'mozadd-update-mozilla 'permanent-local-hook t)
+
+
+(provide 'mozadd)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; mozadd.el ends here
diff --git a/emacs.d/nxhtml/related/php-imenu.el b/emacs.d/nxhtml/related/php-imenu.el
new file mode 100644
index 0000000..560bac0
--- /dev/null
+++ b/emacs.d/nxhtml/related/php-imenu.el
@@ -0,0 +1,174 @@
+;;; php-imenu.el --- object-oriented, hierarchical imenu for PHP
+;;;
+;;; Maintainer: Marcel Cary <marcel-cary of care2.com>
+;;; Keywords: php languages oop
+;;; Created: 2008-06-23
+;;; Modified: 2008-07-18
+;;; X-URL: http://www.oak.homeunix.org/~marcel/blog/articles/2008/07/14/nested-imenu-for-php
+;;;
+;;; Copyright (C) 2008 Marcel Cary
+;;;
+;;; 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 2
+;;; of the License, 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; if not, write to the Free Software
+;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+;;;
+;;;
+;;; Usage
+;;;
+;;; Rename this file to php-imenu.el if it isn't already then place it in
+;;; your Emacs lisp path (eg. site-lisp) and add to your .emacs file:
+;;;
+;;;--------------cut here-------------------------------------------
+; ;; Load the php-imenu index function
+; (autoload 'php-imenu-create-index "php-imenu" nil t)
+; ;; Add the index creation function to the php-mode-hook
+; (add-hook 'php-mode-user-hook 'php-imenu-setup)
+; (defun php-imenu-setup ()
+; (setq imenu-create-index-function (function php-imenu-create-index))
+; ;; uncomment if you prefer speedbar:
+; ;(setq php-imenu-alist-postprocessor (function reverse))
+; (imenu-add-menubar-index)
+; )
+;;;----------------end here--------------------------------------------
+;;;
+;;; Commentary
+;;;
+;;; Refines php-mode's imenu support. Imenu provides a menubar entry called
+;;; "Index" that allows you to jump to a structural element of a file. While
+;;; php-mode generates separate lists of functions and classes in imenu,
+;;; php-imenu.el (this code) generates a tree of class and function
+;;; definitions. It lists functions under the classes in which they're
+;;; defined. The hierarchical display of functions within their classes makes
+;;; the "Index" menu far more useful in understanding the high-level structure
+;;; of a file, and it makes it easier to find a method when a file contains
+;;; multiple by the same name.
+;;;
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'imenu)
+(require 'thingatpt)
+
+;;; Alas, speedbar shows menu items in reverse, but only below the top level.
+;;; Provide a way to fix it. See sample configuration in file comment.
+(defvar php-imenu-alist-postprocessor (function identity))
+
+;;; Want to see properties or defines? Add an entry for them here.
+(defvar php-imenu-patterns nil)
+(setq php-imenu-patterns
+ (list
+ ;; types: classes and interfaces
+ (list
+ ;; for some reason [:space:] and \s- aren't matching \n
+ (concat "^\\s-*"
+ "\\(\\(abstract[[:space:]\n]+\\)?class\\|interface\\)"
+ "[[:space:]\n]+"
+ "\\([a-zA-Z0-9_]+\\)[[:space:]\n]*" ; class/iface name
+ "\\([a-zA-Z0-9_[:space:]\n]*\\)" ; extends / implements clauses
+ "[{]")
+ (lambda ()
+ (message "%S %S"
+ (match-string-no-properties 3)
+ (match-string-no-properties 1))
+ (concat (match-string-no-properties 3)
+ " - "
+ (match-string-no-properties 1)))
+ (lambda ()
+ (save-excursion
+ (backward-up-list 1)
+ (forward-sexp)
+ (point))))
+ ;; functions
+ (list
+ (concat "^[[:space:]\n]*"
+ "\\(\\(public\\|protected\\|private\\|"
+ "static\\|abstract\\)[[:space:]\n]+\\)*"
+ "function[[:space:]\n]*&?[[:space:]\n]*"
+ "\\([a-zA-Z0-9_]+\\)[[:space:]\n]*" ; function name
+ "[(]")
+ (lambda ()
+ (concat (match-string-no-properties 3) "()"))
+ (lambda ()
+ (save-excursion
+ (backward-up-list 1)
+ (forward-sexp)
+ (when (not (looking-at "\\s-*;"))
+ (forward-sexp))
+ (point))))
+ ))
+
+;;; Global variable to pass to imenu-progress-message in multiple functions
+(defvar php-imenu-prev-pos nil)
+
+;;; An implementation of imenu-create-index-function
+(defun php-imenu-create-index ()
+ (let (prev-pos)
+ (imenu-progress-message php-imenu-prev-pos 0)
+ (let ((result (php-imenu-create-index-helper (point-min) (point-max) nil)))
+ ;(message "bye %S" result)
+ (imenu-progress-message php-imenu-prev-pos 100)
+ result)))
+
+(defun php-imenu-create-index-helper (min max name)
+ (let ((combined-pattern
+ (concat "\\("
+ (mapconcat
+ (function (lambda (pat) (first pat)))
+ php-imenu-patterns "\\)\\|\\(")
+ "\\)"))
+ (index-alist '()))
+ (goto-char min)
+ (save-match-data
+ (while (re-search-forward combined-pattern max t)
+ (let ((pos (set-marker (make-marker) (match-beginning 0)))
+ (min (match-end 0))
+ (pat (save-excursion
+ (goto-char (match-beginning 0))
+ (find-if (function
+ (lambda (pat) (looking-at (first pat))))
+ php-imenu-patterns))))
+ (when (not pat)
+ (message "php-imenu: How can no pattern get us here! %S" pos))
+ (when (and pat
+ (not (php-imenu-in-string-p))
+ )
+ (let* ((name (funcall (second pat)))
+ (max (funcall (third pat)))
+ (children (php-imenu-create-index-helper min max name)))
+ ;; should validate max: what happens if unmatched curly?
+ ;(message "%S %S %S" nm name (mapcar (function first) children))
+ (if (equal '() children)
+ (push (cons name pos) index-alist)
+ (push (cons name
+ (funcall php-imenu-alist-postprocessor
+ (cons (cons "*go*" pos)
+ children)))
+ index-alist))
+ ))
+ (imenu-progress-message php-imenu-prev-pos nil)
+ )))
+ (reverse index-alist)))
+
+;;; Recognize when in quoted strings or heredoc-style string literals
+(defun php-imenu-in-string-p ()
+ (save-match-data
+ (or (in-string-p)
+ (let ((pt (point)))
+ (save-excursion
+ (and (re-search-backward "<<<\\([A-Za-z0-9_]+\\)$" nil t)
+ (not (re-search-forward (concat "^"
+ (match-string-no-properties 1)
+ ";$")
+ pt t))))))))
diff --git a/emacs.d/nxhtml/related/php-mode.el b/emacs.d/nxhtml/related/php-mode.el
new file mode 100644
index 0000000..a25fb82
--- /dev/null
+++ b/emacs.d/nxhtml/related/php-mode.el
@@ -0,0 +1,1231 @@
+;;; php-mode.el --- major mode for editing PHP code
+
+;; Copyright (C) 1999, 2000, 2001, 2003, 2004 Turadg Aleahmad
+;; 2008 Aaron S. Hawley
+
+;; Maintainer: Aaron S. Hawley <ashawley at users.sourceforge.net>
+;; Author: Turadg Aleahmad, 1999-2004
+;; Keywords: php languages oop
+;; Created: 1999-05-17
+;; Modified: 2008-11-28 Fri
+;; X-URL: http://php-mode.sourceforge.net/
+
+(defconst php-mode-version-number "1.5.0-nxhtml-1.94"
+ "PHP Mode version number.")
+
+;;; License
+
+;; This file 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
+;; of the License, or (at your option) any later version.
+
+;; This file 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 file; if not, write to the Free Software
+;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
+
+;;; Usage
+
+;; Put this file in your Emacs lisp path (eg. site-lisp) and add to
+;; your .emacs file:
+;;
+;; (require 'php-mode)
+
+;; To use abbrev-mode, add lines like this:
+;; (add-hook 'php-mode-hook
+;; '(lambda () (define-abbrev php-mode-abbrev-table "ex" "extends")))
+
+;; To make php-mode compatible with html-mode, see http://php-mode.sf.net
+
+;; Many options available under Help:Customize
+;; Options specific to php-mode are in
+;; Programming/Languages/Php
+;; Since it inherits much functionality from c-mode, look there too
+;; Programming/Languages/C
+
+;;; Commentary:
+
+;; PHP mode is a major mode for editing PHP 3 and 4 source code. It's
+;; an extension of C mode; thus it inherits all C mode's navigation
+;; functionality. But it colors according to the PHP grammar and indents
+;; according to the PEAR coding guidelines. It also includes a couple
+;; handy IDE-type features such as documentation search and a source
+;; and class browser.
+
+;;; Contributors: (in chronological order)
+
+;; Juanjo, Torsten Martinsen, Vinai Kopp, Sean Champ, Doug Marcey,
+;; Kevin Blake, Rex McMaster, Mathias Meyer, Boris Folgmann, Roland
+;; Rosenfeld, Fred Yankowski, Craig Andrews, John Keller, Ryan
+;; Sammartino, ppercot, Valentin Funk, Stig Bakken, Gregory Stark,
+;; Chris Morris, Nils Rennebarth, Gerrit Riessen, Eric Mc Sween,
+;; Ville Skytta, Giacomo Tesio, Lennart Borgman, Stefan Monnier,
+;; Aaron S. Hawley, Ian Eure, Bill Lovett, Dias Badekas, David House
+
+;;; Changelog:
+
+;; 1.5.0-nxhtml-1.88 (Lennart Borgman)
+;; Don't indent heredoc end mark
+;; 1.5.0-nxhtml-1.61 (Lennart Borgman)
+;; Added php-mode-to-use.
+;; Made underscore be part of identifiers.
+;; Remove php-mode-to.
+;; Make the indentation check only on current line.
+;; Warn only once per session about indentation.
+;; Tell if can't complete in `php-complete-function'.
+;; Move back point after checking indentation in
+;; `php-check-html-for-indentation'.
+;; Add `c-at-vsemi-p-fn' etc after advice from Alan Mackenzie.
+;;
+;; 1.5
+;; Support function keywords like public, private and the ampersand
+;; character for function-based commands. Support abstract, final,
+;; static, public, private and protected keywords in Imenu. Fix
+;; reversed order of Imenu entries. Use font-lock-preprocessor-face
+;; for PHP and ASP tags. Make php-mode-modified a literal value
+;; rather than a computed string. Add date and time constants of
+;; PHP. (Dias Badekas) Fix false syntax highlighting of keywords
+;; because of underscore character. Change HTML indentation warning
+;; to match only HTML at the beginning of the line. Fix
+;; byte-compiler warnings. Clean-up whitespace and audited style
+;; consistency of code. Remove conditional bindings and XEmacs code
+;; that likely does nothing.
+;;
+;; 1.4
+;; Updated GNU GPL to version 3. Ported to Emacs 22 (CC mode
+;; 5.31). M-x php-mode-version shows version. Provide end-of-defun
+;; beginning-of-defun functionality. Support add-log library.
+;; Fix __CLASS__ constant (Ian Eure). Allow imenu to see visibility
+;; declarations -- "private", "public", "protected". (Bill Lovett)
+;;
+;; 1.3
+;; Changed the definition of # using a tip from Stefan
+;; Monnier to correct highlighting and indentation. (Lennart Borgman)
+;; Changed the highlighting of the HTML part. (Lennart Borgman)
+;;
+;; See the ChangeLog file included with the source package.
+
+
+;;; Code:
+
+(require 'add-log)
+(require 'speedbar)
+(require 'font-lock)
+(require 'cc-mode)
+(require 'cc-langs)
+(require 'custom)
+(require 'etags)
+(eval-when-compile
+ (require 'regexp-opt))
+
+;; Local variables
+;;;###autoload
+(defgroup php nil
+ "Major mode `php-mode' for editing PHP code."
+ :prefix "php-"
+ :group 'languages)
+
+(defcustom php-default-face 'default
+ "Default face in `php-mode' buffers."
+ :type 'face
+ :group 'php)
+
+(defcustom php-speedbar-config t
+ "When set to true automatically configures Speedbar to observe PHP files.
+Ignores php-file patterns option; fixed to expression \"\\.\\(inc\\|php[s34]?\\)\""
+ :type 'boolean
+ :set (lambda (sym val)
+ (set-default sym val)
+ (if (and val (boundp 'speedbar))
+ (speedbar-add-supported-extension
+ "\\.\\(inc\\|php[s34]?\\|phtml\\)")))
+ :group 'php)
+
+(defcustom php-mode-speedbar-open nil
+ "Normally `php-mode' starts with the speedbar closed.
+Turning this on will open it whenever `php-mode' is loaded."
+ :type 'boolean
+ :set (lambda (sym val)
+ (set-default sym val)
+ (when val
+ (speedbar 1)))
+ :group 'php)
+
+(defvar php-imenu-generic-expression
+ '(
+ ("Private Methods"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?private\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ ("Protected Methods"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?protected\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ ("Public Methods"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?public\\s-+\\(?:static\\s-+\\)?function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ ("Classes"
+ "^\\s-*class\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*" 1)
+ ("All Functions"
+ "^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)
+ )
+ "Imenu generic expression for PHP Mode. See `imenu-generic-expression'."
+ )
+
+(defcustom php-manual-url "http://www.php.net/manual/en/"
+ "URL at which to find PHP manual.
+You can replace \"en\" with your ISO language code."
+ :type 'string
+ :group 'php)
+
+(defcustom php-search-url "http://www.php.net/"
+ "URL at which to search for documentation on a word."
+ :type 'string
+ :group 'php)
+
+(defcustom php-completion-file ""
+ "Path to the file which contains the function names known to PHP."
+ :type 'string
+ :group 'php)
+
+(defcustom php-manual-path ""
+ "Path to the directory which contains the PHP manual."
+ :type 'string
+ :group 'php)
+
+;;;###autoload
+(defcustom php-file-patterns '("\\.php[s34]?\\'" "\\.phtml\\'" "\\.inc\\'")
+ "List of file patterns for which to automatically invoke `php-mode'."
+ :type '(repeat (regexp :tag "Pattern"))
+ :set (lambda (sym val)
+ (set-default sym val)
+ (let ((php-file-patterns-temp val))
+ (while php-file-patterns-temp
+ (add-to-list 'auto-mode-alist
+ (cons (car php-file-patterns-temp) 'php-mode))
+ (setq php-file-patterns-temp (cdr php-file-patterns-temp)))))
+ :group 'php)
+
+(defcustom php-mode-hook nil
+ "List of functions to be executed on entry to `php-mode'."
+ :type 'hook
+ :group 'php)
+
+(defcustom php-mode-pear-hook nil
+ "Hook called when a PHP PEAR file is opened with `php-mode'."
+ :type 'hook
+ :group 'php)
+
+(defcustom php-mode-force-pear nil
+ "Normally PEAR coding rules are enforced only when the filename contains \"PEAR.\"
+Turning this on will force PEAR rules on all PHP files."
+ :type 'boolean
+ :group 'php)
+
+(defconst php-mode-modified "2009-08-12"
+ "PHP Mode build date.")
+
+(defun php-mode-version ()
+ "Display string describing the version of PHP mode."
+ (interactive)
+ (message "PHP mode %s of %s"
+ php-mode-version-number php-mode-modified))
+
+(defconst php-beginning-of-defun-regexp
+ "^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+&?\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*("
+ "Regular expression for a PHP function.")
+
+(defun php-beginning-of-defun (&optional arg)
+ "Move to the beginning of the ARGth PHP function from point.
+Implements PHP version of `beginning-of-defun-function'."
+ (interactive "p")
+ (let ((arg (or arg 1)))
+ (while (> arg 0)
+ (re-search-backward php-beginning-of-defun-regexp
+ nil 'noerror)
+ (setq arg (1- arg)))
+ (while (< arg 0)
+ (end-of-line 1)
+ (let ((opoint (point)))
+ (beginning-of-defun 1)
+ (forward-list 2)
+ (forward-line 1)
+ (if (eq opoint (point))
+ (re-search-forward php-beginning-of-defun-regexp
+ nil 'noerror))
+ (setq arg (1+ arg))))))
+
+(defun php-end-of-defun (&optional arg)
+ "Move the end of the ARGth PHP function from point.
+Implements PHP befsion of `end-of-defun-function'
+
+See `php-beginning-of-defun'."
+ (interactive "p")
+ (php-beginning-of-defun (- (or arg 1))))
+
+
+(defvar php-warned-bad-indent nil)
+;;(make-variable-buffer-local 'php-warned-bad-indent)
+
+;; Do it but tell it is not good if html tags in buffer.
+(defun php-check-html-for-indentation ()
+ (let ((html-tag-re "^\\s-*</?\\sw+.*?>")
+ (here (point)))
+ (goto-char (line-beginning-position))
+ (if (or (when (boundp 'mumamo-multi-major-mode) mumamo-multi-major-mode)
+ ;; Fix-me: no idea how to check for mmm or multi-mode
+ (save-match-data
+ (not (or (re-search-forward html-tag-re (line-end-position) t)
+ (re-search-backward html-tag-re (line-beginning-position) t)))))
+ (progn
+ (goto-char here)
+ t)
+ (goto-char here)
+ (setq php-warned-bad-indent t)
+ ;;(setq php-warned-bad-indent nil)
+ (let* ((known-multi-libs '(("mumamo" mumamo (lambda () (nxhtml-mumamo)))
+ ("mmm-mode" mmm-mode (lambda () (mmm-mode 1)))
+ ("multi-mode" multi-mode (lambda () (multi-mode 1)))))
+ (known-names (mapcar (lambda (lib) (car lib)) known-multi-libs))
+ (available-multi-libs (delq nil
+ (mapcar
+ (lambda (lib)
+ (when (locate-library (car lib)) lib))
+ known-multi-libs)))
+ (available-names (mapcar (lambda (lib) (car lib)) available-multi-libs))
+ (base-msg
+ (concat
+ "Indentation fails badly with mixed HTML/PHP in the HTML part in
+plaín `php-mode'. To get indentation to work you must use an
+Emacs library that supports 'multiple major modes' in a buffer.
+Parts of the buffer will then be in `php-mode' and parts in for
+example `html-mode'. Known such libraries are:\n\t"
+ (mapconcat 'identity known-names ", ")
+ "\n"
+ (if available-multi-libs
+ (concat
+ "You have these available in your `load-path':\n\t"
+ (mapconcat 'identity available-names ", ")
+ "\n\n"
+ "Do you want to turn any of those on? ")
+ "You do not have any of those in your `load-path'.")))
+ (is-using-multi
+ (catch 'is-using
+ (dolist (lib available-multi-libs)
+ (when (and (boundp (cadr lib))
+ (symbol-value (cadr lib)))
+ (throw 'is-using t))))))
+ (unless is-using-multi
+ (if available-multi-libs
+ (if (not (y-or-n-p base-msg))
+ (message "Did not do indentation, but you can try again now if you want")
+ (let* ((name
+ (if (= 1 (length available-multi-libs))
+ (car available-names)
+ ;; Minibuffer window is more than one line, fix that first:
+ (message "")
+ (completing-read "Choose multiple major mode support library: "
+ available-names nil t
+ (car available-names)
+ '(available-names . 1)
+ )))
+ (mode (when name
+ (caddr (assoc name available-multi-libs)))))
+ (when mode
+ ;; Minibuffer window is more than one line, fix that first:
+ (message "")
+ (load name)
+ (funcall mode))))
+ (lwarn 'php-indent :warning base-msg)))
+ nil))))
+
+(defun php-cautious-indent-region (start end &optional quiet)
+ (if (or php-warned-bad-indent
+ (php-check-html-for-indentation))
+ (funcall 'c-indent-region start end quiet)))
+
+(defun php-cautious-indent-line ()
+ (if (or php-warned-bad-indent
+ (php-check-html-for-indentation))
+ (let ((here (point))
+ doit)
+ (move-beginning-of-line nil)
+ ;; Don't indent heredoc end mark
+ (save-match-data
+ (unless (looking-at "[a-zA-Z0-9_]+;\n")
+ (setq doit t)))
+ (goto-char here)
+ (when doit
+ (funcall 'c-indent-line)))))
+
+(defconst php-tags '("<?php" "?>" "<?" "<?="))
+(defconst php-tags-key (regexp-opt php-tags))
+
+(defconst php-block-stmt-1-kwds '("do" "else" "finally" "try"))
+(defconst php-block-stmt-2-kwds
+ '("for" "if" "while" "switch" "foreach" "elseif" "catch all"))
+
+(defconst php-block-stmt-1-key
+ (regexp-opt php-block-stmt-1-kwds))
+(defconst php-block-stmt-2-key
+ (regexp-opt php-block-stmt-2-kwds))
+
+(defconst php-class-decl-kwds '("class" "interface"))
+
+(defconst php-class-key
+ (concat
+ "\\(" (regexp-opt php-class-decl-kwds) "\\)\\s-+"
+ (c-lang-const c-symbol-key c) ;; Class name.
+ "\\(\\s-+extends\\s-+" (c-lang-const c-symbol-key c) "\\)?" ;; Name of superclass.
+ "\\(\\s-+implements\\s-+[^{]+{\\)?")) ;; List of any adopted protocols.
+
+
+(defun php-c-at-vsemi-p (&optional pos)
+ "Return t on html lines (including php region border), otherwise nil.
+POS is a position on the line in question.
+
+This is was done due to the problem reported here:
+
+ URL `https://answers.launchpad.net/nxhtml/+question/43320'"
+ (setq pos (or pos (point)))
+ (let ((here (point))
+ ret)
+ (save-match-data
+ (goto-char pos)
+ (beginning-of-line)
+ (setq ret (looking-at
+ (rx
+ (or (seq
+ bol
+ (0+ space)
+ "<"
+ (in "a-z\\?"))
+ (seq
+ ;;(0+ anything)
+ (0+ not-newline)
+ (in "a-z\\?")
+ ">"
+ (0+ space)
+ eol))))))
+ (goto-char here)
+ ret))
+
+(defun php-c-vsemi-status-unknown-p ()
+ "See `php-c-at-vsemi-p'."
+ )
+
+;;;###autoload
+(define-derived-mode php-mode c-mode "PHP"
+ "Major mode for editing PHP code.\n\n\\{php-mode-map}"
+ (c-add-language 'php-mode 'c-mode)
+
+;; PHP doesn't have C-style macros.
+;; HACK: Overwrite this syntax with rules to match <?php and others.
+;; (c-lang-defconst c-opt-cpp-start php php-tags-key)
+;; (c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start))
+ (set (make-local-variable 'c-opt-cpp-start) php-tags-key)
+;; (c-lang-defconst c-opt-cpp-start php php-tags-key)
+;; (c-lang-defvar c-opt-cpp-start (c-lang-const c-opt-cpp-start))
+ (set (make-local-variable 'c-opt-cpp-prefix) php-tags-key)
+
+ (c-set-offset 'cpp-macro 0)
+
+;; (c-lang-defconst c-block-stmt-1-kwds php php-block-stmt-1-kwds)
+;; (c-lang-defvar c-block-stmt-1-kwds (c-lang-const c-block-stmt-1-kwds))
+ (set (make-local-variable 'c-block-stmt-1-key) php-block-stmt-1-key)
+
+;; (c-lang-defconst c-block-stmt-2-kwds php php-block-stmt-2-kwds)
+;; (c-lang-defvar c-block-stmt-2-kwds (c-lang-const c-block-stmt-2-kwds))
+ (set (make-local-variable 'c-block-stmt-2-key) php-block-stmt-2-key)
+
+ ;; Specify that cc-mode recognize Javadoc comment style
+ (set (make-local-variable 'c-doc-comment-style)
+ '((php-mode . javadoc)))
+
+;; (c-lang-defconst c-class-decl-kwds
+;; php php-class-decl-kwds)
+ (set (make-local-variable 'c-class-key) php-class-key)
+
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ '((php-font-lock-keywords-1
+ php-font-lock-keywords-2
+ ;; Comment-out the next line if the font-coloring is too
+ ;; extreme/ugly for you.
+ php-font-lock-keywords-3)
+ nil ; KEYWORDS-ONLY
+ t ; CASE-FOLD
+ (("_" . "w")) ; SYNTAX-ALIST
+ nil)) ; SYNTAX-BEGIN
+ (modify-syntax-entry ?# "< b" php-mode-syntax-table)
+ ;;(modify-syntax-entry ?_ "w" php-mode-syntax-table)
+
+ ;; Electric behaviour must be turned off, they do not work since
+ ;; they can not find the correct syntax in embedded PHP.
+ ;;
+ ;; Seems to work with narrowing so let it be on if the user prefers it.
+ ;;(setq c-electric-flag nil)
+
+ (setq font-lock-maximum-decoration t
+ case-fold-search t ; PHP vars are case-sensitive
+ imenu-generic-expression php-imenu-generic-expression)
+
+ ;; Do not force newline at end of file. Such newlines can cause
+ ;; trouble if the PHP file is included in another file before calls
+ ;; to header() or cookie().
+ (set (make-local-variable 'require-final-newline) nil)
+ (set (make-local-variable 'next-line-add-newlines) nil)
+
+ ;; PEAR coding standards
+ (add-hook 'php-mode-pear-hook
+ (lambda ()
+ (set (make-local-variable 'tab-width) 4)
+ (set (make-local-variable 'c-basic-offset) 4)
+ (set (make-local-variable 'indent-tabs-mode) nil)
+ (c-set-offset 'block-open' - )
+ (c-set-offset 'block-close' 0 )) nil t)
+
+ (if (or php-mode-force-pear
+ (and (stringp buffer-file-name)
+ (string-match "PEAR\\|pear"
+ (buffer-file-name))
+ (string-match "\\.php$" (buffer-file-name))))
+ (run-hooks 'php-mode-pear-hook))
+
+ (setq indent-line-function 'php-cautious-indent-line)
+ (setq indent-region-function 'php-cautious-indent-region)
+ (setq c-special-indent-hook nil)
+ (setq c-at-vsemi-p-fn 'php-c-at-vsemi-p)
+ (setq c-vsemi-status-unknown-p 'php-c-vsemi-status-unknown-p)
+
+ (set (make-local-variable 'syntax-begin-function)
+ 'c-beginning-of-syntax)
+ (set (make-local-variable 'beginning-of-defun-function)
+ 'php-beginning-of-defun)
+ (set (make-local-variable 'end-of-defun-function)
+ 'php-end-of-defun)
+ (set (make-local-variable 'open-paren-in-column-0-is-defun-start)
+ nil)
+ (set (make-local-variable 'defun-prompt-regexp)
+ "^\\s-*function\\s-+&?\\s-*\\(\\(\\sw\\|\\s_\\)+\\)\\s-*")
+ (set (make-local-variable 'add-log-current-defun-header-regexp)
+ php-beginning-of-defun-regexp)
+
+ (run-hooks 'php-mode-hook))
+
+;; Make a menu keymap (with a prompt string)
+;; and make it the menu bar item's definition.
+(define-key php-mode-map [menu-bar] (make-sparse-keymap))
+(define-key php-mode-map [menu-bar php]
+ (cons "PHP" (make-sparse-keymap "PHP")))
+
+;; Define specific subcommands in this menu.
+(define-key php-mode-map [menu-bar php complete-function]
+ '("Complete function name" . php-complete-function))
+(define-key php-mode-map
+ [menu-bar php browse-manual]
+ '("Browse manual" . php-browse-manual))
+(define-key php-mode-map
+ [menu-bar php search-documentation]
+ '("Search documentation" . php-search-documentation))
+
+;; Define function name completion function
+(defvar php-completion-table nil
+ "Obarray of tag names defined in current tags table and functions known to PHP.")
+
+(defun php-complete-function ()
+ "Perform function completion on the text around point.
+Completes to the set of names listed in the current tags table
+and the standard php functions.
+The string to complete is chosen in the same way as the default
+for \\[find-tag] (which see)."
+ (interactive)
+ (let ((pattern (php-get-pattern))
+ beg
+ completion
+ (php-functions (php-completion-table)))
+ (if (not pattern) (message "Nothing to complete")
+ (if (not (search-backward pattern nil t))
+ (message "Can't complete here")
+ (setq beg (point))
+ (forward-char (length pattern))
+ (setq completion (try-completion pattern php-functions nil))
+ (cond ((eq completion t))
+ ((null completion)
+ (message "Can't find completion for \"%s\"" pattern)
+ (ding))
+ ((not (string= pattern completion))
+ (delete-region beg (point))
+ (insert completion))
+ (t
+ (message "Making completion list...")
+ (with-output-to-temp-buffer "*Completions*"
+ (display-completion-list
+ (all-completions pattern php-functions)))
+ (message "Making completion list...%s" "done")))))))
+
+(defun php-completion-table ()
+ "Build variable `php-completion-table' on demand.
+The table includes the PHP functions and the tags from the
+current `tags-file-name'."
+ (or (and tags-file-name
+ (save-excursion (tags-verify-table tags-file-name))
+ php-completion-table)
+ (let ((tags-table
+ (if (and tags-file-name
+ (functionp 'etags-tags-completion-table))
+ (with-current-buffer (get-file-buffer tags-file-name)
+ (etags-tags-completion-table))
+ nil))
+ (php-table
+ (cond ((and (not (string= "" php-completion-file))
+ (file-readable-p php-completion-file))
+ (php-build-table-from-file php-completion-file))
+ (php-manual-path
+ (php-build-table-from-path php-manual-path))
+ (t nil))))
+ (unless (or php-table tags-table)
+ (error
+ (concat "No TAGS file active nor are "
+ "`php-completion-file' or `php-manual-path' set")))
+ (when tags-table
+ ;; Combine the tables.
+ (mapatoms (lambda (sym) (intern (symbol-name sym) php-table))
+ tags-table))
+ (setq php-completion-table php-table))))
+
+(defun php-build-table-from-file (filename)
+ (let ((table (make-vector 1022 0))
+ (buf (find-file-noselect filename)))
+ (save-excursion
+ (set-buffer buf)
+ (goto-char (point-min))
+ (while (re-search-forward
+ "^\\([-a-zA-Z0-9_.]+\\)\n"
+ nil t)
+ (intern (buffer-substring (match-beginning 1) (match-end 1))
+ table)))
+ (kill-buffer buf)
+ table))
+
+(defun php-build-table-from-path (path)
+ (let ((table (make-vector 1022 0))
+ (files (directory-files
+ path
+ nil
+ "^function\\..+\\.html$")))
+ (mapc (lambda (file)
+ (string-match "\\.\\([-a-zA-Z_0-9]+\\)\\.html$" file)
+ (intern
+ (replace-regexp-in-string
+ "-" "_" (substring file (match-beginning 1) (match-end 1)) t)
+ table))
+ files)
+ table))
+
+;; Find the pattern we want to complete
+;; find-tag-default from GNU Emacs etags.el
+(defun php-get-pattern ()
+ (save-excursion
+ (while (looking-at "\\sw\\|\\s_")
+ (forward-char 1))
+ (if (or (re-search-backward "\\sw\\|\\s_"
+ (save-excursion (beginning-of-line) (point))
+ t)
+ (re-search-forward "\\(\\sw\\|\\s_\\)+"
+ (save-excursion (end-of-line) (point))
+ t))
+ (progn (goto-char (match-end 0))
+ (buffer-substring-no-properties
+ (point)
+ (progn (forward-sexp -1)
+ (while (looking-at "\\s'")
+ (forward-char 1))
+ (point))))
+ nil)))
+
+(defun php-show-arglist ()
+ (interactive)
+ (let* ((tagname (php-get-pattern))
+ (buf (find-tag-noselect tagname nil nil))
+ arglist)
+ (save-excursion
+ (set-buffer buf)
+ (goto-char (point-min))
+ (when (re-search-forward
+ (format "function\\s-+%s\\s-*(\\([^{]*\\))" tagname)
+ nil t)
+ (setq arglist (buffer-substring-no-properties
+ (match-beginning 1) (match-end 1)))))
+ (if arglist
+ (message "Arglist for %s: %s" tagname arglist)
+ (message "Unknown function: %s" tagname))))
+
+;; Define function documentation function
+(defun php-search-documentation ()
+ "Search PHP documentation for the word at point."
+ (interactive)
+ (browse-url (concat php-search-url (current-word t))))
+
+;; Define function for browsing manual
+(defun php-browse-manual ()
+ "Bring up manual for PHP."
+ (interactive)
+ (browse-url php-manual-url))
+
+;; Define shortcut
+(define-key php-mode-map
+ "\C-c\C-f"
+ 'php-search-documentation)
+
+;; Define shortcut
+(define-key php-mode-map
+ [(meta tab)]
+ 'php-complete-function)
+
+;; Define shortcut
+(define-key php-mode-map
+ "\C-c\C-m"
+ 'php-browse-manual)
+
+;; Define shortcut
+(define-key php-mode-map
+ '[(control .)]
+ 'php-show-arglist)
+
+;; Use the Emacs standard indentation binding. This may upset c-mode
+;; which does not follow this at the moment, but I see no better
+;; choice.
+(define-key php-mode-map [?\t] 'indent-for-tab-command)
+
+
+(defconst php-constants
+ (eval-when-compile
+ (regexp-opt
+ '(;; core constants
+ "__LINE__" "__FILE__"
+ "__FUNCTION__" "__CLASS__" "__METHOD__"
+ "PHP_OS" "PHP_VERSION"
+ "TRUE" "FALSE" "NULL"
+ "E_ERROR" "E_NOTICE" "E_PARSE" "E_WARNING" "E_ALL" "E_STRICT"
+ "E_USER_ERROR" "E_USER_WARNING" "E_USER_NOTICE"
+ "DEFAULT_INCLUDE_PATH" "PEAR_INSTALL_DIR" "PEAR_EXTENSION_DIR"
+ "PHP_BINDIR" "PHP_LIBDIR" "PHP_DATADIR" "PHP_SYSCONFDIR"
+ "PHP_LOCALSTATEDIR" "PHP_CONFIG_FILE_PATH"
+ "PHP_EOL"
+
+ ;; date and time constants
+ "DATE_ATOM" "DATE_COOKIE" "DATE_ISO8601"
+ "DATE_RFC822" "DATE_RFC850" "DATE_RFC1036" "DATE_RFC1123"
+ "DATE_RFC2822" "DATE_RFC3339"
+ "DATE_RSS" "DATE_W3C"
+
+ ;; from ext/standard:
+ "EXTR_OVERWRITE" "EXTR_SKIP" "EXTR_PREFIX_SAME"
+ "EXTR_PREFIX_ALL" "EXTR_PREFIX_INVALID" "SORT_ASC" "SORT_DESC"
+ "SORT_REGULAR" "SORT_NUMERIC" "SORT_STRING" "ASSERT_ACTIVE"
+ "ASSERT_CALLBACK" "ASSERT_BAIL" "ASSERT_WARNING"
+ "ASSERT_QUIET_EVAL" "CONNECTION_ABORTED" "CONNECTION_NORMAL"
+ "CONNECTION_TIMEOUT" "M_E" "M_LOG2E" "M_LOG10E" "M_LN2"
+ "M_LN10" "M_PI" "M_PI_2" "M_PI_4" "M_1_PI" "M_2_PI"
+ "M_2_SQRTPI" "M_SQRT2" "M_SQRT1_2" "CRYPT_SALT_LENGTH"
+ "CRYPT_STD_DES" "CRYPT_EXT_DES" "CRYPT_MD5" "CRYPT_BLOWFISH"
+ "DIRECTORY_SEPARATOR" "SEEK_SET" "SEEK_CUR" "SEEK_END"
+ "LOCK_SH" "LOCK_EX" "LOCK_UN" "LOCK_NB" "HTML_SPECIALCHARS"
+ "HTML_ENTITIES" "ENT_COMPAT" "ENT_QUOTES" "ENT_NOQUOTES"
+ "INFO_GENERAL" "INFO_CREDITS" "INFO_CONFIGURATION"
+ "INFO_ENVIRONMENT" "INFO_VARIABLES" "INFO_LICENSE" "INFO_ALL"
+ "CREDITS_GROUP" "CREDITS_GENERAL" "CREDITS_SAPI"
+ "CREDITS_MODULES" "CREDITS_DOCS" "CREDITS_FULLPAGE"
+ "CREDITS_QA" "CREDITS_ALL" "PHP_OUTPUT_HANDLER_START"
+ "PHP_OUTPUT_HANDLER_CONT" "PHP_OUTPUT_HANDLER_END"
+ "STR_PAD_LEFT" "STR_PAD_RIGHT" "STR_PAD_BOTH"
+ "PATHINFO_DIRNAME" "PATHINFO_BASENAME" "PATHINFO_EXTENSION"
+ "CHAR_MAX" "LC_CTYPE" "LC_NUMERIC" "LC_TIME" "LC_COLLATE"
+ "LC_MONETARY" "LC_ALL" "LC_MESSAGES" "LOG_EMERG" "LOG_ALERT"
+ "LOG_CRIT" "LOG_ERR" "LOG_WARNING" "LOG_NOTICE" "LOG_INFO"
+ "LOG_DEBUG" "LOG_KERN" "LOG_USER" "LOG_MAIL" "LOG_DAEMON"
+ "LOG_AUTH" "LOG_SYSLOG" "LOG_LPR" "LOG_NEWS" "LOG_UUCP"
+ "LOG_CRON" "LOG_AUTHPRIV" "LOG_LOCAL0" "LOG_LOCAL1"
+ "LOG_LOCAL2" "LOG_LOCAL3" "LOG_LOCAL4" "LOG_LOCAL5"
+ "LOG_LOCAL6" "LOG_LOCAL7" "LOG_PID" "LOG_CONS" "LOG_ODELAY"
+ "LOG_NDELAY" "LOG_NOWAIT" "LOG_PERROR"
+
+ ;; Disabled by default because they slow buffer loading
+ ;; If you have use for them, uncomment the strings
+ ;; that you want colored.
+ ;; To compile, you may have to increase 'max-specpdl-size'
+
+ ;; from other bundled extensions:
+; "CAL_EASTER_TO_xxx" "VT_NULL" "VT_EMPTY" "VT_UI1" "VT_I2"
+; "VT_I4" "VT_R4" "VT_R8" "VT_BOOL" "VT_ERROR" "VT_CY" "VT_DATE"
+; "VT_BSTR" "VT_DECIMAL" "VT_UNKNOWN" "VT_DISPATCH" "VT_VARIANT"
+; "VT_I1" "VT_UI2" "VT_UI4" "VT_INT" "VT_UINT" "VT_ARRAY"
+; "VT_BYREF" "CP_ACP" "CP_MACCP" "CP_OEMCP" "CP_SYMBOL"
+; "CP_THREAD_ACP" "CP_UTF7" "CP_UTF8" "CPDF_PM_NONE"
+; "CPDF_PM_OUTLINES" "CPDF_PM_THUMBS" "CPDF_PM_FULLSCREEN"
+; "CPDF_PL_SINGLE" "CPDF_PL_1COLUMN" "CPDF_PL_2LCOLUMN"
+; "CPDF_PL_2RCOLUMN" "CURLOPT_PORT" "CURLOPT_FILE"
+; "CURLOPT_INFILE" "CURLOPT_INFILESIZE" "CURLOPT_URL"
+; "CURLOPT_PROXY" "CURLOPT_VERBOSE" "CURLOPT_HEADER"
+; "CURLOPT_HTTPHEADER" "CURLOPT_NOPROGRESS" "CURLOPT_NOBODY"
+; "CURLOPT_FAILONERROR" "CURLOPT_UPLOAD" "CURLOPT_POST"
+; "CURLOPT_FTPLISTONLY" "CURLOPT_FTPAPPEND" "CURLOPT_NETRC"
+; "CURLOPT_FOLLOWLOCATION" "CURLOPT_FTPASCII" "CURLOPT_PUT"
+; "CURLOPT_MUTE" "CURLOPT_USERPWD" "CURLOPT_PROXYUSERPWD"
+; "CURLOPT_RANGE" "CURLOPT_TIMEOUT" "CURLOPT_POSTFIELDS"
+; "CURLOPT_REFERER" "CURLOPT_USERAGENT" "CURLOPT_FTPPORT"
+; "CURLOPT_LOW_SPEED_LIMIT" "CURLOPT_LOW_SPEED_TIME"
+; "CURLOPT_RESUME_FROM" "CURLOPT_COOKIE" "CURLOPT_SSLCERT"
+; "CURLOPT_SSLCERTPASSWD" "CURLOPT_WRITEHEADER"
+; "CURLOPT_COOKIEFILE" "CURLOPT_SSLVERSION"
+; "CURLOPT_TIMECONDITION" "CURLOPT_TIMEVALUE"
+; "CURLOPT_CUSTOMREQUEST" "CURLOPT_STDERR" "CURLOPT_TRANSFERTEXT"
+; "CURLOPT_RETURNTRANSFER" "CURLOPT_QUOTE" "CURLOPT_POSTQUOTE"
+; "CURLOPT_INTERFACE" "CURLOPT_KRB4LEVEL"
+; "CURLOPT_HTTPPROXYTUNNEL" "CURLOPT_FILETIME"
+; "CURLOPT_WRITEFUNCTION" "CURLOPT_READFUNCTION"
+; "CURLOPT_PASSWDFUNCTION" "CURLOPT_HEADERFUNCTION"
+; "CURLOPT_MAXREDIRS" "CURLOPT_MAXCONNECTS" "CURLOPT_CLOSEPOLICY"
+; "CURLOPT_FRESH_CONNECT" "CURLOPT_FORBID_REUSE"
+; "CURLOPT_RANDOM_FILE" "CURLOPT_EGDSOCKET"
+; "CURLOPT_CONNECTTIMEOUT" "CURLOPT_SSL_VERIFYPEER"
+; "CURLOPT_CAINFO" "CURLOPT_BINARYTRANSER"
+; "CURLCLOSEPOLICY_LEAST_RECENTLY_USED" "CURLCLOSEPOLICY_OLDEST"
+; "CURLINFO_EFFECTIVE_URL" "CURLINFO_HTTP_CODE"
+; "CURLINFO_HEADER_SIZE" "CURLINFO_REQUEST_SIZE"
+; "CURLINFO_TOTAL_TIME" "CURLINFO_NAMELOOKUP_TIME"
+; "CURLINFO_CONNECT_TIME" "CURLINFO_PRETRANSFER_TIME"
+; "CURLINFO_SIZE_UPLOAD" "CURLINFO_SIZE_DOWNLOAD"
+; "CURLINFO_SPEED_DOWNLOAD" "CURLINFO_SPEED_UPLOAD"
+; "CURLINFO_FILETIME" "CURLE_OK" "CURLE_UNSUPPORTED_PROTOCOL"
+; "CURLE_FAILED_INIT" "CURLE_URL_MALFORMAT"
+; "CURLE_URL_MALFORMAT_USER" "CURLE_COULDNT_RESOLVE_PROXY"
+; "CURLE_COULDNT_RESOLVE_HOST" "CURLE_COULDNT_CONNECT"
+; "CURLE_FTP_WEIRD_SERVER_REPLY" "CURLE_FTP_ACCESS_DENIED"
+; "CURLE_FTP_USER_PASSWORD_INCORRECT"
+; "CURLE_FTP_WEIRD_PASS_REPLY" "CURLE_FTP_WEIRD_USER_REPLY"
+; "CURLE_FTP_WEIRD_PASV_REPLY" "CURLE_FTP_WEIRD_227_FORMAT"
+; "CURLE_FTP_CANT_GET_HOST" "CURLE_FTP_CANT_RECONNECT"
+; "CURLE_FTP_COULDNT_SET_BINARY" "CURLE_PARTIAL_FILE"
+; "CURLE_FTP_COULDNT_RETR_FILE" "CURLE_FTP_WRITE_ERROR"
+; "CURLE_FTP_QUOTE_ERROR" "CURLE_HTTP_NOT_FOUND"
+; "CURLE_WRITE_ERROR" "CURLE_MALFORMAT_USER"
+; "CURLE_FTP_COULDNT_STOR_FILE" "CURLE_READ_ERROR"
+; "CURLE_OUT_OF_MEMORY" "CURLE_OPERATION_TIMEOUTED"
+; "CURLE_FTP_COULDNT_SET_ASCII" "CURLE_FTP_PORT_FAILED"
+; "CURLE_FTP_COULDNT_USE_REST" "CURLE_FTP_COULDNT_GET_SIZE"
+; "CURLE_HTTP_RANGE_ERROR" "CURLE_HTTP_POST_ERROR"
+; "CURLE_SSL_CONNECT_ERROR" "CURLE_FTP_BAD_DOWNLOAD_RESUME"
+; "CURLE_FILE_COULDNT_READ_FILE" "CURLE_LDAP_CANNOT_BIND"
+; "CURLE_LDAP_SEARCH_FAILED" "CURLE_LIBRARY_NOT_FOUND"
+; "CURLE_FUNCTION_NOT_FOUND" "CURLE_ABORTED_BY_CALLBACK"
+; "CURLE_BAD_FUNCTION_ARGUMENT" "CURLE_BAD_CALLING_ORDER"
+; "CURLE_HTTP_PORT_FAILED" "CURLE_BAD_PASSWORD_ENTERED"
+; "CURLE_TOO_MANY_REDIRECTS" "CURLE_UNKOWN_TELNET_OPTION"
+; "CURLE_TELNET_OPTION_SYNTAX" "CURLE_ALREADY_COMPLETE"
+; "DBX_MYSQL" "DBX_ODBC" "DBX_PGSQL" "DBX_MSSQL" "DBX_PERSISTENT"
+; "DBX_RESULT_INFO" "DBX_RESULT_INDEX" "DBX_RESULT_ASSOC"
+; "DBX_CMP_TEXT" "DBX_CMP_NUMBER" "XML_ELEMENT_NODE"
+; "XML_ATTRIBUTE_NODE" "XML_TEXT_NODE" "XML_CDATA_SECTION_NODE"
+; "XML_ENTITY_REF_NODE" "XML_ENTITY_NODE" "XML_PI_NODE"
+; "XML_COMMENT_NODE" "XML_DOCUMENT_NODE" "XML_DOCUMENT_TYPE_NODE"
+; "XML_DOCUMENT_FRAG_NODE" "XML_NOTATION_NODE"
+; "XML_HTML_DOCUMENT_NODE" "XML_DTD_NODE" "XML_ELEMENT_DECL_NODE"
+; "XML_ATTRIBUTE_DECL_NODE" "XML_ENTITY_DECL_NODE"
+; "XML_NAMESPACE_DECL_NODE" "XML_GLOBAL_NAMESPACE"
+; "XML_LOCAL_NAMESPACE" "XML_ATTRIBUTE_CDATA" "XML_ATTRIBUTE_ID"
+; "XML_ATTRIBUTE_IDREF" "XML_ATTRIBUTE_IDREFS"
+; "XML_ATTRIBUTE_ENTITY" "XML_ATTRIBUTE_NMTOKEN"
+; "XML_ATTRIBUTE_NMTOKENS" "XML_ATTRIBUTE_ENUMERATION"
+; "XML_ATTRIBUTE_NOTATION" "XPATH_UNDEFINED" "XPATH_NODESET"
+; "XPATH_BOOLEAN" "XPATH_NUMBER" "XPATH_STRING" "XPATH_POINT"
+; "XPATH_RANGE" "XPATH_LOCATIONSET" "XPATH_USERS" "FBSQL_ASSOC"
+; "FBSQL_NUM" "FBSQL_BOTH" "FDFValue" "FDFStatus" "FDFFile"
+; "FDFID" "FDFFf" "FDFSetFf" "FDFClearFf" "FDFFlags" "FDFSetF"
+; "FDFClrF" "FDFAP" "FDFAS" "FDFAction" "FDFAA" "FDFAPRef"
+; "FDFIF" "FDFEnter" "FDFExit" "FDFDown" "FDFUp" "FDFFormat"
+; "FDFValidate" "FDFKeystroke" "FDFCalculate"
+; "FRIBIDI_CHARSET_UTF8" "FRIBIDI_CHARSET_8859_6"
+; "FRIBIDI_CHARSET_8859_8" "FRIBIDI_CHARSET_CP1255"
+; "FRIBIDI_CHARSET_CP1256" "FRIBIDI_CHARSET_ISIRI_3342"
+; "FTP_ASCII" "FTP_BINARY" "FTP_IMAGE" "FTP_TEXT" "IMG_GIF"
+; "IMG_JPG" "IMG_JPEG" "IMG_PNG" "IMG_WBMP" "IMG_COLOR_TILED"
+; "IMG_COLOR_STYLED" "IMG_COLOR_BRUSHED"
+; "IMG_COLOR_STYLEDBRUSHED" "IMG_COLOR_TRANSPARENT"
+; "IMG_ARC_ROUNDED" "IMG_ARC_PIE" "IMG_ARC_CHORD"
+; "IMG_ARC_NOFILL" "IMG_ARC_EDGED" "GMP_ROUND_ZERO"
+; "GMP_ROUND_PLUSINF" "GMP_ROUND_MINUSINF" "HW_ATTR_LANG"
+; "HW_ATTR_NR" "HW_ATTR_NONE" "IIS_READ" "IIS_WRITE"
+; "IIS_EXECUTE" "IIS_SCRIPT" "IIS_ANONYMOUS" "IIS_BASIC"
+; "IIS_NTLM" "NIL" "OP_DEBUG" "OP_READONLY" "OP_ANONYMOUS"
+; "OP_SHORTCACHE" "OP_SILENT" "OP_PROTOTYPE" "OP_HALFOPEN"
+; "OP_EXPUNGE" "OP_SECURE" "CL_EXPUNGE" "FT_UID" "FT_PEEK"
+; "FT_NOT" "FT_INTERNAL" "FT_PREFETCHTEXT" "ST_UID" "ST_SILENT"
+; "ST_SET" "CP_UID" "CP_MOVE" "SE_UID" "SE_FREE" "SE_NOPREFETCH"
+; "SO_FREE" "SO_NOSERVER" "SA_MESSAGES" "SA_RECENT" "SA_UNSEEN"
+; "SA_UIDNEXT" "SA_UIDVALIDITY" "SA_ALL" "LATT_NOINFERIORS"
+; "LATT_NOSELECT" "LATT_MARKED" "LATT_UNMARKED" "SORTDATE"
+; "SORTARRIVAL" "SORTFROM" "SORTSUBJECT" "SORTTO" "SORTCC"
+; "SORTSIZE" "TYPETEXT" "TYPEMULTIPART" "TYPEMESSAGE"
+; "TYPEAPPLICATION" "TYPEAUDIO" "TYPEIMAGE" "TYPEVIDEO"
+; "TYPEOTHER" "ENC7BIT" "ENC8BIT" "ENCBINARY" "ENCBASE64"
+; "ENCQUOTEDPRINTABLE" "ENCOTHER" "INGRES_ASSOC" "INGRES_NUM"
+; "INGRES_BOTH" "IBASE_DEFAULT" "IBASE_TEXT" "IBASE_UNIXTIME"
+; "IBASE_READ" "IBASE_COMMITTED" "IBASE_CONSISTENCY"
+; "IBASE_NOWAIT" "IBASE_TIMESTAMP" "IBASE_DATE" "IBASE_TIME"
+; "LDAP_DEREF_NEVER" "LDAP_DEREF_SEARCHING" "LDAP_DEREF_FINDING"
+; "LDAP_DEREF_ALWAYS" "LDAP_OPT_DEREF" "LDAP_OPT_SIZELIMIT"
+; "LDAP_OPT_TIMELIMIT" "LDAP_OPT_PROTOCOL_VERSION"
+; "LDAP_OPT_ERROR_NUMBER" "LDAP_OPT_REFERRALS" "LDAP_OPT_RESTART"
+; "LDAP_OPT_HOST_NAME" "LDAP_OPT_ERROR_STRING"
+; "LDAP_OPT_MATCHED_DN" "LDAP_OPT_SERVER_CONTROLS"
+; "LDAP_OPT_CLIENT_CONTROLS" "GSLC_SSL_NO_AUTH"
+; "GSLC_SSL_ONEWAY_AUTH" "GSLC_SSL_TWOWAY_AUTH" "MCAL_SUNDAY"
+; "MCAL_MONDAY" "MCAL_TUESDAY" "MCAL_WEDNESDAY" "MCAL_THURSDAY"
+; "MCAL_FRIDAY" "MCAL_SATURDAY" "MCAL_JANUARY" "MCAL_FEBRUARY"
+; "MCAL_MARCH" "MCAL_APRIL" "MCAL_MAY" "MCAL_JUNE" "MCAL_JULY"
+; "MCAL_AUGUST" "MCAL_SEPTEMBER" "MCAL_OCTOBER" "MCAL_NOVEMBER"
+; "MCAL_RECUR_NONE" "MCAL_RECUR_DAILY" "MCAL_RECUR_WEEKLY"
+; "MCAL_RECUR_MONTHLY_MDAY" "MCAL_RECUR_MONTHLY_WDAY"
+; "MCAL_RECUR_YEARLY" "MCAL_M_SUNDAY" "MCAL_M_MONDAY"
+; "MCAL_M_TUESDAY" "MCAL_M_WEDNESDAY" "MCAL_M_THURSDAY"
+; "MCAL_M_FRIDAY" "MCAL_M_SATURDAY" "MCAL_M_WEEKDAYS"
+; "MCAL_M_WEEKEND" "MCAL_M_ALLDAYS" "MCRYPT_" "MCRYPT_"
+; "MCRYPT_ENCRYPT" "MCRYPT_DECRYPT" "MCRYPT_DEV_RANDOM"
+; "MCRYPT_DEV_URANDOM" "MCRYPT_RAND" "SWFBUTTON_HIT"
+; "SUNFUNCS_RET_STRING" "SUNFUNCS_RET_DOUBLE"
+; "SWFBUTTON_DOWN" "SWFBUTTON_OVER" "SWFBUTTON_UP"
+; "SWFBUTTON_MOUSEUPOUTSIDE" "SWFBUTTON_DRAGOVER"
+; "SWFBUTTON_DRAGOUT" "SWFBUTTON_MOUSEUP" "SWFBUTTON_MOUSEDOWN"
+; "SWFBUTTON_MOUSEOUT" "SWFBUTTON_MOUSEOVER"
+; "SWFFILL_RADIAL_GRADIENT" "SWFFILL_LINEAR_GRADIENT"
+; "SWFFILL_TILED_BITMAP" "SWFFILL_CLIPPED_BITMAP"
+; "SWFTEXTFIELD_HASLENGTH" "SWFTEXTFIELD_NOEDIT"
+; "SWFTEXTFIELD_PASSWORD" "SWFTEXTFIELD_MULTILINE"
+; "SWFTEXTFIELD_WORDWRAP" "SWFTEXTFIELD_DRAWBOX"
+; "SWFTEXTFIELD_NOSELECT" "SWFTEXTFIELD_HTML"
+; "SWFTEXTFIELD_ALIGN_LEFT" "SWFTEXTFIELD_ALIGN_RIGHT"
+; "SWFTEXTFIELD_ALIGN_CENTER" "SWFTEXTFIELD_ALIGN_JUSTIFY"
+; "UDM_FIELD_URLID" "UDM_FIELD_URL" "UDM_FIELD_CONTENT"
+; "UDM_FIELD_TITLE" "UDM_FIELD_KEYWORDS" "UDM_FIELD_DESC"
+; "UDM_FIELD_DESCRIPTION" "UDM_FIELD_TEXT" "UDM_FIELD_SIZE"
+; "UDM_FIELD_RATING" "UDM_FIELD_SCORE" "UDM_FIELD_MODIFIED"
+; "UDM_FIELD_ORDER" "UDM_FIELD_CRC" "UDM_FIELD_CATEGORY"
+; "UDM_PARAM_PAGE_SIZE" "UDM_PARAM_PAGE_NUM"
+; "UDM_PARAM_SEARCH_MODE" "UDM_PARAM_CACHE_MODE"
+; "UDM_PARAM_TRACK_MODE" "UDM_PARAM_PHRASE_MODE"
+; "UDM_PARAM_CHARSET" "UDM_PARAM_STOPTABLE"
+; "UDM_PARAM_STOP_TABLE" "UDM_PARAM_STOPFILE"
+; "UDM_PARAM_STOP_FILE" "UDM_PARAM_WEIGHT_FACTOR"
+; "UDM_PARAM_WORD_MATCH" "UDM_PARAM_MAX_WORD_LEN"
+; "UDM_PARAM_MAX_WORDLEN" "UDM_PARAM_MIN_WORD_LEN"
+; "UDM_PARAM_MIN_WORDLEN" "UDM_PARAM_ISPELL_PREFIXES"
+; "UDM_PARAM_ISPELL_PREFIX" "UDM_PARAM_PREFIXES"
+; "UDM_PARAM_PREFIX" "UDM_PARAM_CROSS_WORDS"
+; "UDM_PARAM_CROSSWORDS" "UDM_LIMIT_CAT" "UDM_LIMIT_URL"
+; "UDM_LIMIT_TAG" "UDM_LIMIT_LANG" "UDM_LIMIT_DATE"
+; "UDM_PARAM_FOUND" "UDM_PARAM_NUM_ROWS" "UDM_PARAM_WORDINFO"
+; "UDM_PARAM_WORD_INFO" "UDM_PARAM_SEARCHTIME"
+; "UDM_PARAM_SEARCH_TIME" "UDM_PARAM_FIRST_DOC"
+; "UDM_PARAM_LAST_DOC" "UDM_MODE_ALL" "UDM_MODE_ANY"
+; "UDM_MODE_BOOL" "UDM_MODE_PHRASE" "UDM_CACHE_ENABLED"
+; "UDM_CACHE_DISABLED" "UDM_TRACK_ENABLED" "UDM_TRACK_DISABLED"
+; "UDM_PHRASE_ENABLED" "UDM_PHRASE_DISABLED"
+; "UDM_CROSS_WORDS_ENABLED" "UDM_CROSSWORDS_ENABLED"
+; "UDM_CROSS_WORDS_DISABLED" "UDM_CROSSWORDS_DISABLED"
+; "UDM_PREFIXES_ENABLED" "UDM_PREFIX_ENABLED"
+; "UDM_ISPELL_PREFIXES_ENABLED" "UDM_ISPELL_PREFIX_ENABLED"
+; "UDM_PREFIXES_DISABLED" "UDM_PREFIX_DISABLED"
+; "UDM_ISPELL_PREFIXES_DISABLED" "UDM_ISPELL_PREFIX_DISABLED"
+; "UDM_ISPELL_TYPE_AFFIX" "UDM_ISPELL_TYPE_SPELL"
+; "UDM_ISPELL_TYPE_DB" "UDM_ISPELL_TYPE_SERVER" "UDM_MATCH_WORD"
+; "UDM_MATCH_BEGIN" "UDM_MATCH_SUBSTR" "UDM_MATCH_END"
+; "MSQL_ASSOC" "MSQL_NUM" "MSQL_BOTH" "MYSQL_ASSOC" "MYSQL_NUM"
+; "MYSQL_BOTH" "MYSQL_USE_RESULT" "MYSQL_STORE_RESULT"
+; "OCI_DEFAULT" "OCI_DESCRIBE_ONLY" "OCI_COMMIT_ON_SUCCESS"
+; "OCI_EXACT_FETCH" "SQLT_BFILEE" "SQLT_CFILEE" "SQLT_CLOB"
+; "SQLT_BLOB" "SQLT_RDD" "OCI_B_SQLT_NTY" "OCI_SYSDATE"
+; "OCI_B_BFILE" "OCI_B_CFILEE" "OCI_B_CLOB" "OCI_B_BLOB"
+; "OCI_B_ROWID" "OCI_B_CURSOR" "OCI_B_BIN" "OCI_ASSOC" "OCI_NUM"
+; "OCI_BOTH" "OCI_RETURN_NULLS" "OCI_RETURN_LOBS"
+; "OCI_DTYPE_FILE" "OCI_DTYPE_LOB" "OCI_DTYPE_ROWID" "OCI_D_FILE"
+; "OCI_D_LOB" "OCI_D_ROWID" "ODBC_TYPE" "ODBC_BINMODE_PASSTHRU"
+; "ODBC_BINMODE_RETURN" "ODBC_BINMODE_CONVERT" "SQL_ODBC_CURSORS"
+; "SQL_CUR_USE_DRIVER" "SQL_CUR_USE_IF_NEEDED" "SQL_CUR_USE_ODBC"
+; "SQL_CONCURRENCY" "SQL_CONCUR_READ_ONLY" "SQL_CONCUR_LOCK"
+; "SQL_CONCUR_ROWVER" "SQL_CONCUR_VALUES" "SQL_CURSOR_TYPE"
+; "SQL_CURSOR_FORWARD_ONLY" "SQL_CURSOR_KEYSET_DRIVEN"
+; "SQL_CURSOR_DYNAMIC" "SQL_CURSOR_STATIC" "SQL_KEYSET_SIZE"
+; "SQL_CHAR" "SQL_VARCHAR" "SQL_LONGVARCHAR" "SQL_DECIMAL"
+; "SQL_NUMERIC" "SQL_BIT" "SQL_TINYINT" "SQL_SMALLINT"
+; "SQL_INTEGER" "SQL_BIGINT" "SQL_REAL" "SQL_FLOAT" "SQL_DOUBLE"
+; "SQL_BINARY" "SQL_VARBINARY" "SQL_LONGVARBINARY" "SQL_DATE"
+; "SQL_TIME" "SQL_TIMESTAMP" "SQL_TYPE_DATE" "SQL_TYPE_TIME"
+; "SQL_TYPE_TIMESTAMP" "SQL_BEST_ROWID" "SQL_ROWVER"
+; "SQL_SCOPE_CURROW" "SQL_SCOPE_TRANSACTION" "SQL_SCOPE_SESSION"
+; "SQL_NO_NULLS" "SQL_NULLABLE" "SQL_INDEX_UNIQUE"
+; "SQL_INDEX_ALL" "SQL_ENSURE" "SQL_QUICK"
+; "X509_PURPOSE_SSL_CLIENT" "X509_PURPOSE_SSL_SERVER"
+; "X509_PURPOSE_NS_SSL_SERVER" "X509_PURPOSE_SMIME_SIGN"
+; "X509_PURPOSE_SMIME_ENCRYPT" "X509_PURPOSE_CRL_SIGN"
+; "X509_PURPOSE_ANY" "PKCS7_DETACHED" "PKCS7_TEXT"
+; "PKCS7_NOINTERN" "PKCS7_NOVERIFY" "PKCS7_NOCHAIN"
+; "PKCS7_NOCERTS" "PKCS7_NOATTR" "PKCS7_BINARY" "PKCS7_NOSIGS"
+; "OPENSSL_PKCS1_PADDING" "OPENSSL_SSLV23_PADDING"
+; "OPENSSL_NO_PADDING" "OPENSSL_PKCS1_OAEP_PADDING"
+; "ORA_BIND_INOUT" "ORA_BIND_IN" "ORA_BIND_OUT"
+; "ORA_FETCHINTO_ASSOC" "ORA_FETCHINTO_NULLS"
+; "PREG_PATTERN_ORDER" "PREG_SET_ORDER" "PREG_SPLIT_NO_EMPTY"
+; "PREG_SPLIT_DELIM_CAPTURE"
+; "PGSQL_ASSOC" "PGSQL_NUM" "PGSQL_BOTH"
+; "PRINTER_COPIES" "PRINTER_MODE" "PRINTER_TITLE"
+; "PRINTER_DEVICENAME" "PRINTER_DRIVERVERSION"
+; "PRINTER_RESOLUTION_Y" "PRINTER_RESOLUTION_X" "PRINTER_SCALE"
+; "PRINTER_BACKGROUND_COLOR" "PRINTER_PAPER_LENGTH"
+; "PRINTER_PAPER_WIDTH" "PRINTER_PAPER_FORMAT"
+; "PRINTER_FORMAT_CUSTOM" "PRINTER_FORMAT_LETTER"
+; "PRINTER_FORMAT_LEGAL" "PRINTER_FORMAT_A3" "PRINTER_FORMAT_A4"
+; "PRINTER_FORMAT_A5" "PRINTER_FORMAT_B4" "PRINTER_FORMAT_B5"
+; "PRINTER_FORMAT_FOLIO" "PRINTER_ORIENTATION"
+; "PRINTER_ORIENTATION_PORTRAIT" "PRINTER_ORIENTATION_LANDSCAPE"
+; "PRINTER_TEXT_COLOR" "PRINTER_TEXT_ALIGN" "PRINTER_TA_BASELINE"
+; "PRINTER_TA_BOTTOM" "PRINTER_TA_TOP" "PRINTER_TA_CENTER"
+; "PRINTER_TA_LEFT" "PRINTER_TA_RIGHT" "PRINTER_PEN_SOLID"
+; "PRINTER_PEN_DASH" "PRINTER_PEN_DOT" "PRINTER_PEN_DASHDOT"
+; "PRINTER_PEN_DASHDOTDOT" "PRINTER_PEN_INVISIBLE"
+; "PRINTER_BRUSH_SOLID" "PRINTER_BRUSH_CUSTOM"
+; "PRINTER_BRUSH_DIAGONAL" "PRINTER_BRUSH_CROSS"
+; "PRINTER_BRUSH_DIAGCROSS" "PRINTER_BRUSH_FDIAGONAL"
+; "PRINTER_BRUSH_HORIZONTAL" "PRINTER_BRUSH_VERTICAL"
+; "PRINTER_FW_THIN" "PRINTER_FW_ULTRALIGHT" "PRINTER_FW_LIGHT"
+; "PRINTER_FW_NORMAL" "PRINTER_FW_MEDIUM" "PRINTER_FW_BOLD"
+; "PRINTER_FW_ULTRABOLD" "PRINTER_FW_HEAVY" "PRINTER_ENUM_LOCAL"
+; "PRINTER_ENUM_NAME" "PRINTER_ENUM_SHARED"
+; "PRINTER_ENUM_DEFAULT" "PRINTER_ENUM_CONNECTIONS"
+; "PRINTER_ENUM_NETWORK" "PRINTER_ENUM_REMOTE" "PSPELL_FAST"
+; "PSPELL_NORMAL" "PSPELL_BAD_SPELLERS" "PSPELL_RUN_TOGETHER"
+; "SID" "SID" "AF_UNIX" "AF_INET" "SOCK_STREAM" "SOCK_DGRAM"
+; "SOCK_RAW" "SOCK_SEQPACKET" "SOCK_RDM" "MSG_OOB" "MSG_WAITALL"
+; "MSG_PEEK" "MSG_DONTROUTE" "SO_DEBUG" "SO_REUSEADDR"
+; "SO_KEEPALIVE" "SO_DONTROUTE" "SO_LINGER" "SO_BROADCAST"
+; "SO_OOBINLINE" "SO_SNDBUF" "SO_RCVBUF" "SO_SNDLOWAT"
+; "SO_RCVLOWAT" "SO_SNDTIMEO" "SO_RCVTIMEO" "SO_TYPE" "SO_ERROR"
+; "SOL_SOCKET" "PHP_NORMAL_READ" "PHP_BINARY_READ"
+; "PHP_SYSTEM_READ" "SOL_TCP" "SOL_UDP" "MOD_COLOR" "MOD_MATRIX"
+; "TYPE_PUSHBUTTON" "TYPE_MENUBUTTON" "BSHitTest" "BSDown"
+; "BSOver" "BSUp" "OverDowntoIdle" "IdletoOverDown"
+; "OutDowntoIdle" "OutDowntoOverDown" "OverDowntoOutDown"
+; "OverUptoOverDown" "OverUptoIdle" "IdletoOverUp" "ButtonEnter"
+; "ButtonExit" "MenuEnter" "MenuExit" "XML_ERROR_NONE"
+; "XML_ERROR_NO_MEMORY" "XML_ERROR_SYNTAX"
+; "XML_ERROR_NO_ELEMENTS" "XML_ERROR_INVALID_TOKEN"
+; "XML_ERROR_UNCLOSED_TOKEN" "XML_ERROR_PARTIAL_CHAR"
+; "XML_ERROR_TAG_MISMATCH" "XML_ERROR_DUPLICATE_ATTRIBUTE"
+; "XML_ERROR_JUNK_AFTER_DOC_ELEMENT" "XML_ERROR_PARAM_ENTITY_REF"
+; "XML_ERROR_UNDEFINED_ENTITY" "XML_ERROR_RECURSIVE_ENTITY_REF"
+; "XML_ERROR_ASYNC_ENTITY" "XML_ERROR_BAD_CHAR_REF"
+; "XML_ERROR_BINARY_ENTITY_REF"
+; "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF"
+; "XML_ERROR_MISPLACED_XML_PI" "XML_ERROR_UNKNOWN_ENCODING"
+; "XML_ERROR_INCORRECT_ENCODING"
+; "XML_ERROR_UNCLOSED_CDATA_SECTION"
+; "XML_ERROR_EXTERNAL_ENTITY_HANDLING" "XML_OPTION_CASE_FOLDING"
+; "XML_OPTION_TARGET_ENCODING" "XML_OPTION_SKIP_TAGSTART"
+; "XML_OPTION_SKIP_WHITE" "YPERR_BADARGS" "YPERR_BADDB"
+; "YPERR_BUSY" "YPERR_DOMAIN" "YPERR_KEY" "YPERR_MAP"
+; "YPERR_NODOM" "YPERR_NOMORE" "YPERR_PMAP" "YPERR_RESRC"
+; "YPERR_RPC" "YPERR_YPBIND" "YPERR_YPERR" "YPERR_YPSERV"
+; "YPERR_VERS" "FORCE_GZIP" "FORCE_DEFLATE"
+
+ ;; PEAR constants
+; "PEAR_ERROR_RETURN" "PEAR_ERROR_PRINT" "PEAR_ERROR_TRIGGER"
+; "PEAR_ERROR_DIE" "PEAR_ERROR_CALLBACK" "OS_WINDOWS" "OS_UNIX"
+; "PEAR_OS" "DB_OK" "DB_ERROR" "DB_ERROR_SYNTAX"
+; "DB_ERROR_CONSTRAINT" "DB_ERROR_NOT_FOUND"
+; "DB_ERROR_ALREADY_EXISTS" "DB_ERROR_UNSUPPORTED"
+; "DB_ERROR_MISMATCH" "DB_ERROR_INVALID" "DB_ERROR_NOT_CAPABLE"
+; "DB_ERROR_TRUNCATED" "DB_ERROR_INVALID_NUMBER"
+; "DB_ERROR_INVALID_DATE" "DB_ERROR_DIVZERO"
+; "DB_ERROR_NODBSELECTED" "DB_ERROR_CANNOT_CREATE"
+; "DB_ERROR_CANNOT_DELETE" "DB_ERROR_CANNOT_DROP"
+; "DB_ERROR_NOSUCHTABLE" "DB_ERROR_NOSUCHFIELD"
+; "DB_ERROR_NEED_MORE_DATA" "DB_ERROR_NOT_LOCKED"
+; "DB_ERROR_VALUE_COUNT_ON_ROW" "DB_ERROR_INVALID_DSN"
+; "DB_ERROR_CONNECT_FAILED" "DB_WARNING" "DB_WARNING_READ_ONLY"
+; "DB_PARAM_SCALAR" "DB_PARAM_OPAQUE" "DB_BINMODE_PASSTHRU"
+; "DB_BINMODE_RETURN" "DB_BINMODE_CONVERT" "DB_FETCHMODE_DEFAULT"
+; "DB_FETCHMODE_ORDERED" "DB_FETCHMODE_ASSOC"
+; "DB_FETCHMODE_FLIPPED" "DB_GETMODE_ORDERED" "DB_GETMODE_ASSOC"
+; "DB_GETMODE_FLIPPED" "DB_TABLEINFO_ORDER"
+; "DB_TABLEINFO_ORDERTABLE" "DB_TABLEINFO_FULL"
+
+ )))
+ "PHP constants.")
+
+(defconst php-keywords
+ (eval-when-compile
+ (regexp-opt
+ ;; "class", "new" and "extends" get special treatment
+ ;; "case" and "default" get special treatment elsewhere
+ '("and" "as" "break" "continue" "declare" "do" "echo" "else" "elseif"
+ "endfor" "endforeach" "endif" "endswitch" "endwhile" "exit"
+ "extends" "for" "foreach" "global" "if" "include" "include_once"
+ "next" "or" "require" "require_once" "return" "static" "switch"
+ "then" "var" "while" "xor" "throw" "catch" "try"
+ "instanceof" "catch all" "finally")))
+ "PHP keywords.")
+
+(defconst php-identifier
+ (eval-when-compile
+ '"[a-zA-Z\_\x7f-\xff][a-zA-Z0-9\_\x7f-\xff]*")
+ "Characters in a PHP identifier.")
+
+(defconst php-types
+ (eval-when-compile
+ (regexp-opt '("array" "bool" "boolean" "char" "const" "double" "float"
+ "int" "integer" "long" "mixed" "object" "real"
+ "string")))
+ "PHP types.")
+
+(defconst php-superglobals
+ (eval-when-compile
+ (regexp-opt '("_GET" "_POST" "_COOKIE" "_SESSION" "_ENV" "GLOBALS"
+ "_SERVER" "_FILES" "_REQUEST")))
+ "PHP superglobal variables.")
+
+;; Set up font locking
+(defconst php-font-lock-keywords-1
+ (list
+ ;; Fontify constants
+ (cons
+ (concat "[^_$]?\\<\\(" php-constants "\\)\\>[^_]?")
+ '(1 font-lock-constant-face))
+
+ ;; Fontify keywords
+ (cons
+ (concat "[^_$]?\\<\\(" php-keywords "\\)\\>[^_]?")
+ '(1 font-lock-keyword-face))
+
+ ;; Fontify keywords and targets, and case default tags.
+ (list "\\<\\(break\\|case\\|continue\\)\\>\\s-+\\(-?\\sw+\\)?"
+ '(1 font-lock-keyword-face) '(2 font-lock-constant-face t t))
+ ;; This must come after the one for keywords and targets.
+ '(":" ("^\\s-+\\(\\sw+\\)\\s-+\\s-+$"
+ (beginning-of-line) (end-of-line)
+ (1 font-lock-constant-face)))
+
+ ;; treat 'print' as keyword only when not used like a function name
+ '("\\<print\\s-*(" . php-default-face)
+ '("\\<print\\>" . font-lock-keyword-face)
+
+ ;; Fontify PHP tag
+ (cons php-tags-key font-lock-preprocessor-face)
+
+ ;; Fontify ASP-style tag
+ '("<\\%\\(=\\)?" . font-lock-preprocessor-face)
+ '("\\%>" . font-lock-preprocessor-face)
+
+ )
+ "Subdued level highlighting for PHP mode.")
+
+(defconst php-font-lock-keywords-2
+ (append
+ php-font-lock-keywords-1
+ (list
+
+ ;; class declaration
+ '("\\<\\(class\\|interface\\)\\s-+\\(\\sw+\\)?"
+ (1 font-lock-keyword-face) (2 font-lock-type-face nil t))
+ ;; handle several words specially, to include following word,
+ ;; thereby excluding it from unknown-symbol checks later
+ ;; FIX to handle implementing multiple
+ ;; currently breaks on "class Foo implements Bar, Baz"
+ '("\\<\\(new\\|extends\\|implements\\)\\s-+\\$?\\(\\sw+\\)"
+ (1 font-lock-keyword-face) (2 font-lock-type-face))
+
+ ;; function declaration
+ '("\\<\\(function\\)\\s-+&?\\(\\sw+\\)\\s-*("
+ (1 font-lock-keyword-face)
+ (2 font-lock-function-name-face nil t))
+
+ ;; class hierarchy
+ '("\\<\\(self\\|parent\\)\\>" (1 font-lock-constant-face nil nil))
+
+ ;; method and variable features
+ '("\\<\\(private\\|protected\\|public\\)\\s-+\\$?\\sw+"
+ (1 font-lock-keyword-face))
+
+ ;; method features
+ '("^\\s-*\\(abstract\\|static\\|final\\)\\s-+\\$?\\sw+"
+ (1 font-lock-keyword-face))
+
+ ;; variable features
+ '("^\\s-*\\(static\\|const\\)\\s-+\\$?\\sw+"
+ (1 font-lock-keyword-face))
+ ))
+ "Medium level highlighting for PHP mode.")
+
+(defconst php-font-lock-keywords-3
+ (append
+ php-font-lock-keywords-2
+ (list
+
+ ;; <word> or </word> for HTML
+ ;;'("</?\\sw+[^> ]*>" . font-lock-constant-face)
+ ;;'("</?\\sw+[^>]*" . font-lock-constant-face)
+ ;;'("<!DOCTYPE" . font-lock-constant-face)
+ '("</?[a-z!:]+" . font-lock-constant-face)
+
+ ;; HTML >
+ '("<[^>]*\\(>\\)" (1 font-lock-constant-face))
+
+ ;; HTML tags
+ '("\\(<[a-z]+\\)[[:space:]]+\\([a-z:]+=\\)[^>]*?" (1 font-lock-constant-face) (2 font-lock-constant-face) )
+ '("\"[[:space:]]+\\([a-z:]+=\\)" (1 font-lock-constant-face))
+
+ ;; HTML entities
+ ;;'("&\\w+;" . font-lock-variable-name-face)
+
+ ;; warn about '$' immediately after ->
+ '("\\$\\sw+->\\s-*\\(\\$\\)\\(\\sw+\\)"
+ (1 font-lock-warning-face) (2 php-default-face))
+
+ ;; warn about $word.word -- it could be a valid concatenation,
+ ;; but without any spaces we'll assume $word->word was meant.
+ '("\\$\\sw+\\(\\.\\)\\sw"
+ 1 font-lock-warning-face)
+
+ ;; Warn about ==> instead of =>
+ '("==+>" . font-lock-warning-face)
+
+ ;; exclude casts from bare-word treatment (may contain spaces)
+ `(,(concat "(\\s-*\\(" php-types "\\)\\s-*)")
+ 1 font-lock-type-face)
+
+ ;; PHP5: function declarations may contain classes as parameters type
+ `(,(concat "[(,]\\s-*\\(\\sw+\\)\\s-+&?\\$\\sw+\\>")
+ 1 font-lock-type-face)
+
+ ;; Fontify variables and function calls
+ '("\\$\\(this\\|that\\)\\W" (1 font-lock-constant-face nil nil))
+ `(,(concat "\\$\\(" php-superglobals "\\)\\W")
+ (1 font-lock-constant-face nil nil)) ;; $_GET & co
+ '("\\$\\(\\sw+\\)" (1 font-lock-variable-name-face)) ;; $variable
+ '("->\\(\\sw+\\)" (1 font-lock-variable-name-face t t)) ;; ->variable
+ '("->\\(\\sw+\\)\\s-*(" . (1 php-default-face t t)) ;; ->function_call
+ '("\\(\\sw+\\)::\\sw+\\s-*(?" . (1 font-lock-type-face)) ;; class::member
+ '("::\\(\\sw+\\>[^(]\\)" . (1 php-default-face)) ;; class::constant
+ '("\\<\\sw+\\s-*[[(]" . php-default-face) ;; word( or word[
+ '("\\<[0-9]+" . php-default-face) ;; number (also matches word)
+
+ ;; Warn on any words not already fontified
+ '("\\<\\sw+\\>" . font-lock-warning-face)
+
+ ))
+ "Gauchy level highlighting for PHP mode.")
+
+(provide 'php-mode)
+
+;;; php-mode.el ends here
diff --git a/emacs.d/nxhtml/related/readme.txt b/emacs.d/nxhtml/related/readme.txt
new file mode 100644
index 0000000..465fbf6
--- /dev/null
+++ b/emacs.d/nxhtml/related/readme.txt
@@ -0,0 +1,7 @@
+This subdir (related/) contains files that are taken from different
+places and are maybe modified to work with nXhtml.
+
+Please notice that major mode that are used with mumamo-mode must be a
+bit more carefully written. One problem I have noticed is that some
+major modes requuires that buffer-file-name is non-nil. That
+assumption does not work when mumamo-mode is used!
diff --git a/emacs.d/nxhtml/related/rhino.js b/emacs.d/nxhtml/related/rhino.js
new file mode 100644
index 0000000..efc50f0
--- /dev/null
+++ b/emacs.d/nxhtml/related/rhino.js
@@ -0,0 +1,14 @@
+// Where you store your files
+var project_folder = 'file:///c:/emacs/p/091105/EmacsW32/nxhtml/related/';
+// Browser environment wrapper over Rhino
+load(project_folder + 'env.js');
+// For DOM constructing
+window.location = project_folder + 'blank.html';
+var my_script = arguments[0];
+// If DOM ready
+window.onload = function(){
+ // Avoid recursive inclusion
+ if ("rhino_flymake.js" != my_script) {
+ load(my_script);
+ }
+}
diff --git a/emacs.d/nxhtml/related/smarty-mode.el b/emacs.d/nxhtml/related/smarty-mode.el
new file mode 100644
index 0000000..ad003b5
--- /dev/null
+++ b/emacs.d/nxhtml/related/smarty-mode.el
@@ -0,0 +1,2753 @@
+;;; smarty-mode.el --- major mode for editing Smarty templates
+
+;; Author: Vincent DEBOUT <deboutv@free.fr>
+;; Maintainer: Vincent DEBOUT <deboutv@free.fr>
+;; Keywords: languages smarty templates
+;; WWW: http://deboutv.free.fr/lisp/smarty/
+
+;;; 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 2
+;; of the License, 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; if not, write to the Free Software
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+;; Minor changes by Lennart Borgman
+
+(defconst smarty-version "0.0.5"
+ "Smarty Mode version number.")
+
+(defconst smarty-time-stamp "2007-11-01"
+ "Smarty Mode time stamp for last update.")
+
+(defconst smarty-is-xemacs (string-match "XEmacs" emacs-version)
+ "Non-nil if XEmacs is used.")
+
+(require 'font-lock)
+(when (not smarty-is-xemacs)
+ (require 'cc-mode)
+ (require 'custom)
+ (require 'etags))
+(eval-when-compile
+ (require 'regexp-opt))
+;;(when smarty-is-xemacs
+ (require 'easymenu)
+ (require 'hippie-exp)
+;;)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Customization
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(defgroup smarty nil
+ "Customizations for Smarty mode."
+ :prefix "smarty-"
+ :group 'languages)
+
+(defgroup smarty-mode nil
+ "Customizations for Smarty mode."
+ :group 'smarty)
+
+(defcustom smarty-electric-mode t
+ "*Non-nil enables electrification (automatic template generation).
+If nil, template generators can still be invoked through key bindings and
+menu. Is indicated in the modeline by \"/e\" after the mode name and can be
+toggled by `\\[smarty-electric-mode]'."
+ :type 'boolean
+ :group 'smarty-mode)
+
+(defcustom smarty-stutter-mode t
+ "*Non-nil enables stuttering.
+Is indicated in the modeline by \"/s\" after the mode name and can be toggled
+by `\\[smarty-stutter-mode]'."
+ :type 'boolean
+ :group 'smarty-mode)
+
+(defgroup smarty-menu nil
+ "Customizations for menues."
+ :group 'smarty)
+
+(defcustom smarty-source-file-menu t
+ "*Non-nil means add a menu of all source files in current directory."
+ :type 'boolean
+ :group 'smarty-menu)
+
+(defgroup smarty-highlight nil
+ "Customizations for highlight."
+ :group 'smarty)
+
+(defcustom smarty-highlight-plugin-functions t
+ "*Non-nil means highlight the plugin functions in the buffer."
+ :type 'boolean
+ :group 'smarty-highlight)
+
+(defgroup smarty-template nil
+ "Customizations for templates."
+ :group 'smarty)
+
+(defgroup smarty-header nil
+ "Customizations for header template."
+ :group 'smarty-template)
+
+(defcustom smarty-file-header ""
+ "*String or file to insert as file header.
+If the string specifies an existing file name, the contents of the file is
+inserted, otherwise the string itself is inserted as file header.
+Type `C-j' for newlines.
+If the header contains RCS keywords, they may be written as <RCS>Keyword<RCS>
+if the header needs to be version controlled.
+
+The following keywords for template generation are supported:
+ <filename> : replaced by the name of the buffer
+ <author> : replaced by the user name and email address
+ \(`user-full-name',`mail-host-address', `user-mail-address')
+ <login> : replaced by user login name (`user-login-name')
+ <company> : replaced by contents of option `smarty-company-name'
+ <date> : replaced by the current date
+ <year> : replaced by the current year
+ <copyright> : replaced by copyright string (`smarty-copyright-string')
+ <cursor> : final cursor position."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-file-footer ""
+ "*String or file to insert as file footer.
+If the string specifies an existing file name, the contents of the file is
+inserted, otherwise the string itself is inserted as file footer (i.e. at
+the end of the file).
+Type `C-j' for newlines.
+The same keywords as in option `smarty-file-header' can be used."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-company-name ""
+ "*Name of company to insert in file header.
+See option `smarty-file-header'."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-copyright-string ""
+ "*Copyright string to insert in file header.
+Can be multi-line string (type `C-j' for newline) and contain other file
+header keywords (see option `smarty-file-header')."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-date-format "%Y-%m-%d"
+ "*Specifies the date format to use in the header.
+This string is passed as argument to the command `format-time-string'.
+For more information on format strings, see the documentation for the
+`format-time-string' command (C-h f `format-time-string')."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-modify-date-prefix-string ""
+ "*Prefix string of modification date in Smarty file header.
+If actualization of the modification date is called (menu,
+`\\[smarty-template-modify]'), this string is searched and the rest
+of the line replaced by the current date."
+ :type 'string
+ :group 'smarty-header)
+
+(defcustom smarty-modify-date-on-saving nil
+ "*Non-nil means update the modification date when the buffer is saved.
+Calls function `\\[smarty-template-modify]').
+
+NOTE: Activate the new setting in a Smarty buffer by using the menu entry
+ \"Activate Options\"."
+ :type 'boolean
+ :group 'smarty-header)
+
+(defgroup smarty-misc nil
+ "Miscellaneous customizations."
+ :group 'smarty)
+
+(defcustom smarty-left-delimiter "{"
+ "Left escaping delimiter."
+ :type 'string
+ :group 'smarty-misc)
+
+(defcustom smarty-right-delimiter "}"
+ "Right escaping delimiter."
+ :type 'string
+ :group 'smarty-misc)
+
+(defcustom smarty-intelligent-tab t
+ "*Non-nil means `TAB' does indentation, word completion and tab insertion.
+That is, if preceding character is part of a word then complete word,
+else if not at beginning of line then insert tab,
+else if last command was a `TAB' or `RET' then dedent one step,
+else indent current line (i.e. `TAB' is bound to `smarty-electric-tab').
+If nil, TAB always indents current line (i.e. `TAB' is bound to
+`indent-according-to-mode').
+
+NOTE: Activate the new setting in a Smarty buffer by using the menu entry
+ \"Activate Options\"."
+ :type 'boolean
+ :group 'smarty-misc)
+
+(defcustom smarty-word-completion-in-minibuffer t
+ "*Non-nil enables word completion in minibuffer (for template prompts).
+
+NOTE: Activate the new setting by restarting Emacs."
+ :type 'boolean
+ :group 'smarty-misc)
+
+(defcustom smarty-word-completion-case-sensitive nil
+ "*Non-nil means word completion using `TAB' is case sensitive.
+That is, `TAB' completes words that start with the same letters and case.
+Otherwise, case is ignored."
+ :type 'boolean
+ :group 'smarty-misc)
+
+;; Functions
+
+(defun smarty-customize ()
+ "Call the customize function with `smarty' as argument."
+ (interactive)
+ (customize-browse 'smarty))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Variables
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-menu-max-size 20
+ "*Specifies the maximum size of a menu before splitting it into submenues.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Menu tools functions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-menu-split (list title)
+ "Split menu LIST into several submenues, if number of
+elements > `smarty-menu-max-size'."
+ (if (> (length list) smarty-menu-max-size)
+ (let ((remain list)
+ (result '())
+ (sublist '())
+ (menuno 1)
+ (i 0))
+ (while remain
+ (setq sublist (cons (car remain) sublist))
+ (setq remain (cdr remain))
+ (setq i (+ i 1))
+ (if (= i smarty-menu-max-size)
+ (progn
+ (setq result (cons (cons (format "%s %s" title menuno)
+ (nreverse sublist)) result))
+ (setq i 0)
+ (setq menuno (+ menuno 1))
+ (setq sublist '()))))
+ (and sublist
+ (setq result (cons (cons (format "%s %s" title menuno)
+ (nreverse sublist)) result)))
+ (nreverse result))
+ list))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Source file menu
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-sources-menu nil)
+
+;; Create the source menu
+(defun smarty-add-source-files-menu ()
+ "Scan directory for all Smarty source files and generate menu.
+The directory of the current source file is scanned."
+ (interactive)
+ (message "Scanning directory for source files ...")
+ (let ((newmap (current-local-map))
+ (file-list (smarty-get-source-files))
+ menu-list found)
+ ;; Create list for menu
+ (setq found nil)
+ (while file-list
+ (setq found t)
+ (setq menu-list (cons (vector (car file-list)
+ (list 'find-file (car file-list)) t)
+ menu-list))
+ (setq file-list (cdr file-list)))
+ (setq menu-list (smarty-menu-split menu-list "Sources"))
+ (when found (setq menu-list (cons "--" menu-list)))
+ (setq menu-list (cons ["*Rescan*" smarty-add-source-files-menu t] menu-list))
+ (setq menu-list (cons "Sources" menu-list))
+ ;; Create menu
+ (easy-menu-add menu-list)
+ (easy-menu-define smarty-sources-menu newmap
+ "Smarty source files menu" menu-list))
+ (message ""))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Smarty menu
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-create-mode-menu ()
+ "Create Smarty Mode menu."
+ `("Smarty"
+ ("Templates"
+ ("Built-in Functions"
+ ["capture" smarty-template-capture t]
+ ["config_load" smarty-template-config-load t]
+ ["else" smarty-template-else t]
+ ["elseif" smarty-template-elseif t]
+ ["foreach" smarty-template-foreach t]
+ ["foreachelse" smarty-template-foreachelse t]
+ ["if" smarty-template-if t]
+ ["include" smarty-template-include t]
+ ["include_php" smarty-template-include-php t]
+ ["insert" smarty-template-insert t]
+ ["ldelim" smarty-template-ldelim t]
+ ["literal" smarty-template-literal t]
+ ["php" smarty-template-php t]
+ ["rdelim" smarty-template-rdelim t]
+ ["section" smarty-template-section t]
+ ["sectionelse" smarty-template-sectionelse t]
+ ["strip" smarty-template-strip t])
+ ("Custom Functions"
+ ["assign" smarty-template-assign t]
+ ["counter" smarty-template-counter t]
+ ["cycle" smarty-template-cycle t]
+ ["debug" smarty-template-debug t]
+ ["eval" smarty-template-eval t]
+ ["fetch" smarty-template-fetch t]
+ ["html_checkboxes" smarty-template-html-checkboxes t]
+ ["html_image" smarty-template-html-image t]
+ ["html_options" smarty-template-html-options t]
+ ["html_radios" smarty-template-html-radios t]
+ ["html_select_date" smarty-template-html-select-date t]
+ ["html_select_time" smarty-template-html-select-time t]
+ ["html_table" smarty-template-html-table t]
+ ["mailto" smarty-template-mailto t]
+ ["math" smarty-template-math t]
+ ["popup" smarty-template-popup t]
+ ["popup_init" smarty-template-popup-init t]
+ ["textformat" smarty-template-textformat t])
+ ("Variable Modifiers"
+ ["capitalize" smarty-template-capitalize t]
+ ["cat" smarty-template-cat t]
+ ["count_characters" smarty-template-count-characters t]
+ ["count_paragraphs" smarty-template-count-paragraphs t]
+ ["count_sentences" smarty-template-count-sentences t]
+ ["count_words" smarty-template-count-words t]
+ ["date_format" smarty-template-date-format t]
+ ["default" smarty-template-default t]
+ ["escape" smarty-template-escape t]
+ ["indent" smarty-template-indent t]
+ ["lower" smarty-template-lower t]
+ ["nl2br" smarty-template-nl2br t]
+ ["regex_replace" smarty-template-regex-replace t]
+ ["replace" smarty-template-replace t]
+ ["spacify" smarty-template-spacify t]
+ ["string_format" smarty-template-string-format t]
+ ["strip" smarty-template-vstrip t]
+ ["strip_tags" smarty-template-strip-tags t]
+ ["truncate" smarty-template-truncate t]
+ ["upper" smarty-template-upper t]
+ ["wordwrap" smarty-template-wordwrap t])
+ ("Plugins (Functions)"
+ ("BlockRepeatPlugin"
+ ["repeat" smarty-template-repeat t]
+ ["str_repeat" smarty-template-str-repeat t])
+ ("ClipCache"
+ ["clipcache" smarty-template-clipcache t]
+ ["include_clipcache" smarty-template-include-clipcache t])
+ ("SmartyFormtool"
+ ["formtool_checkall" smarty-template-formtool-checkall t]
+ ["formtool_copy" smarty-template-formtool-copy t]
+ ["formtool_count_chars" smarty-template-formtool-count-chars t]
+ ["formtool_init" smarty-template-formtool-init t]
+ ["formtool_move" smarty-template-formtool-move t]
+ ["formtool_moveall" smarty-template-formtool-moveall t]
+ ["formtool_movedown" smarty-template-formtool-movedown t]
+ ["formtool_moveup" smarty-template-formtool-moveup t]
+ ["formtool_remove" smarty-template-formtool-remove t]
+ ["formtool_rename" smarty-template-formtool-rename t]
+ ["formtool_save" smarty-template-formtool-save t]
+ ["formtool_selectall" smarty-template-formtool-selectall t])
+ ("SmartyPaginate"
+ ["paginate_first" smarty-template-paginate-first t]
+ ["paginate_last" smarty-template-paginate-last t]
+ ["paginate_middle" smarty-template-paginate-middle t]
+ ["paginate_next" smarty-template-paginate-next t]
+ ["paginate_prev" smarty-template-paginate-prev t])
+ ("SmartyValidate"
+ ["validate" smarty-template-validate t]))
+ ("Plugins (Variable Modifiers)"
+ ("AlternativeDateModifierPlugin"
+ ["date_format2" smarty-template-date-formatto t])
+ ("B2Smilies"
+ ["B2Smilies" smarty-template-btosmilies t])
+ ("BBCodePlugin"
+ ["bbcode2html" smarty-template-bbcodetohtml t])
+ )
+ "--"
+ ["Insert Header" smarty-template-header t]
+ ["Insert Footer" smarty-template-footer t]
+ ["Insert Date" smarty-template-insert-date t]
+ ["Modify Date" smarty-template-modify t])
+ "--"
+ ["Show Messages" smarty-show-messages :keys "C-c M-m"]
+ ["Smarty Mode Documentation" smarty-doc-mode :keys "C-c C-h"]
+ ["Version" smarty-version :keys "C-c C-v"]
+ "--"
+ ("Options"
+ ("Mode"
+ ["Electric Mode"
+ (progn (customize-set-variable 'smarty-electric-mode
+ (not smarty-electric-mode))
+ (smarty-mode-line-update))
+ :style toggle :selected smarty-electric-mode :keys "C-c C-m C-e"]
+ ["Stutter Mode"
+ (progn (customize-set-variable 'smarty-stutter-mode
+ (not smarty-stutter-mode))
+ (smarty-mode-line-update))
+ :style toggle :selected smarty-stutter-mode :keys "C-c C-m C-s"]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-mode) t])
+ ("Menu"
+ ["Source Menu"
+ (customize-set-variable 'smarty-source-file-menu
+ (not smarty-source-file-menu))
+ :style toggle :selected smarty-source-file-menu]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-menu) t])
+ ("Highlight"
+ ["Highlight plugin functions"
+ (progn (customize-set-variable 'smarty-highlight-plugin-functions
+ (not smarty-highlight-plugin-functions)))
+ :style toggle :selected smarty-highlight-plugin-functions]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-highlight) t])
+ ("Template"
+ ("Header"
+ ["Header template..."
+ (customize-option 'smarty-file-header) t]
+ ["Footer template..."
+ (customize-option 'smarty-file-footer) t]
+ ["Company..."
+ (customize-option 'smarty-company-name) t]
+ ["Copyright..."
+ (customize-option 'smarty-copyright-string) t]
+ ["Date format..."
+ (customize-option 'smarty-date-format) t]
+ ["Modify date prefix..."
+ (customize-option 'smarty-modify-date-prefix-string) t]
+ ["Modify date on saving"
+ (customize-set-variable 'smarty-modify-date-on-saving
+ (not smarty-modify-date-on-saving))
+ :style toggle :selected smarty-modify-date-on-saving]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-header) t])
+ "--"
+ ["Customize Group..." (customize-group 'smarty-template) t])
+ ("Miscellaneous"
+ ["Left delimiter..."
+ (customize-option 'smarty-left-delimiter) t]
+ ["Right delimiter..."
+ (customize-option 'smarty-right-delimiter) t]
+ ["Use Intelligent Tab"
+ (progn (customize-set-variable 'smarty-intelligent-tab
+ (not smarty-intelligent-tab))
+ (smarty-activate-customizations))
+ :style toggle :selected smarty-intelligent-tab]
+ ["Word Completion in Minibuffer"
+ (progn (customize-set-variable 'smarty-word-completion-in-minibuffer
+ (not smarty-word-completion-in-minibuffer))
+ (message "Activate new setting by saving options and restarting Emacs"))
+ :style toggle :selected smarty-word-completion-in-minibuffer]
+ ["Completion is case sensitive"
+ (customize-set-variable 'smarty-word-completion-case-sensitive
+ (not smarty-word-completion-case-sensitive))
+ :style toggle :selected smarty-word-completion-case-sensitive]
+ "--"
+ ["Customize Group..." (customize-group 'smarty-misc) t])
+ "--"
+ ["Save Options" customize-save-customized t]
+ ["Activate Options" smarty-activate-customizations t]
+ ["Browse Options..." smarty-customize t])))
+
+(defvar smarty-mode-menu-list (smarty-create-mode-menu)
+ "Smarty Mode menu.")
+
+(defvar smarty-mode-map nil
+ "Keymap for Smarty Mode.")
+
+(defun smarty-update-mode-menu ()
+ "Update Smarty Mode menu."
+ (interactive)
+ (easy-menu-remove smarty-mode-menu-list)
+ (setq smarty-mode-menu-list (smarty-create-mode-menu))
+ (easy-menu-add smarty-mode-menu-list)
+ (easy-menu-define smarty-mode-menu smarty-mode-map
+ "Menu keymap for Smarty Mode." smarty-mode-menu-list))
+
+
+
+
+(defvar smarty-mode-hook nil)
+
+(defvar smarty-functions nil
+ "List of Smarty functions.")
+
+(defvar smarty-functions-regexp nil
+ "Regexp for Smarty functions.")
+
+(defconst smarty-01-functions
+ '("capture" "config_load" "foreach" "foreachelse" "include"
+ "include_php" "insert" "if" "elseif" "else" "ldelim" "rdelim"
+ "literal" "php" "section" "sectionelse" "strip" "assign" "counter"
+ "cycle" "debug" "eval" "fetch" "html_checkboxes" "html_image"
+ "html_options" "html_radios" "html_select_date" "html_select_time"
+ "html_table" "math" "mailto" "popup_init" "popup" "textformat")
+ "Smarty built-in & custom functions.")
+
+(defvar smarty-modifiers nil
+ "List of Smarty variable modifiers.")
+
+(defvar smarty-modifiers-regexp nil
+ "Regexp for Smarty variable modifiers.")
+
+(defconst smarty-01-modifiers
+ '("capitalize" "cat" "count_characters" "count_paragraphs"
+ "count_sentences" "count_words" "date_format" "default"
+ "escape" "indent" "lower" "nl2br" "regex_replace" "replace"
+ "spacify" "string_format" "strip" "strip_tags" "truncate"
+ "upper" "wordwrap")
+ "Smarty variable modifiers.")
+
+(defvar smarty-plugins-functions nil
+ "List of Smarty functions.")
+
+(defvar smarty-plugins-functions-regexp nil
+ "Regexp for Smarty functions.")
+
+(defconst smarty-01-plugins-functions
+ '("validate" "formtool_checkall" "formtool_copy" "formtool_count_chars"
+ "formtool_init" "formtool_move" "formtool_moveall"
+ "formtool_movedown" "formtool_moveup" "formtool_remove"
+ "formtool_rename" "formtool_save" "formtool_selectall"
+ "paginate_first" "paginate_last" "paginate_middle"
+ "paginate_next" "paginate_prev" "clipcache" "include_clipcache"
+ "repeat" "str_repeat")
+ "Smarty plugins functions.")
+
+(defvar smarty-plugins-modifiers nil
+ "List of Smarty variable modifiers.")
+
+(defvar smarty-plugins-modifiers-regexp nil
+ "Regexp for Smarty functions.")
+
+(defconst smarty-01-plugins-modifiers
+ '("B2Smilies" "bbcode2html" "date_format2")
+ "Smarty plugins modifiers.")
+
+(defconst smarty-constants
+ (eval-when-compile
+ (regexp-opt
+ '("TRUE" "FALSE" "NULL") t))
+ "Smarty constants.")
+
+
+;; Syntax table creation
+(defvar smarty-mode-syntax-table nil
+ "Syntax table for smarty-mode.")
+
+(defvar smarty-mode-ext-syntax-table nil
+ "Syntax table extended by `_' used in `smarty-mode' buffers.")
+
+(defun smarty-create-syntax-table ()
+ (if smarty-mode-syntax-table
+ ()
+ (setq smarty-mode-syntax-table (make-syntax-table))
+
+ ;; Make | a punctuation character
+ (modify-syntax-entry ?| "." smarty-mode-syntax-table)
+ ;; Make " a punctuation character so highlighing works withing html strings
+ (modify-syntax-entry ?\" "." smarty-mode-syntax-table)
+ ;; define parentheses to match
+ (modify-syntax-entry ?\( "()" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\) ")(" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\{ "(}" smarty-mode-syntax-table)
+ (modify-syntax-entry ?\} "){" smarty-mode-syntax-table)
+ )
+ (set-syntax-table smarty-mode-syntax-table)
+ ;; extended syntax table including '_' (for simpler search regexps)
+ (setq smarty-mode-ext-syntax-table (copy-syntax-table smarty-mode-syntax-table))
+ (modify-syntax-entry ?_ "w" smarty-mode-ext-syntax-table))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; File/directory manipulation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-directory-files (directory &optional full match)
+ "Call `directory-files' if DIRECTORY exists, otherwise generate error
+message."
+ (if (not (file-directory-p directory))
+ (smarty-warning-when-idle "No such directory: \"%s\"" directory)
+ (let ((dir (directory-files directory full match)))
+ (setq dir (delete "." dir))
+ (setq dir (delete ".." dir))
+ dir)))
+
+(defun smarty-get-source-files (&optional full directory)
+ "Get list of SMARTY source files in DIRECTORY or current directory."
+ (let ((mode-alist auto-mode-alist)
+ filename-regexp)
+ ;; create regular expressions for matching file names
+ (setq filename-regexp "\\`[^.].*\\(")
+ (while mode-alist
+ (when (eq (cdar mode-alist) 'smarty-mode)
+ (setq filename-regexp
+ (concat filename-regexp (caar mode-alist) "\\|")))
+ (setq mode-alist (cdr mode-alist)))
+ (setq filename-regexp
+ (concat (substring filename-regexp 0
+ (string-match "\\\\|$" filename-regexp)) "\\)"))
+ ;; find files
+ (smarty-directory-files
+ (or directory default-directory) full filename-regexp)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Messages reporting
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-warnings nil
+ "Warnings to tell the user during start up.")
+
+(defun smarty-run-when-idle (secs repeat function)
+ "Wait until idle, then run FUNCTION."
+ (if (fboundp 'start-itimer)
+ (start-itimer "smarty-mode" function secs repeat t)
+; (run-with-idle-timer secs repeat function)))
+ ;; explicitely activate timer (necessary when Emacs is already idle)
+ (aset (run-with-idle-timer secs repeat function) 0 nil)))
+
+(defun smarty-warning-when-idle (&rest args)
+ "Wait until idle, then print out warning STRING and beep."
+ (save-match-data ;; runs in timer
+ (if noninteractive
+ (smarty-warning (apply 'format args) t)
+ (unless smarty-warnings
+ (smarty-run-when-idle .1 nil 'smarty-print-warnings))
+ (setq smarty-warnings (cons (apply 'format args) smarty-warnings)))))
+
+(defun smarty-warning (string &optional nobeep)
+ "Print out warning STRING and beep."
+ (message (concat "WARNING: " string))
+ (unless (or nobeep noninteractive) (beep)))
+
+(defun smarty-print-warnings ()
+ "Print out messages in variable `smarty-warnings'."
+ (let ((no-warnings (length smarty-warnings)))
+ (setq smarty-warnings (nreverse smarty-warnings))
+ (while smarty-warnings
+ (message (concat "WARNING: " (car smarty-warnings)))
+ (setq smarty-warnings (cdr smarty-warnings)))
+ (beep)
+ (when (> no-warnings 1)
+ (message "WARNING: See warnings in message buffer (type `C-c M-m')."))))
+
+(defun smarty-show-messages ()
+ "Get *Messages* buffer to show recent messages."
+ (interactive)
+ (display-buffer " *Message-Log*"))
+
+(defun smarty-version ()
+ "Echo the current version of Smarty Mode in the minibuffer."
+ (interactive)
+ (message "Smarty Mode %s (%s)" smarty-version smarty-time-stamp)
+ (smarty-keep-region-active))
+
+;; active regions
+(defun smarty-keep-region-active ()
+ "Do whatever is necessary to keep the region active in XEmacs.
+Ignore byte-compiler warnings you might see."
+ (and (boundp 'zmacs-region-stays)
+ (setq zmacs-region-stays t)))
+
+(defmacro smarty-prepare-search-1 (&rest body)
+ "Enable case insensitive search and switch to syntax table that includes '_',
+then execute BODY, and finally restore the old environment. Used for
+consistent searching."
+ `(let ((case-fold-search t) ; case insensitive search
+ (current-syntax-table (syntax-table))
+ result
+ (restore-prog ; program to restore enviroment
+ '(progn
+ ;; restore syntax table
+ (set-syntax-table current-syntax-table))))
+ ;; use extended syntax table
+ (set-syntax-table smarty-mode-ext-syntax-table)
+ ;; execute BODY safely
+ (setq result
+ (condition-case info
+ (progn ,@body)
+ (error (eval restore-prog) ; restore environment on error
+ (error (cadr info))))) ; pass error up
+ ;; restore environment
+ (eval restore-prog)
+ result))
+
+(defmacro smarty-prepare-search-2 (&rest body)
+ "Enable case insensitive search, switch to syntax table that includes '_',
+and remove `intangible' overlays, then execute BODY, and finally restore the
+old environment. Used for consistent searching."
+ `(let ((case-fold-search t) ; case insensitive search
+ (current-syntax-table (syntax-table))
+ result overlay-all-list overlay-intangible-list overlay
+ (restore-prog ; program to restore enviroment
+ '(progn
+ ;; restore syntax table
+ (set-syntax-table current-syntax-table)
+ ;; restore `intangible' overlays
+ (when (fboundp 'overlay-lists)
+ (while overlay-intangible-list
+ (overlay-put (car overlay-intangible-list) 'intangible t)
+ (setq overlay-intangible-list
+ (cdr overlay-intangible-list)))))))
+ ;; use extended syntax table
+ (set-syntax-table smarty-mode-ext-syntax-table)
+ ;; remove `intangible' overlays
+ (when (fboundp 'overlay-lists)
+ (setq overlay-all-list (overlay-lists))
+ (setq overlay-all-list
+ (append (car overlay-all-list) (cdr overlay-all-list)))
+ (while overlay-all-list
+ (setq overlay (car overlay-all-list))
+ (when (memq 'intangible (overlay-properties overlay))
+ (setq overlay-intangible-list
+ (cons overlay overlay-intangible-list))
+ (overlay-put overlay 'intangible nil))
+ (setq overlay-all-list (cdr overlay-all-list))))
+ ;; execute BODY safely
+ (setq result
+ (condition-case info
+ (progn ,@body)
+ (error (eval restore-prog) ; restore environment on error
+ (error (cadr info))))) ; pass error up
+ ;; restore environment
+ (eval restore-prog)
+ result))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Enabling/disabling
+
+(defun smarty-mode-line-update ()
+ "Update the modeline string for Smarty major mode."
+ (setq mode-name (concat "Smarty"
+ (and (or smarty-electric-mode smarty-stutter-mode) "/")
+ (and smarty-electric-mode "e")
+ (and smarty-stutter-mode "s")))
+ (force-mode-line-update t))
+
+(defun smarty-electric-mode (arg)
+ "Toggle Smarty electric mode.
+Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
+ (interactive "P")
+ (setq smarty-electric-mode
+ (cond ((or (not arg) (zerop arg)) (not smarty-electric-mode))
+ ((> arg 0) t) (t nil)))
+ (smarty-mode-line-update))
+
+(defun smarty-stutter-mode (arg)
+ "Toggle Smarty stuttering mode.
+Turn on if ARG positive, turn off if ARG negative, toggle if ARG zero or nil."
+ (interactive "P")
+ (setq smarty-stutter-mode
+ (cond ((or (not arg) (zerop arg)) (not smarty-stutter-mode))
+ ((> arg 0) t) (t nil)))
+ (smarty-mode-line-update))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Smarty code delimitation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-in-literal ()
+ "Determine if point is in a Smarty literal."
+ (save-excursion
+ (let ((here (point))
+ start state)
+ (beginning-of-line)
+ (setq start (point))
+ (goto-char here)
+ (setq state (parse-partial-sexp start (point)))
+ (cond
+ ((nth 3 state) 'string)
+ ((nth 4 state) 'comment)
+ (t nil)))))
+
+(defun smarty-in-comment-p ()
+ "Check if point is in a comment."
+ (let ((result nil) (here (point-marker)) found)
+ (save-excursion
+ (setq found (re-search-backward (regexp-quote (concat smarty-left-delimiter "*")) nil t))
+ (when found
+ (setq result (re-search-forward (regexp-quote (concat "*" smarty-right-delimiter)) here t))
+ (setq result (not result))))
+ result))
+
+(defun smarty-after-ldelim ()
+ "Check that the previous character is the left delimiter."
+ (let ((here (point-marker)) ldelim-found ldelim-point)
+ (save-excursion
+ (setq ldelim-found (re-search-backward (regexp-quote smarty-left-delimiter) nil t))
+ (re-search-forward (regexp-quote smarty-left-delimiter) here t)
+ (setq ldelim-point (point-marker))
+ (goto-char here)
+ (if (and (= here ldelim-point) ldelim-found)
+ t
+ nil))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Words to expand
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-words-init ()
+ "Initialize reserved words."
+ (setq smarty-functions smarty-01-functions)
+ (setq smarty-modifiers smarty-01-modifiers)
+ (setq smarty-plugins-functions smarty-01-plugins-functions)
+ (setq smarty-plugins-modifiers smarty-01-plugins-modifiers)
+ (setq smarty-functions-regexp (concat "\\<\\(" (regexp-opt smarty-functions) "\\)\\>"))
+ (setq smarty-modifiers-regexp (concat "\\<\\(" (regexp-opt smarty-modifiers) "\\)\\>"))
+ (setq smarty-plugins-functions-regexp (concat "\\<\\(" (regexp-opt smarty-plugins-functions) "\\)\\>"))
+ (setq smarty-plugins-modifiers-regexp (concat "\\<\\(" (regexp-opt smarty-plugins-modifiers) "\\)\\>"))
+ (smarty-abbrev-list-init))
+
+(defvar smarty-abbrev-list nil
+ "Predefined abbreviations for Smarty.")
+
+(defun smarty-abbrev-list-init ()
+ (setq smarty-abbrev-list
+ (append
+ (list nil) smarty-functions
+ (list nil) smarty-modifiers
+ (list nil) smarty-plugins-functions
+ (list nil) smarty-plugins-modifiers)))
+
+(defvar smarty-expand-upper-case nil)
+
+(defun smarty-try-expand-abbrev (old)
+ "Try expanding abbreviations from `smarty-abbrev-list'."
+ (unless old
+ (he-init-string (he-dabbrev-beg) (point))
+ (setq he-expand-list
+ (let ((abbrev-list smarty-abbrev-list)
+ (sel-abbrev-list '()))
+ (while abbrev-list
+ ; (if (stringp (car abbrev-list))
+ ; (insert (concat " " (car abbrev-list))))
+ (when (or (not (stringp (car abbrev-list)))
+ (string-match
+ (concat "^" he-search-string) (car abbrev-list)))
+ (setq sel-abbrev-list
+ (cons (car abbrev-list) sel-abbrev-list)))
+ (setq abbrev-list (cdr abbrev-list)))
+ (nreverse sel-abbrev-list))))
+ (while (and he-expand-list
+ (or (not (stringp (car he-expand-list)))
+ (he-string-member (car he-expand-list) he-tried-table t)))
+ (unless (stringp (car he-expand-list))
+ (setq smarty-expand-upper-case (car he-expand-list)))
+ (setq he-expand-list (cdr he-expand-list)))
+ (if (null he-expand-list)
+ (progn (when old (he-reset-string))
+ nil)
+ (he-substitute-string
+ (if smarty-expand-upper-case
+ (upcase (car he-expand-list))
+ (car he-expand-list))
+ t)
+ (setq he-expand-list (cdr he-expand-list))
+ t))
+
+;; initialize reserved words for Smarty Mode
+(smarty-words-init)
+
+;; function for expanding abbrevs and dabbrevs
+(defun smarty-expand-abbrev (arg))
+(fset 'smarty-expand-abbrev (make-hippie-expand-function
+ '(try-expand-dabbrev
+ try-expand-dabbrev-all-buffers
+ smarty-try-expand-abbrev)))
+
+;; function for expanding parenthesis
+(defun smarty-expand-paren (arg))
+(fset 'smarty-expand-paren (make-hippie-expand-function
+ '(try-expand-list
+ try-expand-list-all-buffers)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Stuttering
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-end-comment-column 80)
+
+(defvar found) ;; silence compiler, dyn var
+
+(defun smarty-electric-tab (&optional prefix-arg)
+ "If preceding character is part of a word or a paren then hippie-expand,
+else if right of non whitespace on line then insert tab,
+else if last command was a tab or return then dedent one step or if a comment
+toggle between normal indent and inline comment indent,
+else indent `correctly'."
+ (interactive "*P")
+ (smarty-prepare-search-2
+ (cond
+ ;; expand word
+ ((= (char-syntax (preceding-char)) ?w)
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil)
+ (hippie-expand-only-buffers
+ (or (and (boundp 'hippie-expand-only-buffers)
+ hippie-expand-only-buffers)
+ '(smarty-mode))))
+ (smarty-expand-abbrev prefix-arg)))
+ ;; expand parenthesis
+ ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil))
+ (smarty-expand-paren prefix-arg))))
+ (setq this-command 'smarty-electric-tab)))
+
+(defun smarty-electric-space (count)
+ "Expand abbreviations and self-insert space(s)."
+ (interactive "p")
+ (let ((here (point-marker)) ldelim-found ldelim-point rdelim-found rdelim-point
+ delete-a)
+ (setq ldelim-found (re-search-backward (regexp-quote smarty-left-delimiter) nil t))
+ (re-search-forward (regexp-quote smarty-left-delimiter) here t)
+ (setq ldelim-point (point-marker))
+ (goto-char here)
+ (setq rdelim-found (re-search-backward (regexp-quote (concat " " smarty-right-delimiter)) nil t))
+ (re-search-forward (regexp-quote (concat " " smarty-right-delimiter)) here t)
+ (setq rdelim-point (point-marker))
+ (goto-char here)
+ (cond ((and (= here ldelim-point) ldelim-found) (insert (concat "ldelim" smarty-right-delimiter)))
+ ((and (= here rdelim-point) rdelim-found)
+ (re-search-backward (regexp-quote (concat " " smarty-right-delimiter)) nil t)
+ (delete-char 1)
+ (insert (concat " " smarty-left-delimiter "rdelim"))
+ (goto-char here))
+ ((smarty-in-comment-p)
+ (self-insert-command count)
+ (cond ((>= (current-column) (+ 2 smarty-end-comment-column))
+ (backward-char 1)
+ (skip-chars-backward "^ \t\n")
+ (indent-new-comment-line)
+ (skip-chars-forward "^ \t\n")
+ (forward-char 1))
+ ((>= (current-column) smarty-end-comment-column)
+ (indent-new-comment-line))
+ (t nil)))
+ ((or (and (>= (preceding-char) ?a) (<= (preceding-char) ?z))
+ (and (>= (preceding-char) ?A) (<= (preceding-char) ?Z))
+ (and (>= (preceding-char) ?0) (<= (preceding-char) ?9)))
+ (progn
+ (setq here (point-marker))
+ (insert " ")
+ (setq delete-a t)
+ (if (re-search-backward "|" nil t)
+ (progn
+ (setq found (re-search-forward (regexp-quote "B2Smilies") here t))
+ (if (and found (= here (point-marker)))
+ (replace-match "btosmilies")
+ (setq found (re-search-forward (regexp-quote "bbcode2html") here t))
+ (if (and found (= here (point-marker)))
+ (replace-match "bbcodetohtml")
+ (setq found (re-search-forward (regexp-quote "date_format2") here t))
+ (if (and found (= here (point-marker)))
+ (replace-match "date_formatto")
+ (goto-char here)
+ (setq delete-a nil)
+ (delete-char 1)))))
+ (goto-char here)
+ (setq delete-a nil)
+ (delete-char 1)))
+ (smarty-prepare-search-1 (expand-abbrev))
+ (self-insert-command count)
+ (if (and delete-a (looking-at " "))
+ (delete-char 1)))
+ (t (self-insert-command count)))))
+
+(defun smarty-electric-open-bracket (count)
+ "'(' --> '(', '((' --> '[', '[(' --> '{'"
+ (interactive "p")
+ (if (and smarty-stutter-mode (= count 1) (not (smarty-in-literal)))
+ (if (= (preceding-char) ?\()
+ (progn (delete-char -1) (insert-char ?\[ 1))
+ (if (= (preceding-char) ?\[)
+ (progn (delete-char -1) (insert-char ?\{ 1))
+ (insert-char ?\( 1)))
+ (self-insert-command count)))
+
+(defun smarty-electric-close-bracket (count)
+ "')' --> ')', '))' --> ']', '])' --> '}'"
+ (interactive "p")
+ (if (and smarty-stutter-mode (= count 1) (not (smarty-in-literal)))
+ (progn
+ (if (= (preceding-char) ?\))
+ (progn (delete-char -1) (insert-char ?\] 1))
+ (if (= (preceding-char) ?\])
+ (progn (delete-char -1) (insert-char ?} 1))
+ (insert-char ?\) 1)))
+ (blink-matching-open))
+ (self-insert-command count)))
+
+(defun smarty-electric-star (count)
+ "After a left delimiter add a right delemiter to close the comment"
+ (interactive "p")
+ (let ((here (point-marker)) found)
+ (if (and smarty-stutter-mode (= count 1) (not (smarty-in-literal)))
+ (progn
+ (setq found (re-search-backward (regexp-quote smarty-left-delimiter) nil t))
+ (re-search-forward (regexp-quote smarty-left-delimiter) here t)
+ (if (not (and (= here (point-marker)) found))
+ (progn (goto-char here)
+ (self-insert-command count))
+ (self-insert-command count)
+ (insert " ")
+ (setq here (point-marker))
+ (insert " *")
+ (insert smarty-right-delimiter)
+ (goto-char here)))
+ (self-insert-command count))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Electrification
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defconst smarty-template-prompt-syntax "[^ =<>][^<>@.\n]*[^ =<>]"
+ "Syntax of prompt inserted by template generators.")
+
+(defvar smarty-template-invoked-by-hook nil
+ "Indicates whether a template has been invoked by a hook or by key or menu.
+Used for undoing after template abortion.")
+
+(defun smarty-minibuffer-tab (&optional prefix-arg)
+ "If preceding character is part of a word or a paren then hippie-expand,
+else insert tab (used for word completion in Smarty minibuffer)."
+ (interactive "P")
+ (cond
+ ;; expand word
+ ((= (char-syntax (preceding-char)) ?w)
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil)
+ (hippie-expand-only-buffers
+ (or (and (boundp 'hippie-expand-only-buffers)
+ hippie-expand-only-buffers)
+ '(smarty-mode))))
+ (smarty-expand-abbrev prefix-arg)))
+ ;; expand parenthesis
+ ((or (= (preceding-char) ?\() (= (preceding-char) ?\)))
+ (let ((case-fold-search (not smarty-word-completion-case-sensitive))
+ (case-replace nil))
+ (smarty-expand-paren prefix-arg)))
+ ;; insert tab
+ (t (insert-tab))))
+
+;; correct different behavior of function `unread-command-events' in XEmacs
+(defun smarty-character-to-event (arg))
+(defalias 'smarty-character-to-event
+ (if (fboundp 'character-to-event) 'character-to-event 'identity))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Abbrev ook bindings
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-mode-abbrev-table nil
+ "Abbrev table to use in `smarty-mode' buffers.")
+
+(defun smarty-mode-abbrev-table-init ()
+ "Initialize `smarty-mode-abbrev-table'."
+ (when smarty-mode-abbrev-table (clear-abbrev-table smarty-mode-abbrev-table))
+ (define-abbrev-table 'smarty-mode-abbrev-table
+ (append
+ '(
+ ("capture" "" smarty-template-capture-hook 0)
+ ("config_load" "" smarty-template-config-load-hook 0)
+ ("else" "" smarty-template-else-hook 0)
+ ("elseif" "" smarty-template-elseif-hook 0)
+ ("foreach" "" smarty-template-foreach-hook 0)
+ ("foreachelse" "" smarty-template-foreachelse-hook 0)
+ ("if" "" smarty-template-if-hook 0)
+ ("include" "" smarty-template-include-hook 0)
+ ("include_php" "" smarty-template-include-php-hook 0)
+ ("insert" "" smarty-template-insert-hook 0)
+ ("ldelim" "" smarty-template-ldelim-hook 0)
+ ("literal" "" smarty-template-literal-hook 0)
+ ("php" "" smarty-template-php-hook 0)
+ ("rdelim" "" smarty-template-rdelim-hook 0)
+ ("section" "" smarty-template-section-hook 0)
+ ("sectionelse" "" smarty-template-sectionelse-hook 0)
+ ("strip" "" smarty-template-strip-hook 0)
+ ("assign" "" smarty-template-assign-hook 0)
+ ("counter" "" smarty-template-counter-hook 0)
+ ("cycle" "" smarty-template-cycle-hook 0)
+ ("debug" "" smarty-template-debug-hook 0)
+ ("eval" "" smarty-template-eval-hook 0)
+ ("fetch" "" smarty-template-fetch-hook 0)
+ ("html_checkboxes" "" smarty-template-html-checkboxes-hook 0)
+ ("html_image" "" smarty-template-html-image-hook 0)
+ ("html_options" "" smarty-template-html-options-hook 0)
+ ("html_radios" "" smarty-template-html-radios-hook 0)
+ ("html_select_date" "" smarty-template-html-select-date-hook 0)
+ ("html_select_time" "" smarty-template-html-select-time-hook 0)
+ ("html_table" "" smarty-template-html-table-hook 0)
+ ("mailto" "" smarty-template-mailto-hook 0)
+ ("math" "" smarty-template-math-hook 0)
+ ("popup" "" smarty-template-popup-hook 0)
+ ("popup_init" "" smarty-template-popup-init-hook 0)
+ ("textformat" "" smarty-template-textformat-hook 0)
+ ("capitalize" "" smarty-template-capitalize-hook 0)
+ ("cat" "" smarty-template-cat-hook 0)
+ ("count_characters" "" smarty-template-count-characters-hook 0)
+ ("count_paragraphs" "" smarty-template-count-paragraphs-hook 0)
+ ("count_sentences" "" smarty-template-count-sentences-hook 0)
+ ("count_words" "" smarty-template-count-words-hook 0)
+ ("date_format" "" smarty-template-date-format-hook 0)
+ ("default" "" smarty-template-default-hook 0)
+ ("escape" "" smarty-template-escape-hook 0)
+ ("indent" "" smarty-template-indent-hook 0)
+ ("lower" "" smarty-template-lower-hook 0)
+ ("nl2br" "" smarty-template-nl2br-hook 0)
+ ("regex_replace" "" smarty-template-regex-replace-hook 0)
+ ("replace" "" smarty-template-replace-hook 0)
+ ("spacify" "" smarty-template-spacify-hook 0)
+ ("string_format" "" smarty-template-string-format-hook 0)
+ ("strip" "" smarty-template-vstrip-hook 0)
+ ("strip_tags" "" smarty-template-strip-tags-hook 0)
+ ("truncate" "" smarty-template-truncate-hook 0)
+ ("upper" "" smarty-template-upper-hook 0)
+ ("wordwrap" "" smarty-template-wordwrap-hook 0)
+ ("validate" "" smarty-template-validate-hook 0)
+ ("clipcache" "" smarty-template-clipcache-hook 0)
+ ("repeat" "" smarty-template-repeat-hook 0)
+ ("str_repeat" "" smarty-template-str-repeat-hook 0)
+ ("include_clipcache" "" smarty-template-include-clipcache-hook 0)
+ ("formtool_checkall" "" smarty-template-formtool-checkall-hook 0)
+ ("formtool_copy" "" smarty-template-formtool-copy-hook 0)
+ ("formtool_count_chars" "" smarty-template-formtool-count-chars-hook 0)
+ ("formtool_init" "" smarty-template-formtool-init-hook 0)
+ ("formtool_move" "" smarty-template-formtool-move-hook 0)
+ ("formtool_moveall" "" smarty-template-formtool-moveall-hook 0)
+ ("formtool_movedown" "" smarty-template-formtool-movedown-hook 0)
+ ("formtool_moveup" "" smarty-template-formtool-moveup-hook 0)
+ ("formtool_remove" "" smarty-template-formtool-remove-hook 0)
+ ("formtool_rename" "" smarty-template-formtool-rename-hook 0)
+ ("formtool_save" "" smarty-template-formtool-save-hook 0)
+ ("formtool_selectall" "" smarty-template-formtool-selectall-hook 0)
+ ("paginate_first" "" smarty-template-paginate-first-hook 0)
+ ("paginate_last" "" smarty-template-paginate-last-hook 0)
+ ("paginate_middle" "" smarty-template-paginate-middle-hook 0)
+ ("paginate_next" "" smarty-template-paginate-next-hook 0)
+ ("paginate_prev" "" smarty-template-paginate-prev-hook 0)
+ ("btosmilies" "" smarty-template-btosmilies-hook 0)
+ ("bbcodetohtml" "" smarty-template-bbcodetohtml-hook 0)
+ ("date_formatto" "" smarty-template-date-formatto-hook 0)))))
+
+;; initialize abbrev table for Smarty Mode
+(smarty-mode-abbrev-table-init)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Abbrev hooks
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-hooked-abbrev (func)
+ "Do function, if syntax says abbrev is a keyword, invoked by hooked abbrev,
+but not if inside a comment or quote)."
+ (if (or (smarty-in-literal)
+ (smarty-in-comment-p))
+ (progn
+ (insert " ")
+ (unexpand-abbrev)
+ (delete-char -1))
+ (if (not smarty-electric-mode)
+ (progn
+ (insert " ")
+ (unexpand-abbrev)
+ (backward-word 1)
+ (delete-char 1))
+ (let ((invoke-char last-command-event)
+ (abbrev-mode -1)
+ (smarty-template-invoked-by-hook t))
+ (let ((caught (catch 'abort
+ (funcall func))))
+ (when (stringp caught) (message caught)))
+ (when (= invoke-char ?-) (setq abbrev-start-location (point)))
+ ;; delete CR which is still in event queue
+ (if (fboundp 'enqueue-eval-event)
+ (enqueue-eval-event 'delete-char -1)
+ (setq unread-command-events ; push back a delete char
+ (list (smarty-character-to-event ?\177))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Fontification
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-font-lock-keywords-1
+ (list
+
+ ;; Fontify built-in functions
+ (cons
+ (concat (regexp-quote smarty-left-delimiter) "[/]*" smarty-functions-regexp)
+ '(1 font-lock-keyword-face))
+
+ (cons
+ (concat "\\<\\(" smarty-constants "\\)\\>")
+ 'font-lock-constant-face)
+
+ (cons (concat "\\(" (regexp-quote (concat smarty-left-delimiter "*")) "\\(\\s-\\|\\w\\|\\s.\\|\\s_\\|\\s(\\|\\s)\\|\\s\\\\)*" (regexp-quote (concat "*" smarty-right-delimiter)) "\\)")
+ 'font-lock-comment-face)
+
+ )
+ "Subdued level highlighting for Smarty mode.")
+
+(defconst smarty-font-lock-keywords-2
+ (append
+ smarty-font-lock-keywords-1
+ (list
+
+ ;; Fontify variable names (\\sw\\|\\s_\\) matches any word character +
+ ;; underscore
+ '("\\$\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face)) ; $variable
+ '("->\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face t t)) ; ->variable
+ '("\\.\\(\\(?:\\sw\\|\\s_\\)+\\)" (1 font-lock-variable-name-face t t)) ; .variable
+ '("->\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" (1 font-lock-function-name-face t t)) ; ->function_call
+ '("\\<\\(\\(?:\\sw\\|\\s_\\)+\\s-*\\)(" (1 font-lock-function-name-face)) ; word(
+ '("\\<\\(\\(?:\\sw\\|\\s_\\)+\\s-*\\)[[]" (1 font-lock-variable-name-face)) ; word[
+ '("\\<[0-9]+" . 'default) ; number (also matches word)
+
+ ;; Fontify strings
+ ;;'("\"\\([^\"]*\\)\"[^\"]+" (1 font-lock-string-face t t))
+ ))
+
+ "Medium level highlighting for Smarty mode.")
+
+(defconst smarty-font-lock-keywords-3
+ (append
+ smarty-font-lock-keywords-2
+ (list
+ ;; Fontify modifiers
+ (cons (concat "|\\(" smarty-modifiers-regexp "\\)[:|]+") '(1 font-lock-function-name-face))
+ (cons (concat "|\\(" smarty-modifiers-regexp "\\)" (regexp-quote smarty-right-delimiter)) '(1 font-lock-function-name-face))
+
+ ;; Fontify config vars
+ (cons (concat (regexp-quote smarty-left-delimiter) "\\(#\\(?:\\sw\\|\\s_\\)+#\\)") '(1 font-lock-constant-face))))
+ "Balls-out highlighting for Smarty mode.")
+
+(defconst smarty-font-lock-keywords-4
+ (append
+ smarty-font-lock-keywords-3
+ (list
+ ;; Fontify plugin functions
+ (cons
+ (concat (regexp-quote smarty-left-delimiter) "[/]*" smarty-plugins-functions-regexp)
+ '(1 font-lock-keyword-face))
+
+ (cons (concat "|\\(" smarty-plugins-modifiers-regexp "\\)[:|]+") '(1 font-lock-function-name-face))
+ (cons (concat "|\\(" smarty-plugins-modifiers-regexp "\\)" (regexp-quote smarty-right-delimiter)) '(1 font-lock-function-name-face)))))
+
+(defvar smarty-font-lock-keywords smarty-font-lock-keywords-3
+ "Default highlighting level for Smarty mode")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Mode map
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar smarty-template-map nil
+ "Keymap for Smarty templates.")
+
+(defun smarty-template-map-init ()
+ "Initialize `smarty-template-map'."
+ (setq smarty-template-map (make-sparse-keymap))
+ ;; key bindings for Smarty templates
+ (define-key smarty-template-map "\C-ba" 'smarty-template-capture)
+ (define-key smarty-template-map "\C-bc" 'smarty-template-config-load)
+ (define-key smarty-template-map "\C-b\M-e" 'smarty-template-else)
+ (define-key smarty-template-map "\C-b\C-e" 'smarty-template-elseif)
+ (define-key smarty-template-map "\C-b\C-f" 'smarty-template-foreach)
+ (define-key smarty-template-map "\C-b\M-f" 'smarty-template-foreachelse)
+ (define-key smarty-template-map "\C-bf" 'smarty-template-if)
+ (define-key smarty-template-map "\C-b\C-i" 'smarty-template-include)
+ (define-key smarty-template-map "\C-b\M-i" 'smarty-template-include-php)
+ (define-key smarty-template-map "\C-bi" 'smarty-template-insert)
+ (define-key smarty-template-map "\C-bl" 'smarty-template-ldelim)
+ (define-key smarty-template-map "\C-b\C-l" 'smarty-template-literal)
+ (define-key smarty-template-map "\C-bp" 'smarty-template-php)
+ (define-key smarty-template-map "\C-br" 'smarty-template-rdelim)
+ (define-key smarty-template-map "\C-b\C-s" 'smarty-template-section)
+ (define-key smarty-template-map "\C-b\M-s" 'smarty-template-sectionelse)
+ (define-key smarty-template-map "\C-bs" 'smarty-template-strip)
+ (define-key smarty-template-map "\C-ca" 'smarty-template-assign)
+ (define-key smarty-template-map "\C-co" 'smarty-template-counter)
+ (define-key smarty-template-map "\C-cc" 'smarty-template-cycle)
+ (define-key smarty-template-map "\C-cd" 'smarty-template-debug)
+ (define-key smarty-template-map "\C-ce" 'smarty-template-eval)
+ (define-key smarty-template-map "\C-cf" 'smarty-template-fetch)
+ (define-key smarty-template-map "\C-c\C-hc" 'smarty-template-html-checkboxes)
+ (define-key smarty-template-map "\C-c\C-hi" 'smarty-template-html-image)
+ (define-key smarty-template-map "\C-c\C-ho" 'smarty-template-html-options)
+ (define-key smarty-template-map "\C-c\C-hr" 'smarty-template-html-radios)
+ (define-key smarty-template-map "\C-c\C-hd" 'smarty-template-html-select-date)
+ (define-key smarty-template-map "\C-c\C-hm" 'smarty-template-html-select-time)
+ (define-key smarty-template-map "\C-c\C-ht" 'smarty-template-html-table)
+ (define-key smarty-template-map "\C-ci" 'smarty-template-mailto)
+ (define-key smarty-template-map "\C-ch" 'smarty-template-math)
+ (define-key smarty-template-map "\C-c\C-p" 'smarty-template-popup)
+ (define-key smarty-template-map "\C-c\M-p" 'smarty-template-popup-init)
+ (define-key smarty-template-map "\C-ct" 'smarty-template-textformat)
+ (define-key smarty-template-map "\C-vp" 'smarty-template-capitalize)
+ (define-key smarty-template-map "\C-vc" 'smarty-template-cat)
+ (define-key smarty-template-map "\C-v\C-cc" 'smarty-template-count-characters)
+ (define-key smarty-template-map "\C-v\C-cp" 'smarty-template-count-paragraphs)
+ (define-key smarty-template-map "\C-v\C-cs" 'smarty-template-count-sentences)
+ (define-key smarty-template-map "\C-v\C-cw" 'smarty-template-count-words)
+ (define-key smarty-template-map "\C-vf" 'smarty-template-date-format)
+ (define-key smarty-template-map "\C-vd" 'smarty-template-default)
+ (define-key smarty-template-map "\C-ve" 'smarty-template-escape)
+ (define-key smarty-template-map "\C-vi" 'smarty-template-indent)
+ (define-key smarty-template-map "\C-vl" 'smarty-template-lower)
+ (define-key smarty-template-map "\C-vn" 'smarty-template-nl2br)
+ (define-key smarty-template-map "\C-vx" 'smarty-template-regex-replace)
+ (define-key smarty-template-map "\C-v\C-p" 'smarty-template-replace)
+ (define-key smarty-template-map "\C-vy" 'smarty-template-spacify)
+ (define-key smarty-template-map "\C-vs" 'smarty-template-string-format)
+ (define-key smarty-template-map "\C-v\C-s" 'smarty-template-vstrip)
+ (define-key smarty-template-map "\C-v\M-s" 'smarty-template-strip-tags)
+ (define-key smarty-template-map "\C-vt" 'smarty-template-truncate)
+ (define-key smarty-template-map "\C-vu" 'smarty-template-upper)
+ (define-key smarty-template-map "\C-vw" 'smarty-template-wordwrap)
+ (define-key smarty-template-map "\C-h" 'smarty-template-header)
+ (define-key smarty-template-map "\C-f" 'smarty-template-footer)
+ (define-key smarty-template-map "\C-di" 'smarty-template-insert-date)
+ (define-key smarty-template-map "\C-dm" 'smarty-template-modify))
+
+;; initialize template map for Smarty Mode
+(smarty-template-map-init)
+
+(defun smarty-mode-map-init ()
+ "Initialize `smarty-mode-map'."
+ (setq smarty-mode-map (make-sparse-keymap))
+ ;; template key bindings
+ (define-key smarty-mode-map "\C-c\C-t" smarty-template-map)
+ ;; mode specific key bindings
+ (define-key smarty-mode-map "\C-c\C-m\C-e" 'smarty-electric-mode)
+ (define-key smarty-mode-map "\C-c\C-m\C-s" 'smarty-stutter-mode)
+ (define-key smarty-mode-map "\C-c\C-s\C-u" 'smarty-add-source-files-menu)
+ (define-key smarty-mode-map "\C-c\M-m" 'smarty-show-messages)
+ (define-key smarty-mode-map "\C-c\C-h" 'smarty-doc-mode)
+ (define-key smarty-mode-map "\C-c\C-v" 'smarty-version)
+ ;; electric key bindings
+ (when smarty-intelligent-tab
+ (define-key smarty-mode-map "\t" 'smarty-electric-tab))
+ (define-key smarty-mode-map " " 'smarty-electric-space)
+ (define-key smarty-mode-map "(" 'smarty-electric-open-bracket)
+ (define-key smarty-mode-map ")" 'smarty-electric-close-bracket)
+ (define-key smarty-mode-map "*" 'smarty-electric-star))
+
+;; initialize mode map for Smarty Mode
+(smarty-mode-map-init)
+
+(defvar smarty-minibuffer-local-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map minibuffer-local-map)
+ (when smarty-word-completion-in-minibuffer
+ (define-key map "\t" 'smarty-minibuffer-tab))
+ map)
+ "Keymap for minibuffer used in Smarty Mode.")
+
+(mapcar
+ (function
+ (lambda (sym)
+ (put sym 'delete-selection t) ; for `delete-selection-mode' (Emacs)
+ (put sym 'pending-delete t))) ; for `pending-delete-mode' (XEmacs)
+ '(smarty-electric-space
+ smarty-electric-tab
+ smarty-electric-open-bracket
+ smarty-electric-close-bracket
+ smarty-electric-star))
+
+;;;###autoload
+(defun smarty-mode ()
+ "Smarty Mode
+***********
+
+Smarty Mode is a GNU XEmacs major mode for editing Smarty templates.
+
+1 Introduction
+**************
+
+Smarty-Mode is a mode allowing easy edit of Smarty templates:
+highlight, templates, navigation into source files...
+
+
+
+Features (new features in bold) :
+
+ * Completion
+
+ * Customizable
+
+ * Highlight
+
+ * Menu
+
+ * Stuttering
+
+ * Templates
+ - Built-in Functions
+
+ - User Functions
+
+ - Variable Modifiers
+
+ - Plugin (Functions)
+ * BlockRepeatPlugin
+
+ * ClipCache
+
+ * Smarty Formtool
+
+ * Smarty Paginate
+
+ * Smarty Validate
+
+ - Plugin (Variable Modifiers)
+ * AlternativeDateModifierPlugin
+
+ * B2Smilies
+
+ * BBCodePlugin
+
+ - Fonctions Non-Smarty
+
+
+
+This manual describes Smarty Mode version 0.0.5.
+
+2 Installation
+**************
+
+2.1 Requirements
+================
+
+Smarty Mode is a XEmacs major mode that needs the following
+software/packages:
+
+ * XEmacs (http://www.xemacs.org/).
+
+ * `font-lock' mode generaly installed with XEmacs.
+
+ * `assoc' mode generaly installed with XEmacs.
+
+ * `easymenu' mode generaly installed with XEmacs.
+
+ * `hippie-exp' mode generaly installed with XEmacs.
+
+Before continuing, you must be sure to have all this packages
+installed.
+
+2.2 Download
+============
+
+Two internet address to download Smarty Mode :
+
+ * Principal: Smarty-Mode 0.0.5
+ (http://deboutv.free.fr/lisp/smarty/download/smarty-0.0.5.tar.gz)
+ (http://deboutv.free.fr/lisp/smarty/)
+
+ * Secondary: Smarty-Mode 0.0.5
+ (http://www.morinie.fr/lisp/smarty/download/smarty-0.0.5.tar.gz)
+ (http://www.morinie.fr/lisp/smarty/)
+
+ * Old releases: Smarty-Mode
+ (http://deboutv.free.fr/lisp/smarty/download.php)
+ (http://deboutv.free.fr/lisp/smarty/)
+
+2.3 Installation
+================
+
+2.3.1 Installation
+------------------
+
+To install Smarty Mode you need to choose an installation directory
+\(for example `/usr/local/share/lisp' or `c:\lisp'). The administrator
+must have the write rights on this directory.
+
+With your favorite unzip software, unzip the archive in the
+installation directory.
+
+Example:
+ cd /usr/local/share/lisp
+ tar zxvf smarty-0.0.5.tar.gz
+Now you have a `smarty' directory in the installation directory. This
+directory contains 2 files `smarty-mode.el' and `smarty-mode.elc' and
+another directory `docs' containing the documentation.
+
+You need to configure XEmacs. open you initialization file `init.el'
+\(open the file or start XEmacs then choose the Options menu and Edit
+Init File). Add the following lines (the installation directory in
+this example is `/usr/local/share/lisp') :
+
+ (setq load-path
+ (append (list \"/usr/local/share/lisp/\") load-path))
+ (autoload 'smarty-mode \"smarty-mode\" \"Smarty Mode\" t)
+
+2.3.2 Update
+------------
+
+The update is easy. You need to unzip the archive in the installation
+directory to remove the old release.
+
+Example:
+ cd /usr/local/share/lisp
+ rm -rf smarty
+ tar zxvf smarty-0.0.5.tar.gz
+
+2.4 Invoke Smarty-Mode
+======================
+
+You have two possibilities to invoke the Smarty Mode.
+
+ - Manually: At each file opening you need to launch Smarty Mode
+ with the following command:
+
+ `M-x smarty-mode'
+
+ - Automatically: Add the following linesin your initialization
+ file `init.el' :
+
+ (setq auto-mode-alist
+ (append
+ '((\"\\.tpl$\" . smarty-mode))
+ auto-mode-alist))
+
+
+3 Customization
+***************
+
+This chapter describes the differents parameters and functions that
+you can change to customize Smarty Mode. To do that, open a Smarty
+file, click on the Smarty menu and choose Options then Browse
+Options....
+
+3.1 Parameters
+==============
+
+3.1.1 Mode
+----------
+
+Smarty Mode has 2 modes allowing to simplify the writing of Smarty
+templates. You can enable/disable each mode individually.
+
+`smarty-electric-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable automatic generation of template.
+ If `nil'; template generators can still be invoked through key
+ bindings and menu. Is indicated in the modeline by \"/e\" after
+ the mode name and can be toggled by `smarty-electric-mode'.
+
+`smarty-stutter-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable the stuttering. Is indicated in the
+ modeline by \"/s\" after the mode name and can be toggled by
+ `smarty-stutter-mode'.
+
+3.1.2 Menu
+----------
+
+Smarty Mode has also 1 menu that you can enable/disable. The menu
+Sources is specific to each Smarty files opened.
+
+`smarty-source-file-menu'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; the Sources menu is enabled. This menu
+ contains the list of Smarty file located in the current
+ directory. The Sources menu scans the directory when a file is
+ opened.
+
+3.1.3 Menu
+----------
+
+`smarty-highlight-plugin-functions'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; the functions described in the smarty
+ plugins are highlighted.
+
+3.1.4 Templates
+---------------
+
+3.1.4.1 Header
+..............
+
+`smarty-file-header'
+ Type: string
+ Default value: `\"\"'
+ Description: String or file to insert as file header. If the
+ string specifies an existing file name the contents of the file
+ is inserted; otherwise the string itself is inserted as file
+ header.
+ Type `C-j' for newlines.
+ The follonwing keywords are supported:
+ <filename>: replaced by the file name.
+ <author>: replaced by the user name and email address.
+ <login>: replaced by `user-login-name'.
+ <company>: replaced by `smarty-company-name' content.
+ <date>: replaced by the current date.
+ <year>: replaced by the current year.
+ <copyright>: replaced by `smarty-copyright-string' content.
+ <cursor>: final cursor position.
+
+`smarty-file-footer'
+ Type: string
+ Default value: `\"\"'
+ Description: String or file to insert as file footer. See
+ `smarty-file-header'
+
+`smarty-company-name'
+ Type: string
+ Default value: `\"\"'
+ Description: Name of the company to insert in file header.
+
+`smarty-copyright-string'
+ Type: string
+ Default value: `\"\"'
+ Description: Coryright string to insert in file header.
+
+`smarty-date-format'
+ Type: string
+ Default value: `\"%Y-%m-%d\"'
+ Description: Date format.
+
+`smarty-modify-date-prefix-string'
+ Type: string
+ Default value: `\"\"'
+ Description: Prefix string of modification date in Smarty file
+ header.
+
+`smarty-modify-date-on-saving'
+ Type: bool
+ Default value: `nil'
+ Description: If `t'; update the modification date when the
+ buffer is saved.
+
+3.1.5 Miscellaneous
+-------------------
+
+`smarty-left-delimiter'
+ Type: string
+ Default value: `\"\"'
+ Description: Left escaping delimiter for Smarty templates.
+
+`smarty-right-delimiter'
+ Type: string
+ Default value: `\"\"'
+ Description: Right escaping delimiter for Smarty templates.
+
+`smarty-intelligent-tab'
+ Type: bool
+ Default value: `t'
+ Description: If `t'; TAB does indentation; completion and insert
+ tabulations. If `nil'; TAB does only indentation.
+
+`smarty-word-completion-in-minibuffer'
+ Type: bool
+ Default value: `t'
+ Description: If `t'; enable completion in the minibuffer.
+
+`smarty-word-completion-case-sensitive'
+ Type: bool
+ Default value: `nil'
+ Description: If `t'; completion is case sensitive.
+
+3.2 Functions
+=============
+
+3.2.1 Mode
+----------
+
+`smarty-electric-mode'
+ Menu: Smarty -> Options -> Mode -> Electric Mode
+ Keybinding: `C-c C-m C-e'
+ Description: This functions is used to enable/disable the
+ electric mode.
+
+`smarty-stutter-mode'
+ Menu: Smarty -> Options -> Mode -> Stutter Mode
+ Keybinding: `C-c C-m C-s'
+ Description: This function is used to enable/disable the stutter
+ mode.
+
+4 Menus
+*******
+
+There are 2 menus: Smarty and Sources. All theses menus can be
+accessed from the menubar or from the right click. This chapter
+describes each menus.
+
+4.1 Smarty
+==========
+
+This is the main menu of Smarty Mode. It allows an easy access to the
+main features of the Smarty Mode: Templates (see *Note Templates::)
+and Options (see *Note Customization::).
+
+This menu contains also 3 functions that are discussed in the next
+part.
+
+4.1.1 Functions
+---------------
+
+`smarty-show-messages'
+ Menu: Smarty -> Show Messages
+ Keybinding: `C-c M-m'
+ Description: This function opens the *Messages* buffer to
+ display previous error messages.
+
+`smarty-doc-mode'
+ Menu: Smarty -> Smarty Mode Documentation
+ Keybinding: `C-c C-h'
+ Description: This function opens the *Help* buffer and prints in
+ it the Smarty Mode documentation.
+
+`smarty-version'
+ Menu: Smarty -> Version
+ Keybinding: `C-c C-v'
+ Description: This function displays in the minibuffer the
+ current Smarty Mode version with the timestamp.
+
+4.2 Sources
+===========
+
+The Sources menu shows the Smarty files in the current directory. If
+you add or delete a file in the current directory, you need to
+refresh the menu.
+
+4.2.1 Customization
+-------------------
+
+`smarty-source-file-menu'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; the Sources menu is enabled. This menu
+ contains the list of Smarty file located in the current
+ directory. The Sources menu scans the directory when a file is
+ opened.
+
+4.2.2 Functions
+---------------
+
+`smarty-add-source-files-menu'
+ Menu: Sources -> *Rescan*
+ Keybinding: `C-c C-s C-u'
+ Description: This function is used to refresh the Sources menu.
+
+5 Stuttering
+************
+
+The stutter mode is a mode that affects a function to a key. For
+example, when you use the `ENTER' key, the associated function will
+create a new line and indent it.
+
+5.1 Customization
+=================
+
+`smarty-stutter-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable the stuttering. Is indicated in the
+ modeline by \"/s\" after the mode name and can be toggled by
+ `smarty-stutter-mode'.
+
+5.2 Functions
+=============
+
+`SPACE'
+ If in comment, indent the comment and add new line if necessary.
+ In other case, add a space.
+
+`('
+ If the previous character is a `(', the `((' will be replaced by
+ `['.
+ If the previous character is a `[', the `[(' will be replaced by
+ `{'.
+ In other case, insert a `('.
+
+`)'
+ If the previous character is a `)', the `))' will be replaced by
+ `]'.
+ If the previous character is a `]', the `])' will be replaced by
+ `}'.
+ In other case, insert a `)'.
+
+6 Templates
+***********
+
+In the Smarty Mode, the Smarty functions (like if, while, for, fopen,
+fclose) are predefined in functions called \"Templates\".
+
+Each template can be invoked by the function name or by using the
+<SPACE> key after the Smarty function name in the buffer (Note, using
+`M-<SPACE>' disable the template).
+
+A template can be aborted by using the `C-g' or by lefting empty the
+tempate prompt (in the minibuffer).
+
+6.1 Customization
+=================
+
+`smarty-electric-mode'
+ Type: boolean
+ Default value: `t'
+ Description: If `t'; enable automatic generation of template.
+ If `nil'; template generators can still be invoked through key
+ bindings and menu. Is indicated in the modeline by \"/e\" after
+ the mode name and can be toggled by `smarty-electric-mode'.
+
+For a complete description of the template customizable variables,
+see *Note Cu01-Pa01-Template::
+
+6.2 Functions
+=============
+
+6.2.1 Smarty Functions
+----------------------
+
+For Smarty functions, see PDF or HTML documentation.
+
+6.2.2 Non-Smarty Functions
+--------------------------
+
+`smarty-template-header'
+ Menu: Smarty -> Templates -> Insert Header
+ Keybinding: `C-c C-t C-h'
+ Description: This function is used to insert a header in the
+ current buffer.
+
+`smarty-template-footer'
+ Menu: Smarty -> Templates -> Insert Footer
+ Keybinding: `C-c C-t C-f'
+ Description: This function is used to insert a footer in the
+ current buffer.
+
+`smarty-template-insert-date'
+ Menu: Smarty -> Templates -> Insert Date
+ Keybinding: `C-c C-t C-d i'
+ Description: This function is used to insert the date in the
+ current buffer.
+
+`smarty-template-modify'
+ Menu: Smarty -> Templates -> Modify Date
+ Keybinding: `C-c C-t C-d m'
+ Description: This function is used to modify the last
+ modification date in the current buffer.
+
+7 Bugs, Help
+************
+
+ * To report bugs: Bugtracker
+ (http://bugtracker.morinie.fr/lisp/set_project.php?project_id=2)
+
+ * To obtain help you can post on the dedicated forum: Forum
+ (http://forum.morinie.fr/lisp/)
+
+8 Key bindings
+**************
+
+\\{smarty-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'smarty-mode)
+ (setq mode-name "Smarty")
+
+ (smarty-create-syntax-table)
+
+ ;; set maps and tables
+ (use-local-map smarty-mode-map)
+ (set-syntax-table smarty-mode-syntax-table)
+ (setq local-abbrev-table smarty-mode-abbrev-table)
+
+ (set (make-local-variable 'comment-start) (concat smarty-left-delimiter "*"))
+ (set (make-local-variable 'comment-end) (concat "*" smarty-right-delimiter))
+ (set (make-local-variable 'comment-multi-line) t)
+ (set (make-local-variable 'smarty-end-comment-column) 80)
+
+ (make-local-variable 'font-lock-defaults)
+ (if smarty-highlight-plugin-functions
+ (setq smarty-font-lock-keywords smarty-font-lock-keywords-4)
+ (setq smarty-font-lock-keywords smarty-font-lock-keywords-3))
+ (setq font-lock-defaults
+ '((smarty-font-lock-keywords)
+ nil ; Keywords only (i.e. no comment or string highlighting
+ t ; case fold
+ nil ; syntax-alist
+ nil ; syntax-begin
+ ))
+
+ (setq font-lock-maximum-decoration t
+ case-fold-search t)
+
+ ;; add source file menu
+ (if smarty-source-file-menu (smarty-add-source-files-menu))
+ ;; add Smarty menu
+ (easy-menu-add smarty-mode-menu-list)
+ (easy-menu-define smarty-mode-menu smarty-mode-map
+ "Menu keymap for Smarty Mode." smarty-mode-menu-list)
+
+ ;; (message "Smarty Mode %s.%s" smarty-version
+ ;; (if noninteractive "" " See menu for documentation and release notes."))
+ (smarty-mode-line-update)
+ (run-hooks 'smarty-mode-hook))
+
+(defun smarty-doc-mode ()
+ "Display Smarty Mode documentation in *Help* buffer."
+ (interactive)
+ (with-output-to-temp-buffer
+ (if (fboundp 'help-buffer) (help-buffer) "*Help*")
+ (princ mode-name)
+ (princ " mode:\n")
+ (princ (documentation 'smarty-mode))
+ (with-current-buffer standard-output
+ (help-mode))
+ (print-help-return-message)))
+
+(defun smarty-activate-customizations ()
+ "Activate all customizations on local variables."
+ (interactive)
+ (smarty-mode-map-init)
+ (use-local-map smarty-mode-map)
+ (set-syntax-table smarty-mode-syntax-table)
+ (smarty-update-mode-menu)
+ (run-hooks 'menu-bar-update-hook)
+ (smarty-mode-line-update))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Templates
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun smarty-template-field (prompt &optional follow-string optional
+ begin end is-string string-char default)
+ "Prompt for string and insert it in buffer with optional FOLLOW-STRING.
+If OPTIONAL is nil, the prompt is left if an empty string is inserted. If
+an empty string is inserted, return nil and call `smarty-template-undo' for
+the region between BEGIN and END. IS-STRING indicates whether a string
+with double-quotes is to be inserted. DEFAULT specifies a default string."
+ (let ((position (point))
+ string)
+ (insert "<" prompt ">")
+ (if (not (> (length string-char) 0))
+ (setq string-char "\""))
+ (setq string
+ (condition-case ()
+ (read-from-minibuffer (concat prompt ": ")
+ (or (and is-string (cons (concat string-char string-char) 1)) default)
+ smarty-minibuffer-local-map)
+ (quit (if (and optional begin end)
+ (progn (beep) "")
+ (keyboard-quit)))))
+ (when (or (not (equal string "")) optional)
+ (delete-region position (point)))
+ (when (and (equal string "") optional begin end)
+ (smarty-template-undo begin end)
+ (message "Template aborted"))
+ (unless (equal string "")
+ (insert string))
+ (when (or (not (equal string "")) (not optional))
+ (insert (or follow-string "")))
+ (if (equal string "") nil string)))
+
+(defun smarty-template-undo (begin end)
+ "Undo aborted template by deleting region and unexpanding the keyword."
+ (cond (smarty-template-invoked-by-hook
+ (goto-char end)
+ (insert " ")
+ (delete-region begin end)
+ (unexpand-abbrev))
+ (t (delete-region begin end))))
+
+(defun smarty-template-generic-function (label close-label field mandatory-count &optional infinite special-field force-var)
+ "Generic function template 'label field1= field2=..."
+ (interactive)
+ (let ((start (point)) found here result-value elt continue field-count stop prompt)
+ (if smarty-template-invoked-by-hook
+ (setq found (smarty-after-ldelim))
+ (insert smarty-left-delimiter)
+ (setq found t))
+ (insert label)
+ (setq here (point-marker))
+ (insert " ")
+ (when found
+ (setq elt field)
+ (setq continue t)
+ (setq field-count 0)
+ (setq stop nil)
+ (while (and elt continue)
+ (setq prompt (car elt))
+ (when (not special-field)
+ (insert prompt "="))
+ (setq result-value (smarty-template-field prompt nil t))
+ (if (and (not result-value)
+ (< field-count mandatory-count))
+ (progn (setq continue nil)
+ (delete-region start (point))
+ (insert (concat label " "))
+ (setq stop t))
+ (if (not result-value)
+ (setq continue nil)
+ (setq here (point-marker))
+ (insert " ")))
+ (setq field-count (+ 1 field-count))
+ (setq elt (cdr elt)))
+ (when (and infinite (or continue force-var))
+ (when (not continue)
+ (delete-region here (point))
+ (insert " "))
+ (setq continue t)
+ (while continue
+ (setq result-value (smarty-template-field "var_name" "=" t here))
+ (if (not result-value)
+ (setq continue nil)
+ (setq continue (smarty-template-field "var_value" nil t here))
+ (setq here (point-marker))
+ (insert " "))))
+ (when (not stop)
+ (delete-region here (point))
+ (if (> 0 mandatory-count)
+ (delete-char -1))
+ (insert smarty-right-delimiter)
+ (setq here (point-marker))
+ (if close-label
+ (insert smarty-left-delimiter "/" label smarty-right-delimiter))
+ (goto-char here)))))
+
+(defun smarty-template-generic-modifier (label field mandatory-count)
+ "Generic modifier template '|label:field1:field2..."
+ (interactive)
+ (let ((start (point)) found here result-value elt continue field-count stop prompt)
+ (setq found (re-search-backward (concat (regexp-quote smarty-left-delimiter) "\\$\\(\\sw\\|\\s.\\)+" (regexp-quote "|")) nil t))
+ (if found
+ (progn
+ (setq found (re-search-forward (regexp-quote smarty-right-delimiter) start t))
+ (if (not found)
+ (progn
+ (goto-char start)
+ (insert label)
+ (setq here (point-marker))
+ (setq elt field)
+ (setq continue t)
+ (setq field-count 0)
+ (setq stop nil)
+ (while (and elt continue)
+ (setq prompt (car elt))
+ (insert ":")
+ (setq result-value (smarty-template-field prompt nil t))
+ (if (and (not result-value)
+ (< field-count mandatory-count))
+ (progn (setq continue nil)
+ (delete-region start (point))
+ (insert (concat label " "))
+ (setq stop t))
+ (if (not result-value)
+ (setq continue nil)
+ (setq here (point-marker))
+ (insert ":")))
+ (setq field-count (+ 1 field-count))
+ (setq elt (cdr elt)))
+ (when (not stop)
+ (delete-region here (point))
+ (if (not (or (looking-at smarty-right-delimiter)
+ (looking-at "|")))
+ (insert smarty-right-delimiter))))
+ (goto-char start)
+ (insert label " ")))
+ (goto-char start)
+ (insert label " "))))
+
+(defun smarty-template-capture-hook ()
+ (smarty-hooked-abbrev 'smarty-template-capture))
+(defun smarty-template-config-load-hook ()
+ (smarty-hooked-abbrev 'smarty-template-config-load))
+(defun smarty-template-else-hook ()
+ (smarty-hooked-abbrev 'smarty-template-else))
+(defun smarty-template-elseif-hook ()
+ (smarty-hooked-abbrev 'smarty-template-elseif))
+(defun smarty-template-foreach-hook ()
+ (smarty-hooked-abbrev 'smarty-template-foreach))
+(defun smarty-template-foreachelse-hook ()
+ (smarty-hooked-abbrev 'smarty-template-foreachelse))
+(defun smarty-template-if-hook ()
+ (smarty-hooked-abbrev 'smarty-template-if))
+(defun smarty-template-include-hook ()
+ (smarty-hooked-abbrev 'smarty-template-include))
+(defun smarty-template-include-php-hook ()
+ (smarty-hooked-abbrev 'smarty-template-include-php))
+(defun smarty-template-insert-hook ()
+ (smarty-hooked-abbrev 'smarty-template-insert))
+(defun smarty-template-ldelim-hook ()
+ (smarty-hooked-abbrev 'smarty-template-ldelim))
+(defun smarty-template-literal-hook ()
+ (smarty-hooked-abbrev 'smarty-template-literal))
+(defun smarty-template-php-hook ()
+ (smarty-hooked-abbrev 'smarty-template-php))
+(defun smarty-template-rdelim-hook ()
+ (smarty-hooked-abbrev 'smarty-template-rdelim))
+(defun smarty-template-section-hook ()
+ (smarty-hooked-abbrev 'smarty-template-section))
+(defun smarty-template-sectionelse-hook ()
+ (smarty-hooked-abbrev 'smarty-template-sectionelse))
+(defun smarty-template-strip-hook ()
+ (smarty-hooked-abbrev 'smarty-template-strip))
+
+(defun smarty-template-assign-hook ()
+ (smarty-hooked-abbrev 'smarty-template-assign))
+(defun smarty-template-counter-hook ()
+ (smarty-hooked-abbrev 'smarty-template-counter))
+(defun smarty-template-cycle-hook ()
+ (smarty-hooked-abbrev 'smarty-template-cycle))
+(defun smarty-template-debug-hook ()
+ (smarty-hooked-abbrev 'smarty-template-debug))
+(defun smarty-template-eval-hook ()
+ (smarty-hooked-abbrev 'smarty-template-eval))
+(defun smarty-template-fetch-hook ()
+ (smarty-hooked-abbrev 'smarty-template-fetch))
+(defun smarty-template-html-checkboxes-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-checkboxes))
+(defun smarty-template-html-image-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-image))
+(defun smarty-template-html-options-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-options))
+(defun smarty-template-html-radios-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-radios))
+(defun smarty-template-html-select-date-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-select-date))
+(defun smarty-template-html-select-time-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-select-time))
+(defun smarty-template-html-table-hook ()
+ (smarty-hooked-abbrev 'smarty-template-html-table))
+(defun smarty-template-mailto-hook ()
+ (smarty-hooked-abbrev 'smarty-template-mailto))
+(defun smarty-template-math-hook ()
+ (smarty-hooked-abbrev 'smarty-template-math))
+(defun smarty-template-popup-hook ()
+ (smarty-hooked-abbrev 'smarty-template-popup))
+(defun smarty-template-popup-init-hook ()
+ (smarty-hooked-abbrev 'smarty-template-popup-init))
+(defun smarty-template-textformat-hook ()
+ (smarty-hooked-abbrev 'smarty-template-textformat))
+
+(defun smarty-template-capitalize-hook ()
+ (smarty-hooked-abbrev 'smarty-template-capitalize))
+(defun smarty-template-cat-hook ()
+ (smarty-hooked-abbrev 'smarty-template-cat))
+(defun smarty-template-count-characters-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-characters))
+(defun smarty-template-count-paragraphs-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-paragraphs))
+(defun smarty-template-count-sentences-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-sentences))
+(defun smarty-template-count-words-hook ()
+ (smarty-hooked-abbrev 'smarty-template-count-words))
+(defun smarty-template-date-format-hook ()
+ (smarty-hooked-abbrev 'smarty-template-date-format))
+(defun smarty-template-default-hook ()
+ (smarty-hooked-abbrev 'smarty-template-default))
+(defun smarty-template-escape-hook ()
+ (smarty-hooked-abbrev 'smarty-template-escape))
+(defun smarty-template-indent-hook ()
+ (smarty-hooked-abbrev 'smarty-template-indent))
+(defun smarty-template-lower-hook ()
+ (smarty-hooked-abbrev 'smarty-template-lower))
+(defun smarty-template-nl2br-hook ()
+ (smarty-hooked-abbrev 'smarty-template-nl2br))
+(defun smarty-template-regex-replace-hook ()
+ (smarty-hooked-abbrev 'smarty-template-regex-replace))
+(defun smarty-template-replace-hook ()
+ (smarty-hooked-abbrev 'smarty-template-replace))
+(defun smarty-template-spacify-hook ()
+ (smarty-hooked-abbrev 'smarty-template-spacify))
+(defun smarty-template-string-format-hook ()
+ (smarty-hooked-abbrev 'smarty-template-string-format))
+(defun smarty-template-vstrip-hook ()
+ (smarty-hooked-abbrev 'smarty-template-vstrip))
+(defun smarty-template-strip-tags-hook ()
+ (smarty-hooked-abbrev 'smarty-template-strip-tags))
+(defun smarty-template-truncate-hook ()
+ (smarty-hooked-abbrev 'smarty-template-truncate))
+(defun smarty-template-upper-hook ()
+ (smarty-hooked-abbrev 'smarty-template-upper))
+(defun smarty-template-wordwrap-hook ()
+ (smarty-hooked-abbrev 'smarty-template-wordwrap))
+
+(defun smarty-template-validate-hook ()
+ (smarty-hooked-abbrev 'smarty-template-validate))
+(defun smarty-template-clipcache-hook ()
+ (smarty-hooked-abbrev 'smarty-template-clipcache))
+(defun smarty-template-include-clipcache-hook ()
+ (smarty-hooked-abbrev 'smarty-template-include-clipcache))
+(defun smarty-template-formtool-checkall-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-checkall))
+(defun smarty-template-formtool-copy-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-copy))
+(defun smarty-template-formtool-count-chars-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-count-chars))
+(defun smarty-template-formtool-init-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-init))
+(defun smarty-template-formtool-move-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-move))
+(defun smarty-template-formtool-moveall-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-moveall))
+(defun smarty-template-formtool-movedown-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-movedown))
+(defun smarty-template-formtool-moveup-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-moveup))
+(defun smarty-template-formtool-remove-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-remove))
+(defun smarty-template-formtool-rename-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-rename))
+(defun smarty-template-formtool-save-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-save))
+(defun smarty-template-formtool-selectall-hook ()
+ (smarty-hooked-abbrev 'smarty-template-formtool-selectall))
+(defun smarty-template-paginate-first-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-first))
+(defun smarty-template-paginate-last-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-last))
+(defun smarty-template-paginate-middle-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-middle))
+(defun smarty-template-paginate-next-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-next))
+(defun smarty-template-paginate-prev-hook ()
+ (smarty-hooked-abbrev 'smarty-template-paginate-prev))
+
+(defun smarty-template-btosmilies-hook ()
+ (smarty-hooked-abbrev 'smarty-template-btosmilies))
+(defun smarty-template-bbcodetohtml-hook ()
+ (smarty-hooked-abbrev 'smarty-template-bbcodetohtml))
+(defun smarty-template-date-formatto-hook ()
+ (smarty-hooked-abbrev 'smarty-template-date-formatto))
+
+(defun smarty-template-capture ()
+ "Insert a capture statement."
+ (interactive)
+ (smarty-template-generic-function "capture" t '("name" "assign") 0))
+
+(defun smarty-template-config-load ()
+ "Insert a config_load statement."
+ (interactive)
+ (smarty-template-generic-function "config_load" nil '("file" "section" "scope" "global") 1))
+
+(defun smarty-template-else ()
+ "Insert a else statement."
+ (interactive)
+ (smarty-template-generic-function "else" nil '() 0))
+
+(defun smarty-template-elseif ()
+ "Insert a elseif statement."
+ (interactive)
+ (smarty-template-generic-function "elseif" nil '("condition") 1 nil t))
+
+(defun smarty-template-foreach ()
+ "Insert a foreach statement."
+ (interactive)
+ (smarty-template-generic-function "foreach" t '("from" "item" "key" "name") 2))
+
+(defun smarty-template-foreachelse ()
+ "Insert a foreachelse statement."
+ (interactive)
+ (smarty-template-generic-function "foreachelse" nil '() 0))
+
+(defun smarty-template-if ()
+ "Insert a if statement."
+ (interactive)
+ (smarty-template-generic-function "if" t '("condition") 1 nil t))
+
+(defun smarty-template-include ()
+ "Insert a include statement."
+ (interactive)
+ (smarty-template-generic-function "include" nil '("file" "assign") 1 t))
+
+(defun smarty-template-include-php ()
+ "Insert a include_php statement."
+ (interactive)
+ (smarty-template-generic-function "include_php" nil '("file" "once" "assign") 1))
+
+(defun smarty-template-insert ()
+ "Insert a insert statement."
+ (interactive)
+ (smarty-template-generic-function "insert" nil '("name" "assign" "script") 1 t))
+
+(defun smarty-template-ldelim ()
+ "Insert a ldelim statement."
+ (interactive)
+ (smarty-template-generic-function "ldelim" nil '() 0))
+
+(defun smarty-template-literal ()
+ "Insert a literal statement."
+ (interactive)
+ (smarty-template-generic-function "literal" t '() 0))
+
+(defun smarty-template-php ()
+ "Insert a php statement."
+ (interactive)
+ (smarty-template-generic-function "php" t '() 0))
+
+(defun smarty-template-rdelim ()
+ "Insert a rdelim statement."
+ (interactive)
+ (smarty-template-generic-function "rdelim" nil '() 0))
+
+(defun smarty-template-section ()
+ "Insert a section statement."
+ (interactive)
+ (smarty-template-generic-function "section" t '("name" "loop" "start" "step" "max" "show") 2))
+
+(defun smarty-template-sectionelse ()
+ "Insert a sectionelse statement."
+ (interactive)
+ (smarty-template-generic-function "sectionelse" nil '() 0))
+
+(defun smarty-template-strip ()
+ "Insert a strip statement."
+ (interactive)
+ (smarty-template-generic-function "strip" t '() 0))
+
+
+(defun smarty-template-assign ()
+ "Insert a assign statement."
+ (interactive)
+ (smarty-template-generic-function "assign" nil '("var" "value") 2))
+
+(defun smarty-template-counter ()
+ "Insert a counter statement."
+ (interactive)
+ (smarty-template-generic-function "counter" nil '("name" "start" "skip" "direction" "print" "assign") 0))
+
+(defun smarty-template-cycle ()
+ "Insert a cycle statement."
+ (interactive)
+ (smarty-template-generic-function "cycle" nil '("values" "name" "print" "advance" "delimiter" "assign" "reset") 1))
+
+(defun smarty-template-debug ()
+ "Insert a debug statement."
+ (interactive)
+ (smarty-template-generic-function "debug" nil '("output") 0))
+
+(defun smarty-template-eval ()
+ "Insert a eval statement."
+ (interactive)
+ (smarty-template-generic-function "eval" nil '("var" "assign") 1))
+
+(defun smarty-template-fetch ()
+ "Insert a fetch statement."
+ (interactive)
+ (smarty-template-generic-function "fetch" nil '("file" "assign") 1))
+
+(defun smarty-template-html-checkboxes ()
+ "Insert a html_checkboxes statement."
+ (interactive)
+ (smarty-template-generic-function "html_checkboxes" nil '("name" "values" "output" "selected" "options" "separator" "assign" "labels") 0))
+
+(defun smarty-template-html-image ()
+ "Insert a html_image statement."
+ (interactive)
+ (smarty-template-generic-function "html_image" nil '("file" "height" "width" "basedir" "alt" "href" "path_prefix") 1))
+
+(defun smarty-template-html-options ()
+ "Insert a html_options statement."
+ (interactive)
+ (smarty-template-generic-function "html_options" nil '("name" "values" "output" "selected" "options") 0))
+
+(defun smarty-template-html-radios ()
+ "Insert a html_radios statement."
+ (interactive)
+ (smarty-template-generic-function "html_radios" nil '("name" "values" "output" "selected" "options" "separator" "assign") 0))
+
+(defun smarty-template-html-select-date ()
+ "Insert a html_select_date statement."
+ (interactive)
+ (smarty-template-generic-function "html_select_date" nil '("prefix" "time" "start_year" "end_year" "display_days" "display_months" "display_years" "month_format" "day_format" "day_value_format" "year_as_text" "reverse_years" "field_array" "day_size" "month_size" "year_size" "all_extra" "day_extra" "month_extra" "year_extra" "field_order" "field_separator" "month_value_format" "year_empty" "month_empty" "day_empty") 0))
+
+(defun smarty-template-html-select-time ()
+ "Insert a html_select_time statement."
+ (interactive)
+ (smarty-template-generic-function "html_select_time" nil '("prefix" "time" "display_hours" "display_minutes" "display_seconds" "display_meridian" "use_24_hours" "minute_interval" "second_interval" "field_array" "all_extra" "hour_extra" "minute_extra" "second_extra" "meridian_extra") 0))
+
+(defun smarty-template-html-table ()
+ "Insert a html_table statement."
+ (interactive)
+ (smarty-template-generic-function "html_table" nil '("loop" "cols" "rows" "inner" "caption" "table_attr" "th_attr" "tr_attr" "td_attr" "trailpad" "hdir" "vdir") 1))
+
+(defun smarty-template-mailto ()
+ "Insert a mailto statement."
+ (interactive)
+ (smarty-template-generic-function "mailto" nil '("address" "text" "encode" "cc" "bcc" "subject" "newsgroups" "followupto" "extra") 1))
+
+(defun smarty-template-math ()
+ "Insert a math statement."
+ (interactive)
+ (smarty-template-generic-function "math" nil '("equation" "format" "assign") 1 t nil t))
+
+(defun smarty-template-popup ()
+ "Insert a popup statement."
+ (interactive)
+ (smarty-template-generic-function "popup" nil '("text" "trigger" "sticky" "caption" "fgcolor" "bgcolor" "textcolor" "capcolor" "closecolor" "textfont" "captionfont" "closefont" "textsize" "captionsize" "closesize" "width" "height" "left" "right" "center" "above" "below" "border" "offsetx" "offsety" "fgbackground" "bgbackground" "closetext" "noclose" "status" "autostatus" "autostatuscap" "inarray" "caparray" "capicon" "snapx" "snapy" "fixx" "fixy" "background" "padx" "pady" "fullhtml" "frame" "function" "delay" "hauto" "vauto") 1))
+
+(defun smarty-template-popup-init ()
+ "Insert a popup_init statement."
+ (interactive)
+ (smarty-template-generic-function "popup_init" nil '("src") 1))
+
+(defun smarty-template-textformat ()
+ "Insert a textformat statement."
+ (interactive)
+ (smarty-template-generic-function "textformat" t '("style" "indent" "indent_first" "indent_char" "wrap" "wrap_char" "wrap_cut" "assign") 0))
+
+(defun smarty-template-capitalize ()
+ "Insert a capitalize statement."
+ (interactive)
+ (smarty-template-generic-modifier "capitalize" '("upcase_numeric") 0))
+
+(defun smarty-template-cat ()
+ "Insert a cat statement."
+ (interactive)
+ (smarty-template-generic-modifier "cat" '("value") 0))
+
+(defun smarty-template-count-characters ()
+ "Insert a count_characters statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_characters" '("include_whitespace") 0))
+
+(defun smarty-template-count-paragraphs ()
+ "Insert a count_paragraphs statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_paragraphs" '() 0))
+
+(defun smarty-template-count-sentences ()
+ "Insert a count_sentences statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_sentences" '() 0))
+
+(defun smarty-template-count-words ()
+ "Insert a count_words statement."
+ (interactive)
+ (smarty-template-generic-modifier "count_words" '() 0))
+
+(defun smarty-template-date-format ()
+ "Insert a date_format statement."
+ (interactive)
+ (smarty-template-generic-modifier "date_format" '("format" "default") 0))
+
+(defun smarty-template-default ()
+ "Insert a default statement."
+ (interactive)
+ (smarty-template-generic-modifier "default" '("value") 0))
+
+(defun smarty-template-escape ()
+ "Insert a escape statement."
+ (interactive)
+ (smarty-template-generic-modifier "escape" '("html|htmlall|url|urlpathinfo|quotes|hex|hexentity|javascript|mail" "charset") 0))
+
+(defun smarty-template-indent ()
+ "Insert a indent statement."
+ (interactive)
+ (smarty-template-generic-modifier "indent" '("value" "character") 0))
+
+(defun smarty-template-lower ()
+ "Insert a lower statement."
+ (interactive)
+ (smarty-template-generic-modifier "lower" '() 0))
+
+(defun smarty-template-nl2br ()
+ "Insert a nl2br statement."
+ (interactive)
+ (smarty-template-generic-modifier "nl2br" '() 0))
+
+(defun smarty-template-regex-replace ()
+ "Insert a regex_replace statement."
+ (interactive)
+ (smarty-template-generic-modifier "regex_replace" '("regexp" "string_to_replace") 2))
+
+(defun smarty-template-replace ()
+ "Insert a replace statement."
+ (interactive)
+ (smarty-template-generic-modifier "replace" '("string" "string_to_replace_with") 2))
+
+(defun smarty-template-spacify ()
+ "Insert a spacify statement."
+ (interactive)
+ (smarty-template-generic-modifier "spacify" '("character") 0))
+
+(defun smarty-template-string-format ()
+ "Insert a string_format statement."
+ (interactive)
+ (smarty-template-generic-modifier "string_format" '("format") 1))
+
+(defun smarty-template-vstrip ()
+ "Insert a strip statement."
+ (interactive)
+ (smarty-template-generic-modifier "strip" '() 0))
+
+(defun smarty-template-strip-tags ()
+ "Insert a strip_tags statement."
+ (interactive)
+ (smarty-template-generic-modifier "strip_tags" '("replace_by_space") 0))
+
+(defun smarty-template-truncate ()
+ "Insert a truncate statement."
+ (interactive)
+ (smarty-template-generic-modifier "truncate" '("count" "text_to_replace" "character_boundary" "middle_string") 0))
+
+(defun smarty-template-upper ()
+ "Insert a upper statement."
+ (interactive)
+ (smarty-template-generic-modifier "upper" '() 0))
+
+(defun smarty-template-wordwrap ()
+ "Insert a wordwrap statement."
+ (interactive)
+ (smarty-template-generic-modifier "wordwrap" '("count" "string" "character_boundary") 0))
+
+
+(defun smarty-template-validate ()
+ "Insert a validate statement."
+ (interactive)
+ (smarty-template-generic-function "validate" nil '("field" "criteria" "message" "form" "transform" "trim" "empty" "halt" "assign" "append" "page") 3))
+
+(defun smarty-template-repeat ()
+ "Insert a repeat statement."
+ (interactive)
+ (smarty-template-generic-function "repeat" nil '("count" "assign") 1))
+
+(defun smarty-template-str_repeat ()
+ "Insert a str_repeat statement."
+ (interactive)
+ (smarty-template-generic-function "str_repeat" nil '("string" "count" "assign") 2))
+
+(defun smarty-template-clipcache ()
+ "Insert a clipcache statement."
+ (interactive)
+ (smarty-template-generic-function "clipcache" nil '("id" "group" "ttl" "ldelim" "rdelim") 3))
+
+(defun smarty-template-include-clipcache ()
+ "Insert a include_clipcache statement."
+ (interactive)
+ (smarty-template-generic-function "include_clipcache" nil '("file" "cache_id" "cache_lifetime" "ldelim" "rdelim") 3))
+
+(defun smarty-template-formtool-checkall ()
+ "Insert a formtool_checkall statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_checkall" nil '("name" "class" "style") 1))
+
+(defun smarty-template-formtool-copy ()
+ "Insert a formtool_copy statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_copy" nil '("from" "to" "save" "button_text" "all" "counter" "class" "style") 3))
+
+(defun smarty-template-formtool-count-chars ()
+ "Insert a formtool_count_chars statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_count_chars" nil '("name" "limit" "alert") 3))
+
+(defun smarty-template-formtool-init ()
+ "Insert a formtool_init statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_init" nil '("src") 1))
+
+(defun smarty-template-formtool-move ()
+ "Insert a formtool_move statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_move" nil '("from" "to" "save_from" "save_to" "all" "count_to" "count_from" "class" "style") 4))
+
+(defun smarty-template-formtool-moveall ()
+ "Insert a formtool_moveall statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_moveall" nil '("from" "to" "save_from" "save_to" "all" "count_to" "count_from" "class" "style") 4))
+
+(defun smarty-template-formtool-movedown ()
+ "Insert a formtool_movedown statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_movedown" nil '("save" "name" "class" "style") 2))
+
+(defun smarty-template-formtool-moveup ()
+ "Insert a formtool_moveup statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_moveup" nil '("save" "name" "class" "style") 2))
+
+(defun smarty-template-formtool-remove ()
+ "Insert a formtool_remove statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_remove" nil '("from" "save" "all" "counter" "class" "style") 2))
+
+(defun smarty-template-formtool-rename ()
+ "Insert a formtool_rename statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_rename" nil '("name" "from" "save" "class" "style") 3))
+
+(defun smarty-template-formtool-save ()
+ "Insert a formtool_save statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_save" nil '("from" "name" "save") 3))
+
+(defun smarty-template-formtool-selectall ()
+ "Insert a formtool_selectall statement."
+ (interactive)
+ (smarty-template-generic-function "formtool_selectall" nil '("name" "class" "style") 1))
+
+(defun smarty-template-paginate-first ()
+ "Insert a paginate_first statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_first" nil '("id" "text") 0))
+
+(defun smarty-template-paginate-last ()
+ "Insert a paginate_last statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_last" nil '("id" "text") 0))
+
+(defun smarty-template-paginate-middle ()
+ "Insert a paginate_middle statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_middle" nil '("id" "format" "prefix" "page_limit" "link_prefix" "link_suffix") 0))
+
+(defun smarty-template-paginate-next ()
+ "Insert a paginate_next statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_next" nil '("id" "text") 0))
+
+(defun smarty-template-paginate-prev ()
+ "Insert a paginate_prev statement."
+ (interactive)
+ (smarty-template-generic-function "paginate_prev" nil '("id" "text") 0))
+
+
+(defun smarty-template-btosmilies ()
+ "Insert a B2Smilies statement."
+ (interactive)
+ (smarty-template-generic-modifier "B2Smilies" '() 0))
+
+(defun smarty-template-bbcodetohtml ()
+ "Insert a bbcode2html statement."
+ (interactive)
+ (smarty-template-generic-modifier "bbcode2html" '() 0))
+
+(defun smarty-template-date-formatto ()
+ "Insert a date_format2 statement."
+ (interactive)
+ (smarty-template-generic-modifier "date_format2" '("format" "default") 0))
+
+;;
+
+(defun smarty-resolve-env-variable (string)
+ "Resolve environment variables in STRING."
+ (while (string-match "\\(.*\\)${?\\(\\(\\w\\|_\\)+\\)}?\\(.*\\)" string)
+ (setq string (concat (match-string 1 string)
+ (getenv (match-string 2 string))
+ (match-string 4 string))))
+ string)
+
+(defun smarty-insert-string-or-file (string)
+ "Insert STRING or file contents if STRING is an existing file name."
+ (unless (equal string "")
+ (let ((file-name
+ (progn (string-match "^\\([^\n]+\\)" string)
+ (smarty-resolve-env-variable (match-string 1 string)))))
+ (if (file-exists-p file-name)
+ (forward-char (cadr (insert-file-contents file-name)))
+ (insert string)))))
+
+(defun smarty-template-insert-date ()
+ "Insert date in appropriate format."
+ (interactive)
+ (insert
+ (cond
+ ;; 'american, 'european, 'scientific kept for backward compatibility
+ ((eq smarty-date-format 'american) (format-time-string "%m/%d/%Y" nil))
+ ((eq smarty-date-format 'european) (format-time-string "%d.%m.%Y" nil))
+ ((eq smarty-date-format 'scientific) (format-time-string "%Y/%m/%d" nil))
+ (t (format-time-string smarty-date-format nil)))))
+
+(defun smarty-template-header (&optional file-title)
+ "Insert a Smarty file header."
+ (interactive)
+ (unless (equal smarty-file-header "")
+ (let (pos)
+ (save-excursion
+ (smarty-insert-string-or-file smarty-file-header)
+ (setq pos (point-marker)))
+ (smarty-template-replace-header-keywords
+ (point-min-marker) pos file-title))))
+
+(defun smarty-template-footer ()
+ "Insert a Smarty file footer."
+ (interactive)
+ (unless (equal smarty-file-footer "")
+ (let (pos)
+ (save-excursion
+ (setq pos (point-marker))
+ (smarty-insert-string-or-file smarty-file-footer)
+ (unless (= (preceding-char) ?\n)
+ (insert "\n")))
+ (smarty-template-replace-header-keywords pos (point-max-marker)))))
+
+(defun smarty-template-replace-header-keywords (beg end &optional file-title is-model)
+ "Replace keywords in header and footer."
+ (let ()
+ (smarty-prepare-search-2
+ (save-excursion
+ (goto-char beg)
+ (while (search-forward "<filename>" end t)
+ (replace-match (buffer-name) t t))
+ (goto-char beg)
+ (while (search-forward "<copyright>" end t)
+ (replace-match smarty-copyright-string t t))
+ (goto-char beg)
+ (while (search-forward "<author>" end t)
+ (replace-match "" t t)
+ (insert (user-full-name))
+ (when user-mail-address (insert " <" user-mail-address ">")))
+ (goto-char beg)
+ (while (search-forward "<login>" end t)
+ (replace-match (user-login-name) t t))
+ (goto-char beg)
+ (while (search-forward "<company>" end t)
+ (replace-match smarty-company-name t t))
+ (goto-char beg)
+ ;; Replace <RCS> with $, so that RCS for the source is
+ ;; not over-enthusiastic with replacements
+ (while (search-forward "<RCS>" end t)
+ (replace-match "$" nil t))
+ (goto-char beg)
+ (while (search-forward "<date>" end t)
+ (replace-match "" t t)
+ (smarty-template-insert-date))
+ (goto-char beg)
+ (while (search-forward "<year>" end t)
+ (replace-match (format-time-string "%Y" nil) t t))
+ (goto-char beg)
+ (let (string)
+ (while
+ (re-search-forward "<\\(\\(\\w\\|\\s_\\)*\\) string>" end t)
+ (setq string (read-string (concat (match-string 1) ": ")))
+ (replace-match string t t)))
+ (goto-char beg)
+ (when (and (not is-model) (search-forward "<cursor>" end t))
+ (replace-match "" t t))))))
+
+(provide 'smarty-mode)
+;;; smarty-mode.el ends here
diff --git a/emacs.d/nxhtml/related/tt-mode.el b/emacs.d/nxhtml/related/tt-mode.el
new file mode 100644
index 0000000..cf01a47
--- /dev/null
+++ b/emacs.d/nxhtml/related/tt-mode.el
@@ -0,0 +1,124 @@
+;; tt-mode.el --- Emacs major mode for editing Template Toolkit files
+;;
+;; Copyright (c) 2002 Dave Cross, all rights reserved.
+;;
+;; This file may be distributed under the same terms as GNU Emacs.
+;;
+;; $Id: tt-mode.el 13 2008-01-27 09:35:16Z dave $
+;;
+;; This file adds simple font highlighting of TT directives when you are
+;; editing Template Toolkit files.
+;;
+;; I usually give these files an extension of .tt and in order to automatically
+;; invoke this mode for these files, I have the following in my .emacs file.
+;;
+;; (setq load-path
+;; (cons "/home/dave/xemacs" load-path))
+;; (autoload 'tt-mode "tt-mode")
+;; (setq auto-mode-alist
+;; (append '(("\\.tt$" . tt-mode)) auto-mode-alist ))
+;;
+;; Something similar may well work for you.
+;;
+;; Author: Dave Cross <dave@dave.org.uk>
+;;
+;; Modified by Lennart Borgman 2008-08-06
+
+(require 'font-lock)
+
+(defvar tt-mode-hook nil
+ "List of functions to call when entering TT mode")
+
+(defvar tt-keywords
+ (concat "\\b\\(?:"
+ (regexp-opt (list "GET" "CALL" "SET" "DEFAULT" "INSERT" "INCLUDE"
+ "BLOCK" "END" "PROCESS" "WRAPPER" "IF" "UNLESS"
+ "ELSIF" "ELSE" "SWITCH" "CASE" "FOR" "FOREACH"
+ "WHILE" "FILTER" "USE" "MACRO" "PERL" "RAWPERL"
+ "TRY" "THROW" "CATCH" "FINAL" "LAST" "RETURN"
+ "STOP" "CLEAR" "META" "TAGS"))
+ "\\)\\b"))
+
+(defvar tt-font-lock-keywords
+ (list
+ ;; Fontify [& ... &] expressions
+ '("\\(\\[%[-+]?\\)\\(\\(.\\|\n\\)+?\\)\\([-+]?%\\]\\)"
+ (1 font-lock-string-face t)
+ (2 font-lock-variable-name-face t)
+ (4 font-lock-string-face t))
+ ;; Look for keywords within those expressions
+ ;;
+ ;; Comment out whole directive tag
+ '("\\[%\\(#.*?\\)%\\]"
+ (1 font-lock-comment-face t))
+ ;; Comments to end of line
+;;; '("\\[%\\(?:.\\|\n\\)*\\(#.*\\)"
+;;; (1 font-lock-comment-face t))
+ '("\\[% *\\([a-z_0-9]*\\) *%\\]"
+ (1 font-lock-constant-face t))
+ (list (concat
+ "\\(\\[%[-+]?\\|;\\)[ \n\t]*\\("
+ tt-keywords
+ "\\)")
+ 2 font-lock-keyword-face t)
+ )
+ "Expressions to font-lock in tt-mode.")
+
+;; (defvar tt-font-lock-keywords
+;; ;; Since this is used in a multi major mode we
+;; (list
+;; ;; Fontify [& ... &] expressions
+;; ;;; '("^\\([-+]?\\)\\(\\(.\\|\n\\)+?\\)\\([-+]?\\)$"
+;; ;;; (1 font-lock-string-face t)
+;; ;;; (2 font-lock-variable-name-face t)
+;; ;;; (4 font-lock-string-face t))
+;; '("\\(#.*\\)$"
+;; (1 font-lock-comment-face t))
+;; '("^ *\\([a-z_0-9]*\\) *$"
+;; (1 font-lock-constant-face t))
+;; (list (concat
+;; "^\\(?:[-+]?\\|;\\)[ \n\t]*\\("
+;; tt-keywords
+;; "\\)")
+;; )
+;; 1 font-lock-keyword-face t)
+;; )
+;; "Expressions to font-lock in tt-mode.")
+
+(defvar tt-font-lock-defaults
+ '(tt-font-lock-keywords nil t))
+
+(defun tt-mode-after-change (beg end pre-len)
+ ;; add/remove font-lock-multiline
+ ;; Fix-me: add variable for search lengths
+ (let* ((here (point))
+ (beg-is-ml (get-text-property beg 'font-lock-multiline))
+ tt-beg
+ tt-end
+ )
+ (when beg-is-ml
+ (let ((beg-ok (not (previous-single-property-change
+ here 'font-lock-multiline
+ nil (- here 1))))
+ )
+ (when beg-ok
+ (goto-char beg)
+ (search-forward "%]" end t)
+ )
+ (search-forward "[%" end t)
+ ))
+ (when tt-end
+ (remove-list-of-text-properties here tt-beg '(font-lock-multiline))
+ (set-text-properties tt-beg tt-end '(font-lock-multiline t))))
+ )
+
+
+;;;###autoload
+(define-derived-mode tt-mode fundamental-mode "TT"
+ "Major mode for editing Template Toolkit files."
+ (set (make-local-variable 'font-lock-defaults) tt-font-lock-defaults)
+ (add-hook 'after-change-functions 'tt-mode-after-change nil t)
+ )
+
+(provide 'tt-mode)
+;; tt-mode.el ends here
diff --git a/emacs.d/nxhtml/related/visual-basic-mode.el b/emacs.d/nxhtml/related/visual-basic-mode.el
new file mode 100644
index 0000000..ca448a6
--- /dev/null
+++ b/emacs.d/nxhtml/related/visual-basic-mode.el
@@ -0,0 +1,1263 @@
+;;; visual-basic-mode.el
+;; This is free software.
+
+;; A mode for editing Visual Basic programs.
+;; Modified version of Fred White's visual-basic-mode.el
+
+;; Copyright (C) 1996 Fred White <fwhite@alum.mit.edu>
+;; Copyright (C) 1998 Free Software Foundation, Inc.
+;; (additions by Dave Love)
+;; Copyright (C) 2008-2009 Free Software Foundation, Inc.
+;; (additions by Randolph Fritz and Vincent Belaiche (VB1) )
+
+;; Author: Fred White <fwhite@alum.mit.edu>
+;; Adapted-by: Dave Love <d.love@dl.ac.uk>
+;; : Kevin Whitefoot <kevin.whitefoot@nopow.abb.no>
+;; : Randolph Fritz <rfritz@u.washington.edu>
+;; : Vincent Belaiche (VB1) <vincentb1@users.sourceforge.net>
+;; Version: 1.4.8 (2009-09-29)
+;; Serial Version: %Id: 17%
+;; Keywords: languages, basic, Evil
+
+
+;; (Old) LCD Archive Entry:
+;; basic-mode|Fred White|fwhite@alum.mit.edu|
+;; A mode for editing Visual Basic programs.|
+;; 18-Apr-96|1.0|~/modes/basic-mode.el.Z|
+
+;; This file is NOT part of GNU Emacs but the same permissions apply.
+;;
+;; GNU Emacs 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 2, or (at your
+;; option) any later version.
+;;
+;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; 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 2 of the
+;; License, or (at your option) any later version.
+
+;;; Commentary:
+
+;; Purpose of this package:
+;; This is a mode for editing programs written in The World's Most
+;; Successful Programming Language. It features automatic
+;; indentation, font locking, keyword capitalization, and some minor
+;; convenience functions.
+
+;; Installation instructions
+;; Put visual-basic-mode.el somewhere in your path, compile it, and add
+;; the following to your init file:
+
+;; (autoload 'visual-basic-mode "visual-basic-mode" "Visual Basic mode." t)
+;; (setq auto-mode-alist (append '(("\\.\\(frm\\|bas\\|cls\\)$" .
+;; visual-basic-mode)) auto-mode-alist))
+;;
+;; If you are doing Rhino scripts, add:
+;; (setq auto-mode-alist (append '(("\\.\\(frm\\|bas\\|cls\\|rvb\\)$" .
+;; visual-basic-mode)) auto-mode-alist))
+
+;; If you had visual-basic-mode already installed, you may need to call
+;; visual-basic-upgrade-keyword-abbrev-table the first time that
+;; visual-basic-mode is loaded.
+
+;; Of course, under Windows 3.1, you'll have to name this file
+;; something shorter than visual-basic-mode.el
+
+;; Revisions:
+;; 1.0 18-Apr-96 Initial version
+;; 1.1 Accomodate emacs 19.29+ font-lock-defaults
+;; Simon Marshall <Simon.Marshall@esrin.esa.it>
+; 1.2 Rename to visual-basic-mode
+;; 1.3 Fix some indentation bugs.
+;; 1.3+ Changes by Dave Love: [No attempt at compatibility with
+;; anything other than Emacs 20, sorry, but little attempt to
+;; sanitize for Emacs 20 specifically.]
+;; Change `_' syntax only for font-lock and imenu, not generally;
+;; provide levels of font-locking in the current fashion;
+;; font-lock case-insensitively; use regexp-opt with the font-lok
+;; keywords; imenu support; `visual-basic-split-line', bound to
+;; C-M-j; account for single-statement `if' in indentation; add
+;; keyword "Global"; use local-write-file-hooks, not
+;; write-file-hooks.
+;; 1.4 September 1998
+;; 1.4 KJW Add begin..end, add extra keywords
+;; Add customisation for single line if. Disallow by default.
+;; Fix if regexp to require whitespace after if and require then.
+;; Add more VB keywords. Make begin..end work as if..endif so
+;; that forms are formatted correctly.
+;; 1.4.1 KJW Merged Dave Love and KJW versions.
+;; Added keywords suggested by Mickey Ferguson
+;; <MFerguson@peinc.com>
+;; Fixed imenu variable to find private variables and enums
+
+;; Changed syntax class of =, <, > to punctuation to allow dynamic
+;; abbreviations to pick up only the word at point rather than the
+;; whole expression.
+
+;; Fixed bug introduced by KJW adding suport for begin...end in
+;; forms whereby a single end outdented.
+
+;; Partially fixed failure to recognise if statements with
+;; continuations (still fails on 'single line' if with
+;; continuation, ugh).
+;; 1.4.2 RF added "class" and "null" keywords, "Rhino" script note.
+;; 1.4.3 VB1 added
+;; 1) function visual-basic-if-not-on-single-line to recognize single line
+;; if statements, even when line is broken. variable
+;; visual-basic-allow-single-line-if default set to t again.
+;; 2) use of 'words in calling regexp-opt rather than concat \\< ...\\>
+;; 3) new keywords Preserve and Explicit
+;; 1.4.4 VB1 added function visual-basic-close-block
+;; 1.4.5 VB1, (expand-abbrev) within (save-excusion...)
+;; 1.4.6 VB1 correct visual-basic-close-block (single line If case)
+;; 1.4.7 VB1 correct visual-basic-close-block (For/Next)
+;; 1.4.8 VB1 correct visual-basic-close-block (Property, + add With /End With)
+;; add command visual-basic-insert-item
+
+;; Lennart Borgman:
+;; 2009-11-20
+;; - Added eval-and-compile to visual-basic-label-regexp.
+;;
+;; Notes:
+;; Dave Love
+;; BTW, here's a script for making tags tables that I (Dave Love) have
+;; used with reasonable success. It assumes a hacked version of etags
+;; with support for case-folded regexps. I think this is now in the
+;; development version at <URL:ftp://fly.cnuce.cnr.it/pub/> and should
+;; make it into Emacs after 20.4.
+
+;; #! /bin/sh
+
+;; # etags-vb: (so-called) Visual (so-called) Basic TAGS generation.
+;; # Dave Love <d.love@dl.ac.uk>. Public domain.
+;; # 1997-11-21
+
+;; if [ $# -lt 1 ]; then
+;; echo "Usage: `basename $0` [etags options] VBfile ... [etags options] " 1>&2
+;; exit 1
+;; fi
+
+;; if [ $1 = "--help" ] || [ $1 = "-h" ]; then
+;; echo "Usage: `basename $0` [etags options] VBfile ... [etags options]
+
+;; "
+;; etags --help
+;; fi
+
+;; exec etags --lang=none -c '/\(global\|public\)[ \t]+\(\(const\|type\)[ \t]+\)*\([a-z_0-9]+\)/\4/' \
+;; -c '/public[ \t]+\(sub\|function\|class\)[ \t]+\([a-z_0-9]+\)/\2/' \
+;; "$@"
+
+;; End Notes Dave Love
+
+
+;; Known bugs:
+;; Doesn't know about ":" separated stmts
+
+
+
+;; todo:
+;; fwd/back-compound-statement
+;; completion over OCX methods and properties.
+;; IDE integration
+;; Change behaviour of ESC-q to recognise words used as paragraph
+;; titles and prevent them being dragged into the previous
+;; paragraph.
+;; etc.
+
+
+;;; Code:
+
+(provide 'visual-basic-mode)
+
+(defvar visual-basic-xemacs-p (string-match "XEmacs\\|Lucid" (emacs-version)))
+(defvar visual-basic-winemacs-p (string-match "Win-Emacs" (emacs-version)))
+(defvar visual-basic-win32-p (eq window-system 'w32))
+
+;; Variables you may want to customize.
+(defvar visual-basic-mode-indent 8 "*Default indentation per nesting level.")
+(defvar visual-basic-fontify-p t "*Whether to fontify Basic buffers.")
+(defvar visual-basic-capitalize-keywords-p t
+ "*Whether to capitalize BASIC keywords.")
+(defvar visual-basic-wild-files "*.frm *.bas *.cls"
+ "*Wildcard pattern for BASIC source files.")
+(defvar visual-basic-ide-pathname nil
+ "*The full pathname of your Visual Basic exe file, if any.")
+;; VB
+(defvar visual-basic-allow-single-line-if t
+ "*Whether to allow single line if")
+
+
+(defvar visual-basic-defn-templates
+ (list "Public Sub ()\nEnd Sub\n\n"
+ "Public Function () As Variant\nEnd Function\n\n"
+ "Public Property Get ()\nEnd Property\n\n")
+ "*List of function templates though which visual-basic-new-sub cycles.")
+
+(defvar visual-basic-imenu-generic-expression
+ '((nil "^\\s-*\\(public\\|private\\)*\\s-+\\(declare\\s-+\\)*\\(sub\\|function\\)\\s-+\\(\\sw+\\>\\)"
+ 4)
+ ("Constants"
+ "^\\s-*\\(private\\|public\\|global\\)*\\s-*\\(const\\s-+\\)\\(\\sw+\\>\\s-*=\\s-*.+\\)$\\|'"
+ 3)
+ ("Variables"
+ "^\\(private\\|public\\|global\\|dim\\)+\\s-+\\(\\sw+\\>\\s-+as\\s-+\\sw+\\>\\)"
+ 2)
+ ("Types" "^\\(public\\s-+\\)*type\\s-+\\(\\sw+\\)" 2)))
+
+
+
+(defvar visual-basic-mode-syntax-table nil)
+(if visual-basic-mode-syntax-table
+ ()
+ (setq visual-basic-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\' "\<" visual-basic-mode-syntax-table) ; Comment starter
+ (modify-syntax-entry ?\n ">" visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\\ "w" visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\= "." visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\< "." visual-basic-mode-syntax-table)
+ (modify-syntax-entry ?\> "." visual-basic-mode-syntax-table)) ; Make =, etc., punctuation so that dynamic abbreviations work properly
+
+
+(defvar visual-basic-mode-map nil)
+(if visual-basic-mode-map
+ ()
+ (setq visual-basic-mode-map (make-sparse-keymap))
+ (define-key visual-basic-mode-map "\t" 'visual-basic-indent-line)
+ (define-key visual-basic-mode-map "\r" 'visual-basic-newline-and-indent)
+ (define-key visual-basic-mode-map "\M-\r" 'visual-basic-insert-item)
+ (define-key visual-basic-mode-map "\C-c\C-j" 'visual-basic-insert-item)
+ (define-key visual-basic-mode-map "\M-\C-a" 'visual-basic-beginning-of-defun)
+ (define-key visual-basic-mode-map "\M-\C-e" 'visual-basic-end-of-defun)
+ (define-key visual-basic-mode-map "\M-\C-h" 'visual-basic-mark-defun)
+ (define-key visual-basic-mode-map "\M-\C-\\" 'visual-basic-indent-region)
+ (define-key visual-basic-mode-map "\M-q" 'visual-basic-fill-or-indent)
+ (define-key visual-basic-mode-map "\M-\C-j" 'visual-basic-split-line)
+ (define-key visual-basic-mode-map "\C-c]" 'visual-basic-close-block)
+ (cond (visual-basic-winemacs-p
+ (define-key visual-basic-mode-map '(control C) 'visual-basic-start-ide))
+ (visual-basic-win32-p
+ (define-key visual-basic-mode-map (read "[?\\S-\\C-c]") 'visual-basic-start-ide)))
+ (if visual-basic-xemacs-p
+ (progn
+ (define-key visual-basic-mode-map "\M-G" 'visual-basic-grep)
+ (define-key visual-basic-mode-map '(meta backspace) 'backward-kill-word)
+ (define-key visual-basic-mode-map '(control meta /) 'visual-basic-new-sub))))
+
+
+;; These abbrevs are valid only in a code context.
+(defvar visual-basic-mode-abbrev-table nil)
+
+(defvar visual-basic-mode-hook ())
+
+
+;; Is there a way to case-fold all regexp matches?
+;; Change KJW Add enum, , change matching from 0 or more to zero or one for public etc.
+(eval-and-compile
+ (defconst visual-basic-defun-start-regexp
+ (concat
+ "^[ \t]*\\([Pp]ublic \\|[Pp]rivate \\|[Ss]tatic\\|[Ff]riend \\)?"
+ "\\([Ss]ub\\|[Ff]unction\\|[Pp]roperty +[GgSsLl]et\\|[Tt]ype\\|[Ee]num\\|[Cc]lass\\)"
+ "[ \t]+\\(\\w+\\)[ \t]*(?")))
+
+
+(defconst visual-basic-defun-end-regexp
+ "^[ \t]*[Ee]nd \\([Ss]ub\\|[Ff]unction\\|[Pp]roperty\\|[Tt]ype\\|[Ee]num\\|[Cc]lass\\)")
+
+(defconst visual-basic-dim-regexp
+ "^[ \t]*\\([Cc]onst\\|[Dd]im\\|[Pp]rivate\\|[Pp]ublic\\)\\_>" )
+
+
+;; Includes the compile-time #if variation.
+;; KJW fixed if to require a whitespace so as to avoid matching, for
+;; instance, iFileName and to require then.
+
+;; Two versions; one recognizes single line if just as though it were
+;; a multi-line and the other does not. Modified again to remove the
+;; requirement for then so as to allow it to match if statements that
+;; have continuations -- VB1 further elaborated on this for single line
+;; if statement to be recognized on broken lines.
+;;(defconst visual-basic-if-regexp
+;; "^[ \t]*#?[Ii]f[ \t]+.*[ \t]+[Tt]hen[ \t]*.*\\('\\|$\\)")
+(defconst visual-basic-if-regexp
+ "^[ \t]*#?[Ii]f[ \t]+.*[ \t_]+")
+
+(defconst visual-basic-ifthen-regexp "^[ \t]*#?[Ii]f.+\\<[Tt]hen\\>\\s-\\S-+")
+
+(defconst visual-basic-else-regexp "^[ \t]*#?[Ee]lse\\([Ii]f\\)?")
+(defconst visual-basic-endif-regexp "[ \t]*#?[Ee]nd[ \t]*[Ii]f")
+
+(defconst visual-basic-looked-at-continuation-regexp "_[ \t]*$")
+
+(defconst visual-basic-continuation-regexp
+ (concat "^.*" visual-basic-looked-at-continuation-regexp))
+
+(eval-and-compile
+ (defconst visual-basic-label-regexp "^[ \t]*[a-zA-Z0-9_]+:$"))
+
+(defconst visual-basic-select-regexp "^[ \t]*[Ss]elect[ \t]+[Cc]ase")
+(defconst visual-basic-case-regexp "^[ \t]*[Cc]ase")
+(defconst visual-basic-select-end-regexp "^[ \t]*[Ee]nd[ \t]+[Ss]elect")
+
+
+(defconst visual-basic-for-regexp "^[ \t]*[Ff]or\\b")
+(defconst visual-basic-next-regexp "^[ \t]*[Nn]ext\\b")
+
+(defconst visual-basic-do-regexp "^[ \t]*[Dd]o\\b")
+(defconst visual-basic-loop-regexp "^[ \t]*[Ll]oop\\b")
+
+(defconst visual-basic-while-regexp "^[ \t]*[Ww]hile\\b")
+(defconst visual-basic-wend-regexp "^[ \t]*[Ww]end\\b")
+
+;; Added KJW Begin..end for forms
+(defconst visual-basic-begin-regexp "^[ \t]*[Bb]egin)?")
+;; This has created a bug. End on its own in code should not outdent.
+;; How can we fix this? They are used in separate Lisp expressions so
+;; add another one.
+(defconst visual-basic-end-begin-regexp "^[ \t]*[Ee]nd")
+
+(defconst visual-basic-with-regexp "^[ \t]*[Ww]ith\\b")
+(defconst visual-basic-end-with-regexp "^[ \t]*[Ee]nd[ \t]+[Ww]ith\\b")
+
+(defconst visual-basic-blank-regexp "^[ \t]*$")
+(defconst visual-basic-comment-regexp "^[ \t]*\\s<.*$")
+
+
+;; This is some approximation of the set of reserved words in Visual Basic.
+(eval-and-compile
+ (defvar visual-basic-all-keywords
+ '("Add" "Aggregate" "And" "App" "AppActivate" "Application" "Array" "As"
+ "Asc" "AscB" "Atn" "Attribute"
+ "Beep" "Begin" "BeginTrans" "Boolean" "ByVal" "ByRef"
+ "CBool" "CByte" "CCur"
+ "CDate" "CDbl" "CInt" "CLng" "CSng" "CStr" "CVErr" "CVar" "Call"
+ "Case" "ChDir" "ChDrive" "Character" "Choose" "Chr" "ChrB" "Class"
+ "ClassModule" "Clipboard" "Close" "Collection" "Column" "Columns"
+ "Command" "CommitTrans" "CompactDatabase" "Component" "Components"
+ "Const" "Container" "Containers" "Cos" "CreateDatabase" "CreateObject"
+ "CurDir" "Currency"
+ "DBEngine" "DDB" "Data" "Database" "Databases"
+ "Date" "DateAdd" "DateDiff" "DatePart" "DateSerial" "DateValue" "Day"
+ "Debug" "Declare" "Deftype" "DeleteSetting" "Dim" "Dir" "Do"
+ "DoEvents" "Domain"
+ "Double" "Dynaset" "EOF" "Each" "Else" "Empty" "End" "EndProperty"
+ "Enum" "Environ" "Erase" "Err" "Error" "Exit" "Exp" "Explicit" "FV" "False" "Field"
+ "Fields" "FileAttr" "FileCopy" "FileDateTime" "FileLen" "Fix" "Font" "For"
+ "Form" "FormTemplate" "Format" "Forms" "FreeFile" "FreeLocks" "Friend"
+ "Function"
+ "Get" "GetAllSettings" "GetAttr" "GetObject" "GetSetting" "Global" "GoSub"
+ "GoTo" "Group" "Groups" "Hex" "Hour" "IIf" "IMEStatus" "IPmt" "IRR"
+ "If" "Implements" "InStr" "Input" "Int" "Integer" "Is" "IsArray" "IsDate"
+ "IsEmpty" "IsError" "IsMissing" "IsNull" "IsNumeric" "IsObject" "Kill"
+ "LBound" "LCase" "LOF" "LSet" "LTrim" "Left" "Len" "Let" "Like" "Line"
+ "Load" "LoadPicture" "LoadResData" "LoadResPicture" "LoadResString" "Loc"
+ "Lock" "Log" "Long" "Loop" "MDIForm" "MIRR" "Me" "MenuItems"
+ "MenuLine" "Mid" "Minute" "MkDir" "Month" "MsgBox" "NPV" "NPer" "Name"
+ "New" "Next" "Not" "Now" "Nothing" "Null" "Object" "Oct" "On" "Open"
+ "OpenDatabase"
+ "Operator" "Option" "Optional"
+ "Or" "PPmt" "PV" "Parameter" "Parameters" "Partition"
+ "Picture" "Pmt" "Preserve" "Print" "Printer" "Printers" "Private"
+ "ProjectTemplate" "Property"
+ "Properties" "Public" "Put" "QBColor" "QueryDef" "QueryDefs"
+ "RSet" "RTrim" "Randomize" "Rate" "ReDim" "Recordset" "Recordsets"
+ "RegisterDatabase" "Relation" "Relations" "Rem" "RepairDatabase"
+ "Reset" "Resume" "Return" "Right" "RmDir" "Rnd" "Rollback" "RowBuffer"
+ "SLN" "SYD" "SavePicture" "SaveSetting" "Screen" "Second" "Seek"
+ "SelBookmarks" "Select" "SelectedComponents" "SendKeys" "Set"
+ "SetAttr" "SetDataAccessOption" "SetDefaultWorkspace" "Sgn" "Shell"
+ "Sin" "Single" "Snapshot" "Space" "Spc" "Sqr" "Static" "Step" "Stop" "Str"
+ "StrComp" "StrConv" "String" "Sub" "SubMenu" "Switch" "Tab" "Table"
+ "TableDef" "TableDefs" "Tan" "Then" "Time" "TimeSerial" "TimeValue"
+ "Timer" "To" "Trim" "True" "Type" "TypeName" "UBound" "UCase" "Unload"
+ "Unlock" "Val" "Variant" "VarType" "Verb" "Weekday" "Wend"
+ "While" "Width" "With" "Workspace" "Workspaces" "Write" "Year")))
+
+(defvar visual-basic-font-lock-keywords-1
+ (eval-when-compile
+ (list
+ ;; Names of functions.
+ (list visual-basic-defun-start-regexp
+ '(1 font-lock-keyword-face nil t)
+ '(2 font-lock-keyword-face nil t)
+ '(3 font-lock-function-name-face))
+
+ ;; Statement labels
+ (cons visual-basic-label-regexp 'font-lock-keyword-face)
+
+ ;; Case values
+ ;; String-valued cases get font-lock-string-face regardless.
+ (list "^[ \t]*case[ \t]+\\([^'\n]+\\)" 1 'font-lock-keyword-face t)
+
+ ;; Any keywords you like.
+ (list (regexp-opt
+ '("Dim" "If" "Then" "Else" "ElseIf" "End If") 'words)
+ 1 'font-lock-keyword-face))))
+
+(defvar visual-basic-font-lock-keywords-2
+ (append visual-basic-font-lock-keywords-1
+ (eval-when-compile
+ `((, (regexp-opt visual-basic-all-keywords 'words)
+ 1 font-lock-keyword-face)))))
+
+(defvar visual-basic-font-lock-keywords visual-basic-font-lock-keywords-1)
+
+
+(put 'visual-basic-mode 'font-lock-keywords 'visual-basic-font-lock-keywords)
+
+;;;###autoload
+(defun visual-basic-mode ()
+ "A mode for editing Microsoft Visual Basic programs.
+Features automatic indentation, font locking, keyword capitalization,
+and some minor convenience functions.
+Commands:
+\\{visual-basic-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map visual-basic-mode-map)
+ (setq major-mode 'visual-basic-mode)
+ (setq mode-name "Visual Basic")
+ (set-syntax-table visual-basic-mode-syntax-table)
+
+ ;;; This does not work in multi major modes.
+ ;;(add-hook 'local-write-file-hooks 'visual-basic-untabify)
+
+ (setq local-abbrev-table visual-basic-mode-abbrev-table)
+ (if visual-basic-capitalize-keywords-p
+ (progn
+ (make-local-variable 'pre-abbrev-expand-hook)
+ (add-hook 'pre-abbrev-expand-hook 'visual-basic-pre-abbrev-expand-hook)
+ (abbrev-mode 1)))
+
+ (make-local-variable 'comment-start)
+ (setq comment-start "' ")
+ (make-local-variable 'comment-start-skip)
+ (setq comment-start-skip "'+ *")
+ (make-local-variable 'comment-column)
+ (setq comment-column 40)
+ (make-local-variable 'comment-end)
+ (setq comment-end "")
+
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'visual-basic-indent-line)
+
+ (if visual-basic-fontify-p
+ (visual-basic-enable-font-lock))
+
+ (make-local-variable 'imenu-generic-expression)
+ (setq imenu-generic-expression visual-basic-imenu-generic-expression)
+
+ (set (make-local-variable 'imenu-syntax-alist) `((,(string-to-char "_") . "w")))
+ (set (make-local-variable 'imenu-case-fold-search) t)
+
+ ;;(make-local-variable 'visual-basic-associated-files)
+ ;; doing this here means we need not check to see if it is bound later.
+ (add-hook 'find-file-hooks 'visual-basic-load-associated-files)
+
+ (run-hooks 'visual-basic-mode-hook))
+
+
+(defun visual-basic-enable-font-lock ()
+ ;; Emacs 19.29 requires a window-system else font-lock-mode errs out.
+ (cond ((or visual-basic-xemacs-p window-system)
+
+ ;; In win-emacs this sets font-lock-keywords back to nil!
+ (if visual-basic-winemacs-p
+ (font-lock-mode 1))
+
+ ;; Accomodate emacs 19.29+
+ ;; From: Simon Marshall <Simon.Marshall@esrin.esa.it>
+ (cond ((boundp 'font-lock-defaults)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ `((visual-basic-font-lock-keywords
+ visual-basic-font-lock-keywords-1
+ visual-basic-font-lock-keywords-2)
+ nil t ((,(string-to-char "_") . "w")))))
+ (t
+ (make-local-variable 'font-lock-keywords)
+ (setq font-lock-keywords visual-basic-font-lock-keywords)))
+
+ (if visual-basic-winemacs-p
+ (font-lock-fontify-buffer)
+ (font-lock-mode 1)))))
+
+;; KJW should add some odds and bobs here to cover "end if" one way
+;; could be to create the abbreviations by removing whitespace then we
+;; could put "end if", "end with" and so on in the keyword table
+;; Another idea would be to make it intelligent enough to substitute
+;; the correct end for the construct (with, select, if)
+;; Is this what the abbrev table hook entry is for?
+(defun visual-basic-construct-keyword-abbrev-table ()
+ (if visual-basic-mode-abbrev-table
+ nil
+ (let ((words visual-basic-all-keywords)
+ (word nil)
+ (list nil))
+ (while words
+ (setq word (car words)
+ words (cdr words))
+ (setq list (cons (list (downcase word) word) list)))
+
+ (define-abbrev-table 'visual-basic-mode-abbrev-table list))))
+
+;; Would like to do this at compile-time.
+(visual-basic-construct-keyword-abbrev-table)
+
+
+(defun visual-basic-upgrade-keyword-abbrev-table ()
+ "Use this in case of upgrading visual-basic-mode.el"
+ (interactive)
+
+ (let ((words visual-basic-all-keywords)
+ (word nil)
+ (list nil))
+ (while words
+ (setq word (car words)
+ words (cdr words))
+ (setq list (cons (list (downcase word) word) list)))
+ (define-abbrev-table 'visual-basic-mode-abbrev-table list)))
+
+
+(defun visual-basic-in-code-context-p ()
+ (if (fboundp 'buffer-syntactic-context) ; XEmacs function.
+ (null (buffer-syntactic-context))
+ ;; Attempt to simulate buffer-syntactic-context
+ ;; I don't know how reliable this is.
+ (let* ((beg (save-excursion
+ (beginning-of-line)
+ (point)))
+ (list
+ (parse-partial-sexp beg (point))))
+ (and (null (nth 3 list)) ; inside string.
+ (null (nth 4 list)))))) ; inside comment
+
+
+(defun visual-basic-pre-abbrev-expand-hook ()
+ ;; Allow our abbrevs only in a code context.
+ (setq local-abbrev-table
+ (if (visual-basic-in-code-context-p)
+ visual-basic-mode-abbrev-table)))
+
+
+(defun visual-basic-newline-and-indent (&optional count)
+ "Insert a newline, updating indentation."
+ (interactive)
+ (save-excursion
+ (expand-abbrev)
+ (visual-basic-indent-line))
+ (call-interactively 'newline-and-indent))
+
+(defun visual-basic-beginning-of-defun ()
+ (interactive)
+ (re-search-backward visual-basic-defun-start-regexp))
+
+(defun visual-basic-end-of-defun ()
+ (interactive)
+ (re-search-forward visual-basic-defun-end-regexp))
+
+(defun visual-basic-mark-defun ()
+ (interactive)
+ (beginning-of-line)
+ (visual-basic-end-of-defun)
+ (set-mark (point))
+ (visual-basic-beginning-of-defun)
+ (if visual-basic-xemacs-p
+ (zmacs-activate-region)))
+
+(defun visual-basic-indent-defun ()
+ (interactive)
+ (save-excursion
+ (visual-basic-mark-defun)
+ (call-interactively 'visual-basic-indent-region)))
+
+
+(defun visual-basic-fill-long-comment ()
+ "Fills block of comment lines around point."
+ ;; Derived from code in ilisp-ext.el.
+ (interactive)
+ (save-excursion
+ (beginning-of-line)
+ (let ((comment-re "^[ \t]*\\s<+[ \t]*"))
+ (if (looking-at comment-re)
+ (let ((fill-prefix
+ (buffer-substring
+ (progn (beginning-of-line) (point))
+ (match-end 0))))
+
+ (while (and (not (bobp))
+ (looking-at visual-basic-comment-regexp))
+ (forward-line -1))
+ (if (not (bobp)) (forward-line 1))
+
+ (let ((start (point)))
+
+ ;; Make all the line prefixes the same.
+ (while (and (not (eobp))
+ (looking-at comment-re))
+ (replace-match fill-prefix)
+ (forward-line 1))
+
+ (if (not (eobp))
+ (beginning-of-line))
+
+ ;; Fill using fill-prefix
+ (fill-region-as-paragraph start (point))))))))
+
+
+(defun visual-basic-fill-or-indent ()
+ "Fill long comment around point, if any, else indent current definition."
+ (interactive)
+ (cond ((save-excursion
+ (beginning-of-line)
+ (looking-at visual-basic-comment-regexp))
+ (visual-basic-fill-long-comment))
+ (t
+ (visual-basic-indent-defun))))
+
+
+(defun visual-basic-new-sub ()
+ "Insert template for a new subroutine. Repeat to cycle through alternatives."
+ (interactive)
+ (beginning-of-line)
+ (let ((templates (cons visual-basic-blank-regexp
+ visual-basic-defn-templates))
+ (tem nil)
+ (bound (point)))
+ (while templates
+ (setq tem (car templates)
+ templates (cdr templates))
+ (cond ((looking-at tem)
+ (replace-match (or (car templates)
+ ""))
+ (setq templates nil))))
+
+ (search-backward "()" bound t)))
+
+
+;; (defun visual-basic-untabify ()
+;; "Do not allow any tabs into the file."
+;; (if (eq major-mode 'visual-basic-mode)
+;; (untabify (point-min) (point-max)))
+;; nil)
+
+(defun visual-basic-default-tag ()
+ (if (and (not (bobp))
+ (save-excursion
+ (backward-sexp)
+ (looking-at "\\w")))
+ (backward-word 1))
+ (let ((s (point))
+ (e (save-excursion
+ (forward-sexp)
+ (point))))
+ (buffer-substring s e)))
+
+(defun visual-basic-grep (tag)
+ "Search BASIC source files in current directory for TAG."
+ (interactive
+ (list (let* ((def (visual-basic-default-tag))
+ (tag (read-string
+ (format "Grep for [%s]: " def))))
+ (if (string= tag "") def tag))))
+ (grep (format "grep -n %s %s" tag visual-basic-wild-files)))
+
+
+;;; IDE Connection.
+
+(defun visual-basic-buffer-project-file ()
+ "Return a guess as to the project file associated with the current buffer."
+ (car (directory-files (file-name-directory (buffer-file-name)) t "\\.vbp")))
+
+(defun visual-basic-start-ide ()
+ "Start Visual Basic (or your favorite IDE, (after Emacs, of course))
+on the first project file in the current directory.
+Note: it's not a good idea to leave Visual Basic running while you
+are editing in Emacs, since Visual Basic has no provision for reloading
+changed files."
+ (interactive)
+ (let (file)
+ (cond ((null visual-basic-ide-pathname)
+ (error "No pathname set for Visual Basic. See visual-basic-ide-pathname"))
+ ((null (setq file (visual-basic-buffer-project-file)))
+ (error "No project file found"))
+ ((fboundp 'win-exec)
+ (iconify-emacs)
+ (win-exec visual-basic-ide-pathname 'win-show-normal file))
+ ((fboundp 'start-process)
+ (iconify-frame (selected-frame))
+ (start-process "*VisualBasic*" nil visual-basic-ide-pathname file))
+ (t
+ (error "No way to spawn process!")))))
+
+
+
+;;; Indentation-related stuff.
+
+(defun visual-basic-indent-region (start end)
+ "Perform visual-basic-indent-line on each line in region."
+ (interactive "r")
+ (save-excursion
+ (goto-char start)
+ (beginning-of-line)
+ (while (and (not (eobp))
+ (< (point) end))
+ (if (not (looking-at visual-basic-blank-regexp))
+ (visual-basic-indent-line))
+ (forward-line 1)))
+
+ (cond ((fboundp 'zmacs-deactivate-region)
+ (zmacs-deactivate-region))
+ ((fboundp 'deactivate-mark)
+ (deactivate-mark))))
+
+
+
+(defun visual-basic-previous-line-of-code ()
+ (if (not (bobp))
+ (forward-line -1)) ; previous-line depends on goal column
+ (while (and (not (bobp))
+ (or (looking-at visual-basic-blank-regexp)
+ (looking-at visual-basic-comment-regexp)))
+ (forward-line -1)))
+
+
+(defun visual-basic-find-original-statement ()
+ "If the current line is a continuation, move back to the original stmt."
+ (let ((here (point)))
+ (visual-basic-previous-line-of-code)
+ (while (and (not (bobp))
+ (looking-at visual-basic-continuation-regexp))
+ (setq here (point))
+ (visual-basic-previous-line-of-code))
+ (goto-char here)))
+
+(defun visual-find-matching-stmt (open-p close-p)
+ ;; Searching backwards
+ (let ((level 0))
+ (while (and (>= level 0) (not (bobp)))
+ (visual-basic-previous-line-of-code)
+ (visual-basic-find-original-statement)
+ (cond ((funcall close-p)
+ (setq level (+ level 1)))
+ ((funcall open-p)
+ (setq level (- level 1)))))))
+
+(defun visual-basic-find-matching-stmt (open-regexp close-regexp)
+ (visual-find-matching-stmt
+ (lambda () (looking-at open-regexp))
+ (lambda () (looking-at close-regexp))))
+
+(defun visual-basic-get-complete-tail-of-line ()
+ "Return the tail of the current statement line, starting at
+ point and going up to end of statement line. If you want the
+ complete statement line, you have to call functions
+ `visual-basic-find-original-statement' and then
+ `beginning-of-line' before"
+ (let* ((start-point (point))
+ complete-line
+ (line-beg start-point)
+ line-end)
+ (while (null line-end)
+ (end-of-line)
+ (setq line-end (point))
+ (if (search-backward "_" line-beg t)
+ (if (looking-at visual-basic-looked-at-continuation-regexp)
+ ;; folded line
+ (progn
+ (setq line-end (1- (point))
+ complete-line (cons
+ (buffer-substring-no-properties
+ line-beg line-end)
+ complete-line)
+ line-end nil)
+ (beginning-of-line 2)
+ (setq line-beg (point)))
+ ;; _ found, but not a folded line (this is a syntax error)
+ (setq complete-line
+ (cons (buffer-substring-no-properties line-beg line-end) complete-line)))
+ ;; not a folded line
+ (setq complete-line
+ (cons (buffer-substring-no-properties line-beg line-end)
+ complete-line))))
+ (mapconcat 'identity (nreverse complete-line) " ")))
+
+(defun visual-basic-if-not-on-single-line ()
+ "Return non-`nil' when the If statement is not on a single statement
+line, i.e. requires a matching End if. Note that a statement line may
+be folded over several code lines."
+ (if (looking-at visual-basic-if-regexp)
+ (save-excursion
+ (beginning-of-line)
+ (let (p1
+ p2
+ ;; 1st reconstruct complete line
+ (complete-line (visual-basic-get-complete-tail-of-line)) )
+
+ ;; now complete line has been reconstructed, drop confusing elements
+
+ ;; remove any VB string from complete line, as strings may disrupt : and ' detection
+ (while (and (setq p1 (string-match "\"" complete-line))
+ (setq p2 (string-match "\"" complete-line (1+ p1))))
+ (setq complete-line (concat (substring complete-line 0 p1)
+ (substring complete-line (1+ p2)))))
+ ;; now drop tailing comment if any
+ (when (setq p1 (string-match "'" complete-line))
+ (setq complete-line (substring complete-line p1)))
+ ;; now drop 1st concatenated instruction is any
+ (when (setq p1 (string-match ":" complete-line))
+ (setq complete-line (substring complete-line p1)))
+ ;;
+ (string-match "Then\\s-*$" complete-line))); end (save-excursion ...)
+ ;; else, not a basic if
+ nil))
+
+(defun visual-basic-find-matching-if ()
+ (visual-find-matching-stmt 'visual-basic-if-not-on-single-line
+ (lambda () (looking-at visual-basic-endif-regexp))))
+
+(defun visual-basic-find-matching-select ()
+ (visual-basic-find-matching-stmt visual-basic-select-regexp
+ visual-basic-select-end-regexp))
+
+(defun visual-basic-find-matching-for ()
+ (visual-basic-find-matching-stmt visual-basic-for-regexp
+ visual-basic-next-regexp))
+
+(defun visual-basic-find-matching-do ()
+ (visual-basic-find-matching-stmt visual-basic-do-regexp
+ visual-basic-loop-regexp))
+
+(defun visual-basic-find-matching-while ()
+ (visual-basic-find-matching-stmt visual-basic-while-regexp
+ visual-basic-wend-regexp))
+
+(defun visual-basic-find-matching-with ()
+ (visual-basic-find-matching-stmt visual-basic-with-regexp
+ visual-basic-end-with-regexp))
+
+;;; If this fails it must return the indent of the line preceding the
+;;; end not the first line because end without matching begin is a
+;;; normal simple statement
+(defun visual-basic-find-matching-begin ()
+ (let ((original-point (point)))
+ (visual-basic-find-matching-stmt visual-basic-begin-regexp
+ visual-basic-end-begin-regexp)
+ (if (bobp) ;failed to find a matching begin so assume that it is
+ ;an end statement instead and use the indent of the
+ ;preceding line.
+ (progn (goto-char original-point)
+ (visual-basic-previous-line-of-code)))))
+
+
+(defun visual-basic-calculate-indent ()
+ (let ((original-point (point)))
+ (save-excursion
+ (beginning-of-line)
+ ;; Some cases depend only on where we are now.
+ (cond ((or (looking-at visual-basic-defun-start-regexp)
+ (looking-at visual-basic-label-regexp)
+ (looking-at visual-basic-defun-end-regexp))
+ 0)
+
+ ;; The outdenting stmts, which simply match their original.
+ ((or (looking-at visual-basic-else-regexp)
+ (looking-at visual-basic-endif-regexp))
+ (visual-basic-find-matching-if)
+ (current-indentation))
+
+ ;; All the other matching pairs act alike.
+ ((looking-at visual-basic-next-regexp) ; for/next
+ (visual-basic-find-matching-for)
+ (current-indentation))
+
+ ((looking-at visual-basic-loop-regexp) ; do/loop
+ (visual-basic-find-matching-do)
+ (current-indentation))
+
+ ((looking-at visual-basic-wend-regexp) ; while/wend
+ (visual-basic-find-matching-while)
+ (current-indentation))
+
+ ((looking-at visual-basic-end-with-regexp) ; with/end with
+ (visual-basic-find-matching-with)
+ (current-indentation))
+
+ ((looking-at visual-basic-select-end-regexp) ; select case/end select
+ (visual-basic-find-matching-select)
+ (current-indentation))
+
+ ;; A case of a select is somewhat special.
+ ((looking-at visual-basic-case-regexp)
+ (visual-basic-find-matching-select)
+ (+ (current-indentation) visual-basic-mode-indent))
+
+ ;; Added KJW: Make sure that this comes after the cases
+ ;; for if..endif, end select because end-regexp will also
+ ;; match "end select" etc.
+ ((looking-at visual-basic-end-begin-regexp) ; begin/end
+ (visual-basic-find-matching-begin)
+ (current-indentation))
+
+ (t
+ ;; Other cases which depend on the previous line.
+ (visual-basic-previous-line-of-code)
+
+ ;; Skip over label lines, which always have 0 indent.
+ (while (looking-at visual-basic-label-regexp)
+ (visual-basic-previous-line-of-code))
+
+ (cond
+ ((looking-at visual-basic-continuation-regexp)
+ (visual-basic-find-original-statement)
+ ;; Indent continuation line under matching open paren,
+ ;; or else one word in.
+ (let* ((orig-stmt (point))
+ (matching-open-paren
+ (condition-case ()
+ (save-excursion
+ (goto-char original-point)
+ (beginning-of-line)
+ (backward-up-list 1)
+ ;; Only if point is now w/in cont. block.
+ (if (<= orig-stmt (point))
+ (current-column)))
+ (error nil))))
+ (cond (matching-open-paren
+ (1+ matching-open-paren))
+ (t
+ ;; Else, after first word on original line.
+ (back-to-indentation)
+ (forward-word 1)
+ (while (looking-at "[ \t]")
+ (forward-char 1))
+ (current-column)))))
+ (t
+ (visual-basic-find-original-statement)
+
+ (let ((indent (current-indentation)))
+ ;; All the various +indent regexps.
+ (cond ((looking-at visual-basic-defun-start-regexp)
+ (+ indent visual-basic-mode-indent))
+
+ ((or (visual-basic-if-not-on-single-line)
+ (and (looking-at visual-basic-else-regexp)
+ (not (and visual-basic-allow-single-line-if
+ (looking-at visual-basic-ifthen-regexp)))))
+ (+ indent visual-basic-mode-indent))
+
+ ((or (looking-at visual-basic-select-regexp)
+ (looking-at visual-basic-case-regexp))
+ (+ indent visual-basic-mode-indent))
+
+ ((or (looking-at visual-basic-do-regexp)
+ (looking-at visual-basic-for-regexp)
+ (looking-at visual-basic-while-regexp)
+ (looking-at visual-basic-with-regexp)
+ (looking-at visual-basic-begin-regexp))
+ (+ indent visual-basic-mode-indent))
+
+ (t
+ ;; By default, just copy indent from prev line.
+ indent))))))))))
+
+(defun visual-basic-indent-to-column (col)
+ (let* ((bol (save-excursion
+ (beginning-of-line)
+ (point)))
+ (point-in-whitespace
+ (<= (point) (+ bol (current-indentation))))
+ (blank-line-p
+ (save-excursion
+ (beginning-of-line)
+ (looking-at visual-basic-blank-regexp))))
+
+ (cond ((/= col (current-indentation))
+ (save-excursion
+ (beginning-of-line)
+ (back-to-indentation)
+ (delete-region bol (point))
+ (indent-to col))))
+
+ ;; If point was in the whitespace, move back-to-indentation.
+ (cond (blank-line-p
+ (end-of-line))
+ (point-in-whitespace
+ (back-to-indentation)))))
+
+
+(defun visual-basic-indent-line ()
+ "Indent current line for BASIC."
+ (interactive)
+ (visual-basic-indent-to-column (visual-basic-calculate-indent)))
+
+
+(defun visual-basic-split-line ()
+ "Split line at point, adding continuation character or continuing a comment.
+In Abbrev mode, any abbrev before point will be expanded."
+ (interactive)
+ (let ((pps-list (parse-partial-sexp (save-excursion
+ (beginning-of-line)
+ (point))
+ (point))))
+ ;; Dispatch on syntax at this position.
+ (cond ((equal t (nth 4 pps-list)) ; in comment
+ (indent-new-comment-line))
+ ((equal t (nth 4 pps-list)) ; in string
+ (error "Can't break line inside a string"))
+ (t (just-one-space) ; leading space on next line
+ ; doesn't count, sigh
+ (insert "_")
+ (visual-basic-newline-and-indent)))))
+
+(defun visual-basic-detect-idom ()
+ "Detects whether this is a VBA or VBS script. Returns symbol
+ `vba' if it is VBA, `nil' otherwise"
+ (let (ret)
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (cond
+ ((looking-at "^[ \t]*Attribute\\s-+VB_Name\\s-+= ") (setq ret 'vba)))
+ ))
+ ret))
+
+(defun visual-basic-close-block ()
+ "Insert `End If' is current block is a `If Then ...', `End
+With' if the block is a `With ...', etc..."
+ (interactive)
+ (let (end-statement end-indent)
+ (save-excursion
+ (save-match-data
+ (while
+ (unless (bobp)
+ (visual-basic-previous-line-of-code)
+ (visual-basic-find-original-statement)
+ (cond
+ ;; Cases where the current statement is a start-of-smthing statement
+ ((looking-at visual-basic-defun-start-regexp)
+ (let ((smt (match-string 2)))
+ (when (string-match "\\`Prop" smt)
+ (setq smt "Property"))
+ (setq end-statement (concat "End " smt)
+ end-indent 0))
+ nil)
+ ((looking-at visual-basic-select-regexp)
+ (setq end-statement "End Select"
+ end-indent (current-indentation))
+ nil)
+ ((looking-at visual-basic-with-regexp)
+ (setq end-statement "End With"
+ end-indent (current-indentation))
+ nil)
+ ((looking-at visual-basic-case-regexp)
+ (setq end-statement "End Select"
+ end-indent (max 0 (- (current-indentation) visual-basic-mode-indent)))
+ nil)
+ ((looking-at visual-basic-begin-regexp)
+ (setq end-statement "End"
+ end-indent (current-indentation))
+ nil)
+ ((or (visual-basic-if-not-on-single-line)
+ (looking-at visual-basic-else-regexp))
+ (setq end-statement "End If"
+ end-indent (current-indentation))
+ nil)
+
+ ((looking-at visual-basic-do-regexp)
+ (setq end-statement "Loop"
+ end-indent (current-indentation))
+ nil)
+
+ ((looking-at visual-basic-for-regexp)
+ (goto-char (match-end 0))
+ (setq end-statement "Next"
+ end-indent (current-indentation))
+ (let ((vb-idom (visual-basic-detect-idom)))
+ (cond
+ ;; for VBA add the variable name after Next.
+ ((eq vb-idom 'vba)
+ (when (looking-at "\\s-+\\(Each\\s-+\\|\\)\\([^ \t\n\r]+\\)")
+ (setq end-statement (concat end-statement " " (match-string 2)))))))
+ nil)
+ ;; Cases where the current statement is an end-of-smthing statement
+ ((or (looking-at visual-basic-else-regexp)
+ (looking-at visual-basic-endif-regexp))
+ (visual-basic-find-matching-if)
+ t)
+ ((looking-at visual-basic-next-regexp) ; for/next
+ (visual-basic-find-matching-for)
+ t)
+ ((looking-at visual-basic-loop-regexp) ; do/loop
+ (visual-basic-find-matching-do)
+ t)
+ ((looking-at visual-basic-wend-regexp) ; while/wend
+ (visual-basic-find-matching-while)
+ t)
+ ((looking-at visual-basic-end-with-regexp) ; with/end with
+ (visual-basic-find-matching-with)
+ t)
+ ((looking-at visual-basic-select-end-regexp) ; select case/end select
+ (visual-basic-find-matching-select)
+ t)
+
+
+ ;; default is to loop again back to previous line of code.
+ (t t))))))
+ (when end-statement
+ (insert end-statement)
+ (visual-basic-indent-to-column end-indent))))
+
+(defvar delta-split-to-cur-point) ;; Don't know what it is, just silence compiler
+
+(defun visual-basic-insert-item ()
+ "Insert a new item in a block.
+
+This function is under developement, and for the time being only Dim items are handled.
+
+Interting an item means:
+
+* Add a `Case' or `Case Else' into a `Select ... End Select'
+ block. Pressing again toggles between `Case' and `Case
+ Else'. `Case Else' is possible only if there is not already a `Case Else'.
+
+* split a Dim declaration over several lines.
+
+* Add an `Else' or `ElseIf ... Then' into an `If ... Then ... End
+ If' block. Pressing again toggles between `Else' and `ElseIf
+ ... Then'. `Else' is possible only if therei s not already an
+ `Else'.
+"
+ (interactive)
+ ;; possible cases are
+ ;; dim-split-before => split before variable name
+ ;; dim-split-after => split after type name if any
+ ;; if-with-else
+ ;; if-without-else
+ ;; select-with-else
+ ;; select-without-else
+ ;; not-itemizable
+ (let (item-case
+ item-ident
+ split-point
+ cur-point-mark
+ prefix
+ tentative-split-point
+ block-stack (cur-point (point)) previous-line-of-code)
+ (save-excursion
+ (save-match-data
+ (beginning-of-line)
+ (while
+ (progn
+ (visual-basic-find-original-statement)
+ (cond
+ ;; dim case
+ ;;--------------------------------------------------------------
+ ((and (null previous-line-of-code)
+ (looking-at visual-basic-dim-regexp)
+ (null (save-match-data (looking-at visual-basic-defun-start-regexp))))
+ (setq prefix (buffer-substring-no-properties
+ (point)
+ (goto-char (setq split-point (match-end 0)))))
+ (while
+ (progn
+ (if
+ (looking-at "\\s-*\\sw+\\s-*")
+ (progn
+ (goto-char (setq tentative-split-point (match-end 0)))
+ (if (>= tentative-split-point cur-point)
+ nil
+ (while (or
+ (looking-at "([^)\n]+)\\s-*")
+ (looking-at visual-basic-looked-at-continuation-regexp))
+ (goto-char (setq tentative-split-point (match-end 0))))
+ (when (looking-at "As\\s-+\\sw+\\s-*")
+ (goto-char (setq tentative-split-point (match-end 0))))
+ (when (looking-at visual-basic-looked-at-continuation-regexp)
+ (beginning-of-line 2))
+ (if (looking-at ",")
+ (goto-char (setq split-point (match-end 0)))
+ (setq split-point (point))
+ nil)))
+ nil)))
+ (goto-char split-point)
+ (setq item-case (if (<= split-point cur-point) 'dim-split-before 'dim-split-after))
+ (setq delta-split-to-cur-point (- split-point cur-point))
+ (setq cur-point-mark (make-marker))
+ (set-marker cur-point-mark cur-point)
+ (looking-at "\\s-*")
+ (setq delta-split-to-cur-point (- delta-split-to-cur-point
+ (- (match-end 0) (match-beginning 0))))
+ (delete-region (point) (match-end 0))
+ (when (looking-back ",")
+ (delete-region split-point (1- split-point)))
+ (insert "\n" prefix " ")
+ (setq cur-point (marker-position cur-point-mark))
+ (set-marker cur-point-mark nil)
+ nil)
+ ;; next
+ ((looking-at visual-basic-next-regexp)
+ (push (list 'next) block-stack))
+ ;; default
+ ;;--------------------------------------------------------------
+ (t (if (bobp)
+ (setq item-case 'not-itemizable)))
+ )
+ (when (null item-case)
+ (visual-basic-previous-line-of-code)
+ (setq previous-line-of-code t))
+ (null item-case)))))
+ (cond
+ ((eq item-case 'dim-split-after)
+ (goto-char cur-point))
+ )
+ ))
+
+;;; Some experimental functions
+
+;;; Load associated files listed in the file local variables block
+(defun visual-basic-load-associated-files ()
+ "Load files that are useful to have around when editing the source of the file that has just been loaded.
+The file must have a local variable that lists the files to be loaded.
+If the file name is relative it is relative to the directory
+containing the current buffer. If the file is already loaded nothing
+happens, this prevents circular references causing trouble. After an
+associated file is loaded its associated files list will be
+processed."
+ (if (boundp 'visual-basic-associated-files)
+ (let ((files visual-basic-associated-files)
+ (file nil))
+ (while files
+ (setq file (car files)
+ files (cdr files))
+ (message "Load associated file: %s" file)
+ (visual-basic-load-file-ifnotloaded file default-directory)))))
+
+
+
+(defun visual-basic-load-file-ifnotloaded (file default-directory)
+ "Load file if not already loaded.
+If file is relative then default-directory provides the path"
+ (let((file-absolute (expand-file-name file default-directory)))
+ (if (get-file-buffer file-absolute); don't do anything if the buffer is already loaded
+ ()
+ (find-file-noselect file-absolute ))))
+
+
+
+;;; visual-basic-mode.el ends here
+
+
+;External Links
+;* [http://visualbasic.freetutes.com/ Visual Basic tutorials]
+
diff --git a/emacs.d/nxhtml/related/wikipedia-mode.el b/emacs.d/nxhtml/related/wikipedia-mode.el
new file mode 100644
index 0000000..c219e19
--- /dev/null
+++ b/emacs.d/nxhtml/related/wikipedia-mode.el
@@ -0,0 +1,2296 @@
+;;; wikipedia-mode.el --- Mode for editing Wikipedia articles off-line
+;; Copyright (C) 2003, 2004, 2006 Chong Yidong, Uwe Brauer
+
+;; Author: Chong Yidong <cyd at stupidchicken com>
+;; Maintainer: Uwe Brauer <oub at mat.ucm.es>
+;; Version: 0.51
+;; Keywords: wiki
+;; $Id: wikipedia-mode.el,v 1.5 2006/05/30 15:16:45 oub Exp oub $
+
+
+;; This file is not part of GNU Emacs.
+
+;;{{{ GPL2
+
+;; This file 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 2 of
+;; the License, or (at your option) any later version.
+
+;; This file 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 GNU Emacs; if not, write to the Free
+;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+;; MA 02111-1307 USA
+
+;;}}}
+
+;;; Commentary:
+
+;; This is `wikipedia-mode', a major mode for editing articles written
+;; in the markup language used by Wikipedia, the free on-line
+;; encyclopedia (http://www.wikipedia.org). It is intended to work
+;; with GNU Emacs 21.x, and Xemacs 21.4.x. See below for details.
+
+;; wikipedia mode can be found also at:
+;; http://en.wikipedia.org/wiki/Wikipedia:Wikipedia-mode.el
+
+;;{{{ INSTALLING WIKIPEDIA-MODE
+
+;; Installing wikipedia-mode
+;; =========================
+;;
+;; Save wikipedia-mode.el in a convenient directory, preferably in
+;; your `load-path'. Add the following to your `user-init-file':
+;;
+;; (autoload 'wikipedia-mode
+;; "wikipedia-mode.el"
+;; "Major mode for editing documents in Wikipedia markup." t)
+;;
+;; If you did not save wikipedia-mode.el in your `load-path', you must
+;; use the full pathname. On MS Windows, use forward slashes (/)
+;; rather than back slashes (\) to indicate the directory, e.g.:
+;;
+;; (autoload 'wikipedia-mode
+;; "C:/Documents and Settings/USERNAME/.emacs.d/Wikipedia-mode.el"
+;; "Major mode for editing documents in Wikipedia markup." t)
+;;
+;; If you want to associate filenames ending in ".wiki" with
+;; wikipedia-mode, add the following to your init file:
+;;
+;; (setq auto-mode-alist
+;; (cons '("\\.wiki\\'" . wikipedia-mode) auto-mode-alist))
+
+;;}}}
+
+;;{{{ REQUIREMENTS
+
+;; This is not a real requirements but I highly recommend to use
+;; outline-magic written by Carsten Dominik. If you don't want to use it
+;; you have to comment out the relevant reference to outline magic.
+;; It can be found at
+;; http://www.astro.uva.nl/~dominik/Tools/outline-magic.el
+
+
+
+
+;;}}}
+
+;;{{{ RECOMMENDATIONS INSTALLING LONGLINES-MODE
+
+;; Installing longlines-mode
+;; =========================
+;;
+;; If you are using Emacs 22 or later longlines-mode is included so
+;; please skip this section!
+;;
+;; Wikipedia articles don't use newline characters to break paragraphs
+;; into lines, so each paragraph looks like a super-long line to
+;; Emacs. To let Emacs handle "soft word wrapping", you need to
+;; download a third-party package, longlines-mode.
+;;
+;; Download longlines.el, saving into your `load-path':
+;;
+;; http://www.emacswiki.org/elisp/longlines.el
+;;
+;; Add the following to your `user-init-file':
+;;
+;; (autoload 'longlines-mode "longlines.el"
+;; "Minor mode for editing long lines." t)
+;;
+;;
+;; WARNING: if you insert text from one file in wikipedia-mode to
+;; another file in wikipedia-mode I strongly recommend, to turn
+;; longlines-mode off, before the copying!
+
+;;}}}
+
+;;{{{ RECOMMENDATIONS INSTALLING PABBREV-MODE
+
+;; Installing pabbrev-mode
+;; =========================
+;;
+;; You may find pabbrev.el useful, which can be found at
+;; http://www.russet.org.uk/download/emacs/pabbrev.el
+
+
+;;}}}
+
+;;{{{ Xemacs or (GNU) Emacs
+
+;; Xemacs or (GNU) Emacs
+;; =====================
+;; Usually that is a question of taste. However almost all wikipedia
+;; articles nowadays use UTF8 coding, so the question which of the
+;; Macsen to use, boils down to which degree UTF8 support is
+;; implemented (no mule Xemacs is ruled out). While Xemacs has the
+;; better font support, the UTF8 support still is not complete and
+;; hence at the time being it is sad for the maintainer (a long time
+;; Xemacs user) to recommend NOT to use Xemacs, even not 21.5.x, which
+;; has a much better implemented UTF8 coding engine. That might
+;; however change in the foreseeable future....
+;; WARNING: at least for me in Debian testing/unstable Emacs does not
+;; ship all fonts necessary for a flawless editing of UTF8 files. For
+;; example you can chose Greek input, write Greek text, but then when
+;; you close and open the file again, the Greek symbol are not
+;; displayed but you see empty blocks. The reason seems that emacs
+;; chooses for the input fonts other fonts as for the display (don't
+;; ask me). However for installing the (ugly) UTF8 compatible fonts
+;; from ..... solved that problem.
+
+
+;;}}}
+
+;;{{{ INSTALLING EE-HELPER or MOZEX
+
+;; Installing the helper programs.
+;; =========================
+;; Helper Programs: MozEx and EE-HELPER. There are three possibilities
+;; in order to use Emacs as an external editor
+;;
+;; (1) Firefox add-on It's All Text: Recommended. The elisp
+;; library its-all-text.el makes it easier to use this.
+;;
+;; PROS: Easy to intall, supported. (You need to add Emacs
+;; client as the editor.) Can be used for editing other
+;; text fields with Emacs too.
+;;
+;; (2) EE-HELPER: This is perl script which will communicate with
+;; the wikipedia server. However that sometimes be slow.
+
+;; PROS: if the editor supports UTF8, then ee-helper will
+;; pass the coding flawlessly.
+;;
+;; CONTRA: the problem with this script is that it directly
+;; communicates with the wikipedia site and does not
+;; warn you about simultaneous editing. Use it with
+;; care!!! Moreover section editing is not implemented.
+
+;; (3) MozEx: this is a Java-script which allows to communicate
+;; Mozilla (or Firefox) directly with Emacs.
+
+;; PROS: After finishing editing you use the wikipedia
+;; software to submit your changes and not the script,
+;; so you are warned about possible conflicting editing.
+;;
+;; CONTRA: the official version does not support UTF8,
+;; however there is now a new semi official version which
+;; does support UTF8.
+
+;; Installing It's All Text
+;; ========================
+;;
+;; Go to the home page and follow the instructions there:
+;;
+;; https://addons.mozilla.org/en-US/firefox/addon/4125
+;;
+;; Then open It's All Text preferences from the Firefox Add-ons page
+;; and choose emacsclient as your editor (emacsclientw.exe on
+;; Windows).
+
+;; Installing ee-helper
+;; ====================
+;;
+;; Download the perl script from
+;;
+;; http://meta.wikimedia.org/wiki/Help:External_editors
+;;
+;; and follow the instructions. configure the .ee-ini file. chance in
+;; your personal wikipedia-mode-map account setting the editing
+;; functions: activate the `external editor' option.
+
+;; Installing MozEx
+;; ================
+;;
+;; If your web browser is Mozilla or Firefox, take a look at the MozEx
+;; extension, which allows you to call Emacs for editing text boxes:
+;;
+;; http://mozex.mozdev.org/development.html
+;;
+;; See also
+;;
+;; http://www.emacswiki.org/cgi-bin/wiki/FireFox
+;;
+;; If you mostly use MozEx to edit Wikipedia articles, it might be
+;; worthwhile to tell Emacs to enter wikipedia-mode whenever it is
+;; called by MozEx. Just add this to your `user-init-file':
+;;
+;; (add-to-list 'auto-mode-alist '("mozex.\\.*" . wikipedia-mode))
+
+;; Recall: you have to click on edit (either edit article or edit
+;; section), then use mouse3 (or shift f10), then select
+;; mozex, then edit textarea: Edit-->mouse3-->mozex-->Edit
+;; Textarea. After editing, you have to _click_ on the
+;; text in the browser otherwise Mozilla will ignore your
+;; typing.
+
+;;}}}
+
+;;{{{ NEWS
+
+
+;; NEWS
+;; ==================================
+;; (1) Font setting has changed.
+;; (2) Some makeup formats have been added: italics, bold, strong
+;; emphasise, links.
+;; (3) outline-cycle from Carsten Dominiks outline-magic has been
+;; added.
+;; (4) "Draft", "send" and "reply" (for discussion pages)
+;; abilities 'based' on ideas of John Wigleys remember.el: see
+;; the functions wikipedia-draft-*
+;; RATIONALE: This comes handy in 2 situations
+;; 1. You are editing articles which various authors (this I
+;; think is the usual case), you then want not to submit
+;; your edit immediately but want to copy it somewhere and
+;; to continue later. You can use the following functions
+;; for doing that:
+;; wikipedia-draft-buffer \C-c\C-b
+;; wikipedia-draft-region \C-c\C-r
+;; then the buffer/region will be appended to the
+;; wikipedia-draft-data-file (default is
+;; "~/Wiki/discussions/draft.wiki", which you can visit via
+;; wikipedia-draft-view-draft) and it will be
+;; surrounded by the ^L marks in order to set a page.
+;; moreover on top on that a section header == will be
+;; inserted, which consists of the Word Draft, a subject
+;; you are asked for and a date stamp.
+;;
+;; Another possibility consists in using the function
+;; wikipedia-draft, bound to \C-c \C-m then a new buffer
+;; will opened already in wikipedia mode. You edit and then
+;; either can send the content of the buffer to the
+;; wikipedia-draft-data-file in the same manner as
+;; described above using the function
+;; wikipedia-draft-buffer (bound to \C-c\C-k)
+;;
+;; BACK: In order to copy/send the content of temporary
+;; buffer or of a page in the wikipedia-draft-data-file
+;; back in to your wikipedia file, use the function
+;; `wikipedia-send-to-mozex'. You
+;; will be asked to which buffer to copy your text!
+;;
+;;
+;; 2. You want to reply in a discussion page to a specific
+;; contribution, you can use either the function
+;;
+;; \\[wikipedia-reply-at-point-simple] bound to [(meta shift r)]
+;; which inserts a newline, a hline, and the signature of
+;; the author. Or can use
+;; \\[wikipedia-draft-reply] bound [(meta r)]
+;; which does the same as wikipedia-reply-at-point-simple
+;; but in a temporary draft buffer.
+;;
+;; BACK: In order to copy/send the content of that buffer
+;; back in to your wikipedia file, use the function
+;; \\[wikipedia-send-to-mozex] bound to "\C-c\C-c". You
+;; will be asked to which buffer to copy your text! If
+;; you want a copy to be send to your draft file, use
+;; the variable wikipedia-draft-send-archive
+;;
+
+;;}}}
+
+;;{{{ NEW FUNCTIONS AND VARIABLES
+
+
+;; VERSION 0.4
+;;==================
+;; NEW FUNCTIONS
+;; ------------------
+;; wikipedia-insert-enumerate
+;; wikipedia-insert-itemize
+;; wikipedia-insert-strong-emphasis (renamed to wikipedia-insert-bold-italic)
+;; wikipedia-insert-bold
+;; wikipedia-insert-italics
+;; wikipedia-insert-header
+;; wikipedia-insert-link-wiki
+;; wikipedia-turn-on-outline-minor-mode
+;; wikipedia-insert-signature
+;; wikipedia-insert-hline
+;; wikipedia-unfill-paragraph-or-region
+;; wikipedia-start-paragraph
+;; wikipedia-hardlines
+;; wikipedia-outline-magic-keys
+;; wikipedia-enhance-indent
+;; wikipedia-yank-prefix
+;; wikipedia-simple-outline-promote
+;; wikipedia-simple-outline-demote
+;; wikipedia-next-long-line
+;; wikipedia-unfill-paragraph
+;; wikipedia-rename-buffer
+;; wikipedia-draft
+;; wikipedia-draft-buffer-desc
+;; wikipedia-draft-append-to-file
+;; wikipedia-draft-page
+;; wikipedia-draft-region (&optional beg end)
+;; wikipedia-draft-buffer
+;; wikipedia-draft-clipboard
+;; wikipedia-draft-mode
+;; wikipedia-draft-view-draft
+;; wikipedia-mark-section
+;; wikipedia-activate-region
+;; wikipedia-copy-page-to-register
+;; wikipedia-insert-page-to-register
+;; wikipedia-send-to-mozex (target-buffer)
+;; wikipedia-reply-at-point-simple
+;; wikipedia-draft-reply
+;; wikipedia-insert-quotation-with-signature
+;; wikipedia-insert-quotation
+
+;; NEW VARIABLES
+;;---------------------
+;; wikipedia-enumerate-with-terminate-paragraph
+;; wikipedia-draft-buffer "*Wikipedia-Draft*"
+;; wikipedia-draft-mode-map
+;; wikipedia-draft-mode-hook
+;; wikipedia-draft-register ?R
+;; wikipedia-draft-filter-functions
+;; wikipedia-draft-handler-functions '(wikipedia-draft-append-to-file)
+;; wikipedia-draft-data-file "~/Wiki/discussions/draft.wiki"
+;; wikipedia-draft-leader-text "== "
+;; wikipedia-draft-page ?S
+;; wikipedia-draft-send-archive
+;; wikipedia-reply-with-quote
+
+
+;; VERSION 0.5
+;;====================================
+;; NEW FUNCTIONS
+;; ------------------------------------
+;; wikipedia-insert-audio
+;; wikipedia-insert-image
+;; wikipedia-insert-link-www (renamed to wikipedia-insert-link-external)
+;; wikipedia-insert-user
+;; wikipedia-mark-signature
+;; wikipedia-outline-cycle
+;; wikipedia-reply-at-signature
+;; wikipedia-terminate-paragraph-and-indent
+;; wikipedia-yank-prefix
+
+;; NEW VARIABLES (defvar, defcustom, defconst)
+;; ----------------------
+;; wikipedia-reply-with-hline
+;; wikipedia-user-simplify-signature
+;; wikipedia-english-or-german
+;; wikipedia-draft-reply-register ?M
+;; wikipedia-mode-version
+
+;; VERSION 0.51
+;;====================================
+;;
+;; - Now requires Emacs 22 or higher.
+;; - Cleaned the code in various ways.
+;; - Removed wikipedia-english-or-german
+;; - Removed some private stuff
+;; - Simplified some key bindings.
+;; - Changed some key bindings to those used in org-mode.
+;; - Added wikipedia-lang etc
+;; - Added support for templates
+;; - Adjusted header end after inserting heading/promoting/demoting
+;; - Removed some functions that are already supported by outline.el
+;; - Changed wikipedia-mode menus
+;; - Added support for bullets and numbering
+
+;;}}}
+
+;;{{{ TODO
+
+;; Todo
+;; ----
+
+
+;; * Implement TeX highlighting in <math> environment
+;; * Implement (La)TeX input syntax, following the ideas of CDlatex.el
+;; * Make outline-cycle work correctly
+;; * wikipedia-reply-at-point-simple should use regexp!
+
+;;}}}
+
+
+
+;;; Code:
+
+(require 'org)
+
+(defconst wikipedia-mode-version (concat "0." (substring "$Revision: 1.5 $" 13 14))
+ "$Id: wikipedia-mode.el,v 1.5 2006/05/30 15:16:45 oub Exp oub $
+
+Report bugs to: Uwe Brauer oub at mat.ucm.es")
+
+;;{{{ LANGS
+
+;; (defvar wikipedia-english-or-german t
+;; "*Variable in order to set the english (t) or german (nil) environment.")
+
+(require 'tutorial) ;; for lang strings
+
+(defvar wikipedia-lang "English")
+
+(defvar wikipedia-langs-added nil)
+;;(defconst xlang-strings nil)
+
+(unless wikipedia-langs-added
+ (defun add-lang-strings (lang new-strings)
+ (let ((lang-rec (assoc lang lang-strings)))
+ (if lang-rec
+ (dolist (str new-strings)
+ (nconc (cdr lang-rec) (list str)))
+ (setq lang-rec (cons lang new-strings))
+ (add-to-list 'lang-strings lang-rec))))
+
+ (add-lang-strings "English"
+ '(
+ (wikip-username-prompt . "Name of user: ")
+ (wikip-image-mark . "[[Image:")
+ (wikip-media-mark . "[[Media:")
+ (wikip-utc . "(UTC)")
+ (wikip-user-mark . "[[User:")
+ ))
+ (add-lang-strings "Deutsch"
+ '(
+ (wikip-username-prompt . "Name des Benutzers: ")
+ (wikip-image-mark . "[[Bild:")
+ (wikip-media-mark . "[[Bild:")
+ (wikip-utc . "(CET)")
+ (wikip-user-mark . "[[Benutzer:")
+ ))
+ (setq wikipedia-langs-added t))
+
+;;}}}
+
+;;{{{ TAGS
+
+(defvar wikipedia-simple-tags
+ '("b" "big" "blockquote" "br" "caption" "code" "center" "cite" "del"
+ "dfn" "dl" "em" "i" "ins" "kbd" "math" "nowiki" "ol" "pre" "samp"
+ "small" "strike" "strong" "sub" "sup" "tt" "u" "ul" "var")
+ "Tags that do not accept arguments.")
+
+(defvar wikipedia-complex-tags
+ '("a" "div" "font" "table" "td" "th" "tr")
+ "Tags that accept arguments.")
+
+(defvar wikipedia-url-protocols
+ '("ftp" "gopher" "http" "https" "mailto" "news")
+ "Valid protocols for URLs in Wikipedia articles.")
+
+;;}}}
+
+;;{{{ FACES
+
+(defvar font-wikipedia-sedate-face 'font-wikipedia-sedate-face
+ "Face to use for Wikipedia minor keywords.")
+
+(defvar font-wikipedia-italic-face 'font-wikipedia-italic-face
+ "Face to use for Wikipedia italics.")
+(defvar font-wikipedia-bold-face 'font-wikipedia-bold-face
+ "Face to use for Wikipedia bolds.")
+(defvar font-wikipedia-math-face 'font-wikipedia-math-face
+ "Face to use for Wikipedia math environments.")
+(defvar font-wikipedia-string-face 'font-wikipedia-string-face
+ "Face to use for strings. This is set by Font Wikipedia.")
+(defvar font-wikipedia-verbatim-face 'font-wikipedia-verbatim-face
+ "Face to use for text in verbatim macros or environments.")
+
+
+
+
+(defface font-wikipedia-bold-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit bold))
+ ((assq :weight custom-face-attributes) '(:weight bold))
+ (t '(:bold t)))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "DarkOliveGreen" ,@font))
+ (((class color) (background dark))
+ (:foreground "OliveDrab" ,@font))
+ (t (,@font))))
+ "Face used to highlight text to be typeset in bold."
+ :group 'font-wikipedia-highlighting-faces)
+
+(defface font-wikipedia-italic-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit italic))
+ ((assq :slant custom-face-attributes) '(:slant italic))
+ (t '(:italic t)))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "DarkOliveGreen" ,@font))
+ (((class color) (background dark))
+ (:foreground "OliveDrab" ,@font))
+ (t (,@font))))
+ "Face used to highlight text to be typeset in italic."
+ :group 'font-wikipedia-highlighting-faces)
+
+(defface font-wikipedia-math-face
+ (let ((font (cond ((assq :inherit custom-face-attributes)
+ '(:inherit underline))
+ (t '(:underline t)))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "SaddleBrown"))
+ (((class color) (background dark))
+ (:foreground "burlywood"))
+ (t (,@font))))
+ "Face used to highlight math."
+ :group 'font-wikipedia-highlighting-faces)
+
+(defface font-wikipedia-sedate-face
+ '((((class grayscale) (background light)) (:foreground "DimGray"))
+ (((class grayscale) (background dark)) (:foreground "LightGray"))
+ (((class color) (background light)) (:foreground "DimGray"))
+ (((class color) (background dark)) (:foreground "LightGray"))
+;;;(t (:underline t))
+ )
+ "Face used to highlight sedate stuff."
+ :group 'font-wikipedia-highlighting-faces)
+
+(defface font-wikipedia-string-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit italic))
+ ((assq :slant custom-face-attributes) '(:slant italic))
+ (t '(:italic t)))))
+ `((((type tty) (class color))
+ (:foreground "green"))
+ (((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "RosyBrown"))
+ (((class color) (background dark))
+ (:foreground "LightSalmon"))
+ (t (,@font))))
+ "Face used to highlight strings."
+ :group 'font-wikipedia-highlighting-faces)
+
+(defface font-wikipedia-warning-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit bold))
+ ((assq :weight custom-face-attributes) '(:weight bold))
+ (t '(:bold t)))))
+ `((((class grayscale)(background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale)(background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color)(background light))
+ (:foreground "red" ,@font))
+ (((class color)(background dark))
+ (:foreground "red" ,@font))
+ (t (,@font))))
+ "Face for important keywords."
+ :group 'font-wikipedia-highlighting-faces)
+
+(defface font-wikipedia-verbatim-face
+ (let ((font (if (and (assq :inherit custom-face-attributes)
+ (if (featurep 'xemacs)
+ (find-face 'fixed-pitch)
+ (facep 'fixed-pitch)))
+ '(:inherit fixed-pitch)
+ '(:family "courier"))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "SaddleBrown" ,@font))
+ (((class color) (background dark))
+ (:foreground "burlywood" ,@font))
+ (t (,@font))))
+ "Face used to highlight TeX verbatim environments."
+ :group 'font-wikipedia-highlighting-faces)
+
+
+(defvar wikipedia-font-lock-keywords
+ (list
+
+ ;; Apostrophe-style text markup
+ (cons "''''\\([^']\\|[^']'\\)*?\\(''''\\|\n\n\\)"
+ 'font-lock-builtin-face)
+ (cons "'''\\([^']\\|[^']'\\)*?\\('''\\|\n\n\\)"
+ ; 'font-lock-builtin-face)
+ 'font-wikipedia-bold-face)
+ (cons "''\\([^']\\|[^']'\\)*?\\(''\\|\n\n\\)"
+ 'font-wikipedia-italic-face)
+
+ ;; Headers and dividers
+ (list "^\\(==+\\)\\(.*\\)\\(\\1\\)"
+ '(1 font-lock-builtin-face)
+ ; '(2 wikipedia-header-face)
+ '(2 font-wikipedia-sedate-face)
+ '(3 font-lock-builtin-face))
+ (cons "^-----*" 'font-lock-builtin-face)
+
+ ;; Bare URLs and ISBNs
+ (cons (concat "\\(^\\| \\)" (regexp-opt wikipedia-url-protocols t)
+ "://[-A-Za-z0-9._\/~%+&#?!=()@]+")
+ 'font-lock-variable-name-face)
+ (cons "\\(^\\| \\)ISBN [-0-9A-Z]+" 'font-lock-variable-name-face)
+
+ ;; Colon indentation, lists, definitions, and tables
+ (cons "^\\(:+\\|[*#]+\\||[}-]?\\|{|\\)" 'font-lock-builtin-face)
+
+ (list "^\\(;\\)\\([^:\n]*\\)\\(:?\\)"
+ '(1 font-lock-builtin-face)
+ '(2 font-lock-keyword-face)
+ '(3 font-lock-builtin-face))
+
+
+
+ ;; Tags and comments
+
+ (list (concat "\\(</?\\)"
+ (regexp-opt wikipedia-simple-tags t) "\\(>\\)")
+ '(1 font-lock-builtin-face t t)
+ '(2 font-lock-function-name-face t t)
+ '(3 font-lock-builtin-face t t))
+ (list (concat "\\(</?\\)"
+ (regexp-opt wikipedia-complex-tags t)
+ "\\(\\(?: \\(?:[^\"'/><]\\|\"[^\"]*\"\\|'[^']*'\\)*\\)?\\)\\(>\\)")
+ '(1 font-lock-builtin-face t t)
+ '(2 font-lock-function-name-face t t)
+ '(3 font-lock-keyword-face t t)
+ '(4 font-lock-builtin-face t t))
+ (cons (concat "<!-- \\([^->]\\|>\\|-\\([^-]\\|-[^>]\\)\\)*-->")
+ '(0 font-lock-comment-face t t))
+
+
+
+ ;; External Links
+
+ (list (concat "\\(\\[\\)\\(\\(?:"
+ (regexp-opt wikipedia-url-protocols)
+ "\\)://[-A-Za-z0-9._\/~%-+&#?!=()@]+\\)\\(\\(?: [^]\n]*\\)?\\)\\(\\]\\)")
+ '(1 font-lock-builtin-face t t)
+ '(2 font-lock-variable-name-face t t)
+ '(3 font-lock-keyword-face t t)
+ '(4 font-lock-builtin-face t t))
+
+
+
+
+ ;; Wiki links
+ '("\\(\\[\\[\\)\\([^]\n|]*\\)\\(|?\\)\\([^]\n]*\\)\\(\\]\\]\\)"
+ (1 font-lock-builtin-face t t)
+ (2 font-lock-variable-name-face t t)
+ (3 font-lock-builtin-face t t)
+ (4 font-lock-keyword-face t t)
+ (5 font-lock-builtin-face t t))
+
+ ;; Wiki variables
+ '("\\({{\\)\\(.+?\\)\\(}}\\)"
+ (1 font-lock-builtin-face t t)
+ (2 font-lock-variable-name-face t t)
+ (3 font-lock-builtin-face t t))
+
+ ;; Character entity references
+ (cons "&#?[a-zA-Z0-9]+;" '(0 font-lock-type-face t t))
+
+ ;; Preformatted text
+ (cons "^ .*$" '(0 font-lock-constant-face t t))
+
+ ;; Math environment (uniform highlight only, no TeX markup)
+ (list "<math>\\(\\(\n?.\\)*\\)</math>"
+ '(1 font-lock-keyword-face t t))))
+
+ ; )
+
+;;}}}
+
+;;{{{ Menu and header stuff
+
+(defvar wikipedia-imenu-generic-expression
+ ;;(list '(nil "^==+ *\\(.*[^\n=]\\)==+" 1))
+ (list '(nil "^=+ *\\(.*[^\n=]\\)=+" 1))
+ "Imenu expression for `wikipedia-mode'. See `imenu-generic-expression'.")
+
+;; (defun wikipedia-next-header ()
+;; "Move point to the end of the next section header."
+;; (interactive)
+;; (let ((oldpoint (point)))
+;; (end-of-line)
+;; (if (re-search-forward "\\(^==+\\).*\\1" (point-max) t)
+;; (beginning-of-line)
+;; (goto-char oldpoint)
+;; (message "No section headers after point."))))
+
+;; (defun wikipedia-prev-header ()
+;; "Move point to the start of the previous section header."
+;; (interactive)
+;; (unless (re-search-backward "\\(^==+\\).*\\1" (point-min) t)
+;; (message "No section headers before point.")))
+
+;;}}}
+
+;;{{{ Paragraph terminate and filling stuff (Chong)
+
+(defun wikipedia-terminate-paragraph () ;Version:1.58
+ "New list item or paragraph.
+In a list, start a new list item. In a paragraph, start a new
+paragraph.
+
+If the current paragraph is colon indented, the new paragraph
+will be indented in the same way."
+ (interactive)
+ (let (indent-chars)
+ (save-excursion
+ (beginning-of-line)
+ (while (cond ((looking-at "^$") nil)
+ ((looking-at "^\\(\\(?: \\|:+\\|[#*]+\\) *\\)")
+ (setq indent-chars (match-string 1)) nil)
+ ((eq (point) (point-min)) nil)
+ ((progn (forward-line -1) t)))
+ t))
+ (newline) (if (not indent-chars) (newline)
+ (insert indent-chars))))
+
+(defun wikipedia-terminate-paragraph-and-indent ()
+ "New list item or paragraph, ignore *,#.
+In a list, start a new list item. In a paragraph, start a new
+paragraph but *,# will be ignored.
+
+If the current paragraph is colon ; indented, the new paragraph
+will be indented in the same way."
+ (interactive)
+ (let (indent-chars)
+ (save-excursion
+ (beginning-of-line)
+ (while (cond ((looking-at "^$") nil)
+ ((looking-at "^\\(\\(?: \\|:+\\) *\\)")
+ (setq indent-chars (match-string 1)) nil)
+ ((eq (point) (point-min)) nil)
+ ((progn (forward-line -1) t)))
+ t))
+ (newline) (if (not indent-chars) (newline)
+ (insert indent-chars))))
+
+
+(defun wikipedia-link-fill-nobreak-p ()
+ "Function for `fill-nobreak-predicate'.
+When filling, don't break the line for preformatted (fixed-width)
+text or inside a Wiki link."
+ (save-excursion
+ (let ((pos (point)))
+ (or (eq (char-after (line-beginning-position)) ? )
+ (if (re-search-backward "\\[\\[" (line-beginning-position) t)
+ ;; Break if the link is really really long.
+ ;; You often get this with captioned images.
+ (null (or (> (- pos (point)) fill-column)
+ (re-search-forward "\\]\\]" pos t))))))))
+
+(defun wikipedia-fill-article ()
+ "Fill the entire article."
+ (interactive)
+ (save-excursion
+ (fill-region (point-min) (point-max))))
+
+(defun wikipedia-unfill-article ()
+ "Unfill article.
+Undo filling, deleting stand-alone newlines (newlines that do not
+end paragraphs, list entries, etc.)"
+ (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward ".\\(\n\\)\\([^# *;:|!\n]\\|----\\)" nil t)
+ (replace-match " " nil nil nil 1)))
+ (message "Stand-alone newlines deleted"))
+
+
+(defun wikipedia-unfill-paragraph-with-newline (&optional justifyp)
+ (interactive "P")
+ (let ((before (point))) ;Version:1.3
+ (save-excursion
+ (forward-paragraph)
+ (or (bolp) (newline 1))
+ (let ((end (point))
+ (start (progn (backward-paragraph) (point))))
+ (goto-char before)
+ (while (re-search-forward ".\\(\n\\)\\([^# *;:|!\n]\\|----\\)" nil t)
+ (replace-match " " nil nil nil 1))))))
+ ; (message "Stand-alone newlines IN PARAGRAPH deleted"))
+
+(defun wikipedia-unfill-region ()
+ "Unfill region.
+Undo filling, deleting stand-alone newlines (newlines that do not
+end paragraphs, list entries, etc.) see also the function
+\\[wikipedia-unfill-paragraph-or-region] and the even simpler
+function \\[wikipedia-unfill-paragraph-simple]."
+ (interactive)
+ (save-excursion
+ (narrow-to-region (point) (mark))
+ (goto-char (point-min))
+ (while (re-search-forward ".\\(\n\\)\\([^# *;:|!\n]\\|----\\)" nil t)
+ (replace-match " " nil nil nil 1)))
+ (message "Stand-alone newlines deleted")
+ (widen))
+
+;;}}}
+
+;;{{{ Main function wikipedia mode (using define-derived mode)
+
+;;{{{ KEY SETTING
+;; (defvar wikipedia-outline-map
+;; (let ((map (make-sparse-keymap)))
+;; (define-key map [(down)] 'outline-next-visible-heading)
+;; (define-key map [(up)] 'outline-previous-visible-heading)
+;; (define-key map "n" 'outline-next-visible-heading)
+;; (define-key map "p" 'outline-previous-visible-heading)
+;; (define-key map "f" 'outline-forward-same-level)
+;; (define-key map "b" 'outline-backward-same-level)
+;; (define-key map "u" 'outline-up-heading)
+;; (define-key map "/" 'org-occur)
+;; (define-key map "\C-c\C-n" 'outline-next-visible-heading)
+;; (define-key map "\C-c\C-p" 'outline-previous-visible-heading)
+;; (define-key map "\C-c\C-f" 'outline-forward-same-level)
+;; (define-key map "\C-c\C-b" 'outline-backward-same-level)
+;; (define-key map "\C-c\C-u" 'outline-up-heading)
+;; map))
+
+
+(defvar wikipedia-mode-map
+ (let ((map (make-sparse-keymap)))
+ ;;(define-key map "\M-n" 'wikipedia-next-header)
+ (define-key map "\C-c\C-n" 'wikipedia-next-long-line)
+ ;; (define-key map "\M-p" 'wikipedia-prev-header)
+ ;; (define-key map [(meta down)] 'wikipedia-next-header)
+ ;; (define-key map [(meta up)] 'wikipedia-prev-header)
+ (define-key map "\C-j" 'wikipedia-terminate-paragraph)
+ ;;(define-key map "RET" 'wikipedia-newline)
+ (define-key map [(shift return)] 'wikipedia-newline)
+
+ ;;(define-key mm [separator-format] '("--"))
+;; (define-key mm [outline]
+;; '("Toggle Outline Mode..." . outline-minor-mode))
+ ;;(define-key mm [separator-edit-structure] '("--"))
+
+
+ ;; Use some mnemonic
+ ;;(define-key map "\C-c\C-q" 'wikipedia-unfill-article)
+ (define-key map "\C-c\M-qua" 'wikipedia-unfill-article)
+ ;;(define-key map "\C-c\M-q" 'wikipedia-fill-article)
+ (define-key map "\C-c\M-qfa" 'wikipedia-fill-article)
+ ;;(define-key map "\M-u" 'wikipedia-unfill-paragraph-or-region)
+ (define-key map "\C-c\M-qur" 'wikipedia-unfill-paragraph-or-region)
+ ;;(define-key map "\C-c\C-u" 'wikipedia-unfill-paragraph-simple)
+ (define-key map "\C-c\M-qup" 'wikipedia-unfill-paragraph-simple)
+
+ (define-key map "\C-c\C-fs" 'wikipedia-insert-bold-italic)
+ (define-key map "\C-c\C-fb" 'wikipedia-insert-bold) ;Version:1.3
+ (define-key map "\C-c\C-fi" 'wikipedia-insert-italics)
+ (define-key map "\C-c\C-fn" 'wikipedia-insert-nowiki)
+
+ (define-key map "\C-c\C-ts" 'wikipedia-insert-signature)
+ (define-key map "\C-c\C-tt" 'wikipedia-insert-template)
+ (define-key map "\C-c\C-tu" 'wikipedia-insert-user)
+ ;;(define-key map "\C-c\C-fq" 'wikipedia-insert-quotation)
+ ;;(define-key map "\C-c\C-fh" 'wikipedia-insert-header)
+ (define-key map "\C-c\C-fr" 'wikipedia-insert-hline) ;Version:1.30
+ (define-key map "\C-c\C-li" 'wikipedia-insert-link-wiki)
+ (define-key map "\C-c\C-le" 'wikipedia-insert-link-external)
+
+ ;; Breaks key binding conventions:
+ ;;(define-key map [(meta f7)] 'wikipedia-draft)
+ ;;(define-key map [(meta f8)] 'wikipedia-reply-at-point-simple)
+ ;;(define-key map [(meta f9)] 'wikipedia-draft-view-draft)
+
+ (define-key map "\C-c\C-r" 'wikipedia-reply-at-point-simple)
+
+ ;; Breaks key binding conventions:
+ ;;(define-key map "\C-cr" 'wikipedia-draft-region)
+
+ (define-key map [(meta r)] 'wikipedia-draft-reply)
+ (define-key map "\C-c\C-m" 'wikipedia-draft) ;Version:1.25
+ (define-key map "\C-c\C-b" 'wikipedia-draft-region)
+ (define-key map "\C-c\C-d" 'wikipedia-draft-buffer)
+ (define-key map "\C-c\C-k" 'wikipedia-draft-buffer)
+ (define-key map "\C-c\C-p" 'wikipedia-draft-copy-page-to-register) ;Version:1.39
+ ;; (define-key map "\C-c\C-c" 'wikipedia-draft-send-to-mozex)
+ (define-key map "\C-c\C-s" 'wikipedia-draft-yank-page-to-register)
+
+ (define-key map [(control meta prior)] 'wikipedia-enhance-indent)
+ (define-key map [(control meta next)] 'wikipedia-yank-prefix)
+ (define-key map [(meta return)] 'wikipedia-insert-enumerate)
+ (define-key map [(meta control return)] 'wikipedia-insert-enumerate-nonewline)
+ ;; private setting
+ ;; This is bound to C-j by default:
+ ;;(define-key map [(shift return)] 'newline-and-indent) ;Version:1.24
+ (define-key map "\C-\\" 'wikipedia-insert-itemize) ;Version:1.28
+ (define-key map [(control return)] 'wikipedia-insert-itemize)
+
+ ;; The next three breaks Emacs key binding conventions, are they really necessary?
+ ;;(define-key map "\C-ca" 'auto-capitalize-mode)
+ ;;(define-key map "\C-ci" 'set-input-method)
+ ;;(define-key map "\C-ct" 'toggle-input-method) ;Version:1.23
+
+ (define-key map [(shift tab)] 'org-shifttab)
+ (define-key map [backtab] 'org-shifttab)
+ (define-key map [tab] 'org-cycle)
+
+ map))
+
+(defvar wikipedia-org-menu nil)
+;; From org.el:
+(easy-menu-define wikipedia-org-menu wikipedia-mode-map "Wikipedia menu"
+ '("Wikipedia"
+ ("Show/Hide"
+ ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
+ ["Cycle Global Visibility" org-shifttab]
+ ["Sparse Tree" org-occur t]
+ ["Reveal Context" org-reveal t]
+ ["Show All" show-all t]
+ "--"
+ ["Subtree to indirect buffer" org-tree-to-indirect-buffer t])
+ "--"
+ ["New Heading" outline-insert-heading t]
+ ("Navigate Headings"
+ ["Up" outline-up-heading t]
+ ["Next" outline-next-visible-heading t]
+ ["Previous" outline-previous-visible-heading t]
+ ["Next Same Level" outline-forward-same-level t]
+ ["Previous Same Level" outline-backward-same-level t]
+ "--"
+ ["Jump" org-goto t])
+ ("Edit Structure"
+ ["Move Subtree Up" outline-move-subtree-up]
+ ["Move Subtree Down" outline-move-subtree-down]
+ "--"
+ ["Copy Subtree" org-copy-special]
+ ["Cut Subtree" org-cut-special]
+ ["Paste Subtree" org-paste-special]
+ "--"
+ ["Promote Heading" wikipedia-simple-outline-promote]
+ ["Promote Subtree" outline-promote]
+ ["Demote Heading" wikipedia-simple-outline-demote]
+ ["Demote Subtree" outline-demote])
+ ("Filling"
+ ["Unfill article" wikipedia-unfill-article]
+ ["Fill article" wikipedia-fill-article])
+ "--"
+ ("Format"
+ ["Horizontal line" wikipedia-insert-hline]
+ "--"
+ ["Indent Paragraph" wikipedia-indent-paragraph]
+ ["Deindent Paragraph" wikipedia-deindent-paragraph]
+ "--"
+ ["Insert No Wiki Formatting" wikipedia-insert-nowiki]
+ ["Bold-Italic" wikipedia-insert-bold-italic]
+ ["Italic" wikipedia-insert-italics]
+ ["Bold" wikipedia-insert-bold]
+ "--"
+ ("Insert"
+ ("Templates"
+ ["Site Specific Template" wikipedia-insert-template]
+ ["Signature" wikipedia-insert-signature]
+ )
+ ("Links"
+ ["External Link" wikipedia-insert-link-external]
+ ["Internal Wiki Link" wikipedia-insert-link-wiki]
+ )
+ ("Bullets and numbering"
+ ["Bullet" wikipedia-insert-bullet]
+ ["Numbering" wikipedia-insert-numbering]
+ )
+ ))
+ ))
+;;}}}
+
+
+;;;###autoload
+;;{{{ Main function wikipedia-mode
+
+(define-derived-mode wikipedia-mode outline-mode "Wikipedia"
+ "Major mode for editing wikimedia style wikis.
+Major mode for editing articles written in the markup language
+used by Wikipedia, the free on-line
+encyclopedia (see URL `http://www.wikipedia.org').
+
+There are several ways to use wikipedia-mode:
+
+- You can simply cut and paste articles between Emacs and your
+ web browser's text box.
+- If you are using Firefox you can use the It's All Text add-on
+ for Firefox.
+- You can use MozEx, a Mozilla/Firefox web browser extension that
+ allows you to call Emacs from a text
+ box (see URL `http://mozex.mozdev.org/').
+- Another way is to use the PERL script ee-helper, which allows
+ you to up and download wiki texts.
+
+Wikipedia articles are usually unfilled: newline characters are not
+used for breaking paragraphs into lines. Unfortunately, Emacs does not
+handle word wrapping yet. As a workaround, wikipedia-mode turns on
+longlines-mode automatically. In case something goes wrong, the
+following commands may come in handy:
+
+\\[wikipedia-fill-article] fills the buffer.
+\\[wikipedia-unfill-article] unfills the buffer.
+Be warned that function can be dead slow, better use wikipedia-unfill-paragraph-or-region.
+\\[wikipedia-unfill-paragraph-or-region] unfills the paragraph
+\\[wikipedia-unfill-paragraph-simple] doehe same but simpler.
+
+
+
+The following commands put in markup structures.
+
+\\[wikipedia-insert-bold-italic] bold+italic
+\\[wikipedia-insert-bold] bold text
+\\[wikipedia-insert-italics] italics
+\\[wikipedia-insert-nowiki] no wiki markup
+\\[wikipedia-insert-link-wiki] inserts a link
+
+The following commands are also defined:
+\\[wikipedia-insert-user] inserts user name
+\\[wikipedia-insert-signature] inserts ~~~~
+\\[wikipedia-insert-enumerate] inserts enumerate type structures
+\\[wikipedia-insert-itemize] inserts itemize type structures
+\\[wikipedia-insert-hline] inserts a hline
+
+The draft functionality
+\\[wikipedia-draft]
+\\[wikipedia-draft-region]
+\\[wikipedia-draft-view-draft]
+\\[wikipedia-draft-page]
+\\[wikipedia-draft-buffer]
+
+Replying and sending functionality
+\\[wikipedia-reply-at-point-simple]
+\\[wikipedia-draft-reply]
+
+
+The register functionality
+\\[wikipedia-copy-page-to-register]
+\\[defun wikipedia-insert-page-to-register]
+
+
+Some simple editing commands.
+\\[wikipedia-enhance-indent]
+\\[wikipedia-yank-prefix]
+\\[wikipedia-unfill-paragraph-or-region]
+
+
+
+\\[wikipedia-terminate-paragraph] starts a new list item or paragraph in a context-aware manner."
+
+ (set (make-local-variable 'adaptive-fill-regexp) "[ ]*")
+ (set (make-local-variable 'comment-start-skip) "\\(?:<!\\)?-- *")
+ (set (make-local-variable 'comment-end-skip) " *--\\([ \n]*>\\)?")
+ (set (make-local-variable 'comment-start) "<!-- ")
+ (set (make-local-variable 'comment-end) " -->")
+ (set (make-local-variable 'paragraph-start)
+ "\\*\\| \\|#\\|;\\|:\\||\\|!\\|$")
+ (set (make-local-variable 'sentence-end-double-space) nil)
+ (set (make-local-variable 'font-lock-multiline) t)
+ (set (make-local-variable 'font-lock-defaults)
+ '(wikipedia-font-lock-keywords t nil nil nil))
+ (set (make-local-variable 'fill-nobreak-predicate)
+ 'wikipedia-link-fill-nobreak-p)
+ (set (make-local-variable 'auto-fill-inhibit-regexp) "^[ *#:|;]")
+
+ ;; Support for outline-minor-mode. No key conflicts, so we'll use
+ ;; the normal outline-mode prefix.
+ ;;(set (make-local-variable 'outline-regexp) "==+")
+ (set (make-local-variable 'outline-regexp) "=+")
+ ;;(set (make-local-variable 'outline-heading-end-regexp) "=+") ;; For betting fixing
+ ;; (set (make-local-variable 'outline-regexp) "=+")
+ ;; (set (make-local-variable 'outline-regexp) ":")
+
+ ;; Fix-me: Why change this?? Should not the user do this globally instead?
+ ;;(set (make-local-variable 'outline-minor-mode-prefix) "\C-c\C-o")
+
+ ;; Fix-mde For longlines-mode??:
+ (set (make-local-variable 'auto-fill-inhibit-regexp) "^[ *#:|;]")
+
+ ;: From org.el:
+ ;; Get rid of Outline menus, they are not needed
+ ;; Need to do this here because define-derived-mode sets up
+ ;; the keymap so late. Still, it is a waste to call this each time
+ ;; we switch another buffer into org-mode.
+ (if (featurep 'xemacs)
+ (when (boundp 'outline-mode-menu-heading)
+ ;; Assume this is Greg's port, it used easymenu
+ (easy-menu-remove outline-mode-menu-heading)
+ (easy-menu-remove outline-mode-menu-show)
+ (easy-menu-remove outline-mode-menu-hide))
+ (define-key wikipedia-mode-map [menu-bar headings] 'undefined)
+ (define-key wikipedia-mode-map [menu-bar hide] 'undefined)
+ (define-key wikipedia-mode-map [menu-bar show] 'undefined))
+
+ (easy-menu-add wikipedia-org-menu)
+
+ ;; Turn on the Imenu automatically.
+;; (when menu-bar-mode
+;; (set (make-local-variable 'imenu-generic-expression)
+;; wikipedia-imenu-generic-expression)
+;; (imenu-add-to-menubar "TOC"))
+
+ (modify-syntax-entry ?< "(>" wikipedia-mode-syntax-table)
+ (modify-syntax-entry ?> ")<" wikipedia-mode-syntax-table)
+
+ ;;}}}
+
+ ;;; This is the wrong way to do it, see add-hook:
+ ;; (make-local-variable 'change-major-mode-hook)
+
+ ;; Check if our version of outline.el has the new header hooks:
+ (require 'outline)
+ (when (boundp 'outline-demote-hook)
+ (add-hook 'outline-demote-hook 'wikipedia-outline-insert-heading-f nil t)
+ (add-hook 'outline-promote-hook 'wikipedia-outline-insert-heading-f nil t)
+ (add-hook 'outline-insert-heading-hook 'wikipedia-outline-insert-heading-f nil t)
+ )
+ )
+
+(defun wikipedia-outline-insert-heading-f ()
+ (insert " ")
+ (backward-char)
+ (wikipedia-adjust-header-end))
+
+;; wikipedia-mode ends here
+;;}}}
+
+;;{{{ longlines-mode
+
+(defun wikipedia-turn-on-longlines () ;Version:1.58
+ "Turn on longlines-mode if it is defined."
+ (if (functionp 'longlines-mode)
+ (longlines-mode 1)))
+
+(defcustom wikipedia-use-longlines-mode nil
+ "Turn on longlines-mode' if non-nil.
+Unfortunately there are some bugs in `longlines-mode' so turning
+it on is an option currently."
+ :type 'boolean
+ :set (lambda (sym val)
+ (set-default sym val)
+ (if val
+ (add-hook 'wikipedia-mode-hook 'wikipedia-turn-on-longlines)
+ (remove-hook 'wikipedia-mode-hook 'wikipedia-turn-on-longlines)))
+ :group 'wikipedia)
+
+;;}}}
+
+;; New formating stuff for inserting simple formating structures such
+
+;;{{{ Insert makeup and templates
+
+(defvar wikipedia-enumerate-with-terminate-paragraph nil
+ "*Before insert enumerate/itemize do \\[wikipedia-terminate-paragraph].")
+
+(defun wikipedia-region-active-p ()
+ (or (and (boundp 'zmacs-region-active-p) zmacs-region-active-p)
+ (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)))
+
+(defun wikipedia-insert-around-region (before after)
+ (if (wikipedia-region-active-p)
+ (save-excursion
+ (let ((beginning (region-beginning))
+ (end (region-end))
+ (check (= (string-to-char before) ?')))
+ ;; When we are inserting ' do not mix them:
+ (if (or (not check)
+ (not (memq ?'
+ (append (buffer-substring-no-properties
+ beginning end) nil))))
+ (progn
+ (goto-char end)
+ (insert after)
+ (goto-char beginning)
+ (insert before))
+ (message "Sorry, the region already contains the char '.")
+ )))
+ (insert before)
+ (insert after)
+ (backward-char (length after))))
+
+(defun wikipedia-insert-enumerate ()
+ "Insert enumerated items.
+Format depends on `wikipedia-enumerate-with-terminate-paragraph'.
+Note however that `wikipedia-terminate-paragraph' does not work
+very well will longlines-mode."
+ (interactive)
+ (if wikipedia-enumerate-with-terminate-paragraph
+ (progn
+ (wikipedia-terminate-paragraph)
+ (insert "#"))
+ (newline nil)
+ (insert ":#")))
+
+
+
+
+
+(defun wikipedia-insert-itemize ()
+ "Insert not enumerated items.
+Format depends on `wikipedia-enumerate-with-terminate-paragraph'.
+Note however that the `wikipedia-terminate-paragraph' does not
+work very well will longlines-mode."
+ (interactive)
+ (if wikipedia-enumerate-with-terminate-paragraph
+ (progn
+ (wikipedia-terminate-paragraph)
+ (insert "*"))
+ (newline nil)
+ (insert ":*")))
+
+
+(defun wikipedia-insert-bold-italic ()
+ "Insert strong emphasis.
+Uses four apostrophes (e.g. ''''FOO''''.) When mark is active, surrounds region."
+ (interactive)
+ (wikipedia-insert-around-region "''''" "''''"))
+
+
+(defun wikipedia-insert-bold ()
+ "Insert bold.
+Uses three apostrophes (e.g. '''FOO'''.) When mark is active,
+surrounds region."
+ (interactive)
+ (wikipedia-insert-around-region "'''" "'''"))
+
+
+(defun wikipedia-insert-italics ()
+ "Insert italics.
+Uses two apostrophes (e.g. ''FOO''.) When mark is active,
+surrounds region."
+ (interactive)
+ (wikipedia-insert-around-region "''" "''"))
+
+(defun wikipedia-indent-paragraph ()
+ (interactive)
+ (backward-paragraph)
+ )
+(defun wikipedia-deindent-paragraph ()
+ (interactive)
+ )
+;;}}}
+;;{{{ Templates
+
+;; http://en.wikipedia.org/wiki/Template:Quotation
+;; http://en.wikipedia.org/wiki/Help:A_quick_guide_to_templates
+(defvar wikipedia-site nil)
+(make-variable-buffer-local 'wikipedia-site)
+(defvar wikipedia-site-history nil)
+
+(defcustom wikipedia-templates nil
+ "Templates for different wikis."
+ :type '(repeat (list
+ (string :tag "Wiki site")
+ (repeat
+ (list
+ (string :tag "Template name")
+ (string :tag "Template code")))))
+ :group 'wikipedia)
+
+(defun wikipedia-insert-template ()
+ "Prompts for a template and inserts it."
+ (interactive)
+ (let* ((t-name-code (wikipedia-get-template))
+ (t-name (car t-name-code))
+ ;; Ask how to insert:
+ (choices '("Evaluate when page is created"
+ "Substitute when saving this source page"
+ "Show template when page is fetched"
+ "Insert template itself"))
+ (hist (copy-sequence choices))
+ (default (car choices))
+ (choice (completing-read
+ "How do you want to insert the template? "
+ choices
+ nil
+ t
+ default
+ (cons 'hist 1))))
+;; (lwarn 't :warning "t-name=%s" t-name)
+;; (lwarn 't :warning "choice=%s" choice)
+;; (lwarn 't :warning "0=%s" (nth 0 choices))
+;; (lwarn 't :warning "1=%s" (nth 1 choices))
+;; (lwarn 't :warning "2=%s" (nth 2 choices))
+ (cond
+ ((string= choice (nth 0 choices))
+ ;;(lwarn 't :warning "evaluate=>%s" (concat "{{" t-name "}}"))
+ (insert "{{" t-name "}}")
+ )
+ ((string= choice (nth 1 choices))
+ ;;(lwarn 't :warning "subst=>%s" (concat "{{subst:" t-name "}}"))
+ (insert "{{subst:" t-name "}}")
+ )
+ ((string= choice (nth 2 choices))
+ ;;(lwarn 't :warning "raw=>%s" (concat "{{msgnw:" t-name "}}"))
+ (insert "{{msgnw:" t-name "}}")
+ )
+ ((string= choice (nth 3 choices))
+ (insert (cdr t-name-code))
+ ))))
+
+(defun wikipedia-get-template ()
+ (let* ((sites (mapcar (lambda (t-sites)
+ (car t-sites))
+ wikipedia-templates))
+ (hist (copy-sequence sites))
+ (default-site wikipedia-site)
+ (histpos (if (not default-site)
+ 1
+ (catch 'pos
+ (let ((n 0))
+ (dolist (elt sites)
+ (setq n (1+ n))
+ (when (string= default-site elt)
+ (throw 'pos n)))))))
+ (site (if (= 1 (length sites))
+ (car sites)
+ (completing-read "Wiki site: "
+ sites
+ nil
+ t
+ default-site
+ (cons 'hist histpos))))
+ (s-t (assoc site wikipedia-templates))
+ (templates (car (cdr s-t)))
+ (t-names (mapcar (lambda (t-for-site)
+ ;;(lwarn 't :warning "t-for-site=%s" t-for-site)
+ (car t-for-site))
+ templates))
+ (t-name (wikipedia-get-template-name site templates))
+ (code (car (cdr (assoc t-name templates))))
+ )
+ (setq wikipedia-site site)
+;; (lwarn 't :warning "site=%s" site)
+;; (lwarn 't :warning "s-t=%s" s-t)
+;; (lwarn 't :warning "templates=%s" templates)
+;; (lwarn 't :warning "t-names=%s" t-names)
+;; (lwarn 't :warning "t-name=%s" t-name)
+;; (lwarn 't :warning "code=%s" code)
+ (cons t-name code)))
+
+(defun wikipedia-get-template-name (site templates)
+ ""
+ (let* ((prompt "Template: ")
+ (minibuffer-local-must-match-map (copy-keymap minibuffer-local-must-match-map))
+ (hist (mapcar (lambda (elt)
+ (car elt))
+ templates))
+ (desc-fun (lambda ()
+ (let ((s (minibuffer-contents-no-properties)))
+ (when (< 0 (length s))
+ (wikipedia-describe-template s site templates)))))
+ (up-fun (lambda () (interactive)
+ (previous-history-element 1)
+ (funcall desc-fun)))
+ (down-fun (lambda () (interactive)
+ (next-history-element 1)
+ (funcall desc-fun)))
+ (default nil)
+ (histpos (if (not default) 1))
+ (default-name (if default
+ default
+ (car (nth (1- histpos) templates))))
+ (tpl-name nil)
+ )
+ (define-key minibuffer-local-must-match-map [up] up-fun)
+ (define-key minibuffer-local-must-match-map [down] down-fun)
+ (save-window-excursion
+ (wikipedia-describe-template default-name site templates)
+ (setq tpl-name (completing-read prompt
+ templates
+ nil ; predicate
+ t ; require-match
+ default-name ;; initial-input
+ (cons 'hist histpos) ;; hist
+ )))
+ (when (= 0 (length tpl-name))
+ (error "No template name given"))
+ (let ((tpl (assoc tpl-name templates)))
+ (unless tpl
+ (error "There is no template named %s for site %s" tpl-name site))
+ ;;(lwarn 't :warning "tpl=%s" tpl)
+ )
+ tpl-name))
+
+(defun wikipedia-describe-template (name site templates)
+ (let ((tpl-rec (assoc name templates)))
+ (with-output-to-temp-buffer (help-buffer)
+ (with-current-buffer (help-buffer)
+ (help-setup-xref (list #'wikipedia-describe-template name site templates) (interactive-p))
+ (let ((inhibit-read-only t)
+ start end
+ here
+ (tpl (assoc name templates)))
+ ;;(insert (format "%S\n\n" family))
+ (insert (format "%s - a wiki template for site %s" name site))
+ (insert "\n\n")
+ (setq start (point))
+ (insert (cadr tpl))
+ (setq end (point))
+ (with-no-warnings (print-help-return-message))
+ ;;(put-text-property start end 'face 'highlight)
+ (goto-char start)
+ (setq here (point))
+ (while (re-search-forward "\\(?:<onlyinclude>\\|</onlyinclude>\\|<noinclude>.*</noinclude>\\)" end t)
+ (put-text-property here (match-beginning 0) 'face 'highlight)
+ (setq here (point))
+ )
+ (put-text-property (point) end 'face 'highlight)
+ )))))
+
+(defun wikipedia-insert-nowiki ()
+ "Mark the region as 'nowiki'.
+When mark is active, surrounds region."
+ (interactive)
+ (wikipedia-insert-around-region "<nowiki>" "</nowiki>"))
+
+
+
+(defun wikipedia-insert-user ()
+ "Prompt for a user name, insert [[User:foo]]"
+ (interactive)
+ (let ((user (read-string (get-lang-string wikipedia-lang 'wikip-username-prompt)))
+ (user-mark (get-lang-string wikipedia-lang 'wikip-user-mark)))
+ (insert (concat user-mark user "|" user "]]"))))
+
+(defun wikipedia-insert-signature () ;Version:1.4
+ "Insert \"~~~~\".
+This will be shown as your user identity when showing the page."
+ (interactive)
+ (insert "~~~~"))
+
+
+
+(defun wikipedia-insert-reply-prefix () ;Version:1.60
+ "Quotation box of the form {{Quotation}}{{}}. When mark is active,
+surrounds region."
+ (interactive)
+ (beginning-of-line 1)
+ (search-forward "[[")
+ (backward-char 2)
+ (mark-sexp 1)
+ (copy-to-register wikipedia-draft-reply-register (region-beginning) (region-end) nil)
+ (end-of-line 1)
+ (wikipedia-terminate-paragraph)
+ (beginning-of-line 1)
+ (kill-line nil)
+ (insert "----")
+ (newline 1)
+ (yank)
+ (insert ":'''Re: ")
+ (insert-register wikipedia-draft-reply-register 1)
+ (insert "''' ")
+ (end-of-line 1))
+
+;; (defun wikipedia-insert-header ()
+;; "Insert subheader via == (e.g. == FOO ==.)"
+;; (interactive)
+;; (unless (bolp)
+;; (beginning-of-line))
+;; (insert "== ")
+;; (end-of-line)
+;; (insert " ==")
+;; (backward-char 3))
+
+(defvar wikipedia-link-wiki-history nil)
+
+(defun wikipedia-insert-link-wiki ()
+ "Insert link via [[ (e.g. [[FOO]].) When mark is active, surround region."
+ (interactive)
+ (if (wikipedia-region-active-p)
+ (wikipedia-insert-around-region "[[" "]]")
+ (let* ((link (read-string "Wiki link: " nil wikipedia-link-wiki-history))
+ (name (read-string "Name (optional): ")))
+ (insert "[[" link)
+ (when (< 0 (length name))
+ (insert "|" name))
+ (insert "]]"))))
+
+(defun wikipedia-insert-link-external ()
+ "Insert link via [[ (e.g. [http://FOO].) When mark is active, surround region."
+ (interactive)
+ (if (wikipedia-region-active-p)
+ (wikipedia-insert-around-region "[" "]")
+ (let* ((choices '("Plain" "Footnote" "Named"))
+ (hist (copy-sequence choices))
+ (style (completing-read
+ "Link style: " ; prompt
+ choices ; collection
+ nil ; predicate
+ t ; requite-match
+ "Plain" ; initial-input
+ (cons 'hist 1) ; hist
+ ))
+ (url (read-string "URL: "))
+ name)
+ ;;(lwarn 't :warning "style=%s" style)
+ (cond
+ ((string= style "Plain")
+ (insert url))
+ ((string= style "Footnote")
+ (insert "[" url "]"))
+ ((string= style "Named")
+ (let ((name (read-string "Link name: ")))
+ (insert "[" url)
+ (when (< 0 (length name))
+ (insert " " name))
+ (insert "]")))
+ (t
+ (error "Internal error, bad style=%s" style))))))
+
+
+(defun wikipedia-insert-image ()
+ "Insert link image, e.g. [[Image:FOO]].
+When mark is active, surround region."
+ (interactive)
+ (let ((img-mark (get-lang-string wikipedia-lang 'wikip-image-mark)))
+ (wikipedia-insert-around-region img-mark "]]")))
+
+(defun wikipedia-insert-audio ()
+ "Insert audio link, e.g. [[Media:FOO]].
+When mark is active, surround region."
+ (interactive)
+ (let ((aud-mark (get-lang-string wikipedia-lang 'wikip-audio-mark)))
+ (wikipedia-insert-around-region aud-mark "]]")))
+
+
+
+
+;; (defun wikipedia-turn-on-outline-minor-mode ()
+;; "Turn on outline minor mode."
+;; ;;(interactive)
+;; (outline-minor-mode nil))
+
+
+
+
+
+
+(defun wikipedia-insert-hline () ;Version:1.29
+ "Insert \"----\" "
+ (interactive)
+ (end-of-line)
+ (insert hard-newline "----" hard-newline))
+
+(defun wikipedia-newline (&optional arg)
+ "Insert newline and check for bullets and numbering."
+ (interactive "*P")
+ (let ((here (point))
+ (line-type nil))
+ (beginning-of-line)
+ (when (eq ?* (char-after))
+ (setq line-type 'bullet))
+ (when (eq ?# (char-after))
+ (setq line-type 'numbered))
+ (if (and line-type
+ (looking-at ".\\s-*$"))
+ (progn
+ (delete-region (match-beginning 0) (match-end 0))
+ (newline arg))
+ (goto-char here)
+ (newline arg)
+ (cond
+ ((eq line-type 'bullet)
+ (insert "* "))
+ ((eq line-type 'numbered)
+ (insert "# "))))))
+
+;;}}}
+
+;;{{{ bullets and numbering
+
+;; Fix-me: Seems like this and my newline stuff already was there ... ;-)
+(defun wikipedia-insert-bullet ()
+ "Insert a bullet."
+ (interactive)
+ (end-of-line)
+ (newline)
+ (insert "* "))
+
+(defun wikipedia-insert-numbering ()
+ "Insert numbering."
+ (interactive)
+ (end-of-line)
+ (newline)
+ (insert "# "))
+
+;;}}}
+
+;;{{{ filling and longline
+
+(defun wikipedia-unfill-paragraph-or-region () ;Version:1.7
+ "Unfill region.
+This function does NOT explicitly search for \"soft newlines\" as
+does wikipedia-unfill-region."
+ (interactive)
+ (when use-hard-newlines
+ ;; (backward-paragraph 1)
+ ;; (next-line 1)
+ (beginning-of-line 1)
+ (set-fill-prefix)
+ ;; Fix-me: The use of make-local-variable here looks incorrect,
+ ;; use lexical binding instead:
+;; (set (make-local-variable 'use-hard-newlines) nil)
+;; (set (make-local-variable 'sentence-end-double-space) t)
+;; (set (make-local-variable 'paragraph-start) "[   \n ]")
+ (let ((use-hard-newlines nil)
+ (sentence-end-double-space t)
+ (paragraph-start nil))
+ (when (featurep 'xemacs)
+ (let ((fill-column (point-max)))
+ (fill-paragraph-or-region nil)))
+ (unless (featurep 'xemacs)
+ (let ((fill-column (point-max)))
+ (fill-paragraph nil)))))
+;; (set (make-local-variable 'use-hard-newlines) t)
+;; (set (make-local-variable 'sentence-end-double-space) nil)
+;; (set (make-local-variable 'paragraph-start) "\\*\\| \\|#\\|;\\|:\\||\\|!\\|$"))
+ (unless use-hard-newlines
+ ;; (backward-paragraph 1)
+ ;; (next-line 1)
+ (beginning-of-line 1)
+ (set-fill-prefix)
+;; (set (make-local-variable 'sentence-end-double-space) t)
+;; (set (make-local-variable 'paragraph-start)
+ (let ((sentence-end-double-space t)
+ (paragraph-start nil))
+ (when (featurep 'xemacs)
+ (let ((fill-column (point-max)))
+ (fill-paragraph-or-region nil)))
+ (unless (featurep 'xemacs)
+ (let ((fill-column (point-max)))
+ (fill-paragraph nil))))
+;; (set (make-local-variable 'sentence-end-double-space) nil)
+;; (set (make-local-variable 'paragraph-start) "\\*\\| \\|#\\|;\\|:\\||\\|!\\|$")
+ ))
+
+
+
+
+;; (defun wikipedia-start-paragraph ()
+;; (interactive)
+;; (set (make-local-variable 'paragraph-start)
+;; "\\*\\| \\|#\\|;\\|:\\||\\|!\\|$"))
+
+;; Use function use-hard-newlines instead:
+;; (defun wikipedia-hardlines ()
+;; "Set use-hard-newlines to NIL."
+;; (interactive)
+;; (setq use-hard-newlines nil))
+
+;; from emacs wiki
+(defun wikipedia-next-long-line ()
+ "Move forward to the next long line with column-width greater
+ than `fill-column'.
+
+ TODO: When function reaches end of buffer, save-excursion to
+ starting point.
+ Generalise to make `previous-long-line'."
+ (interactive)
+ ;; global-variable: fill-column
+ (if (= (forward-line) 0)
+ (let ((line-length
+ (save-excursion
+ (end-of-line)
+ (current-column))))
+ (if (<= line-length fill-column)
+ (wikipedia-next-long-line)
+ (message "Long line found")))
+ ;; Stop, end of buffer reached.
+ (error "Long line not found")))
+
+
+(defun wikipedia-unfill-paragraph-simple ()
+ "A very simple function for unfilling a paragraph."
+ (interactive)
+ (if (functionp 'filladapt-mode)
+ (filladapt-mode nil))
+ (let ((fill-column (point-max)))
+ (fill-paragraph nil)
+ (if (functionp 'filladapt-mode)
+ (filladapt-mode nil))))
+
+;;}}}
+
+;;{{{ outline and outline-magic stuff
+
+;;(add-hook 'wikipedia-mode-hook 'wikipedia-turn-on-outline-minor-mode)
+;;(remove-hook 'wikipedia-mode-hook 'wikipedia-turn-on-outline-minor-mode)
+
+(defun wikipedia-outline-cycle ()
+ (interactive)
+ (if (functionp 'outline-cycle)
+ (outline-cycle)))
+
+;; Fix-me: Unfortunately outline maybe does not take care of the
+;; heading endings when promoting and demoting (I have submitted a bug
+;; report for this and hooks will be added). To work around this we
+;; defadvice outline-demote/promote:
+
+(require 'outline)
+(unless (boundp 'outline-demote-hook)
+
+ (defadvice outline-demote (after wikipedia-outline-demote-advice
+ (&optional which))
+ "Adjust heading after demote."
+ (unless which
+ (wikipedia-adjust-header-end)))
+
+ (defadvice outline-promote (after wikipedia-outline-promote-advice
+ (&optional which))
+ "Adjust heading after promote."
+ (unless which
+ (wikipedia-adjust-header-end)))
+
+ (defadvice outline-insert-heading (after wikipedia-outline-insert-heading-advice
+ ())
+ "Adjust heading after insert new heading."
+ (wikipedia-adjust-header-end))
+
+ )
+
+(defun wikipedia-adjust-header-end ()
+ (when (eq major-mode 'wikipedia-mode)
+ (let ((here (point))
+ (end-pos (line-end-position))
+ bgn-mark
+ bgn-len
+ end-mark
+ end-len
+ )
+ (beginning-of-line)
+ (when (looking-at outline-regexp)
+ (setq bgn-mark (match-string-no-properties 0))
+ (setq bgn-len (length bgn-mark))
+ (end-of-line)
+ (if (looking-back outline-regexp nil t)
+ (when (progn
+ (setq end-mark (match-string-no-properties 0))
+ (setq end-len (length end-mark))
+ (/= end-len bgn-len))
+ (replace-match bgn-mark))
+ (insert bgn-mark)))
+ ;;(lwarn 't :warning "bgn-len=%s, end-len=%s" bgn-len end-len)
+ (goto-char here))))
+
+
+
+;;(add-hook 'outline-minor-mode-hook 'wikipedia-outline-magic-keys)
+(add-hook 'wikipedia-mode-hook 'wikipedia-outline-magic-keys)
+
+(defun wikipedia-outline-magic-keys ()
+ (interactive)
+ (unless (featurep 'xemacs)
+ (local-set-key [(shift iso-lefttab)] 'wikipedia-outline-cycle))
+ (local-set-key [iso-left-tab] 'wikipedia-outline-cycle)
+ ;;(local-set-key [(meta left)] 'outline-promote)
+ (local-set-key [(meta shift left)] 'outline-promote)
+ ;;(local-set-key [(meta right)] 'outline-demote)
+ (local-set-key [(meta shift right)] 'outline-demote)
+ ;;(local-set-key [(control left)] 'wikipedia-simple-outline-promote)
+ (local-set-key [(meta left)] 'wikipedia-simple-outline-promote)
+ ;;(local-set-key [(control right)] 'wikipedia-simple-outline-demote)
+ (local-set-key [(meta right)] 'wikipedia-simple-outline-demote)
+ (local-set-key [(shift return)] 'newline-and-indent)
+ ;;(local-set-key [(control up)] 'outline-move-subtree-up)
+ (local-set-key [(meta shift up)] 'outline-move-subtree-up)
+ ;;(local-set-key [(control down)] 'outline-move-subtree-down))
+ (local-set-key [(meta shift down)] 'outline-move-subtree-down))
+
+(defun wikipedia-enhance-indent () ;Version:1.26
+ (interactive)
+ (string-rectangle (region-beginning) (region-end) ":"))
+
+(defun wikipedia-yank-prefix () ;Version:1.26
+ (interactive)
+ (string-rectangle (region-beginning) (region-end) ":"))
+
+;; modification for outline-magic
+
+(defun wikipedia-simple-outline-promote ()
+ "Function simple deletes \"=\" and the end and the beginning of line,
+does not promote the whole tree!"
+ (interactive)
+ (save-excursion
+ (progn
+ (beginning-of-line 1)
+ (search-forward "=")
+ (delete-char 1 nil)
+ (end-of-line 1)
+ (search-backward "=")
+ (delete-char 1 nil))))
+
+(defun wikipedia-simple-outline-demote ()
+ "Function simple adds \"=\" and the end and the beginning of line,
+does not promote the whole tree!"
+ (interactive)
+ (save-excursion
+ (progn
+ (beginning-of-line 1)
+ (search-forward "=")
+ (insert "=")
+ (end-of-line 1)
+ (search-backward "=")
+ (insert "="))))
+
+
+(defun wikipedia-rename-buffer () ;Version:1.5
+ "Make sure that the option UNIQUE is used."
+ (interactive)
+ (rename-buffer (read-string "Name of new buffer (unique): " ) 1))
+
+;;}}}
+
+;;{{{ wikipedia drafts functionality: `stolen' from remember.el:
+
+(defgroup wikipedia-draft nil
+ "A mode to wikipedia-draft information."
+ :group 'data)
+
+;;; User Variables:
+
+(defcustom wikipedia-draft-mode-hook nil
+ "*Functions run upon entering wikipedia-draft-mode."
+ :type 'hook
+ :group 'wikipedia-draft)
+
+(defcustom wikipedia-draft-register ?R
+ "The register in which the window configuration is stored."
+ :type 'character
+ :group 'wikipedia-draft)
+
+(defcustom wikipedia-draft-filter-functions nil
+ "*Functions run to filter wikipedia-draft data.
+All functions are run in the wikipedia-draft buffer."
+ :type 'hook
+ :group 'wikipedia-draft)
+
+(defcustom wikipedia-draft-handler-functions '(wikipedia-draft-append-to-file)
+ "*Functions run to process wikipedia-draft data.
+Each function is called with the current buffer narrowed to what the
+user wants wikipedia-drafted.
+If any function returns non-nil, the data is assumed to have been
+recorded somewhere by that function. "
+ :type 'hook
+ :group 'wikipedia-draft)
+
+(defcustom wikipedia-draft-data-file "~/Wiki/discussions/draft.wiki"
+ "*The file in which to store the wikipedia drafts."
+ :type 'file
+ :group 'wikipedia-draft)
+
+(defcustom wikipedia-draft-reply-register ?M
+ "The register in which the window configuration is stored."
+ :type 'character
+ :group 'wikipedia-draft)
+
+(defcustom wikipedia-draft-page ?S ;Version:1.37
+ "The register in which the a page of the wiki draft file is stored."
+ :type 'character
+ :group 'wikipedia-draft)
+
+
+(defcustom wikipedia-draft-leader-text "== "
+ "*The text used to begin each wikipedia-draft item."
+ :type 'string
+ :group 'wikipedia-draft)
+
+
+;;; Internal Variables:
+
+(defvar wikipedia-draft-buffer "*Wikipedia-Draft*"
+ "The name of the wikipedia-draft (temporary) data entry buffer.")
+
+;;; User Functions:
+
+;;;###autoload
+(defun wikipedia-draft ()
+ "Open a temporary buffer in wikipedia mode for editing an
+ wikipedia draft, which an arbitrary piece of data. After
+ finishing the editing either use \\[wikipedia-draft-buffer] to
+ send the data into the wikipedia-draft-data-file, or send the
+ buffer using `wikipedia-draft-send-to-mozex' and insert it later
+ into a wikipedia article."
+ (interactive)
+ (window-configuration-to-register wikipedia-draft-register)
+ (let ((buf (get-buffer-create wikipedia-draft-buffer)))
+ (switch-to-buffer-other-window buf)
+ (wikipedia-mode)
+ (message " C-c C-k sends to draft file, C-c C-c sends to org buffer.")))
+
+
+
+
+
+(defsubst wikipedia-draft-time-to-seconds (time)
+ "Convert TIME to a floating point number."
+ (+ (* (car time) 65536.0)
+ (cadr time)
+ (/ (or (car (cdr (cdr time))) 0) 1000000.0)))
+
+(defsubst wikipedia-draft-mail-date (&optional rfc822-p)
+ "Return a simple date. Nothing fancy."
+ (if rfc822-p
+ (format-time-string "%a, %e %b %Y %T %z" (current-time))
+ (format-time-string "%c" (current-time))))
+
+(defun wikipedia-draft-buffer-desc ()
+ "Using the first line of the current buffer, create a short description."
+ (buffer-substring (point-min)
+ (save-excursion
+ (goto-char (point-min))
+ (end-of-line)
+ (if (> (- (point) (point-min)) 60)
+ (goto-char (+ (point-min) 60)))
+ (point))))
+
+
+;; Wikipedia-Drafting to plain files:
+
+
+(defun wikipedia-draft-append-to-file ()
+ "Add a header together with a subject to the text and add it to the
+draft file. It might be better if longlines-mode is off."
+ (let ((text (buffer-string))
+ (desc (wikipedia-draft-buffer-desc)))
+ (with-temp-buffer
+ (insert "\n\n")
+ (insert wikipedia-draft-leader-text)
+ (insert "Draft: ") ;Version:1.39
+ (insert (read-string "Enter Subject: "))
+ (insert " ")
+ (insert (current-time-string))
+ (insert " ")
+ (insert wikipedia-draft-leader-text)
+ (insert "\n\n") ;Version:1.27
+ (insert " ")
+ (insert "\n\n")
+ (insert text)
+ (insert "\n")
+ (insert " ")
+ (insert "\n")
+ (if (not (bolp))
+ (insert "\n\n"))
+ (if (find-buffer-visiting wikipedia-draft-data-file)
+ (let ((wikipedia-draft-text (buffer-string)))
+ (set-buffer (get-file-buffer wikipedia-draft-data-file))
+ (save-excursion
+ (goto-char (point-max))
+ (insert "\n")
+ (insert wikipedia-draft-text)
+ (insert "\n")
+ (save-buffer)))
+ (append-to-file (point-min) (point-max) wikipedia-draft-data-file)))))
+
+
+(setq wikipedia-draft-handler-functions 'wikipedia-draft-append-to-file)
+
+
+(custom-add-option 'wikipedia-draft-handler-functions 'wikipedia-draft-append-to-file)
+
+;;;###autoload
+(defun wikipedia-draft-page () ;Version:1.32
+ (interactive)
+ (mark-page)
+ (copy-region-as-kill (region-beginning) (region-end))
+ (wikipedia-draft)
+ (yank nil))
+
+
+(defun wikipedia-draft-region (&optional beg end)
+ "Wikipedia-Draft the data from BEG to END.
+If called from within the wikipedia-draft buffer, BEG and END are ignored,
+and the entire buffer will be wikipedia-drafted. If called from any other
+buffer, that region, plus any context information specific to that
+region, will be wikipedia-drafted."
+ (interactive)
+ (let ((b (or beg (min (point) (or (mark) (point-min)))))
+ (e (or end (max (point) (or (mark) (point-max))))))
+ (save-restriction
+ (narrow-to-region b e)
+ (run-hook-with-args-until-success 'wikipedia-draft-handler-functions)
+ (when (equal wikipedia-draft-buffer (buffer-name))
+ (kill-buffer (current-buffer))
+ (jump-to-register wikipedia-draft-register)))))
+
+;;
+;;;###autoload
+(defun wikipedia-draft-buffer ()
+ "Wikipedia-draft-buffer sends the contents of the current (temporary)
+buffer to the wikipedia-draft-buffer, see the variable
+wikipedia-draft-data-file."
+ (interactive)
+ (wikipedia-draft-region (point-min) (point-max)))
+
+(defun wikipedia-draft-clipboard ()
+ "Wikipedia-Draft the contents of the current clipboard.
+Most useful for wikipedia-drafting things from Netscape or other X Windows
+application."
+ (interactive)
+ (with-temp-buffer
+ (insert (x-get-clipboard))
+ (run-hook-with-args-until-success 'wikipedia-draft-handler-functions)))
+
+;;;###autoload
+
+
+;;; Internal Functions:
+(defvar wikipedia-draft-send-archive t ;Version:1.56
+ "*Archive the reply.")
+
+(defvar wikipedia-draft-mode-map
+ (let ((m (make-sparse-keymap)))
+ (define-key m "\C-c\C-k" 'wikipedia-draft-buffer)
+ (define-key m "\C-c\C-d" 'wikipedia-draft-buffer)
+ m))
+
+(defun wikipedia-draft-mode ()
+ "Major mode for output from \\[wikipedia-draft].
+\\<wikipedia-draft-mode-map> This buffer is used to collect data that
+you want wikipedia-draft. Just hit \\[wikipedia-draft-region] when
+you're done entering, and it will go ahead and file the data for
+latter retrieval, and possible indexing.
+\\{wikipedia-draft-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (indented-text-mode)
+ (use-local-map wikipedia-draft-mode-map)
+ (setq major-mode 'wikipedia-draft-mode
+ mode-name "Wikipedia-Draft")
+ (run-hooks 'wikipedia-draft-mode-hook))
+
+
+(defun wikipedia-draft-view-draft ()
+ (interactive)
+ "Simple shortcut to visit the file, which contains the wikipedia drafts."
+ (find-file wikipedia-draft-data-file))
+
+;;}}}
+
+;;{{{ functions for marking regions
+
+(defun wikipedia-mark-section () ;Version:1.36
+ "Set mark at end of current logical section, and point at top."
+ (interactive)
+ (re-search-forward (concat "== " "[a-z,A-z \t]*"
+ " =="))
+ (re-search-backward "^")
+ (set-mark (point))
+ (re-search-backward (concat "== " "[a-z,A-z \t]*"
+ " "))
+ (wikipedia-activate-region))
+
+(defun wikipedia-mark-signature () ;Version:1.36
+ "Set mark at end of current logical section, and point at top."
+ (interactive)
+ (re-search-forward "]]") ;;[[ ]]
+ (re-search-backward "^")
+ (set-mark (point))
+ (re-search-backward "[[")
+ (wikipedia-activate-region))
+
+(when (featurep 'xemacs)
+ (fset 'wikipedia-activate-region (symbol-function 'zmacs-activate-region)))
+
+(unless (featurep 'xemacs)
+ (defun wikipedia-activate-region ()
+ nil))
+
+;;}}}
+
+;;{{{ `reply' and `send' functions
+
+(defun wikipedia-draft-copy-page-to-register () ;Version:1.47
+ "Copy a page via the wikipedia-draft-register."
+ (interactive)
+ (save-excursion
+ (narrow-to-page nil)
+ (copy-to-register wikipedia-draft-page (point-min) (point-max) nil)
+ (message "draft page copied to wikipedia register wikipedia-draft-page.")
+ (widen)))
+
+ ;aux function
+(defun wikipedia-draft-yank-page-to-register () ;Version:1.50
+ "Insert a page via the wikipedia-draft-register."
+ (interactive)
+ (insert-register wikipedia-draft-page nil))
+
+
+
+(defun wikipedia-draft-send-to-mozex (target-buffer) ;Version:1.56
+ "Copy the current page from the wikipedia draft file to
+ TARGET-BUFFER, this buffer is named something like mozex.textarea.
+Check the variable wikipedia-draft-send-archive. If it is t, then
+additionally the text will be archived in the draft.wiki file. Check
+longlines-mode, it might be better if it is set off."
+ (interactive "bTarget buffer: ")
+ (let ((src-buf (current-buffer)))
+ (wikipedia-draft-copy-page-to-register)
+ (switch-to-buffer target-buffer)
+ (end-of-line 1)
+ (newline 1)
+ (wikipedia-draft-yank-page-to-register)
+ (message "The page has been sent (copied) to the mozex file!")
+ (switch-to-buffer "*Wikipedia-Draft*")
+ (when wikipedia-draft-send-archive ;Version:1.56
+ (let ((text (buffer-string)) ;Version:1.59
+ (desc (wikipedia-draft-buffer-desc)))
+ (with-temp-buffer
+ (insert "\n\n")
+ (insert wikipedia-draft-leader-text)
+ (insert-register wikipedia-draft-reply-register 1)
+ (insert " ")
+ (insert (current-time-string))
+ (insert " ")
+ (insert wikipedia-draft-leader-text)
+ (insert "\n\n")
+ (insert " ")
+ (insert "\n\n")
+ (insert text)
+ (insert "\n")
+ (insert " ")
+ (insert "\n")
+ (if (not (bolp))
+ (insert "\n\n"))
+ (if (find-buffer-visiting wikipedia-draft-data-file)
+ (let ((wikipedia-draft-text (buffer-string)))
+ (set-buffer (get-file-buffer wikipedia-draft-data-file))
+ (save-excursion
+ (goto-char (point-max))
+ (insert "\n")
+ (insert wikipedia-draft-text)
+ (insert "\n")
+ (save-buffer)))
+ (append-to-file (point-min) (point-max) wikipedia-draft-data-file)))))
+ (when (equal wikipedia-draft-buffer (buffer-name))
+ (kill-buffer (current-buffer)))
+ (switch-to-buffer target-buffer)))
+
+
+;;Apr_22_2006
+(defvar wikipedia-reply-with-hline nil
+ "*Whether to use a hline as a header seperator in the reply.")
+
+(defvar wikipedia-reply-with-quote nil ;Version:1.60
+ "*Whether to use a quotation tempalate or not.")
+
+(defvar wikipedia-user-simplify-signature t
+ "*Simple varible in order to threat complicated signatures of users, which uses
+fonts and other makeup.")
+
+(defun wikipedia-reply-at-signature () ;Version:1.40
+ "Very simple function to add the reply prefix to the signature,
+sorrounded by the boldface makeup. You have to set the point BEFORE
+the signature, then the functions inserts the following
+:'''Re: [[User:foo]]'''."
+ (interactive)
+ (beginning-of-line 1)
+ (search-forward "[[")
+ (mark-word 3)
+ (yank)
+ (end-of-line 1)
+ (wikipedia-terminate-paragraph)
+ (insert ":'''Re: ")
+ (insert "[[")
+ (yank)
+ (insert "]]")
+ (insert "'''"))
+
+
+
+
+(defun wikipedia-draft-reply () ;Version:1.62
+ "Open a temporary buffer in wikipedia mode for editing an wikipedia
+draft, with an arbitrary piece of data. After finishing the editing
+|]]:either use \"C-c C-k\" \\[wikipedia-draft-buffer] to send the data into
+the wikipedia-draft-data-file, or send the buffer \"C-c\C-c\",
+\\[wikipedia-draft-send-to-mozex] to the current wikipedia article via
+mozex. Check the varibale wikipedia-draft-send-archive."
+ (interactive)
+ (wikipedia-reply-at-point-simple)
+ (beginning-of-line 1)
+ (kill-line nil)
+ (save-excursion
+ (window-configuration-to-register wikipedia-draft-register)
+ (let ((buf (get-buffer-create wikipedia-draft-buffer)))
+ (switch-to-buffer-other-window buf)
+ (wikipedia-mode)
+ (if (functionp 'pabbrev-mode)
+ (pabbrev-mode))
+ (when (not wikipedia-reply-with-quote)
+ (when wikipedia-reply-with-hline
+ (insert "----")
+ (newline 1))
+ (yank)
+ (end-of-line 1))
+ (when wikipedia-reply-with-quote
+ (insert "{{Quotation|")
+ (yank)
+ (insert "'''Re: ")
+ (insert-register wikipedia-draft-reply-register 1)
+ (insert "''' |~~~~}}")
+ (backward-char 7))
+ (message " C-c C-k sends to draft, C-c C-c sends to org buffer."))))
+
+(defun wikipedia-reply-at-point-simple () ;Version:1.65
+ "Reply to posts in discussion forums.
+You have to put the region around the signature, then the
+functions inserts the following
+:'''Re: [[User:foo]]'''."
+ (interactive)
+ (beginning-of-line 1)
+ (search-forward (get-lang-string wikipedia-lang 'wikip-utc))
+ (search-backward (get-lang-string wikipedia-lang 'wikip-user-mark))
+ (when (not wikipedia-user-simplify-signature)
+ (mark-word 3))
+ (when wikipedia-user-simplify-signature
+ (mark-word 2))
+ (copy-to-register wikipedia-draft-reply-register (region-beginning) (region-end) nil)
+ (end-of-line 1)
+ (wikipedia-terminate-paragraph-and-indent)
+ (insert ":'''Re: ")
+ (insert-register wikipedia-draft-reply-register 1)
+ (when wikipedia-user-simplify-signature
+ (insert "|]]''' "))
+ (when (not wikipedia-user-simplify-signature)
+ (insert "]]''' ")))
+
+;;}}}
+
+;;{{{ Optional private stuff:
+
+;; (defun wikipedia-insert-quotation-with-signature () ;Version:1.60
+;; "Insert quotation with signature.
+;; When mark is active, surrounds region."
+;; (interactive)
+;; (wikipedia-insert-around-region "{{Quotation|" "}}{{~~~~}}"))
+
+;; (defun wikipedia-insert-quotation () ;Version:1.60
+;; "Insert quotation box.
+;; When mark is active, surrounds region."
+;; (interactive)
+;; ;; Fix-me: This uses a template, is that really always available???
+;; (wikipedia-insert-around-region "{{Quotation|" "}}"))
+
+;; (define-key wikipedia-mode-map "\C-c\C-fv" 'wikipedia-insert-bible-verse-template)
+;;
+;; (defun wikipedia-insert-bible-verse-template ()
+;; "Insert a template for the quotation of bible verses."
+;; (interactive)
+;; (insert "({{niv|")
+;; (let ((name (read-string "Name: ")))
+;; (insert (concat name "|"))
+;; (let ((verse (read-string "Verse: ")))
+;; (insert (concat verse "|" name " " verse "}})")))))
+
+;;}}}
+
+(provide 'wikipedia-mode)
+;;; wikipedia-mode.el ends here.
+
+