AtCoder Submission Language Detector

Automatically detects the language used based on the information in the source code comments and selects it as the one to be submitted.

2022-09-20 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  1. // ==UserScript==
  2. // @name AtCoder Submission Language Detector
  3. // @namespace https://twitter.com/KakurenboUni
  4. // @version 1.0.1
  5. // @description Automatically detects the language used based on the information in the source code comments and selects it as the one to be submitted.
  6. // @author uni-kakurenbo
  7. // @match https://atcoder.jp/contests/*/tasks/*
  8. // @match https://atcoder.jp/contests/*/submit*
  9. // @match https://atcoder.jp/contests/*/custom_test*
  10. // @license MIT
  11. // @supportURL https://twitter.com/KakurenboUni
  12. // ==/UserScript==
  13.  
  14. (async function () {
  15. "use strict";
  16.  
  17. const DETECTION_REG_EXP = /#.*lang(?:uage)?:?(?<args>\s+[^\n\r*/#]+)/;
  18.  
  19. await rendered();
  20.  
  21. const $editor = $(".editor").data("editor").doc;
  22. const $plainTextarea = $(".plain-textarea");
  23.  
  24. const $selectLanguage = $("#select-lang select");
  25. const $languageOptions = $selectLanguage[0].querySelectorAll("option");
  26. const languageOptions = [].map.call($languageOptions, ({ value, label, dataset: { mime } = {} }) => {
  27. return {
  28. id: value,
  29. label: label.toLowerCase() ?? "",
  30. code: mime?.toLowerCase().replaceAll(/^.+\/x?|src$/g, "") ?? "",
  31. };
  32. });
  33.  
  34. $editor.on("change", updateLanguageSettings);
  35. $plainTextarea.on("input", updateLanguageSettings);
  36. document.addEventListener("paste", updateLanguageSettings);
  37. $("#input-open-file").on("change", () => { setTimeout(updateLanguageSettings, 0); });
  38.  
  39. function updateLanguageSettings() {
  40. const sourceCode = getSourceCode();
  41.  
  42. const languageInfomation = sourceCode.match(DETECTION_REG_EXP);
  43. if (!languageInfomation || !languageInfomation?.groups?.args) return;
  44.  
  45. let languageSelectors = languageInfomation.groups.args?.trim().replace(/\s+/g, " ").split(" ");
  46. languageSelectors = languageSelectors.map((selector) => selector.toLowerCase());
  47.  
  48. const selectedOption = languageOptions.find((option) => {
  49. return (
  50. languageSelectors.includes(option.id) ||
  51. languageSelectors.every((selector) => option.label.includes(selector)) ||
  52. languageSelectors.every((selector) => option.code.includes(selector))
  53. );
  54. });
  55.  
  56. if (!selectedOption) return;
  57.  
  58. $selectLanguage.val(selectedOption.id).trigger("change");
  59. }
  60.  
  61. async function rendered() {
  62. let timer;
  63. await new Promise((resolve) => {
  64. observer();
  65. function observer() {
  66. if (typeof CodeMirror == "function") {
  67. resolve();
  68. }
  69. timer = setTimeout(observer, 10);
  70. }
  71. });
  72. clearTimeout(timer);
  73. }
  74. })();