<commit_before>$(function() {
  $('.edit.button').add('.edit-post-cancel').click(function(e) {
    e.preventDefault();

    var post = $(this).closest('.post');
    var message = post.find('.message').toggle();
    var form = post.find('form.edit-post-form').toggle();

    form[0].reset();
    form.find('textarea').height(message.height());
  });

  lichess.loadScript('/assets/vendor/jquery-textcomplete/dist/jquery.textcomplete.js').then(function() {

    var getThreadParticipants = function() {
      var topicId = $('.post-text-area').attr('data-topic');

      if (!topicId) {
        return jQuery.Deferred().resolve([]);
      } else {
        return $.ajax({
          url: "/forum/participants/" + topicId
        });
      }
    };

    var searchCandidates = function(term, candidateUsers) {
      return candidateUsers.filter(function(user) {
        return user.toLowerCase().indexOf(term.toLowerCase()) === 0;
      });
    };

    // We only ask the server for the thread participants once the user has clicked the text box as most hits to the
    // forums will be only to read the thread. So the 'thread participants' starts out empty until the post text area
    // is focused.
    var threadParticipants = Promise.resolve([]);

    $('.post-text-area').textcomplete([{
      match: /(^|\s)@(|[a-zA-Z_-][\w-]{0,19})$/,
      search: function(term, callback) {

        // Initially we only autocomplete by participants in the thread. As the user types more,
        // we can autocomplete against all users on the site.
        threadParticipants.then(function(participants) {
          var forumParticipantCandidates = searchCandidates(term, participants);

          if (forumParticipantCandidates.length != 0) {
            // We always prefer a match on the forum thread partcipants' usernames
            callback(forumParticipantCandidates);
          }
          else if (term.length >= 3) {
            // We fall back to every site user after 3 letters of the username have been entered
            // and there are no matches in the forum thread participants
            $.ajax({
              url: "/player/autocomplete?term=" + term,
              success: function(candidateUsers) {
                callback(searchCandidates(term, candidateUsers));
              }
            });
          } else {
            callback([]);
          }
        });
      },
      replace: function(mention) {
        return '$1@' + mention + ' ';
      }
    }], {
      placement: 'top',
      appendTo: '#lichess_forum'
    });

    $('.post-text-area').one('focus', function() {
      threadParticipants = Promise.resolve(getThreadParticipants());
    });
  });
});
<commit_msg>Looks like I accidentally removed a couple of niklasf's changes in my last commit (the cache flag)<commit_after>$(function() {
  $('.edit.button').add('.edit-post-cancel').click(function(e) {
    e.preventDefault();

    var post = $(this).closest('.post');
    var message = post.find('.message').toggle();
    var form = post.find('form.edit-post-form').toggle();

    form[0].reset();
    form.find('textarea').height(message.height());
  });

  lichess.loadScript('/assets/vendor/jquery-textcomplete/dist/jquery.textcomplete.js').then(function() {

    var getThreadParticipants = function() {
      var topicId = $('.post-text-area').attr('data-topic');

      if (!topicId) {
        return jQuery.Deferred().resolve([]);
      } else {
        return $.ajax({
          url: "/forum/participants/" + topicId
        });
      }
    };

    var searchCandidates = function(term, candidateUsers) {
      return candidateUsers.filter(function(user) {
        return user.toLowerCase().indexOf(term.toLowerCase()) === 0;
      });
    };

    // We only ask the server for the thread participants once the user has clicked the text box as most hits to the
    // forums will be only to read the thread. So the 'thread participants' starts out empty until the post text area
    // is focused.
    var threadParticipants = Promise.resolve([]);

    $('.post-text-area').textcomplete([{
      match: /(^|\s)@(|[a-zA-Z_-][\w-]{0,19})$/,
      search: function(term, callback) {

        // Initially we only autocomplete by participants in the thread. As the user types more,
        // we can autocomplete against all users on the site.
        threadParticipants.then(function(participants) {
          var forumParticipantCandidates = searchCandidates(term, participants);

          if (forumParticipantCandidates.length != 0) {
            // We always prefer a match on the forum thread partcipants' usernames
            callback(forumParticipantCandidates);
          }
          else if (term.length >= 3) {
            // We fall back to every site user after 3 letters of the username have been entered
            // and there are no matches in the forum thread participants
            $.ajax({
              url: "/player/autocomplete",
              data: {
                term: term
              },
              success: function(candidateUsers) {
                callback(searchCandidates(term, candidateUsers));
              },
              cache: true
            });
          } else {
            callback([]);
          }
        });
      },
      replace: function(mention) {
        return '$1@' + mention + ' ';
      }
    }], {
      placement: 'top',
      appendTo: '#lichess_forum'
    });

    $('.post-text-area').one('focus', function() {
      threadParticipants = Promise.resolve(getThreadParticipants());
    });
  });
});

{'fraction_non_alphanumeric': 0.1403414195867026, 'fraction_numerical': 0.003234501347708895, 'mean_word_length': 2.289598108747045, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4310876', 'n_tokens_mistral': 1559, 'n_tokens_neox': 1464, 'n_words': 398}