行を上下に移動(Mery 2.7 用)

行を上下に移動(Mery 2.7 用) 編集

2019/05/07 sukemaru

Mery 2.6.9 で「変更行の強調表示」が実装されて以来、複数行の選択範囲で「選択範囲を上下に移動」マクロを実行すると行番号が太字だらけになってしまっていましたが、Mery 2.7.0スクロールバーマーカーが実装されたことにより「変更行」がますます目立つようになりました。

このマクロでは、Mery 2.7.0 から実装された BeginUndoGroup/EndUndoGroup メソッド を活用し、あえて「マクロの記録」で生成したようなコードにして「変更行の強調表示」を最小限にしてあります。

Mery 2.7.4 以上のバージョンであれば「ブックマーク」を維持できるようにしてありますが、それ以前のバージョンの Mery でこのマクロを実行した場合は「変更行の強調だらけ」「ブックマーク設定が消える」仕様で動作します。

選択範囲が複数行のときを考慮した動作仕様になっています。

  • 「選択範囲を含む論理行全体」が上下に移動します。
  • 選択範囲がないときは、カーソルのある行を移動します。
  • 行の途中から始まる選択範囲や、行の途中で終わる選択範囲は「論理行全体」にまで拡張します。
  • 行番号のクリック&ドラッグで複数行を範囲選択した場合、カーソル位置がひとつ下の行の先頭になりますが、選択範囲を自動的に調整して「さいごの改行」は無視します。

ダウンロード 編集

ファイル:行を上下に移動(Mery 2.7 用).zip」(アイコン入り)

ソースコード 編集

行を上に移動 編集

#title = "行を上に移動"
#tooltip = "行を上に移動 (複数行可)"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",223

var d = editor.ActiveDocument;
var s = editor.ActiveDocument.selection;
// 移動元の選択範囲
var ty = s.GetTopPointY(mePosLogical);
var by = s.GetBottomPointY(mePosLogical);
var bx = s.GetBottomPointX(mePosLogical);

// 「行を上に移動」の中断処理
if (d.ReadOnly) {
	Status = " ドキュメントは書き換え禁止です。";
} else if (ty == 1) { // 上にいけない 
	Status = " ファイルの先頭です";
} else {
	Redraw = false;
	// 選択範囲の末尾が終端の空行 ( ^[EOF] ) にあるときの調整
	// カーソル位置に文字がないばあいを [EOF] と判定する
	var eof = (bx == 1 && !d.Text.charAt(s.GetActivePos())) ? "\n" : "";
	// 選択範囲の末尾が行頭にあるときの調整
	if (ty != by && bx == 1) {
		by--;
	}

	/* 移動範囲のブックマーク設定を維持する(Mery 2.7.4 以上) */
	if (VersionCheck("2.7.4")) {
		BeginUndoGroup();
		var sy = ScrollY;
		// 選択範囲を確定する
		s.SetAnchorPoint(mePosLogical, 1, ty);
		s.SetActivePoint(mePosLogical, 1, by, true);
		s.EndOfLine(true, mePosLogical);
		if (eof) {
			s.SetActivePos(s.GetActivePos() + 1, true);
		}
		var tp = s.GetAnchorPos();
		var bp = s.GetActivePos();
		// 「移動先の行」
		var pLine = d.GetLine(ty - 1, 0);
		// 移動元の先頭行と「移動先の行」のブックマークを確認
		var nBookmark, pBookmark;
		s.SetActivePos(tp - 1);
		if (s.NextBookmark() && s.GetActivePointY(mePosLogical) == ty) {
			nBookmark = true;
		}
		s.SetActivePos(tp);
		if (s.PreviousBookmark() && s.GetActivePointY(mePosLogical) == ty - 1) {
			pBookmark = true;
		}
		// 選択範囲の末尾に「移動先の行」の文字列を追加
		s.SetActivePos(bp);
		s.Text = "\n" + pLine;
		if (pBookmark) {
			editor.ExecuteCommandByID(MEID_EDIT_TOGGLE_BOOKMARK = 2126);
		}
		// 「移動先の行」(上)を削除
		s.SetActivePos(tp - 1);
		s.SelectLine();
		s.Delete();
		// ブックマークを復旧
		if (nBookmark != pBookmark) {
			editor.ExecuteCommandByID(MEID_EDIT_TOGGLE_BOOKMARK = 2126);
		}
		// 範囲選択(カーソルは移動後の先頭)
		s.SetAnchorPoint(mePosLogical, 1, by + eof.length);
		ScrollY = sy;
	}

	/* 移動範囲のブックマーク設定を維持しない */
	else {
		// 選択範囲を拡張する
		s.SetAnchorPoint(mePosLogical, 1, ty - 1);
		s.SetActivePoint(mePosLogical, 1, by, true);
		s.EndOfLine(true, mePosLogical);
		if (eof) {
			s.SetActivePos(s.GetActivePos() + 1, true);
		}
		// 選択行を上へ移動
		var a = s.Text.split("\n");
		a.push(a.shift());
		s.Text = a.join("\n");
		// 移動元のテキストを範囲選択(末尾改行 \n を含める)
		// カーソルは移動後の先頭
		s.StartOfLine(false, mePosLogical);
		s.SetAnchorPos(s.GetActivePos());
		s.SetActivePoint(mePosLogical, 1, ty - 1, true);
	}
	Redraw = true;
}

