<commit_before><!doctype html>
<html>
<head>
  <title>Language Canvas</title>
    <link rel="stylesheet" href="codemirror/lib/codemirror.css">
    <link rel="stylesheet" href="codemirror/theme/ambiance.css">
    <link rel="stylesheet" href="bootstrap/css/bootstrap.css">
    <style type="text/css">
      .nav {
        margin-top: 1em;
        margin-bottom: 5px;
        padding: 0 1em;
      }


      form {
        margin: 0;
      }

      .parser {
        margin-top: 1px;
      }

      .nav button {
        margin-left: 5px;
      }

    </style>
    <script src="codemirror/lib/codemirror.js"></script>
    <script src="codemirror/mode/flexible/flexible.js"></script>
    <script src="codemirror/mode/slymtax/slymtax.js"></script>
    <script src="codemirror/mode/javascript/javascript.js"></script>
    <script src="codemirror/mode/css/css.js"></script>

    <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
    <script src="bootstrap/js/bootstrap.js"></script>

    <script src="http://github.com/downloads/dmajda/pegjs/peg-0.7.0.min.js"></script>
    <script src="namegenerator.js"></script>
    
    <script type="text/javascript">

    var codeMirrors = [];

    function refreshEditors() {
      var tabHeight = $(window).outerHeight() - $(".nav").outerHeight(true);
      $(".code .CodeMirror-scroll").height(tabHeight * 0.75);
      $(".parser .CodeMirror-scroll").height(tabHeight * 0.25 - 1);

      for (var i = codeMirrors.length - 1; i >= 0; i--) { codeMirrors[i].refresh(); };
    }

    function addLanguage (name, code, syntax) {
      var human_name = name;
      name = name.replace(" ", "-");
      // create tab
      var tab = $("<li><a href=\"#tab-" + name + "\" data-toggle=\"tab\">" + human_name + "</a></li>");

      // make tab clickable
      $(tab).find("a").click(function (e) {
        e.preventDefault();
        $(this).tab('show');

        refreshEditors();
      });

      // create tab content pane
      var tab_pane = $("<div class=\"tab-pane\" id=\"tab-" + name + "\"> <form class=\"code\"><textarea></textarea></form> <form class=\"parser\"><textarea></textarea></form> </div>");

      // add syntax editor
      var parser = CodeMirror.fromTextArea($(tab_pane).find('.parser textarea').get(0), {
        theme:"ambiance",
        mode: "text/slymtax",
        smartIndent:false,
        onChange:function() {
          var Syntax = [];
          var syntaxLines = parser.getValue().split("\n");
          for (var i = syntaxLines.length - 1; i >= 0; i--) {
            try {
              var matches, token, styles;
              if(matches = /\/([^\/]+)\/\s*:\s*(.+)/.exec(syntaxLines[i])) {
                // regexp rule
                token = new RegExp("^" + matches[1].trim().replace(/ /g, "")); // whitespace replace, bad idea?
                styles = matches[2].trim().split(" ");
                
              } else if(matches = /'([^']+)'\s*:\s*(.+)/.exec(syntaxLines[i])) {
                // string rule
                token = matches[1].trim();
                styles = matches[2].trim().split(" ");

              } else {
                continue;
              }
              
              if(typeof styles != "undefined" && typeof token != "undefined") Syntax.push([token, styles]);

            } catch(e) {}
          }

          parser.syntax = Syntax;
          editor.setOption("mode", editor.getOption("mode")) // refresh editor
        }
      });
      parser.syntax = [];

      // add code editor
      var editor = CodeMirror.fromTextArea($(tab_pane).find('.code textarea').get(0), {
        theme:"ambiance",
        mode: {
          name: "flexible",
          parser: parser
        },
        lineNumbers: true,

        onHighlightComplete:function() {
          // localStorage.setItem(name, JSON.stringify({ code:editor.getValue(), syntax:parser.getValue() }));
        }
      });

      // populate editors
      editor.setValue(code);
      parser.setValue(syntax);

      // refresh editor
      editor.setOption("mode", editor.getOption("mode")); 

      // store editors for future
      codeMirrors.push(parser);
      codeMirrors.push(editor);

      // insert tab and content into dom
      $(".nav").append(tab);
      $(".tab-content").append(tab_pane);
    }



    $(function() {
      $(window).resize(function() {
        refreshEditors();
      });

      $("#add-language").click(function (e) {
        addLanguage(NameGenerator.make_name("adjective%5 [animal name gem planet tree emotion letter] suffix%2"), "# <NAME>'s Syntax Canvas\n# \n# type your code here, and your syntax in the lower pane\n# syntax syntax is MATCH : STYLE, STYLE... where MATCH is\n# a single quoted string, a simple regex or a regex with\n# captures and STYLE is an unquoted style name, indicating\n# how to style the text. Custom styling coming soon. \n# \n# styles are: keyword, atom, number, def, variable, variable-2\n# variable-3, property, operator, comment, string, string-2\n# meta, error, qualifier, builtin, bracket, tag, attribute\n# header, quote, hr, link  \n\nself.range = (10...32)", "/\\((\\d+)(...)(\\d+)\\)/ : number operator number\n/#.*/ : comment\n'self' : builtin")
        $(".nav a:last").click();
      });

      localStorage.clear();
      localStorage.setItem("Quack", JSON.stringify({code:"foo = bar", syntax:"'foo':special"}));

      for (var i = localStorage.length - 1; i >= 0; i--) {

        var name = localStorage.key(i);
        var data = JSON.parse(localStorage.getItem(name));
        if(data)
          addLanguage(name, data.code, data.syntax)
      }

      $(".nav a:first").click();

      refreshEditors();
    });
