couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ryanram...@apache.org
Subject [07/51] [partial] Restructure to simpler jam/erica style.
Date Sat, 11 May 2013 05:48:20 GMT
http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/closetag.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/closetag.js b/src/fauxton/jam/codemirror/lib/util/closetag.js
new file mode 100644
index 0000000..5096678
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/closetag.js
@@ -0,0 +1,164 @@
+/**
+ * Tag-closer extension for CodeMirror.
+ *
+ * This extension adds a "closeTag" utility function that can be used with key bindings to 
+ * insert a matching end tag after the ">" character of a start tag has been typed.  It can
+ * also complete "</" if a matching start tag is found.  It will correctly ignore signal
+ * characters for empty tags, comments, CDATA, etc.
+ *
+ * The function depends on internal parser state to identify tags.  It is compatible with the
+ * following CodeMirror modes and will ignore all others:
+ * - htmlmixed
+ * - xml
+ *
+ * See demos/closetag.html for a usage example.
+ * 
+ * @author Nathan Williams <nathan@nlwillia.net>
+ * Contributed under the same license terms as CodeMirror.
+ */
+(function() {
+	/** Option that allows tag closing behavior to be toggled.  Default is true. */
+	CodeMirror.defaults['closeTagEnabled'] = true;
+	
+	/** Array of tag names to add indentation after the start tag for.  Default is the list of block-level html tags. */
+	CodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];
+
+	/** Array of tag names where an end tag is forbidden. */
+	CodeMirror.defaults['closeTagVoid'] = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
+
+	function innerState(cm, state) {
+		return CodeMirror.innerMode(cm.getMode(), state).state;
+	}
+
+
+	/**
+	 * Call during key processing to close tags.  Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.
+	 * - cm: The editor instance.
+	 * - ch: The character being processed.
+	 * - indent: Optional.  An array of tag names to indent when closing.  Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.
+	 *   Pass false to disable indentation.  Pass an array to override the default list of tag names.
+	 * - vd: Optional.  An array of tag names that should not be closed.  Omit to use the default void (end tag forbidden) tag list defined in the 'closeTagVoid' option.  Ignored in xml mode.
+	 */
+	CodeMirror.defineExtension("closeTag", function(cm, ch, indent, vd) {
+		if (!cm.getOption('closeTagEnabled')) {
+			throw CodeMirror.Pass;
+		}
+		
+		/*
+		 * Relevant structure of token:
+		 *
+		 * htmlmixed
+		 * 		className
+		 * 		state
+		 * 			htmlState
+		 * 				type
+		 *				tagName
+		 * 				context
+		 * 					tagName
+		 * 			mode
+		 * 
+		 * xml
+		 * 		className
+		 * 		state
+		 * 			tagName
+		 * 			type
+		 */
+		
+		var pos = cm.getCursor();
+		var tok = cm.getTokenAt(pos);
+		var state = innerState(cm, tok.state);
+
+		if (state) {
+			
+			if (ch == '>') {
+				var type = state.type;
+				
+				if (tok.className == 'tag' && type == 'closeTag') {
+					throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
+				}
+			
+				cm.replaceSelection('>'); // Mode state won't update until we finish the tag.
+				pos = {line: pos.line, ch: pos.ch + 1};
+				cm.setCursor(pos);
+		
+				tok = cm.getTokenAt(cm.getCursor());
+				state = innerState(cm, tok.state);
+				if (!state) throw CodeMirror.Pass;
+				var type = state.type;
+
+				if (tok.className == 'tag' && type != 'selfcloseTag') {
+					var tagName = state.tagName;
+					if (tagName.length > 0 && shouldClose(cm, vd, tagName)) {
+						insertEndTag(cm, indent, pos, tagName);
+					}
+					return;
+				}
+				
+				// Undo the '>' insert and allow cm to handle the key instead.
+				cm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);
+				cm.replaceSelection("");
+			
+			} else if (ch == '/') {
+				if (tok.className == 'tag' && tok.string == '<') {
+					var ctx = state.context, tagName = ctx ? ctx.tagName : '';
+					if (tagName.length > 0) {
+						completeEndTag(cm, pos, tagName);
+						return;
+					}
+				}
+			}
+		
+		}
+		
+		throw CodeMirror.Pass; // Bubble if not handled
+	});
+
+	function insertEndTag(cm, indent, pos, tagName) {
+		if (shouldIndent(cm, indent, tagName)) {
+			cm.replaceSelection('\n\n</' + tagName + '>', 'end');
+			cm.indentLine(pos.line + 1);
+			cm.indentLine(pos.line + 2);
+			cm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});
+		} else {
+			cm.replaceSelection('</' + tagName + '>');
+			cm.setCursor(pos);
+		}
+	}
+	
+	function shouldIndent(cm, indent, tagName) {
+		if (typeof indent == 'undefined' || indent == null || indent == true) {
+			indent = cm.getOption('closeTagIndent');
+		}
+		if (!indent) {
+			indent = [];
+		}
+		return indexOf(indent, tagName.toLowerCase()) != -1;
+	}
+	
+	function shouldClose(cm, vd, tagName) {
+		if (cm.getOption('mode') == 'xml') {
+			return true; // always close xml tags
+		}
+		if (typeof vd == 'undefined' || vd == null) {
+			vd = cm.getOption('closeTagVoid');
+		}
+		if (!vd) {
+			vd = [];
+		}
+		return indexOf(vd, tagName.toLowerCase()) == -1;
+	}
+	
+	// C&P from codemirror.js...would be nice if this were visible to utilities.
+	function indexOf(collection, elt) {
+		if (collection.indexOf) return collection.indexOf(elt);
+		for (var i = 0, e = collection.length; i < e; ++i)
+			if (collection[i] == elt) return i;
+		return -1;
+	}
+
+	function completeEndTag(cm, pos, tagName) {
+		cm.replaceSelection('/' + tagName + '>');
+		cm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });
+	}
+	
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/dialog.css
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/dialog.css b/src/fauxton/jam/codemirror/lib/util/dialog.css
new file mode 100644
index 0000000..8c4f847
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/dialog.css
@@ -0,0 +1,27 @@
+.CodeMirror-dialog {
+  position: relative;
+}
+
+.CodeMirror-dialog > div {
+  position: absolute;
+  top: 0; left: 0; right: 0;
+  background: white;
+  border-bottom: 1px solid #eee;
+  z-index: 15;
+  padding: .1em .8em;
+  overflow: hidden;
+  color: #333;
+}
+
+.CodeMirror-dialog input {
+  border: none;
+  outline: none;
+  background: transparent;
+  width: 20em;
+  color: inherit;
+  font-family: monospace;
+}
+
+.CodeMirror-dialog button {
+  font-size: 70%;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/dialog.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/dialog.js b/src/fauxton/jam/codemirror/lib/util/dialog.js
new file mode 100644
index 0000000..7aad7ea
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/dialog.js
@@ -0,0 +1,70 @@
+// Open simple dialogs on top of an editor. Relies on dialog.css.
+
+(function() {
+  function dialogDiv(cm, template) {
+    var wrap = cm.getWrapperElement();
+    var dialog = wrap.insertBefore(document.createElement("div"), wrap.firstChild);
+    dialog.className = "CodeMirror-dialog";
+    dialog.innerHTML = '<div>' + template + '</div>';
+    return dialog;
+  }
+
+  CodeMirror.defineExtension("openDialog", function(template, callback) {
+    var dialog = dialogDiv(this, template);
+    var closed = false, me = this;
+    function close() {
+      if (closed) return;
+      closed = true;
+      dialog.parentNode.removeChild(dialog);
+    }
+    var inp = dialog.getElementsByTagName("input")[0], button;
+    if (inp) {
+      CodeMirror.connect(inp, "keydown", function(e) {
+        if (e.keyCode == 13 || e.keyCode == 27) {
+          CodeMirror.e_stop(e);
+          close();
+          me.focus();
+          if (e.keyCode == 13) callback(inp.value);
+        }
+      });
+      inp.focus();
+      CodeMirror.connect(inp, "blur", close);
+    } else if (button = dialog.getElementsByTagName("button")[0]) {
+      CodeMirror.connect(button, "click", function() {
+        close();
+        me.focus();
+      });
+      button.focus();
+      CodeMirror.connect(button, "blur", close);
+    }
+    return close;
+  });
+
+  CodeMirror.defineExtension("openConfirm", function(template, callbacks) {
+    var dialog = dialogDiv(this, template);
+    var buttons = dialog.getElementsByTagName("button");
+    var closed = false, me = this, blurring = 1;
+    function close() {
+      if (closed) return;
+      closed = true;
+      dialog.parentNode.removeChild(dialog);
+      me.focus();
+    }
+    buttons[0].focus();
+    for (var i = 0; i < buttons.length; ++i) {
+      var b = buttons[i];
+      (function(callback) {
+        CodeMirror.connect(b, "click", function(e) {
+          CodeMirror.e_preventDefault(e);
+          close();
+          if (callback) callback(me);
+        });
+      })(callbacks[i]);
+      CodeMirror.connect(b, "blur", function() {
+        --blurring;
+        setTimeout(function() { if (blurring <= 0) close(); }, 200);
+      });
+      CodeMirror.connect(b, "focus", function() { ++blurring; });
+    }
+  });
+})();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/foldcode.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/foldcode.js b/src/fauxton/jam/codemirror/lib/util/foldcode.js
new file mode 100644
index 0000000..02cfb50
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/foldcode.js
@@ -0,0 +1,196 @@
+// the tagRangeFinder function is
+//   Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
+// released under the MIT license (../../LICENSE) like the rest of CodeMirror
+CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
+  var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
+  var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
+  var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
+
+  var lineText = cm.getLine(line);
+  var found = false;
+  var tag = null;
+  var pos = 0;
+  while (!found) {
+    pos = lineText.indexOf("<", pos);
+    if (-1 == pos) // no tag on line
+      return;
+    if (pos + 1 < lineText.length && lineText[pos + 1] == "/") { // closing tag
+      pos++;
+      continue;
+    }
+    // ok we weem to have a start tag
+    if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...
+      pos++;
+      continue;
+    }
+    var gtPos = lineText.indexOf(">", pos + 1);
+    if (-1 == gtPos) { // end of start tag not in line
+      var l = line + 1;
+      var foundGt = false;
+      var lastLine = cm.lineCount();
+      while (l < lastLine && !foundGt) {
+        var lt = cm.getLine(l);
+        var gt = lt.indexOf(">");
+        if (-1 != gt) { // found a >
+          foundGt = true;
+          var slash = lt.lastIndexOf("/", gt);
+          if (-1 != slash && slash < gt) {
+            var str = lineText.substr(slash, gt - slash + 1);
+            if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
+              if (hideEnd === true) l++;
+              return l;
+            }
+          }
+        }
+        l++;
+      }
+      found = true;
+    }
+    else {
+      var slashPos = lineText.lastIndexOf("/", gtPos);
+      if (-1 == slashPos) { // cannot be empty tag
+        found = true;
+        // don't continue
+      }
+      else { // empty tag?
+        // check if really empty tag
+        var str = lineText.substr(slashPos, gtPos - slashPos + 1);
+        if (!str.match( /\/\s*\>/ )) { // finally not empty
+          found = true;
+          // don't continue
+        }
+      }
+    }
+    if (found) {
+      var subLine = lineText.substr(pos + 1);
+      tag = subLine.match(xmlNAMERegExp);
+      if (tag) {
+        // we have an element name, wooohooo !
+        tag = tag[0];
+        // do we have the close tag on same line ???
+        if (-1 != lineText.indexOf("</" + tag + ">", pos)) // yep
+        {
+          found = false;
+        }
+        // we don't, so we have a candidate...
+      }
+      else
+        found = false;
+    }
+    if (!found)
+      pos++;
+  }
+
+  if (found) {
+    var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
+    var startTagRegExp = new RegExp(startTag, "g");
+    var endTag = "</" + tag + ">";
+    var depth = 1;
+    var l = line + 1;
+    var lastLine = cm.lineCount();
+    while (l < lastLine) {
+      lineText = cm.getLine(l);
+      var match = lineText.match(startTagRegExp);
+      if (match) {
+        for (var i = 0; i < match.length; i++) {
+          if (match[i] == endTag)
+            depth--;
+          else
+            depth++;
+          if (!depth) {
+            if (hideEnd === true) l++;
+            return l;
+          }
+        }
+      }
+      l++;
+    }
+    return;
+  }
+};
+
+CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
+  var lineText = cm.getLine(line), at = lineText.length, startChar, tokenType;
+  for (;;) {
+    var found = lineText.lastIndexOf("{", at);
+    if (found < 0) break;
+    tokenType = cm.getTokenAt({line: line, ch: found}).className;
+    if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
+    at = found - 1;
+  }
+  if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
+  var count = 1, lastLine = cm.lineCount(), end;
+  outer: for (var i = line + 1; i < lastLine; ++i) {
+    var text = cm.getLine(i), pos = 0;
+    for (;;) {
+      var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos);
+      if (nextOpen < 0) nextOpen = text.length;
+      if (nextClose < 0) nextClose = text.length;
+      pos = Math.min(nextOpen, nextClose);
+      if (pos == text.length) break;
+      if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
+        if (pos == nextOpen) ++count;
+        else if (!--count) { end = i; break outer; }
+      }
+      ++pos;
+    }
+  }
+  if (end == null || end == line + 1) return;
+  if (hideEnd === true) end++;
+  return end;
+};
+
+CodeMirror.indentRangeFinder = function(cm, line) {
+  var tabSize = cm.getOption("tabSize");
+  var myIndent = cm.getLineHandle(line).indentation(tabSize), last;
+  for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {
+    var handle = cm.getLineHandle(i);
+    if (!/^\s*$/.test(handle.text)) {
+      if (handle.indentation(tabSize) <= myIndent) break;
+      last = i;
+    }
+  }
+  if (!last) return null;
+  return last + 1;
+};
+
+CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
+  var folded = [];
+  if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
+
+  function isFolded(cm, n) {
+    for (var i = 0; i < folded.length; ++i) {
+      var start = cm.lineInfo(folded[i].start);
+      if (!start) folded.splice(i--, 1);
+      else if (start.line == n) return {pos: i, region: folded[i]};
+    }
+  }
+
+  function expand(cm, region) {
+    cm.clearMarker(region.start);
+    for (var i = 0; i < region.hidden.length; ++i)
+      cm.showLine(region.hidden[i]);
+  }
+
+  return function(cm, line) {
+    cm.operation(function() {
+      var known = isFolded(cm, line);
+      if (known) {
+        folded.splice(known.pos, 1);
+        expand(cm, known.region);
+      } else {
+        var end = rangeFinder(cm, line, hideEnd);
+        if (end == null) return;
+        var hidden = [];
+        for (var i = line + 1; i < end; ++i) {
+          var handle = cm.hideLine(i);
+          if (handle) hidden.push(handle);
+        }
+        var first = cm.setMarker(line, markText);
+        var region = {start: first, hidden: hidden};
+        cm.onDeleteLine(first, function() { expand(cm, region); });
+        folded.push(region);
+      }
+    });
+  };
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/formatting.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/formatting.js b/src/fauxton/jam/codemirror/lib/util/formatting.js
new file mode 100644
index 0000000..00ffe78
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/formatting.js
@@ -0,0 +1,196 @@
+// ============== Formatting extensions ============================
+(function() {
+  // Define extensions for a few modes
+  CodeMirror.extendMode("css", {
+    commentStart: "/*",
+    commentEnd: "*/",
+    wordWrapChars: [";", "\\{", "\\}"],
+    autoFormatLineBreaks: function (text) {
+      return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2");
+    }
+  });
+
+  function jsNonBreakableBlocks(text) {
+    var nonBreakableRegexes = [/for\s*?\((.*?)\)/,
+                               /\"(.*?)(\"|$)/,
+                               /\'(.*?)(\'|$)/,
+                               /\/\*(.*?)(\*\/|$)/,
+                               /\/\/.*/];
+    var nonBreakableBlocks = [];
+    for (var i = 0; i < nonBreakableRegexes.length; i++) {
+      var curPos = 0;
+      while (curPos < text.length) {
+        var m = text.substr(curPos).match(nonBreakableRegexes[i]);
+        if (m != null) {
+          nonBreakableBlocks.push({
+            start: curPos + m.index,
+            end: curPos + m.index + m[0].length
+          });
+          curPos += m.index + Math.max(1, m[0].length);
+        }
+        else { // No more matches
+          break;
+        }
+      }
+    }
+    nonBreakableBlocks.sort(function (a, b) {
+      return a.start - b.start;
+    });
+
+    return nonBreakableBlocks;
+  }
+
+  CodeMirror.extendMode("javascript", {
+    commentStart: "/*",
+    commentEnd: "*/",
+    wordWrapChars: [";", "\\{", "\\}"],
+
+    autoFormatLineBreaks: function (text) {
+      var curPos = 0;
+      var split = this.jsonMode ? function(str) {
+        return str.replace(/([,{])/g, "$1\n").replace(/}/g, "\n}");
+      } : function(str) {
+        return str.replace(/(;|\{|\})([^\r\n;])/g, "$1\n$2");
+      };
+      var nonBreakableBlocks = jsNonBreakableBlocks(text), res = "";
+      if (nonBreakableBlocks != null) {
+        for (var i = 0; i < nonBreakableBlocks.length; i++) {
+          if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block
+            res += split(text.substring(curPos, nonBreakableBlocks[i].start));
+            curPos = nonBreakableBlocks[i].start;
+          }
+          if (nonBreakableBlocks[i].start <= curPos
+              && nonBreakableBlocks[i].end >= curPos) { // Skip non-breakable block
+            res += text.substring(curPos, nonBreakableBlocks[i].end);
+            curPos = nonBreakableBlocks[i].end;
+          }
+        }
+        if (curPos < text.length)
+          res += split(text.substr(curPos));
+      } else {
+        res = split(text);
+      }
+      return res.replace(/^\n*|\n*$/, "");
+    }
+  });
+
+  CodeMirror.extendMode("xml", {
+    commentStart: "<!--",
+    commentEnd: "-->",
+    wordWrapChars: [">"],
+
+    autoFormatLineBreaks: function (text) {
+      var lines = text.split("\n");
+      var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)");
+      var reOpenBrackets = new RegExp("<", "g");
+      var reCloseBrackets = new RegExp("(>)([^\r\n])", "g");
+      for (var i = 0; i < lines.length; i++) {
+        var mToProcess = lines[i].match(reProcessedPortion);
+        if (mToProcess != null && mToProcess.length > 3) { // The line starts with whitespaces and ends with whitespaces
+          lines[i] = mToProcess[1]
+            + mToProcess[2].replace(reOpenBrackets, "\n$&").replace(reCloseBrackets, "$1\n$2")
+            + mToProcess[3];
+          continue;
+        }
+      }
+      return lines.join("\n");
+    }
+  });
+
+  function localModeAt(cm, pos) {
+    return CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(pos).state).mode;
+  }
+
+  function enumerateModesBetween(cm, line, start, end) {
+    var outer = cm.getMode(), text = cm.getLine(line);
+    if (end == null) end = text.length;
+    if (!outer.innerMode) return [{from: start, to: end, mode: outer}];
+    var state = cm.getTokenAt({line: line, ch: start}).state;
+    var mode = CodeMirror.innerMode(outer, state).mode;
+    var found = [], stream = new CodeMirror.StringStream(text);
+    stream.pos = stream.start = start;
+    for (;;) {
+      outer.token(stream, state);
+      var curMode = CodeMirror.innerMode(outer, state).mode;
+      if (curMode != mode) {
+        var cut = stream.start;
+        // Crappy heuristic to deal with the fact that a change in
+        // mode can occur both at the end and the start of a token,
+        // and we don't know which it was.
+        if (mode.name == "xml" && text.charAt(stream.pos - 1) == ">") cut = stream.pos;
+        found.push({from: start, to: cut, mode: mode});
+        start = cut;
+        mode = curMode;
+      }
+      if (stream.pos >= end) break;
+      stream.start = stream.pos;
+    }
+    if (start < end) found.push({from: start, to: end, mode: mode});
+    return found;
+  }
+
+  // Comment/uncomment the specified range
+  CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
+    var curMode = localModeAt(this, from), cm = this;
+    this.operation(function() {
+      if (isComment) { // Comment range
+        cm.replaceRange(curMode.commentEnd, to);
+        cm.replaceRange(curMode.commentStart, from);
+        if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
+          cm.setCursor(from.line, from.ch + curMode.commentStart.length);
+      } else { // Uncomment range
+        var selText = cm.getRange(from, to);
+        var startIndex = selText.indexOf(curMode.commentStart);
+        var endIndex = selText.lastIndexOf(curMode.commentEnd);
+        if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
+          // Take string till comment start
+          selText = selText.substr(0, startIndex)
+          // From comment start till comment end
+            + selText.substring(startIndex + curMode.commentStart.length, endIndex)
+          // From comment end till string end
+            + selText.substr(endIndex + curMode.commentEnd.length);
+        }
+        cm.replaceRange(selText, from, to);
+      }
+    });
+  });
+
+  // Applies automatic mode-aware indentation to the specified range
+  CodeMirror.defineExtension("autoIndentRange", function (from, to) {
+    var cmInstance = this;
+    this.operation(function () {
+      for (var i = from.line; i <= to.line; i++) {
+        cmInstance.indentLine(i, "smart");
+      }
+    });
+  });
+
+  // Applies automatic formatting to the specified range
+  CodeMirror.defineExtension("autoFormatRange", function (from, to) {
+    var cm = this;
+    cm.operation(function () {
+      for (var cur = from.line, end = to.line; cur <= end; ++cur) {
+        var f = {line: cur, ch: cur == from.line ? from.ch : 0};
+        var t = {line: cur, ch: cur == end ? to.ch : null};
+        var modes = enumerateModesBetween(cm, cur, f.ch, t.ch), mangled = "";
+        var text = cm.getRange(f, t);
+        for (var i = 0; i < modes.length; ++i) {
+          var part = modes.length > 1 ? text.slice(modes[i].from, modes[i].to) : text;
+          if (mangled) mangled += "\n";
+          if (modes[i].mode.autoFormatLineBreaks) {
+            mangled += modes[i].mode.autoFormatLineBreaks(part);
+          } else mangled += text;
+        }
+        if (mangled != text) {
+          for (var count = 0, pos = mangled.indexOf("\n"); pos != -1; pos = mangled.indexOf("\n", pos + 1), ++count) {}
+          cm.replaceRange(mangled, f, t);
+          cur += count;
+          end += count;
+        }
+      }
+      for (var cur = from.line + 1; cur <= end; ++cur)
+        cm.indentLine(cur, "smart");
+      cm.setSelection(from, cm.getCursor(false));
+    });
+  });
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/javascript-hint.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/javascript-hint.js b/src/fauxton/jam/codemirror/lib/util/javascript-hint.js
new file mode 100644
index 0000000..ff15adb
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/javascript-hint.js
@@ -0,0 +1,134 @@
+(function () {
+  function forEach(arr, f) {
+    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
+  }
+  
+  function arrayContains(arr, item) {
+    if (!Array.prototype.indexOf) {
+      var i = arr.length;
+      while (i--) {
+        if (arr[i] === item) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return arr.indexOf(item) != -1;
+  }
+
+  function scriptHint(editor, keywords, getToken) {
+    // Find the token at the cursor
+    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
+    // If it's not a 'word-style' token, ignore the token.
+		if (!/^[\w$_]*$/.test(token.string)) {
+      token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
+                       className: token.string == "." ? "property" : null};
+    }
+    // If it is a property, find out what it is a property of.
+    while (tprop.className == "property") {
+      tprop = getToken(editor, {line: cur.line, ch: tprop.start});
+      if (tprop.string != ".") return;
+      tprop = getToken(editor, {line: cur.line, ch: tprop.start});
+      if (tprop.string == ')') {
+        var level = 1;
+        do {
+          tprop = getToken(editor, {line: cur.line, ch: tprop.start});
+          switch (tprop.string) {
+          case ')': level++; break;
+          case '(': level--; break;
+          default: break;
+          }
+        } while (level > 0);
+        tprop = getToken(editor, {line: cur.line, ch: tprop.start});
+				if (tprop.className == 'variable')
+					tprop.className = 'function';
+				else return; // no clue
+      }
+      if (!context) var context = [];
+      context.push(tprop);
+    }
+    return {list: getCompletions(token, context, keywords),
+            from: {line: cur.line, ch: token.start},
+            to: {line: cur.line, ch: token.end}};
+  }
+
+  CodeMirror.javascriptHint = function(editor) {
+    return scriptHint(editor, javascriptKeywords,
+                      function (e, cur) {return e.getTokenAt(cur);});
+  };
+
+  function getCoffeeScriptToken(editor, cur) {
+  // This getToken, it is for coffeescript, imitates the behavior of
+  // getTokenAt method in javascript.js, that is, returning "property"
+  // type and treat "." as indepenent token.
+    var token = editor.getTokenAt(cur);
+    if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
+      token.end = token.start;
+      token.string = '.';
+      token.className = "property";
+    }
+    else if (/^\.[\w$_]*$/.test(token.string)) {
+      token.className = "property";
+      token.start++;
+      token.string = token.string.replace(/\./, '');
+    }
+    return token;
+  }
+
+  CodeMirror.coffeescriptHint = function(editor) {
+    return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken);
+  };
+
+  var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
+                     "toUpperCase toLowerCase split concat match replace search").split(" ");
+  var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
+                    "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
+  var funcProps = "prototype apply call bind".split(" ");
+  var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
+                  "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
+  var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
+                  "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
+
+  function getCompletions(token, context, keywords) {
+    var found = [], start = token.string;
+    function maybeAdd(str) {
+      if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
+    }
+    function gatherCompletions(obj) {
+      if (typeof obj == "string") forEach(stringProps, maybeAdd);
+      else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
+      else if (obj instanceof Function) forEach(funcProps, maybeAdd);
+      for (var name in obj) maybeAdd(name);
+    }
+
+    if (context) {
+      // If this is a property, see if it belongs to some object we can
+      // find in the current environment.
+      var obj = context.pop(), base;
+      if (obj.className == "variable")
+        base = window[obj.string];
+      else if (obj.className == "string")
+        base = "";
+      else if (obj.className == "atom")
+        base = 1;
+      else if (obj.className == "function") {
+        if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
+            (typeof window.jQuery == 'function'))
+          base = window.jQuery();
+        else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
+          base = window._();
+      }
+      while (base != null && context.length)
+        base = base[context.pop().string];
+      if (base != null) gatherCompletions(base);
+    }
+    else {
+      // If not, just look in the window object and any local scope
+      // (reading into JS mode internals to get at the local variables)
+      for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
+      gatherCompletions(window);
+      forEach(keywords, maybeAdd);
+    }
+    return found;
+  }
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/loadmode.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/loadmode.js b/src/fauxton/jam/codemirror/lib/util/loadmode.js
new file mode 100644
index 0000000..60fafbb
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/loadmode.js
@@ -0,0 +1,51 @@
+(function() {
+  if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
+
+  var loading = {};
+  function splitCallback(cont, n) {
+    var countDown = n;
+    return function() { if (--countDown == 0) cont(); };
+  }
+  function ensureDeps(mode, cont) {
+    var deps = CodeMirror.modes[mode].dependencies;
+    if (!deps) return cont();
+    var missing = [];
+    for (var i = 0; i < deps.length; ++i) {
+      if (!CodeMirror.modes.hasOwnProperty(deps[i]))
+        missing.push(deps[i]);
+    }
+    if (!missing.length) return cont();
+    var split = splitCallback(cont, missing.length);
+    for (var i = 0; i < missing.length; ++i)
+      CodeMirror.requireMode(missing[i], split);
+  }
+
+  CodeMirror.requireMode = function(mode, cont) {
+    if (typeof mode != "string") mode = mode.name;
+    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
+    if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
+
+    var script = document.createElement("script");
+    script.src = CodeMirror.modeURL.replace(/%N/g, mode);
+    var others = document.getElementsByTagName("script")[0];
+    others.parentNode.insertBefore(script, others);
+    var list = loading[mode] = [cont];
+    var count = 0, poll = setInterval(function() {
+      if (++count > 100) return clearInterval(poll);
+      if (CodeMirror.modes.hasOwnProperty(mode)) {
+        clearInterval(poll);
+        loading[mode] = null;
+        ensureDeps(mode, function() {
+          for (var i = 0; i < list.length; ++i) list[i]();
+        });
+      }
+    }, 200);
+  };
+
+  CodeMirror.autoLoadMode = function(instance, mode) {
+    if (!CodeMirror.modes.hasOwnProperty(mode))
+      CodeMirror.requireMode(mode, function() {
+        instance.setOption("mode", instance.getOption("mode"));
+      });
+  };
+}());

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/match-highlighter.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/match-highlighter.js b/src/fauxton/jam/codemirror/lib/util/match-highlighter.js
new file mode 100644
index 0000000..59098ff
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/match-highlighter.js
@@ -0,0 +1,44 @@
+// Define match-highlighter commands. Depends on searchcursor.js
+// Use by attaching the following function call to the onCursorActivity event:
+	//myCodeMirror.matchHighlight(minChars);
+// And including a special span.CodeMirror-matchhighlight css class (also optionally a separate one for .CodeMirror-focused -- see demo matchhighlighter.html)
+
+(function() {
+  var DEFAULT_MIN_CHARS = 2;
+  
+  function MatchHighlightState() {
+	this.marked = [];
+  }
+  function getMatchHighlightState(cm) {
+	return cm._matchHighlightState || (cm._matchHighlightState = new MatchHighlightState());
+  }
+  
+  function clearMarks(cm) {
+	var state = getMatchHighlightState(cm);
+	for (var i = 0; i < state.marked.length; ++i)
+		state.marked[i].clear();
+	state.marked = [];
+  }
+  
+  function markDocument(cm, className, minChars) {
+    clearMarks(cm);
+	minChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);
+	if (cm.somethingSelected() && cm.getSelection().replace(/^\s+|\s+$/g, "").length >= minChars) {
+		var state = getMatchHighlightState(cm);
+		var query = cm.getSelection();
+		cm.operation(function() {
+			if (cm.lineCount() < 2000) { // This is too expensive on big documents.
+			  for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
+				//Only apply matchhighlight to the matches other than the one actually selected
+				if (!(cursor.from().line === cm.getCursor(true).line && cursor.from().ch === cm.getCursor(true).ch))
+					state.marked.push(cm.markText(cursor.from(), cursor.to(), className));
+			  }
+			}
+		  });
+	}
+  }
+
+  CodeMirror.defineExtension("matchHighlight", function(className, minChars) {
+    markDocument(this, className, minChars);
+  });
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/multiplex.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/multiplex.js b/src/fauxton/jam/codemirror/lib/util/multiplex.js
new file mode 100644
index 0000000..2147308
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/multiplex.js
@@ -0,0 +1,77 @@
+CodeMirror.multiplexingMode = function(outer /*, others */) {
+  // Others should be {open, close, mode [, delimStyle]} objects
+  var others = Array.prototype.slice.call(arguments, 1);
+  var n_others = others.length;
+
+  function indexOf(string, pattern, from) {
+    if (typeof pattern == "string") return string.indexOf(pattern, from);
+    var m = pattern.exec(from ? string.slice(from) : string);
+    return m ? m.index + from : -1;
+  }
+
+  return {
+    startState: function() {
+      return {
+        outer: CodeMirror.startState(outer),
+        innerActive: null,
+        inner: null
+      };
+    },
+
+    copyState: function(state) {
+      return {
+        outer: CodeMirror.copyState(outer, state.outer),
+        innerActive: state.innerActive,
+        inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
+      };
+    },
+
+    token: function(stream, state) {
+      if (!state.innerActive) {
+        var cutOff = Infinity, oldContent = stream.string;
+        for (var i = 0; i < n_others; ++i) {
+          var other = others[i];
+          var found = indexOf(oldContent, other.open, stream.pos);
+          if (found == stream.pos) {
+            stream.match(other.open);
+            state.innerActive = other;
+            state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
+            return other.delimStyle;
+          } else if (found != -1 && found < cutOff) {
+            cutOff = found;
+          }
+        }
+        if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
+        var outerToken = outer.token(stream, state.outer);
+        if (cutOff != Infinity) stream.string = oldContent;
+        return outerToken;
+      } else {
+        var curInner = state.innerActive, oldContent = stream.string;
+        var found = indexOf(oldContent, curInner.close, stream.pos);
+        if (found == stream.pos) {
+          stream.match(curInner.close);
+          state.innerActive = state.inner = null;
+          return curInner.delimStyle;
+        }
+        if (found > -1) stream.string = oldContent.slice(0, found);
+        var innerToken = curInner.mode.token(stream, state.inner);
+        if (found > -1) stream.string = oldContent;
+        var cur = stream.current(), found = cur.indexOf(curInner.close);
+        if (found > -1) stream.backUp(cur.length - found);
+        return innerToken;
+      }
+    },
+    
+    indent: function(state, textAfter) {
+      var mode = state.innerActive ? state.innerActive.mode : outer;
+      if (!mode.indent) return CodeMirror.Pass;
+      return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
+    },
+
+    electricChars: outer.electricChars,
+
+    innerMode: function(state) {
+      return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
+    }
+  };
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/overlay.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/overlay.js b/src/fauxton/jam/codemirror/lib/util/overlay.js
new file mode 100644
index 0000000..fba3898
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/overlay.js
@@ -0,0 +1,59 @@
+// Utility function that allows modes to be combined. The mode given
+// as the base argument takes care of most of the normal mode
+// functionality, but a second (typically simple) mode is used, which
+// can override the style of text. Both modes get to parse all of the
+// text, but when both assign a non-null style to a piece of code, the
+// overlay wins, unless the combine argument was true, in which case
+// the styles are combined.
+
+// overlayParser is the old, deprecated name
+CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) {
+  return {
+    startState: function() {
+      return {
+        base: CodeMirror.startState(base),
+        overlay: CodeMirror.startState(overlay),
+        basePos: 0, baseCur: null,
+        overlayPos: 0, overlayCur: null
+      };
+    },
+    copyState: function(state) {
+      return {
+        base: CodeMirror.copyState(base, state.base),
+        overlay: CodeMirror.copyState(overlay, state.overlay),
+        basePos: state.basePos, baseCur: null,
+        overlayPos: state.overlayPos, overlayCur: null
+      };
+    },
+
+    token: function(stream, state) {
+      if (stream.start == state.basePos) {
+        state.baseCur = base.token(stream, state.base);
+        state.basePos = stream.pos;
+      }
+      if (stream.start == state.overlayPos) {
+        stream.pos = stream.start;
+        state.overlayCur = overlay.token(stream, state.overlay);
+        state.overlayPos = stream.pos;
+      }
+      stream.pos = Math.min(state.basePos, state.overlayPos);
+      if (stream.eol()) state.basePos = state.overlayPos = 0;
+
+      if (state.overlayCur == null) return state.baseCur;
+      if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
+      else return state.overlayCur;
+    },
+    
+    indent: base.indent && function(state, textAfter) {
+      return base.indent(state.base, textAfter);
+    },
+    electricChars: base.electricChars,
+
+    innerMode: function(state) { return {state: state.base, mode: base}; },
+    
+    blankLine: function(state) {
+      if (base.blankLine) base.blankLine(state.base);
+      if (overlay.blankLine) overlay.blankLine(state.overlay);
+    }
+  };
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/pig-hint.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/pig-hint.js b/src/fauxton/jam/codemirror/lib/util/pig-hint.js
new file mode 100644
index 0000000..08e0dbf
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/pig-hint.js
@@ -0,0 +1,123 @@
+(function () {
+  function forEach(arr, f) {
+    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
+  }
+  
+  function arrayContains(arr, item) {
+    if (!Array.prototype.indexOf) {
+      var i = arr.length;
+      while (i--) {
+        if (arr[i] === item) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return arr.indexOf(item) != -1;
+  }
+
+  function scriptHint(editor, keywords, getToken) {
+    // Find the token at the cursor
+    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
+    // If it's not a 'word-style' token, ignore the token.
+
+    if (!/^[\w$_]*$/.test(token.string)) {
+        token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
+                         className: token.string == ":" ? "pig-type" : null};
+    }
+      
+    if (!context) var context = [];
+    context.push(tprop);
+    
+    var completionList = getCompletions(token, context); 
+    completionList = completionList.sort();
+    //prevent autocomplete for last word, instead show dropdown with one word
+    if(completionList.length == 1) {
+      completionList.push(" ");
+    }
+
+    return {list: completionList,
+              from: {line: cur.line, ch: token.start},
+              to: {line: cur.line, ch: token.end}};
+  }
+  
+  CodeMirror.pigHint = function(editor) {
+    return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
+  };
+ 
+ function toTitleCase(str) {
+    return str.replace(/(?:^|\s)\w/g, function(match) {
+        return match.toUpperCase();
+    });
+ }
+  
+  var pigKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
+  + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
+  + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
+  + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE " 
+  + "NEQ MATCHES TRUE FALSE";
+  var pigKeywordsU = pigKeywords.split(" ");
+  var pigKeywordsL = pigKeywords.toLowerCase().split(" ");
+  
+  var pigTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP";
+  var pigTypesU = pigTypes.split(" ");
+  var pigTypesL = pigTypes.toLowerCase().split(" ");
+  
+  var pigBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL " 
+  + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
+  + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
+  + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
+  + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
+  + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
+  + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA  "
+  + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
+  + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
+  + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER";  
+  var pigBuiltinsU = pigBuiltins.split(" ").join("() ").split(" ");  
+  var pigBuiltinsL = pigBuiltins.toLowerCase().split(" ").join("() ").split(" ");   
+  var pigBuiltinsC = ("BagSize BinStorage Bloom BuildBloom ConstantSize CubeDimensions DoubleAbs "
+  + "DoubleAvg DoubleBase DoubleMax DoubleMin DoubleRound DoubleSum FloatAbs FloatAvg FloatMax "
+  + "FloatMin FloatRound FloatSum GenericInvoker IntAbs IntAvg IntMax IntMin IntSum "
+  + "InvokeForDouble InvokeForFloat InvokeForInt InvokeForLong InvokeForString Invoker "
+  + "IsEmpty JsonLoader JsonMetadata JsonStorage LongAbs LongAvg LongMax LongMin LongSum MapSize "
+  + "MonitoredUDF Nondeterministic OutputSchema PigStorage PigStreaming StringConcat StringMax "
+  + "StringMin StringSize TextLoader TupleSize Utf8StorageConverter").split(" ").join("() ").split(" ");
+                    
+  function getCompletions(token, context) {
+    var found = [], start = token.string;
+    function maybeAdd(str) {
+      if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
+    }
+    
+    function gatherCompletions(obj) {
+      if(obj == ":") {
+        forEach(pigTypesL, maybeAdd);
+      }
+      else {
+        forEach(pigBuiltinsU, maybeAdd);
+        forEach(pigBuiltinsL, maybeAdd);
+        forEach(pigBuiltinsC, maybeAdd);
+        forEach(pigTypesU, maybeAdd);
+        forEach(pigTypesL, maybeAdd);
+        forEach(pigKeywordsU, maybeAdd);
+        forEach(pigKeywordsL, maybeAdd);
+      }
+    }
+
+    if (context) {
+      // If this is a property, see if it belongs to some object we can
+      // find in the current environment.
+      var obj = context.pop(), base;
+
+      if (obj.className == "pig-word") 
+          base = obj.string;
+      else if(obj.className == "pig-type")
+          base = ":" + obj.string;
+        
+      while (base != null && context.length)
+        base = base[context.pop().string];
+      if (base != null) gatherCompletions(base);
+    }
+    return found;
+  }
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/runmode-standalone.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/runmode-standalone.js b/src/fauxton/jam/codemirror/lib/util/runmode-standalone.js
new file mode 100644
index 0000000..afdf044
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/runmode-standalone.js
@@ -0,0 +1,90 @@
+/* Just enough of CodeMirror to run runMode under node.js */
+
+function splitLines(string){ return string.split(/\r?\n|\r/); };
+
+function StringStream(string) {
+  this.pos = this.start = 0;
+  this.string = string;
+}
+StringStream.prototype = {
+  eol: function() {return this.pos >= this.string.length;},
+  sol: function() {return this.pos == 0;},
+  peek: function() {return this.string.charAt(this.pos) || null;},
+  next: function() {
+    if (this.pos < this.string.length)
+      return this.string.charAt(this.pos++);
+  },
+  eat: function(match) {
+    var ch = this.string.charAt(this.pos);
+    if (typeof match == "string") var ok = ch == match;
+    else var ok = ch && (match.test ? match.test(ch) : match(ch));
+    if (ok) {++this.pos; return ch;}
+  },
+  eatWhile: function(match) {
+    var start = this.pos;
+    while (this.eat(match)){}
+    return this.pos > start;
+  },
+  eatSpace: function() {
+    var start = this.pos;
+    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
+    return this.pos > start;
+  },
+  skipToEnd: function() {this.pos = this.string.length;},
+  skipTo: function(ch) {
+    var found = this.string.indexOf(ch, this.pos);
+    if (found > -1) {this.pos = found; return true;}
+  },
+  backUp: function(n) {this.pos -= n;},
+  column: function() {return this.start;},
+  indentation: function() {return 0;},
+  match: function(pattern, consume, caseInsensitive) {
+    if (typeof pattern == "string") {
+      function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
+      if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+        if (consume !== false) this.pos += pattern.length;
+        return true;
+      }
+    }
+    else {
+      var match = this.string.slice(this.pos).match(pattern);
+      if (match && consume !== false) this.pos += match[0].length;
+      return match;
+    }
+  },
+  current: function(){return this.string.slice(this.start, this.pos);}
+};
+exports.StringStream = StringStream;
+
+exports.startState = function(mode, a1, a2) {
+  return mode.startState ? mode.startState(a1, a2) : true;
+};
+
+var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
+exports.defineMode = function(name, mode) { modes[name] = mode; };
+exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
+exports.getMode = function(options, spec) {
+  if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
+    spec = mimeModes[spec];
+  if (typeof spec == "string")
+    var mname = spec, config = {};
+  else if (spec != null)
+    var mname = spec.name, config = spec;
+  var mfactory = modes[mname];
+  if (!mfactory) throw new Error("Unknown mode: " + spec);
+  return mfactory(options, config || {});
+};
+
+exports.runMode = function(string, modespec, callback) {
+  var mode = exports.getMode({indentUnit: 2}, modespec);
+  var lines = splitLines(string), state = exports.startState(mode);
+  for (var i = 0, e = lines.length; i < e; ++i) {
+    if (i) callback("\n");
+    var stream = new exports.StringStream(lines[i]);
+    while (!stream.eol()) {
+      var style = mode.token(stream, state);
+      callback(stream.current(), style, i, stream.start);
+      stream.start = stream.pos;
+    }
+  }
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/runmode.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/runmode.js b/src/fauxton/jam/codemirror/lib/util/runmode.js
new file mode 100644
index 0000000..327976b
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/runmode.js
@@ -0,0 +1,53 @@
+CodeMirror.runMode = function(string, modespec, callback, options) {
+  function esc(str) {
+    return str.replace(/[<&]/g, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
+  }
+
+  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
+  var isNode = callback.nodeType == 1;
+  var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+  if (isNode) {
+    var node = callback, accum = [], col = 0;
+    callback = function(text, style) {
+      if (text == "\n") {
+        accum.push("<br>");
+        col = 0;
+        return;
+      }
+      var escaped = "";
+      // HTML-escape and replace tabs
+      for (var pos = 0;;) {
+        var idx = text.indexOf("\t", pos);
+        if (idx == -1) {
+          escaped += esc(text.slice(pos));
+          col += text.length - pos;
+          break;
+        } else {
+          col += idx - pos;
+          escaped += esc(text.slice(pos, idx));
+          var size = tabSize - col % tabSize;
+          col += size;
+          for (var i = 0; i < size; ++i) escaped += " ";
+          pos = idx + 1;
+        }
+      }
+
+      if (style) 
+        accum.push("<span class=\"cm-" + esc(style) + "\">" + escaped + "</span>");
+      else
+        accum.push(escaped);
+    };
+  }
+  var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
+  for (var i = 0, e = lines.length; i < e; ++i) {
+    if (i) callback("\n");
+    var stream = new CodeMirror.StringStream(lines[i]);
+    while (!stream.eol()) {
+      var style = mode.token(stream, state);
+      callback(stream.current(), style, i, stream.start);
+      stream.start = stream.pos;
+    }
+  }
+  if (isNode)
+    node.innerHTML = accum.join("");
+};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/search.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/search.js b/src/fauxton/jam/codemirror/lib/util/search.js
new file mode 100644
index 0000000..356283a
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/search.js
@@ -0,0 +1,118 @@
+// Define search commands. Depends on dialog.js or another
+// implementation of the openDialog method.
+
+// Replace works a little oddly -- it will do the replace on the next
+// Ctrl-G (or whatever is bound to findNext) press. You prevent a
+// replace by making sure the match is no longer selected when hitting
+// Ctrl-G.
+
+(function() {
+  function SearchState() {
+    this.posFrom = this.posTo = this.query = null;
+    this.marked = [];
+  }
+  function getSearchState(cm) {
+    return cm._searchState || (cm._searchState = new SearchState());
+  }
+  function getSearchCursor(cm, query, pos) {
+    // Heuristic: if the query string is all lowercase, do a case insensitive search.
+    return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
+  }
+  function dialog(cm, text, shortText, f) {
+    if (cm.openDialog) cm.openDialog(text, f);
+    else f(prompt(shortText, ""));
+  }
+  function confirmDialog(cm, text, shortText, fs) {
+    if (cm.openConfirm) cm.openConfirm(text, fs);
+    else if (confirm(shortText)) fs[0]();
+  }
+  function parseQuery(query) {
+    var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
+    return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
+  }
+  var queryDialog =
+    'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
+  function doSearch(cm, rev) {
+    var state = getSearchState(cm);
+    if (state.query) return findNext(cm, rev);
+    dialog(cm, queryDialog, "Search for:", function(query) {
+      cm.operation(function() {
+        if (!query || state.query) return;
+        state.query = parseQuery(query);
+        if (cm.lineCount() < 2000) { // This is too expensive on big documents.
+          for (var cursor = getSearchCursor(cm, state.query); cursor.findNext();)
+            state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
+        }
+        state.posFrom = state.posTo = cm.getCursor();
+        findNext(cm, rev);
+      });
+    });
+  }
+  function findNext(cm, rev) {cm.operation(function() {
+    var state = getSearchState(cm);
+    var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
+    if (!cursor.find(rev)) {
+      cursor = getSearchCursor(cm, state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});
+      if (!cursor.find(rev)) return;
+    }
+    cm.setSelection(cursor.from(), cursor.to());
+    state.posFrom = cursor.from(); state.posTo = cursor.to();
+  });}
+  function clearSearch(cm) {cm.operation(function() {
+    var state = getSearchState(cm);
+    if (!state.query) return;
+    state.query = null;
+    for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear();
+    state.marked.length = 0;
+  });}
+
+  var replaceQueryDialog =
+    'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
+  var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
+  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
+  function replace(cm, all) {
+    dialog(cm, replaceQueryDialog, "Replace:", function(query) {
+      if (!query) return;
+      query = parseQuery(query);
+      dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
+        if (all) {
+          cm.compoundChange(function() { cm.operation(function() {
+            for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
+              if (typeof query != "string") {
+                var match = cm.getRange(cursor.from(), cursor.to()).match(query);
+                cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
+              } else cursor.replace(text);
+            }
+          });});
+        } else {
+          clearSearch(cm);
+          var cursor = getSearchCursor(cm, query, cm.getCursor());
+          function advance() {
+            var start = cursor.from(), match;
+            if (!(match = cursor.findNext())) {
+              cursor = getSearchCursor(cm, query);
+              if (!(match = cursor.findNext()) ||
+                  (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
+            }
+            cm.setSelection(cursor.from(), cursor.to());
+            confirmDialog(cm, doReplaceConfirm, "Replace?",
+                          [function() {doReplace(match);}, advance]);
+          }
+          function doReplace(match) {
+            cursor.replace(typeof query == "string" ? text :
+                           text.replace(/\$(\d)/, function(w, i) {return match[i];}));
+            advance();
+          }
+          advance();
+        }
+      });
+    });
+  }
+
+  CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
+  CodeMirror.commands.findNext = doSearch;
+  CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
+  CodeMirror.commands.clearSearch = clearSearch;
+  CodeMirror.commands.replace = replace;
+  CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/searchcursor.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/searchcursor.js b/src/fauxton/jam/codemirror/lib/util/searchcursor.js
new file mode 100644
index 0000000..1750aad
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/searchcursor.js
@@ -0,0 +1,119 @@
+(function(){
+  function SearchCursor(cm, query, pos, caseFold) {
+    this.atOccurrence = false; this.cm = cm;
+    if (caseFold == null && typeof query == "string") caseFold = false;
+
+    pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};
+    this.pos = {from: pos, to: pos};
+
+    // The matches method is filled in based on the type of query.
+    // It takes a position and a direction, and returns an object
+    // describing the next occurrence of the query, or null if no
+    // more matches were found.
+    if (typeof query != "string") { // Regexp match
+      if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
+      this.matches = function(reverse, pos) {
+        if (reverse) {
+          query.lastIndex = 0;
+          var line = cm.getLine(pos.line).slice(0, pos.ch), match = query.exec(line), start = 0;
+          while (match) {
+            start += match.index + 1;
+	    line = line.slice(start);
+            query.lastIndex = 0;
+            var newmatch = query.exec(line);
+            if (newmatch) match = newmatch;
+            else break;
+          }
+          start--;
+        } else {
+          query.lastIndex = pos.ch;
+          var line = cm.getLine(pos.line), match = query.exec(line),
+          start = match && match.index;
+        }
+        if (match)
+          return {from: {line: pos.line, ch: start},
+                  to: {line: pos.line, ch: start + match[0].length},
+                  match: match};
+      };
+    } else { // String query
+      if (caseFold) query = query.toLowerCase();
+      var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
+      var target = query.split("\n");
+      // Different methods for single-line and multi-line queries
+      if (target.length == 1)
+        this.matches = function(reverse, pos) {
+          var line = fold(cm.getLine(pos.line)), len = query.length, match;
+          if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
+              : (match = line.indexOf(query, pos.ch)) != -1)
+            return {from: {line: pos.line, ch: match},
+                    to: {line: pos.line, ch: match + len}};
+        };
+      else
+        this.matches = function(reverse, pos) {
+          var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
+          var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
+          if (reverse ? offsetA >= pos.ch || offsetA != match.length
+              : offsetA <= pos.ch || offsetA != line.length - match.length)
+            return;
+          for (;;) {
+            if (reverse ? !ln : ln == cm.lineCount() - 1) return;
+            line = fold(cm.getLine(ln += reverse ? -1 : 1));
+            match = target[reverse ? --idx : ++idx];
+            if (idx > 0 && idx < target.length - 1) {
+              if (line != match) return;
+              else continue;
+            }
+            var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
+            if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
+              return;
+            var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};
+            return {from: reverse ? end : start, to: reverse ? start : end};
+          }
+        };
+    }
+  }
+
+  SearchCursor.prototype = {
+    findNext: function() {return this.find(false);},
+    findPrevious: function() {return this.find(true);},
+
+    find: function(reverse) {
+      var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
+      function savePosAndFail(line) {
+        var pos = {line: line, ch: 0};
+        self.pos = {from: pos, to: pos};
+        self.atOccurrence = false;
+        return false;
+      }
+
+      for (;;) {
+        if (this.pos = this.matches(reverse, pos)) {
+          this.atOccurrence = true;
+          return this.pos.match || true;
+        }
+        if (reverse) {
+          if (!pos.line) return savePosAndFail(0);
+          pos = {line: pos.line-1, ch: this.cm.getLine(pos.line-1).length};
+        }
+        else {
+          var maxLine = this.cm.lineCount();
+          if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
+          pos = {line: pos.line+1, ch: 0};
+        }
+      }
+    },
+
+    from: function() {if (this.atOccurrence) return this.pos.from;},
+    to: function() {if (this.atOccurrence) return this.pos.to;},
+
+    replace: function(newText) {
+      var self = this;
+      if (this.atOccurrence)
+        self.pos.to = this.cm.replaceRange(newText, self.pos.from, self.pos.to);
+    }
+  };
+
+  CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
+    return new SearchCursor(this, query, pos, caseFold);
+  });
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/simple-hint.css
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/simple-hint.css b/src/fauxton/jam/codemirror/lib/util/simple-hint.css
new file mode 100644
index 0000000..4387cb9
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/simple-hint.css
@@ -0,0 +1,16 @@
+.CodeMirror-completions {
+  position: absolute;
+  z-index: 10;
+  overflow: hidden;
+  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+  box-shadow: 2px 3px 5px rgba(0,0,0,.2);
+}
+.CodeMirror-completions select {
+  background: #fafafa;
+  outline: none;
+  border: none;
+  padding: 0;
+  margin: 0;
+  font-family: monospace;
+}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/simple-hint.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/simple-hint.js b/src/fauxton/jam/codemirror/lib/util/simple-hint.js
new file mode 100644
index 0000000..0ce25f9
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/simple-hint.js
@@ -0,0 +1,102 @@
+(function() {
+  CodeMirror.simpleHint = function(editor, getHints, givenOptions) {
+    // Determine effective options based on given values and defaults.
+    var options = {}, defaults = CodeMirror.simpleHint.defaults;
+    for (var opt in defaults)
+      if (defaults.hasOwnProperty(opt))
+        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
+    
+    function collectHints(previousToken) {
+      // We want a single cursor position.
+      if (editor.somethingSelected()) return;
+
+      var tempToken = editor.getTokenAt(editor.getCursor());
+
+      // Don't show completions if token has changed and the option is set.
+      if (options.closeOnTokenChange && previousToken != null &&
+          (tempToken.start != previousToken.start || tempToken.className != previousToken.className)) {
+        return;
+      }
+
+      var result = getHints(editor);
+      if (!result || !result.list.length) return;
+      var completions = result.list;
+      function insert(str) {
+        editor.replaceRange(str, result.from, result.to);
+      }
+      // When there is only one completion, use it directly.
+      if (options.completeSingle && completions.length == 1) {
+        insert(completions[0]);
+        return true;
+      }
+
+      // Build the select widget
+      var complete = document.createElement("div");
+      complete.className = "CodeMirror-completions";
+      var sel = complete.appendChild(document.createElement("select"));
+      // Opera doesn't move the selection when pressing up/down in a
+      // multi-select, but it does properly support the size property on
+      // single-selects, so no multi-select is necessary.
+      if (!window.opera) sel.multiple = true;
+      for (var i = 0; i < completions.length; ++i) {
+        var opt = sel.appendChild(document.createElement("option"));
+        opt.appendChild(document.createTextNode(completions[i]));
+      }
+      sel.firstChild.selected = true;
+      sel.size = Math.min(10, completions.length);
+      var pos = options.alignWithWord ? editor.charCoords(result.from) : editor.cursorCoords();
+      complete.style.left = pos.x + "px";
+      complete.style.top = pos.yBot + "px";
+      document.body.appendChild(complete);
+      // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
+      var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
+      if(winW - pos.x < sel.clientWidth)
+        complete.style.left = (pos.x - sel.clientWidth) + "px";
+      // Hack to hide the scrollbar.
+      if (completions.length <= 10)
+        complete.style.width = (sel.clientWidth - 1) + "px";
+
+      var done = false;
+      function close() {
+        if (done) return;
+        done = true;
+        complete.parentNode.removeChild(complete);
+      }
+      function pick() {
+        insert(completions[sel.selectedIndex]);
+        close();
+        setTimeout(function(){editor.focus();}, 50);
+      }
+      CodeMirror.connect(sel, "blur", close);
+      CodeMirror.connect(sel, "keydown", function(event) {
+        var code = event.keyCode;
+        // Enter
+        if (code == 13) {CodeMirror.e_stop(event); pick();}
+        // Escape
+        else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
+        else if (code != 38 && code != 40 && code != 33 && code != 34 && !CodeMirror.isModifierKey(event)) {
+          close(); editor.focus();
+          // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
+          editor.triggerOnKeyDown(event);
+          // Don't show completions if the code is backspace and the option is set.
+          if (!options.closeOnBackspace || code != 8) {
+            setTimeout(function(){collectHints(tempToken);}, 50);
+          }
+        }
+      });
+      CodeMirror.connect(sel, "dblclick", pick);
+
+      sel.focus();
+      // Opera sometimes ignores focusing a freshly created node
+      if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
+      return true;
+    }
+    return collectHints();
+  };
+  CodeMirror.simpleHint.defaults = {
+    closeOnBackspace: true,
+    closeOnTokenChange: false,
+    completeSingle: true,
+    alignWithWord: true
+  };
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/lib/util/xml-hint.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/lib/util/xml-hint.js b/src/fauxton/jam/codemirror/lib/util/xml-hint.js
new file mode 100644
index 0000000..dd9d858
--- /dev/null
+++ b/src/fauxton/jam/codemirror/lib/util/xml-hint.js
@@ -0,0 +1,131 @@
+
+(function() {
+
+    CodeMirror.xmlHints = [];
+
+    CodeMirror.xmlHint = function(cm, simbol) {
+
+        if(simbol.length > 0) {
+            var cursor = cm.getCursor();
+            cm.replaceSelection(simbol);
+            cursor = {line: cursor.line, ch: cursor.ch + 1};
+            cm.setCursor(cursor);
+        }
+
+        CodeMirror.simpleHint(cm, getHint);
+    };
+
+    var getHint = function(cm) {
+
+        var cursor = cm.getCursor();
+
+        if (cursor.ch > 0) {
+
+            var text = cm.getRange({line: 0, ch: 0}, cursor);
+            var typed = '';
+            var simbol = '';
+            for(var i = text.length - 1; i >= 0; i--) {
+                if(text[i] == ' ' || text[i] == '<') {
+                    simbol = text[i];
+                    break;
+                }
+                else {
+                    typed = text[i] + typed;
+                }
+            }
+
+            text = text.slice(0, text.length - typed.length);
+
+            var path = getActiveElement(cm, text) + simbol;
+            var hints = CodeMirror.xmlHints[path];
+
+            if(typeof hints === 'undefined')
+                hints = [''];
+            else {
+                hints = hints.slice(0);
+                for (var i = hints.length - 1; i >= 0; i--) {
+                    if(hints[i].indexOf(typed) != 0)
+                        hints.splice(i, 1);
+                }
+            }
+
+            return {
+                list: hints,
+                from: { line: cursor.line, ch: cursor.ch - typed.length },
+                to: cursor
+            };
+        };
+    };
+
+    var getActiveElement = function(codeMirror, text) {
+
+        var element = '';
+
+        if(text.length >= 0) {
+
+            var regex = new RegExp('<([^!?][^\\s/>]*).*?>', 'g');
+
+            var matches = [];
+            var match;
+            while ((match = regex.exec(text)) != null) {
+                matches.push({
+                    tag: match[1],
+                    selfclose: (match[0].slice(match[0].length - 2) === '/>')
+                });
+            }
+
+            for (var i = matches.length - 1, skip = 0; i >= 0; i--) {
+
+                var item = matches[i];
+
+                if (item.tag[0] == '/')
+                {
+                    skip++;
+                }
+                else if (item.selfclose == false)
+                {
+                    if (skip > 0)
+                    {
+                        skip--;
+                    }
+                    else
+                    {
+                        element = '<' + item.tag + '>' + element;
+                    }
+                }
+            }
+
+            element += getOpenTag(text);
+        }
+
+        return element;
+    };
+
+    var getOpenTag = function(text) {
+
+        var open = text.lastIndexOf('<');
+        var close = text.lastIndexOf('>');
+
+        if (close < open)
+        {
+            text = text.slice(open);
+
+            if(text != '<') {
+
+                var space = text.indexOf(' ');
+                if(space < 0)
+                    space = text.indexOf('\t');
+                if(space < 0)
+                    space = text.indexOf('\n');
+
+                if (space < 0)
+                    space = text.length;
+
+                return text.slice(0, space);
+            }
+        }
+
+        return '';
+    };
+
+})();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/mode/clike/clike.js
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/mode/clike/clike.js b/src/fauxton/jam/codemirror/mode/clike/clike.js
new file mode 100644
index 0000000..69668a4
--- /dev/null
+++ b/src/fauxton/jam/codemirror/mode/clike/clike.js
@@ -0,0 +1,285 @@
+CodeMirror.defineMode("clike", function(config, parserConfig) {
+  var indentUnit = config.indentUnit,
+      keywords = parserConfig.keywords || {},
+      builtin = parserConfig.builtin || {},
+      blockKeywords = parserConfig.blockKeywords || {},
+      atoms = parserConfig.atoms || {},
+      hooks = parserConfig.hooks || {},
+      multiLineStrings = parserConfig.multiLineStrings;
+  var isOperatorChar = /[+\-*&%=<>!?|\/]/;
+
+  var curPunc;
+
+  function tokenBase(stream, state) {
+    var ch = stream.next();
+    if (hooks[ch]) {
+      var result = hooks[ch](stream, state);
+      if (result !== false) return result;
+    }
+    if (ch == '"' || ch == "'") {
+      state.tokenize = tokenString(ch);
+      return state.tokenize(stream, state);
+    }
+    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+      curPunc = ch;
+      return null;
+    }
+    if (/\d/.test(ch)) {
+      stream.eatWhile(/[\w\.]/);
+      return "number";
+    }
+    if (ch == "/") {
+      if (stream.eat("*")) {
+        state.tokenize = tokenComment;
+        return tokenComment(stream, state);
+      }
+      if (stream.eat("/")) {
+        stream.skipToEnd();
+        return "comment";
+      }
+    }
+    if (isOperatorChar.test(ch)) {
+      stream.eatWhile(isOperatorChar);
+      return "operator";
+    }
+    stream.eatWhile(/[\w\$_]/);
+    var cur = stream.current();
+    if (keywords.propertyIsEnumerable(cur)) {
+      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+      return "keyword";
+    }
+    if (builtin.propertyIsEnumerable(cur)) {
+      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+      return "builtin";
+    }
+    if (atoms.propertyIsEnumerable(cur)) return "atom";
+    return "variable";
+  }
+
+  function tokenString(quote) {
+    return function(stream, state) {
+      var escaped = false, next, end = false;
+      while ((next = stream.next()) != null) {
+        if (next == quote && !escaped) {end = true; break;}
+        escaped = !escaped && next == "\\";
+      }
+      if (end || !(escaped || multiLineStrings))
+        state.tokenize = null;
+      return "string";
+    };
+  }
+
+  function tokenComment(stream, state) {
+    var maybeEnd = false, ch;
+    while (ch = stream.next()) {
+      if (ch == "/" && maybeEnd) {
+        state.tokenize = null;
+        break;
+      }
+      maybeEnd = (ch == "*");
+    }
+    return "comment";
+  }
+
+  function Context(indented, column, type, align, prev) {
+    this.indented = indented;
+    this.column = column;
+    this.type = type;
+    this.align = align;
+    this.prev = prev;
+  }
+  function pushContext(state, col, type) {
+    return state.context = new Context(state.indented, col, type, null, state.context);
+  }
+  function popContext(state) {
+    var t = state.context.type;
+    if (t == ")" || t == "]" || t == "}")
+      state.indented = state.context.indented;
+    return state.context = state.context.prev;
+  }
+
+  // Interface
+
+  return {
+    startState: function(basecolumn) {
+      return {
+        tokenize: null,
+        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
+        indented: 0,
+        startOfLine: true
+      };
+    },
+
+    token: function(stream, state) {
+      var ctx = state.context;
+      if (stream.sol()) {
+        if (ctx.align == null) ctx.align = false;
+        state.indented = stream.indentation();
+        state.startOfLine = true;
+      }
+      if (stream.eatSpace()) return null;
+      curPunc = null;
+      var style = (state.tokenize || tokenBase)(stream, state);
+      if (style == "comment" || style == "meta") return style;
+      if (ctx.align == null) ctx.align = true;
+
+      if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
+      else if (curPunc == "{") pushContext(state, stream.column(), "}");
+      else if (curPunc == "[") pushContext(state, stream.column(), "]");
+      else if (curPunc == "(") pushContext(state, stream.column(), ")");
+      else if (curPunc == "}") {
+        while (ctx.type == "statement") ctx = popContext(state);
+        if (ctx.type == "}") ctx = popContext(state);
+        while (ctx.type == "statement") ctx = popContext(state);
+      }
+      else if (curPunc == ctx.type) popContext(state);
+      else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
+        pushContext(state, stream.column(), "statement");
+      state.startOfLine = false;
+      return style;
+    },
+
+    indent: function(state, textAfter) {
+      if (state.tokenize == tokenComment) return CodeMirror.Pass;
+      if (state.tokenize != tokenBase && state.tokenize != null) return 0;
+      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
+      if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
+      var closing = firstChar == ctx.type;
+      if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit);
+      else if (ctx.align) return ctx.column + (closing ? 0 : 1);
+      else return ctx.indented + (closing ? 0 : indentUnit);
+    },
+
+    electricChars: "{}"
+  };
+});
+
+(function() {
+  function words(str) {
+    var obj = {}, words = str.split(" ");
+    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
+    return obj;
+  }
+  var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
+    "double static else struct entry switch extern typedef float union for unsigned " +
+    "goto while enum void const signed volatile";
+
+  function cppHook(stream, state) {
+    if (!state.startOfLine) return false;
+    stream.skipToEnd();
+    return "meta";
+  }
+
+  // C#-style strings where "" escapes a quote.
+  function tokenAtString(stream, state) {
+    var next;
+    while ((next = stream.next()) != null) {
+      if (next == '"' && !stream.eat('"')) {
+        state.tokenize = null;
+        break;
+      }
+    }
+    return "string";
+  }
+
+  function mimes(ms, mode) {
+    for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
+  }
+
+  mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
+    name: "clike",
+    keywords: words(cKeywords),
+    blockKeywords: words("case do else for if switch while struct"),
+    atoms: words("null"),
+    hooks: {"#": cppHook}
+  });
+  mimes(["text/x-c++src", "text/x-c++hdr"], {
+    name: "clike",
+    keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
+                    "static_cast typeid catch operator template typename class friend private " +
+                    "this using const_cast inline public throw virtual delete mutable protected " +
+                    "wchar_t"),
+    blockKeywords: words("catch class do else finally for if struct switch try while"),
+    atoms: words("true false null"),
+    hooks: {"#": cppHook}
+  });
+  CodeMirror.defineMIME("text/x-java", {
+    name: "clike",
+    keywords: words("abstract assert boolean break byte case catch char class const continue default " + 
+                    "do double else enum extends final finally float for goto if implements import " +
+                    "instanceof int interface long native new package private protected public " +
+                    "return short static strictfp super switch synchronized this throw throws transient " +
+                    "try void volatile while"),
+    blockKeywords: words("catch class do else finally for if switch try while"),
+    atoms: words("true false null"),
+    hooks: {
+      "@": function(stream, state) {
+        stream.eatWhile(/[\w\$_]/);
+        return "meta";
+      }
+    }
+  });
+  CodeMirror.defineMIME("text/x-csharp", {
+    name: "clike",
+    keywords: words("abstract as base break case catch checked class const continue" + 
+                    " default delegate do else enum event explicit extern finally fixed for" + 
+                    " foreach goto if implicit in interface internal is lock namespace new" + 
+                    " operator out override params private protected public readonly ref return sealed" + 
+                    " sizeof stackalloc static struct switch this throw try typeof unchecked" + 
+                    " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + 
+                    " global group into join let orderby partial remove select set value var yield"),
+    blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
+    builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
+                    " Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
+                    " UInt64 bool byte char decimal double short int long object"  +
+                    " sbyte float string ushort uint ulong"),
+    atoms: words("true false null"),
+    hooks: {
+      "@": function(stream, state) {
+        if (stream.eat('"')) {
+          state.tokenize = tokenAtString;
+          return tokenAtString(stream, state);
+        }
+        stream.eatWhile(/[\w\$_]/);
+        return "meta";
+      }
+    }
+  });
+  CodeMirror.defineMIME("text/x-scala", {
+    name: "clike",
+    keywords: words(
+      
+      /* scala */
+      "abstract case catch class def do else extends false final finally for forSome if " +
+      "implicit import lazy match new null object override package private protected return " +
+      "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
+      "<% >: # @ " +
+                    
+      /* package scala */
+      "assert assume require print println printf readLine readBoolean readByte readShort " +
+      "readChar readInt readLong readFloat readDouble " +
+      
+      "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
+      "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
+      "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
+      "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
+      "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
+      
+      /* package java.lang */            
+      "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
+      "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
+      "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
+      "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
+      
+      
+    ),
+    blockKeywords: words("catch class do else finally for forSome if match switch try while"),
+    atoms: words("true false null"),
+    hooks: {
+      "@": function(stream, state) {
+        stream.eatWhile(/[\w\$_]/);
+        return "meta";
+      }
+    }
+  });
+}());

