OptiYan 2

EYanIDE 优化 2.0

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         OptiYan 2
// @namespace    http://lunarine.cc/
// @version      2024.1.6
// @description  EYanIDE 优化 2.0
// @author       Liu Baicheng
// @match        http://121.36.38.167/
// @icon         http://121.36.38.167/static/favicon1.ico
// @grant        unsafeWindow
// @license      MIT
// @resource     css https://unpkg.com/[email protected]/dist/css/mdui.min.css
// @grant        GM_getResourceURL
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/js/mdui.min.js
// @connect      api.mkc.icu
// ==/UserScript==

(function () {
    'use strict';

    function classOptimize() {

        let divs = document.querySelectorAll('div.ui.dropdown.selection');

        // 遍历并删除这些 div
        divs.forEach(div => {
            div.remove();
        });

        const ModalFileList = document.getElementById("file-list-modal");
        ModalFileList.style.height = "auto";
        ModalFileList.style.width = "500px";
        ModalFileList.style.marginTop = "50px";
        // ModalFileList.style.marginLeft = "30%";
        // ModalFileList.style.marginRight = "30% !important";

        var windowWidth = window.innerWidth;
        var windowHeight = window.innerHeight;
        var elementWidth = 500;
        var left = (windowWidth - elementWidth) / 2;

        ModalFileList.style.position = 'absolute';
        ModalFileList.style.left = left + 'px';

        var compilerOptionsInput = document.getElementById('compiler-options');
        compilerOptionsInput.value = "-O3";
        compilerOptionsInput.style.display = "none";
        var comilerArgsInput = document.getElementById('command-line-arguments');
        if (comilerArgsInput) comilerArgsInput.remove();

        document.getElementById("username-display").innerHTML = `<i class="user icon"></i>` + document.getElementById("username-display").innerHTML;
    }

    function formatCppTemplateLine(line) {
        const templateRegex = /(\btemplate\b|\bvector\b|\bmap\b|\bset\b|\bp(?:air|queue)\b|<.*>)/;
        if (templateRegex.test(line.trim())) {
            return line
                .replace(/\s*(<|>)\s*/g, '$1')
                .replace(/>(\w)/g, '> $1');
        }
        return line;
    }

    function formatCppCode(code) {
        code = code.replace(/\/\*[\s\S]*?\*\//g, '');
        code = code.replace(/\/\/.*$/gm, '');
        const lines = code.split('\n');
        let formattedLines = [];
        let indentLevel = 0;
        const indentSpace = '    ';
        let inStruct = false;

        for (let i = 0; i < lines.length; i++) {
            let line = lines[i].trim();
            const isEndOfStructWithVar = line.match(/}\s*[a-zA-Z_][a-zA-Z0-9_]*\s*\[?\s*[^;]*;/);

            if (line.includes('{') && !line.endsWith('{')) {
                line = line.replace(/\s*{\s*/g, ' {\n' + indentSpace.repeat(indentLevel + 1));
            }

            if (line.startsWith('struct')) {
                inStruct = true;
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                indentLevel++;
                continue;
            }

            if (line.endsWith('};') || isEndOfStructWithVar) {
                if (indentLevel) indentLevel--;
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                inStruct = false;

                if (isEndOfStructWithVar) {
                    continue;
                }
                formattedLines.push('');
                continue;
            }

            if (inStruct) {
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                continue;
            }

            if (line.startsWith('#include')) {
                line = line.replace(/#include\s*<\s*([\w./+-]+)\s*>/g, '#include <$1>');
                formattedLines.push(line);
                continue;
            }

            if (line === 'using namespace std;') {
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                formattedLines.push('');
                continue;
            }

            if (line.endsWith(')') && lines[i + 1] && lines[i + 1].trim() === '{') {
                line += ' {';
                i++;
            }

            line = line.replace(/\s*([+\-*/=<>&|]+)\s*/g, ' $1 ');
            line = line.replace(/\s*,\s*/g, ', ');
            line = line.replace(/\s*([+\-]{2})\s*/g, '$1');
            line = line.replace(/\s*;\s*/g, '; ');
            line = line.replace(/\)\s*(?=[a-zA-Z+\-*/])/g, ') ');

            line = line.replace(/(?<=[+\*/])\s*\(/g, ' (');
            line = line.replace(/(?<!\S)-\s*\(/g, '-(');
            line = line.replace(/\b(for|while|if|else|switch|case|do)\s*(?=[({])/g, '$1 ');

            line = formatCppTemplateLine(line);
            line = line.replace(/!\s*=\s*/g, '!= ');


            if (line.endsWith('}')) {
                if (indentLevel) indentLevel--;
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                if (indentLevel === 0 && !inStruct && line.endsWith('}')) {
                    formattedLines.push('');
                }
                continue;
            }

            if (line.includes("}")) {
                indentLevel--;
            }

            if (line.includes(') {')) {
                if (indentLevel === 0 && !inStruct && formattedLines[formattedLines.length - 1] != '') {
                    formattedLines.push('');
                    formattedLines.push(indentSpace.repeat(indentLevel) + line);
                    indentLevel++;
                    continue;
                }
            }

            if (line) {
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
            }

            if (line.endsWith('{')) {
                indentLevel++;
            }
        }

        return formattedLines.join('\n').trim();
    }

    function formatCode() {
        const res = formatCppCode(unsafeWindow.sourceEditor.getValue());
        unsafeWindow.sourceEditor.setValue(res);
    }

    classOptimize();

    document.addEventListener('keydown', function (event) {
        if (event.ctrlKey && event.altKey) {
            formatCode(); // 调用目标函数
            mdui.snackbar({
                message: '代码格式化成功'
            });
        } else if (event.keyCode === 122) { // F11
            event.preventDefault();
            unsafeWindow.run();
        } else if (event.keyCode === 116) { // F5
            event.preventDefault();
        } else if (event.ctrlKey && event.keyCode === 82) { // Ctrl+R
            event.preventDefault();
        } else if (event.ctrlKey && event.keyCode === 121) { // Ctrl+R
            event.preventDefault();
        } else if (event.keyCode == 83 && event.ctrlKey) {
            event.preventDefault();
            saveCode();
        }
    });

    var title;

    window.addEventListener('load', function () {

        var footer = document.querySelector('#site-footer');

        if (footer) {
            var span = document.createElement('span');
            span.id = 'optiyan-line';
            span.textContent = 'OptiYan 已加载 Version: V1.1.0';
            span.style.color = "#fff";
            span.style.float = "left";
            span.style.left = "0";
            span.style.textAlign = "left";
            span.style.width = "fit-content";
            footer.appendChild(span);
        }

        var runBtn = document.getElementById('run-btn-label');
        runBtn.textContent = '运行 (F11 / Ctrl + ↵)';
        unsafeWindow.formatCppCode = formatCppCode;


        var loadBtn = document.getElementById('loadcode');
        loadBtn.className = "ui inverted primary labeled icon blue button";

        let fileNameInputDiv = document.createElement("div");

        fileNameInputDiv.className = "ui action inverted icon input";
        document.querySelectorAll("div.item.fitted.borderless.wide.screen.only")[0].appendChild(fileNameInputDiv);

        var fileNameInput = document.createElement('input');
        fileNameInput.id = "filename";
        fileNameInput.placeholder = "请输入文件名"

        fileNameInputDiv.appendChild(fileNameInput);

        document.getElementById("filename").value = "main.cpp";

        fileNameInputDiv.innerHTML += `
        <button id="saveCodeButton" class="ui icon button">
            <i class="save icon"></i>
        </button>
        `;
        document.getElementById("saveCodeButton").addEventListener('click', function () {
            saveCode();
        });
        // const spans = document.querySelectorAll('span.lm_title');

        // spans.forEach(span => {
        //     if (span.textContent.trim() === 'main.cpp') {
        //         title = span;
        //         console.log(title.innerHTML);
        //     }
        // });
        formatCode();
        classOptimize();
        // if (loading) document.getElementById("site-content").removeChild(loading);
        // document.getElementById("site-content").childNodes[0].style.display = '';
    });

    function updateColor() {
        let status = document.getElementById("status-line");
        if (status) {
            if (status.innerText.includes('Error')) {
                const sitefooter = document.querySelector('#site-footer');
                const linefooter = document.querySelector('#status-line');

                sitefooter.style.backgroundColor = "#c14343";
                linefooter.style.backgroundColor = "#c14343";
            } else if (status.innerText.includes('Accept')) {
                const sitefooter = document.querySelector('#site-footer');
                const linefooter = document.querySelector('#status-line');
                sitefooter.style.backgroundColor = "#05a705";
                linefooter.style.backgroundColor = "#05a705";
            } else {
                const sitefooter = document.querySelector('#site-footer');
                const linefooter = document.querySelector('#status-line');
                sitefooter.style.backgroundColor = "#9775fa";
                linefooter.style.backgroundColor = "#9775fa";
            }
        } else {
            const sitefooter = document.querySelector('#site-footer');
            const linefooter = document.querySelector('#status-line');
            sitefooter.style.backgroundColor = "#9775fa";
            linefooter.style.backgroundColor = "#9775fa";
        }

    }

    let script = document.createElement('script');
    script.src = "https://unpkg.com/[email protected]/dist/js/mdui.min.js?v=20240817";

    script.onload = function () {
        console.log('mdui 已加载');
    };

    document.body.appendChild(script);
    console.log(GM_getResourceURL("css"), GM_getResourceText("css"));
    GM_addStyle(GM_getResourceText("css"));

    setInterval(updateColor, 100);

    function createTimestampString(text) {
        // 获取当前时间的时间戳
        const timestamp = Math.floor(Date.now() / 1000); // 以秒为单位的时间戳
        console.log(timestamp);
        // 返回格式化字符串
        return `${text}:${timestamp}`;
    }

    function parseTimestampString(timestampString) {
        // 分割字符串,获取 text 和时间戳
        const [text, timestamp] = timestampString.split(':');
        // 将时间戳转换为格式化的时间
        const date = new Date(timestamp * 1000); // 将时间戳转换为毫秒
        const formattedTime = date.toLocaleString().slice(0, 19).replace('T', ' '); // 格式化为 YYYY-MM-DD HH:mm:ss
        return { text, formattedTime };
    }

    var curFileName;

    unsafeWindow.loadFileContent = function loadFileContent(filename) {
        document.getElementById("status-line").innerText = '正在加载文件...';
        fetch(`/load_file_content?filename=${encodeURIComponent(filename)}`)
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 使用 Monaco 编辑器加载文件内容
                    sourceEditor.setModel(monaco.editor.createModel(data.code, 'plaintext', monaco.Uri.file(filename + Math.floor(Math.random() * (9999 - 1111 + 1)) + 1111)));
                    monaco.editor.setModelLanguage(sourceEditor.getModel(), $selectLanguage.find(":selected").attr("mode"));
                    console.log(title);
                    curFileName = filename;
                    filename = parseTimestampString(filename).text;
                    title.innerText = filename + '.cpp';
                    $('#file-list-modal').modal('hide');
                    document.title = title.innerHTML;
                    document.getElementById("status-line").innerText = `已加载 ${filename}`;
                    document.getElementById("filename").value = filename;
                } else {
                    mdui.snackbar({
                        message: 'Failed to load file content: ' + data.message
                    });
                    document.getElementById("status-line").innerText = `${data.message}`;
                }
            })
            .catch((error) => {
                console.error('Error:', error);
                mdui.snackbar({
                    message: 'An error occurred while loading file content.'
                });
            });
    }

    unsafeWindow.showFileList = function showFileList() {
        fetch('/load_file_list')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const fileListDiv = document.getElementById('file-list');
                    fileListDiv.innerHTML = '';
                    fileListDiv.className = "ui middle aligned divided list";
                    // 创建文件列表
                    data.files.forEach(file => {
                        const fileItemDiv = document.createElement('div');
                        fileItemDiv.className = 'item';
                        const fileName = document.createElement('div');
                        fileName.classList.add('content')
                        //fileButton.className = 'ui button';
                        const info = parseTimestampString(file.filename);
                        const filename = info.text;
                        const time = info.formattedTime;

                        fileName.innerHTML = `
<a class="header">${filename}</a>
<div class="description">上次修改时间:${time}</div>

`;

                        const icon = document.createElement('i');
                        icon.className = "large file middle aligned icon";

                        const fileManage = document.createElement('div');
                        fileManage.className = "right floated ui content buttons";

                        const fileButton = document.createElement('div');
                        fileButton.className = 'ui icon circular button';
                        fileButton.innerHTML = `<i class="folder open icon"></i>`;;
                        fileButton.onclick = () => loadFileContent(file.filename);

                        const deleteButton = document.createElement('div');
                        deleteButton.className = 'ui icon circular red button';
                        deleteButton.innerHTML = `<i class="trash icon"></i>`;
                        deleteButton.onclick = () => deleteFile(file.filename, false);

                        fileManage.appendChild(fileButton);
                        
                        const orDiv = document.createElement('div');
                        //orDiv.classList.add('or');
                        //orDiv.setAttribute("data-text", "或");
                        //fileManage.appendChild(orDiv);
                        fileManage.appendChild(deleteButton);

                        fileItemDiv.appendChild(fileManage);
                        fileItemDiv.appendChild(icon);
                        fileItemDiv.appendChild(fileName);
                        fileListDiv.appendChild(fileItemDiv);

                    });

                    // 显示模态框
                    $('#file-list-modal').modal({
                        centered: true
                    }).modal('show')
                } else {
                    mdui.snackbar({
                        message: 'Failed to load file list: ' + data.message
                    });
                }
            })
            .catch((error) => {
                console.error('Error:', error);
                mdui.snackbar({
                    message: 'An error occurred while loading file list.'
                });
            });
    }


    unsafeWindow.deleteFile = function deleteFile(filename, enforce) {
        console.log("deleting")
        console.log(enforce);
        if (filename == null || !filename.includes(":")) return;
        const fileName = parseTimestampString(filename).text;
        if (enforce || confirm(`Are you sure you want to delete "${fileName}"?`)) {
            fetch(`/delete_file?filename=${encodeURIComponent(filename)}`, { method: 'DELETE' })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        if (!enforce) mdui.snackbar({
                            message: '删除成功'
                        });
                        if (!enforce) showFileList(); // Refresh the file list
                    } else {
                        mdui.snackbar({
                            message: 'Failed to delete file: ' + data.message
                        });
                    }
                })
                .catch((error) => {
                    console.error('Error:', error);
                    mdui.snackbar({
                        message: 'An error occurred while deleting the file.'
                    });
                });
        }
    }

    unsafeWindow.saveCode = function saveCode() {
        var fileName;
        console.log(title);
        if (title.innerText == "main.cpp" || "SOURCE") fileName = document.getElementById("filename").value;
        else {
            fileName = document.getElementById("filename").value;
        }
        if (fileName && fileName != "Untitled") {
            if (title.innerText != "main.cpp")
                if (document.getElementById("filename").value == title.innerText.replace(/\.[^/.]+$/, "")) unsafeWindow.deleteFile(curFileName, true);
            title.innerText = fileName + '.cpp';
            fileName = createTimestampString(fileName);
            unsafeWindow.saveFile(fileName);
            mdui.snackbar({
                message: '保存成功'
            });
            curFileName = fileName;
            document.title = title.innerHTML;
        } else {
            mdui.snackbar({
                message: '请输入有效的文件名或描述!'
            });
        }
    }
    setInterval(() => {
        const spans = document.querySelectorAll('span.lm_title');
        spans.forEach(span => {
            if (span.textContent.trim() === 'main.cpp' || span.textContent.trim() === "SOURCE") {
                title = span;
                //console.log(title.innerHTML);
            }
        });
        //console.log(title);
        if (title && title.innerText == "SOURCE") {
            title.innerText = parseTimestampString(curFileName || "main:114514").text + '.cpp';
        }
    }, 100);

})();