「選択範囲を広げる」の版間の差分
ナビゲーションに移動
検索に移動
編集の要約なし |
編集の要約なし |
||
| 18行目: | 18行目: | ||
**上記の条件に当てはまらず、選択範囲末尾の右側に括弧の開始記号がある場合には、その括弧を全て洗濯する | **上記の条件に当てはまらず、選択範囲末尾の右側に括弧の開始記号がある場合には、その括弧を全て洗濯する | ||
**上記の動作によって選択範囲が広がらなかった場合には、選択範囲を左右それぞれ1単語ずつ広げる | **上記の動作によって選択範囲が広がらなかった場合には、選択範囲を左右それぞれ1単語ずつ広げる | ||
=== ソースコード: === | |||
<source lang="javascript"> | <source lang="javascript"> | ||
| 250行目: | 252行目: | ||
sel.SetActivePos(endPos, SHIFT); | sel.SetActivePos(endPos, SHIFT); | ||
} | } | ||
} | |||
</source> | |||
=== Mery Ver.3.0.1 以降に対応するマルチカーソル対応実装 (試験実装メソッドを利用): === | |||
<source lang="javascript"> | |||
#title="選択範囲を広げる" | |||
BeginUndoGroup(); | |||
Redraw = false; | |||
//■括弧の定義(0+2n:開き/1+2n:閉じ) | |||
var BRACKET = '()<>[]{}「」『』【】()'; | |||
var sel = document.selection; | |||
var txt = Document.Text; | |||
if (sel.Mode === meModeMulti) { | |||
doMultiAction(main); | |||
} else { | |||
main(); | |||
} | |||
function main() { | |||
if (sel.IsEmpty) { | |||
var selectStartPos = selectBottomPos = sel.GetActivePos(); | |||
if (leftCharIsStartBracket(selectStartPos) | |||
|| rightCharIsEndBracket(selectBottomPos)) { | |||
// カーソルの左右いずれかに開き括弧があった場合 | |||
moveToBracketEnd(selectStartPos, selectBottomPos); | |||
} else { | |||
// 単語を選択 | |||
sel.SelectWord(); | |||
} | |||
} else { | |||
expandSelection(); | |||
} | |||
} | |||
function expandSelection() { | |||
var EXTEND_ON = true; | |||
var EXTEND_OFF = false; | |||
// 選択範囲取得 | |||
var topX = sel.GetTopPointX(mePosLogical); | |||
var topY = sel.GetTopPointY(mePosLogical); | |||
var bottomX = sel.GetBottomPointX(mePosLogical); | |||
var bottomY = sel.GetBottomPointY(mePosLogical); | |||
// 選択終了位置のポジション取得 | |||
sel.SetActivePoint(mePosLogical, bottomX, bottomY, EXTEND_OFF); | |||
var selectBottomPos = sel.GetActivePos(); | |||
// 選択開始位置に移動 | |||
sel.SetActivePoint(mePosLogical, topX, topY, EXTEND_OFF); | |||
var selectTopPos = sel.GetActivePos(); | |||
var selectStartPos, selectEndPos; | |||
if (selectTopPos <= selectBottomPos) { | |||
selectStartPos = selectTopPos; | |||
selectEndPos = selectBottomPos; | |||
} else { | |||
selectStartPos = selectBottomPos; | |||
selectEndPos = selectTopPos; | |||
} | |||
if (bothSideCharIsBracket(selectStartPos, selectEndPos)) { | |||
// 両脇が括弧だった場合 | |||
sel.CharLeft(EXTEND_OFF); | |||
sel.SetActivePos(selectEndPos, EXTEND_ON); | |||
sel.CharRight(EXTEND_ON); | |||
} else if (txt.charAt(selectEndPos) === '.') { | |||
// 選択範囲末尾右側がドットだった場合 | |||
selectRightSideWordsOfDot(selectStartPos, selectEndPos); | |||
} else if (leftCharIsStartBracket(selectEndPos + 1)) { | |||
// 選択範囲右側が開始括弧だった場合 | |||
selectRightSideWordsOfBracket(selectStartPos, selectEndPos); | |||
} else if ( | |||
leftCharIsStartBracket(selectStartPos) || | |||
rightCharIsEndBracket(selectEndPos) | |||
) { | |||
// 左右どちらかが括弧だった場合 | |||
moveToBracketEnd(selectStartPos, selectEndPos); | |||
} else { | |||
// 選択範囲を拡大 | |||
sel.WordLeft(EXTEND_OFF); | |||
sel.SetActivePos(selectEndPos, EXTEND_ON); | |||
sel.WordRight(EXTEND_ON); | |||
} | |||
// 選択範囲拡大後の選択範囲取得 | |||
var expandedTopX = sel.GetTopPointX(mePosLogical); | |||
var expandedTopY = sel.GetTopPointY(mePosLogical); | |||
var expandedBottomX = sel.GetBottomPointX(mePosLogical); | |||
var expandedBottomY = sel.GetBottomPointY(mePosLogical); | |||
// 選択範囲が変わっていない場合は、左右1単語ずつ拡大する | |||
if ( | |||
topX === expandedTopX && | |||
topY === expandedTopY && | |||
bottomX === expandedBottomX && | |||
bottomY === expandedBottomY | |||
) { | |||
sel.SetActivePos(selectStartPos); | |||
sel.WordLeft(EXTEND_OFF); | |||
sel.SetActivePos(selectEndPos, EXTEND_ON); | |||
sel.WordRight(EXTEND_ON); | |||
} | |||
} | |||
function selectRightSideWordsOfDot(selectStartPos, selectEndPos) { | |||
if (txt.charAt(selectEndPos) !== '.') { | |||
return; | |||
} | |||
var EXTEND_ON = true; | |||
sel.SetActivePos(selectStartPos); | |||
sel.SetActivePos(selectEndPos, EXTEND_ON); | |||
sel.CharRight(EXTEND_ON); | |||
sel.WordRight(EXTEND_ON); | |||
selectRightSideWordsOfDot(selectStartPos, sel.GetActivePos()); | |||
} | |||
function selectRightSideWordsOfBracket(selectStartPos, selectEndPos) { | |||
if (!leftCharIsStartBracket(selectEndPos + 1)) { | |||
return; | |||
} | |||
moveToBracketEnd(selectEndPos + 1, selectEndPos + 1); | |||
var movedEndPos = sel.GetActivePos() + 1; | |||
var EXTEND_ON = true; | |||
sel.SetActivePos(selectStartPos); | |||
sel.SetActivePos(movedEndPos, EXTEND_ON); | |||
} | |||
function leftCharIsStartBracket(selectStartPos) { | |||
var startPos; | |||
if (selectStartPos) { | |||
startPos = selectStartPos; | |||
} else { | |||
startPos = Document.Selection.GetActivePos(); | |||
} | |||
var startChar = txt.charAt(startPos - 1); //カーソル左側の文字を取得 | |||
var startBrcIdx = BRACKET.indexOf(startChar); | |||
return startBrcIdx !== -1 && startChar !== '' && startBrcIdx % 2 === 0; | |||
} | |||
function rightCharIsEndBracket(selectEndPos) { | |||
var endPos; | |||
if (selectEndPos) { | |||
endPos = selectEndPos; | |||
} else { | |||
endPos = Document.Selection.GetActivePos(); | |||
} | |||
var endChar = txt.charAt(endPos); //カーソル右側の文字を取得 | |||
var endBrcIdx = BRACKET.indexOf(endChar); | |||
return endBrcIdx !== -1 && endChar !== '' && endBrcIdx % 2 === 1; | |||
} | |||
function bothSideCharIsBracket(selectStartPos, selectEndPos) { | |||
var txt = Document.Text; | |||
var sPos = selectStartPos; //カーソル始点 | |||
var ePos = selectEndPos; //カーソル終点 | |||
var sBrc = txt.charAt(sPos - 1); //カーソル始点左側の文字を取得 | |||
var eBrc = txt.charAt(ePos); //カーソル終点右側の文字を取得 | |||
var isBrc = BRACKET.indexOf(sBrc); | |||
var ieBrc = BRACKET.indexOf(eBrc); | |||
return ( | |||
!(isBrc === -1 || sBrc === '') && | |||
!(ieBrc === -1 || eBrc === '') && | |||
ieBrc - isBrc === 1 | |||
); | |||
} | |||
function moveToBracketEnd(selectStartPos, selectEndPos) { | |||
//■範囲選択(true:する/false:しない) | |||
var SHIFT = true; | |||
quit: { | |||
var startPos = selectStartPos; | |||
var endPos = selectEndPos; | |||
var startChar = txt.charAt(startPos - 1); //選択範囲開始左側の文字を取得 | |||
var startBrcIdx = BRACKET.indexOf(startChar); | |||
var endChar = txt.charAt(selectEndPos); //選択範囲末尾右側の文字を取得 | |||
var endBrcIdx = BRACKET.indexOf(endChar); | |||
var nest = 1; | |||
var s; | |||
var e; | |||
var pairChar; | |||
if (leftCharIsStartBracket(selectStartPos)) { | |||
//◆開き括弧の場合、末尾方向へ探す | |||
pairChar = BRACKET.charAt(startBrcIdx + 1); //対応する閉じ括弧を取得 | |||
s = txt.indexOf(startChar, startPos - 1); | |||
while (nest) { | |||
e = txt.indexOf(pairChar, s + 1); | |||
s = txt.indexOf(startChar, s + 1); | |||
if (e === -1) break; | |||
if (s < e && s !== -1) { | |||
nest++; | |||
e = s; | |||
} else { | |||
nest--; | |||
s = e; | |||
} | |||
if (e !== -1 && endPos < e) { | |||
endPos = e; | |||
} | |||
} | |||
} else if (rightCharIsEndBracket(selectEndPos)) { | |||
//◆閉じ括弧の場合、先頭方向へ探す | |||
pairChar = BRACKET.charAt(endBrcIdx - 1); //対応する開き括弧を取得 | |||
e = txt.lastIndexOf(endChar, endPos); | |||
while (nest) { | |||
s = txt.lastIndexOf(pairChar, e - 1); | |||
e = txt.lastIndexOf(endChar, e - 1); | |||
if (s === -1 || startPos <= 0) break; | |||
if (s < e && s !== -1) { | |||
nest++; | |||
s = e; | |||
} else { | |||
nest--; | |||
e = s; | |||
} | |||
if (s !== -1 && startPos > s) { | |||
startPos = s + 1; | |||
} | |||
} | |||
} else { | |||
break quit; | |||
} | |||
sel.SetActivePos(startPos); | |||
sel.SetActivePos(endPos, SHIFT); | |||
} | |||
} | |||
function doMultiAction(fn) { | |||
var d = document, s = d.selection; | |||
s.Mode = meModeMulti; | |||
// ① まず、GetActivePos と GetAnchorPos で複数選択のリストを作成します | |||
var selections = [{ s: s.GetAnchorPos(), e: s.GetActivePos() }]; | |||
if (s.Count > 0) { | |||
selections = []; | |||
for (var i = 0; i < s.Count; i++) | |||
selections.push({ s: s.GetActivePos(i), e: s.GetAnchorPos(i) }); | |||
} | |||
var p = 0; | |||
var q = 0; | |||
for (var i = 0; i < selections.length; i++) { | |||
// ② そのリストを上から順に SetActivePos で、「シングルカーソル」で範囲選択します。この段階で複数選択は解除され、通常のマクロ操作が可能となります | |||
s.SetActivePos(selections[i].s + p); | |||
s.SetActivePos(selections[i].e + p, true); | |||
q = d.TextLength; | |||
// ③ <ここで通常のマクロの機能を使って普通に編集などを行います> | |||
fn(); | |||
p += d.TextLength - q; | |||
// ④ 処理を行った後の選択範囲をリストに反映し、これをリストの最後まで繰り返します | |||
selections[i] = { s: s.GetAnchorPos(), e: s.GetActivePos() }; | |||
} | |||
// ⑤ そのリストを上から順に document.selection.AddPos(StartPos, EndPos) で複数選択として復元します | |||
for (var i = 0; i < selections.length; i++) | |||
s.AddPos(selections[i].s, selections[i].e); | |||
} | } | ||
2020年3月22日 (日) 23:25時点における版
選択範囲を広げる
選択範囲を徐々に広げます。VSCode や IntelliJ っぽいやつです。
私は Sublime Text に倣い、Ctrl+Shift+Space に割り当てて使っています。
未選択状態での動作:
- カーソルの左、もしくは右に括弧記号がある場合は括弧の中全体を選択
- それ以外はカーソル位置の単語を選択
選択状態での動作:
- 選択状態によって選択範囲を広げる
- 選択範囲の開始位置に括弧の開始記号がある場合は、括弧全体に選択範囲を広げる
- 上記の条件に当てはまらず、選択範囲末尾の右側に括弧の終了記号がある場合は、括弧全体に選択範囲を広げる
- 上記の条件に当てはまらず、選択範囲末尾の右側にドットがある場合には、そのドット連なりの一番右側の単語まで選択範囲を広げる
- 上記の条件に当てはまらず、選択範囲末尾の右側に括弧の開始記号がある場合には、その括弧を全て洗濯する
- 上記の動作によって選択範囲が広がらなかった場合には、選択範囲を左右それぞれ1単語ずつ広げる
ソースコード:
#title="選択範囲を広げる"
BeginUndoGroup();
Redraw = false;
//■括弧の定義(0+2n:開き/1+2n:閉じ)
var BRACKET = '()<>[]{}「」『』【】()';
var sel = document.selection;
var txt = Document.Text;
if (sel.Mode === meModeMulti) {
// マルチカーソル動作中の場合は SelectWord しか行わない
sel.SelectWord();
} else if (sel.IsEmpty) {
var selectStartPos = selectBottomPos = sel.GetActivePos();
if (leftCharIsStartBracket(selectStartPos)
|| rightCharIsEndBracket(selectBottomPos)) {
// カーソルの左右いずれかに開き括弧があった場合
moveToBracketEnd(selectStartPos, selectBottomPos);
} else {
// 単語を選択
sel.SelectWord();
}
} else {
expandSelection();
}
function expandSelection() {
var EXTEND_ON = true;
var EXTEND_OFF = false;
// 選択範囲取得
var topX = sel.GetTopPointX(mePosLogical);
var topY = sel.GetTopPointY(mePosLogical);
var bottomX = sel.GetBottomPointX(mePosLogical);
var bottomY = sel.GetBottomPointY(mePosLogical);
// 選択終了位置のポジション取得
sel.SetActivePoint(mePosLogical, bottomX, bottomY, EXTEND_OFF);
var selectBottomPos = sel.GetActivePos();
// 選択開始位置に移動
sel.SetActivePoint(mePosLogical, topX, topY, EXTEND_OFF);
var selectTopPos = sel.GetActivePos();
var selectStartPos, selectEndPos;
if (selectTopPos <= selectBottomPos) {
selectStartPos = selectTopPos;
selectEndPos = selectBottomPos;
} else {
selectStartPos = selectBottomPos;
selectEndPos = selectTopPos;
}
if (bothSideCharIsBracket(selectStartPos, selectEndPos)) {
// 両脇が括弧だった場合
sel.CharLeft(EXTEND_OFF);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.CharRight(EXTEND_ON);
} else if (txt.charAt(selectEndPos) === '.') {
// 選択範囲末尾右側がドットだった場合
selectRightSideWordsOfDot(selectStartPos, selectEndPos);
} else if (leftCharIsStartBracket(selectEndPos + 1)) {
// 選択範囲右側が開始括弧だった場合
selectRightSideWordsOfBracket(selectStartPos, selectEndPos);
} else if (
leftCharIsStartBracket(selectStartPos) ||
rightCharIsEndBracket(selectEndPos)
) {
// 左右どちらかが括弧だった場合
moveToBracketEnd(selectStartPos, selectEndPos);
} else {
// 選択範囲を拡大
sel.WordLeft(EXTEND_OFF);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.WordRight(EXTEND_ON);
}
// 選択範囲拡大後の選択範囲取得
var expandedTopX = sel.GetTopPointX(mePosLogical);
var expandedTopY = sel.GetTopPointY(mePosLogical);
var expandedBottomX = sel.GetBottomPointX(mePosLogical);
var expandedBottomY = sel.GetBottomPointY(mePosLogical);
// 選択範囲が変わっていない場合は、左右1単語ずつ拡大する
if (
topX === expandedTopX &&
topY === expandedTopY &&
bottomX === expandedBottomX &&
bottomY === expandedBottomY
) {
sel.SetActivePos(selectStartPos);
sel.WordLeft(EXTEND_OFF);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.WordRight(EXTEND_ON);
}
}
function selectRightSideWordsOfDot(selectStartPos, selectEndPos) {
if (txt.charAt(selectEndPos) !== '.') {
return;
}
var EXTEND_ON = true;
sel.SetActivePos(selectStartPos);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.CharRight(EXTEND_ON);
sel.WordRight(EXTEND_ON);
selectRightSideWordsOfDot(selectStartPos, sel.GetActivePos());
}
function selectRightSideWordsOfBracket(selectStartPos, selectEndPos) {
if (!leftCharIsStartBracket(selectEndPos + 1)) {
return;
}
moveToBracketEnd(selectEndPos + 1, selectEndPos + 1);
var movedEndPos = sel.GetActivePos() + 1;
var EXTEND_ON = true;
sel.SetActivePos(selectStartPos);
sel.SetActivePos(movedEndPos, EXTEND_ON);
}
function leftCharIsStartBracket(selectStartPos) {
var startPos;
if (selectStartPos) {
startPos = selectStartPos;
} else {
startPos = Document.Selection.GetActivePos();
}
var startChar = txt.charAt(startPos - 1); //カーソル左側の文字を取得
var startBrcIdx = BRACKET.indexOf(startChar);
return startBrcIdx !== -1 && startChar !== '' && startBrcIdx % 2 === 0;
}
function rightCharIsEndBracket(selectEndPos) {
var endPos;
if (selectEndPos) {
endPos = selectEndPos;
} else {
endPos = Document.Selection.GetActivePos();
}
var endChar = txt.charAt(endPos); //カーソル右側の文字を取得
var endBrcIdx = BRACKET.indexOf(endChar);
return endBrcIdx !== -1 && endChar !== '' && endBrcIdx % 2 === 1;
}
function bothSideCharIsBracket(selectStartPos, selectEndPos) {
var txt = Document.Text;
var sPos = selectStartPos; //カーソル始点
var ePos = selectEndPos; //カーソル終点
var sBrc = txt.charAt(sPos - 1); //カーソル始点左側の文字を取得
var eBrc = txt.charAt(ePos); //カーソル終点右側の文字を取得
var isBrc = BRACKET.indexOf(sBrc);
var ieBrc = BRACKET.indexOf(eBrc);
return (
!(isBrc === -1 || sBrc === '') &&
!(ieBrc === -1 || eBrc === '') &&
ieBrc - isBrc === 1
);
}
function moveToBracketEnd(selectStartPos, selectEndPos) {
//■範囲選択(true:する/false:しない)
var SHIFT = true;
quit: {
var startPos = selectStartPos;
var endPos = selectEndPos;
var startChar = txt.charAt(startPos - 1); //選択範囲開始左側の文字を取得
var startBrcIdx = BRACKET.indexOf(startChar);
var endChar = txt.charAt(selectEndPos); //選択範囲末尾右側の文字を取得
var endBrcIdx = BRACKET.indexOf(endChar);
var nest = 1;
var s;
var e;
var pairChar;
// if (startBrcIdx !== -1 && startChar !== '' && startBrcIdx % 2 === 0) {
if (leftCharIsStartBracket(selectStartPos)) {
//◆開き括弧の場合、末尾方向へ探す
pairChar = BRACKET.charAt(startBrcIdx + 1); //対応する閉じ括弧を取得
s = txt.indexOf(startChar, startPos - 1);
while (nest) {
e = txt.indexOf(pairChar, s + 1);
s = txt.indexOf(startChar, s + 1);
if (e === -1) break;
if (s < e && s !== -1) {
nest++;
e = s;
} else {
nest--;
s = e;
}
if (e !== -1 && endPos < e) {
endPos = e;
}
}
// } else if (endBrcIdx !== -1 && endChar !== '' && endBrcIdx % 2 === 1) {
} else if (rightCharIsEndBracket(selectEndPos)) {
//◆閉じ括弧の場合、先頭方向へ探す
pairChar = BRACKET.charAt(endBrcIdx - 1); //対応する開き括弧を取得
e = txt.lastIndexOf(endChar, endPos);
while (nest) {
s = txt.lastIndexOf(pairChar, e - 1);
e = txt.lastIndexOf(endChar, e - 1);
if (s === -1 || startPos <= 0) break;
if (s < e && s !== -1) {
nest++;
s = e;
} else {
nest--;
e = s;
}
if (s !== -1 && startPos > s) {
startPos = s + 1;
}
}
} else {
break quit;
}
sel.SetActivePos(startPos);
sel.SetActivePos(endPos, SHIFT);
}
}
Mery Ver.3.0.1 以降に対応するマルチカーソル対応実装 (試験実装メソッドを利用):
#title="選択範囲を広げる"
BeginUndoGroup();
Redraw = false;
//■括弧の定義(0+2n:開き/1+2n:閉じ)
var BRACKET = '()<>[]{}「」『』【】()';
var sel = document.selection;
var txt = Document.Text;
if (sel.Mode === meModeMulti) {
doMultiAction(main);
} else {
main();
}
function main() {
if (sel.IsEmpty) {
var selectStartPos = selectBottomPos = sel.GetActivePos();
if (leftCharIsStartBracket(selectStartPos)
|| rightCharIsEndBracket(selectBottomPos)) {
// カーソルの左右いずれかに開き括弧があった場合
moveToBracketEnd(selectStartPos, selectBottomPos);
} else {
// 単語を選択
sel.SelectWord();
}
} else {
expandSelection();
}
}
function expandSelection() {
var EXTEND_ON = true;
var EXTEND_OFF = false;
// 選択範囲取得
var topX = sel.GetTopPointX(mePosLogical);
var topY = sel.GetTopPointY(mePosLogical);
var bottomX = sel.GetBottomPointX(mePosLogical);
var bottomY = sel.GetBottomPointY(mePosLogical);
// 選択終了位置のポジション取得
sel.SetActivePoint(mePosLogical, bottomX, bottomY, EXTEND_OFF);
var selectBottomPos = sel.GetActivePos();
// 選択開始位置に移動
sel.SetActivePoint(mePosLogical, topX, topY, EXTEND_OFF);
var selectTopPos = sel.GetActivePos();
var selectStartPos, selectEndPos;
if (selectTopPos <= selectBottomPos) {
selectStartPos = selectTopPos;
selectEndPos = selectBottomPos;
} else {
selectStartPos = selectBottomPos;
selectEndPos = selectTopPos;
}
if (bothSideCharIsBracket(selectStartPos, selectEndPos)) {
// 両脇が括弧だった場合
sel.CharLeft(EXTEND_OFF);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.CharRight(EXTEND_ON);
} else if (txt.charAt(selectEndPos) === '.') {
// 選択範囲末尾右側がドットだった場合
selectRightSideWordsOfDot(selectStartPos, selectEndPos);
} else if (leftCharIsStartBracket(selectEndPos + 1)) {
// 選択範囲右側が開始括弧だった場合
selectRightSideWordsOfBracket(selectStartPos, selectEndPos);
} else if (
leftCharIsStartBracket(selectStartPos) ||
rightCharIsEndBracket(selectEndPos)
) {
// 左右どちらかが括弧だった場合
moveToBracketEnd(selectStartPos, selectEndPos);
} else {
// 選択範囲を拡大
sel.WordLeft(EXTEND_OFF);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.WordRight(EXTEND_ON);
}
// 選択範囲拡大後の選択範囲取得
var expandedTopX = sel.GetTopPointX(mePosLogical);
var expandedTopY = sel.GetTopPointY(mePosLogical);
var expandedBottomX = sel.GetBottomPointX(mePosLogical);
var expandedBottomY = sel.GetBottomPointY(mePosLogical);
// 選択範囲が変わっていない場合は、左右1単語ずつ拡大する
if (
topX === expandedTopX &&
topY === expandedTopY &&
bottomX === expandedBottomX &&
bottomY === expandedBottomY
) {
sel.SetActivePos(selectStartPos);
sel.WordLeft(EXTEND_OFF);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.WordRight(EXTEND_ON);
}
}
function selectRightSideWordsOfDot(selectStartPos, selectEndPos) {
if (txt.charAt(selectEndPos) !== '.') {
return;
}
var EXTEND_ON = true;
sel.SetActivePos(selectStartPos);
sel.SetActivePos(selectEndPos, EXTEND_ON);
sel.CharRight(EXTEND_ON);
sel.WordRight(EXTEND_ON);
selectRightSideWordsOfDot(selectStartPos, sel.GetActivePos());
}
function selectRightSideWordsOfBracket(selectStartPos, selectEndPos) {
if (!leftCharIsStartBracket(selectEndPos + 1)) {
return;
}
moveToBracketEnd(selectEndPos + 1, selectEndPos + 1);
var movedEndPos = sel.GetActivePos() + 1;
var EXTEND_ON = true;
sel.SetActivePos(selectStartPos);
sel.SetActivePos(movedEndPos, EXTEND_ON);
}
function leftCharIsStartBracket(selectStartPos) {
var startPos;
if (selectStartPos) {
startPos = selectStartPos;
} else {
startPos = Document.Selection.GetActivePos();
}
var startChar = txt.charAt(startPos - 1); //カーソル左側の文字を取得
var startBrcIdx = BRACKET.indexOf(startChar);
return startBrcIdx !== -1 && startChar !== '' && startBrcIdx % 2 === 0;
}
function rightCharIsEndBracket(selectEndPos) {
var endPos;
if (selectEndPos) {
endPos = selectEndPos;
} else {
endPos = Document.Selection.GetActivePos();
}
var endChar = txt.charAt(endPos); //カーソル右側の文字を取得
var endBrcIdx = BRACKET.indexOf(endChar);
return endBrcIdx !== -1 && endChar !== '' && endBrcIdx % 2 === 1;
}
function bothSideCharIsBracket(selectStartPos, selectEndPos) {
var txt = Document.Text;
var sPos = selectStartPos; //カーソル始点
var ePos = selectEndPos; //カーソル終点
var sBrc = txt.charAt(sPos - 1); //カーソル始点左側の文字を取得
var eBrc = txt.charAt(ePos); //カーソル終点右側の文字を取得
var isBrc = BRACKET.indexOf(sBrc);
var ieBrc = BRACKET.indexOf(eBrc);
return (
!(isBrc === -1 || sBrc === '') &&
!(ieBrc === -1 || eBrc === '') &&
ieBrc - isBrc === 1
);
}
function moveToBracketEnd(selectStartPos, selectEndPos) {
//■範囲選択(true:する/false:しない)
var SHIFT = true;
quit: {
var startPos = selectStartPos;
var endPos = selectEndPos;
var startChar = txt.charAt(startPos - 1); //選択範囲開始左側の文字を取得
var startBrcIdx = BRACKET.indexOf(startChar);
var endChar = txt.charAt(selectEndPos); //選択範囲末尾右側の文字を取得
var endBrcIdx = BRACKET.indexOf(endChar);
var nest = 1;
var s;
var e;
var pairChar;
if (leftCharIsStartBracket(selectStartPos)) {
//◆開き括弧の場合、末尾方向へ探す
pairChar = BRACKET.charAt(startBrcIdx + 1); //対応する閉じ括弧を取得
s = txt.indexOf(startChar, startPos - 1);
while (nest) {
e = txt.indexOf(pairChar, s + 1);
s = txt.indexOf(startChar, s + 1);
if (e === -1) break;
if (s < e && s !== -1) {
nest++;
e = s;
} else {
nest--;
s = e;
}
if (e !== -1 && endPos < e) {
endPos = e;
}
}
} else if (rightCharIsEndBracket(selectEndPos)) {
//◆閉じ括弧の場合、先頭方向へ探す
pairChar = BRACKET.charAt(endBrcIdx - 1); //対応する開き括弧を取得
e = txt.lastIndexOf(endChar, endPos);
while (nest) {
s = txt.lastIndexOf(pairChar, e - 1);
e = txt.lastIndexOf(endChar, e - 1);
if (s === -1 || startPos <= 0) break;
if (s < e && s !== -1) {
nest++;
s = e;
} else {
nest--;
e = s;
}
if (s !== -1 && startPos > s) {
startPos = s + 1;
}
}
} else {
break quit;
}
sel.SetActivePos(startPos);
sel.SetActivePos(endPos, SHIFT);
}
}
function doMultiAction(fn) {
var d = document, s = d.selection;
s.Mode = meModeMulti;
// ① まず、GetActivePos と GetAnchorPos で複数選択のリストを作成します
var selections = [{ s: s.GetAnchorPos(), e: s.GetActivePos() }];
if (s.Count > 0) {
selections = [];
for (var i = 0; i < s.Count; i++)
selections.push({ s: s.GetActivePos(i), e: s.GetAnchorPos(i) });
}
var p = 0;
var q = 0;
for (var i = 0; i < selections.length; i++) {
// ② そのリストを上から順に SetActivePos で、「シングルカーソル」で範囲選択します。この段階で複数選択は解除され、通常のマクロ操作が可能となります
s.SetActivePos(selections[i].s + p);
s.SetActivePos(selections[i].e + p, true);
q = d.TextLength;
// ③ <ここで通常のマクロの機能を使って普通に編集などを行います>
fn();
p += d.TextLength - q;
// ④ 処理を行った後の選択範囲をリストに反映し、これをリストの最後まで繰り返します
selections[i] = { s: s.GetAnchorPos(), e: s.GetActivePos() };
}
// ⑤ そのリストを上から順に document.selection.AddPos(StartPos, EndPos) で複数選択として復元します
for (var i = 0; i < selections.length; i++)
s.AddPos(selections[i].s, selections[i].e);
}
更新履歴
2020/03/15 マルチカーソル時の動作を考慮し処理を追加
スポンサーリンク