您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
言語ごとにテンプレートを登録して、貼り付けの手間を減らします
// ==UserScript== // @name AtCoder Template // @namespace http://atcoder.jp/ // @version 0.4 // @description 言語ごとにテンプレートを登録して、貼り付けの手間を減らします // @author magurofly // @match https://atcoder.jp/contests/*/tasks/* // @match https://atcoder.jp/contests/*/submit* // @match https://atcoder.jp/contests/*/custom_test* // @grant unsafeWindow // @grant GM_getValue // @grant GM_setValue // @icon https://www.google.com/s2/favicons?domain=atcoder.jp // @license CC0 1.0 Universal // ==/UserScript== (function() { 'use strict'; const VERSION = "0.4"; const $ = unsafeWindow.$; // 設定があればロード const config = (() => { let data = {}; { const config_json = GM_getValue("config", "{}"); if (config_json) { try { data = JSON.parse(config_json); } catch (e) { console.error("AtCoder Template: Invalid JSON", config_json); } } } return { save() { const config_json = JSON.stringify(data); GM_setValue("config", config_json); console.info("AtCoder Template: saved config"); }, delete(key) { delete data[key]; this.save(); }, get(key, defaultValue = null) { return (key in data) ? data[key] : defaultValue; }, set(key, value) { data[key] = value; this.save(); }, }; })(); class View { constructor() { this.lang = $("#select-lang select[name='data.LanguageId']"); const btnEditTemplate = $(`<button type="button" class="btn btn-default btn-sm">Edit Templates</button>`); const btnLoadTemplate = $(`<button type="button" class="btn btn-danger btn-sm">Load Template</button>`); $(".editor-buttons").append(btnEditTemplate, btnLoadTemplate); btnEditTemplate.click(() => { const langId = this.lang.val(); const langLabel = this.lang.find(":selected").text(); this.openTemplateEditor(langId, langLabel); }); btnLoadTemplate.click(() => { if (this.getText()) { if (!confirm("テンプレートを読み込むと、現在のソースは上書きされます。読み込みますか?")) return; } const langId = this.lang.val(); if (!this.loadTemplate()) { alert(`言語ID ${langId} のテンプレートは登録されていません`); } }); this.modal = $(`<section class="modal fade">`).html(` <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span>×</span></button> <h4 class="modal-title">テンプレートの編集</h4> </div> <div class="modal-body"> <div class="row"> <p class="col"><span id="atcoder-template-desc"></span>テンプレートを編集します</p> </div> <div class="row"> <textarea rows="10" id="atcoder-template-editor" class="col" style="margin: 1%; width: 98%; height: 100%; font-family: monospace"></textarea> </div> <div class="row"><div class="col"> <button type="button" id="atcoder-template-save" class="btn btn-primary">保存</button> <button type="button" id="atcoder-template-delete" class="btn btn-danger">削除</button> </div></div> </div> </div> </div> `); this.modal.appendTo(unsafeWindow.document.body); // 言語が変更されるたびに loadTemplate する // ただし、提出欄が空でない場合はしない this.lang.on("change", _e => { if (!this.getText()) this.loadTemplate(); }); this.loadTemplate(); } // `languageId` で指定した言語 ID に対するテンプレートを提出欄に貼り付ける // 返り値: テンプレートが登録されているかどうか loadTemplate(languageId = null) { languageId = languageId || this.lang.val(); const template = config.get(languageId); if (template != null) { this.setText(template); return true; } else { return false; } } setText(text) { const toggler = $('.btn-toggle-editor'); if (!toggler.hasClass('active')) { unsafeWindow.ace.edit('editor').setValue(text); } else { $('.plain-textarea').val(text); } } getText() { const toggler = $('.btn-toggle-editor'); if (!toggler.hasClass('active')) { return unsafeWindow.ace.edit('editor').getValue(); } else { return $('.plain-textarea').val(); } } openTemplateEditor(languageId, label = languageId) { const editor = this.modal.find("#atcoder-template-editor"); this.modal.find("#atcoder-template-desc").text(`${label} [${languageId}] の`); editor.val(config.get(languageId, "")); this.modal.find("#atcoder-template-save")[0].onclick = () => { console.log("saved", editor.val()); config.set(languageId, editor.val()); config.save(); }; this.modal.find("#atcoder-template-delete")[0].onclick = () => { config.delete(languageId); editor.val(""); }; this.modal.modal(); } } unsafeWindow.AtCoderTemplate = { version: VERSION, view: new View(), }; })();