「
選択範囲を広げる
」を編集中
ナビゲーションに移動
検索に移動
警告:
ログインしていません。編集を行うと、あなたの IP アドレスが公開されます。
ログイン
または
アカウントを作成
すれば、あなたの編集はその利用者名とともに表示されるほか、その他の利点もあります。
スパム攻撃防止用のチェックです。 けっして、ここには、値の入力は
しない
でください!
== 選択範囲を徐々に広げる == 選択範囲を徐々に広げます。VSCode や IntelliJ っぽいやつです。 私は Sublime Text に倣い、Ctrl+Shift+Space に割り当てて使っています。 === 未選択状態での動作 === * 選択範囲が空の場合、カーソル位置の単語を選択します。 * カーソル位置が括弧だった場合は、括弧の中身も選択します。 * ドットを検出した場合は、ドットの1つ右の単語も選択します。 * ハイフンを検出した場合は、ハイフンで区切られた1つ右の単語も選択します。 === 選択状態での動作 === * 選択範囲がある場合、選択範囲の前後にある括弧を検出し、その中身を選択します。 * ドットを検出した場合は、ドットの1つ左または右の単語まで拡張します。 * ハイフンを検出した場合は、ハイフンで区切られた1つ右の単語まで拡張します。 * これらの記号を検出しなかった場合は、単純な選択範囲の拡張を行います。 === ソースコード === <syntaxhighlight lang="javascript"> #title = "選択範囲を広げる" /** * 選択範囲を広げるためのマクロです。 * * 選択範囲が空の場合、カーソル位置の単語を選択します。 * カーソル位置が括弧だった場合は、括弧の中身も選択します。 * ドットを検出した場合は、ドットの1つ右の単語も選択します。 * ハイフンを検出した場合は、ハイフンで区切られた1つ右の単語も選択します。 * * 選択範囲がある場合、選択範囲の前後にある括弧を検出し、その中身を選択します。 * ドットを検出した場合は、ドットの1つ左または右の単語まで拡張します。 * ハイフンを検出した場合は、ハイフンで区切られた1つ右の単語まで拡張します。 * これらの記号を検出しなかった場合は、単純な選択範囲の拡張を行います。 */ BeginUndoGroup(); Redraw = false; //■括弧の定義(0+2n:開き/1+2n:閉じ) var BRACKET = '()<>[]{}「」『』【】()[]{}〈〉《》〔〕〘〙〚〛〖〗‘’“”'; var doc = document; var sel = document.selection; var txt = document.Text; function main() { if (sel.IsEmpty) { // 未選択の場合 var beforePos = sel.GetActivePos(); sel.SelectWord(); var selChar = sel.Text; var selCharIndex = BRACKET.indexOf(selChar); if (selChar.length === 1 && selCharIndex !== -1) { // 選択文字が括弧記号1文字の場合、括弧の中身を選択 if (selCharIndex % 2 === 1) { // 閉じ括弧の場合 sel.CharLeft(); var topX = sel.GetTopPointX(mePosLogical); var topY = sel.GetTopPointY(mePosLogical); var bottomX = sel.GetBottomPointX(mePosLogical); var bottomY = sel.GetBottomPointY(mePosLogical); selectToBracketStart(topX, topY, bottomX, bottomY, selChar); } else if (selCharIndex % 2 === 0) { // 開き括弧の場合 var topX = sel.GetTopPointX(mePosLogical); var topY = sel.GetTopPointY(mePosLogical); var bottomX = sel.GetBottomPointX(mePosLogical); var bottomY = sel.GetBottomPointY(mePosLogical); var activePos = sel.GetActivePos(); selectToBracketEnd(topX, topY, bottomX, bottomY, selChar); if (beforePos === activePos) { // 行末で先頭方向に向かって選択していた場合は、先頭の開き括弧の選択を外す sel.SetAnchorPos(beforePos); } else if (activePos !== sel.GetActivePos()) { // 括弧の中身が選択された場合、閉じ括弧も選択する sel.SetActivePos(sel.GetActivePos() + 1, true); } } } else if (selChar === ".") { // ドットの場合 // ドットの1つ右の単語まで拡張 selectFuncNameToChild(sel.GetActivePos() - 1); } else if (selChar === "-") { // ドットの場合 // ドットの1つ右の単語まで拡張 selectHyphenSeparatedWord(sel.GetActivePos() - 1); } } else { // 選択済みの場合 // 現在の選択範囲を取得 var topX = sel.GetTopPointX(mePosLogical); var topY = sel.GetTopPointY(mePosLogical); var bottomX = sel.GetBottomPointX(mePosLogical); var bottomY = sel.GetBottomPointY(mePosLogical); // 選択範囲の左右の文字を取得 var leftChar = "dummy"; if (topX - 2 >= 0) leftChar = doc.GetLine(topY, meGetLineWithNewLines).charAt(topX - 2); var rightChar = doc.GetLine(bottomY, meGetLineWithNewLines).charAt(bottomX - 1); var rightIndex = BRACKET.indexOf(rightChar); var leftIndex = BRACKET.indexOf(leftChar); if (rightChar === ".") { // 選択範囲の右にドットがある場合 // 末尾方向にドットを検索 sel.SetActivePoint(mePosLogical, bottomX, bottomY, false); selectFuncNameToChild(sel.GetActivePos()); sel.SetAnchorPoint(mePosLogical, topX, topY); } else if (rightChar === "-") { // 選択範囲の右にハイフンがある場合 sel.SetActivePoint(mePosLogical, bottomX, bottomY, false); selectHyphenSeparatedWord(sel.GetActivePos()); sel.SetAnchorPoint(mePosLogical, topX, topY); } else if (rightIndex % 2 === 0) { // 右位置に開き括弧があるかをチェック // 選択範囲を広げる selectToBracketEnd(topX, topY, bottomX + 1, bottomY, rightChar); // 閉じ括弧も選択する sel.CharRight(true); } else if (leftChar === ".") { // 選択範囲の左にドットがある場合 // 先頭方向にドットを検索 sel.SetActivePoint(mePosLogical, topX, topY, false); selectFuncNameToParent(sel.GetActivePos() - 2); sel.SetAnchorPoint(mePosLogical, bottomX, bottomY); } else if (rightIndex % 2 === 1) { // 右位置に閉じ括弧があるかをチェック // 選択範囲を広げる selectToBracketStart(topX, topY, bottomX, bottomY, rightChar); } else if (leftIndex % 2 === 0) { // 左位置に括弧があるかをチェック // 選択範囲を広げる selectToBracketEnd(topX, topY, bottomX, bottomY, leftChar); } else { // いずれでもない場合は、選択開始位置と終了位置の両方で単語選択を行う simpleExpand(topX, topY, bottomX, bottomY, 0); } var afterTopX = sel.GetTopPointX(mePosLogical); var afterTopY = sel.GetTopPointY(mePosLogical); var afterBottomX = sel.GetBottomPointX(mePosLogical); var afterBottomY = sel.GetBottomPointY(mePosLogical); // 選択範囲を広げる処理の後も同じ位置の場合、通常の選択範囲を広げる処理を行う if (topX === afterTopX && topY === afterTopY && bottomX === afterBottomX && bottomY === afterBottomY) { simpleExpand(afterTopX, afterTopY, afterBottomX, afterBottomY, 1); } } } function selectFuncNameToChild(pos) { // "$" はEOFへの対応 var movePos = txt.slice(pos + 1).search(/[^a-z0-9_-]|$/i) + pos + 1; sel.SetActivePos(movePos, true); } function selectFuncNameToParent(pos) { var toSeparator1 = txt.lastIndexOf(".", pos); var toSeparator2 = txt.lastIndexOf("\n", pos); var toSeparator3 = txt.lastIndexOf(" ", pos); var toSeparator4 = txt.lastIndexOf("\t", pos); var toSeparator5 = txt.lastIndexOf(" ", pos); var maxIndex = Math.max(toSeparator1, toSeparator2, toSeparator3, toSeparator4, toSeparator5); sel.SetActivePos(maxIndex + 1, true); } function selectHyphenSeparatedWord(pos) { // "$" はEOFへの対応 var movePos = txt.slice(pos + 1).search(/[^a-z0-9_]|$/i) + pos + 1; sel.SetActivePos(movePos, true); } // 単純な選択範囲の拡大 function simpleExpand(topX, topY, bottomX, bottomY, offset) { // 拡大範囲は行を跨がないようにする // 左側の拡大後の位置を取得 var simpleExpandTopX = sel.GetTopPointX(mePosLogical); var simpleExpandTopY = sel.GetTopPointY(mePosLogical); sel.SetActivePoint(mePosLogical, topX, topY, false); var leftChar = txt.charAt(sel.GetActivePos() - 1); if (leftChar !== "\n" && leftChar !== "") { // 行頭以外のときだけ、左側を拡大 sel.CharLeft(false, 1 + offset); sel.SelectWord(); simpleExpandTopX = sel.GetTopPointX(mePosLogical); simpleExpandTopY = sel.GetTopPointY(mePosLogical); } // 右側の拡大後の位置を取得 sel.SetActivePoint(mePosLogical, bottomX, bottomY, false); var simpleExpandBottomX = sel.GetBottomPointX(mePosLogical); var simpleExpandBottomY = sel.GetBottomPointY(mePosLogical); var rightChar = txt.charAt(sel.GetActivePos()); if (rightChar !== "\n" && rightChar !== "") { // 行末以外のときだけ、右側を拡大 if (offset > 0) { sel.CharRight(false, offset); } sel.SelectWord(); simpleExpandBottomX = sel.GetBottomPointX(mePosLogical); simpleExpandBottomY = sel.GetBottomPointY(mePosLogical); } // 選択範囲を広げる sel.SetActivePoint(mePosLogical, simpleExpandTopX, simpleExpandTopY, false); sel.SetActivePoint(mePosLogical, simpleExpandBottomX, simpleExpandBottomY, true); } // 先頭方向の開き括弧まで選択範囲を広げる function selectToBracketStart(topX, topY, bottomX, bottomY, endChar) { var endBracketIndex = BRACKET.indexOf(endChar); sel.SetActivePoint(mePosLogical, topX, topY, false); var startPos = sel.GetActivePos(); sel.SetActivePoint(mePosLogical, bottomX, bottomY, false); var endPos = sel.GetActivePos(); var nest = 1; var s; var e; var pairChar; pairChar = BRACKET.charAt(endBracketIndex - 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; } } sel.SetActivePos(startPos); sel.SetActivePos(endPos, true); } // 末尾方向の閉じ括弧まで選択範囲を広げる function selectToBracketEnd(topX, topY, bottomX, bottomY, startChar) { var startBracketIndex = BRACKET.indexOf(startChar); sel.SetActivePoint(mePosLogical, topX, topY, false); var startPos = sel.GetActivePos(); sel.SetActivePoint(mePosLogical, bottomX, bottomY, false); var endPos = sel.GetActivePos(); var nest = 1; var s; var e; var pairChar; pairChar = BRACKET.charAt(startBracketIndex + 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; } } sel.SetActivePos(startPos); sel.SetActivePos(endPos, true); } 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); } if (sel.Mode === meModeMulti) { doMultiAction(main); } else { main(); } </syntaxhighlight> == 更新履歴 == * 2023/07/21 ** 処理を見直し、より適切な範囲に拡張するよう調整しました。 * 2020/03/22 ** Mery Ver.3.0.1 マルチカーソル対応化の試験実装メソッドを使った実装を追加しました。 * 2020/03/15 ** マルチカーソル時の動作を考慮し処理を追加しました。
編集内容の要約:
MeryWikiへの投稿はすべて、他の投稿者によって編集、変更、除去される場合があります。 自分が書いたものが他の人に容赦なく編集されるのを望まない場合は、ここに投稿しないでください。
また、投稿するのは、自分で書いたものか、パブリック ドメインまたはそれに類するフリーな資料からの複製であることを約束してください(詳細は
MeryWiki:著作権
を参照)。
著作権保護されている作品は、許諾なしに投稿しないでください!
このページを編集するには、下記の数式を計算してその答えを欄に入力してください (
ヘルプ
):
いちたすには =
編集を中止
編集の仕方
(新しいウィンドウで開きます)
スポンサーリンク
案内メニュー
個人用ツール
ログインしていません
トーク
投稿記録
アカウント作成
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
編集
履歴表示
その他
検索
スポンサーリンク
スポンサーリンク
案内
メインページ
ヘルプ
よくある質問
マクロリファレンス
マクロライブラリ
プラグインライブラリ
構文ファイル
テーマ
寄付・開発支援
練習用ページ
開発室
開発者のブログ
ツール
スポンサーリンク