| 1929 | |
| 1930 | var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; |
| 1931 | function matchBrackets(autoclear) { |
| 1932 | var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1; |
| 1933 | var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; |
| 1934 | if (!match) return; |
| 1935 | var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles; |
| 1936 | for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2) |
| 1937 | if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;} |
| 1938 | |
| 1939 | var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; |
| 1940 | function scan(line, from, to) { |
| 1941 | if (!line.text) return; |
| 1942 | var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur; |
| 1943 | for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) { |
| 1944 | var text = st[i]; |
| 1945 | if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;} |
| 1946 | for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) { |
| 1947 | if (pos >= from && pos < to && re.test(cur = text.charAt(j))) { |
| 1948 | var match = matching[cur]; |
| 1949 | if (match.charAt(1) == ">" == forward) stack.push(cur); |
| 1950 | else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; |
| 1951 | else if (!stack.length) return {pos: pos, match: true}; |
| 1952 | } |
| 1953 | } |
| 1954 | } |
| 1955 | } |
| 1956 | for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) { |
| 1957 | var line = getLine(i), first = i == head.line; |
| 1958 | var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length); |
| 1959 | if (found) break; |
| 1960 | } |
| 1961 | if (!found) found = {pos: null, match: false}; |
| 1962 | var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; |
| 1963 | var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style), |
| 1964 | two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style); |
| 1965 | var clear = operation(function(){one.clear(); two && two.clear();}); |
| 1966 | if (autoclear) setTimeout(clear, 800); |
| 1967 | else bracketHighlighted = clear; |
| 1968 | } |
| 1969 | |
| 1970 | // Finds the line to start with when starting a parse. Tries to |
| 1971 | // find a line with a stateAfter, so that it can start with a |