diff --git a/demo/changemode.html b/demo/changemode.html
index 17c82d277c5bf3cd9eec4ca4e14712f12fd0f0c4..89536277a722fcd4863b366e43188b6fd5f9352f 100644
--- a/demo/changemode.html
+++ b/demo/changemode.html
@@ -32,7 +32,6 @@ either JavaScript or Scheme mode based on that.</p>
   var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
     mode: "scheme",
     lineNumbers: true,
-    matchBrackets: true,
     tabMode: "indent"
   });
   editor.connect("change", function() {
diff --git a/doc/compress.html b/doc/compress.html
index 3e4abc1479716e9babc907e94cd1cf0f4bc4ad07..7e3438edb4ff1ec9ab8ac97a460fc6f9828ee89d 100644
--- a/doc/compress.html
+++ b/doc/compress.html
@@ -119,6 +119,7 @@
           <option value="http://codemirror.net/lib/util/dialog.js">dialog.js</option>
           <option value="http://codemirror.net/lib/util/search.js">search.js</option>
           <option value="http://codemirror.net/lib/util/searchcursor.js">searchcursor.js</option>
+          <option value="http://codemirror.net/lib/util/matchbrackets.js">matchbrackets.js</option>
           <option value="http://codemirror.net/lib/util/formatting.js">formatting.js</option>
           <option value="http://codemirror.net/lib/util/match-highlighter.js">match-highlighter.js</option>
           <option value="http://codemirror.net/lib/util/closetag.js">closetag.js</option>
diff --git a/doc/manual.html b/doc/manual.html
index f94b86777519d67780995655dfea71fdc12c898e..2b56b6ff074a5fbf06e13fe430ae6eabeeaa4e68 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -211,10 +211,6 @@
       simply <code>true</code>), focusing of the editor is also
       disallowed.</dd>
 
-      <dt id="option_matchBrackets"><code>matchBrackets (boolean)</code></dt>
-      <dd>Determines whether brackets are matched whenever the cursor
-      is moved next to a bracket.</dd>
-
       <dt id="option_cursorBlinkRate"><code>cursorBlinkRate (number)</code></dt>
       <dd>Half-period in milliseconds used for cursor blinking. The default blink
       rate is 530ms.</dd>
@@ -740,9 +736,6 @@
       widget again, simply use DOM methods (move it somewhere else, or
       call <code>removeChild</code> on its parent).</dd>
 
-      <dt id="matchBrackets"><code>matchBrackets()</code></dt>
-      <dd>Force matching-bracket-highlighting to happen.</dd>
-
       <dt id="lineCount"><code>lineCount() → number</code></dt>
       <dd>Get the number of lines in the editor.</dd>
 
@@ -867,6 +860,13 @@
     will cause the given value (usually a method) to be added to all
     CodeMirror instances created from then on.</p>
 
+    <p id="defineOption">Similarly, <code>CodeMirror.defineOption(name,
+    default, updateFunc)</code> can be used to define new options for
+    CodeMirror. The <code>updateFunc</code> will be called with the
+    editor instance and the new value when an editor is initialized,
+    and whenever the option is modified
+    through <a href="#setOption"><code>setOption</code></a>.</p>
+
     <h2 id="addons">Add-ons</h2>
 
     <p>The <code>lib/util</code> directory in the distribution
@@ -917,6 +917,14 @@
       on <code>searchcursor.js</code>, and will make use
       of <a href="#util_dialog"><code>openDialog</code></a> when
       available to make prompting for search queries less ugly.</dd>
+      <dt id="util_matchbrackets"><a href="../lib/util/matchbrackets.js"><code>matchbrackets.js</code></a></dt>
+      <dd>Defines an option <code>matchBrackets</code> which, when set
+      to true, causes matching brackets to be highlighted whenever the
+      cursor is next to them. It also adds a
+      method <code>matchBrackets</code> that forces this to happen
+      once, and a method <code>findMatchingBracket</code> that can be
+      used to run the bracket-finding algorithm that this uses
+      internally.</dd>
       <dt id="util_foldcode"><a href="../lib/util/foldcode.js"><code>foldcode.js</code></a></dt>
       <dd>Helps with code folding.
       See <a href="../demo/folding.html">the demo</a> for an example.
diff --git a/lib/codemirror.js b/lib/codemirror.js
index afc15dd83ef1448d0d78bc0134006344d3721c7b..54af4cad2e5393fd5f8734f9cea350281f8bc88a 100644
--- a/lib/codemirror.js
+++ b/lib/codemirror.js
@@ -21,19 +21,21 @@ window.CodeMirror = (function() {
       replaceSelection: operation(replaceSelection),
       focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},
       setOption: function(option, value) {
-        var oldVal = options[option];
+        if (options[option] == value) return;
         options[option] = value;
         if (option == "mode" || option == "indentUnit") loadMode();
         else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();}
         else if (option == "readOnly" && !value) {resetInput(true);}
         else if (option == "theme") themeChanged();
-        else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
+        else if (option == "lineWrapping") operation(wrappingChanged)();
         else if (option == "tabSize") updateDisplay(true);
         else if (option == "keyMap") keyMapChanged();
         else if (option == "gutters" || option == "lineNumbers") setGuttersForLineNumbers();
         if (option == "lineNumbers" || option == "gutters" || option == "firstLineNumber" ||
             option == "theme" || option == "lineNumberFormatter")
           guttersChanged();
+        if (optionHandlers.hasOwnProperty(option))
+          optionHandlers[option](instance, value);
       },
       getOption: function(option) {return options[option];},
       undo: operation(undo),
@@ -57,7 +59,6 @@ window.CodeMirror = (function() {
         history.time = 0;
         return {done: history.done.concat([]), undone: history.undone.concat([])};
       },
-      matchBrackets: operation(function(){matchBrackets(true);}),
       getTokenAt: operation(function(pos) {
         pos = clipPos(pos);
         return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), options.tabSize, pos.ch);
@@ -2012,46 +2013,6 @@ window.CodeMirror = (function() {
       }, options.cursorBlinkRate);
     }
 
-    var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
-    function matchBrackets(autoclear) {
-      var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;
-      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
-      if (!match) return;
-      var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles;
-      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)
-        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}
-
-      var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
-      function scan(line, from, to) {
-        if (!line.text) return;
-        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;
-        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {
-          var text = st[i];
-          if (st[i+1] != style) {pos += d * text.length; continue;}
-          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {
-            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {
-              var match = matching[cur];
-              if (match.charAt(1) == ">" == forward) stack.push(cur);
-              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
-              else if (!stack.length) return {pos: pos, match: true};
-            }
-          }
-        }
-      }
-      for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {
-        var line = getLine(i), first = i == head.line;
-        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);
-        if (found) break;
-      }
-      if (!found) found = {pos: null, match: false};
-      var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
-      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),
-          two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);
-      var clear = operation(function(){one.clear(); two && two.clear();});
-      if (autoclear) setTimeout(clear, 800);
-      else bracketHighlighted = clear;
-    }
-
     // Finds the line to start with when starting a parse. Tries to
     // find a line with a stateAfter, so that it can start with a
     // valid state. If that fails, it returns the line with the
