您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Move lines up and down in textarea with Alt + Arrow Up/Down hotkeys, same as in VSCode
// ==UserScript== // @name Move Lines in Textarea with Alt + Arrow Up/Down // @author NWP // @description Move lines up and down in textarea with Alt + Arrow Up/Down hotkeys, same as in VSCode // @namespace https://greasyfork.runtimutd.eu.org/users/877912 // @version 0.2 // @license MIT // @match *://*/* // @grant none // ==/UserScript== (function() { 'use strict'; function moveLine(element, direction) { const start = element.selectionStart; const value = element.value; const lines = value.split('\n'); const lineIndex = value.substr(0, start).split('\n').length - 1; const lineStart = value.lastIndexOf('\n', start - 1) + 1; const cursorOffsetInLine = start - lineStart; if ((direction === 'up' && lineIndex === 0) || (direction === 'down' && lineIndex === lines.length - 1)) { return; } const targetLineIndex = direction === 'up' ? lineIndex - 1 : lineIndex + 1; [lines[lineIndex], lines[targetLineIndex]] = [lines[targetLineIndex], lines[lineIndex]]; const newValue = lines.join('\n'); const newLineStart = newValue.split('\n').slice(0, targetLineIndex).join('\n').length + (targetLineIndex > 0 ? 1 : 0); const newCursorPosition = newLineStart + cursorOffsetInLine; element.value = newValue; element.setSelectionRange(newCursorPosition, newCursorPosition); } function handleKeyDown(e) { if (e.altKey && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) { const activeElement = document.activeElement; if (activeElement && activeElement.tagName === 'TEXTAREA') { e.preventDefault(); const direction = e.key === 'ArrowUp' ? 'up' : 'down'; moveLine(activeElement, direction); } } } function observeTextAreas() { document.addEventListener('keydown', handleKeyDown); const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.tagName === 'TEXTAREA' || (node.nodeType === Node.ELEMENT_NODE && node.querySelector('textarea'))) { document.addEventListener('keydown', handleKeyDown); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); } observeTextAreas(); })();