http://git-wip-us.apache.org/repos/asf/couchdb/blob/4615a788/src/fauxton/jam/codemirror/mode/clike/index.html
----------------------------------------------------------------------
diff --git a/src/fauxton/jam/codemirror/mode/clike/index.html b/src/fauxton/jam/codemirror/mode/clike/index.html
new file mode 100644
index 0000000..90a5fc1
--- /dev/null
+++ b/src/fauxton/jam/codemirror/mode/clike/index.html
@@ -0,0 +1,102 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>CodeMirror: C-like mode</title>
+    <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/codemirror.js"></script>
+    <script src="clike.js"></script>
+    <link rel="stylesheet" href="../../doc/docs.css">
+    <style>.CodeMirror {border: 2px inset #dee;}</style>
+  </head>
+  <body>
+    <h1>CodeMirror: C-like mode</h1>
+
+<form><textarea id="code" name="code">
+/* C demo code */
+
+#include <zmq.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <malloc.h>
+
+typedef struct {
+  void* arg_socket;
+  zmq_msg_t* arg_msg;
+  char* arg_string;
+  unsigned long arg_len;
+  int arg_int, arg_command;
+
+  int signal_fd;
+  int pad;
+  void* context;
+  sem_t sem;
+} acl_zmq_context;
+
+#define p(X) (context->arg_##X)
+
+void* zmq_thread(void* context_pointer) {
+  acl_zmq_context* context = (acl_zmq_context*)context_pointer;
+  char ok = 'K', err = 'X';
+  int res;
+
+  while (1) {
+    while ((res = sem_wait(&amp;context->sem)) == EINTR);
+    if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}
+    switch(p(command)) {
+    case 0: goto cleanup;
+    case 1: p(socket) = zmq_socket(context->context, p(int)); break;
+    case 2: p(int) = zmq_close(p(socket)); break;
+    case 3: p(int) = zmq_bind(p(socket), p(string)); break;
+    case 4: p(int) = zmq_connect(p(socket), p(string)); break;
+    case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;
+    case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
+    case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
+    case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
+    case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
+    }
+    p(command) = errno;
+    write(context->signal_fd, &amp;ok, 1);
+  }
+ cleanup:
+  close(context->signal_fd);
+  free(context_pointer);
+  return 0;
+}
+
+void* zmq_thread_init(void* zmq_context, int signal_fd) {
+  acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
+  pthread_t thread;
+
+  context->context = zmq_context;
+  context->signal_fd = signal_fd;
+  sem_init(&amp;context->sem, 1, 0);
+  pthread_create(&amp;thread, 0, &amp;zmq_thread, context);
+  pthread_detach(thread);
+  return context;
+}
+</textarea></form>
+
+    <script>
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
+        lineNumbers: true,
+        matchBrackets: true,
+        mode: "text/x-csrc"
+      });
+    </script>
+
+    <p>Simple mode that tries to handle C-like languages as well as it
+    can. Takes two configuration parameters: <code>keywords</code>, an
+    object whose property names are the keywords in the language,
+    and <code>useCPP</code>, which determines whether C preprocessor
+    directives are recognized.</p>
+
+    <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
+    (C code), <code>text/x-c++src</code> (C++
+    code), <code>text/x-java</code> (Java
+    code), <code>text/x-csharp</code> (C#).</p>
+  </body>
+</html>


Mime
View raw message