@@ -2168,11 +2129,6 @@ window.CodeMirror = (function() {
           (updateInput === true || (updateInput !== false && selectionChanged)))
         resetInput(userSelChange);
 
-      if (selectionChanged && options.matchBrackets)
-        setTimeout(operation(function() {
-          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}
-          if (posEq(sel.from, sel.to)) matchBrackets(false);
-        }), 20);
       var sc = selectionChanged, cbs = delayedCallbacks; // these can be reset by callbacks
       delayedCallbacks = null;
       if (textChanged)
@@ -2200,6 +2156,9 @@ window.CodeMirror = (function() {
       if (extensions.propertyIsEnumerable(ext) &&
           !instance.propertyIsEnumerable(ext))
         instance[ext] = extensions[ext];
+    for (var opt in optionHandlers)
+      if (optionHandlers.propertyIsEnumerable(opt))
+        optionHandlers[opt](instance, options[opt]);
     return instance;
   } // (end of function CodeMirror)
 
@@ -2225,7 +2184,6 @@ window.CodeMirror = (function() {
     firstLineNumber: 1,
     readOnly: false,
     dragDrop: true,
-    matchBrackets: false,
     cursorBlinkRate: 530,
     workTime: 100,
     workDelay: 200,
@@ -2284,6 +2242,11 @@ window.CodeMirror = (function() {
   CodeMirror.defineExtension = function(name, func) {
     extensions[name] = func;
   };
+  var optionHandlers = CodeMirror.optionHandlers = {};
+  CodeMirror.defineOption = function(name, deflt, handler) {
+    CodeMirror.defaults[name] = deflt;
+    optionHandlers[name] = handler;
+  };
 
   var commands = CodeMirror.commands = {
     selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},
diff --git a/lib/util/matchbrackets.js b/lib/util/matchbrackets.js
new file mode 100644
index 0000000000000000000000000000000000000000..52583e2f26eafd47a4bfaa70d7ce6d4f91cad289
--- /dev/null
+++ b/lib/util/matchbrackets.js
@@ -0,0 +1,61 @@
+(function() {
+  var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
+  function findMatchingBracket(cm) {
+    var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
+    var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
+    if (!match) return null;
+    var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1;
+    var style = cm.getTokenAt({line: cur.line, ch: pos + 1}).className;
+
+    var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
+    function scan(line, lineNo, start) {
+      if (!line.text) return;
+      var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
+      if (start != null) pos = start + d;
+      for (; pos != end; pos += d) {
+        var ch = line.text.charAt(pos);
+        if (re.test(ch) && cm.getTokenAt({line: lineNo, ch: pos + 1}).className == style) {
+          var match = matching[ch];
+          if (match.charAt(1) == ">" == forward) stack.push(ch);
+          else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
+          else if (!stack.length) return {pos: pos, match: true};
+        }
+      }
+    }
+    for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
+      if (i == cur.line) found = scan(line, i, pos);
+      else found = scan(cm.getLineHandle(i), i);
+      if (found) break;
+    }
+    return {from: {line: cur.line, ch: pos}, to: found && {line: i, ch: found.pos}, match: found && found.match};
+  }
+
+  function matchBrackets(cm, autoclear) {
+    var found = findMatchingBracket(cm);
+    if (!found) return;
+    var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
+    var one = cm.markText(found.from, {line: found.from.line, ch: found.from.ch + 1}, style);
+    var two = found.to && cm.markText(found.to, {line: found.to.line, ch: found.to.ch + 1}, style);
+    var clear = function() {
+      cm.operation(function() { one.clear(); two && two.clear(); });
+    };
+    if (autoclear) setTimeout(clear, 800);
+    else return clear;
+  }
+
+  var currentlyHighlighted = null;
+  function doMatchBrackets(cm) {
+    setTimeout(cm.operation(function() {
+      if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
+      if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
+    }), 20);
+  }
+
+  CodeMirror.defineOption("matchBrackets", false, function(cm, val) {
+    if (val) cm.connect("cursorActivity", doMatchBrackets);
+    else cm.disconnect("cursorActivity", doMatchBrackets);
+  });
+
+  CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
+  CodeMirror.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);});
+})();
diff --git a/mode/clike/index.html b/mode/clike/index.html
index 90a5fc105b100b15387696934b0f0912bc6d4d63..ca10c4bc23a9cba1d55597f2ecd2ce72710702c7 100644
--- a/mode/clike/index.html
+++ b/mode/clike/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: C-like mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="clike.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style>.CodeMirror {border: 2px inset #dee;}</style>
diff --git a/mode/clike/scala.html b/mode/clike/scala.html
index a5aba99cacd7c386dbec2ddcce9feb84208cd942..39115967ab8b452c649a17f0309695a673dcf318 100644
--- a/mode/clike/scala.html
+++ b/mode/clike/scala.html
@@ -6,6 +6,7 @@
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <link rel="stylesheet" href="../../theme/ambiance.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="clike.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style>
diff --git a/mode/ecl/index.html b/mode/ecl/index.html
index d6b41f4e5f9261223222c3d67ae0dba677c7ea02..77006ae6e6014492d84df8ec105ee5d8e941c9d7 100644
--- a/mode/ecl/index.html
+++ b/mode/ecl/index.html
@@ -29,10 +29,7 @@ d := dataset('tmp::qb', r, thor);
 output(d);
 </textarea></form>
     <script>
-      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
-        tabMode: "indent",
-        matchBrackets: true,
-      });
+      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
     </script>
 
     <p>Based on CodeMirror's clike mode.  For more information see <a href="http://hpccsystems.com">HPCC Systems</a> web site.</p>
