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

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

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

// Allow the user to control outdenting if desired
var $outdentColon              = true; // : (initializer list)
var $outdentRightParen         = true; // )
var $outdentLeftBrace          = true; // {
var $outdentRightBrace         = true; // }
var $outdentRightBracket       = true; // ]
var $outdentChevron            = true; // >
var $alignDots                 = true; // .
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'
         if (/^\s*[\{\}\>\]\)<.:]/.test(input)) {
            return true;
         }

      }

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

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

      }

      return false;

   };

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

      if (/^\s*\{/.test(line)) {
         var re = this.$codeModel.reNakedBlockTokens;
         if (prevLine !== null) {
            for (var key in re) {
               if (re[key].test(prevLine)) {
                  this.setIndent(session, row, row - 1);
                  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.autoOutdent = function(state, session, row) {

      var doc = session.doc;
      var line = this.$codeModel.getLineSansComments(doc, row);
      var prevLine = null;
      if (row > 0)
         prevLine = this.$codeModel.getLineSansComments(doc, 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;
      }

      // 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(line)) {

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

            var tokenCursor = new TokenCursor(this.$codeModel.$tokens, row, 0);
            var rowToUse = null;
            if (tokenCursor.moveBackwardOverMatchingParens()) {
               if (tokenCursor.moveToPreviousToken()) {
                  rowToUse = tokenCursor.$row;
               }
            } else {
               while (tokenCursor.moveToPreviousToken()) {
                  if (tokenCursor.currentValue() === "class") {
                     rowToUse = tokenCursor.$row;
                     break;
                  }

                  var type = tokenCursor.currentType();
                  if (!(type === "keyword" || type === "identifier")) {
                     break;
                  }
               }
            }
         
            if (rowToUse >= 0) {
               this.setIndent(session, row, rowToUse, session.getTabString(),
                              function(oldIndent, newIndent) {
                                 return oldIndent === newIndent;
                              });
            }

         }
      }

      // Outdent for lines starting with a '>' if an associated matching
      // token can be found. This is intended for template contexts --
      // we short-circuit our lookback if we bump into a ';' token.
      if ($outdentChevron && /^\s*>/.test(line)) {
         if (this.$codeModel.$tokenUtils.$tokenizeUpToRow(row)) {
            var tokenCursor = new TokenCursor(this.$codeModel.$tokens, row, 0);
            if (tokenCursor.bwdToMatchingTokenShortCircuit(function(cursor) {
               return cursor.currentValue() === ";";
            }))
            {
               this.setIndent(session, row, tokenCursor.$row);
            }
         }
      }

      // Outdent for closing braces (to match the indentation of their
      // matched opening brace
      //
      // If the line on which the matching '{' was found is of
      // the form
      //
      //  foo) {
      //
      // then indent according to the location of the matching
      // '('
      //
      // This rule should apply to closing braces with semi-colons
      // or comments following as well.
      if ($outdentRightBrace && /^\s*\}/.test(line)) {

         var openBracketPos = session.findMatchingBracket({
            row: row,
            column: line.indexOf("}") + 1
         });

         if (openBracketPos !== null) {

            // If the open brace lies on its own line, match its indentation
            var openBracketLine =
                   doc.$lines[openBracketPos.row].replace(/\/\/.*/, "");

            if (/^\s*\{/.test(openBracketLine)) {
               this.setIndent(session, row, openBracketPos.row);
               return;
            }

            // Otherwise, try looking upwards to get an appropriate indentation
            var heuristicRow = this.$codeModel.getRowForOpenBraceIndent(
               session,
               openBracketPos.row
            );

            if (heuristicRow >= 0) {
               this.setIndent(session, row, heuristicRow);
               return;
            }

         } 

      }

      if ($outdentRightParen) {

         var closingParenMatch = /^\s*\)/.exec(line);
         if (closingParenMatch) {
            var openParenPos = session.findMatchingBracket({
               row: row,
               column: line.indexOf(")") + 1
            });
            if (openParenPos) {
               this.setIndent(session, row, openParenPos.row);
               return;
            }
         }
      }

      if ($outdentRightBracket) {

         var closingBracketMatch = /^\s*\]/.exec(line);
         if (closingBracketMatch) {
            var openBracketPos = session.findMatchingBracket({
               row: row,
               column: line.indexOf("]") + 1
            });
            if (openBracketPos) {
               this.setIndent(session, row, openBracketPos.row);
               return;
            }
         }
      }
      
      // If we just typed 'public:', 'private:' or 'protected:',
      // we should outdent if possible. Do so by looking for the
      // enclosing 'class' scope.
      if ($alignClassAccessModifiers &&
          /^\s*public\s*:[^:]|^\s*private\s*:[^:]|^\s*protected\s*:[^:]/.test(line)) {

         // Find the associated open bracket.
         var openBraceRow = this.$codeModel.doFindMatchingBracketRow(
            "}",
            doc,
            row,
            1E6,
            "backward",
            1,
            0
         );

         if (openBraceRow >= 0) {
            // If this open brace is already associated with a class or struct,
            // step over all of those rows.
            var heuristicRow =<commit_msg>fix outdenting<commit_after>define("mode/c_cpp_matching_brace_outdent", function(require, exports, module) {

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

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

// Allow the user to control outdenting if desired
var $outdentColon              = true; // : (initializer list)
var $outdentRightParen         = true; // )
var $outdentLeftBrace          = true; // {
var $outdentRightBrace         = true; // }
var $outdentRightBracket       = true; // ]
var $outdentChevron            = true; // >
var $alignDots                 = true; // .
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'
         if (/^\s*[\{\}\>\]\)<.:]/.test(input)) {
            return true;
         }

      }

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

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

      }

      return false;

   };

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

      if (/^\s*\{/.test(line)) {
         var re = this.$codeModel.reNakedBlockTokens;
         if (prevLine !== null) {
            for (var key in re) {
               if (re[key].test(prevLine)) {
                  this.setIndent(session, row, row - 1);
                  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.autoOutdent = function(state, session, row) {

      var doc = session.doc;
      var line = this.$codeModel.getLineSansComments(doc, row);
      var prevLine = null;
      if (row > 0)
         prevLine = this.$codeModel.getLineSansComments(doc, 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;
      }

      // 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(line)) {

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

            var tokenCursor = new TokenCursor(this.$codeModel.$tokens, row, 0);
            var rowToUse = null;
            if (tokenCursor.moveBackwardOverMatchingParens()) {
               if (tokenCursor.moveToPreviousToken()) {
                  rowToUse = tokenCursor.$row;
               }
            } else {
               while (tokenCursor.moveToPreviousToken()) {
                  if (tokenCursor.currentValue() === "class") {
                     rowToUse = tokenCursor.$row;
                     break;
                  }

                  var type = tokenCursor.currentType();
                  if (!(type === "keyword" || type === "identifier")) {
                     break;
                  }
               }
            }
         
            if (rowToUse >= 0) {
               this.setIndent(session, row, rowToUse, session.getTabString(),
                              function(oldIndent, newIndent) {
                                 return oldIndent === newIndent;
                              });
            }

         }
      }

      // Outdent for lines starting with a '>' if an associated matching
      // token can be found. This is intended for template contexts --
      // we short-circuit our lookback if we bump into a ';' token.
      if ($outdentChevron && /^\s*>/.test(line)) {
         if (this.$codeModel.$tokenUtils.$tokenizeUpToRow(row)) {
            var tokenCursor = new TokenCursor(this.$codeModel.$tokens, row, 0);
            if (tokenCursor.bwdToMatchingTokenShortCircuit(function(cursor) {
               return cursor.currentValue() === ";";
            }))
            {
               this.setIndent(session, row, tokenCursor.$row);
            }
         }
      }

      // Outdent for closing braces (to match the indentation of their
      // matched opening brace
      //
      // If the line on which the matching '{' was found is of
      // the form
      //
      //  foo) {
      //
      // then indent according to the location of the matching
      // '('
      //
      // This rule should apply to closing braces with semi-colons
      // or comments following as well.
      if ($outdentRightBrace && /^\s*\}/.test(line)) {

         var openBracketPos = session.findMatchingBracket({
            row: row,
            column: line.indexOf("}") + 1
         });

         if (openBracketPos !== null) {

            // If the open brace lies on its own line, match its indentation
            var openBracketLine =
                   doc.$lines[openBracketPos.row].replace(/\/\/.*/, "");

            if (/^\s*\{/.test(openBracketLine)) {
               this.setIndent(session, row, openBracketPos.row);
               return;
            }

            // Otherwise, try looking upwards to get an appropriate indentation
            var heuristicRow = this.$codeModel.getRowForOpenBraceIndent(
               session,
               openBracketPos.row
            );

            if (heuristicRow >= 0) {
               this.setIndent(session, row, heuristicRow);
               return;
            }

         } 

      }

      if ($outdentRightParen) {

         var closingParenMatch = /^\s*\)/.exec(line);
         if (closingParenMatch) {
            var openParenPos = session.findMatchingBracket({
               row: row,
               column: line.indexOf(")") + 1
            });
            if (openParenPos) {
               this.setIndent(session, row, openParenPos.row);
               return;
            }
         }
      }

      if ($outdentRightBracket) {

         var closingBracketMatch = /^\s*\]/.exec(line);
         if (closingBracketMatch) {
            var openBracketPos = session.findMatchingBracket({
               row: row,
               column: line.indexOf("]") + 1
            });
            if (openBracketPos) {
               this.setIndent(session, row, openBracketPos.row);
               return;
            }
         }
      }
      
      // If we just typed 'public:', 'private:' or 'protected:',
      // we should outdent if possible. Do so by looking for the
      // enclosing 'class' scope.
      if ($alignClassAccessModifiers &&
          /^\s*public\s*:\s*$|^\s*private\s*:\s*$|^\s*protected\s*:\s*$]/.test(line)) {

         // Find the associated open bracket.
         var openBraceRow = this.$codeModel.doFindMatchingBracketRow(
            "}",
            doc,
            row,
            1E6,
            "backward",
            1,
            0
         );

         if (openBraceRow >= 0) {
            // If this open brace is already associated with a class or struct,
            // step over all of those rows.
            var heuristicRow =
{'fraction_non_alphanumeric': 0.12881709223553933, 'fraction_numerical': 0.0019801980198019802, 'mean_word_length': 1.5374851249504164, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2979016', 'n_tokens_mistral': 5552, 'n_tokens_neox': 5286, 'n_words': 1365}