選択範囲の行を並び替えるUserScript
要件
選択範囲が存在する状態で特定のkeyを押すと、以下の作業をおこなう
辞書順に並び替える
コードブロックやテーブルにかかわらず、任意の場所で実行できるようにする
目的
実装
選択範囲内に含まれる行を全て削除して書き換える
テロメアがすべての行で更新されることになるが、気にしないことにする
いや、並び替える必要のある行だけ Ctrl
+ ↑
/ ↓
で並び替えたほうが楽か?
選択範囲に含まれる行をすべて削除してから入力するときに、 \n
の入力後にインデントを削除する必要が生じる
これはキー入力とテキスト入力の組み合わせになるため、間に sleep()
を挟む必要があり、面倒?
想像するほど面倒でもないかもしれない
とりあえず二通りの方法で実装してみるか。
テキスト入力で書き換える
Ctrl
+矢印キーで入れ替える
script.jsimport {selection} from '/api/code/takker/scrapbox-selection-2/script.js';
import {scrapboxDOM} from '/api/code/takker/scrapbox-dom-accessor/script.js';
import {goLine, goHead, enterEdit, upLines} from '/api/code/takker/scrapbox-edit-emulation/script.js';
import {line as l} from '/api/code/takker/scrapbox-line-info-2/script.js';
import {press} from '/api/code/takker/scrapbox-keyboard-emulation-2/script.js';
import {insertText} from '/api/code/takker/scrapbox-insert-text/script.js';
export async function sortLines() {
const {start: {lineNo: startNo}, end: {lineNo: endNo}} = selection.range;
const sortedLineDOMs = scrapbox.Page.lines
.slice(startNo, 1 + endNo)
.map((line, i) => {return {lineDOM: scrapboxDOM.lines.children[i + startNo], text: line.text}})
.sort((a,b)=>new Intl.Collator().compare(a.text,b.text))
.map(({lineDOM}) => lineDOM);
// 一番上から順に入れ替え作業をする
let insertPosition = startNo;
for (const lineDOM of sortedLineDOMs) {
const presentPosition = l(lineDOM).index; // 現在の行の位置
if (presentPosition !== insertPosition) {
goLine({index: presentPosition});
await sleep(10);
upLines(presentPosition - insertPosition);
}
insertPosition++;
}
}
const sleep = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));