diff --git a/mode/erlang/index.html b/mode/erlang/index.html
index c28389aa9051d640c2a2b1f04c6aebdbe3f97ebe..f6bee8f7233615e06bc23760856a88ea91fe1803 100644
--- a/mode/erlang/index.html
+++ b/mode/erlang/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: Erlang mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="erlang.js"></script>
     <link rel="stylesheet" href="../../theme/erlang-dark.css">
     <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
diff --git a/mode/gfm/index.html b/mode/gfm/index.html
index d0214c17d6af7a4de899f835b3083cccb2041675..08c8b227911e5fafaf8017c4c252dda5148b04f0 100644
--- a/mode/gfm/index.html
+++ b/mode/gfm/index.html
@@ -39,7 +39,6 @@ See http://github.github.com/github-flavored-markdown/
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         mode: 'gfm',
         lineNumbers: true,
-        matchBrackets: true,
         theme: "default"
       });
     </script>
diff --git a/mode/go/index.html b/mode/go/index.html
index 24b1cb9db0057676ee8da2cbaa670a65253cf75b..1a9ef53852f40a7de0ea50be12e60a53f78b7da0 100644
--- a/mode/go/index.html
+++ b/mode/go/index.html
@@ -6,6 +6,7 @@
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <link rel="stylesheet" href="../../theme/elegant.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="go.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>
diff --git a/mode/groovy/index.html b/mode/groovy/index.html
index 0393362a47cf428403ac73183f88843f8958043a..d0d76bfa90f8c0f44defdd1fcd8fefce9ec258f3 100644
--- a/mode/groovy/index.html
+++ b/mode/groovy/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: Groovy mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="groovy.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>
diff --git a/mode/haskell/index.html b/mode/haskell/index.html
index 963430f3f6f34d10402bb198cbb25d9dc454620e..b304a2768284e5361fcdd123854181abde109030 100644
--- a/mode/haskell/index.html
+++ b/mode/haskell/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: Haskell mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="haskell.js"></script>
     <link rel="stylesheet" href="../../theme/elegant.css">
     <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
