1 #title = "indent"
  2 #tooltip = "桁数判別インデント+空行を含むインデント+空行のみインデント"
  3 #include "lib\sgc4jsee.jsee"
  4 
  5 /**
  6  * @fileOverview
  7  * 選択範囲がない場合、キャレットより下にあるインデントの桁数を判別してインデントします。<br />
  8  * 選択範囲にインデントされた行と空行が混在している場合は、空行のみをインデントします。<br />
  9  * それ以外の場合、空行を含む全行に対してインデントを行います。
 10  * 
 11  * @author gecca from 雪月花 (http://setsugecca.org/)
 12  * @version 1.00 for EmEditor v10.0
 13  */
 14 
 15 (function() {
 16 	var redraw = Redraw;
 17 	Redraw = false;
 18 	
 19 	var logger = JseeUtil.getLogger(false, "桁数判別インデント+空行を含むインデント+空行のみインデント.jsee");
 20 	
 21 	var indent = JseeUtil.getIndent();
 22 	logger.log("indent:" + indent);
 23 	
 24 	// インデントを判別して貼り付けより転用
 25 	var indentSpaces = [];
 26 	for(var i=0;i<document.Config.Indent.IndentColumns;i++) {indentSpaces.push(" ");}
 27 	var indentSpace = indentSpaces.join("");
 28 	logger.log("indentSpace:" + indentSpace);
 29 	var transitionalIndentPattern = "^(\t|" + indentSpace + ")*";
 30 	var transitionalIndentMatcher = new RegExp(transitionalIndentPattern);
 31 	var tabSpaces = [];
 32 	for(var i=0;i<document.Config.Indent.TabColumns;i++) {tabSpaces.push(" ");}
 33 	var tabSpace = tabSpaces.join("");
 34 	
 35 	// 下部で空行でない行のインデント
 36 	var lowerLineIndent = (function() {
 37 		var topY = document.selection.GetTopPointY(eePosLogical);
 38 		var lineCnt = document.GetLines();
 39 		for(var i=topY + 1;i<=lineCnt;i++) {
 40 			if(document.getLine(i)) {
 41 				transitionalIndentMatcher.test(document.getLine(i));
 42 				return RegExp.lastMatch;
 43 			}
 44 		}
 45 	})();
 46 	
 47 	var notSelected = !document.selection.Text;
 48 	
 49 	// 選択範囲を保存
 50 	var topX = document.selection.GetTopPointX(eePosLogical);
 51 	var topY = document.selection.GetTopPointY(eePosLogical);
 52 	var bottomX = document.selection.GetBottomPointX(eePosLogical);
 53 	var bottomY = document.selection.GetBottomPointY(eePosLogical);
 54 	
 55 	// 行選択
 56 	JseeUtil.selectLines();
 57 	
 58 	// 現在行の中で最も小さいインデント(ただし空行を除く)
 59 	var minimumIndent = JseeUtil.getMinimumIndent(document.selection.Text.replace(/\r\n|\r/g, "\n").replace(/(^|\n)\n+/g, "$1"));
 60 	logger.log("minimumIndent:" + minimumIndent);
 61 	var indentReplacer = new RegExp("(^|\r\n|\r|\n)(?![\r\n]?$)" + minimumIndent, "g");
 62 	if(logger.available()) {
 63 		logger.log("indentReplacer:" + JseeUtil.toString(indentReplacer));
 64 	}
 65 	
 66 	// 追加後のインデント
 67 	var additionalIndent = (function() {
 68 		// 下部で空行でない行のインデントがない場合は、1つインデント
 69 		if(!lowerLineIndent) {
 70 			return indent;
 71 		}
 72 		// インデントを補充する必要がない場合は、1つインデント
 73 		var uppderIndentLength = lowerLineIndent.replace(/\t/g, tabSpace).length;
 74 		if(uppderIndentLength <= minimumIndent.replace(/\t/g, tabSpace).length) {
 75 			return indent;
 76 		}
 77 		// インデントを補充する必要がある場合は、補充分のインデント
 78 		var buf = minimumIndent;
 79 		var arr = [];
 80 		while(uppderIndentLength > buf.replace(/\t/g, tabSpace).length) {
 81 			buf = indent + buf;
 82 			arr.push(indent);
 83 		}
 84 		return arr.join("");
 85 	})();
 86 	logger.log("additionalIndent:" + JseeUtil.escEscSeq(additionalIndent));
 87 	var resultIndent = additionalIndent + minimumIndent;
 88 	logger.log("resultIndent:" + JseeUtil.escEscSeq(resultIndent));
 89 	
 90 	// 最初に選択されていなかった場合
 91 	if(notSelected) {
 92 		logger.log("最初に選択されていなかった場合");
 93 		// 行選択しても選択範囲がない場合は、ただインデントを出力
 94 		if(!document.selection.Text) {
 95 			logger.log("ただインデントを出力");
 96 			Redraw = redraw;
 97 			document.selection.Text = indent;
 98 		// 行選択して選択範囲がある場合は、その行の先頭を桁数判別後インデントに置換
 99 		} else {
100 			logger.log("行の先頭を桁数判別後インデントに置換");
101 			document.selection.Text = document.selection.Text.replace(indentReplacer, "$1" + resultIndent);
102 			Redraw = redraw;
103 			document.selection.SetActivePoint(eePosLogical, topX + additionalIndent.length, topY);
104 		}
105 	
106 	// 最初に選択されていた場合
107 	} else {
108 		logger.log("最初に選択されていた場合");
109 		// インデントされた行と空行が混在している場合は、空行のみをインデント
110 		// (行選択の場合、末尾で必ずマッチしてしまうため、空行のマッチで$は使用しない)
111 		if(document.selection.Text.match(/(^)(\r|\n)|(\n)(\r|\n)|(\r)(\r)/) && !document.selection.Text.match(/^\S/m)) {
112 			logger.log("空行のみをインデント");
113 			document.selection.Text = document.selection.Text.replace(/(^)(\r|\n)|(\n)(\r|\n)|(\r)(\r)/g, "$1$3$5" + minimumIndent + "$2$4$6");
114 			
115 		// それ以外の場合は空行を含む全行をインデント
116 		} else {
117 			logger.log("空行を含む全行をインデント");
118 			document.selection.Text = document.selection.Text.replace(/(^|\r\n|\r|\n)/g, "$1" + indent).replace(new RegExp(indent + "$"), "");
119 		}
120 		
121 		// インデントの長さ分、x座標を調整する (ただし先頭のx座標が動くのはおかしいので、それ以外の場合のみ)
122 		var _topX = (topX == 1) ? topX : topX + additionalIndent.length;
123 		var _bottomX = (bottomX == 1) ? bottomX : bottomX + indent.length;
124 		
125 		// 選択範囲を復元
126 		Redraw = redraw;
127 		document.selection.SetActivePoint(eePosLogical, _topX, topY);
128 		document.selection.SetActivePoint(eePosLogical, _bottomX, bottomY, true);
129 	}
130 })();
131