<commit_before>define("mode/c_cpp_matching_brace_outdent", function(require, exports, module) {

var Range = require("ace/range").Range;

var CppTokenCursor = require("mode/token_cursor").CppTokenCursor;
var MatchingBraceOutdent = function(codeModel) {
   this.codeModel = codeModel;
};

// Allow the user to control various levels of outdenting if desired
var $outdentColon              = true; // : (initializer list)
var $outdentRightParen         = true; // )
var $outdentLeftBrace          = true; // {
var $outdentRightBrace         = true; // }
var $outdentRightBracket       = true; // ]
var $outdentRightArrow         = true; // >
var $alignDots                 = true; // .
var $alignEquals               = true; // int x = 1,
                                       //     y = 2;
var $alignStreamIn             = true; // >>
var $alignStreamOut            = true; // <<
var $alignClassAccessModifiers = true; // public: etc.
var $alignCase                 = true; // case 'a':

(function() {

   // Set the indent of the line at 'row' to the indentation at
   // 'rowFrom'. This operation is only performed if the indentation
   // of the lines at 'rowTo' and 'rowFrom' match.
   //
   // 'predicate' is an (optional) function taking the old and new
   // indents, and returning true or false -- this is used to ensure
   // outdenting only occurs when explicitly desired.
   this.setIndent = function(session, rowTo, rowFrom, extraIndent, predicate) {

      var doc = session.getDocument();
      extraIndent = typeof extraIndent === "string" ?
         extraIndent :
         "";

      var line = doc.$lines[rowTo];
      var prevLine = doc.$lines[rowFrom];

      var oldIndent = this.$getIndent(line);
      var newIndent = this.$getIndent(prevLine);

      if (typeof predicate !== "function" || predicate(oldIndent, newIndent)) {
         doc.replace(
            new Range(rowTo, 0, rowTo, oldIndent.length),
            newIndent + extraIndent
         );
      }
      
   };

   this.checkOutdent = function(state, line, input) {

      if (state == "start") {

         // private: / public: / protected
         // also class initializer lists
         if (input === ":") {
            return true;
         }

         // outdenting for lines starting with 'closers' and 'openers'
         // also preproc lines
         if (/^\s*[#\{\}\>\]\)<.:]/.test(input))
            return true;

         // outdenting for '='
         if (input === "=")
            return true;

      }

      // check for nudging of '/' to the left (?)
      if (state == "comment") {

         if (input == "/") {
            return true;
         }

      }

      return false;

   };

   this.escapeRegExp = function(string) {
      return string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
   };

   this.alignStartToken = function(token, session, row, line, prevLine) {

      if (prevLine === null || line === null) return false;
      var regex = new RegExp("^\\s*" + this.escapeRegExp(token));
      if (regex.test(line)) {
         var index = prevLine.indexOf(token);
         if (index >= 0) {

            var doc = session.getDocument();
            var oldIndent = this.$getIndent(line);
            var newIndent = new Array(index + 1).join(" ");

            doc.replace(
               new Range(row, 0, row, oldIndent.length),
               newIndent
            );

            return true;
         }
      }
      return false;
   };

   this.alignEquals = function(session, row, line, prevLine) {

      if (prevLine === null || line === null) return false;
      var equalsIndex = line.indexOf("=");

      // Bail if there is more than one '=' on the line
      if (equalsIndex !== line.lastIndexOf("="))
         return false;
      
      var prevLineEqualsIndex = prevLine.indexOf("=");
      if (equalsIndex !== -1 && prevLineEqualsIndex !== -1 && /,\s*$/.test(prevLine))
      {
         var doc = session.getDocument();
         var oldIndent = this.$getIndent(line);
         if (oldIndent.length >= prevLineEqualsIndex)
            return false;

         var diff = prevLineEqualsIndex - equalsIndex;
         if (diff <= 0)
            return false;

         var newIndent = new Array(oldIndent.length + diff + 1).join(" ");

         doc.replace(
            new Range(row, 0, row, oldIndent.length),
            newIndent
         );

         return true;
         
      }

      return false;
      
   };

   this.autoOutdent = function(state, session, row) {

      var doc = session.doc;
      var line = doc.getLine(row);
      var prevLine = null;
      if (row > 0)
         prevLine = doc.getLine(row - 1);
      var indent = this.$getIndent(line);

      // Check for '<<', '.'alignment
      if ($alignStreamOut && this.alignStartToken("<<", session, row, line, prevLine))
         return;

      if ($alignStreamIn && this.alignStartToken(">>", session, row, line, prevLine))
         return;

      if ($alignDots && this.alignStartToken(".", session, row, line, prevLine))
         return;

      if ($alignEquals && this.alignEquals(session, row, line, prevLine))
         return;

      // Outdent for a ':' places on its own line if it appears the
      // user is creating an initialization list for
      // a constructor, e.g.
      //
      //     SomeConstructor(int a,
      //                     int b)
      //         :
      //         ^
      //
      // We also perform a similar action for class inheritance, e.g.
      //
      //     class Foo
      //         :
      if ($outdentColon &&
          /^\s*:/.test(doc.getLine(row)) &&
          !/^\s*::/.test(doc.getLine(row))) {

         if (this.codeModel.$tokenUtils.$tokenizeUpToRow(row)) {

            var tokenCursor = new CppTokenCursor(this.codeModel.$tokens, row, 0);
            var rowToUse = -1;

            // First, handle constructors. Note that we need to first walk
            // over some keywords, e.g.
            //
            //     int foo(int a, int b) const noexcept()<commit_msg>disable 'equals' alignment for now (doesn't work as intended)<commit_after>define("mode/c_cpp_matching_brace_outdent", function(require, exports, module) {

var Range = require("ace/range").Range;

var CppTokenCursor = require("mode/token_cursor").CppTokenCursor;
var MatchingBraceOutdent = function(codeModel) {
   this.codeModel = codeModel;
};

// Allow the user to control various levels of outdenting if desired
var $outdentColon              = true; // : (initializer list)
var $outdentRightParen         = true; // )
var $outdentLeftBrace          = true; // {
var $outdentRightBrace         = true; // }
var $outdentRightBracket       = true; // ]
var $outdentRightArrow         = true; // >
var $alignDots                 = true; // .
var $alignEquals               = true; // int x = 1,
                                       //     y = 2;
var $alignStreamIn             = true; // >>
var $alignStreamOut            = true; // <<
var $alignClassAccessModifiers = true; // public: etc.
var $alignCase                 = true; // case 'a':

(function() {

   // Set the indent of the line at 'row' to the indentation at
   // 'rowFrom'. This operation is only performed if the indentation
   // of the lines at 'rowTo' and 'rowFrom' match.
   //
   // 'predicate' is an (optional) function taking the old and new
   // indents, and returning true or false -- this is used to ensure
   // outdenting only occurs when explicitly desired.
   this.setIndent = function(session, rowTo, rowFrom, extraIndent, predicate) {

      var doc = session.getDocument();
      extraIndent = typeof extraIndent === "string" ?
         extraIndent :
         "";

      var line = doc.$lines[rowTo];
      var prevLine = doc.$lines[rowFrom];

      var oldIndent = this.$getIndent(line);
      var newIndent = this.$getIndent(prevLine);

      if (typeof predicate !== "function" || predicate(oldIndent, newIndent)) {
         doc.replace(
            new Range(rowTo, 0, rowTo, oldIndent.length),
            newIndent + extraIndent
         );
      }
      
   };

   this.checkOutdent = function(state, line, input) {

      if (state == "start") {

         // private: / public: / protected
         // also class initializer lists
         if (input === ":") {
            return true;
         }

         // outdenting for lines starting with 'closers' and 'openers'
         // also preproc lines
         if (/^\s*[#\{\}\>\]\)<.:]/.test(input))
            return true;

         // outdenting for '='
         if (input === "=")
            return true;

      }

      // check for nudging of '/' to the left (?)
      if (state == "comment") {

         if (input == "/") {
            return true;
         }

      }

      return false;

   };

   this.escapeRegExp = function(string) {
      return string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
   };

   this.alignStartToken = function(token, session, row, line, prevLine) {

      if (prevLine === null || line === null) return false;
      var regex = new RegExp("^\\s*" + this.escapeRegExp(token));
      if (regex.test(line)) {
         var index = prevLine.indexOf(token);
         if (index >= 0) {

            var doc = session.getDocument();
            var oldIndent = this.$getIndent(line);
            var newIndent = new Array(index + 1).join(" ");

            doc.replace(
               new Range(row, 0, row, oldIndent.length),
               newIndent
            );

            return true;
         }
      }
      return false;
   };

   this.alignEquals = function(session, row, line, prevLine) {

      if (prevLine === null || line === null) return false;
      var equalsIndex = line.indexOf("=");

      // Bail if there is more than one '=' on the line
      if (equalsIndex !== line.lastIndexOf("="))
         return false;
      
      var prevLineEqualsIndex = prevLine.indexOf("=");
      if (equalsIndex !== -1 && prevLineEqualsIndex !== -1 && /,\s*$/.test(prevLine))
      {
         var doc = session.getDocument();
         var oldIndent = this.$getIndent(line);
         if (oldIndent.length >= prevLineEqualsIndex)
            return false;

         var diff = prevLineEqualsIndex - equalsIndex;
         if (diff <= 0)
            return false;

         var newIndent = new Array(oldIndent.length + diff + 1).join(" ");

         doc.replace(
            new Range(row, 0, row, oldIndent.length),
            newIndent
         );

         return true;
         
      }

      return false;
      
   };

   this.autoOutdent = function(state, session, row) {

      var doc = session.doc;
      var line = doc.getLine(row);
      var prevLine = null;
      if (row > 0)
         prevLine = doc.getLine(row - 1);
      var indent = this.$getIndent(line);

      // Check for '<<', '.'alignment
      if ($alignStreamOut && this.alignStartToken("<<", session, row, line, prevLine))
         return;

      if ($alignStreamIn && this.alignStartToken(">>", session, row, line, prevLine))
         return;

      if ($alignDots && this.alignStartToken(".", session, row, line, prevLine))
         return;

      // if ($alignEquals && this.alignEquals(session, row, line, prevLine))
      //    return;

      // Outdent for a ':' places on its own line if it appears the
      // user is creating an initialization list for
      // a constructor, e.g.
      //
      //     SomeConstructor(int a,
      //                     int b)
      //         :
      //         ^
      //
      // We also perform a similar action for class inheritance, e.g.
      //
      //     class Foo
      //         :
      if ($outdentColon &&
          /^\s*:/.test(doc.getLine(row)) &&
          !/^\s*::/.test(doc.getLine(row))) {

         if (this.codeModel.$tokenUtils.$tokenizeUpToRow(row)) {

            var tokenCursor = new CppTokenCursor(this.codeModel.$tokens, row, 0);
            var rowToUse = -1;

            // First, handle constructors. Note that we need to first walk
            // over some keywords, e.g.
            //
            //     int foo(int a, int b) const noexcept()
{'fraction_non_alphanumeric': 0.1388477366255144, 'fraction_numerical': 0.0024691358024691358, 'mean_word_length': 1.7697743332573512, 'pattern_counts': {'":': 2, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6538602', 'n_tokens_mistral': 3639, 'n_tokens_neox': 3477, 'n_words': 973}