diff --git a/mode/haxe/index.html b/mode/haxe/index.html
index ee5983ae0d28153263ee145b99ea5300c6ce1352..1125741ad570d2a66ae8e4566be49774245572e6 100644
--- a/mode/haxe/index.html
+++ b/mode/haxe/index.html
@@ -80,7 +80,6 @@ enum Color
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         indentUnit: 4,
         indentWithTabs: true
       });
diff --git a/mode/htmlembedded/index.html b/mode/htmlembedded/index.html
index a4b5883676445f41e80dbf59e1f74f8b9fd1c1fe..5a37dd637dfe12b331a269b6dc0a77cbecf1a9dd 100644
--- a/mode/htmlembedded/index.html
+++ b/mode/htmlembedded/index.html
@@ -32,7 +32,6 @@ This is an example of EJS (embedded javascript)
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         mode: "application/x-ejs",
         indentUnit: 4,
         indentWithTabs: true,
diff --git a/mode/javascript/index.html b/mode/javascript/index.html
index 206df3fca1b5011e2ea3664fcfe68c3d1ed68b32..3d5b2ea80e64cb4c5f41c4edbb8d1fd9ef468354 100644
--- a/mode/javascript/index.html
+++ b/mode/javascript/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: JavaScript mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="javascript.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
diff --git a/mode/less/index.html b/mode/less/index.html
index 69467bbb2d47d82a7d9154bd55902b565764d01f..dd2f588fd9264fffdfa34c94ac72a9908b921780 100644
--- a/mode/less/index.html
+++ b/mode/less/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: LESS mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="less.js"></script>
     <style>.CodeMirror {background: #f8f8f8; border: 1px solid #ddd; font-size:12px} .CodeMirror-scroll {height: 400px}</style>
     <link rel="stylesheet" href="../../doc/docs.css">
diff --git a/mode/lua/index.html b/mode/lua/index.html
index 6e984f414994cf9c6df71c15a581512fb6e4f84d..df83f9b47d1e85e6aa2eac19d7bfe7ae00f2bf69 100644
--- a/mode/lua/index.html
+++ b/mode/lua/index.html
@@ -4,6 +4,7 @@
     <meta charset="utf-8">
     <title>CodeMirror: Lua mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="../../lib/codemirror.js"></script>
     <script src="lua.js"></script>
     <link rel="stylesheet" href="../../theme/neat.css">
diff --git a/mode/markdown/index.html b/mode/markdown/index.html
index 59e79f6fd048d2c50cc910d046152b8df2a4d7e1..f5bd1f7f88d19848bdf72918decdd4a2528e0ecc 100644
--- a/mode/markdown/index.html
+++ b/mode/markdown/index.html
@@ -328,7 +328,6 @@ Output:
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         mode: 'markdown',
         lineNumbers: true,
-        matchBrackets: true,
         theme: "default"
       });
     </script>
