OptiYan

EYanIDE 优化

目前为 2024-08-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name OptiYan
  3. // @namespace http://lunarine.cc/
  4. // @version 2024-08-20
  5. // @description EYanIDE 优化
  6. // @author Liu Baicheng
  7. // @match http://121.36.38.167/
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=tampermonkey.net
  9. // @grant unsafeWindow
  10. // @license MIT
  11. // @resource css https://unpkg.com/mdui@1.0.2/dist/css/mdui.min.css
  12. // @grant GM_getResourceURL
  13. // @grant GM_getResourceText
  14. // @grant GM_addStyle
  15. // @grant GM_xmlhttpRequest
  16. // @grant GM_notification
  17. // @grant GM_setValue
  18. // @grant GM_getValue
  19. // @grant GM_registerMenuCommand
  20. // @require https://cdn.jsdelivr.net/npm/mdui@1.0.2/dist/js/mdui.min.js
  21. // @connect api.mkc.icu
  22. // ==/UserScript==
  23.  
  24. (function () {
  25. 'use strict';
  26.  
  27. const spans = document.querySelectorAll('span.lm_title');
  28. var title;
  29. // 遍历并输出内容为 main.cpp 的 span
  30. spans.forEach(span => {
  31. if (span.textContent.trim() === 'main.cpp') {
  32. title = span;
  33. }
  34. });
  35.  
  36. function classOptimize() {
  37.  
  38. const divs = document.querySelectorAll('div.ui.dropdown.selection');
  39.  
  40. // 遍历并删除这些 div
  41. divs.forEach(div => {
  42. div.remove();
  43. });
  44.  
  45. var compilerOptionsInput = document.getElementById('compiler-options');
  46. compilerOptionsInput.value = "-O3";
  47. var comilerArgsInput = document.getElementById('command-line-arguments');
  48. comilerArgsInput.remove();
  49. var navbar = document.getElementById("site-navigation");
  50. let optibar = document.createElement('div');
  51. optibar.classList.add("right");
  52. optibar.classList.add("menu");
  53. navbar.appendChild(optibar);
  54.  
  55. let tdiv = document.createElement('div');
  56. tdiv.className = "item no-right-padding borderless";
  57. tdiv.id = "userbar"
  58. optibar.appendChild(tdiv);
  59.  
  60. // let tbutton = document.createElement('button');
  61. // tbutton.className = "ui labeled icon button";
  62. // tbutton.id = "optiso";
  63. // tbutton.innerHTML = `<i class="search icon"></i><span>搜索</span>`;
  64. // tdiv.appendChild(tbutton);
  65.  
  66. // tbutton.onclick = function () {
  67. // let input = unsafeWindow.stdinEditor.getValue();
  68. // console.log(input);
  69. // tbutton.classList.add('loading');
  70. // requestGPT(input).then(response => {
  71. // unsafeWindow.sourceEditor.setValue(response);
  72. // tbutton.classList.remove('loading');
  73. // });
  74. // };
  75. }
  76.  
  77. function formatCppTemplateLine(line) {
  78. const templateRegex = /(\btemplate\b|\bvector\b|\bmap\b|\bset\b|\bp(?:air|queue)\b|<.*>)/;
  79. if (templateRegex.test(line.trim())) {
  80. return line
  81. .replace(/\s*(<|>)\s*/g, '$1')
  82. .replace(/>(\w)/g, '> $1');
  83. }
  84. return line;
  85. }
  86.  
  87. function formatCppCode(code) {
  88. code = code.replace(/\/\*[\s\S]*?\*\//g, '');
  89. code = code.replace(/\/\/.*$/gm, '');
  90. const lines = code.split('\n');
  91. let formattedLines = [];
  92. let indentLevel = 0;
  93. const indentSpace = ' ';
  94. let inStruct = false;
  95.  
  96. for (let i = 0; i < lines.length; i++) {
  97. let line = lines[i].trim();
  98. const isEndOfStructWithVar = line.match(/}\s*[a-zA-Z_][a-zA-Z0-9_]*\s*\[?\s*[^;]*;/);
  99.  
  100. if (line.includes('{') && !line.endsWith('{')) {
  101. line = line.replace(/\s*{\s*/g, ' {\n' + indentSpace.repeat(indentLevel + 1));
  102. }
  103.  
  104. if (line.startsWith('struct')) {
  105. inStruct = true;
  106. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  107. indentLevel++;
  108. continue;
  109. }
  110.  
  111. if (line.endsWith('};') || isEndOfStructWithVar) {
  112. if (indentLevel) indentLevel--;
  113. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  114. inStruct = false;
  115.  
  116. if (isEndOfStructWithVar) {
  117. continue;
  118. }
  119. formattedLines.push('');
  120. continue;
  121. }
  122.  
  123. if (inStruct) {
  124. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  125. continue;
  126. }
  127.  
  128. if (line.startsWith('#include')) {
  129. line = line.replace(/#include\s*<\s*([\w./+-]+)\s*>/g, '#include <$1>');
  130. formattedLines.push(line);
  131. continue;
  132. }
  133.  
  134. if (line === 'using namespace std;') {
  135. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  136. formattedLines.push('');
  137. continue;
  138. }
  139.  
  140. if (line.endsWith(')') && lines[i + 1] && lines[i + 1].trim() === '{') {
  141. line += ' {';
  142. i++;
  143. }
  144.  
  145. line = line.replace(/\s*([+\-*/=<>&|]+)\s*/g, ' $1 ');
  146. line = line.replace(/\s*,\s*/g, ', ');
  147. line = line.replace(/\s*([+\-]{2})\s*/g, '$1');
  148. line = line.replace(/\s*;\s*/g, '; ');
  149. line = line.replace(/\)\s*(?=[a-zA-Z+\-*/])/g, ') ');
  150.  
  151. line = line.replace(/(?<=[+\*/])\s*\(/g, ' (');
  152. line = line.replace(/(?<!\S)-\s*\(/g, '-(');
  153. line = line.replace(/\b(for|while|if|else|switch|case|do)\s*(?=[({])/g, '$1 ');
  154.  
  155. line = formatCppTemplateLine(line);
  156. line = line.replace(/!\s*=\s*/g, '!= ');
  157.  
  158.  
  159. if (line.endsWith('}')) {
  160. if (indentLevel) indentLevel--;
  161. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  162. if (indentLevel === 0 && !inStruct && line.endsWith('}')) {
  163. formattedLines.push('');
  164. }
  165. continue;
  166. }
  167.  
  168. if (line.includes("}")) {
  169. indentLevel--;
  170. }
  171.  
  172. if (line.includes(') {')) {
  173. if (indentLevel === 0 && !inStruct && formattedLines[formattedLines.length - 1] != '') {
  174. formattedLines.push('');
  175. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  176. indentLevel++;
  177. continue;
  178. }
  179. }
  180.  
  181. if (line) {
  182. formattedLines.push(indentSpace.repeat(indentLevel) + line);
  183. }
  184.  
  185. if (line.endsWith('{')) {
  186. indentLevel++;
  187. }
  188. }
  189.  
  190. return formattedLines.join('\n').trim();
  191. }
  192.  
  193. function formatCode() {
  194. const res = formatCppCode(unsafeWindow.sourceEditor.getValue());
  195. unsafeWindow.sourceEditor.setValue(res);
  196. }
  197.  
  198. classOptimize();
  199.  
  200. document.addEventListener('keydown', function (event) {
  201. if (event.ctrlKey && event.altKey) {
  202. formatCode(); // 调用目标函数
  203. mdui.snackbar({
  204. message: '代码格式化成功'
  205. });
  206. } else if (event.keyCode === 122) { // F11
  207. event.preventDefault();
  208. unsafeWindow.run();
  209. } else if (event.keyCode === 116) { // F5
  210. event.preventDefault();
  211. } else if (event.ctrlKey && event.keyCode === 82) { // Ctrl+R
  212. event.preventDefault();
  213. } else if (event.ctrlKey && event.keyCode === 121) { // Ctrl+R
  214. event.preventDefault();
  215. } else if (event.keyCode == 83 && event.ctrlKey) {
  216. event.preventDefault();
  217. saveFile();
  218. }
  219. });
  220.  
  221. unsafeWindow.formatCppCode = formatCppCode;
  222. formatCode();
  223.  
  224. window.addEventListener('load', function () {
  225. var footer = document.querySelector('#site-footer');
  226. if (footer) {
  227. var span = document.createElement('span');
  228. span.id = 'optiyan-line';
  229. span.textContent = 'OptiYan 已加载 Version: V1.1.0';
  230. span.style.color = "#fff";
  231. span.style.float = "left";
  232. span.style.left = "0";
  233. span.style.textAlign = "left";
  234. span.style.width = "fit-content";
  235. footer.appendChild(span);
  236. }
  237. var runBtn = document.getElementById('run-btn-label');
  238. runBtn.textContent = 'Run (F11 / Ctrl + ↵)';
  239. });
  240.  
  241. function updateColor() {
  242. let status = document.getElementById("status-line");
  243. if (status) {
  244. if (status.innerText.includes('Error')) {
  245. const sitefooter = document.querySelector('#site-footer');
  246. const linefooter = document.querySelector('#status-line');
  247.  
  248. sitefooter.style.backgroundColor = "#c14343";
  249. linefooter.style.backgroundColor = "#c14343";
  250. } else if (status.innerText.includes('Accept')) {
  251. const sitefooter = document.querySelector('#site-footer');
  252. const linefooter = document.querySelector('#status-line');
  253. sitefooter.style.backgroundColor = "#05a705";
  254. linefooter.style.backgroundColor = "#05a705";
  255. } else {
  256. const sitefooter = document.querySelector('#site-footer');
  257. const linefooter = document.querySelector('#status-line');
  258. sitefooter.style.backgroundColor = "#9775fa";
  259. linefooter.style.backgroundColor = "#9775fa";
  260. }
  261. } else {
  262. const sitefooter = document.querySelector('#site-footer');
  263. const linefooter = document.querySelector('#status-line');
  264. sitefooter.style.backgroundColor = "#9775fa";
  265. linefooter.style.backgroundColor = "#9775fa";
  266. }
  267.  
  268. }
  269.  
  270. let script = document.createElement('script');
  271. script.src = "https://unpkg.com/mdui@1.0.2/dist/js/mdui.min.js?v=20240817";
  272.  
  273. script.onload = function () {
  274. console.log('mdui 已加载');
  275. };
  276.  
  277. document.body.appendChild(script);
  278. console.log(GM_getResourceURL("css"), GM_getResourceText("css"));
  279. GM_addStyle(GM_getResourceText("css"));
  280.  
  281. setInterval(updateColor, 100);
  282.  
  283. var userbar = document.getElementById('userbar');
  284. //var fileList = document.getElementById('fileList');
  285. var loginButton = document.createElement('button');
  286. loginButton.className = "ui labeled icon button";
  287. loginButton.innerHTML = `<i class="user icon"></i><span>登陆</span>`;
  288. loginButton.style.marginRight = "5px";
  289. loginButton.addEventListener('click', function () {
  290. login();
  291. });
  292. var registerButton = document.createElement('button');
  293. registerButton.className = "ui labeled icon button";
  294. registerButton.innerHTML = `<i class="add icon"></i><span>注册</span>`;
  295. registerButton.style.marginRight = "5px";
  296. registerButton.addEventListener('click', function () {
  297. register();
  298. });
  299. var logoutButton = document.createElement('button');
  300. logoutButton.innerHTML = `<i class="sign-out icon"></i><span>退出登录</span>`;
  301. logoutButton.className = "ui labeled icon button";
  302. logoutButton.addEventListener('click', function () {
  303. logout();
  304. });
  305.  
  306. var saveButton = document.createElement('button');
  307. saveButton.innerHTML = `<i class="save icon"></i><span>保存文件 (Ctrl + S)</span>`;
  308. saveButton.style.marginRight = "5px";
  309. saveButton.className = "ui labeled icon button";
  310. saveButton.addEventListener('click', function () {
  311. saveFile();
  312. });
  313.  
  314. var deleteButton = document.createElement('button');
  315. deleteButton.innerHTML = `<i class="trash icon"></i><span>删除文件</span>`;
  316. deleteButton.style.marginRight = "5px";
  317. deleteButton.className = "ui red labeled icon button";
  318. deleteButton.addEventListener('click', function () {
  319. deleteFile();
  320. });
  321.  
  322. var userMessage = document.createElement('div');
  323. userMessage.classList.add('ui');
  324. userMessage.classList.add('site-link');
  325. userMessage.style.marginRight = "30px";
  326.  
  327. var openButton = document.createElement('button');
  328. openButton.innerHTML = `<i class="file icon"></i><span>打开文件</span>`;
  329. openButton.style.marginRight = "5px";
  330. openButton.className = "ui labeled icon button";
  331. openButton.addEventListener('click', function () {
  332. var filename = prompt('请输入文件名');
  333. if (filename != null && filename.length >= 1) {
  334. loadFile(filename);
  335. mdui.snackbar({
  336. message: '文件加载成功'
  337. });
  338. } else {
  339. mdui.snackbar({
  340. message: '文件加载失败'
  341. });
  342. }
  343. openButton.classList.remove('loading');
  344. });
  345.  
  346. // 初始化用户界面
  347. function updateUI() {
  348. userbar.innerHTML = '';
  349. if (isLoggedIn) {
  350. userMessage.innerText = "已登录为 @" + Gusername;
  351. userbar.appendChild(userMessage);
  352. userbar.appendChild(saveButton);
  353. if(title.innerText != "main.cpp") userbar.appendChild(deleteButton);
  354. userbar.appendChild(openButton);
  355. userbar.appendChild(logoutButton);
  356. } else {
  357. userbar.appendChild(loginButton);
  358. userbar.appendChild(registerButton);
  359. }
  360. }
  361.  
  362. let token = localStorage.getItem('token');
  363. let Gusername = localStorage.getItem('username');
  364. let isLoggedIn = !!token; // 如果 token 存在,则 isLoggedIn 为 true
  365.  
  366. function login() {
  367. var username = prompt('请输入用户名');
  368. var password = prompt('请输入密码');
  369. loginButton.classList.add('loading');
  370. GM_xmlhttpRequest({
  371. method: 'POST',
  372. url: 'http://api.mkc.icu/login',
  373. headers: {
  374. 'Content-Type': 'application/json'
  375. },
  376. data: JSON.stringify({
  377. username: username,
  378. password: password
  379. }),
  380. onload: function (response) {
  381. var data = JSON.parse(response.responseText);
  382. if (data.token) {
  383. mdui.snackbar({
  384. message: '登录成功'
  385. });
  386. token = data.token;
  387. isLoggedIn = true;
  388. Gusername = username;
  389. localStorage.setItem('token', token); // 保存 token 到 localStorage
  390. localStorage.setItem('username', username);
  391. loginButton.classList.remove('loading');
  392. updateUI();
  393. openFile();
  394. } else {
  395. mdui.snackbar({
  396. message: '登录失败'
  397. });
  398. }
  399. },
  400. onerror: function (error) {
  401. console.error('登录请求错误:', error);
  402. }
  403. });
  404. }
  405.  
  406. function register() {
  407. var username = prompt('请输入用户名');
  408. var password = prompt('请输入密码');
  409. const a = Math.floor(Math.random() * (9999 - 1000 + 1)) + 1000;
  410. const b = Math.floor(Math.random() * (9999 - 1000 + 1)) + 1000;
  411. var answer = prompt(`请输入 ${a} + ${b} 的答案`);
  412.  
  413. if (answer != a + b) {
  414. mdui.snackbar({
  415. message: `注册失败:你是人机嘛?`
  416. });
  417. return;
  418. }
  419. registerButton.classList.add('loading');
  420. GM_xmlhttpRequest({
  421. method: 'POST',
  422. url: 'http://api.mkc.icu/register',
  423. headers: {
  424. 'Content-Type': 'application/json'
  425. },
  426. data: JSON.stringify({
  427. username: username,
  428. password: password
  429. }),
  430. onload: function (response) {
  431. var data = JSON.parse(response.responseText);
  432. if (data.message === '注册成功') {
  433. token = data.token;
  434. isLoggedIn = true;
  435. Gusername = username;
  436. localStorage.setItem('token', token); // 保存 token 到 localStorage
  437. localStorage.setItem('username', username);
  438. mdui.snackbar({
  439. message: '注册成功'
  440. });
  441. registerButton.classList.remove('loading');
  442. updateUI();
  443. openFile();
  444. } else {
  445. mdui.snackbar({
  446. message: `注册失败:${data.message}`
  447. });
  448. }
  449. },
  450. onerror: function (error) {
  451. console.error('注册请求错误:', error);
  452. }
  453. });
  454. }
  455.  
  456. function saveFile() {
  457. if (!isLoggedIn) {
  458. mdui.snackbar({
  459. message: `请先登录!`
  460. });
  461. return;
  462. }
  463. var filename;
  464. if (title.innerText == "main.cpp") filename = prompt('请输入文件名');
  465. else filename = title.innerText;
  466. if (filename == null || filename == "" || filename.length <= 1) {
  467. mdui.snackbar({
  468. message: `文件名不能为空!`
  469. });
  470. return;
  471. }
  472. var content = unsafeWindow.sourceEditor.getValue();
  473. saveButton.classList.add('loading');
  474. GM_xmlhttpRequest({
  475. method: 'POST',
  476. url: 'http://api.mkc.icu/files',
  477. headers: {
  478. 'Content-Type': 'application/json',
  479. },
  480. data: JSON.stringify({
  481. token: token, // 将token放入body中
  482. filename: filename,
  483. content: content
  484. }),
  485. onload: function (response) {
  486. try {
  487. var data = JSON.parse(response.responseText);
  488. title.innerText = filename + ".cpp";
  489. if (data.message === '文件保存成功') {
  490. openFile();
  491. mdui.snackbar({
  492. message: `文件保存成功!`
  493. });
  494. saveButton.classList.remove('loading');
  495. updateUI();
  496.  
  497. } else {
  498. mdui.snackbar({
  499. message: `保存失败:${data.message}`
  500. });
  501. saveButton.classList.remove('loading');
  502. }
  503. } catch (e) {
  504. console.error('解析响应时出错:', e);
  505. }
  506. },
  507. onerror: function (error) {
  508. console.error('保存文件请求错误:', error);
  509. }
  510. });
  511. }
  512.  
  513. function deleteFile() {
  514. if (!isLoggedIn) {
  515. alert('请先登录');
  516. return;
  517. }
  518. var filename;
  519. if (title.innerText == "main.cpp") filename = prompt('请输入文件名');
  520. else {
  521. filename = title.innerText;
  522. filename = filename.replace(/\.[^/.]+$/, "");
  523. }
  524. if (filename == '') {
  525. alert('文件名不能为空!');
  526. return;
  527. }
  528. var content = unsafeWindow.sourceEditor.getValue();
  529. deleteButton.classList.add('loading');
  530. GM_xmlhttpRequest({
  531. method: 'POST',
  532. url: 'http://api.mkc.icu/delete',
  533. headers: {
  534. 'Content-Type': 'application/json',
  535. },
  536. data: JSON.stringify({
  537. token: token, // 将token放入body中
  538. filename: filename
  539. }),
  540. onload: function (response) {
  541. try {
  542. var data = JSON.parse(response.responseText);
  543. if (data.message === '文件删除成功') {
  544. openFile();
  545. mdui.snackbar({
  546. message: `文件删除成功!`
  547. });
  548. deleteButton.classList.remove('loading');
  549. updateUI();
  550. } else {
  551. mdui.snackbar({
  552. message: `文件删除失败:${data.message}`
  553. });
  554. deleteButton.classList.remove('loading');
  555. }
  556. } catch (e) {
  557. console.error('解析响应时出错:', e);
  558. }
  559. },
  560. onerror: function (error) {
  561. console.error('删除文件请求错误:', error);
  562. }
  563. });
  564. }
  565.  
  566. function openFile() {
  567. if (!isLoggedIn) {
  568. mdui.snackbar({
  569. message: `请先登录!`
  570. });
  571. return;
  572. }
  573.  
  574. GM_xmlhttpRequest({
  575. method: 'GET',
  576. url: `http://api.mkc.icu/files?token=${encodeURIComponent(token)}`,
  577. headers: {
  578. 'Content-Type': 'application/json',
  579. },
  580. onload: function (response) {
  581. try {
  582. unsafeWindow.stdoutEditor.setValue("当前文件:");
  583. var data = JSON.parse(response.responseText);
  584. if (data.files && data.files.length > 0) {
  585. data.files.forEach(filename => {
  586. unsafeWindow.stdoutEditor.setValue(unsafeWindow.stdoutEditor.getValue() + "\n - " + filename);
  587. });
  588. unsafeWindow.stdoutEditor.setValue(unsafeWindow.stdoutEditor.getValue() + '\n输入文件名称加载。');
  589. } else {
  590. mdui.snackbar({
  591. message: `你还没有保存过文件......`
  592. });
  593. }
  594. } catch (e) {
  595. console.error('解析响应时出错:', e);
  596. }
  597. },
  598. onerror: function (error) {
  599. console.error('打开文件请求错误:', error);
  600. }
  601. });
  602. }
  603.  
  604. function loadFile(filename) {
  605. openButton.classList.add('loading');
  606. GM_xmlhttpRequest({
  607. method: 'GET',
  608. url: `http://api.mkc.icu/files/${filename}?token=${encodeURIComponent(token)}`,
  609. onload: function (response) {
  610. var data = JSON.parse(response.responseText);
  611. unsafeWindow.sourceEditor.setValue(data.file); // 将文件内容加载到编辑器中
  612. title.innerText = filename + ".cpp";
  613. openButton.classList.remove('loading');
  614. document.title = filename + " - EYanIDE"
  615. updateUI();
  616. },
  617. onerror: function (error) {
  618. console.error('Error:', error);
  619. openButton.classList.remove('loading');
  620. }
  621. });
  622. }
  623.  
  624. openFile();
  625.  
  626. function logout() {
  627. token = null;
  628. localStorage.removeItem('token');
  629. isLoggedIn = false;
  630. Gusername = '';
  631. localStorage.removeItem('username');
  632. updateUI();
  633. mdui.snackbar({
  634. message: `已注销`
  635. });
  636. }
  637. updateUI();
  638. })();