// ==UserScript== // @name PTA剪贴板逐行打字(自动清除缩进) // @namespace http://tampermonkey.net/ // @version 1.6 // @description 模拟Python版逻辑:检测每行前是否有缩进空格,有则删除,再输入内容 // @author You // @match https://pintia.cn/* // @grant none // ==/UserScript== (function() { 'use strict'; let isPaused = false; let isRunning = false; let container = document.createElement('div'); container.style.cssText = 'position:fixed;top:10px;right:10px;z-index:9999;display:flex;gap:10px;'; document.body.appendChild(container); let startBtn = document.createElement('button'); startBtn.innerHTML = '📋 自动打字'; startBtn.style.cssText = 'padding:10px 20px;background:#4CAF50;color:white;border:none;border-radius:5px;cursor:pointer;font-size:16px;'; container.appendChild(startBtn); let pauseBtn = document.createElement('button'); pauseBtn.innerHTML = '⏸️ 暂停'; pauseBtn.style.cssText = 'padding:10px 20px;background:#FF9800;color:white;border:none;border-radius:5px;cursor:pointer;font-size:16px;display:none;'; container.appendChild(pauseBtn); pauseBtn.onclick = function() { isPaused = !isPaused; pauseBtn.innerHTML = isPaused ? '▶️ 继续' : '⏸️ 暂停'; pauseBtn.style.background = isPaused ? '#2196F3' : '#FF9800'; }; async function deleteIndentIfExists() { // 模拟 Shift+Home 选中光标前面到行首的内容 // 用键盘事件模拟 let editor = document.activeElement; // Shift+Home editor.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', code: 'Home', keyCode: 36, shiftKey: true, bubbles: true, cancelable: true })); await new Promise(r => setTimeout(r, 50)); // 复制选中内容来检测 let oldClipboard = ''; try { oldClipboard = await navigator.clipboard.readText(); } catch(e) {} document.execCommand('copy'); await new Promise(r => setTimeout(r, 50)); let selected = ''; try { selected = await navigator.clipboard.readText(); // 恢复剪贴板 await navigator.clipboard.writeText(oldClipboard); } catch(e) {} // 判断选中内容是否只有空格 if (selected && selected.trim() === '') { // 纯空格,删除 document.execCommand('delete'); } else { // 包含代码,取消选中(按右方向键) editor.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', code: 'ArrowRight', keyCode: 39, bubbles: true })); } await new Promise(r => setTimeout(r, 100)); } async function typeFast(text) { for (let char of text) { while (isPaused) { await new Promise(r => setTimeout(r, 200)); } document.execCommand('insertText', false, char); await new Promise(r => setTimeout(r, 50)); } } startBtn.onclick = async function() { if (isRunning) return; isRunning = true; startBtn.style.display = 'none'; pauseBtn.style.display = 'block'; try { let text = await navigator.clipboard.readText(); let lines = text.split('\n'); let editor = document.querySelector('.CodeMirror textarea') || document.querySelector('.cm-content') || document.activeElement; if (!editor) { alert('请先点击PTA的代码编辑区域'); isRunning = false; startBtn.style.display = 'block'; pauseBtn.style.display = 'none'; return; } editor.focus(); await new Promise(r => setTimeout(r, 300)); for (let i = 0; i < lines.length; i++) { while (isPaused) { await new Promise(r => setTimeout(r, 200)); } if (i === 0) { // 第一行直接输入 if (lines[i]) { await typeFast(lines[i]); } // 回车 document.execCommand('insertText', false, '\n'); await new Promise(r => setTimeout(r, 150)); } else { // 检测并删除缩进 await deleteIndentIfExists(); if (lines[i]) { await typeFast(lines[i]); } // 回车 document.execCommand('insertText', false, '\n'); await new Promise(r => setTimeout(r, 150)); } } alert('✅ 输入完成!'); } catch(e) { alert('❌ 请先复制代码,点击编辑区域,再按按钮'); console.error(e); } isRunning = false; isPaused = false; startBtn.style.display = 'block'; pauseBtn.style.display = 'none'; pauseBtn.innerHTML = '⏸️ 暂停'; pauseBtn.style.background = '#FF9800'; }; })();