diff --git a/mode/mysql/index.html b/mode/mysql/index.html
index bbac836bd16f619a0630f8e060f86e492f4698aa..0403a9699ea8487c66c6113e6baacf0407c2c49f 100644
--- a/mode/mysql/index.html
+++ b/mode/mysql/index.html
@@ -31,8 +31,7 @@ LIMIT 0,30;
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         mode: "text/x-mysql",
-        tabMode: "indent",
-        matchBrackets: true
+        tabMode: "indent"
       });
     </script>
 
diff --git a/mode/ocaml/index.html b/mode/ocaml/index.html
index d286edc17693f8732407c89b312e477e9f1db40f..962fa29eb1efb5375c201514dbb4f368ab640bcd 100644
--- a/mode/ocaml/index.html
+++ b/mode/ocaml/index.html
@@ -10,6 +10,7 @@
 </style>
 
 <script src=../../lib/codemirror.js></script>
+<script src=../../lib/util/matchbrackets.js></script>
 <script src=ocaml.js></script>
 
 <h1>CodeMirror: OCaml mode</h1>
diff --git a/mode/pascal/index.html b/mode/pascal/index.html
index ffd3c741723c6ca09c9381a1e9b948bd7515b259..b3016afb10cbd2bb30b33509e096335cf219e010 100644
--- a/mode/pascal/index.html
+++ b/mode/pascal/index.html
@@ -39,7 +39,6 @@ end;
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         mode: "text/x-pascal"
       });
     </script>
diff --git a/mode/perl/index.html b/mode/perl/index.html
index 8f0b38da2a6b81db2c4a130252f8082b406d5f14..13c7af64d3c79c51f7737915e7e44c844b3d26be 100644
--- a/mode/perl/index.html
+++ b/mode/perl/index.html
@@ -53,8 +53,7 @@ something...
 
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
-        lineNumbers: true,
-        matchBrackets: true
+        lineNumbers: true
       });
     </script>
 
diff --git a/mode/php/index.html b/mode/php/index.html
index cd189a4dec7055568efab16676deafea92a944c7..9ac66ccb0f83a6b644e18f4227beff83896b4571 100644
--- a/mode/php/index.html
+++ b/mode/php/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: PHP mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="../xml/xml.js"></script>
     <script src="../javascript/javascript.js"></script>
     <script src="../css/css.js"></script>