</script>
</head>
<body>
  <ul class="nav nav-tabs">
    <li class="pull-right"><button id="add-language" class="btn btn-small btn-primary"><i class="icon-plus icon-white"></i></button></li>
  </ul>
  <div class="tab-content"></div>
</body>
</html><commit_msg>Support editing language names<commit_after><!doctype html>
<html>
<head>
  <title>Language Canvas</title>
    <link rel="stylesheet" href="codemirror/lib/codemirror.css">
    <link rel="stylesheet" href="codemirror/theme/ambiance.css">
    <link rel="stylesheet" href="bootstrap/css/bootstrap.css">
    <style type="text/css">
      .nav {
        margin-top: 1em;
        margin-bottom: 5px;
        padding: 0 1em;
      }


      form {
        margin: 0;
      }

      .parser {
        margin-top: 1px;
      }

      .nav button {
        margin-left: 5px;
      }

      .nav input:focus {
        outline: none;
      }
      .nav input {
        border: none;
        padding: 0;
        height: 18px;
        position: relative;
        top: -2px;
      }

    </style>
    <script src="codemirror/lib/codemirror.js"></script>
    <script src="codemirror/mode/flexible/flexible.js"></script>
    <script src="codemirror/mode/slymtax/slymtax.js"></script>
    <script src="codemirror/mode/javascript/javascript.js"></script>
    <script src="codemirror/mode/css/css.js"></script>

    <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
    <script src="bootstrap/js/bootstrap.js"></script>

    <script src="http://github.com/downloads/dmajda/pegjs/peg-0.7.0.min.js"></script>
    <script src="namegenerator.js"></script>
    
    <script type="text/javascript">

    var codeMirrors = [];

    function refreshEditors() {
      var tabHeight = $(window).outerHeight() - $(".nav").outerHeight(true);
      $(".code .CodeMirror-scroll").height(tabHeight * 0.75);
      $(".parser .CodeMirror-scroll").height(tabHeight * 0.25 - 1);

      for (var i = codeMirrors.length - 1; i >= 0; i--) { codeMirrors[i].refresh(); };
    }

    function addLanguage (name, code, syntax) {
      var human_name = name;
      name = name.replace(" ", "-");
      // create tab
      var tab = $("<li><a href=\"#tab-" + name + "\" data-toggle=\"tab\">" + human_name + "</a></li>");

      // show tab on click
      $(tab).find("a").click(function (e) {
        e.preventDefault();
        $(this).tab('show');

        refreshEditors();
      });

      // edit language name on double click
      $(tab).find("a").dblclick(function (e) {
        e.preventDefault();
        var originalName = $(this).text();
        var $this = $(this);

        // create input element
        var input =  $("<input style='width:" + $this.width() + "px' placeholder='" + originalName + "'></input>");

        // escape or enter with no text resets name, enter with text sets new name
        input.keydown(function(k) {
          var code = k.keyCode || k.which;
          if(code == 27) { // escape
            k.preventDefault();
            $this.html(originalName);

          } else if(code == 13) { // enter
            k.preventDefault();
            if(input.val() == "") {
              $this.html(originalName);

            } else {
              var newName = input.val();
              $this.html(newName);
              localStorage.setItem(newName, localStorage.getItem(originalName));
              localStorage.removeItem(originalName);
            }
          }
        });

        $this.html(input);
        input.focus();
      });

      // create tab content pane
      var tab_pane = $("<div class=\"tab-pane\" id=\"tab-" + name + "\"> <form class=\"code\"><textarea></textarea></form> <form class=\"parser\"><textarea></textarea></form> </div>");

      // add syntax editor
      var parser = CodeMirror.fromTextArea($(tab_pane).find('.parser textarea').get(0), {
        theme:"ambiance",
        mode: "text/slymtax",
        smartIndent:false,
        onChange:function() {
          var Syntax = [];
          var syntaxLines = parser.getValue().split("\n");
          for (var i = syntaxLines.length - 1; i >= 0; i--) {
            try {
              var matches, token, styles;
              if(matches = /\/([^\/]+)\/\s*:\s*(.+)/.exec(syntaxLines[i])) {
                // regexp rule
                token = new RegExp("^" + matches[1].trim().replace(/ /g, "")); // whitespace replace, bad idea?
                styles = matches[2].trim().split(" ");
                
              } else if(matches = /'([^']+)'\s*:\s*(.+)/.exec(syntaxLines[i])) {
                // string rule
                token = matches[1].trim();
                styles = matches[2].trim().split(" ");

              } else {
                continue;
              }
              
              if(typeof styles != "undefined" && typeof token != "undefined") Syntax.push([token, styles]);

            } catch(e) {}
          }

          parser.syntax = Syntax;
          editor.setOption("mode", editor.getOption("mode")) // refresh editor
        }
      });
      parser.syntax = [];

      // add code editor
      var editor = CodeMirror.fromTextArea($(tab_pane).find('.code textarea').get(0), {
        theme:"ambiance",
        mode: {
          name: "flexible",
          parser: parser
        },
        lineNumbers: true,

        onHighlightComplete:function() {
          localStorage.setItem(name, JSON.stringify({ code:editor.getValue(), syntax:parser.getValue() }));
        }
      });

      // populate editors
      editor.setValue(code);
      parser.setValue(syntax);

      // refresh editor
      editor.setOption("mode", editor.getOption("mode")); 

      // store editors for future
      codeMirrors.push(parser);
      codeMirrors.push(editor);

      // insert tab and content into dom
      $(".nav").append(tab);
      $(".tab-content").append(tab_pane);
    }



    $(function() {
      $(window).resize(function() {
        refreshEditors();
      });

      $("#add-language").click(function (e) {
        addLanguage(NameGenerator.make_name("adjective%5 [animal name gem planet tree emotion letter] suffix%2"), "# <NAME>'s Syntax Canvas\n# \n# type your code here, and your syntax in the lower pane\n# syntax syntax is MATCH : STYLE, STYLE... where MATCH is\n# a single quoted string, a simple regex or a regex with\n# captures and STYLE is an unquoted style name, indicating\n# how to style the text. Custom styling coming soon. \n# \n# styles are: keyword, atom, number, def, variable, variable-2\n# variable-3, property, operator, comment, string, string-2\n# meta, error, qualifier, builtin, bracket, tag, attribute\n# header, quote, hr, link  \n\nself.range = (10...32)", "/\\((\\d+)(...)(\\d+)\\)/ : number operator number\n/#.*/ : comment\n'self' : builtin")
        $(".nav a:last").click();
      });

      for (var i = localStorage.length - 1; i >= 0; i--) {
          var name = localStorage.key(i);
        var data = JSON.parse(localStorage.getItem(name));
        if(data)
          addLanguage(name, data.code, data.syntax)
      }

      $(".nav a:first").click();

      refreshEditors();
    });
</script>
</head>
<body>
  <ul class="nav nav-tabs">
    <li class="pull-right"><button id="add-language" class="btn btn-small btn-primary"><i class="icon-plus icon-white"></i></button></li>
  </ul>
  <div class="tab-content"></div>
</body>
</html>
{'fraction_non_alphanumeric': 0.1814488309697202, 'fraction_numerical': 0.006899195093905711, 'mean_word_length': 2.1975490196078433, 'pattern_counts': {'":': 0, '<': 123, '<?xml version=': 0, '>': 129, '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': '1500575', 'n_tokens_mistral': 4117, 'n_tokens_neox': 3935, 'n_words': 854}