您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
An userscript to improve plain textarea for code editing.
当前为
- // ==UserScript==
- // @name Textarea Plus
- // @description An userscript to improve plain textarea for code editing.
- // @namespace eight04.blogspot.com
- // @include http*
- // @version 1.1.1
- // @grant GM_addStyle
- // ==/UserScript==
- "use strict";
- var ignoreClassList = ["CodeMirror", "ace_editor"];
- var textareaPlus = function(){
- var editor = {
- indent: indent,
- unindent: unindent,
- home: home,
- selectHome: selectHome,
- enter: enter,
- brace0: brace0,
- brace1: brace1
- };
- function selectionRange(data){
- return data.pos[1] - data.pos[0];
- }
- function takeRange(data) {
- if (data.pos[0] > data.pos[1]) {
- return [data.pos[1], data.pos[0]];
- }
- return data.pos;
- }
- function insert(data, text){
- var pos = takeRange(data);
- data.text = data.text.substr(0, pos[0]) + text + data.text.substr(pos[1]);
- data.pos[0] = pos[0] + text.length;
- data.pos[1] = data.pos[0];
- }
- function del(data){
- if (!selectionRange(data)) {
- data.pos[1]++;
- }
- insert(data, "");
- }
- function getLineStart(data, pos){
- if (pos == undefined) {
- pos = data.pos[1];
- }
- if (data.text[pos] == "\n") {
- pos--;
- }
- var s = data.text.lastIndexOf("\n", pos);
- if (s < 0) {
- return 0;
- }
- return s + 1;
- }
- function getLineEnd(data, pos){
- if (pos == undefined) {
- pos = data.pos[1];
- }
- var s = data.text.indexOf("\n", pos);
- if (s < 0) {
- return data.text.length;
- }
- return s;
- }
- function multiIndent(data){
- var pos = takeRange(data);
- var lineStart = getLineStart(data, pos[0]), lineEnd = getLineEnd(data, pos[1]);
- var lines = data.text.substr(lineStart, lineEnd - lineStart);
- var i;
- lines = lines.split("\n");
- for (i = 0; i < lines.length; i++) {
- lines[i] = "\t" + lines[i];
- }
- lines = lines.join("\n");
- data.text = data.text.substr(0, lineStart) + lines + data.text.substr(lineEnd);
- if (data.pos[0] > data.pos[1]) {
- data.pos[1] = lineStart;
- data.pos[0] = lineEnd + i;
- } else {
- data.pos[0] = lineStart;
- data.pos[1] = lineEnd + i;
- }
- }
- function inMultiLine(data) {
- var pos = takeRange(data);
- var s = data.text.indexOf("\n", pos[0]);
- if (s < 0) {
- return false;
- }
- return s < pos[1];
- }
- function indent(data){
- if (!selectionRange(data)) {
- insert(data, "\t");
- if (data.pos[0] < getTextStart(data)) {
- home(data);
- }
- } else {
- if (inMultiLine(data)) {
- multiIndent(data);
- } else {
- insert(data, "\t");
- }
- }
- }
- function multiUnindent(data){
- var pos = takeRange(data);
- var lineStart = getLineStart(data, pos[0]), lineEnd = getLineEnd(data, pos[1]);
- var lines = data.text.substr(lineStart, lineEnd - lineStart);
- var i, m;
- lines = lines.split("\n");
- var len = 0;
- for (i = 0; i < lines.length; i++) {
- m = lines[i].match(/^( {4}| {0,3}\t?)(.*)$/);
- // console.log(m);
- len += m[1].length;
- lines[i] = m[2];
- }
- lines = lines.join("\n");
- data.text = data.text.substr(0, lineStart) + lines + data.text.substr(lineEnd);
- if (data.pos[0] > data.pos[1]) {
- data.pos[1] = lineStart;
- data.pos[0] = lineEnd - len;
- } else {
- data.pos[0] = lineStart;
- data.pos[1] = lineEnd - len;
- }
- }
- function backspace(data) {
- if (selectionRange(data)) {
- del(data);
- } else if (data.pos[0] > 0) {
- data.pos[0]--;
- del(data);
- }
- }
- function unindent(data) {
- if (inMultiLine(data)) {
- multiUnindent(data);
- } else if (!selectionRange(data) && data.text[data.pos[0] - 1] == "\t") {
- backspace(data);
- } else {
- multiUnindent(data);
- home(data);
- }
- }
- function searchFrom(text, re, pos) {
- pos = pos || 0;
- var t = text.substr(pos);
- var s = t.search(re);
- if (s < 0) {
- return -1;
- }
- return s + pos;
- }
- function getTextStart(data, pos) {
- var lineStart = getLineStart(data, pos);
- pos = searchFrom(data.text, /[\S\n]/, lineStart);
- if (pos < 0 || data.text[pos] == "\n") {
- return getLineEnd(data);
- }
- return pos;
- }
- function isTextStart(data) {
- return getTextStart(data) == data.pos[1];
- }
- function home(data) {
- if (isTextStart(data)) {
- data.pos[0] = getLineStart(data);
- } else {
- data.pos[0] = getTextStart(data);
- }
- data.pos[1] = data.pos[0];
- }
- function selectHome(data) {
- var pos = data.pos[0];
- home(data);
- data.pos[0] = pos;
- }
- function getIndents(data) {
- var pos = takeRange(data);
- var lineStart = getLineStart(data, pos[0]);
- var len;
- var textStart = getTextStart(data, pos[0]);
- // console.log(textStart);
- if (textStart >= pos[0]) {
- len = pos[0] - lineStart;
- } else {
- len = textStart - lineStart;
- }
- return data.text.substr(lineStart, len);
- }
- function enter(data) {
- var indents = getIndents(data);
- var range = takeRange(data);
- var p = data.text[range[0] - 1];
- var q = data.text[range[1]];
- insert(data, "\n" + indents);
- if (p == "[" && q == "]" || p == "{" && q == "}") {
- insert(data, "\t\n" + indents);
- data.pos[0] -= indents.length + 1;
- data.pos[1] -= indents.length + 1;
- }
- }
- function brace0(data){
- insert(data, "[]");
- data.pos[0]--;
- data.pos[1]--;
- }
- function brace1(data){
- insert(data, "{}");
- data.pos[0]--;
- data.pos[1]--;
- }
- function init(node, command) {
- var data = {
- text: node.value,
- pos: [node.selectionStart, node.selectionEnd]
- }, t;
- if (node.selectionDirection == "backward") {
- t = data.pos[0];
- data.pos[0] = data.pos[1];
- data.pos[1] = t;
- }
- editor[command](data);
- node.value = data.text;
- if (data.pos[0] > data.pos[1]) {
- node.setSelectionRange(data.pos[1], data.pos[0], "backward");
- } else {
- node.setSelectionRange(data.pos[0], data.pos[1], "forward");
- }
- }
- return init;
- }();
- function validArea(area) {
- if (area.nodeName != "TEXTAREA") {
- return false;
- }
- if (area.dataset.textareaPlus === "false") {
- return false;
- }
- if (area.dataset.textareaPlus === "true") {
- return true;
- }
- // if (area.onkeydown) {
- // area.dataset.textareaPlus = "false";
- // return false;
- // }
- var node = area, i;
- while ((node = node.parentNode) != document.body) {
- for (i = 0; i < ignoreClassList.length; i++) {
- if (node.classList.contains(ignoreClassList[i])) {
- area.dataset.textareaPlus = "false";
- return false;
- }
- }
- }
- area.dataset.textareaPlus = "true";
- return true;
- }
- window.addEventListener("keydown", function(e){
- if (!validArea(e.target) || e.ctrlKey || e.altKey) {
- return;
- }
- var command;
- if (e.keyCode == 9) {
- // tab
- if (e.shiftKey) {
- command = "unindent";
- } else {
- command = "indent";
- }
- } else if (e.keyCode == 13) {
- // enter
- command = "enter";
- } else if (e.keyCode == 36) {
- // home
- if (!e.shiftKey) {
- command = "home";
- } else {
- command = "selectHome";
- }
- } else if (e.keyCode == 219) {
- // braces
- if (!e.shiftKey) {
- command = "brace0";
- } else {
- command = "brace1";
- }
- } else {
- return;
- }
- e.preventDefault();
- e.stopPropagation();
- textareaPlus(e.target, command);
- }, true);
- GM_addStyle("textarea {tab-size: 4; -moz-tab-size: 4; -o-tab-size: 4;}");