diff --git a/mode/pig/index.html b/mode/pig/index.html
index 02b0368a108771d13bff8b416c4e6854f313f3fa..1b0c60267f830c3bd924dc32a6f70452645b442e 100644
--- a/mode/pig/index.html
+++ b/mode/pig/index.html
@@ -28,7 +28,6 @@ STORE c INTO "\path\to\output";
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         indentUnit: 4,
         mode: "text/x-pig"
       });
diff --git a/mode/plsql/index.html b/mode/plsql/index.html
index 3fd00a79e5b94c431092af90ec283be1e7f6e798..9206e42403ff65d038cfe8d74c9a2c314b6d7c84 100644
--- a/mode/plsql/index.html
+++ b/mode/plsql/index.html
@@ -48,7 +48,6 @@ END;
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         indentUnit: 4,
         mode: "text/x-plsql"
       });
diff --git a/mode/python/index.html b/mode/python/index.html
index 9f1164e2e75c7ae058e79a7499a1a1fac50108fa..7a26d278dbb16e8f3acd25cbdeeedce39d614064 100644
--- a/mode/python/index.html
+++ b/mode/python/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: Python mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="python.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
diff --git a/mode/rpm/changes/index.html b/mode/rpm/changes/index.html
index 3f3dccc8710366caaf5464ac27da7799468eb242..e0e2d8778bd0e8e128ac8348b60a4b77d49fb97d 100644
--- a/mode/rpm/changes/index.html
+++ b/mode/rpm/changes/index.html
@@ -44,8 +44,7 @@ Wed Oct  5 14:34:10 UTC 2011 - misterx@example.com
         mode: {name: "changes"},
         lineNumbers: true,
         indentUnit: 4,
-        tabMode: "shift",
-        matchBrackets: true
+        tabMode: "shift"
       });
     </script>
 
diff --git a/mode/rpm/spec/index.html b/mode/rpm/spec/index.html
index 23aef9841c64aec0cf8a2cb2e44d43fe444c4050..8be98b63ec3c9b5f7d1167e2462053376839bb60 100644
--- a/mode/rpm/spec/index.html
+++ b/mode/rpm/spec/index.html
@@ -90,8 +90,7 @@ find %{buildroot} -type f -name '*.la' -exec rm -f {} ';'
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         mode: {name: "spec"},
         lineNumbers: true,
-        indentUnit: 4,
-        matchBrackets: true
+        indentUnit: 4
       });
     </script>
 
diff --git a/mode/ruby/index.html b/mode/ruby/index.html
index 282115b62a7a5e58b9b4260c5d8ed80e142e1343..f226289d7d9b8d08a62ea262a2415083c41513a1 100644
--- a/mode/ruby/index.html
+++ b/mode/ruby/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: Ruby mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="ruby.js"></script>
     <style>
       .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
diff --git a/mode/rust/index.html b/mode/rust/index.html
index b3bbb1f8d9577c00f85b3abb15f7d4d92fb56d8d..a6d47fe84db98e7804c6d36370c4124dab41d9c7 100644
--- a/mode/rust/index.html
+++ b/mode/rust/index.html
@@ -39,7 +39,6 @@ fn check_crate(x: int) {
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         tabMode: "indent"
       });
     </script>
diff --git a/mode/shell/index.html b/mode/shell/index.html
index 2d6d0847234441447781dd442cda04d39cbb603c..0827053ceebbf7f80af9c74e8a39c4dd79d18e50 100644
--- a/mode/shell/index.html
+++ b/mode/shell/index.html
@@ -10,6 +10,7 @@
 </style>
 
 <script src=../../lib/codemirror.js></script>
+<script src="../../lib/util/matchbrackets.js"></script>
 <script src=shell.js></script>
 
 <h1>CodeMirror: Shell mode</h1>
diff --git a/mode/smalltalk/index.html b/mode/smalltalk/index.html
index 9a48ec19fc24a0d46ec56f7c3abce634c7d60f5d..690b560fd7f6d032689d0420431c4dbdda2bbdc8 100644
--- a/mode/smalltalk/index.html
+++ b/mode/smalltalk/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: Smalltalk mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="smalltalk.js"></script>
     <link rel="stylesheet" href="../../doc/docs.css">
     <style>