function VersionCheck(versionStr) {
	var Pad2 = function(str) {
		return str.toString().replace(/[0-9]+/g, function(tmp) {
			return tmp.length < 2 ? "0" + tmp : tmp;
		});
	};
	var editorVer = Number(Pad2(editor.Version).replace(/\./g, "").slice(0, 6));
	var requirement = Number(Pad2(versionStr).replace(/\./g, "").slice(0, 6));
	return (editorVer >= requirement);
}

行を下に移動 編集

#title = "行を下に移動"
#tooltip = "行を下に移動 (複数行可)"
// #icon = "Mery用 マテリアルデザインっぽいアイコン.icl",222

var d = editor.ActiveDocument;
var s = editor.ActiveDocument.selection;
// 移動元の選択範囲
var ty = s.GetTopPointY(mePosLogical);
var by = s.GetBottomPointY(mePosLogical);
var bx = s.GetBottomPointX(mePosLogical);
// 選択範囲の末尾が終端の空行 ( ^[EOF] ) にあるときの調整
// カーソル位置に文字がないばあいを [EOF] と判定する
var eof = (bx == 1 && !d.Text.charAt(s.GetActivePos())) ? true : false;
// 選択範囲の末尾が行頭にあるときの調整
if (ty != by && bx == 1 && !eof) {
	by--;
}

// 「行を下に移動」の中断処理
if (d.ReadOnly) {
	Status = " ドキュメントは書き換え禁止です。";
} else if (by == d.GetLines(0)) { // 下にいけない
	Status = " ファイルの末尾です";
} else {
	Redraw = false;

	/* 移動先のブックマーク設定を維持する(Mery 2.7.4) */
	if (VersionCheck("2.7.4")) {
		BeginUndoGroup();
		var sy = ScrollY;
		// 選択範囲を確定する
		s.SetAnchorPoint(mePosLogical, 1, ty);
		s.SetActivePoint(mePosLogical, 1, by, true);
		s.EndOfLine(true, mePosLogical);
		var len = s.Text.length;
		var tp = s.GetAnchorPos();
		var bp = s.GetActivePos();
		// 「移動先の行」
		var nLine = d.GetLine(by + 1, 0);
		// 移動元の先頭行と「移動先の行」のブックマークを確認
		var nBookmark, pBookmark;
		s.SetActivePoint(mePosLogical, 1, ty + 1);
		if (s.PreviousBookmark() && s.GetActivePointY(mePosLogical) == ty) {
			pBookmark = true;
		}
		s.SetActivePos(bp);
		if (s.NextBookmark() && s.GetActivePointY(mePosLogical) == by + 1) {
			nBookmark = true;
		}
		// 「移動先の行」(下)を削除
		s.SetAnchorPos(bp);
		s.SetActivePos(bp + 1, true);
		s.EndOfLine(true, mePosLogical);
		s.Delete();
		// 選択範囲の先頭に「移動先の行」の文字列を追加
		s.SetActivePos(tp);
		// ブックマークを復旧
		if (nBookmark != pBookmark) {
			editor.ExecuteCommandByID(MEID_EDIT_TOGGLE_BOOKMARK = 2126);
		}
		s.Text = nLine + "\n";
		if (pBookmark) {
			editor.ExecuteCommandByID(MEID_EDIT_TOGGLE_BOOKMARK = 2126);
		}
		// 範囲選択(カーソルは移動後の先頭)
		s.SetAnchorPos(s.GetActivePos() + len + 1);
		ScrollY = sy;
	}

	/* 移動範囲のブックマーク設定を維持しない */
	else {
		// 選択範囲を拡張する
		s.SetAnchorPoint(mePosLogical, 1, ty);
		s.SetActivePoint(mePosLogical, 1, by + 1, true);
		s.EndOfLine(true, mePosLogical);
		// 選択行を下へ移動
		var a = s.Text.split("\n");
		a.unshift(a.pop());
		s.Text = a.join("\n");
		// 移動元のテキストを範囲選択(末尾改行 \n を含める)
		// カーソルは移動後の先頭
		s.SetAnchorPos(s.GetActivePos() + 1);
		s.SetActivePoint(mePosLogical, 1, ty + 1, true);
	}
	Redraw = true;
}

function VersionCheck(versionStr) {
	var Pad2 = function(str) {
		return str.toString().replace(/[0-9]+/g, function(tmp) {
			return tmp.length < 2 ? "0" + tmp : tmp;
		});
	};
	var editorVer = Number(Pad2(editor.Version).replace(/\./g, "").slice(0, 6));
	var requirement = Number(Pad2(versionStr).replace(/\./g, "").slice(0, 6));
	return (editorVer >= requirement);
}
スポンサーリンク