Skip to content

Instantly share code, notes, and snippets.

@AWtnb
Last active March 18, 2021 10:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AWtnb/b5632d2d9618d9e170e8b60393664c14 to your computer and use it in GitHub Desktop.
Save AWtnb/b5632d2d9618d9e170e8b60393664c14 to your computer and use it in GitHub Desktop.
テキストエディタ Mery 用の自作マクロ集。

Mery-editor Macros

テキストエディタ Mery 用の自作マクロ集。

随時更新予定。

// ------------------------------------------------------------
// インデント直後では逆インデント、それ以外は直前の1字を削除
// ------------------------------------------------------------
function selectLine() {
document.selection.EndOfLine(false, mePosLogical);
document.selection.StartOfLine(true, mePosLogical);
}
function getIndentDepth(s) {
const indentChar = new RegExp("^[ \t]+");
const m = indentChar.exec(s);
if (m) {
return m[0].length;
}
return 0;
}
function outdent() {
const slct = document.selection;
if (!slct.IsEmpty || slct.Mode != meModeStream) {
slct.DeleteLeft(1);
return;
}
const cursorX = slct.GetActivePointX(mePosLogical);
const cursorY = slct.GetActivePointY(mePosLogical);
const line = document.GetLine(cursorY, 1);
const depth = getIndentDepth(line);
if (!depth || depth != cursorX - 1) {
slct.DeleteLeft(1);
return;
}
selectLine();
slct.UnIndent();
const outdented = document.GetLine(cursorY, 1);
const postDepth = getIndentDepth(outdented);
const postX = (postDepth)? 1+postDepth : 1;
document.selection.SetActivePoint(mePosLogical, postX, cursorY);
}
function main() {
Redraw = false;
outdent();
Redraw = true;
}
main();
// ------------------------------------------------------------
// 次の段落までジャンプ
// ------------------------------------------------------------
const wholeLines = document.text.split(/\r?\n/);
const max = wholeLines.length;
const blank = new RegExp("^ *$");
function isBlankLine(logicalY) {
const logicalLine = wholeLines[logicalY-1];
return blank.test(logicalLine);
}
function cursorDown(n) {
const y = document.selection.GetActivePointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, 1, y+n, false);
}
function toParagraphEnd() {
const y = document.selection.GetActivePointY(mePosLogical);
let down = max - y;
for (let i = 1; i <= max-y; i++) {
if (isBlankLine(y+i)) {
down = i - 1;
break;
}
}
cursorDown(down);
document.selection.EndOfLine(false, mePosLogical);
}
function skipBlankAreaDown() {
const y = document.selection.GetActivePointY(mePosLogical);
let down = max - y;
for (let i = 1; i <= max-y; i++) {
if (!isBlankLine(y+i)) {
down = i;
break;
}
}
cursorDown(down);
}
function main() {
if (document.selection.Mode != meModeStream) {
return;
}
const x = document.selection.GetActivePointX(mePosLogical);
const y = document.selection.GetActivePointY(mePosLogical);
const line = wholeLines[y-1];
if (y == max) {
document.selection.EndOfLine(false, mePosLogical)
return;
}
if (isBlankLine(y)) {
skipBlankAreaDown();
return;
}
if (isBlankLine(y+1) && x == line.length+1) {
skipBlankAreaDown();
return;
}
toParagraphEnd();
}
main();
// ------------------------------------------------------------
// 前の段落までジャンプ
// ------------------------------------------------------------
const wholeLines = document.text.split(/\r?\n/);
const blank = new RegExp("^ *$");
function isBlankLine(logicalY) {
const logicalLine = wholeLines[logicalY-1];
return blank.test(logicalLine);
}
function cursorUp(n) {
const y = document.selection.GetActivePointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, 1, y-n, false);
}
function toParagraphBeginning() {
const y = document.selection.GetActivePointY(mePosLogical);
let up = y - 1;
for (let i = 1; i < y; i++) {
if (isBlankLine(y-i)) {
up = i - 1;
break;
}
}
cursorUp(up);
}
function skipBlankAreaUp() {
const y = document.selection.GetActivePointY(mePosLogical);
let up = y - 1;
for (let i = 1; i < y; i++) {
if (!isBlankLine(y-i)) {
up = i;
break;
}
}
cursorUp(up);
document.selection.EndOfLine(false, mePosLogical);
}
function main() {
if (document.selection.Mode != meModeStream) {
return
}
const x = document.selection.GetActivePointX(mePosLogical);
const y = document.selection.GetActivePointY(mePosLogical);
if (y == 1) {
document.selection.StartOfLine(false, mePosLogical);
return;
}
if (isBlankLine(y)) {
skipBlankAreaUp();
return;
}
if (isBlankLine(y-1) && x == 1) {
skipBlankAreaUp();
return;
}
toParagraphBeginning();
}
main();
// ------------------------------------------------------------
// 直後の句読点の後ろに移動する
// ------------------------------------------------------------
const wholeLines = document.text.split(/\r?\n/);
const max = wholeLines.length;
const zen = "[、,。;:「」『』【】()〔〕《》〈〉[]・!?←↓↑→○●▲△▼▽◆◇■□★☆~/…― ]";
const han = "[\\[\\]\\(\\)\\.,=<>:;`'\" #]";
const punc = new RegExp(zen+"|"+han);
function getLogicalLine(y) {
return wholeLines[y-1];
}
function hasPunctuation(logicalY) {
const logicalLine = wholeLines[logicalY-1];
return punc.test(logicalLine);
}
function jumpToLine(startY) {
let down = 0;
for (let i = 1; i <= max-startY; i++) {
if (hasPunctuation(startY+i)) {
down = i;
break;
}
}
document.selection.SetActivePoint(mePosLogical, 1, startY+down, false);
}
function setCursorPos(xLogical, yLogical, expandSelection) {
document.selection.SetActivePoint(mePosLogical, xLogical, yLogical, expandSelection);
}
function moveCursor() {
let cursorX = document.selection.GetActivePointX(mePosLogical);
let cursorY = document.selection.GetActivePointY(mePosLogical);
if (cursorX == getLogicalLine(cursorY).length + 1) {
if (cursorY == max) {
return;
}
jumpToLine(cursorY);
cursorX = 1;
cursorY = document.selection.GetActivePointY(mePosLogical);
}
document.selection.EndOfLine(true, mePosLogical);
const strToEndOfLine = document.selection.Text;
const reg = new RegExp("(^.*?(" + zen + "|" + han + ")+)(.*$)");
const m = reg.exec(strToEndOfLine);
if (!m) {
document.selection.EndOfLine(false, mePosLogical);
return;
}
const firstMatch = String(m[1]);
setCursorPos(cursorX+firstMatch.length, cursorY, false);
}
function main() {
if (!document.selection.IsEmpty || document.selection.Mode != meModeStream) {
return
}
Redraw = false;
moveCursor();
Redraw = true;
}
main();
// ------------------------------------------------------------
// 直前の句読点の前に移動する
// ------------------------------------------------------------
const wholeLines = document.text.split(/\r?\n/);
const max = wholeLines.length;
const zen = "[、,。;:「」『』【】()〔〕《》〈〉[]・!?←↓↑→○●▲△▼▽◆◇■□★☆~/…― ]";
const han = "[\\[\\]\\(\\)\\.,=<>:;`'\" #]";
const punc = new RegExp(zen+"|"+han);
function getLogicalLine(y) {
return wholeLines[y-1];
}
function hasPunctuation(logicalY) {
const logicalLine = wholeLines[logicalY-1];
return punc.test(logicalLine);
}
function jumpToLine(startY) {
let up = 0;
for (let i = 1; i < startY; i++) {
if (hasPunctuation(startY-i)) {
up = i;
break;
}
}
const x = getLogicalLine(startY-up).length + 1;
document.selection.SetActivePoint(mePosLogical, x, startY-up, false);
}
function setCursorPos(xLogical, yLogical, expandSelection) {
document.selection.SetActivePoint(mePosLogical, xLogical, yLogical, expandSelection);
}
function moveCursor() {
let cursorX = document.selection.GetActivePointX(mePosLogical);
let cursorY = document.selection.GetActivePointY(mePosLogical);
if (cursorX == 1) {
if (cursorY == 1) {
return;
}
jumpToLine(cursorY);
cursorY = document.selection.GetActivePointY(mePosLogical);
cursorX = document.selection.GetActivePointX(mePosLogical);
}
document.selection.StartOfLine(true, mePosLogical);
const strToStartOfLine = document.selection.Text;
const zen = "[、,。;:「」『』【】()〔〕〈〉《》・!?←↓↑→○●▲△▼▽◆◇■□★☆~/…― ]";
const han = "[\\[\\]\\(\\)\\.,=<>:;`'\" #]";
const reg = new RegExp("(^.*(" + zen + "|" + han + "))(.*?$)");
const m = reg.exec(strToStartOfLine);
if (!m) {
document.selection.StartOfLine(false, mePosLogical);
return;
}
const firstMatch = String(m[1]);
const trailing = new RegExp("(" + zen + "|" + han + ")+$");
const net = firstMatch.replace(trailing, "");
const delta = (strToStartOfLine.length - net.length > 0)? strToStartOfLine.length - net.length : 1;
setCursorPos(cursorX-delta, cursorY, false);
}
function main() {
if (!document.selection.IsEmpty || document.selection.Mode != meModeStream) {
return
}
Redraw = false;
moveCursor();
Redraw = true;
}
main();
// ------------------------------------------------------------
// 行頭に移動する
// ・折り返し状態での表示行頭で実行すると論理行頭に移動。
// ・インデント無しの行頭で実行すると段落先頭に移動。
// ------------------------------------------------------------
const selecting = false;
function getIndentDepth(s) {
const indentChar = new RegExp("^[ \t]+");
const m = indentChar.exec(s);
if (m) {
return m[0].length;
}
return 0;
}
function toBOL () {
const logicalX = document.selection.GetActivePointX(mePosLogical);
const logicalY = document.selection.GetActivePointY(mePosLogical);
const viewX = document.selection.GetActivePointX(mePosView);
const viewY = document.selection.GetActivePointY(mePosView);
const logicalLine = document.GetLine(logicalY, 1);
const indentDepth = getIndentDepth(logicalLine);
if (viewY == 1) {
document.Selection.StartOfLine(selecting, mePosView);
return;
}
document.Selection.StartOfLine(selecting, mePosView);
if (logicalX == indentDepth+1) {
return;
}
document.Selection.CharLeft(selecting, 1);
const inSecondLine = document.Selection.GetActivePointY(mePosLogical) == logicalY;
document.Selection.CharRight(selecting, 2);
document.Selection.CharLeft(selecting, 1);
if (inSecondLine) {
if (viewX > 1) {
return;
}
document.Selection.StartOfLine(selecting, mePosLogical);
}
if (indentDepth < 1) {
return;
}
document.Selection.SetActivePoint(mePosLogical, indentDepth+1, logicalY, selecting);
}
function main() {
if (document.Selection.Mode != meModeStream) {
document.Selection.StartOfLine(selecting, mePosView);
return;
}
Redraw = false;
toBOL();
Redraw = true;
}
main();
// ------------------------------------------------------------
// 行末に移動する
// 折り返し末尾で実行すると論理行末に移動。
// ------------------------------------------------------------
function main () {
const viewY = document.selection.GetActivePointY(mePosView);
const viewX = document.selection.GetActivePointX(mePosView);
const viewLine = document.getLine(viewY);
const selected = !document.selection.IsEmpty;
const opt = (viewX == viewLine.length+1)? mePosLogical : mePosView;
document.selection.EndOfLine(selected, opt);
}
main();
// ------------------------------------------------------------
// 現在のカーソル位置を上に持ってくる
// ------------------------------------------------------------
function main () {
var currentLine = Document.Selection.GetActivePointY(mePosView);
ScrollY = currentLine - 2;
}
main();
// ------------------------------------------------------------
// カッコ内を選択
// ------------------------------------------------------------
function getNthChar(s, n) {
return String(s.charAt(n-1));
}
const bracePairs = {
"(": ")",
"「": "」",
"[": "]",
"〔": "〕",
"『": "』",
"【": "】",
"〈": "〉",
"《": "》",
}
const openBraces = Object.keys(bracePairs).map(function(key){
return String(key);
});
const closeBraces = Object.keys(bracePairs).map(function(key){
const closeBrc = bracePairs[key];
return String(closeBrc);
});
function getOpenBrace(closeBrc) {
const openBrc = Object.keys(bracePairs).filter(function(key){
return bracePairs[key] === closeBrc
});
return String(openBrc);
}
function getOpenBraceX (line) {
let x = 0;
const len = line.length;
const stack = [];
for (let i = 0; i < len; i++) {
const c = getNthChar(line, len - i);
if (closeBraces.indexOf(c) >= 0) {
stack.push(getOpenBrace(c));
continue;
}
if (openBraces.indexOf(c) >= 0) {
let idx = stack.indexOf(c);
if (idx >= 0) {
stack.splice(idx, 1);
continue;
}
x = len - i;
break;
}
}
return x;
}
function getCloseBraceX (line, closeBrace) {
let x = 0;
const openBrace = getOpenBrace(closeBrace);
let skipCloseBrace = 0;
for (let i = 1; i <= line.length; i++) {
const c = getNthChar(line, i);
if (c == openBrace) {
skipCloseBrace += 1;
continue;
}
if (c == closeBrace) {
if (skipCloseBrace) {
skipCloseBrace -= 1;
continue;
}
x = i;
break;
}
}
return x;
}
function expandSelection() {
const logicalX = document.selection.GetActivePointX(mePosLogical);
const logicalY = document.selection.GetActivePointY(mePosLogical);
const logicalLine = document.GetLine(logicalY, 1);
const strFromBOL = logicalLine.slice(0, logicalX-1);
const openPosX = getOpenBraceX(strFromBOL);
if (openPosX < 1) {
return;
}
const openBrc = getNthChar(logicalLine, openPosX);
const closeBrc = bracePairs[openBrc];
const strToEOL = logicalLine.slice(openPosX);
const closePosX = getCloseBraceX(strToEOL, closeBrc);
if (closePosX < 1) {
return;
}
document.selection.SetActivePoint(mePosLogical, openPosX+1, logicalY, false);
document.selection.SetActivePoint(mePosLogical, openPosX+closePosX, logicalY, true);
}
function main() {
if (document.selection.Mode != meModeStream) {
return
}
Redraw = false;
expandSelection();
Redraw = true;
}
main();
// ------------------------------------------------------------
// 段落選択
// ------------------------------------------------------------
const wholeLines = document.text.split(/\r?\n/);
const max = wholeLines.length;
const blank = new RegExp("^ *$");
function isBlankLine(logicalY) {
const logicalLine = wholeLines[logicalY-1];
return blank.test(logicalLine);
}
function cursorUp(n) {
const y = document.selection.GetActivePointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, 1, y-n, false);
}
function selectDown(n) {
const y = document.selection.GetActivePointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, 1, y+n, true);
}
function moveToParagraphBeginning() {
const y = document.selection.GetActivePointY(mePosLogical);
let up = 0;
for (let i = 1; i < y; i++) {
if (isBlankLine(y-i)) {
break;
}
up++
}
cursorUp(up);
}
function selectParagraphToEnd() {
const y = document.selection.GetActivePointY(mePosLogical);
let down = 0;
for (let i = 1; i <= max-y; i++) {
if (isBlankLine(y+i)) {
break;
}
down++
}
selectDown(down);
document.selection.EndOfLine(true, mePosLogical);
}
function main() {
if (document.selection.Mode != meModeStream) {
return;
}
const y = document.selection.GetActivePointY(mePosLogical);
if (isBlankLine(y)) {
return;
}
if(document.selection.IsEmpty){
moveToParagraphBeginning();
}
selectParagraphToEnd();
}
main();
// ------------------------------------------------------------
// 行頭に移動する
// ・折り返し状態での表示行頭で実行すると論理行頭に移動。
// ・インデント無しの行頭で実行すると段落先頭に移動。
// ------------------------------------------------------------
const selecting = true;
function getIndentDepth(s) {
const indentChar = new RegExp("^[ \t]+");
const m = indentChar.exec(s);
if (m) {
return m[0].length;
}
return 0;
}
function toBOL () {
const logicalX = document.selection.GetActivePointX(mePosLogical);
const logicalY = document.selection.GetActivePointY(mePosLogical);
const viewX = document.selection.GetActivePointX(mePosView);
const viewY = document.selection.GetActivePointY(mePosView);
const logicalLine = document.GetLine(logicalY, 1);
const indentDepth = getIndentDepth(logicalLine);
if (viewY == 1) {
document.Selection.StartOfLine(selecting, mePosView);
return;
}
document.Selection.StartOfLine(selecting, mePosView);
if (logicalX == indentDepth+1) {
return;
}
document.Selection.CharLeft(selecting, 1);
const inSecondLine = document.Selection.GetActivePointY(mePosLogical) == logicalY;
document.Selection.CharRight(selecting, 2);
document.Selection.CharLeft(selecting, 1);
if (inSecondLine) {
if (viewX > 1) {
return;
}
document.Selection.StartOfLine(selecting, mePosLogical);
}
if (indentDepth < 1) {
return;
}
document.Selection.SetActivePoint(mePosLogical, indentDepth+1, logicalY, selecting);
}
function main() {
if (document.Selection.Mode != meModeStream) {
document.Selection.StartOfLine(selecting, mePosView);
return;
}
Redraw = false;
toBOL();
Redraw = true;
}
main();
// ------------------------------------------------------------
// 現在位置からファイル末尾まで選択(スクロール位置保存)
// ------------------------------------------------------------
function main() {
const sX = ScrollX
const sY = ScrollY;
const curPos = document.Selection.GetActivePos();
Redraw = false;
document.selection.EndOfDocument();
document.selection.SetActivePos(curPos, true);
ScrollX = sX;
ScrollY = sY;
Redraw = true;
}
main();
// ------------------------------------------------------------
// 行末に移動する
// 折り返し末尾で実行すると論理行末に移動。
// ------------------------------------------------------------
const selecting = true;
function main () {
const viewY = document.selection.GetActivePointY(mePosView);
const viewX = document.selection.GetActivePointX(mePosView);
const viewLine = document.getLine(viewY);
const opt = (viewX == viewLine.length+1)? mePosLogical : mePosView;
document.selection.EndOfLine(selecting, opt);
}
main();
// ------------------------------------------------------------
// カーソルを下に動かす
// 選択中であれば常に選択範囲の下端に。
// ------------------------------------------------------------
function main () {
if (document.selection.IsEmpty || document.selection.Mode != meModeStream) {
document.selection.LineDown();
return;
}
Redraw = false;
const x = document.selection.GetBottomPointX(mePosLogical);
const y = document.selection.GetBottomPointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, x, y)
Redraw = true;
}
main();
// ------------------------------------------------------------
// カーソルを左に動かす
// 選択中であれば常に選択範囲の左に。
// ------------------------------------------------------------
function main () {
if (document.selection.IsEmpty) {
document.selection.CharLeft();
return;
}
if (document.selection.Mode != meModeStream) {
document.selection.Collapse(meCollapseStart);
return;
}
Redraw = false;
const x = document.selection.GetTopPointX(mePosLogical);
const y = document.selection.GetTopPointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, x, y)
Redraw = true;
}
main();
// ------------------------------------------------------------
// カーソルを右に動かす
// 選択中であれば常に選択範囲の右に。
// ------------------------------------------------------------
function main () {
if (document.selection.IsEmpty) {
document.selection.CharRight();
return;
}
if (document.selection.Mode != meModeStream) {
document.selection.Collapse(meCollapseEnd);
return;
}
Redraw = false;
const x = document.selection.GetBottomPointX(mePosLogical);
const y = document.selection.GetBottomPointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, x, y)
Redraw = true;
}
main();
// ------------------------------------------------------------
// カーソルを上に動かす
// 選択中であれば常に選択範囲の上端に。
// ------------------------------------------------------------
function main () {
if (document.selection.IsEmpty || document.selection.Mode != meModeStream) {
document.selection.LineUp();
return;
}
Redraw = false;
const x = document.selection.GetTopPointX(mePosLogical);
const y = document.selection.GetTopPointY(mePosLogical);
document.selection.SetActivePoint(mePosLogical, x, y)
Redraw = true;
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment