(function() {
  var Point;

  Point = require('atom').Point;

  describe("bracket matching", function() {
    var buffer, editor, editorElement, _ref;
    _ref = [], editorElement = _ref[0], editor = _ref[1], buffer = _ref[2];
    beforeEach(function() {
      atom.config.set('bracket-matcher.autocompleteBrackets', true);
      waitsForPromise(function() {
        return atom.workspace.open('sample.js');
      });
      waitsForPromise(function() {
        return atom.packages.activatePackage('bracket-matcher');
      });
      waitsForPromise(function() {
        return atom.packages.activatePackage('language-javascript');
      });
      waitsForPromise(function() {
        return atom.packages.activatePackage('language-xml');
      });
      return runs(function() {
        editor = atom.workspace.getActiveTextEditor();
        editorElement = atom.views.getView(editor);
        return buffer = editor.getBuffer();
      });
    });
    describe("matching bracket highlighting", function() {
      var expectHighlights, expectNoHighlights;
      expectNoHighlights = function() {
        var decorations;
        decorations = editor.getHighlightDecorations().filter(function(decoration) {
          return decoration.properties["class"] === 'bracket-matcher';
        });
        return expect(decorations.length).toBe(0);
      };
      expectHighlights = function(startBufferPosition, endBufferPosition) {
        var decorations;
        decorations = editor.getHighlightDecorations().filter(function(decoration) {
          return decoration.properties["class"] === 'bracket-matcher';
        });
        expect(decorations.length).toBe(2);
        expect(decorations[0].marker.getStartBufferPosition()).toEqual(startBufferPosition);
        return expect(decorations[1].marker.getStartBufferPosition()).toEqual(endBufferPosition);
      };
      describe("when the cursor is before a starting pair", function() {
        return it("highlights the starting pair and ending pair", function() {
          editor.moveToEndOfLine();
          editor.moveLeft();
          return expectHighlights([0, 28], [12, 0]);
        });
      });
      describe("when the cursor is after a starting pair", function() {
        return it("highlights the starting pair and ending pair", function() {
          editor.moveToEndOfLine();
          return expectHighlights([0, 28], [12, 0]);
        });
      });
      describe("when the cursor is before an ending pair", function() {
        return it("highlights the starting pair and ending pair", function() {
          editor.moveToBottom();
          editor.moveLeft();
          editor.moveLeft();
          return expectHighlights([12, 0], [0, 28]);
        });
      });
      describe("when the cursor is after an ending pair", function() {
        return it("highlights the starting pair and ending pair", function() {
          editor.moveToBottom();
          editor.moveLeft();
          return expectHighlights([12, 0], [0, 28]);
        });
      });
      describe("when there are unpaired brackets", function() {
        return it("highlights the correct start/end pairs", function() {
          editor.setText('(()');
          editor.setCursorBufferPosition([0, 0]);
          expectNoHighlights();
          editor.setCursorBufferPosition([0, 1]);
          expectHighlights([0, 1], [0, 2]);
          editor.setCursorBufferPosition([0, 2]);
          expectHighlights([0, 1], [0, 2]);
          editor.setText('())');
          editor.setCursorBufferPosition([0, 0]);
          expectHighlights([0, 0], [0, 1]);
          editor.setCursorBufferPosition([0, 1]);
          expectHighlights([0, 0], [0, 1]);
          editor.setCursorBufferPosition([0, 2]);
          return expectNoHighlights();
        });
      });
      describe("when the cursor is moved off a pair", function() {
        return it("removes the starting pair and ending pair highlights", function() {
          editor.moveToEndOfLine();
          expectHighlights([0, 28], [12, 0]);
          editor.moveToBeginningOfLine();
          return expectNoHighlights();
        });
      });
      describe("when the pair moves", function() {
        return it("repositions the highlights", function() {
          editor.moveToEndOfLine();
          editor.moveLeft();
          expectHighlights([0, 28], [12, 0]);
          editor.deleteToBeginningOfLine();
          return expectHighlights([0, 0], [12, 0]);
        });
      });
      describe("pair balancing", function() {
        return describe("when a second starting pair preceeds the first ending pair", function() {
          return it("advances to the second ending pair", function() {
            editor.setCursorBufferPosition([8, 42]);
            return expectHighlights([8, 42], [8, 54]);
          });
        });
      });
      describe("when the cursor is destroyed", function() {
        return it("updates the highlights to use the editor's last cursor", function() {
          editor.setCursorBufferPosition([0, 29]);
          editor.addCursorAtBufferPosition([9, 0]);
          expectHighlights([0, 28], [12, 0]);
          editor.consolidateSelections();
          expectNoHighlights();
          editor.setCursorBufferPosition([0, 29]);
          return expectHighlights([0, 28], [12, 0]);
        });
      });
      return describe("HTML/XML tag matching", function() {
        beforeEach(function() {
          waitsForPromise(function() {
            return atom.workspace.open('sample.xml');
          });
          return runs(function() {
            editor = atom.workspace.getActiveTextEditor();
            editorElement = atom.views.getView(editor);
            return buffer = editor.buffer, editor;
          });
        });
        describe("when on an opening tag", function() {
          return it("highlight the opening and closing tag", function() {
            buffer.setText("<test>\n  <test>text</test>\n  <!-- </test> -->\n</test>");
            editor.setCursorBufferPosition([0, 0]);
            expectHighlights([0, 1], [3, 2]);
            editor.setCursorBufferPosition([0, 1]);
            return expectHighlights([0, 1], [3, 2]);
          });
        });
        describe("when on a closing tag", function() {
          return it("highlight the opening and closing tag", function() {
            buffer.setText("<test>\n  <!-- <test> -->\n  <test>text</test>\n</test>");
            editor.setCursorBufferPosition([3, 0]);
            expectHighlights([3, 2], [0, 1]);
            editor.setCursorBufferPosition([3, 2]);
            expectHighlights([3, 2], [0, 1]);
            buffer.setText("<test>\n  <test>text</test>\n  <test>text</test>\n</test>");
            editor.setCursorBufferPosition([1, Infinity]);
            expectHighlights([1, 14], [1, 3]);
            editor.setCursorBufferPosition([2, Infinity]);
            return expectHighlights([2, 14], [2, 3]);
          });
        });
        describe("when the tag spans multiple lines", function() {
          return it("highlights the opening and closing tag", function() {
            buffer.setText("<test\n  a=\"test\">\n  text\n</test>");
            editor.setCursorBufferPosition([3, 2]);
            expectHighlights([3, 2], [0, 1]);
            editor.setCursorBufferPosition([0, 1]);
            return expectHighlights([0, 1], [3, 2]);
          });
        });
        describe("when the tag has attributes", function() {
          return it("highlights the opening and closing tags", function() {
            buffer.setText("<test a=\"test\">\n  text\n</test>");
            editor.setCursorBufferPosition([2, 2]);
            expectHighlights([2, 2], [0, 1]);
            editor.setCursorBufferPosition([0, 7]);
            return expectHighlights([0, 1], [2, 2]);
          });
        });
        return describe("when the opening and closing tags are on the same line", function() {
          return it("highlight the opening and closing tags", function() {
            buffer.setText("<test>text</test>");
            editor.setCursorBufferPosition([0, 2]);
            expectHighlights([0, 1], [0, 12]);
            editor.setCursorBufferPosition([0, 12]);
            return expectHighlights([0, 12], [0, 1]);
          });
        });
      });
    });
    describe("when bracket-matcher:go-to-matching-bracket is triggered", function() {
      describe("when the cursor is before the starting pair", function() {
        return it("moves the cursor to after the ending pair", function() {
          editor.moveToEndOfLine();
          editor.moveLeft();
          atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
          return expect(editor.getCursorBufferPosition()).toEqual([12, 1]);
        });
      });
      describe("when the cursor is after the starting pair", function() {
        return it("moves the cursor to before the ending pair", function() {
          editor.moveToEndOfLine();
          atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
          return expect(editor.getCursorBufferPosition()).toEqual([12, 0]);
        });
      });
      describe("when the cursor is before the ending pair", function() {
        return it("moves the cursor to after the starting pair", function() {
          editor.setCursorBufferPosition([12, 0]);
          atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
          return expect(editor.getCursorBufferPosition()).toEqual([0, 29]);
        });
      });
      describe("when the cursor is after the ending pair", function() {
        return it("moves the cursor to before the starting pair", function() {
          editor.setCursorBufferPosition([12, 1]);
          atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
          return expect(editor.getCursorBufferPosition()).toEqual([0, 28]);
        });
      });
      return describe("when the cursor is not adjacent to a pair", function() {
        describe("when within a `{}` pair", function() {
          return it("moves the cursor to before the enclosing brace", function() {
            editor.setCursorBufferPosition([11, 2]);
            atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
            return expect(editor.getCursorBufferPosition()).toEqual([0, 28]);
          });
        });
        describe("when within a `()` pair", function() {
          return it("moves the cursor to before the enclosing brace", function() {
            editor.setCursorBufferPosition([2, 14]);
            atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
            return expect(editor.getCursorBufferPosition()).toEqual([2, 7]);
          });
        });
        return describe('in HTML/XML files', function() {
          beforeEach(function() {
            waitsForPromise(function() {
              return atom.workspace.open('sample.xml');
            });
            return runs(function() {
              editor = atom.workspace.getActiveTextEditor();
              editorElement = atom.views.getView(editor);
              return buffer = editor.buffer, editor;
            });
          });
          describe('when within a <tag></tag> pair', function() {
            return it("moves the cursor to the starting tag", function() {
              editor.setCursorBufferPosition([5, 10]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              return expect(editor.getCursorBufferPosition()).toEqual([4, 9]);
            });
          });
          describe('when on a starting <tag>', function() {
            return it('moves the cursor to the end </tag>', function() {
              editor.setCursorBufferPosition([1, 2]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 2]);
              editor.setCursorBufferPosition([1, 3]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 4]);
              editor.setCursorBufferPosition([1, 4]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 5]);
              editor.setCursorBufferPosition([1, 5]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 6]);
              editor.setCursorBufferPosition([1, 6]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 7]);
              editor.setCursorBufferPosition([1, 7]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 8]);
              editor.setCursorBufferPosition([1, 8]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 8]);
              editor.setCursorBufferPosition([1, 9]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 8]);
              editor.setCursorBufferPosition([1, 10]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([15, 8]);
              editor.setCursorBufferPosition([1, 16]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              return expect(editor.getCursorBufferPosition()).toEqual([15, 8]);
            });
          });
          return describe('when on an ending </tag>', function() {
            return it('moves the cursor to the start <tag>', function() {
              editor.setCursorBufferPosition([15, 2]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 2]);
              editor.setCursorBufferPosition([15, 3]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 3]);
              editor.setCursorBufferPosition([15, 4]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 3]);
              editor.setCursorBufferPosition([15, 5]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 4]);
              editor.setCursorBufferPosition([15, 6]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 5]);
              editor.setCursorBufferPosition([15, 7]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 6]);
              editor.setCursorBufferPosition([15, 8]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              expect(editor.getCursorBufferPosition()).toEqual([1, 7]);
              editor.setCursorBufferPosition([15, 9]);
              atom.commands.dispatch(editorElement, "bracket-matcher:go-to-matching-bracket");
              return expect(editor.getCursorBufferPosition()).toEqual([1, 7]);
            });
          });
        });
      });
    });
    describe("when bracket-matcher:go-to-enclosing-bracket is triggered", function() {
      describe("when within a `{}` pair", function() {
        return it("moves the cursor to before the enclosing brace", function() {
          editor.setCursorBufferPosition([11, 2]);
          atom.commands.dispatch(editorElement, "bracket-matcher:go-to-enclosing-bracket");
          return expect(editor.getCursorBufferPosition()).toEqual([0, 28]);
        });
      });
      return describe("when within a `()` pair", function() {
        return it("moves the cursor to before the enclosing brace", function() {
          editor.setCursorBufferPosition([2, 14]);
          atom.commands.dispatch(editorElement, "bracket-matcher:go-to-enclosing-bracket");
          return expect(editor.getCursorBufferPosition()).toEqual([2, 7]);
        });
      });
    });
    describe("when bracket-match:select-inside-brackets is triggered", function() {
      describe("when the cursor on the left side of a bracket", function() {
        return it("selects the text inside the brackets", function() {
          editor.setCursorBufferPosition([0, 28]);
          atom.commands.dispatch(editorElement, "bracket-matcher:select-inside-brackets");
          return expect(editor.getSelectedBufferRange()).toEqual([[0, 29], [12, 0]]);
        });
      });
      describe("when the cursor on the right side of a bracket", function() {
        return it("selects the text inside the brackets", function() {
          editor.setCursorBufferPosition([1, 30]);
          atom.commands.dispatch(editorElement, "bracket-matcher:select-inside-brackets");
          return expect(editor.getSelectedBufferRange()).toEqual([[1, 30], [9, 2]]);
        });
      });
      describe("when the cursor is inside the brackets", function() {
        return it("selects the text for the closest outer brackets", function() {
          editor.setCursorBufferPosition([6, 6]);
          atom.commands.dispatch(editorElement, "bracket-matcher:select-inside-brackets");
          return expect(editor.getSelectedBufferRange()).toEqual([[4, 29], [7, 4]]);
        });
      });
      return describe('HTML/XML text', function() {
        beforeEach(function() {
          waitsForPromise(function() {
            return atom.workspace.open('sample.xml');
          });
          return runs(function() {
            editor = atom.workspace.getActiveTextEditor();
            editorElement = atom.views.getView(editor);
            return buffer = editor.buffer, editor;
          });
        });
        describe('when the cursor is on a starting tag', function() {
          return it('selects the text inside the starting/closing tag', function() {
            editor.setCursorBufferPosition([4, 9]);
            atom.commands.dispatch(editorElement, "bracket-matcher:select-inside-brackets");
            return expect(editor.getSelectedBufferRange()).toEqual([[4, 13], [6, 8]]);
          });
        });
        describe('when the cursor is on an ending tag', function() {
          return it('selects the text inside the starting/closing tag', function() {
            editor.setCursorBufferPosition([15, 8]);
            atom.commands.dispatch(editorElement, "bracket-matcher:select-inside-brackets");
            return expect(editor.getSelectedBufferRange()).toEqual([[1, 8], [15, 2]]);
          });
        });
        return describe('when the cursor is inside a tag', function() {
          return it('selects the text inside the starting/closing tag', function() {
            editor.setCursorBufferPosition([12, 8]);
            atom.commands.dispatch(editorElement, "bracket-matcher:select-inside-brackets");
            return expect(editor.getSelectedBufferRange()).toEqual([[11, 11], [13, 6]]);
          });
        });
      });
    });
    describe("when bracket-matcher:remove-matching-brackets is triggered", function() {
      describe("when the cursor is not in front of any pair", function() {
        return it("performs a regular backspace action", function() {
          editor.setCursorBufferPosition([0, 1]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(0)).toEqual('ar quicksort = function () {');
          return expect(editor.getCursorBufferPosition()).toEqual([0, 0]);
        });
      });
      describe("when the cursor is at the beginning of a line", function() {
        return it("performs a regular backspace action", function() {
          editor.setCursorBufferPosition([12, 0]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(11)).toEqual('  return sort(Array.apply(this, arguments));};');
          return expect(editor.getCursorBufferPosition()).toEqual([11, 44]);
        });
      });
      describe("when the cursor is on the left side of a starting pair", function() {
        return it("performs a regular backspace action", function() {
          editor.setCursorBufferPosition([0, 28]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(0)).toEqual('var quicksort = function (){');
          return expect(editor.getCursorBufferPosition()).toEqual([0, 27]);
        });
      });
      describe("when the cursor is on the left side of an ending pair", function() {
        return it("performs a regular backspace action", function() {
          editor.setCursorBufferPosition([7, 4]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(7)).toEqual('  }');
          return expect(editor.getCursorBufferPosition()).toEqual([7, 2]);
        });
      });
      describe("when the cursor is on the right side of a starting pair, the ending pair on another line", function() {
        return it("removes both pairs", function() {
          editor.setCursorBufferPosition([0, 29]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(0)).toEqual('var quicksort = function () ');
          expect(editor.lineTextForBufferRow(12)).toEqual(';');
          return expect(editor.getCursorBufferPosition()).toEqual([0, 28]);
        });
      });
      describe("when the cursor is on the right side of an ending pair, the starting pair on another line", function() {
        return it("removes both pairs", function() {
          editor.setCursorBufferPosition([7, 5]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(4)).toEqual('    while(items.length > 0) ');
          expect(editor.lineTextForBufferRow(7)).toEqual('    ');
          return expect(editor.getCursorBufferPosition()).toEqual([7, 4]);
        });
      });
      describe("when the cursor is on the right side of a starting pair, the ending pair on the same line", function() {
        return it("removes both pairs", function() {
          editor.setCursorBufferPosition([11, 14]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(11)).toEqual('  return sortArray.apply(this, arguments);');
          return expect(editor.getCursorBufferPosition()).toEqual([11, 13]);
        });
      });
      describe("when the cursor is on the right side of an ending pair, the starting pair on the same line", function() {
        return it("removes both pairs", function() {
          editor.setCursorBufferPosition([11, 43]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(11)).toEqual('  return sortArray.apply(this, arguments);');
          return expect(editor.getCursorBufferPosition()).toEqual([11, 41]);
        });
      });
      describe("when a starting pair is selected", function() {
        return it("removes both pairs", function() {
          editor.setSelectedBufferRange([[11, 13], [11, 14]]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(11)).toEqual('  return sortArray.apply(this, arguments);');
          return expect(editor.getCursorBufferPosition()).toEqual([11, 13]);
        });
      });
      return describe("when an ending pair is selected", function() {
        return it("removes both pairs", function() {
          editor.setSelectedBufferRange([[11, 42], [11, 43]]);
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-matching-brackets");
          expect(editor.lineTextForBufferRow(11)).toEqual('  return sortArray.apply(this, arguments);');
          return expect(editor.getCursorBufferPosition()).toEqual([11, 41]);
        });
      });
    });
    describe("matching bracket deletion", function() {
      beforeEach(function() {
        return editor.buffer.setText("");
      });
      describe("when selection is not a matching pair of brackets", function() {
        return it("does not change the text", function() {
          editor.insertText("\"woah(");
          editor.selectAll();
          atom.commands.dispatch(editorElement, "bracket-matcher:remove-brackets-from-selection");
          return expect(editor.buffer.getText()).toBe("\"woah(");
        });
      });
      return describe("when selecting a matching pair of brackets", function() {
        describe("on the same line", function() {
          beforeEach(function() {
            editor.buffer.setText("it \"does something\", :meta => true");
            editor.setSelectedBufferRange([[0, 3], [0, 19]]);
            return atom.commands.dispatch(editorElement, "bracket-matcher:remove-brackets-from-selection");
          });
          it("removes the brackets", function() {
            return expect(editor.buffer.getText()).toBe("it does something, :meta => true");
          });
          return it("selects the newly unbracketed text", function() {
            return expect(editor.getSelectedText()).toBe("does something");
          });
        });
        return describe("on separate lines", function() {
          beforeEach(function() {
            editor.buffer.setText("it (\"does something\" do\nend)");
            editor.setSelectedBufferRange([[0, 3], [1, 4]]);
            return atom.commands.dispatch(editorElement, "bracket-matcher:remove-brackets-from-selection");
          });
          it("removes the brackets", function() {
            return expect(editor.buffer.getText()).toBe("it \"does something\" do\nend");
          });
          return it("selects the newly unbracketed text", function() {
            return expect(editor.getSelectedText()).toBe("\"does something\" do\nend");
          });
        });
      });
    });
    describe("matching bracket insertion", function() {
      beforeEach(function() {
        editor.buffer.setText("");
        return atom.config.set('editor.autoIndent', true);
      });
      describe("when more than one character is inserted", function() {
        return it("does not insert a matching bracket", function() {
          editor.insertText("woah(");
          return expect(editor.buffer.getText()).toBe("woah(");
        });
      });
      describe("when there is a word character after the cursor", function() {
        return it("does not insert a matching bracket", function() {
          editor.buffer.setText("ab");
          editor.setCursorBufferPosition([0, 1]);
          editor.insertText("(");
          return expect(editor.buffer.getText()).toBe("a(b");
        });
      });
      describe("when autocompleteBrackets configuration is disabled", function() {
        return it("does not insert a matching bracket", function() {
          atom.config.set('bracket-matcher.autocompleteBrackets', false);
          editor.buffer.setText("}");
          editor.setCursorBufferPosition([0, 0]);
          editor.insertText('{');
          expect(buffer.lineForRow(0)).toBe("{}");
          return expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
        });
      });
      describe("when there are multiple cursors", function() {
        return it("inserts ) at each cursor", function() {
          editor.buffer.setText("()\nab\n[]\n12");
          editor.setCursorBufferPosition([3, 1]);
          editor.addCursorAtBufferPosition([2, 1]);
          editor.addCursorAtBufferPosition([1, 1]);
          editor.addCursorAtBufferPosition([0, 1]);
          editor.insertText(')');
          return expect(editor.buffer.getText()).toBe("())\na)b\n[)]\n1)2");
        });
      });
      describe("when there is a non-word character after the cursor", function() {
        return it("inserts a closing bracket after an opening bracket is inserted", function() {
          editor.buffer.setText("}");
          editor.setCursorBufferPosition([0, 0]);
          editor.insertText('{');
          expect(buffer.lineForRow(0)).toBe("{}}");
          return expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
        });
      });
      describe("when the cursor is at the end of the line", function() {
        return it("inserts a closing bracket after an opening bracket is inserted", function() {
          editor.buffer.setText("");
          editor.insertText('{');
          expect(buffer.lineForRow(0)).toBe("{}");
          expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          editor.buffer.setText("");
          editor.insertText('(');
          expect(buffer.lineForRow(0)).toBe("()");
          expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          editor.buffer.setText("");
          editor.insertText('[');
          expect(buffer.lineForRow(0)).toBe("[]");
          expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          editor.buffer.setText("");
          editor.insertText('"');
          expect(buffer.lineForRow(0)).toBe('""');
          expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          editor.buffer.setText("");
          editor.insertText("'");
          expect(buffer.lineForRow(0)).toBe("''");
          return expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
        });
      });
      describe("when the cursor is on a closing bracket and a closing bracket is inserted", function() {
        describe("when the closing bracket was there previously", function() {
          return it("inserts a closing bracket", function() {
            editor.insertText('()x');
            editor.setCursorBufferPosition([0, 1]);
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("())x");
            return expect(editor.getCursorBufferPosition().column).toBe(2);
          });
        });
        return describe("when the closing bracket was automatically inserted from inserting an opening bracket", function() {
          it("only moves cursor over the closing bracket one time", function() {
            editor.insertText('(');
            expect(buffer.lineForRow(0)).toBe("()");
            editor.setCursorBufferPosition([0, 1]);
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("()");
            expect(editor.getCursorBufferPosition()).toEqual([0, 2]);
            editor.setCursorBufferPosition([0, 1]);
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("())");
            return expect(editor.getCursorBufferPosition()).toEqual([0, 2]);
          });
          it("moves cursor over the closing bracket after other text is inserted", function() {
            editor.insertText('(');
            editor.insertText('ok cool');
            expect(buffer.lineForRow(0)).toBe("(ok cool)");
            editor.setCursorBufferPosition([0, 8]);
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("(ok cool)");
            return expect(editor.getCursorBufferPosition()).toEqual([0, 9]);
          });
          it("works with nested brackets", function() {
            editor.insertText('(');
            editor.insertText('1');
            editor.insertText('(');
            editor.insertText('2');
            expect(buffer.lineForRow(0)).toBe("(1(2))");
            editor.setCursorBufferPosition([0, 4]);
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("(1(2))");
            expect(editor.getCursorBufferPosition()).toEqual([0, 5]);
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("(1(2))");
            return expect(editor.getCursorBufferPosition()).toEqual([0, 6]);
          });
          it("works with mixed brackets", function() {
            editor.insertText('(');
            editor.insertText('}');
            expect(buffer.lineForRow(0)).toBe("(})");
            editor.insertText(')');
            expect(buffer.lineForRow(0)).toBe("(})");
            return expect(editor.getCursorBufferPosition()).toEqual([0, 3]);
          });
          return it("closes brackets with the same begin/end character correctly", function() {
            editor.insertText('"');
            editor.insertText('ok');
            expect(buffer.lineForRow(0)).toBe('"ok"');
            expect(editor.getCursorBufferPosition()).toEqual([0, 3]);
            editor.insertText('"');
            expect(buffer.lineForRow(0)).toBe('"ok"');
            return expect(editor.getCursorBufferPosition()).toEqual([0, 4]);
          });
        });
      });
      describe("when there is text selected on a single line", function() {
        it("wraps the selection with brackets", function() {
          editor.setText('text');
          editor.moveToBottom();
          editor.selectToTop();
          editor.selectAll();
          editor.insertText('(');
          expect(buffer.getText()).toBe('(text)');
          expect(editor.getSelectedBufferRange()).toEqual([[0, 1], [0, 5]]);
          return expect(editor.getLastSelection().isReversed()).toBeTruthy();
        });
        return describe("when the bracket-matcher.wrapSelectionsInBrackets is falsy", function() {
          return it("does not wrap the selection in brackets", function() {
            atom.config.set('bracket-matcher.wrapSelectionsInBrackets', false);
            editor.setText('text');
            editor.moveToBottom();
            editor.selectToTop();
            editor.selectAll();
            editor.insertText('(');
            expect(buffer.getText()).toBe('(');
            return expect(editor.getSelectedBufferRange()).toEqual([[0, 1], [0, 1]]);
          });
        });
      });
      describe("when there is text selected on multiple lines", function() {
        it("wraps the selection with brackets", function() {
          editor.insertText('text\nabcd');
          editor.moveToBottom();
          editor.selectToTop();
          editor.selectAll();
          editor.insertText('(');
          expect('(text\nabcd)').toBe(buffer.getText());
          expect(editor.getSelectedBufferRange()).toEqual([[0, 1], [1, 4]]);
          return expect(editor.getLastSelection().isReversed()).toBeTruthy();
        });
        return describe("when there are multiple selections", function() {
          return it("wraps each selection with brackets", function() {
            editor.setText("a b\nb c\nc b");
            editor.setSelectedBufferRanges([[[0, 2], [0, 3]], [[1, 0], [1, 1]], [[2, 2], [2, 3]]]);
            editor.insertText('"');
            expect(editor.getSelectedBufferRanges()).toEqual([[[0, 3], [0, 4]], [[1, 1], [1, 2]], [[2, 3], [2, 4]]]);
            expect(buffer.lineForRow(0)).toBe('a "b"');
            expect(buffer.lineForRow(1)).toBe('"b" c');
            return expect(buffer.lineForRow(2)).toBe('c "b"');
          });
        });
      });
      describe("when inserting a quote", function() {
        describe("when a word character is before the cursor", function() {
          return it("does not automatically insert the closing quote", function() {
            editor.buffer.setText("abc");
            editor.moveToEndOfLine();
            editor.insertText('"');
            expect(editor.getText()).toBe('abc"');
            editor.buffer.setText("abc");
            editor.moveToEndOfLine();
            editor.insertText("'");
            return expect(editor.getText()).toBe("abc'");
          });
        });
        describe("when a backslash character is before the cursor", function() {
          return it("does not automatically insert the closing quote", function() {
            editor.buffer.setText("\\");
            editor.moveToEndOfLine();
            editor.insertText('"');
            expect(editor.getText()).toBe('\\"');
            editor.buffer.setText("\\");
            editor.moveToEndOfLine();
            editor.insertText("'");
            return expect(editor.getText()).toBe("\\'");
          });
        });
        describe("when an escape sequence is before the cursor", function() {
          return it("does not automatically insert the closing quote", function() {
            editor.buffer.setText('"\\"');
            editor.moveToEndOfLine();
            editor.insertText('"');
            expect(editor.getText()).toBe('"\\""');
            editor.buffer.setText("\"\\'");
            editor.moveToEndOfLine();
            editor.insertText('"');
            expect(editor.getText()).toBe("\"\\'\"");
            editor.buffer.setText("'\\\"");
            editor.moveToEndOfLine();
            editor.insertText("'");
            expect(editor.getText()).toBe("'\\\"'");
            editor.buffer.setText("'\\'");
            editor.moveToEndOfLine();
            editor.insertText("'");
            return expect(editor.getText()).toBe("'\\''");
          });
        });
        describe("when a quote is before the cursor", function() {
          return it("does not automatically insert the closing quote", function() {
            editor.buffer.setText("''");
            editor.moveToEndOfLine();
            editor.insertText("'");
            expect(editor.getText()).toBe("'''");
            editor.buffer.setText('""');
            editor.moveToEndOfLine();
            editor.insertText('"');
            expect(editor.getText()).toBe('"""');
            editor.buffer.setText('``');
            editor.moveToEndOfLine();
            editor.insertText('`');
            expect(editor.getText()).toBe('```');
            editor.buffer.setText("''");
            editor.moveToEndOfLine();
            editor.insertText('"');
            return expect(editor.getText()).toBe("''\"\"");
          });
        });
        describe("when a non word character is before the cursor", function() {
          return it("automatically inserts the closing quote", function() {
            editor.buffer.setText("ab@");
            editor.moveToEndOfLine();
            editor.insertText('"');
            expect(editor.getText()).toBe('ab@""');
            return expect(editor.getCursorBufferPosition()).toEqual([0, 4]);
          });
        });
        describe("when the cursor is on an empty line", function() {
          return it("automatically inserts the closing quote", function() {
            editor.buffer.setText("");
            editor.insertText('"');
            expect(editor.getText()).toBe('""');
            return expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          });
        });
        describe("when the select option to Editor::insertText is true", function() {
          return it("does not automatically insert the closing quote", function() {
            editor.buffer.setText("");
            editor.insertText('"', {
              select: true
            });
            expect(editor.getText()).toBe('"');
            return expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          });
        });
        return describe("when the undo option to Editor::insertText is 'skip'", function() {
          return it("does not automatically insert the closing quote", function() {
            editor.buffer.setText("");
            editor.insertText('"', {
              undo: 'skip'
            });
            expect(editor.getText()).toBe('"');
            return expect(editor.getCursorBufferPosition()).toEqual([0, 1]);
          });
        });
      });
      describe("when return is pressed inside a matching pair", function() {
        it("puts the cursor on the indented empty line", function() {
          editor.insertText('void main() ');
          editor.insertText('{');
          expect(editor.getText()).toBe('void main() {}');
          editor.insertNewline();
          expect(editor.getCursorBufferPosition()).toEqual([1, 2]);
          expect(buffer.lineForRow(1)).toBe('  ');
          expect(buffer.lineForRow(2)).toBe('}');
          editor.setText('  void main() ');
          editor.insertText('{');
          expect(editor.getText()).toBe('  void main() {}');
          editor.insertNewline();
          expect(editor.getCursorBufferPosition()).toEqual([1, 4]);
          expect(buffer.lineForRow(1)).toBe('    ');
          return expect(buffer.lineForRow(2)).toBe('  }');
        });
        describe("when undo is triggered", function() {
          return it("removes both newlines", function() {
            editor.insertText('void main() ');
            editor.insertText('{');
            editor.insertNewline();
            editor.undo();
            return expect(editor.getText()).toBe('void main() {}');
          });
        });
        return describe('when editor.autoIndent is disabled', function() {
          beforeEach(function() {
            return atom.config.set('editor.autoIndent', false);
          });
          return it('does not auto-indent the empty line and closing bracket', function() {
            editor.insertText('  void main() ');
            editor.insertText('{');
            expect(editor.getText()).toBe('  void main() {}');
            editor.insertNewline();
            expect(editor.getCursorBufferPosition()).toEqual([1, 0]);
            expect(buffer.lineForRow(1)).toBe('');
            return expect(buffer.lineForRow(2)).toBe('}');
          });
        });
      });
      return describe("when in language specific scope", function() {
        return describe("string interpolation", function() {
          beforeEach(function() {
            waitsForPromise(function() {
              return atom.packages.activatePackage("language-ruby");
            });
            return runs(function() {
              return buffer.setPath('foo.rb');
            });
          });
          it("should insert curly braces inside doubly quoted string", function() {
            editor.insertText("foo = ");
            editor.insertText('"');
            editor.insertText("#");
            expect(editor.getText()).toBe('foo = "#{}"');
            editor.undo();
            return expect(editor.getText()).toBe('foo = ""');
          });
          it("should not insert curly braces inside singly quoted string", function() {
            editor.insertText("foo = ");
            editor.insertText("'");
            editor.insertText("#");
            return expect(editor.getText()).toBe("foo = '#'");
          });
          it("should insert curly braces inside % string", function() {
            editor.insertText("foo = %");
            editor.insertText('(');
            editor.insertText("#");
            return expect(editor.getText()).toBe('foo = %(#{})');
          });
          it("should not insert curly braces inside non-interpolated % string", function() {
            editor.insertText("foo = %q");
            editor.insertText("(");
            editor.insertText("#");
            return expect(editor.getText()).toBe("foo = %q(#)");
          });
          it("should insert curly braces inside interpolated symbol", function() {
            editor.insertText("foo = :");
            editor.insertText('"');
            editor.insertText("#");
            return expect(editor.getText()).toBe('foo = :"#{}"');
          });
          it('wraps the selection in the interpolation brackets when the selection is a single line', function() {
            editor.setText('foo = "a bar"');
            editor.setSelectedBufferRange([[0, 9], [0, 12]]);
            editor.insertText('#');
            expect(editor.getText()).toBe('foo = "a #{bar}"');
            expect(editor.getSelectedBufferRange()).toEqual([[0, 11], [0, 14]]);
            editor.undo();
            expect(editor.getText()).toBe('foo = "a bar"');
            return expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 12]]);
          });
          return it('does not wrap the selection in the interpolation brackets when the selection is mutli-line', function() {
            editor.setText('foo = "a bar"\nfoo = "a bar"');
            editor.setSelectedBufferRange([[0, 9], [1, 12]]);
            editor.insertText('#');
            expect(editor.getText()).toBe('foo = "a #{}"');
            expect(editor.getSelectedBufferRange()).toEqual([[0, 11], [0, 11]]);
            editor.undo();
            expect(editor.getText()).toBe('foo = "a bar"\nfoo = "a bar"');
            return expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [1, 12]]);
          });
        });
      });
    });
    describe("matching bracket deletion", function() {
      it("deletes the end bracket when it directly precedes a begin bracket that is being backspaced", function() {
        buffer.setText("");
        editor.setCursorBufferPosition([0, 0]);
        editor.insertText('{');
        expect(buffer.lineForRow(0)).toBe("{}");
        editor.backspace();
        return expect(buffer.lineForRow(0)).toBe("");
      });
      return it("does not delete end bracket even if it directly precedes a begin bracket if autocomplete is turned off", function() {
        atom.config.set('bracket-matcher.autocompleteBrackets', false);
        buffer.setText("");
        editor.setCursorBufferPosition([0, 0]);
        editor.insertText("{");
        expect(buffer.lineForRow(0)).toBe("{");
        editor.insertText("}");
        expect(buffer.lineForRow(0)).toBe("{}");
        editor.setCursorBufferPosition([0, 1]);
        editor.backspace();
        return expect(buffer.lineForRow(0)).toBe("}");
      });
    });
    return describe('bracket-matcher:close-tag', function() {
      beforeEach(function() {
        waitsForPromise(function() {
          return atom.workspace.open('sample.html');
        });
        return runs(function() {
          editor = atom.workspace.getActiveTextEditor();
          editorElement = atom.views.getView(editor);
          return buffer = editor.buffer, editor;
        });
      });
      it('closes the first unclosed tag', function() {
        editor.setCursorBufferPosition([5, 14]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        expect(editor.getCursorBufferPosition()).toEqual([5, 18]);
        return expect(editor.getTextInRange([[5, 14], [5, 18]])).toEqual('</a>');
      });
      it('closes the following unclosed tags if called repeatedly', function() {
        editor.setCursorBufferPosition([5, 14]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        expect(editor.getCursorBufferPosition()).toEqual([5, 22]);
        return expect(editor.getTextInRange([[5, 18], [5, 22]])).toEqual('</p>');
      });
      it('does not close any tag if no unclosed tag can be found at the insertion point', function() {
        editor.setCursorBufferPosition([5, 14]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        editor.setCursorBufferPosition([13, 11]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        editor.setCursorBufferPosition([15, 0]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        editor.setCursorBufferPosition([11, 9]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        return expect(editor.getCursorBufferPosition()).toEqual([11, 9]);
      });
      it('does not get confused in case of nested identical tags -- tag not closing', function() {
        editor.setCursorBufferPosition([13, 11]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        return expect(editor.getCursorBufferPosition()).toEqual([13, 16]);
      });
      return it('does not get confused in case of nested identical tags -- tag closing', function() {
        editor.setCursorBufferPosition([13, 11]);
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        expect(editor.getCursorBufferPosition()).toEqual([13, 16]);
        expect(editor.getTextInRange([[13, 10], [13, 16]])).toEqual('</div>');
        atom.commands.dispatch(editorElement, 'bracket-matcher:close-tag');
        return expect(editor.getCursorBufferPosition()).toEqual([13, 16]);
      });
    });
  });

}).call(this);