diff --git a/mode/sparql/index.html b/mode/sparql/index.html
index b7eafa3ca88e8733182844e0478bb79982f9c1d6..a99febd5305b4d33249eed9d2661ba2f647fac14 100644
--- a/mode/sparql/index.html
+++ b/mode/sparql/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: SPARQL mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="sparql.js"></script>
     <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
     <link rel="stylesheet" href="../../doc/docs.css">
diff --git a/mode/tiddlywiki/index.html b/mode/tiddlywiki/index.html
index 40c2dff5b307dc009f2c4a044d4fa330063c1846..89ae85892b211af3e9ad27542106a22440cf4ecb 100644
--- a/mode/tiddlywiki/index.html
+++ b/mode/tiddlywiki/index.html
@@ -5,6 +5,7 @@
     <title>CodeMirror: TiddlyWiki mode</title>
     <link rel="stylesheet" href="../../lib/codemirror.css">
     <script src="../../lib/codemirror.js"></script>
+    <script src="../../lib/util/matchbrackets.js"></script>
     <script src="tiddlywiki.js"></script>
     <link rel="stylesheet" href="tiddlywiki.css">
     <link rel="stylesheet" href="../../doc/docs.css">
diff --git a/mode/tiki/index.html b/mode/tiki/index.html
index 3579cff50811cc60b96618f8dc4cce71d1a56761..7b85a44a7e0b1edd81da263419e0bafdc7fe8707 100644
--- a/mode/tiki/index.html
+++ b/mode/tiki/index.html
@@ -73,9 +73,7 @@ Plugin (inline):
 <script type="text/javascript">
 	var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         mode: 'tiki',      
-        lineNumbers: true,
-        enterMode: 'keep',
-        matchBrackets: true
+        lineNumbers: true
     });
 </script>
 
diff --git a/mode/vb/index.html b/mode/vb/index.html
index af313419be06627d982655ac05f3b49cf436cf57..55dfabfa5671e55de73a6e8f8b11484e5dbafe50 100644
--- a/mode/vb/index.html
+++ b/mode/vb/index.html
@@ -65,7 +65,6 @@ function initText(editor) {
 function init() {
     editor = CodeMirror.fromTextArea(document.getElementById("solution"), {
         lineNumbers: true,
-        matchBrackets: true,
         mode: "text/x-vb",
         readOnly: false,
         tabMode: "shift"
diff --git a/mode/vbscript/index.html b/mode/vbscript/index.html
index e7375fb0fc9723d7789f7a6436476d47fc445729..8c86f9ef9424fd506b8ac2c598e6c4477ac2433f 100644
--- a/mode/vbscript/index.html
+++ b/mode/vbscript/index.html
@@ -32,8 +32,7 @@ End If
 
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
-        lineNumbers: true,
-        matchBrackets: true
+        lineNumbers: true
       });
     </script>
 
diff --git a/mode/velocity/index.html b/mode/velocity/index.html
index 1e25c651e700d0fb2fa5ab519adf2b3a357efa95..fb59cb590df7c0c11e38719611454fa2ef1cb963 100644
--- a/mode/velocity/index.html
+++ b/mode/velocity/index.html
@@ -90,7 +90,6 @@ Addition: #set( $value = $foo + 1 )
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         tabMode: "indent",
-        matchBrackets: true,
         theme: "night",
         lineNumbers: true,
         indentUnit: 4,
diff --git a/mode/verilog/index.html b/mode/verilog/index.html
index f251a34433870240651acec418b2da477b7580dd..c1d14d682a1b61bccd60b836978986788cfa9cd3 100644
--- a/mode/verilog/index.html
+++ b/mode/verilog/index.html
@@ -197,7 +197,6 @@ endmodule
     <script>
       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
         lineNumbers: true,
-        matchBrackets: true,
         mode: "text/x-verilog"
       });
     </script>